diff --git a/gcp-resources/build.gradle.kts b/gcp-resources/build.gradle.kts index cf0473fd6..299d92989 100644 --- a/gcp-resources/build.gradle.kts +++ b/gcp-resources/build.gradle.kts @@ -12,7 +12,7 @@ dependencies { api("io.opentelemetry:opentelemetry-sdk") // Provides GCP resource detection support - implementation("com.google.cloud.opentelemetry:detector-resources-support:0.31.0") + implementation("com.google.cloud.opentelemetry:detector-resources-support:0.32.0") implementation("io.opentelemetry.semconv:opentelemetry-semconv") testImplementation("io.opentelemetry.semconv:opentelemetry-semconv-incubating") diff --git a/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProvider.java b/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProvider.java index d129a5953..80cc1347e 100644 --- a/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProvider.java +++ b/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProvider.java @@ -16,6 +16,8 @@ import static com.google.cloud.opentelemetry.detection.AttributeKeys.GCE_INSTANCE_ID; import static com.google.cloud.opentelemetry.detection.AttributeKeys.GCE_INSTANCE_NAME; import static com.google.cloud.opentelemetry.detection.AttributeKeys.GCE_MACHINE_TYPE; +import static com.google.cloud.opentelemetry.detection.AttributeKeys.GCR_JOB_EXECUTION_KEY; +import static com.google.cloud.opentelemetry.detection.AttributeKeys.GCR_JOB_TASK_INDEX; import static com.google.cloud.opentelemetry.detection.AttributeKeys.GKE_CLUSTER_LOCATION; import static com.google.cloud.opentelemetry.detection.AttributeKeys.GKE_CLUSTER_LOCATION_TYPE; import static com.google.cloud.opentelemetry.detection.AttributeKeys.GKE_CLUSTER_NAME; @@ -106,6 +108,9 @@ public Attributes getAttributes() { case GOOGLE_CLOUD_FUNCTIONS: addGcfAttributes(attrBuilder, detectedPlatform.getAttributes()); break; + case GOOGLE_CLOUD_RUN_JOB: + addGcrJobAttributes(attrBuilder, detectedPlatform.getAttributes()); + break; case GOOGLE_APP_ENGINE: addGaeAttributes(attrBuilder, detectedPlatform.getAttributes()); break; @@ -192,8 +197,8 @@ private static void addGkeAttributes( } /** - * Updates the attributes with the required keys for a GCR (Google Cloud Run) environment. The - * attributes are not updated in case the environment is not deemed to be GCR. + * Updates the attributes with the required keys for a GCR (Google Cloud Run) Service environment. + * The attributes are not updated in case the environment is not deemed to be GCR. * * @param attrBuilder The {@link AttributesBuilder} object that needs to be updated with the * necessary keys. @@ -217,6 +222,34 @@ private static void addGcfAttributes( addCommonAttributesForServerlessCompute(attrBuilder, attributesMap); } + /** + * Update the attributes with the required keys for a GCR (Google Cloud Run) Jobs environment. The + * attributes are not updated in case the environment is not deemed to be GCR jobs environment. + * + * @param attrBuilder The {@link AttributesBuilder} object that needs to be updated with the + * necessary keys. + */ + private static void addGcrJobAttributes( + AttributesBuilder attrBuilder, Map attributesMap) { + attrBuilder.put(CLOUD_PLATFORM, GCP_CLOUD_RUN); + Optional.ofNullable(attributesMap.get(SERVERLESS_COMPUTE_NAME)) + .ifPresent(name -> attrBuilder.put(FAAS_NAME, name)); + Optional.ofNullable(attributesMap.get(SERVERLESS_COMPUTE_INSTANCE_ID)) + .ifPresent(instanceId -> attrBuilder.put(FAAS_INSTANCE, instanceId)); + Optional.ofNullable(attributesMap.get(SERVERLESS_COMPUTE_CLOUD_REGION)) + .ifPresent(cloudRegion -> attrBuilder.put(CLOUD_REGION, cloudRegion)); + Optional.ofNullable(attributesMap.get(GCR_JOB_EXECUTION_KEY)) + .ifPresent( + jobExecutionKey -> + attrBuilder.put(IncubatingAttributes.GCP_CLOUD_RUN_JOB_EXECUTION, jobExecutionKey)); + Optional.ofNullable(attributesMap.get(GCR_JOB_TASK_INDEX)) + .ifPresent( + jobTaskIndex -> + attrBuilder.put( + IncubatingAttributes.GCP_CLOUD_RUN_JOB_TASK_INDEX, + Integer.parseInt(jobTaskIndex))); + } + /** * Updates the attributes with the required keys for a GAE (Google App Engine) environment. The * attributes are not updated in case the environment is not deemed to be GAE. diff --git a/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/IncubatingAttributes.java b/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/IncubatingAttributes.java index c1ed9c1d0..551353288 100644 --- a/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/IncubatingAttributes.java +++ b/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/IncubatingAttributes.java @@ -40,6 +40,11 @@ private CloudPlatformValues() {} public static final AttributeKey FAAS_NAME = AttributeKey.stringKey("faas.name"); public static final AttributeKey FAAS_VERSION = AttributeKey.stringKey("faas.version"); + public static final AttributeKey GCP_CLOUD_RUN_JOB_EXECUTION = + AttributeKey.stringKey("gcp.cloud_run.job.execution"); + public static final AttributeKey GCP_CLOUD_RUN_JOB_TASK_INDEX = + AttributeKey.longKey("gcp.cloud_run.job.task_index"); + public static final AttributeKey GCP_GCE_INSTANCE_HOSTNAME = AttributeKey.stringKey("gcp.gce.instance.hostname"); public static final AttributeKey GCP_GCE_INSTANCE_NAME = diff --git a/gcp-resources/src/test/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProviderTest.java b/gcp-resources/src/test/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProviderTest.java index 2b73b0d76..a399fce7f 100644 --- a/gcp-resources/src/test/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProviderTest.java +++ b/gcp-resources/src/test/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProviderTest.java @@ -16,6 +16,8 @@ import static com.google.cloud.opentelemetry.detection.AttributeKeys.GCE_INSTANCE_ID; import static com.google.cloud.opentelemetry.detection.AttributeKeys.GCE_INSTANCE_NAME; import static com.google.cloud.opentelemetry.detection.AttributeKeys.GCE_MACHINE_TYPE; +import static com.google.cloud.opentelemetry.detection.AttributeKeys.GCR_JOB_EXECUTION_KEY; +import static com.google.cloud.opentelemetry.detection.AttributeKeys.GCR_JOB_TASK_INDEX; import static com.google.cloud.opentelemetry.detection.AttributeKeys.GKE_CLUSTER_LOCATION; import static com.google.cloud.opentelemetry.detection.AttributeKeys.GKE_CLUSTER_LOCATION_TYPE; import static com.google.cloud.opentelemetry.detection.AttributeKeys.GKE_CLUSTER_NAME; @@ -27,6 +29,7 @@ import static com.google.cloud.opentelemetry.detection.AttributeKeys.SERVERLESS_COMPUTE_INSTANCE_ID; import static com.google.cloud.opentelemetry.detection.AttributeKeys.SERVERLESS_COMPUTE_NAME; import static com.google.cloud.opentelemetry.detection.AttributeKeys.SERVERLESS_COMPUTE_REVISION; +import static io.opentelemetry.contrib.gcp.resource.IncubatingAttributes.GCP_CLOUD_RUN_JOB_TASK_INDEX; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static io.opentelemetry.semconv.incubating.CloudIncubatingAttributes.CLOUD_ACCOUNT_ID; import static io.opentelemetry.semconv.incubating.CloudIncubatingAttributes.CLOUD_AVAILABILITY_ZONE; @@ -42,6 +45,7 @@ import static io.opentelemetry.semconv.incubating.FaasIncubatingAttributes.FAAS_INSTANCE; import static io.opentelemetry.semconv.incubating.FaasIncubatingAttributes.FAAS_NAME; import static io.opentelemetry.semconv.incubating.FaasIncubatingAttributes.FAAS_VERSION; +import static io.opentelemetry.semconv.incubating.GcpIncubatingAttributes.GCP_CLOUD_RUN_JOB_EXECUTION; import static io.opentelemetry.semconv.incubating.GcpIncubatingAttributes.GCP_GCE_INSTANCE_HOSTNAME; import static io.opentelemetry.semconv.incubating.GcpIncubatingAttributes.GCP_GCE_INSTANCE_NAME; import static io.opentelemetry.semconv.incubating.HostIncubatingAttributes.HOST_ID; @@ -133,6 +137,23 @@ private static DetectedPlatform generateMockServerlessPlatform( return mockServerlessPlatform; } + private static DetectedPlatform generateMockGcrJobPlatform() { + Map mockAttributes = + new HashMap<>( + ImmutableMap.of( + SERVERLESS_COMPUTE_NAME, "serverless-job", + SERVERLESS_COMPUTE_INSTANCE_ID, "serverless-instance-id", + SERVERLESS_COMPUTE_CLOUD_REGION, "us-central1", + GCR_JOB_TASK_INDEX, "1", + GCR_JOB_EXECUTION_KEY, "serverless-job-a1b2c3")); + DetectedPlatform mockServerlessPlatform = Mockito.mock(DetectedPlatform.class); + Mockito.when(mockServerlessPlatform.getSupportedPlatform()) + .thenReturn(GCPPlatformDetector.SupportedPlatform.GOOGLE_CLOUD_RUN_JOB); + Mockito.when(mockServerlessPlatform.getAttributes()).thenReturn(mockAttributes); + Mockito.when(mockServerlessPlatform.getProjectId()).thenReturn(DUMMY_PROJECT_ID); + return mockServerlessPlatform; + } + private static DetectedPlatform generateMockGaePlatform() { Map mockAttributes = new HashMap<>( @@ -274,7 +295,7 @@ private static void verifyGkeMapping(Resource gotResource, DetectedPlatform dete } @Test - public void testGcrResourceAttributesMapping() { + public void testGcrServiceResourceAttributesMapping() { GCPPlatformDetector mockDetector = Mockito.mock(GCPPlatformDetector.class); DetectedPlatform mockPlatform = generateMockServerlessPlatform(GCPPlatformDetector.SupportedPlatform.GOOGLE_CLOUD_RUN); @@ -321,6 +342,31 @@ private static void verifyServerlessMapping( .containsEntry(CLOUD_REGION, detectedAttributes.get(SERVERLESS_COMPUTE_CLOUD_REGION)); } + @Test + public void testGcrJobResourceAttributesMapping() { + GCPPlatformDetector mockDetector = Mockito.mock(GCPPlatformDetector.class); + DetectedPlatform mockPlatform = generateMockGcrJobPlatform(); + Mockito.when(mockDetector.detectPlatform()).thenReturn(mockPlatform); + Map detectedAttributes = mockPlatform.getAttributes(); + + Resource gotResource = new GCPResourceProvider(mockDetector).createResource(mockConfigProps); + verify(mockPlatform, Mockito.times(1)).getProjectId(); + + assertThat(gotResource.getAttributes()) + .hasSize(8) + .containsEntry(CLOUD_PROVIDER, GCP) + .containsEntry(CLOUD_PLATFORM, GCP_CLOUD_RUN) + .containsEntry(CLOUD_ACCOUNT_ID, DUMMY_PROJECT_ID) + .containsEntry(FAAS_NAME, detectedAttributes.get(SERVERLESS_COMPUTE_NAME)) + .containsEntry(FAAS_NAME, detectedAttributes.get(SERVERLESS_COMPUTE_NAME)) + .containsEntry(FAAS_INSTANCE, detectedAttributes.get(SERVERLESS_COMPUTE_INSTANCE_ID)) + .containsEntry(GCP_CLOUD_RUN_JOB_EXECUTION, detectedAttributes.get(GCR_JOB_EXECUTION_KEY)) + .containsEntry( + GCP_CLOUD_RUN_JOB_TASK_INDEX, + Integer.parseInt(detectedAttributes.get(GCR_JOB_TASK_INDEX))) + .containsEntry(CLOUD_REGION, detectedAttributes.get(SERVERLESS_COMPUTE_CLOUD_REGION)); + } + @Test public void testGaeResourceAttributeMapping() { GCPPlatformDetector mockDetector = Mockito.mock(GCPPlatformDetector.class);