Skip to content

Commit

Permalink
Refactor platform detection from resource provider
Browse files Browse the repository at this point in the history
  • Loading branch information
psx95 committed Dec 31, 2023
1 parent 563ea05 commit 2c2c1d6
Show file tree
Hide file tree
Showing 12 changed files with 822 additions and 613 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.cloud.opentelemetry.detectors;

import java.util.Optional;

/**
* Contains utility functions to retrieve appropriate zone and regions representing the location of
* certain cloud resources.
*/
final class CloudLocationUtil {
/**
* Utility method to extract cloud availability zone from passed {@link GCPMetadataConfig}. The
* method modifies the passed attributesBuilder by adding the extracted property to it. If the
* zone cannot be found, calling this method has no effect.
*
* <ul>
* <li>If the availability zone cannot be found, calling this method has no effect.
* </ul>
*
* <p>Example zone: australia-southeast1-a
*
* @param metadataConfig The {@link GCPMetadataConfig} from which the cloud availability zone
* value is extracted.
*/
static Optional<String> getAvailabilityZoneFromMetadata(GCPMetadataConfig metadataConfig) {
return Optional.ofNullable(metadataConfig.getZone());
}

/**
* Utility method to extract the cloud region from passed {@link GCPMetadataConfig}. The method
* modifies the passed attributesBuilder by adding the extracted property to it.
*
* <ul>
* <li>If the cloud region cannot be found, calling this method has no effect.
* <li>This method uses zone attribute to parse region from it.
* </ul>
*
* <p>Example region: australia-southeast1
*
* @param metadataConfig The {@link GCPMetadataConfig} from which the cloud region value is
* extracted.
*/
static Optional<String> getCloudRegionFromMetadataUsingZone(GCPMetadataConfig metadataConfig) {
Optional<String> optZone = getAvailabilityZoneFromMetadata(metadataConfig);
if (optZone.isPresent()) {
// Parsing required to scope up to a region
String[] splitArr = optZone.get().split("-");
if (splitArr.length > 2) {
return Optional.of(String.join("-", splitArr[0], splitArr[1]));
}
}
return Optional.empty();
}

/**
* Utility method to extract the cloud region from passed {@link GCPMetadataConfig}. The method
* modifies the passed attributesBuilder by adding the extracted property to it.
*
* <ul>
* <li>If the cloud region cannot be found, calling this method has no effect.
* <li>This method directly uses the region attribute from the metadata config.
* </ul>
*
* <p>Example region: australia-southeast1
*
* @param metadataConfig The {@link GCPMetadataConfig} from which the cloud region value is
* extracted.
*/
static Optional<String> getCloudRegionFromMetadataUsingRegion(GCPMetadataConfig metadataConfig) {
return Optional.ofNullable(metadataConfig.getRegion());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
* Provides API to fetch environment variables. This is useful in order to create a mock class for
* testing.
*/
public interface EnvVars {
EnvVars DEFAULT_INSTANCE = System::getenv;
public interface EnvironmentVariables {
/** Returns the current environment variables of the platform this is running in. */
EnvironmentVariables DEFAULT_INSTANCE = System::getenv;

/**
* Grabs the system environment variable. Returns null on failure.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.cloud.opentelemetry.detectors;

import java.util.Optional;

public final class GAEDetector {
public static final GAEDetector DEFAULT_INSTANCE = new GAEDetector();

private final EnvironmentVariables environmentVariables;
private final GCPMetadataConfig metadataConfig;

GAEDetector() {
this.environmentVariables = EnvironmentVariables.DEFAULT_INSTANCE;
this.metadataConfig = GCPMetadataConfig.DEFAULT_INSTANCE;
}

// for testing only
GAEDetector(EnvironmentVariables environmentVariables, GCPMetadataConfig metadataConfig) {
this.environmentVariables = environmentVariables;
this.metadataConfig = metadataConfig;
}

public Optional<String> getAppModuleName() {
return Optional.ofNullable(this.environmentVariables.get("GAE_SERVICE"));
}

public Optional<String> getAppVersion() {
return Optional.ofNullable(this.environmentVariables.get("GAE_VERSION"));
}

public Optional<String> getAppInstanceId() {
return Optional.ofNullable(this.environmentVariables.get("GAE_INSTANCE"));
}

public Optional<String> getAvailabilityZone() {
return CloudLocationUtil.getAvailabilityZoneFromMetadata(this.metadataConfig);
}

public Optional<String> getCloudRegion() {
if (this.environmentVariables.get("GAE_ENV") == null) {
return Optional.empty();
}
if (this.environmentVariables.get("GAE_ENV").equals("standard")) {
return CloudLocationUtil.getCloudRegionFromMetadataUsingRegion(this.metadataConfig);
} else {
return CloudLocationUtil.getCloudRegionFromMetadataUsingZone(this.metadataConfig);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.cloud.opentelemetry.detectors;

import java.util.Optional;

public final class GCEDetector {
public static final GCEDetector DEFAULT_INSTANCE = new GCEDetector();

private final GCPMetadataConfig metadataConfig;

GCEDetector() {
this.metadataConfig = GCPMetadataConfig.DEFAULT_INSTANCE;
}

// for testing only
GCEDetector(GCPMetadataConfig metadataConfig) {
this.metadataConfig = metadataConfig;
}

public Optional<String> getProjectId() {
return Optional.ofNullable(this.metadataConfig.getProjectId());
}

public Optional<String> getAvailabilityZone() {
return CloudLocationUtil.getAvailabilityZoneFromMetadata(this.metadataConfig);
}

public Optional<String> getCloudRegion() {
return CloudLocationUtil.getCloudRegionFromMetadataUsingZone(this.metadataConfig);
}

public Optional<String> getInstanceId() {
return Optional.ofNullable(this.metadataConfig.getInstanceId());
}

public Optional<String> getInstanceName() {
return Optional.ofNullable(this.metadataConfig.getInstanceName());
}

public Optional<String> getMachineType() {
return Optional.ofNullable(this.metadataConfig.getMachineType());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,30 +31,30 @@
* @see <a href="https://cloud.google.com/compute/docs/storing-retrieving-metadata">
* https://cloud.google.com/compute/docs/storing-retrieving-metadata</a>
*/
public final class GCPMetadataConfig {
private static final String DEFAULT_URL = "http://metadata.google.internal/computeMetadata/v1/";
public static final GCPMetadataConfig DEFAULT_INSTANCE = new GCPMetadataConfig(DEFAULT_URL);
final class GCPMetadataConfig {
static final GCPMetadataConfig DEFAULT_INSTANCE = new GCPMetadataConfig();

private static final String DEFAULT_URL = "http://metadata.google.internal/computeMetadata/v1/";
private final String url;
private final Map<String, String> cachedAttributes = new HashMap<>();

// For testing only
public GCPMetadataConfig(String url) {
this.url = url;
private GCPMetadataConfig() {
this.url = DEFAULT_URL;
}

public boolean isRunningOnGcp() {
return getProjectId() != null && !getProjectId().isEmpty();
// For testing only
GCPMetadataConfig(String url) {
this.url = url;
}

// Returns null on failure to retrieve from metadata server
public String getProjectId() {
String getProjectId() {
return getAttribute("project/project-id");
}

// Example response: projects/640212054955/zones/australia-southeast1-a
// Returns null on failure to retrieve from metadata server
public String getZone() {
String getZone() {
String zone = getAttribute("instance/zone");
if (zone != null && zone.contains("/")) {
zone = zone.substring(zone.lastIndexOf('/') + 1);
Expand All @@ -66,7 +66,7 @@ public String getZone() {
// method involve detecting region in GAE standard environment
// Example response: projects/5689182099321/regions/us-central1
// Returns null on failure to retrieve from metadata server
public String getRegion() {
String getRegion() {
String region = getAttribute("instance/region");
if (region != null && region.contains("/")) {
region = region.substring(region.lastIndexOf('/') + 1);
Expand All @@ -75,7 +75,7 @@ public String getRegion() {
}

// Example response: projects/640212054955/machineTypes/e2-medium
public String getMachineType() {
String getMachineType() {
String machineType = getAttribute("instance/machine-type");
if (machineType != null && machineType.contains("/")) {
machineType = machineType.substring(machineType.lastIndexOf('/') + 1);
Expand All @@ -84,27 +84,27 @@ public String getMachineType() {
}

// Returns null on failure to retrieve from metadata server
public String getInstanceId() {
String getInstanceId() {
return getAttribute("instance/id");
}

// Returns null on failure to retrieve from metadata server
public String getClusterName() {
String getClusterName() {
return getAttribute("instance/attributes/cluster-name");
}

// Returns null on failure to retrieve from metadata server
public String getClusterLocation() {
String getClusterLocation() {
return getAttribute("instance/attributes/cluster-location");
}

// Returns null on failure to retrieve from metadata server
public String getInstanceHostName() {
String getInstanceHostName() {
return getAttribute("instance/hostname");
}

// Returns null on failure to retrieve from metadata server
public String getInstanceName() {
String getInstanceName() {
return getAttribute("instance/name");
}

Expand Down
Loading

0 comments on commit 2c2c1d6

Please sign in to comment.