From a006dc692870afad6973d71c8900b08718434aae Mon Sep 17 00:00:00 2001 From: Michele Mancioppi Date: Mon, 9 Jan 2023 13:35:26 +0100 Subject: [PATCH] [Extensions.AWSXRay] Add ECS and Logs attributes based on Metadata v4 endpoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Piotr Kiełkowicz --- .../.publicApi/net452/PublicAPI.Unshipped.txt | 1 - .../.publicApi/net462/PublicAPI.Shipped.txt | 0 .../PublicAPI.Unshipped.txt} | 19 +-- .../netstandard2.0/PublicAPI.Shipped.txt | 12 +- .../netstandard2.0/PublicAPI.Unshipped.txt | 17 ++ .../CHANGELOG.md | 11 ++ ...elemetry.Contrib.Extensions.AWSXRay.csproj | 6 +- .../Resources/AWSEBSResourceDetector.cs | 43 +++-- .../Resources/AWSEC2ResourceDetector.cs | 55 ++++-- .../Resources/AWSECSResourceDetector.cs | 142 +++++++++++++-- .../Resources/AWSEKSResourceDetector.cs | 24 +-- .../Resources/AWSLambdaResourceDetector.cs | 25 ++- .../Resources/AWSSemanticConventions.cs | 14 ++ .../Resources/IResourceDetector.cs | 32 ---- .../Resources/ResourceBuilderExtensions.cs | 46 ----- .../Resources/ResourceDetectorUtils.cs | 7 +- ...ry.Contrib.Extensions.AWSXRay.Tests.csproj | 26 ++- .../Resources/TestAWSEBSResourceDetector.cs | 6 +- .../Resources/TestAWSEC2ResourceDetector.cs | 6 +- .../Resources/TestAWSECSResourceDetector.cs | 161 ++++++++++++++---- .../Resources/TestAWSEKSResourceDetector.cs | 6 +- .../TestAWSLambdaResourceDetector.cs | 3 +- .../TestResourceBuilderExtensions.cs | 54 ------ .../metadatav4-response-container-ec2.json | 44 +++++ ...metadatav4-response-container-fargate.json | 50 ++++++ .../metadatav4-response-task-ec2.json | 94 ++++++++++ .../metadatav4-response-task-fargate.json | 77 +++++++++ 27 files changed, 703 insertions(+), 278 deletions(-) delete mode 100644 src/OpenTelemetry.Contrib.Extensions.AWSXRay/.publicApi/net452/PublicAPI.Unshipped.txt create mode 100644 src/OpenTelemetry.Contrib.Extensions.AWSXRay/.publicApi/net462/PublicAPI.Shipped.txt rename src/OpenTelemetry.Contrib.Extensions.AWSXRay/.publicApi/{net452/PublicAPI.Shipped.txt => net462/PublicAPI.Unshipped.txt} (51%) delete mode 100644 src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/IResourceDetector.cs delete mode 100644 src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/ResourceBuilderExtensions.cs delete mode 100644 test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestResourceBuilderExtensions.cs create mode 100644 test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/ecs_metadata/metadatav4-response-container-ec2.json create mode 100644 test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/ecs_metadata/metadatav4-response-container-fargate.json create mode 100644 test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/ecs_metadata/metadatav4-response-task-ec2.json create mode 100644 test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/ecs_metadata/metadatav4-response-task-fargate.json diff --git a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/.publicApi/net452/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/.publicApi/net452/PublicAPI.Unshipped.txt deleted file mode 100644 index 7dc5c58110..0000000000 --- a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/.publicApi/net452/PublicAPI.Unshipped.txt +++ /dev/null @@ -1 +0,0 @@ -#nullable enable diff --git a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/.publicApi/net462/PublicAPI.Shipped.txt b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/.publicApi/net462/PublicAPI.Shipped.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/.publicApi/net452/PublicAPI.Shipped.txt b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/.publicApi/net462/PublicAPI.Unshipped.txt similarity index 51% rename from src/OpenTelemetry.Contrib.Extensions.AWSXRay/.publicApi/net452/PublicAPI.Shipped.txt rename to src/OpenTelemetry.Contrib.Extensions.AWSXRay/.publicApi/net462/PublicAPI.Unshipped.txt index c9c69207b1..1f9d47053b 100644 --- a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/.publicApi/net452/PublicAPI.Shipped.txt +++ b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/.publicApi/net462/PublicAPI.Unshipped.txt @@ -1,22 +1,17 @@ -#nullable enable OpenTelemetry.Contrib.Extensions.AWSXRay.AWSXRayIdGenerator OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.AWSEBSResourceDetector OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.AWSEBSResourceDetector.AWSEBSResourceDetector() -> void -OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.AWSEBSResourceDetector.Detect() -> System.Collections.Generic.IEnumerable>? +OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.AWSEBSResourceDetector.Detect() -> OpenTelemetry.Resources.Resource OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.AWSEC2ResourceDetector OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.AWSEC2ResourceDetector.AWSEC2ResourceDetector() -> void -OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.AWSEC2ResourceDetector.Detect() -> System.Collections.Generic.IEnumerable>? -OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.IResourceDetector -OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.IResourceDetector.Detect() -> System.Collections.Generic.IEnumerable>? +OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.AWSEC2ResourceDetector.Detect() -> OpenTelemetry.Resources.Resource OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.ResourceDetectorUtils OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.ResourceDetectorUtils.ResourceDetectorUtils() -> void OpenTelemetry.Contrib.Extensions.AWSXRay.Trace.AWSXRayPropagator OpenTelemetry.Contrib.Extensions.AWSXRay.Trace.AWSXRayPropagator.AWSXRayPropagator() -> void -OpenTelemetry.Resources.ResourceBuilderExtensions OpenTelemetry.Trace.TracerProviderBuilderExtensions -override OpenTelemetry.Contrib.Extensions.AWSXRay.Trace.AWSXRayPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func!>! getter) -> OpenTelemetry.Context.Propagation.PropagationContext -override OpenTelemetry.Contrib.Extensions.AWSXRay.Trace.AWSXRayPropagator.Fields.get -> System.Collections.Generic.ISet! -override OpenTelemetry.Contrib.Extensions.AWSXRay.Trace.AWSXRayPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action! setter) -> void -static OpenTelemetry.Resources.ResourceBuilderExtensions.AddDetector(this OpenTelemetry.Resources.ResourceBuilder! resourceBuilder, OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.IResourceDetector! resourceDetector) -> OpenTelemetry.Resources.ResourceBuilder! -static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddXRayTraceId(this OpenTelemetry.Trace.TracerProviderBuilder! builder) -> OpenTelemetry.Trace.TracerProviderBuilder! -static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddXRayTraceIdWithSampler(this OpenTelemetry.Trace.TracerProviderBuilder! builder, OpenTelemetry.Trace.Sampler! sampler) -> OpenTelemetry.Trace.TracerProviderBuilder! +override OpenTelemetry.Contrib.Extensions.AWSXRay.Trace.AWSXRayPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +override OpenTelemetry.Contrib.Extensions.AWSXRay.Trace.AWSXRayPropagator.Fields.get -> System.Collections.Generic.ISet +override OpenTelemetry.Contrib.Extensions.AWSXRay.Trace.AWSXRayPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddXRayTraceId(this OpenTelemetry.Trace.TracerProviderBuilder builder) -> OpenTelemetry.Trace.TracerProviderBuilder +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddXRayTraceIdWithSampler(this OpenTelemetry.Trace.TracerProviderBuilder builder, OpenTelemetry.Trace.Sampler sampler) -> OpenTelemetry.Trace.TracerProviderBuilder \ No newline at end of file diff --git a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/.publicApi/netstandard2.0/PublicAPI.Shipped.txt b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/.publicApi/netstandard2.0/PublicAPI.Shipped.txt index 0c8b8d923f..7caaff30bb 100644 --- a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/.publicApi/netstandard2.0/PublicAPI.Shipped.txt +++ b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/.publicApi/netstandard2.0/PublicAPI.Shipped.txt @@ -21,11 +21,9 @@ OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.ResourceDetectorUtils OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.ResourceDetectorUtils.ResourceDetectorUtils() -> void OpenTelemetry.Contrib.Extensions.AWSXRay.Trace.AWSXRayPropagator OpenTelemetry.Contrib.Extensions.AWSXRay.Trace.AWSXRayPropagator.AWSXRayPropagator() -> void -OpenTelemetry.Resources.ResourceBuilderExtensions OpenTelemetry.Trace.TracerProviderBuilderExtensions -override OpenTelemetry.Contrib.Extensions.AWSXRay.Trace.AWSXRayPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func!>! getter) -> OpenTelemetry.Context.Propagation.PropagationContext -override OpenTelemetry.Contrib.Extensions.AWSXRay.Trace.AWSXRayPropagator.Fields.get -> System.Collections.Generic.ISet! -override OpenTelemetry.Contrib.Extensions.AWSXRay.Trace.AWSXRayPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action! setter) -> void -static OpenTelemetry.Resources.ResourceBuilderExtensions.AddDetector(this OpenTelemetry.Resources.ResourceBuilder! resourceBuilder, OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.IResourceDetector! resourceDetector) -> OpenTelemetry.Resources.ResourceBuilder! -static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddXRayTraceId(this OpenTelemetry.Trace.TracerProviderBuilder! builder) -> OpenTelemetry.Trace.TracerProviderBuilder! -static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddXRayTraceIdWithSampler(this OpenTelemetry.Trace.TracerProviderBuilder! builder, OpenTelemetry.Trace.Sampler! sampler) -> OpenTelemetry.Trace.TracerProviderBuilder! +override OpenTelemetry.Contrib.Extensions.AWSXRay.Trace.AWSXRayPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +override OpenTelemetry.Contrib.Extensions.AWSXRay.Trace.AWSXRayPropagator.Fields.get -> System.Collections.Generic.ISet +override OpenTelemetry.Contrib.Extensions.AWSXRay.Trace.AWSXRayPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddXRayTraceId(this OpenTelemetry.Trace.TracerProviderBuilder builder) -> OpenTelemetry.Trace.TracerProviderBuilder +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddXRayTraceIdWithSampler(this OpenTelemetry.Trace.TracerProviderBuilder builder, OpenTelemetry.Trace.Sampler sampler) -> OpenTelemetry.Trace.TracerProviderBuilder diff --git a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt index 7dc5c58110..45715258f5 100644 --- a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -1 +1,18 @@ #nullable enable +OpenTelemetry.Contrib.Extensions.AWSXRay.AWSXRayIdGenerator +OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.AWSEBSResourceDetector +OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.AWSEBSResourceDetector.AWSEBSResourceDetector() -> void +*REMOVED*OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.AWSEBSResourceDetector.Detect() -> System.Collections.Generic.IEnumerable> +OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.AWSEBSResourceDetector.Detect() -> OpenTelemetry.Resources.Resource +*REMOVED*OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.AWSEC2ResourceDetector.Detect() -> System.Collections.Generic.IEnumerable> +OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.AWSEC2ResourceDetector.Detect() -> OpenTelemetry.Resources.Resource +*REMOVED*OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.AWSECSResourceDetector.Detect() -> System.Collections.Generic.IEnumerable> +OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.AWSECSResourceDetector.Detect() -> OpenTelemetry.Resources.Resource +*REMOVED*OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.AWSEKSResourceDetector.Detect() -> System.Collections.Generic.IEnumerable> +OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.AWSEKSResourceDetector.Detect() -> OpenTelemetry.Resources.Resource +*REMOVED*OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.AWSLambdaResourceDetector.Detect() -> System.Collections.Generic.IEnumerable> +OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.AWSLambdaResourceDetector.Detect() -> OpenTelemetry.Resources.Resource +*REMOVED*OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.IResourceDetector +*REMOVED*OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.IResourceDetector.Detect() -> System.Collections.Generic.IEnumerable> +*REMOVED*OpenTelemetry.Resources.ResourceBuilderExtensions +*REMOVED*static OpenTelemetry.Resources.ResourceBuilderExtensions.AddDetector(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder, OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.IResourceDetector resourceDetector) -> OpenTelemetry.Resources.ResourceBuilder diff --git a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/CHANGELOG.md b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/CHANGELOG.md index 2a694f0725..0b3cb1d475 100644 --- a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/CHANGELOG.md +++ b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/CHANGELOG.md @@ -5,6 +5,17 @@ * Enhancement - AWSXRayIdGenerator - Generate X-Ray IDs with global Random instance instead of recreating with ThreadLocal ([#380](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/380)) +* Raised minimum .NET version to `net462` + ([#875](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/875)) +* Updated OTel SDK package version to 1.3.1 + ([#875](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/875)) +* Enhancement - AWSECSResourceDetector - Implement `aws.{ecs.*,log.*}` resource + attributes with data from ECS Metadata endpoint v4 + ([#875](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/875)) +* Removal - IResourceDetector - Remove local IResourceDetector interface and its + supporting ResourceBuilderExtensions extension, and migrate all detectors to + implement OpenTelemetry.Resources.IResourceDetector + ([#875](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/875)) ## 1.2.0 diff --git a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/OpenTelemetry.Contrib.Extensions.AWSXRay.csproj b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/OpenTelemetry.Contrib.Extensions.AWSXRay.csproj index e70b11a93c..7dbba22c44 100644 --- a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/OpenTelemetry.Contrib.Extensions.AWSXRay.csproj +++ b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/OpenTelemetry.Contrib.Extensions.AWSXRay.csproj @@ -1,7 +1,7 @@ - netstandard2.0;net452 + netstandard2.0;$(NetFrameworkMinimumSupportedVersion) OpenTelemetry extensions for AWS X-Ray. Extensions.AWSXRay- enable @@ -9,11 +9,11 @@ - + - + diff --git a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSEBSResourceDetector.cs b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSEBSResourceDetector.cs index 141464c14e..e84b947534 100644 --- a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSEBSResourceDetector.cs +++ b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSEBSResourceDetector.cs @@ -19,7 +19,9 @@ #if NETSTANDARD using System.Runtime.InteropServices; #endif + using OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.Models; +using OpenTelemetry.Resources; namespace OpenTelemetry.Contrib.Extensions.AWSXRay.Resources; @@ -34,11 +36,9 @@ public class AWSEBSResourceDetector : IResourceDetector /// /// Detector the required and optional resource attributes from AWS ElasticBeanstalk. /// - /// List of key-value pairs of resource attributes. - public IEnumerable>? Detect() + /// Resource with key-value pairs of resource attributes. + public Resource Detect() { - List>? resourceAttributes = null; - try { string? filePath = null; @@ -57,28 +57,43 @@ public class AWSEBSResourceDetector : IResourceDetector var metadata = this.GetEBSMetadata(filePath); - resourceAttributes = this.ExtractResourceAttributes(metadata); + return new Resource(this.ExtractResourceAttributes(metadata)); } catch (Exception ex) { AWSXRayEventSource.Log.ResourceAttributesExtractException(nameof(AWSEBSResourceDetector), ex); } - return resourceAttributes; + return Resource.Empty; } - internal List>? ExtractResourceAttributes(AWSEBSMetadataModel? metadata) + internal List> ExtractResourceAttributes(AWSEBSMetadataModel? metadata) { - var resourceAttributes = new List>() + var resourceAttributes = new List>() { - new KeyValuePair(AWSSemanticConventions.AttributeCloudProvider, "aws"), - new KeyValuePair(AWSSemanticConventions.AttributeCloudPlatform, "aws_elastic_beanstalk"), - new KeyValuePair(AWSSemanticConventions.AttributeServiceName, "aws_elastic_beanstalk"), - new KeyValuePair(AWSSemanticConventions.AttributeServiceNamespace, metadata?.EnvironmentName), - new KeyValuePair(AWSSemanticConventions.AttributeServiceInstanceID, metadata?.DeploymentId), - new KeyValuePair(AWSSemanticConventions.AttributeServiceVersion, metadata?.VersionLabel), + new KeyValuePair(AWSSemanticConventions.AttributeCloudProvider, "aws"), + new KeyValuePair(AWSSemanticConventions.AttributeCloudPlatform, "aws_elastic_beanstalk"), + new KeyValuePair(AWSSemanticConventions.AttributeServiceName, "aws_elastic_beanstalk"), }; + if (metadata != null) + { + if (metadata.EnvironmentName != null) + { + resourceAttributes.Add(new KeyValuePair(AWSSemanticConventions.AttributeServiceNamespace, metadata.EnvironmentName)); + } + + if (metadata.DeploymentId != null) + { + resourceAttributes.Add(new KeyValuePair(AWSSemanticConventions.AttributeServiceInstanceID, metadata.DeploymentId)); + } + + if (metadata.VersionLabel != null) + { + resourceAttributes.Add(new KeyValuePair(AWSSemanticConventions.AttributeServiceVersion, metadata.VersionLabel)); + } + } + return resourceAttributes; } diff --git a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSEC2ResourceDetector.cs b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSEC2ResourceDetector.cs index b6c5908929..9414326a6c 100644 --- a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSEC2ResourceDetector.cs +++ b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSEC2ResourceDetector.cs @@ -16,7 +16,9 @@ using System; using System.Collections.Generic; + using OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.Models; +using OpenTelemetry.Resources; namespace OpenTelemetry.Contrib.Extensions.AWSXRay.Resources; @@ -34,41 +36,62 @@ public class AWSEC2ResourceDetector : IResourceDetector /// /// Detector the required and optional resource attributes from AWS EC2. /// - /// List of key-value pairs of resource attributes. - public IEnumerable>? Detect() + /// Resource with key-value pairs of resource attributes. + public Resource Detect() { - List>? resourceAttributes = null; - try { var token = this.GetAWSEC2Token(); var identity = this.GetAWSEC2Identity(token); var hostName = this.GetAWSEC2HostName(token); - resourceAttributes = this.ExtractResourceAttributes(identity, hostName); + return new Resource(this.ExtractResourceAttributes(identity, hostName)); } catch (Exception ex) { AWSXRayEventSource.Log.ResourceAttributesExtractException(nameof(AWSEC2ResourceDetector), ex); } - return resourceAttributes; + return Resource.Empty; } - internal List> ExtractResourceAttributes(AWSEC2IdentityDocumentModel? identity, string hostName) + internal List> ExtractResourceAttributes(AWSEC2IdentityDocumentModel? identity, string hostName) { - var resourceAttributes = new List>() + var resourceAttributes = new List>() { - new KeyValuePair(AWSSemanticConventions.AttributeCloudProvider, "aws"), - new KeyValuePair(AWSSemanticConventions.AttributeCloudPlatform, "aws_ec2"), - new KeyValuePair(AWSSemanticConventions.AttributeCloudAccountID, identity?.AccountId), - new KeyValuePair(AWSSemanticConventions.AttributeCloudAvailableZone, identity?.AvailabilityZone), - new KeyValuePair(AWSSemanticConventions.AttributeHostID, identity?.InstanceId), - new KeyValuePair(AWSSemanticConventions.AttributeHostType, identity?.InstanceType), - new KeyValuePair(AWSSemanticConventions.AttributeCloudRegion, identity?.Region), - new KeyValuePair(AWSSemanticConventions.AttributeHostName, hostName), + new KeyValuePair(AWSSemanticConventions.AttributeCloudProvider, "aws"), + new KeyValuePair(AWSSemanticConventions.AttributeCloudPlatform, "aws_ec2"), + new KeyValuePair(AWSSemanticConventions.AttributeHostName, hostName), }; + if (identity != null) + { + if (identity.AccountId != null) + { + resourceAttributes.Add(new KeyValuePair(AWSSemanticConventions.AttributeCloudAccountID, identity.AccountId)); + } + + if (identity.AvailabilityZone != null) + { + resourceAttributes.Add(new KeyValuePair(AWSSemanticConventions.AttributeCloudAvailableZone, identity.AvailabilityZone)); + } + + if (identity.InstanceId != null) + { + resourceAttributes.Add(new KeyValuePair(AWSSemanticConventions.AttributeHostID, identity.InstanceId)); + } + + if (identity.InstanceType != null) + { + resourceAttributes.Add(new KeyValuePair(AWSSemanticConventions.AttributeHostType, identity.InstanceType)); + } + + if (identity.Region != null) + { + resourceAttributes.Add(new KeyValuePair(AWSSemanticConventions.AttributeCloudRegion, identity.Region)); + } + } + return resourceAttributes; } diff --git a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSECSResourceDetector.cs b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSECSResourceDetector.cs index 9331685a8e..afb406b700 100644 --- a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSECSResourceDetector.cs +++ b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSECSResourceDetector.cs @@ -16,6 +16,12 @@ using System; using System.Collections.Generic; +using System.Net.Http; +using System.Text.RegularExpressions; + +using Newtonsoft.Json.Linq; + +using OpenTelemetry.Resources; namespace OpenTelemetry.Contrib.Extensions.AWSXRay.Resources; @@ -31,39 +37,151 @@ public class AWSECSResourceDetector : IResourceDetector /// /// Detector the required and optional resource attributes from AWS ECS. /// - /// List of key-value pairs of resource attributes. - public IEnumerable>? Detect() + /// Resource with key-value pairs of resource attributes. + public Resource Detect() { - List>? resourceAttributes = null; - if (!this.IsECSProcess()) { - return resourceAttributes; + return Resource.Empty; } + var resourceAttributes = new List>() + { + new KeyValuePair(AWSSemanticConventions.AttributeCloudProvider, "aws"), + new KeyValuePair(AWSSemanticConventions.AttributeCloudPlatform, "aws_ecs"), + }; + try { var containerId = this.GetECSContainerId(AWSECSMetadataPath); + if (containerId != null) + { + resourceAttributes.Add(new KeyValuePair(AWSSemanticConventions.AttributeContainerID, containerId)); + } + } + catch (Exception ex) + { + AWSXRayEventSource.Log.ResourceAttributesExtractException(nameof(AWSECSResourceDetector), ex); + } - resourceAttributes = this.ExtractResourceAttributes(containerId); + try + { + resourceAttributes.AddRange(this.ExtractMetadataV4ResourceAttributes()); } catch (Exception ex) { AWSXRayEventSource.Log.ResourceAttributesExtractException(nameof(AWSECSResourceDetector), ex); } - return resourceAttributes; + return new Resource(resourceAttributes); } - internal List> ExtractResourceAttributes(string? containerId) + internal List> ExtractMetadataV4ResourceAttributes() { - var resourceAttributes = new List>() + var metadataV4Url = Environment.GetEnvironmentVariable(AWSECSMetadataURLV4Key); + if (metadataV4Url == null) + { + return new List>(); + } + + var httpClientHandler = new HttpClientHandler(); + var metadataV4ContainerResponse = ResourceDetectorUtils.SendOutRequest(metadataV4Url, "GET", null, httpClientHandler).Result; + var metadataV4TaskResponse = ResourceDetectorUtils.SendOutRequest($"{metadataV4Url.TrimEnd('/')}/task", "GET", null, httpClientHandler).Result; + + var containerResponse = JObject.Parse(metadataV4ContainerResponse); + var taskResponse = JObject.Parse(metadataV4TaskResponse); + + var containerArn = containerResponse.Value("ContainerARN"); + if (containerArn == null) + { + AWSXRayEventSource.Log.ResourceAttributesExtractException(nameof(AWSECSResourceDetector), new ArgumentException("The ECS Metadata V4 response did not contain the 'ContainerARN' field")); + return new List>(); + } + + var clusterArn = taskResponse.Value("Cluster"); + if (clusterArn == null) + { + AWSXRayEventSource.Log.ResourceAttributesExtractException(nameof(AWSECSResourceDetector), new ArgumentException("The ECS Metadata V4 response did not contain the 'Cluster' field")); + return new List>(); + } + + if (!clusterArn.StartsWith("arn:")) + { + var baseArn = containerArn.Substring(containerArn.LastIndexOf(":")); + clusterArn = $"{baseArn}:cluster/{clusterArn}"; + } + + var resourceAttributes = new List>() { - new KeyValuePair(AWSSemanticConventions.AttributeCloudProvider, "aws"), - new KeyValuePair(AWSSemanticConventions.AttributeCloudPlatform, "aws_ecs"), - new KeyValuePair(AWSSemanticConventions.AttributeContainerID, containerId), + new KeyValuePair(AWSSemanticConventions.AttributeEcsContainerArn, containerArn), + new KeyValuePair(AWSSemanticConventions.AttributeEcsClusterArn, clusterArn), }; + var launchType = taskResponse.Value("LaunchType") switch { + string type when "ec2".Equals(type.ToLower()) => AWSSemanticConventions.ValueEcsLaunchTypeEc2, + string type when "fargate".Equals(type.ToLower()) => AWSSemanticConventions.ValueEcsLaunchTypeFargate, + _ => null, + }; + + if (launchType != null) + { + resourceAttributes.Add(new KeyValuePair(AWSSemanticConventions.AttributeEcsLaunchtype, launchType)); + } + else + { + AWSXRayEventSource.Log.ResourceAttributesExtractException(nameof(AWSECSResourceDetector), new ArgumentException($"The ECS Metadata V4 response contained the unrecognized launch type '{taskResponse["LaunchType"]}'")); + } + + var taskArn = taskResponse.Value("TaskARN"); + if (taskArn != null) + { + resourceAttributes.Add(new KeyValuePair(AWSSemanticConventions.AttributeEcsTaskArn, taskArn)); + } + + var family = taskResponse.Value("Family"); + if (family != null) + { + resourceAttributes.Add(new KeyValuePair(AWSSemanticConventions.AttributeEcsTaskFamily, family)); + } + + var revision = taskResponse.Value("Revision"); + if (revision != null) + { + resourceAttributes.Add(new KeyValuePair(AWSSemanticConventions.AttributeEcsTaskRevision, revision)); + } + + if ("awslogs".Equals(containerResponse.Value("LogDriver"))) + { + JObject? logOptions = containerResponse.Value("LogOptions"); + if (logOptions != null) + { + var regex = new Regex(@"arn:aws:ecs:([^:]+):([^:]+):.*"); + var match = regex.Match(containerArn); + + if (!match.Success) + { + throw new ArgumentOutOfRangeException($"Cannot parse region and account from the container ARN '{containerArn}'"); + } + + var logsRegion = match.Groups[1]; + var logsAccount = match.Groups[2]; + + var logGroupName = logOptions.Value("awslogs-group"); + if (logGroupName != null) + { + resourceAttributes.Add(new KeyValuePair(AWSSemanticConventions.AttributeLogGroupNames, new string[] { logGroupName })); + resourceAttributes.Add(new KeyValuePair(AWSSemanticConventions.AttributeLogGroupArns, new string[] { $"arn:aws:logs:{logsRegion}:{logsAccount}:log-group:{logGroupName}:*" })); + + var logStreamName = logOptions.Value("awslogs-stream"); + if (logStreamName != null) + { + resourceAttributes.Add(new KeyValuePair(AWSSemanticConventions.AttributeLogStreamNames, new string[] { logStreamName })); + resourceAttributes.Add(new KeyValuePair(AWSSemanticConventions.AttributeLogStreamArns, new string[] { $"arn:aws:logs:{logsRegion}:{logsAccount}:log-group:{logGroupName}:log-stream:{logStreamName}" })); + } + } + } + } + return resourceAttributes; } diff --git a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSEKSResourceDetector.cs b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSEKSResourceDetector.cs index 51c83c24be..a5915f9b29 100644 --- a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSEKSResourceDetector.cs +++ b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSEKSResourceDetector.cs @@ -18,8 +18,10 @@ using System.Collections.Generic; using System.Net.Http; using System.Text; + using OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.Http; using OpenTelemetry.Contrib.Extensions.AWSXRay.Resources.Models; +using OpenTelemetry.Resources; namespace OpenTelemetry.Contrib.Extensions.AWSXRay.Resources; @@ -37,38 +39,38 @@ public class AWSEKSResourceDetector : IResourceDetector /// /// Detector the required and optional resource attributes from AWS EKS. /// - /// List of key-value pairs of resource attributes. - public IEnumerable>? Detect() + /// Resource with key-value pairs of resource attributes. + public Resource Detect() { var credentials = this.GetEKSCredentials(AWSEKSCredentialPath); var httpClientHandler = Handler.Create(AWSEKSCertificatePath); if (credentials == null || !this.IsEKSProcess(credentials, httpClientHandler)) { - return null; + return Resource.Empty; } - return this.ExtractResourceAttributes( + return new Resource(this.ExtractResourceAttributes( this.GetEKSClusterName(credentials, httpClientHandler), - this.GetEKSContainerId(AWSEKSMetadataFilePath)); + this.GetEKSContainerId(AWSEKSMetadataFilePath))); } - internal List> ExtractResourceAttributes(string? clusterName, string? containerId) + internal List> ExtractResourceAttributes(string? clusterName, string? containerId) { - var resourceAttributes = new List>() + var resourceAttributes = new List>() { - new KeyValuePair(AWSSemanticConventions.AttributeCloudProvider, "aws"), - new KeyValuePair(AWSSemanticConventions.AttributeCloudPlatform, "aws_eks"), + new KeyValuePair(AWSSemanticConventions.AttributeCloudProvider, "aws"), + new KeyValuePair(AWSSemanticConventions.AttributeCloudPlatform, "aws_eks"), }; if (!string.IsNullOrEmpty(clusterName)) { - resourceAttributes.Add(new KeyValuePair(AWSSemanticConventions.AttributeK8SClusterName, clusterName)); + resourceAttributes.Add(new KeyValuePair(AWSSemanticConventions.AttributeK8SClusterName, clusterName!)); } if (!string.IsNullOrEmpty(containerId)) { - resourceAttributes.Add(new KeyValuePair(AWSSemanticConventions.AttributeContainerID, containerId)); + resourceAttributes.Add(new KeyValuePair(AWSSemanticConventions.AttributeContainerID, containerId!)); } return resourceAttributes; diff --git a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSLambdaResourceDetector.cs b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSLambdaResourceDetector.cs index ec163976b7..ef00870125 100644 --- a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSLambdaResourceDetector.cs +++ b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSLambdaResourceDetector.cs @@ -16,6 +16,7 @@ using System; using System.Collections.Generic; +using OpenTelemetry.Resources; namespace OpenTelemetry.Contrib.Extensions.AWSXRay.Resources; @@ -31,32 +32,30 @@ public class AWSLambdaResourceDetector : IResourceDetector /// /// Detector the required and optional resource attributes from AWS Lambda. /// - /// List of key-value pairs of resource attributes. - public IEnumerable>? Detect() + /// Resource with key-value pairs of resource attributes. + public Resource Detect() { - List>? resourceAttributes = null; - try { - resourceAttributes = this.ExtractResourceAttributes(); + return new Resource(this.ExtractResourceAttributes()); } catch (Exception ex) { AWSXRayEventSource.Log.ResourceAttributesExtractException(nameof(AWSLambdaResourceDetector), ex); } - return resourceAttributes; + return Resource.Empty; } - internal List> ExtractResourceAttributes() + internal List> ExtractResourceAttributes() { - var resourceAttributes = new List>() + var resourceAttributes = new List>() { - new KeyValuePair(AWSSemanticConventions.AttributeCloudProvider, "aws"), - new KeyValuePair(AWSSemanticConventions.AttributeCloudPlatform, "aws_lambda"), - new KeyValuePair(AWSSemanticConventions.AttributeCloudRegion, GetAWSRegion()), - new KeyValuePair(AWSSemanticConventions.AttributeFaasName, GetFunctionName()), - new KeyValuePair(AWSSemanticConventions.AttributeFaasVersion, GetFunctionVersion()), + new KeyValuePair(AWSSemanticConventions.AttributeCloudProvider, "aws"), + new KeyValuePair(AWSSemanticConventions.AttributeCloudPlatform, "aws_lambda"), + new KeyValuePair(AWSSemanticConventions.AttributeCloudRegion, GetAWSRegion()), + new KeyValuePair(AWSSemanticConventions.AttributeFaasName, GetFunctionName()), + new KeyValuePair(AWSSemanticConventions.AttributeFaasVersion, GetFunctionVersion()), }; return resourceAttributes; diff --git a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSSemanticConventions.cs b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSSemanticConventions.cs index 5291bcf77b..afb4341c5b 100644 --- a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSSemanticConventions.cs +++ b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSSemanticConventions.cs @@ -26,6 +26,15 @@ internal static class AWSSemanticConventions public const string AttributeContainerID = "container.id"; + public const string AttributeEcsContainerArn = "aws.ecs.container.arn"; + public const string AttributeEcsClusterArn = "aws.ecs.cluster.arn"; + public const string AttributeEcsLaunchtype = "aws.ecs.launchtype"; + public const string ValueEcsLaunchTypeEc2 = "ec2"; + public const string ValueEcsLaunchTypeFargate = "fargate"; + public const string AttributeEcsTaskArn = "aws.ecs.task.arn"; + public const string AttributeEcsTaskFamily = "aws.ecs.task.family"; + public const string AttributeEcsTaskRevision = "aws.ecs.task.revision"; + public const string AttributeFaasExecution = "faas.execution"; public const string AttributeFaasID = "faas.id"; public const string AttributeFaasName = "faas.name"; @@ -37,6 +46,11 @@ internal static class AWSSemanticConventions public const string AttributeK8SClusterName = "k8s.cluster.name"; + public const string AttributeLogGroupNames = "aws.log.group.names"; + public const string AttributeLogGroupArns = "aws.log.group.arns"; + public const string AttributeLogStreamNames = "aws.log.stream.names"; + public const string AttributeLogStreamArns = "aws.log.stream.arns"; + public const string AttributeServiceName = "service.name"; public const string AttributeServiceNamespace = "service.namespace"; public const string AttributeServiceInstanceID = "service.instance.id"; diff --git a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/IResourceDetector.cs b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/IResourceDetector.cs deleted file mode 100644 index 7ee26bd3af..0000000000 --- a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/IResourceDetector.cs +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright The OpenTelemetry Authors -// -// 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. -// - -using System.Collections.Generic; - -namespace OpenTelemetry.Contrib.Extensions.AWSXRay.Resources; - -/// -/// Resource detector interface. -/// Mocking https://github.com/open-telemetry/opentelemetry-dotnet/blob/6b7f2dd77cf9d37260a853fcc95f7b77e296065d/src/OpenTelemetry/Resources/IResourceDetector.cs. -/// -public interface IResourceDetector -{ - /// - /// Called to get key-value pairs of attribute from detector. - /// - /// List of key-value pairs of resource attributes. - IEnumerable>? Detect(); -} diff --git a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/ResourceBuilderExtensions.cs b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/ResourceBuilderExtensions.cs deleted file mode 100644 index 0aa64e40a2..0000000000 --- a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/ResourceBuilderExtensions.cs +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright The OpenTelemetry Authors -// -// 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. -// - -using OpenTelemetry.Contrib.Extensions.AWSXRay.Resources; -using OpenTelemetry.Internal; - -namespace OpenTelemetry.Resources; - -/// -/// Extension class for ResourceBuilder. -/// -public static class ResourceBuilderExtensions -{ - /// - /// Add resource detector to ResourceBuilder. - /// - /// being configured. - /// being added. - /// The instance of to chain the calls. - public static ResourceBuilder AddDetector(this ResourceBuilder resourceBuilder, IResourceDetector resourceDetector) - { - Guard.ThrowIfNull(resourceDetector); - - var resourceAttributes = resourceDetector.Detect(); - - if (resourceAttributes != null) - { - resourceBuilder.AddAttributes(resourceAttributes); - } - - return resourceBuilder; - } -} diff --git a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/ResourceDetectorUtils.cs b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/ResourceDetectorUtils.cs index 74509c9cad..fac82fe11f 100644 --- a/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/ResourceDetectorUtils.cs +++ b/src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/ResourceDetectorUtils.cs @@ -29,13 +29,16 @@ namespace OpenTelemetry.Contrib.Extensions.AWSXRay.Resources; /// public class ResourceDetectorUtils { - internal static async Task SendOutRequest(string url, string method, KeyValuePair header, HttpClientHandler? handler = null) + internal static async Task SendOutRequest(string url, string method, KeyValuePair? header, HttpClientHandler? handler = null) { using (var httpRequestMessage = new HttpRequestMessage()) { httpRequestMessage.RequestUri = new Uri(url); httpRequestMessage.Method = new HttpMethod(method); - httpRequestMessage.Headers.Add(header.Key, header.Value); + if (header.HasValue) + { + httpRequestMessage.Headers.Add(header.Value.Key, header.Value.Value); + } var httpClient = handler == null ? new HttpClient() : new HttpClient(handler); using (var response = await httpClient.SendAsync(httpRequestMessage)) diff --git a/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests.csproj b/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests.csproj index a666403913..68fa51593c 100644 --- a/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests.csproj +++ b/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests.csproj @@ -1,11 +1,8 @@ - Unit test project for AWS X-Ray for OpenTelemetry - - netcoreapp3.1 - $(TargetFrameworks);net452 - enable + net7.0;net6.0 + $(TargetFrameworks);$(NetFrameworkMinimumSupportedVersion) @@ -23,11 +20,23 @@ - - + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + - + @@ -35,7 +44,6 @@ - diff --git a/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestAWSEBSResourceDetector.cs b/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestAWSEBSResourceDetector.cs index 1b3df6c3e8..ba5b00e4ca 100644 --- a/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestAWSEBSResourceDetector.cs +++ b/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestAWSEBSResourceDetector.cs @@ -27,11 +27,7 @@ public class TestAWSEBSResourceDetector [Fact] public void TestDetect() { - var ebsResourceDetector = new AWSEBSResourceDetector(); - - var resourceAttributes = ebsResourceDetector.Detect(); - - Assert.Null(resourceAttributes); // will be null as it's not in ebs environment + Assert.Empty(new AWSEBSResourceDetector().Detect().Attributes); // will be null as it's not in ebs environment } [Fact] diff --git a/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestAWSEC2ResourceDetector.cs b/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestAWSEC2ResourceDetector.cs index 8fff5c438c..8507b7f780 100644 --- a/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestAWSEC2ResourceDetector.cs +++ b/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestAWSEC2ResourceDetector.cs @@ -25,11 +25,7 @@ public class TestAWSEC2ResourceDetector [Fact] public void TestDetect() { - var ec2ResourceDetector = new AWSEC2ResourceDetector(); - - var resourceAttributes = ec2ResourceDetector.Detect(); - - Assert.Null(resourceAttributes); // will be null as it's not in ec2 environment + Assert.Empty(new AWSEC2ResourceDetector().Detect().Attributes); // will be null as it's not in ec2 environment } [Fact] diff --git a/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestAWSECSResourceDetector.cs b/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestAWSECSResourceDetector.cs index 73223bb2a7..313d9be906 100644 --- a/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestAWSECSResourceDetector.cs +++ b/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestAWSECSResourceDetector.cs @@ -15,68 +15,171 @@ // using System; +using System.IO; using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Hosting.Server.Features; +using Microsoft.AspNetCore.Http; + using OpenTelemetry.Contrib.Extensions.AWSXRay.Resources; using Xunit; namespace OpenTelemetry.Contrib.Extensions.AWSXRay.Tests.Resources; -public class TestAWSECSResourceDetector +public class TestAWSECSResourceDetector : IDisposable { private const string AWSECSMetadataFilePath = "Resources/SampleMetadataFiles/testcgroup"; private const string AWSECSMetadataURLKey = "ECS_CONTAINER_METADATA_URI"; private const string AWSECSMetadataURLV4Key = "ECS_CONTAINER_METADATA_URI_V4"; - [Fact] - public void TestDetect() + public TestAWSECSResourceDetector() { - var ecsResourceDetector = new AWSECSResourceDetector(); - - var resourceAttributes = ecsResourceDetector?.Detect(); + this.ResetEnvironment(); + } - Assert.Null(resourceAttributes); // will be null as it's not in ecs environment + public void Dispose() + { + this.ResetEnvironment(); } [Fact] - public void TestExtractResourceAttributes() + public void TestNotOnEcs() { - var ecsResourceDetector = new AWSECSResourceDetector(); - var containerId = "Test container id"; - - var resourceAttributes = ecsResourceDetector.ExtractResourceAttributes(containerId).ToDictionary(x => x.Key, x => x.Value); - - Assert.Equal("aws", resourceAttributes[AWSSemanticConventions.AttributeCloudProvider]); - Assert.Equal("aws_ecs", resourceAttributes[AWSSemanticConventions.AttributeCloudPlatform]); - Assert.Equal("Test container id", resourceAttributes[AWSSemanticConventions.AttributeContainerID]); + Assert.Empty(new AWSECSResourceDetector().Detect().Attributes); } [Fact] public void TestGetECSContainerId() { - var ecsResourceDetector = new AWSECSResourceDetector(); - var ecsContainerId = ecsResourceDetector.GetECSContainerId(AWSECSMetadataFilePath); - - Assert.Equal("a4d00c9dd675d67f866c786181419e1b44832d4696780152e61afd44a3e02856", ecsContainerId); + Assert.Equal("a4d00c9dd675d67f866c786181419e1b44832d4696780152e61afd44a3e02856", new AWSECSResourceDetector().GetECSContainerId(AWSECSMetadataFilePath)); } [Fact] - public void TestIsECSProcess() + public void TestEcsMetadataV3() { Environment.SetEnvironmentVariable(AWSECSMetadataURLKey, "TestECSURIKey"); - Environment.SetEnvironmentVariable(AWSECSMetadataURLV4Key, "TestECSURIV4Key"); - var ecsResourceDetector = new AWSECSResourceDetector(); - var isEcsProcess = ecsResourceDetector.IsECSProcess(); + var resourceAttributes = new AWSECSResourceDetector().Detect().Attributes.ToDictionary(x => x.Key, x => x.Value); - Assert.True(isEcsProcess); + Assert.Equal(resourceAttributes[AWSSemanticConventions.AttributeCloudProvider], "aws"); + Assert.Equal(resourceAttributes[AWSSemanticConventions.AttributeCloudPlatform], "aws_ecs"); } [Fact] - public void TestIsNotECSProcess() + public async void TestEcsMetadataV4Ec2() { - var ecsResourceDetector = new AWSECSResourceDetector(); - var isEcsProcess = ecsResourceDetector.IsECSProcess(); + var source = new CancellationTokenSource(); + var token = source.Token; + + await using (var metadataEndpoint = new MockEcsMetadataEndpoint("ecs_metadata/metadatav4-response-container-ec2.json", "ecs_metadata/metadatav4-response-task-ec2.json")) + { + Environment.SetEnvironmentVariable(AWSECSMetadataURLV4Key, metadataEndpoint.Address.ToString()); + var resourceAttributes = new AWSECSResourceDetector().Detect().Attributes.ToDictionary(x => x.Key, x => x.Value); + + Assert.Equal(resourceAttributes[AWSSemanticConventions.AttributeCloudProvider], "aws"); + Assert.Equal(resourceAttributes[AWSSemanticConventions.AttributeCloudPlatform], "aws_ecs"); + Assert.Equal(resourceAttributes[AWSSemanticConventions.AttributeEcsContainerArn], "arn:aws:ecs:us-west-2:111122223333:container/0206b271-b33f-47ab-86c6-a0ba208a70a9"); + Assert.Equal(resourceAttributes[AWSSemanticConventions.AttributeEcsLaunchtype], "ec2"); + Assert.Equal(resourceAttributes[AWSSemanticConventions.AttributeEcsTaskArn], "arn:aws:ecs:us-west-2:111122223333:task/default/158d1c8083dd49d6b527399fd6414f5c"); + Assert.Equal(resourceAttributes[AWSSemanticConventions.AttributeEcsTaskFamily], "curltest"); + Assert.Equal(resourceAttributes[AWSSemanticConventions.AttributeEcsTaskRevision], "26"); + Assert.NotStrictEqual(resourceAttributes[AWSSemanticConventions.AttributeLogGroupNames], new string[] { "/ecs/metadata" }); + Assert.NotStrictEqual(resourceAttributes[AWSSemanticConventions.AttributeLogGroupArns], new string[] { "arn:aws:logs:us-west-2:111122223333:log-group:/ecs/metadata" }); + Assert.NotStrictEqual(resourceAttributes[AWSSemanticConventions.AttributeLogStreamNames], new string[] { "ecs/curl/8f03e41243824aea923aca126495f665" }); + Assert.NotStrictEqual(resourceAttributes[AWSSemanticConventions.AttributeLogStreamArns], new string[] { "arn:aws:logs:us-west-2:111122223333:log-group:/ecs/metadata:log-stream:ecs/curl/8f03e41243824aea923aca126495f665" }); + } + } + + [Fact] + public async void TestEcsMetadataV4Fargate() + { + var source = new CancellationTokenSource(); + var token = source.Token; + + await using (var metadataEndpoint = new MockEcsMetadataEndpoint("ecs_metadata/metadatav4-response-container-fargate.json", "ecs_metadata/metadatav4-response-task-fargate.json")) + { + Environment.SetEnvironmentVariable(AWSECSMetadataURLV4Key, metadataEndpoint.Address.ToString()); + + var resourceAttributes = new AWSECSResourceDetector().Detect().Attributes.ToDictionary(x => x.Key, x => x.Value); + + Assert.Equal(resourceAttributes[AWSSemanticConventions.AttributeCloudProvider], "aws"); + Assert.Equal(resourceAttributes[AWSSemanticConventions.AttributeCloudPlatform], "aws_ecs"); + Assert.Equal(resourceAttributes[AWSSemanticConventions.AttributeEcsContainerArn], "arn:aws:ecs:us-west-2:111122223333:container/05966557-f16c-49cb-9352-24b3a0dcd0e1"); + Assert.Equal(resourceAttributes[AWSSemanticConventions.AttributeEcsLaunchtype], "fargate"); + Assert.Equal(resourceAttributes[AWSSemanticConventions.AttributeEcsTaskArn], "arn:aws:ecs:us-west-2:111122223333:task/default/e9028f8d5d8e4f258373e7b93ce9a3c3"); + Assert.Equal(resourceAttributes[AWSSemanticConventions.AttributeEcsTaskFamily], "curltest"); + Assert.Equal(resourceAttributes[AWSSemanticConventions.AttributeEcsTaskRevision], "3"); + Assert.NotStrictEqual(resourceAttributes[AWSSemanticConventions.AttributeLogGroupNames], new string[] { "/ecs/containerlogs" }); + Assert.NotStrictEqual(resourceAttributes[AWSSemanticConventions.AttributeLogGroupArns], new string[] { "arn:aws:logs:us-west-2:111122223333:log-group:/ecs/containerlogs" }); + Assert.NotStrictEqual(resourceAttributes[AWSSemanticConventions.AttributeLogStreamNames], new string[] { "ecs/curl/cd189a933e5849daa93386466019ab50" }); + Assert.NotStrictEqual(resourceAttributes[AWSSemanticConventions.AttributeLogStreamArns], new string[] { "arn:aws:logs:us-west-2:111122223333:log-group:/ecs/containerlogs:log-stream:ecs/curl/cd189a933e5849daa93386466019ab50" }); + } + } - Assert.False(isEcsProcess); + internal void ResetEnvironment() + { + Environment.SetEnvironmentVariable(AWSECSMetadataURLKey, null); + Environment.SetEnvironmentVariable(AWSECSMetadataURLV4Key, null); + } + + internal class MockEcsMetadataEndpoint : IAsyncDisposable + { + public readonly Uri Address; + private readonly string containerJsonPath; + private readonly string taskJsonPath; + private readonly IWebHost server; + + public MockEcsMetadataEndpoint(string containerJsonPath, string taskJsonPath) + { + this.containerJsonPath = containerJsonPath; + this.taskJsonPath = taskJsonPath; + + this.server = new WebHostBuilder() + .UseKestrel() + .UseUrls("http://127.0.0.1:0") // Use random localhost port + .Configure(app => + { + app.Run(async context => + { + if (context.Request.Method == HttpMethods.Get && context.Request.Path == "/") + { + var content = await File.ReadAllTextAsync($"{Environment.CurrentDirectory}/Resources/{containerJsonPath}"); + var data = Encoding.UTF8.GetBytes(content); + context.Response.ContentType = "application/json"; + await context.Response.Body.WriteAsync(data, 0, data.Length); + } + else if (context.Request.Method == HttpMethods.Get && context.Request.Path == "/task") + { + var content = await File.ReadAllTextAsync($"{Environment.CurrentDirectory}/Resources/{taskJsonPath}"); + var data = Encoding.UTF8.GetBytes(content); + context.Response.ContentType = "application/json"; + await context.Response.Body.WriteAsync(data, 0, data.Length); + } + else + { + context.Response.StatusCode = StatusCodes.Status404NotFound; + await context.Response.WriteAsync("Not found"); + } + }); + }).Build(); + this.server.Start(); + + this.Address = new Uri(this.server.ServerFeatures.Get().Addresses.First()); + } + + public async ValueTask DisposeAsync() + { + await this.DisposeAsyncCore(); + } + + protected virtual async ValueTask DisposeAsyncCore() + { + await this.server.StopAsync(); + } } } diff --git a/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestAWSEKSResourceDetector.cs b/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestAWSEKSResourceDetector.cs index d7689835be..9d761e2516 100644 --- a/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestAWSEKSResourceDetector.cs +++ b/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestAWSEKSResourceDetector.cs @@ -28,11 +28,7 @@ public class TestAWSEKSResourceDetector [Fact] public void TestDetect() { - var eksResourceDetector = new AWSEKSResourceDetector(); - - var resourceAttributes = eksResourceDetector?.Detect(); - - Assert.Null(resourceAttributes); // will be null as it's not in eks environment + Assert.Empty(new AWSEKSResourceDetector().Detect().Attributes); // will be null as it's not in eks environment } [Fact] diff --git a/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestAWSLambdaResourceDetector.cs b/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestAWSLambdaResourceDetector.cs index 78a8c3fdd6..0b6a62a1cc 100644 --- a/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestAWSLambdaResourceDetector.cs +++ b/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestAWSLambdaResourceDetector.cs @@ -30,8 +30,7 @@ public void TestDetect() Environment.SetEnvironmentVariable("AWS_LAMBDA_FUNCTION_NAME", "testfunction"); Environment.SetEnvironmentVariable("AWS_LAMBDA_FUNCTION_VERSION", "latest"); - var lambdaResourceDetector = new AWSLambdaResourceDetector(); - var resourceAttributes = lambdaResourceDetector.Detect().ToDictionary(x => x.Key, x => x.Value); + var resourceAttributes = new AWSLambdaResourceDetector().Detect().Attributes.ToDictionary(x => x.Key, x => x.Value); Assert.Equal("aws", resourceAttributes[AWSSemanticConventions.AttributeCloudProvider]); Assert.Equal("aws_lambda", resourceAttributes[AWSSemanticConventions.AttributeCloudPlatform]); diff --git a/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestResourceBuilderExtensions.cs b/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestResourceBuilderExtensions.cs deleted file mode 100644 index 7ce8115975..0000000000 --- a/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestResourceBuilderExtensions.cs +++ /dev/null @@ -1,54 +0,0 @@ -// -// Copyright The OpenTelemetry Authors -// -// 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. -// - -using System; -using System.Linq; -using OpenTelemetry.Contrib.Extensions.AWSXRay.Resources; -using OpenTelemetry.Resources; -using OpenTelemetry.Trace; -using Xunit; - -namespace OpenTelemetry.Contrib.Extensions.AWSXRay.Tests.Resources; - -public class TestResourceBuilderExtensions -{ - [Fact] - public void TestAddDetector() - { - Environment.SetEnvironmentVariable("AWS_REGION", "us-east-1"); - Environment.SetEnvironmentVariable("AWS_LAMBDA_FUNCTION_NAME", "testfunction"); - Environment.SetEnvironmentVariable("AWS_LAMBDA_FUNCTION_VERSION", "latest"); - - using var tracerProvider = Sdk.CreateTracerProviderBuilder() - .SetResourceBuilder(ResourceBuilder - .CreateDefault() - .AddDetector(new AWSLambdaResourceDetector())) // use lambda resource detector here as it doesn't require sending identical http request to aws endpoint - .Build(); - - var resource = tracerProvider.GetResource(); - var resourceAttributes = resource.Attributes.ToDictionary(x => x.Key, x => x.Value); - - Assert.Equal("aws", resourceAttributes[AWSSemanticConventions.AttributeCloudProvider]); - Assert.Equal("aws_lambda", resourceAttributes[AWSSemanticConventions.AttributeCloudPlatform]); - Assert.Equal("us-east-1", resourceAttributes[AWSSemanticConventions.AttributeCloudRegion]); - Assert.Equal("testfunction", resourceAttributes[AWSSemanticConventions.AttributeFaasName]); - Assert.Equal("latest", resourceAttributes[AWSSemanticConventions.AttributeFaasVersion]); - - Environment.SetEnvironmentVariable("AWS_REGION", null); - Environment.SetEnvironmentVariable("AWS_LAMBDA_FUNCTION_NAME", null); - Environment.SetEnvironmentVariable("AWS_LAMBDA_FUNCTION_VERSION", null); - } -} diff --git a/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/ecs_metadata/metadatav4-response-container-ec2.json b/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/ecs_metadata/metadatav4-response-container-ec2.json new file mode 100644 index 0000000000..b43c2b0d7d --- /dev/null +++ b/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/ecs_metadata/metadatav4-response-container-ec2.json @@ -0,0 +1,44 @@ +{ + "DockerId": "ea32192c8553fbff06c9340478a2ff089b2bb5646fb718b4ee206641c9086d66", + "Name": "curl", + "DockerName": "ecs-curltest-24-curl-cca48e8dcadd97805600", + "Image": "111122223333.dkr.ecr.us-west-2.amazonaws.com/curltest:latest", + "ImageID": "sha256:d691691e9652791a60114e67b365688d20d19940dde7c4736ea30e660d8d3553", + "Labels": { + "com.amazonaws.ecs.cluster": "default", + "com.amazonaws.ecs.container-name": "curl", + "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-west-2:111122223333:task/default/8f03e41243824aea923aca126495f665", + "com.amazonaws.ecs.task-definition-family": "curltest", + "com.amazonaws.ecs.task-definition-version": "24" + }, + "DesiredStatus": "RUNNING", + "KnownStatus": "RUNNING", + "Limits": { + "CPU": 10, + "Memory": 128 + }, + "CreatedAt": "2020-10-02T00:15:07.620912337Z", + "StartedAt": "2020-10-02T00:15:08.062559351Z", + "Type": "NORMAL", + "LogDriver": "awslogs", + "LogOptions": { + "awslogs-create-group": "true", + "awslogs-group": "/ecs/metadata", + "awslogs-region": "us-west-2", + "awslogs-stream": "ecs/curl/8f03e41243824aea923aca126495f665" + }, + "ContainerARN": "arn:aws:ecs:us-west-2:111122223333:container/0206b271-b33f-47ab-86c6-a0ba208a70a9", + "Networks": [ + { + "NetworkMode": "awsvpc", + "IPv4Addresses": [ + "10.0.2.100" + ], + "AttachmentIndex": 0, + "MACAddress": "0e:9e:32:c7:48:85", + "IPv4SubnetCIDRBlock": "10.0.2.0/24", + "PrivateDNSName": "ip-10-0-2-100.us-west-2.compute.internal", + "SubnetGatewayIpv4Address": "10.0.2.1/24" + } + ] +} diff --git a/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/ecs_metadata/metadatav4-response-container-fargate.json b/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/ecs_metadata/metadatav4-response-container-fargate.json new file mode 100644 index 0000000000..ccbe70bc44 --- /dev/null +++ b/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/ecs_metadata/metadatav4-response-container-fargate.json @@ -0,0 +1,50 @@ +{ + "DockerId": "cd189a933e5849daa93386466019ab50-2495160603", + "Name": "curl", + "DockerName": "curl", + "Image": "111122223333.dkr.ecr.us-west-2.amazonaws.com/curltest:latest", + "ImageID": "sha256:25f3695bedfb454a50f12d127839a68ad3caf91e451c1da073db34c542c4d2cb", + "Labels": { + "com.amazonaws.ecs.cluster": "arn:aws:ecs:us-west-2:111122223333:cluster/default", + "com.amazonaws.ecs.container-name": "curl", + "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-west-2:111122223333:task/default/cd189a933e5849daa93386466019ab50", + "com.amazonaws.ecs.task-definition-family": "curltest", + "com.amazonaws.ecs.task-definition-version": "2" + }, + "DesiredStatus": "RUNNING", + "KnownStatus": "RUNNING", + "Limits": { + "CPU": 10, + "Memory": 128 + }, + "CreatedAt": "2020-10-08T20:09:11.44527186Z", + "StartedAt": "2020-10-08T20:09:11.44527186Z", + "Type": "NORMAL", + "Networks": [ + { + "NetworkMode": "awsvpc", + "IPv4Addresses": [ + "192.0.2.3" + ], + "AttachmentIndex": 0, + "MACAddress": "0a:de:f6:10:51:e5", + "IPv4SubnetCIDRBlock": "192.0.2.0/24", + "DomainNameServers": [ + "192.0.2.2" + ], + "DomainNameSearchList": [ + "us-west-2.compute.internal" + ], + "PrivateDNSName": "ip-10-0-0-222.us-west-2.compute.internal", + "SubnetGatewayIpv4Address": "192.0.2.0/24" + } + ], + "ContainerARN": "arn:aws:ecs:us-west-2:111122223333:container/05966557-f16c-49cb-9352-24b3a0dcd0e1", + "LogOptions": { + "awslogs-create-group": "true", + "awslogs-group": "/ecs/containerlogs", + "awslogs-region": "us-west-2", + "awslogs-stream": "ecs/curl/cd189a933e5849daa93386466019ab50" + }, + "LogDriver": "awslogs" +} \ No newline at end of file diff --git a/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/ecs_metadata/metadatav4-response-task-ec2.json b/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/ecs_metadata/metadatav4-response-task-ec2.json new file mode 100644 index 0000000000..101efe0214 --- /dev/null +++ b/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/ecs_metadata/metadatav4-response-task-ec2.json @@ -0,0 +1,94 @@ +{ + "Cluster": "default", + "TaskARN": "arn:aws:ecs:us-west-2:111122223333:task/default/158d1c8083dd49d6b527399fd6414f5c", + "Family": "curltest", + "Revision": "26", + "DesiredStatus": "RUNNING", + "KnownStatus": "RUNNING", + "PullStartedAt": "2020-10-02T00:43:06.202617438Z", + "PullStoppedAt": "2020-10-02T00:43:06.31288465Z", + "AvailabilityZone": "us-west-2d", + "LaunchType": "EC2", + "Containers": [ + { + "DockerId": "598cba581fe3f939459eaba1e071d5c93bb2c49b7d1ba7db6bb19deeb70d8e38", + "Name": "~internal~ecs~pause", + "DockerName": "ecs-curltest-26-internalecspause-e292d586b6f9dade4a00", + "Image": "amazon/amazon-ecs-pause:0.1.0", + "ImageID": "", + "Labels": { + "com.amazonaws.ecs.cluster": "default", + "com.amazonaws.ecs.container-name": "~internal~ecs~pause", + "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-west-2:111122223333:task/default/158d1c8083dd49d6b527399fd6414f5c", + "com.amazonaws.ecs.task-definition-family": "curltest", + "com.amazonaws.ecs.task-definition-version": "26" + }, + "DesiredStatus": "RESOURCES_PROVISIONED", + "KnownStatus": "RESOURCES_PROVISIONED", + "Limits": { + "CPU": 0, + "Memory": 0 + }, + "CreatedAt": "2020-10-02T00:43:05.602352471Z", + "StartedAt": "2020-10-02T00:43:06.076707576Z", + "Type": "CNI_PAUSE", + "Networks": [ + { + "NetworkMode": "awsvpc", + "IPv4Addresses": [ + "10.0.2.61" + ], + "AttachmentIndex": 0, + "MACAddress": "0e:10:e2:01:bd:91", + "IPv4SubnetCIDRBlock": "10.0.2.0/24", + "PrivateDNSName": "ip-10-0-2-61.us-west-2.compute.internal", + "SubnetGatewayIpv4Address": "10.0.2.1/24" + } + ] + }, + { + "DockerId": "ee08638adaaf009d78c248913f629e38299471d45fe7dc944d1039077e3424ca", + "Name": "curl", + "DockerName": "ecs-curltest-26-curl-a0e7dba5aca6d8cb2e00", + "Image": "111122223333.dkr.ecr.us-west-2.amazonaws.com/curltest:latest", + "ImageID": "sha256:d691691e9652791a60114e67b365688d20d19940dde7c4736ea30e660d8d3553", + "Labels": { + "com.amazonaws.ecs.cluster": "default", + "com.amazonaws.ecs.container-name": "curl", + "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-west-2:111122223333:task/default/158d1c8083dd49d6b527399fd6414f5c", + "com.amazonaws.ecs.task-definition-family": "curltest", + "com.amazonaws.ecs.task-definition-version": "26" + }, + "DesiredStatus": "RUNNING", + "KnownStatus": "RUNNING", + "Limits": { + "CPU": 10, + "Memory": 128 + }, + "CreatedAt": "2020-10-02T00:43:06.326590752Z", + "StartedAt": "2020-10-02T00:43:06.767535449Z", + "Type": "NORMAL", + "LogDriver": "awslogs", + "LogOptions": { + "awslogs-create-group": "true", + "awslogs-group": "/ecs/metadata", + "awslogs-region": "us-west-2", + "awslogs-stream": "ecs/curl/158d1c8083dd49d6b527399fd6414f5c" + }, + "ContainerARN": "arn:aws:ecs:us-west-2:111122223333:container/abb51bdd-11b4-467f-8f6c-adcfe1fe059d", + "Networks": [ + { + "NetworkMode": "awsvpc", + "IPv4Addresses": [ + "10.0.2.61" + ], + "AttachmentIndex": 0, + "MACAddress": "0e:10:e2:01:bd:91", + "IPv4SubnetCIDRBlock": "10.0.2.0/24", + "PrivateDNSName": "ip-10-0-2-61.us-west-2.compute.internal", + "SubnetGatewayIpv4Address": "10.0.2.1/24" + } + ] + } + ] +} diff --git a/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/ecs_metadata/metadatav4-response-task-fargate.json b/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/ecs_metadata/metadatav4-response-task-fargate.json new file mode 100644 index 0000000000..7979db708d --- /dev/null +++ b/test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/ecs_metadata/metadatav4-response-task-fargate.json @@ -0,0 +1,77 @@ +{ + "Cluster": "arn:aws:ecs:us-west-2:111122223333:cluster/default", + "TaskARN": "arn:aws:ecs:us-west-2:111122223333:task/default/e9028f8d5d8e4f258373e7b93ce9a3c3", + "Family": "curltest", + "Revision": "3", + "DesiredStatus": "RUNNING", + "KnownStatus": "RUNNING", + "Limits": { + "CPU": 0.25, + "Memory": 512 + }, + "PullStartedAt": "2020-10-08T20:47:16.053330955Z", + "PullStoppedAt": "2020-10-08T20:47:19.592684631Z", + "AvailabilityZone": "us-west-2a", + "Containers": [ + { + "DockerId": "e9028f8d5d8e4f258373e7b93ce9a3c3-2495160603", + "Name": "curl", + "DockerName": "curl", + "Image": "111122223333.dkr.ecr.us-west-2.amazonaws.com/curltest:latest", + "ImageID": "sha256:25f3695bedfb454a50f12d127839a68ad3caf91e451c1da073db34c542c4d2cb", + "Labels": { + "com.amazonaws.ecs.cluster": "arn:aws:ecs:us-west-2:111122223333:cluster/default", + "com.amazonaws.ecs.container-name": "curl", + "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-west-2:111122223333:task/default/e9028f8d5d8e4f258373e7b93ce9a3c3", + "com.amazonaws.ecs.task-definition-family": "curltest", + "com.amazonaws.ecs.task-definition-version": "3" + }, + "DesiredStatus": "RUNNING", + "KnownStatus": "RUNNING", + "Limits": { + "CPU": 10, + "Memory": 128 + }, + "CreatedAt": "2020-10-08T20:47:20.567813946Z", + "StartedAt": "2020-10-08T20:47:20.567813946Z", + "Type": "NORMAL", + "Networks": [ + { + "NetworkMode": "awsvpc", + "IPv4Addresses": [ + "192.0.2.3" + ], + "IPv6Addresses": [ + "2001:dB8:10b:1a00:32bf:a372:d80f:e958" + ], + "AttachmentIndex": 0, + "MACAddress": "02:b7:20:19:72:39", + "IPv4SubnetCIDRBlock": "192.0.2.0/24", + "IPv6SubnetCIDRBlock": "2600:1f13:10b:1a00::/64", + "DomainNameServers": [ + "192.0.2.2" + ], + "DomainNameSearchList": [ + "us-west-2.compute.internal" + ], + "PrivateDNSName": "ip-172-31-30-173.us-west-2.compute.internal", + "SubnetGatewayIpv4Address": "192.0.2.0/24" + } + ], + "ClockDrift": { + "ClockErrorBound": 0.5458234999999999, + "ReferenceTimestamp": "2021-09-07T16:57:44Z", + "ClockSynchronizationStatus": "SYNCHRONIZED" + }, + "ContainerARN": "arn:aws:ecs:us-west-2:111122223333:container/1bdcca8b-f905-4ee6-885c-4064cb70f6e6", + "LogOptions": { + "awslogs-create-group": "true", + "awslogs-group": "/ecs/containerlogs", + "awslogs-region": "us-west-2", + "awslogs-stream": "ecs/curl/e9028f8d5d8e4f258373e7b93ce9a3c3" + }, + "LogDriver": "awslogs" + } + ], + "LaunchType": "FARGATE" +} \ No newline at end of file