-
Notifications
You must be signed in to change notification settings - Fork 178
Unify gcp resource detector #2747
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
jaydeluca
merged 4 commits into
open-telemetry:main
from
psx95:unify-gcp-resource-detector
Apr 10, 2026
+1,411
−81
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/AttributeKeys.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| /* | ||
| * Copyright The OpenTelemetry Authors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package io.opentelemetry.contrib.gcp.resource; | ||
|
|
||
| /** | ||
| * Contains constants that act as keys for the known attributes for {@link | ||
| * GcpPlatformDetector.SupportedPlatform}s. | ||
| */ | ||
| final class AttributeKeys { | ||
| private AttributeKeys() {} | ||
|
|
||
| // GCE Attributes | ||
| public static final String GCE_AVAILABILITY_ZONE = AttributeKeys.AVAILABILITY_ZONE; | ||
| public static final String GCE_CLOUD_REGION = AttributeKeys.CLOUD_REGION; | ||
| public static final String GCE_INSTANCE_ID = AttributeKeys.INSTANCE_ID; | ||
| public static final String GCE_INSTANCE_NAME = AttributeKeys.INSTANCE_NAME; | ||
| public static final String GCE_MACHINE_TYPE = AttributeKeys.MACHINE_TYPE; | ||
| public static final String GCE_INSTANCE_HOSTNAME = "instance_hostname"; | ||
|
|
||
| // GKE Attributes | ||
| public static final String GKE_CLUSTER_NAME = "gke_cluster_name"; | ||
| public static final String GKE_CLUSTER_LOCATION_TYPE = "gke_cluster_location_type"; | ||
| public static final String GKE_CLUSTER_LOCATION = "gke_cluster_location"; | ||
| public static final String GKE_HOST_ID = AttributeKeys.INSTANCE_ID; | ||
|
|
||
| // GKE Location Constants | ||
| public static final String GKE_LOCATION_TYPE_ZONE = "ZONE"; | ||
| public static final String GKE_LOCATION_TYPE_REGION = "REGION"; | ||
|
|
||
| // GAE Attributes | ||
| public static final String GAE_MODULE_NAME = "gae_module_name"; | ||
| public static final String GAE_APP_VERSION = "gae_app_version"; | ||
| public static final String GAE_INSTANCE_ID = AttributeKeys.INSTANCE_ID; | ||
| public static final String GAE_AVAILABILITY_ZONE = AttributeKeys.AVAILABILITY_ZONE; | ||
| public static final String GAE_CLOUD_REGION = AttributeKeys.CLOUD_REGION; | ||
|
|
||
| // Google Serverless Compute Attributes | ||
| public static final String SERVERLESS_COMPUTE_NAME = "serverless_compute_name"; | ||
| public static final String SERVERLESS_COMPUTE_REVISION = "serverless_compute_revision"; | ||
| public static final String SERVERLESS_COMPUTE_AVAILABILITY_ZONE = AttributeKeys.AVAILABILITY_ZONE; | ||
| public static final String SERVERLESS_COMPUTE_CLOUD_REGION = AttributeKeys.CLOUD_REGION; | ||
| public static final String SERVERLESS_COMPUTE_INSTANCE_ID = AttributeKeys.INSTANCE_ID; | ||
|
|
||
| // Cloud Run Job Specific Attributes | ||
| public static final String GCR_JOB_EXECUTION_KEY = "gcr_job_execution_key"; | ||
| public static final String GCR_JOB_TASK_INDEX = "gcr_job_task_index"; | ||
|
|
||
| static final String AVAILABILITY_ZONE = "availability_zone"; | ||
| static final String CLOUD_REGION = "cloud_region"; | ||
| static final String INSTANCE_ID = "instance_id"; | ||
| static final String INSTANCE_NAME = "instance_name"; | ||
| static final String MACHINE_TYPE = "machine_type"; | ||
| } |
36 changes: 36 additions & 0 deletions
36
gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/DetectedPlatform.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| /* | ||
| * Copyright The OpenTelemetry Authors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package io.opentelemetry.contrib.gcp.resource; | ||
|
|
||
| import java.util.Map; | ||
|
|
||
| /** Represents a GCP specific platform on which a cloud application can run. */ | ||
| interface DetectedPlatform { | ||
| /** | ||
| * Method to retrieve the underlying compute platform on which application is running. | ||
| * | ||
| * @return the {@link GcpPlatformDetector.SupportedPlatform} representing the Google Cloud | ||
| * platform on which application is running. | ||
| */ | ||
| GcpPlatformDetector.SupportedPlatform getSupportedPlatform(); | ||
|
|
||
| /** | ||
| * Method to retrieve the GCP Project ID in which the GCP specific platform exists. Every valid | ||
| * platform must have a GCP Project ID associated with it. | ||
| * | ||
| * @return the Google Cloud project ID. | ||
| */ | ||
| String getProjectId(); | ||
|
|
||
| /** | ||
| * Method to retrieve the attributes associated with the compute platform on which the application | ||
| * is running as key-value pairs. The valid keys to query on this {@link Map} are specified in the | ||
| * {@link AttributeKeys}. | ||
| * | ||
| * @return a {@link Map} of attributes specific to the underlying compute platform. | ||
| */ | ||
| Map<String, String> getAttributes(); | ||
| } |
23 changes: 23 additions & 0 deletions
23
gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/EnvironmentVariables.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| /* | ||
| * Copyright The OpenTelemetry Authors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package io.opentelemetry.contrib.gcp.resource; | ||
|
|
||
| /** | ||
| * Provides API to fetch environment variables. This is useful in order to create a mock class for | ||
| * testing. | ||
| */ | ||
| 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. | ||
| * | ||
| * @param key the key of the environment variable in {@code System.getenv()} | ||
| * @return the value received by {@code System.getenv(key)} | ||
| */ | ||
| String get(String key); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
163 changes: 163 additions & 0 deletions
163
gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/GcpMetadataConfig.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,163 @@ | ||
| /* | ||
| * Copyright The OpenTelemetry Authors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package io.opentelemetry.contrib.gcp.resource; | ||
|
|
||
| import java.io.BufferedReader; | ||
| import java.io.IOException; | ||
| import java.io.InputStream; | ||
| import java.io.InputStreamReader; | ||
| import java.net.HttpURLConnection; | ||
| import java.net.URI; | ||
| import java.net.URL; | ||
| import java.nio.charset.StandardCharsets; | ||
| import java.util.Map; | ||
| import java.util.concurrent.ConcurrentHashMap; | ||
| import javax.annotation.Nullable; | ||
|
|
||
| /** | ||
| * Retrieves Google Cloud project-id and a limited set of instance attributes from Metadata server. | ||
| * | ||
| * @see <a href= "https://cloud.google.com/compute/docs/storing-retrieving-metadata"> | ||
| * https://cloud.google.com/compute/docs/storing-retrieving-metadata</a> | ||
| */ | ||
| 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 ConcurrentHashMap<>(); | ||
|
|
||
| private GcpMetadataConfig() { | ||
| this.url = DEFAULT_URL; | ||
| } | ||
|
|
||
| // For testing only | ||
| GcpMetadataConfig(String url) { | ||
| this.url = url; | ||
| } | ||
|
|
||
| // Returns null on failure to retrieve from metadata server | ||
| String getProjectId() { | ||
| return getAttribute("project/project-id"); | ||
| } | ||
|
|
||
| /** | ||
| * Method to extract cloud availability zone from the metadata server. | ||
| * | ||
| * <p>Example response: projects/640212054955/zones/australia-southeast1-a | ||
| * | ||
| * <p>Example zone: australia-southeast1-a | ||
| * | ||
| * @return the extracted zone from the metadata server response or null in case of failure to | ||
| * retrieve from metadata server. | ||
| */ | ||
| String getZone() { | ||
| String zone = getAttribute("instance/zone"); | ||
| if (zone != null && zone.contains("/")) { | ||
| zone = zone.substring(zone.lastIndexOf('/') + 1); | ||
| } | ||
| return zone; | ||
| } | ||
|
|
||
| /** | ||
| * Use this method only when the region cannot be parsed from the zone. Known use-cases of this | ||
| * method involve detecting region in GAE standard environment. | ||
| * | ||
| * <p>Example response: projects/5689182099321/regions/us-central1. | ||
| * | ||
| * @return the retrieved region or null in case of failure to retrieve from metadata server | ||
| */ | ||
| String getRegion() { | ||
| String region = getAttribute("instance/region"); | ||
| if (region != null && region.contains("/")) { | ||
| region = region.substring(region.lastIndexOf('/') + 1); | ||
| } | ||
| return region; | ||
| } | ||
|
|
||
| /** | ||
| * Use this method to parse region from zone. | ||
| * | ||
| * <p>Example region: australia-southeast1 | ||
| * | ||
| * @return parsed region from the zone, if zone is not found or is invalid, this method returns | ||
| * null. | ||
| */ | ||
| @Nullable | ||
| String getRegionFromZone() { | ||
| String region = null; | ||
| String zone = getZone(); | ||
| if (zone != null && !zone.isEmpty()) { | ||
| // Parsing required to scope up to a region | ||
| String[] splitArr = zone.split("-"); | ||
| if (splitArr.length > 2) { | ||
| region = String.join("-", splitArr[0], splitArr[1]); | ||
| } | ||
| } | ||
| return region; | ||
| } | ||
|
|
||
| // Example response: projects/640212054955/machineTypes/e2-medium | ||
| String getMachineType() { | ||
| String machineType = getAttribute("instance/machine-type"); | ||
| if (machineType != null && machineType.contains("/")) { | ||
| machineType = machineType.substring(machineType.lastIndexOf('/') + 1); | ||
| } | ||
| return machineType; | ||
| } | ||
|
|
||
| // Returns null on failure to retrieve from metadata server | ||
| String getInstanceId() { | ||
| return getAttribute("instance/id"); | ||
| } | ||
|
|
||
| // Returns null on failure to retrieve from metadata server | ||
| String getClusterName() { | ||
| return getAttribute("instance/attributes/cluster-name"); | ||
| } | ||
|
|
||
| // Returns null on failure to retrieve from metadata server | ||
| String getClusterLocation() { | ||
| return getAttribute("instance/attributes/cluster-location"); | ||
| } | ||
|
|
||
| // Returns null on failure to retrieve from metadata server | ||
| String getInstanceHostName() { | ||
| return getAttribute("instance/hostname"); | ||
| } | ||
|
|
||
| // Returns null on failure to retrieve from metadata server | ||
| String getInstanceName() { | ||
| return getAttribute("instance/name"); | ||
| } | ||
|
|
||
| // Returns null on failure to retrieve from metadata server | ||
| private String getAttribute(String attributeName) { | ||
| return cachedAttributes.computeIfAbsent(attributeName, this::fetchAttribute); | ||
| } | ||
|
|
||
| // Return the attribute received at <attributeName> relative path or null on | ||
| // failure | ||
| @Nullable | ||
| private String fetchAttribute(String attributeName) { | ||
| try { | ||
| URL url = URI.create(this.url + attributeName).toURL(); | ||
| HttpURLConnection connection = (HttpURLConnection) url.openConnection(); | ||
| connection.setRequestProperty("Metadata-Flavor", "Google"); | ||
| if (connection.getResponseCode() == 200 | ||
| && "Google".equals(connection.getHeaderField("Metadata-Flavor"))) { | ||
| InputStream input = connection.getInputStream(); | ||
| try (BufferedReader reader = | ||
| new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8))) { | ||
| return reader.readLine(); | ||
| } | ||
| } | ||
| } catch (IOException ignore) { | ||
| // ignore | ||
| } | ||
| return null; | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.