From fd7aa9733e886fd2f26c77c64440d985c5e432ea Mon Sep 17 00:00:00 2001 From: Michele Mancioppi Date: Tue, 9 Aug 2022 16:59:51 +0200 Subject: [PATCH] Implement `aws.logs` attributes for the AwsEcsResourceDetector --- .../sdk/extension/aws/resource/ecs.py | 54 ++++++++++++++++++- .../tests/resource/test_ecs.py | 5 ++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/ecs.py b/sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/ecs.py index 5ea9d9372e..ee697ce7c5 100644 --- a/sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/ecs.py +++ b/sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/resource/ecs.py @@ -15,6 +15,7 @@ import json import logging import os +import re import socket from urllib.request import Request, urlopen @@ -91,7 +92,9 @@ def detect(self) -> "Resource": else f"{base_arn}:cluster/{cluster}" ) - return base_resource.merge( + logs_resource = _get_logs_resource(metadata_container) + + return base_resource.merge(logs_resource).merge( Resource( { ResourceAttributes.AWS_ECS_CONTAINER_ARN: metadata_container[ @@ -120,6 +123,55 @@ def detect(self) -> "Resource": return Resource.get_empty() + +def _get_logs_resource(metadata_container): + if metadata_container.get("LogDriver") == "awslogs": + log_options = metadata_container.get("LogOptions") + if log_options: + logs_region = log_options.get("awslogs-region") + logs_group_name = log_options.get("awslogs-group") + logs_stream_name = log_options.get("awslogs-stream") + + container_arn = metadata_container["ContainerARN"] + + if not logs_region: + aws_region_match = re.match(r'arn:aws:ecs:([^:]+):.*', container_arn) + if aws_region_match: + logs_region = aws_region_match.group(1) + + else: + logger.warning("Cannot parse AWS account out of ECS ARN") + + # We need to retrieve the account it from some other ARN to create the + # log-group and log-stream ARNs + aws_account = None + aws_account_match = re.match(r'arn:aws:ecs:[^:]+:([^:]+):.*', container_arn) + if aws_account_match: + aws_account = aws_account_match.group(1) + + logs_group_arn = None + logs_stream_arn = None + if logs_region and aws_account: + if logs_group_name: + logs_group_arn = f"arn:aws:logs:{logs_region}:{aws_account}:log-group:/aws{logs_group_name}:*" + + if logs_stream_name: + logs_stream_arn = f"arn:aws:logs:{logs_region}:{aws_account}:log-group:/aws{logs_group_name}:log-stream:{logs_stream_name}" + + return Resource( + { + ResourceAttributes.AWS_LOG_GROUP_NAMES: [logs_group_name], + ResourceAttributes.AWS_LOG_GROUP_ARNS: [logs_group_arn], + ResourceAttributes.AWS_LOG_STREAM_NAMES: [logs_stream_name], + ResourceAttributes.AWS_LOG_STREAM_ARNS: [logs_stream_arn], + } + ) + else: + logger.warning("The metadata endpoint v4 has returned 'awslogs' as 'LogDriver', but there is no 'LogOptions' data") + + return Resource.get_empty() + + def _http_get(url): with urlopen( Request(url, method="GET"), diff --git a/sdk-extension/opentelemetry-sdk-extension-aws/tests/resource/test_ecs.py b/sdk-extension/opentelemetry-sdk-extension-aws/tests/resource/test_ecs.py index ef4cfca0d6..124844614f 100644 --- a/sdk-extension/opentelemetry-sdk-extension-aws/tests/resource/test_ecs.py +++ b/sdk-extension/opentelemetry-sdk-extension-aws/tests/resource/test_ecs.py @@ -131,11 +131,16 @@ def test_simple_create_metadata_v4( ): mock_http_get_function.side_effect = _http_get_function actual = AwsEcsResourceDetector().detect() + self.maxDiff = None self.assertDictEqual( actual.attributes.copy(), OrderedDict( { **MockEcsResourceAttributes, + ResourceAttributes.AWS_LOG_GROUP_NAMES: ("/ecs/metadata",), + ResourceAttributes.AWS_LOG_GROUP_ARNS: ("arn:aws:logs:us-west-2:111122223333:log-group:/aws/ecs/metadata:*",), + ResourceAttributes.AWS_LOG_STREAM_NAMES: ("ecs/curl/8f03e41243824aea923aca126495f665",), + ResourceAttributes.AWS_LOG_STREAM_ARNS: ("arn:aws:logs:us-west-2:111122223333:log-group:/aws/ecs/metadata:log-stream:ecs/curl/8f03e41243824aea923aca126495f665",), ResourceAttributes.AWS_ECS_CONTAINER_ARN: "arn:aws:ecs:us-west-2:111122223333:container/0206b271-b33f-47ab-86c6-a0ba208a70a9", ResourceAttributes.AWS_ECS_CLUSTER_ARN: "arn:aws:ecs:us-west-2:111122223333:cluster/default", ResourceAttributes.AWS_ECS_LAUNCHTYPE: "EC2",