From b64de7baa75c84ec0146a0851f2ef6f02d4d85ed Mon Sep 17 00:00:00 2001 From: Mengyi Zhou Date: Thu, 27 Jun 2024 13:57:57 -0700 Subject: [PATCH] Add AWS ECS cluster detection --- .../contrib/aws/resource/EcsResource.java | 24 +++++++++++++++++-- .../aws/resource/IncubatingAttributes.java | 2 ++ .../contrib/aws/resource/EcsResourceTest.java | 3 +++ .../test/resources/ecs-task-metadata-v4.json | 2 +- 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java index a1fdb14d2..a5ea04d51 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java @@ -5,6 +5,7 @@ package io.opentelemetry.contrib.aws.resource; +import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.AWS_ECS_CLUSTER_ARN; import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.AWS_ECS_CONTAINER_ARN; import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.AWS_ECS_LAUNCHTYPE; import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.AWS_ECS_TASK_ARN; @@ -163,6 +164,8 @@ static void parseResponse( // account id and region tokens we need later for the cloud.account.id // and cloud.region attributes. String arn = null; + // Cluster can either be ARN or short name. + String cluster = null; while (parser.nextToken() != JsonToken.END_OBJECT) { String value = parser.nextTextValue(); @@ -176,6 +179,9 @@ static void parseResponse( case "DockerName": attrBuilders.put(CONTAINER_NAME, value); break; + case "Cluster": + cluster = value; + break; case "ContainerARN": arn = value; attrBuilders.put(AWS_ECS_CONTAINER_ARN, value); @@ -229,8 +235,22 @@ static void parseResponse( } } - getRegion(arn).ifPresent(region -> attrBuilders.put(CLOUD_REGION, region)); - getAccountId(arn).ifPresent(accountId -> attrBuilders.put(CLOUD_ACCOUNT_ID, accountId)); + String region = getRegion(arn).orElse(null); + String account = getAccountId(arn).orElse(null); + if (region != null) { + attrBuilders.put(CLOUD_REGION, region); + } + if (account != null) { + attrBuilders.put(CLOUD_ACCOUNT_ID, account); + } + if (cluster != null) { + if (cluster.contains(":")) { + attrBuilders.put(AWS_ECS_CLUSTER_ARN, cluster); + } else { + String clusterArn = String.format("arn:aws:ecs:%s:%s:cluster/%s", region, account, cluster); + attrBuilders.put(AWS_ECS_CLUSTER_ARN, clusterArn); + } + } } private EcsResource() {} diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/IncubatingAttributes.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/IncubatingAttributes.java index a81ee7f55..6033f5bcf 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/IncubatingAttributes.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/IncubatingAttributes.java @@ -62,6 +62,8 @@ private CloudProviderValues() {} public static final AttributeKey K8S_CLUSTER_NAME = AttributeKey.stringKey("k8s.cluster.name"); + public static final AttributeKey AWS_ECS_CLUSTER_ARN = + AttributeKey.stringKey("aws.ecs.cluster.arn"); public static final AttributeKey AWS_ECS_CONTAINER_ARN = AttributeKey.stringKey("aws.ecs.container.arn"); public static final AttributeKey AWS_ECS_LAUNCHTYPE = diff --git a/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EcsResourceTest.java b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EcsResourceTest.java index 8a5be041b..a2ad79d00 100644 --- a/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EcsResourceTest.java +++ b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EcsResourceTest.java @@ -6,6 +6,7 @@ package io.opentelemetry.contrib.aws.resource; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; +import static io.opentelemetry.semconv.incubating.AwsIncubatingAttributes.AWS_ECS_CLUSTER_ARN; import static io.opentelemetry.semconv.incubating.AwsIncubatingAttributes.AWS_ECS_CONTAINER_ARN; import static io.opentelemetry.semconv.incubating.AwsIncubatingAttributes.AWS_ECS_LAUNCHTYPE; import static io.opentelemetry.semconv.incubating.AwsIncubatingAttributes.AWS_ECS_TASK_ARN; @@ -78,6 +79,7 @@ void testCreateAttributesV3() throws IOException { entry(CONTAINER_ID, "43481a6ce4842eec8fe72fc28500c6b52edcc0917f105b83379f88cac1ff3946"), entry(CONTAINER_IMAGE_NAME, "nrdlngr/nginx-curl"), entry(io.opentelemetry.semconv.ResourceAttributes.CONTAINER_IMAGE_TAG, "latest"), + entry(AWS_ECS_CLUSTER_ARN, "arn:aws:ecs:us-east-2:012345678910:cluster/default"), entry( AttributeKey.stringKey("aws.ecs.container.image.id"), "sha256:2e00ae64383cfc865ba0a2ba37f61b50a120d2d9378559dcd458dc0de47bc165"), @@ -121,6 +123,7 @@ void testCreateAttributesV4() throws IOException { entry( AttributeKey.stringKey("aws.ecs.container.image.id"), "sha256:d691691e9652791a60114e67b365688d20d19940dde7c4736ea30e660d8d3553"), + entry(AWS_ECS_CLUSTER_ARN, "arn:aws:ecs:us-west-2:111122223333:cluster/default"), entry( AWS_ECS_CONTAINER_ARN, "arn:aws:ecs:us-west-2:111122223333:container/0206b271-b33f-47ab-86c6-a0ba208a70a9"), diff --git a/aws-resources/src/test/resources/ecs-task-metadata-v4.json b/aws-resources/src/test/resources/ecs-task-metadata-v4.json index c8043a745..3188de30f 100644 --- a/aws-resources/src/test/resources/ecs-task-metadata-v4.json +++ b/aws-resources/src/test/resources/ecs-task-metadata-v4.json @@ -1,5 +1,5 @@ { - "Cluster": "default", + "Cluster": "arn:aws:ecs:us-west-2:111122223333:cluster/default", "TaskARN": "arn:aws:ecs:us-west-2:111122223333:task/default/158d1c8083dd49d6b527399fd6414f5c", "Family": "curltest", "Revision": "26",