diff --git a/src/OpenTelemetry.Instrumentation.AWS/.publicApi/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Instrumentation.AWS/.publicApi/PublicAPI.Unshipped.txt index d8633d91a7..d9f3466a01 100644 --- a/src/OpenTelemetry.Instrumentation.AWS/.publicApi/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Instrumentation.AWS/.publicApi/PublicAPI.Unshipped.txt @@ -1,6 +1,13 @@ #nullable enable +OpenTelemetry.Instrumentation.AWS.SemanticConventionVersion +OpenTelemetry.Instrumentation.AWS.SemanticConventionVersion.Legacy = -1 -> OpenTelemetry.Instrumentation.AWS.SemanticConventionVersion +OpenTelemetry.Instrumentation.AWS.SemanticConventionVersion.Latest = 0 -> OpenTelemetry.Instrumentation.AWS.SemanticConventionVersion +OpenTelemetry.Instrumentation.AWS.SemanticConventionVersion.V1_29_0 = 2 -> OpenTelemetry.Instrumentation.AWS.SemanticConventionVersion +OpenTelemetry.Instrumentation.AWS.SemanticConventionVersion.V1_28_0 = 1 -> OpenTelemetry.Instrumentation.AWS.SemanticConventionVersion OpenTelemetry.Instrumentation.AWS.AWSClientInstrumentationOptions OpenTelemetry.Instrumentation.AWS.AWSClientInstrumentationOptions.AWSClientInstrumentationOptions() -> void +OpenTelemetry.Instrumentation.AWS.AWSClientInstrumentationOptions.SemanticConventionVersion.get -> OpenTelemetry.Instrumentation.AWS.SemanticConventionVersion +OpenTelemetry.Instrumentation.AWS.AWSClientInstrumentationOptions.SemanticConventionVersion.set -> void OpenTelemetry.Instrumentation.AWS.AWSClientInstrumentationOptions.SuppressDownstreamInstrumentation.get -> bool OpenTelemetry.Instrumentation.AWS.AWSClientInstrumentationOptions.SuppressDownstreamInstrumentation.set -> void OpenTelemetry.Trace.TracerProviderBuilderExtensions diff --git a/src/OpenTelemetry.Instrumentation.AWS/AWSClientInstrumentationOptions.cs b/src/OpenTelemetry.Instrumentation.AWS/AWSClientInstrumentationOptions.cs index f476d1915d..193c65ebcf 100644 --- a/src/OpenTelemetry.Instrumentation.AWS/AWSClientInstrumentationOptions.cs +++ b/src/OpenTelemetry.Instrumentation.AWS/AWSClientInstrumentationOptions.cs @@ -1,6 +1,8 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +using OpenTelemetry.AWS; + namespace OpenTelemetry.Instrumentation.AWS; /// @@ -12,4 +14,7 @@ public class AWSClientInstrumentationOptions /// Gets or sets a value indicating whether downstream instrumentation is suppressed. /// public bool SuppressDownstreamInstrumentation { get; set; } + + /// + public SemanticConventionVersion SemanticConventionVersion { get; set; } = AWSSemanticConventions.DefaultSemanticConventionVersion; } diff --git a/src/OpenTelemetry.Instrumentation.AWS/CHANGELOG.md b/src/OpenTelemetry.Instrumentation.AWS/CHANGELOG.md index b4affacd6c..25d1d4cf4b 100644 --- a/src/OpenTelemetry.Instrumentation.AWS/CHANGELOG.md +++ b/src/OpenTelemetry.Instrumentation.AWS/CHANGELOG.md @@ -2,6 +2,14 @@ ## Unreleased +* Introduce `AWSClientInstrumentationOptions.SemanticConventionVersion` which + provides a mechanism for developers to opt-in to newer versions of the + of the OpenTelemetry Semantic Conventions. Currently, you need to opt-in + to these new conventions. In the upcoming stable release of this library, + the new conventions will be enabled by default, and the conventions this library + currently emit will no longer be supported. + ([#2367](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/2367)) + ## 1.10.0-beta.2 Released 2024-Dec-12 diff --git a/src/OpenTelemetry.Instrumentation.AWS/Implementation/AWSSemanticConventions.cs b/src/OpenTelemetry.Instrumentation.AWS/Implementation/AWSSemanticConventions.cs deleted file mode 100644 index 61d72da34e..0000000000 --- a/src/OpenTelemetry.Instrumentation.AWS/Implementation/AWSSemanticConventions.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -namespace OpenTelemetry.Instrumentation.AWS.Implementation; - -internal static class AWSSemanticConventions -{ - public const string AttributeAWSServiceName = "aws.service"; - public const string AttributeAWSOperationName = "aws.operation"; - public const string AttributeAWSRegion = "aws.region"; - public const string AttributeAWSRequestId = "aws.requestId"; - - public const string AttributeAWSDynamoTableName = "aws.table_name"; - public const string AttributeAWSSQSQueueUrl = "aws.queue_url"; - - // AWS Bedrock service attributes not yet defined in semantic conventions - public const string AttributeAWSBedrockAgentId = "aws.bedrock.agent.id"; - public const string AttributeAWSBedrockDataSourceId = "aws.bedrock.data_source.id"; - public const string AttributeAWSBedrockGuardrailId = "aws.bedrock.guardrail.id"; - public const string AttributeAWSBedrockKnowledgeBaseId = "aws.bedrock.knowledge_base.id"; - public const string AttributeAWSBedrock = "aws_bedrock"; - - // should be global convention for Gen AI attributes - public const string AttributeGenAiModelId = "gen_ai.request.model"; - public const string AttributeGenAiSystem = "gen_ai.system"; - - public const string AttributeHttpStatusCode = "http.status_code"; - public const string AttributeHttpResponseContentLength = "http.response_content_length"; - - public const string AttributeValueDynamoDb = "dynamodb"; - - public const string AttributeValueRPCSystem = "rpc.system"; - public const string AttributeValueRPCService = "rpc.service"; - public const string AttributeValueRPCMethod = "rpc.method"; -} diff --git a/src/OpenTelemetry.Instrumentation.AWS/Implementation/AWSServiceHelper.cs b/src/OpenTelemetry.Instrumentation.AWS/Implementation/AWSServiceHelper.cs index 7e87865b3c..67ea5d94df 100644 --- a/src/OpenTelemetry.Instrumentation.AWS/Implementation/AWSServiceHelper.cs +++ b/src/OpenTelemetry.Instrumentation.AWS/Implementation/AWSServiceHelper.cs @@ -2,12 +2,28 @@ // SPDX-License-Identifier: Apache-2.0 using Amazon.Runtime; +using OpenTelemetry.AWS; namespace OpenTelemetry.Instrumentation.AWS.Implementation; internal class AWSServiceHelper { - internal static IReadOnlyDictionary> ServiceRequestParameterMap = new Dictionary>() + public AWSServiceHelper(AWSSemanticConventions semanticConventions) + { + this.ParameterAttributeMap = + semanticConventions + .ParameterMappingBuilder + .AddAttributeAWSDynamoTableName("TableName") + .AddAttributeAWSSQSQueueUrl("QueueUrl") + .AddAttributeGenAiModelId("ModelId") + .AddAttributeAWSBedrockAgentId("AgentId") + .AddAttributeAWSBedrockDataSourceId("DataSourceId") + .AddAttributeAWSBedrockGuardrailId("GuardrailId") + .AddAttributeAWSBedrockKnowledgeBaseId("KnowledgeBaseId") + .Build(); + } + + internal static IReadOnlyDictionary> ServiceRequestParameterMap { get; } = new Dictionary>() { { AWSServiceType.DynamoDbService, ["TableName"] }, { AWSServiceType.SQSService, ["QueueUrl"] }, @@ -16,25 +32,14 @@ internal class AWSServiceHelper { AWSServiceType.BedrockRuntimeService, ["ModelId"] }, }; - internal static IReadOnlyDictionary> ServiceResponseParameterMap = new Dictionary>() + internal static IReadOnlyDictionary> ServiceResponseParameterMap { get; } = new Dictionary>() { { AWSServiceType.BedrockService, ["GuardrailId"] }, { AWSServiceType.BedrockAgentService, ["AgentId", "DataSourceId"] }, }; - internal static IReadOnlyDictionary ParameterAttributeMap = new Dictionary() - { - { "TableName", AWSSemanticConventions.AttributeAWSDynamoTableName }, - { "QueueUrl", AWSSemanticConventions.AttributeAWSSQSQueueUrl }, - { "ModelId", AWSSemanticConventions.AttributeGenAiModelId }, - { "AgentId", AWSSemanticConventions.AttributeAWSBedrockAgentId }, - { "DataSourceId", AWSSemanticConventions.AttributeAWSBedrockDataSourceId }, - { "GuardrailId", AWSSemanticConventions.AttributeAWSBedrockGuardrailId }, - { "KnowledgeBaseId", AWSSemanticConventions.AttributeAWSBedrockKnowledgeBaseId }, - }; - // for Bedrock Agent operations, we map each supported operation to one resource: Agent, DataSource, or KnowledgeBase - internal static List BedrockAgentAgentOps = + internal static List BedrockAgentAgentOps { get; } = [ "CreateAgentActionGroup", "CreateAgentAlias", @@ -56,7 +61,7 @@ internal class AWSServiceHelper "UpdateAgent" ]; - internal static List BedrockAgentKnowledgeBaseOps = + internal static List BedrockAgentKnowledgeBaseOps { get; } = [ "AssociateAgentKnowledgeBase", "CreateDataSource", @@ -68,13 +73,15 @@ internal class AWSServiceHelper "UpdateAgentKnowledgeBase" ]; - internal static List BedrockAgentDataSourceOps = + internal static List BedrockAgentDataSourceOps { get; } = [ "DeleteDataSource", "GetDataSource", "UpdateDataSource" ]; + internal IDictionary ParameterAttributeMap { get; } + internal static IReadOnlyDictionary OperationNameToResourceMap() { var operationClassMap = new Dictionary(); diff --git a/src/OpenTelemetry.Instrumentation.AWS/Implementation/AWSTracingPipelineCustomizer.cs b/src/OpenTelemetry.Instrumentation.AWS/Implementation/AWSTracingPipelineCustomizer.cs index d9c1f550a5..6239999bb9 100644 --- a/src/OpenTelemetry.Instrumentation.AWS/Implementation/AWSTracingPipelineCustomizer.cs +++ b/src/OpenTelemetry.Instrumentation.AWS/Implementation/AWSTracingPipelineCustomizer.cs @@ -12,6 +12,8 @@ namespace OpenTelemetry.Instrumentation.AWS.Implementation; /// internal class AWSTracingPipelineCustomizer : IRuntimePipelineCustomizer { + public const string UniqueName = "AWS Tracing Registration Customization"; + private readonly AWSClientInstrumentationOptions options; public AWSTracingPipelineCustomizer(AWSClientInstrumentationOptions options) @@ -19,7 +21,7 @@ public AWSTracingPipelineCustomizer(AWSClientInstrumentationOptions options) this.options = options; } - public string UniqueName => "AWS Tracing Registration Customization"; + string IRuntimePipelineCustomizer.UniqueName => UniqueName; public void Customize(Type serviceClientType, RuntimePipeline pipeline) { diff --git a/src/OpenTelemetry.Instrumentation.AWS/Implementation/AWSTracingPipelineHandler.cs b/src/OpenTelemetry.Instrumentation.AWS/Implementation/AWSTracingPipelineHandler.cs index 2a13fed2ba..ef28d3cc5e 100644 --- a/src/OpenTelemetry.Instrumentation.AWS/Implementation/AWSTracingPipelineHandler.cs +++ b/src/OpenTelemetry.Instrumentation.AWS/Implementation/AWSTracingPipelineHandler.cs @@ -5,8 +5,8 @@ using Amazon.Runtime; using Amazon.Runtime.Internal; using Amazon.Runtime.Telemetry; +using OpenTelemetry.AWS; using OpenTelemetry.Context.Propagation; -using OpenTelemetry.Trace; namespace OpenTelemetry.Instrumentation.AWS.Implementation; @@ -19,17 +19,21 @@ namespace OpenTelemetry.Instrumentation.AWS.Implementation; internal sealed class AWSTracingPipelineHandler : PipelineHandler { private readonly AWSClientInstrumentationOptions options; + private readonly AWSSemanticConventions awsSemanticConventions; + private readonly AWSServiceHelper awsServiceHelper; public AWSTracingPipelineHandler(AWSClientInstrumentationOptions options) { this.options = options; + this.awsSemanticConventions = new AWSSemanticConventions(options.SemanticConventionVersion); + this.awsServiceHelper = new AWSServiceHelper(this.awsSemanticConventions); } public override void InvokeSync(IExecutionContext executionContext) { var activity = this.ProcessBeginRequest(executionContext); base.InvokeSync(executionContext); - ProcessEndRequest(activity, executionContext); + this.ProcessEndRequest(activity, executionContext); } public override async Task InvokeAsync(IExecutionContext executionContext) @@ -37,7 +41,7 @@ public override async Task InvokeAsync(IExecutionContext executionContext) var activity = this.ProcessBeginRequest(executionContext); var ret = await base.InvokeAsync(executionContext).ConfigureAwait(false); - ProcessEndRequest(activity, executionContext); + this.ProcessEndRequest(activity, executionContext); return ret; } @@ -48,7 +52,7 @@ public override async Task InvokeAsync(IExecutionContext executionContext) "IL2075", Justification = "The reflected properties were already used by the AWS SDK's marshallers so the properties could not have been trimmed.")] #endif - private static void AddResponseSpecificInformation(Activity activity, IExecutionContext executionContext) + private void AddResponseSpecificInformation(Activity activity, IExecutionContext executionContext) { var service = executionContext.RequestContext.ServiceMetaData.ServiceId; var responseContext = executionContext.ResponseContext; @@ -67,14 +71,14 @@ private static void AddResponseSpecificInformation(Activity activity, IExecution var operationName = Utils.RemoveSuffix(response.GetType().Name, "Response"); if (AWSServiceHelper.OperationNameToResourceMap()[operationName] == parameter) { - AddBedrockAgentResponseAttribute(activity, response, parameter); + this.AddBedrockAgentResponseAttribute(activity, response, parameter); } } var property = response.GetType().GetProperty(parameter); if (property != null) { - if (AWSServiceHelper.ParameterAttributeMap.TryGetValue(parameter, out var attribute)) + if (this.awsServiceHelper.ParameterAttributeMap.TryGetValue(parameter, out var attribute)) { activity.SetTag(attribute, property.GetValue(response)); } @@ -95,7 +99,7 @@ private static void AddResponseSpecificInformation(Activity activity, IExecution "IL2075", Justification = "The reflected properties were already used by the AWS SDK's marshallers so the properties could not have been trimmed.")] #endif - private static void AddBedrockAgentResponseAttribute(Activity activity, AmazonWebServiceResponse response, string parameter) + private void AddBedrockAgentResponseAttribute(Activity activity, AmazonWebServiceResponse response, string parameter) { var responseObject = response.GetType().GetProperty(Utils.RemoveSuffix(parameter, "Id")); if (responseObject != null) @@ -106,7 +110,7 @@ private static void AddBedrockAgentResponseAttribute(Activity activity, AmazonWe var property = attributeObject.GetType().GetProperty(parameter); if (property != null) { - if (AWSServiceHelper.ParameterAttributeMap.TryGetValue(parameter, out var attribute)) + if (this.awsServiceHelper.ParameterAttributeMap.TryGetValue(parameter, out var attribute)) { activity.SetTag(attribute, property.GetValue(attributeObject)); } @@ -121,7 +125,7 @@ private static void AddBedrockAgentResponseAttribute(Activity activity, AmazonWe "IL2075", Justification = "The reflected properties were already used by the AWS SDK's marshallers so the properties could not have been trimmed.")] #endif - private static void AddRequestSpecificInformation(Activity activity, IRequestContext requestContext) + private void AddRequestSpecificInformation(Activity activity, IRequestContext requestContext) { var service = requestContext.ServiceMetaData.ServiceId; @@ -145,7 +149,7 @@ private static void AddRequestSpecificInformation(Activity activity, IRequestCon var property = request.GetType().GetProperty(parameter); if (property != null) { - if (AWSServiceHelper.ParameterAttributeMap.TryGetValue(parameter, out var attribute)) + if (this.awsServiceHelper.ParameterAttributeMap.TryGetValue(parameter, out var attribute)) { activity.SetTag(attribute, property.GetValue(request)); } @@ -161,7 +165,7 @@ private static void AddRequestSpecificInformation(Activity activity, IRequestCon if (AWSServiceType.IsDynamoDbService(service)) { - activity.SetTag(SemanticConventions.AttributeDbSystem, AWSSemanticConventions.AttributeValueDynamoDb); + this.awsSemanticConventions.TagBuilder.SetTagAttributeDbSystemToDynamoDb(activity); } else if (AWSServiceType.IsSqsService(service)) { @@ -175,18 +179,18 @@ private static void AddRequestSpecificInformation(Activity activity, IRequestCon } else if (AWSServiceType.IsBedrockRuntimeService(service)) { - activity.SetTag(AWSSemanticConventions.AttributeGenAiSystem, AWSSemanticConventions.AttributeAWSBedrock); + this.awsSemanticConventions.TagBuilder.SetTagAttributeGenAiSystemToBedrock(activity); } } - private static void ProcessEndRequest(Activity? activity, IExecutionContext executionContext) + private void ProcessEndRequest(Activity? activity, IExecutionContext executionContext) { if (activity == null || !activity.IsAllDataRequested) { return; } - AddResponseSpecificInformation(activity, executionContext); + this.AddResponseSpecificInformation(activity, executionContext); } private Activity? ProcessBeginRequest(IExecutionContext executionContext) @@ -205,7 +209,7 @@ private static void ProcessEndRequest(Activity? activity, IExecutionContext exec return null; } - AddRequestSpecificInformation(currentActivity, executionContext.RequestContext); + this.AddRequestSpecificInformation(currentActivity, executionContext.RequestContext); return currentActivity; } } diff --git a/src/OpenTelemetry.Instrumentation.AWS/OpenTelemetry.Instrumentation.AWS.csproj b/src/OpenTelemetry.Instrumentation.AWS/OpenTelemetry.Instrumentation.AWS.csproj index b4b422dd49..8f2906daad 100644 --- a/src/OpenTelemetry.Instrumentation.AWS/OpenTelemetry.Instrumentation.AWS.csproj +++ b/src/OpenTelemetry.Instrumentation.AWS/OpenTelemetry.Instrumentation.AWS.csproj @@ -6,6 +6,7 @@ $(TargetFrameworks);$(NetFrameworkMinimumSupportedVersion) AWS client instrumentation for OpenTelemetry .NET. Instrumentation.AWS- + INSTRUMENTATION_AWS;$(DefineConstants)