Skip to content

Commit c455a85

Browse files
ppittlealanwestKielek
authored
Upgrade Semantic Convention handling in AWS libraries. (#2367)
Co-authored-by: Alan West <[email protected]> Co-authored-by: Piotr Kiełkowicz <[email protected]>
1 parent 31cea68 commit c455a85

File tree

48 files changed

+2526
-583
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+2526
-583
lines changed

src/OpenTelemetry.Instrumentation.AWS/.publicApi/PublicAPI.Unshipped.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
#nullable enable
2+
OpenTelemetry.Instrumentation.AWS.SemanticConventionVersion
3+
OpenTelemetry.Instrumentation.AWS.SemanticConventionVersion.Legacy = -1 -> OpenTelemetry.Instrumentation.AWS.SemanticConventionVersion
4+
OpenTelemetry.Instrumentation.AWS.SemanticConventionVersion.Latest = 0 -> OpenTelemetry.Instrumentation.AWS.SemanticConventionVersion
5+
OpenTelemetry.Instrumentation.AWS.SemanticConventionVersion.V1_29_0 = 2 -> OpenTelemetry.Instrumentation.AWS.SemanticConventionVersion
6+
OpenTelemetry.Instrumentation.AWS.SemanticConventionVersion.V1_28_0 = 1 -> OpenTelemetry.Instrumentation.AWS.SemanticConventionVersion
27
OpenTelemetry.Instrumentation.AWS.AWSClientInstrumentationOptions
38
OpenTelemetry.Instrumentation.AWS.AWSClientInstrumentationOptions.AWSClientInstrumentationOptions() -> void
9+
OpenTelemetry.Instrumentation.AWS.AWSClientInstrumentationOptions.SemanticConventionVersion.get -> OpenTelemetry.Instrumentation.AWS.SemanticConventionVersion
10+
OpenTelemetry.Instrumentation.AWS.AWSClientInstrumentationOptions.SemanticConventionVersion.set -> void
411
OpenTelemetry.Instrumentation.AWS.AWSClientInstrumentationOptions.SuppressDownstreamInstrumentation.get -> bool
512
OpenTelemetry.Instrumentation.AWS.AWSClientInstrumentationOptions.SuppressDownstreamInstrumentation.set -> void
613
OpenTelemetry.Trace.TracerProviderBuilderExtensions

src/OpenTelemetry.Instrumentation.AWS/AWSClientInstrumentationOptions.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright The OpenTelemetry Authors
22
// SPDX-License-Identifier: Apache-2.0
33

4+
using OpenTelemetry.AWS;
5+
46
namespace OpenTelemetry.Instrumentation.AWS;
57

68
/// <summary>
@@ -12,4 +14,7 @@ public class AWSClientInstrumentationOptions
1214
/// Gets or sets a value indicating whether downstream instrumentation is suppressed.
1315
/// </summary>
1416
public bool SuppressDownstreamInstrumentation { get; set; }
17+
18+
/// <inheritdoc cref="AWS.SemanticConventionVersion"/>
19+
public SemanticConventionVersion SemanticConventionVersion { get; set; } = AWSSemanticConventions.DefaultSemanticConventionVersion;
1520
}

src/OpenTelemetry.Instrumentation.AWS/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22

33
## Unreleased
44

5+
* Introduce `AWSClientInstrumentationOptions.SemanticConventionVersion` which
6+
provides a mechanism for developers to opt-in to newer versions of the
7+
of the OpenTelemetry Semantic Conventions. Currently, you need to opt-in
8+
to these new conventions. In the upcoming stable release of this library,
9+
the new conventions will be enabled by default, and the conventions this library
10+
currently emit will no longer be supported.
11+
([#2367](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/2367))
12+
513
## 1.10.0-beta.2
614

715
Released 2024-Dec-12

src/OpenTelemetry.Instrumentation.AWS/Implementation/AWSSemanticConventions.cs

Lines changed: 0 additions & 35 deletions
This file was deleted.

src/OpenTelemetry.Instrumentation.AWS/Implementation/AWSServiceHelper.cs

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,28 @@
22
// SPDX-License-Identifier: Apache-2.0
33

44
using Amazon.Runtime;
5+
using OpenTelemetry.AWS;
56

67
namespace OpenTelemetry.Instrumentation.AWS.Implementation;
78

89
internal class AWSServiceHelper
910
{
10-
internal static IReadOnlyDictionary<string, List<string>> ServiceRequestParameterMap = new Dictionary<string, List<string>>()
11+
public AWSServiceHelper(AWSSemanticConventions semanticConventions)
12+
{
13+
this.ParameterAttributeMap =
14+
semanticConventions
15+
.ParameterMappingBuilder
16+
.AddAttributeAWSDynamoTableName("TableName")
17+
.AddAttributeAWSSQSQueueUrl("QueueUrl")
18+
.AddAttributeGenAiModelId("ModelId")
19+
.AddAttributeAWSBedrockAgentId("AgentId")
20+
.AddAttributeAWSBedrockDataSourceId("DataSourceId")
21+
.AddAttributeAWSBedrockGuardrailId("GuardrailId")
22+
.AddAttributeAWSBedrockKnowledgeBaseId("KnowledgeBaseId")
23+
.Build();
24+
}
25+
26+
internal static IReadOnlyDictionary<string, List<string>> ServiceRequestParameterMap { get; } = new Dictionary<string, List<string>>()
1127
{
1228
{ AWSServiceType.DynamoDbService, ["TableName"] },
1329
{ AWSServiceType.SQSService, ["QueueUrl"] },
@@ -16,25 +32,14 @@ internal class AWSServiceHelper
1632
{ AWSServiceType.BedrockRuntimeService, ["ModelId"] },
1733
};
1834

19-
internal static IReadOnlyDictionary<string, List<string>> ServiceResponseParameterMap = new Dictionary<string, List<string>>()
35+
internal static IReadOnlyDictionary<string, List<string>> ServiceResponseParameterMap { get; } = new Dictionary<string, List<string>>()
2036
{
2137
{ AWSServiceType.BedrockService, ["GuardrailId"] },
2238
{ AWSServiceType.BedrockAgentService, ["AgentId", "DataSourceId"] },
2339
};
2440

25-
internal static IReadOnlyDictionary<string, string> ParameterAttributeMap = new Dictionary<string, string>()
26-
{
27-
{ "TableName", AWSSemanticConventions.AttributeAWSDynamoTableName },
28-
{ "QueueUrl", AWSSemanticConventions.AttributeAWSSQSQueueUrl },
29-
{ "ModelId", AWSSemanticConventions.AttributeGenAiModelId },
30-
{ "AgentId", AWSSemanticConventions.AttributeAWSBedrockAgentId },
31-
{ "DataSourceId", AWSSemanticConventions.AttributeAWSBedrockDataSourceId },
32-
{ "GuardrailId", AWSSemanticConventions.AttributeAWSBedrockGuardrailId },
33-
{ "KnowledgeBaseId", AWSSemanticConventions.AttributeAWSBedrockKnowledgeBaseId },
34-
};
35-
3641
// for Bedrock Agent operations, we map each supported operation to one resource: Agent, DataSource, or KnowledgeBase
37-
internal static List<string> BedrockAgentAgentOps =
42+
internal static List<string> BedrockAgentAgentOps { get; } =
3843
[
3944
"CreateAgentActionGroup",
4045
"CreateAgentAlias",
@@ -56,7 +61,7 @@ internal class AWSServiceHelper
5661
"UpdateAgent"
5762
];
5863

59-
internal static List<string> BedrockAgentKnowledgeBaseOps =
64+
internal static List<string> BedrockAgentKnowledgeBaseOps { get; } =
6065
[
6166
"AssociateAgentKnowledgeBase",
6267
"CreateDataSource",
@@ -68,13 +73,15 @@ internal class AWSServiceHelper
6873
"UpdateAgentKnowledgeBase"
6974
];
7075

71-
internal static List<string> BedrockAgentDataSourceOps =
76+
internal static List<string> BedrockAgentDataSourceOps { get; } =
7277
[
7378
"DeleteDataSource",
7479
"GetDataSource",
7580
"UpdateDataSource"
7681
];
7782

83+
internal IDictionary<string, string> ParameterAttributeMap { get; }
84+
7885
internal static IReadOnlyDictionary<string, string> OperationNameToResourceMap()
7986
{
8087
var operationClassMap = new Dictionary<string, string>();

src/OpenTelemetry.Instrumentation.AWS/Implementation/AWSTracingPipelineCustomizer.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,16 @@ namespace OpenTelemetry.Instrumentation.AWS.Implementation;
1212
/// </summary>
1313
internal class AWSTracingPipelineCustomizer : IRuntimePipelineCustomizer
1414
{
15+
public const string UniqueName = "AWS Tracing Registration Customization";
16+
1517
private readonly AWSClientInstrumentationOptions options;
1618

1719
public AWSTracingPipelineCustomizer(AWSClientInstrumentationOptions options)
1820
{
1921
this.options = options;
2022
}
2123

22-
public string UniqueName => "AWS Tracing Registration Customization";
24+
string IRuntimePipelineCustomizer.UniqueName => UniqueName;
2325

2426
public void Customize(Type serviceClientType, RuntimePipeline pipeline)
2527
{

src/OpenTelemetry.Instrumentation.AWS/Implementation/AWSTracingPipelineHandler.cs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
using Amazon.Runtime;
66
using Amazon.Runtime.Internal;
77
using Amazon.Runtime.Telemetry;
8+
using OpenTelemetry.AWS;
89
using OpenTelemetry.Context.Propagation;
9-
using OpenTelemetry.Trace;
1010

1111
namespace OpenTelemetry.Instrumentation.AWS.Implementation;
1212

@@ -19,25 +19,29 @@ namespace OpenTelemetry.Instrumentation.AWS.Implementation;
1919
internal sealed class AWSTracingPipelineHandler : PipelineHandler
2020
{
2121
private readonly AWSClientInstrumentationOptions options;
22+
private readonly AWSSemanticConventions awsSemanticConventions;
23+
private readonly AWSServiceHelper awsServiceHelper;
2224

2325
public AWSTracingPipelineHandler(AWSClientInstrumentationOptions options)
2426
{
2527
this.options = options;
28+
this.awsSemanticConventions = new AWSSemanticConventions(options.SemanticConventionVersion);
29+
this.awsServiceHelper = new AWSServiceHelper(this.awsSemanticConventions);
2630
}
2731

2832
public override void InvokeSync(IExecutionContext executionContext)
2933
{
3034
var activity = this.ProcessBeginRequest(executionContext);
3135
base.InvokeSync(executionContext);
32-
ProcessEndRequest(activity, executionContext);
36+
this.ProcessEndRequest(activity, executionContext);
3337
}
3438

3539
public override async Task<T> InvokeAsync<T>(IExecutionContext executionContext)
3640
{
3741
var activity = this.ProcessBeginRequest(executionContext);
3842
var ret = await base.InvokeAsync<T>(executionContext).ConfigureAwait(false);
3943

40-
ProcessEndRequest(activity, executionContext);
44+
this.ProcessEndRequest(activity, executionContext);
4145

4246
return ret;
4347
}
@@ -48,7 +52,7 @@ public override async Task<T> InvokeAsync<T>(IExecutionContext executionContext)
4852
"IL2075",
4953
Justification = "The reflected properties were already used by the AWS SDK's marshallers so the properties could not have been trimmed.")]
5054
#endif
51-
private static void AddResponseSpecificInformation(Activity activity, IExecutionContext executionContext)
55+
private void AddResponseSpecificInformation(Activity activity, IExecutionContext executionContext)
5256
{
5357
var service = executionContext.RequestContext.ServiceMetaData.ServiceId;
5458
var responseContext = executionContext.ResponseContext;
@@ -67,14 +71,14 @@ private static void AddResponseSpecificInformation(Activity activity, IExecution
6771
var operationName = Utils.RemoveSuffix(response.GetType().Name, "Response");
6872
if (AWSServiceHelper.OperationNameToResourceMap()[operationName] == parameter)
6973
{
70-
AddBedrockAgentResponseAttribute(activity, response, parameter);
74+
this.AddBedrockAgentResponseAttribute(activity, response, parameter);
7175
}
7276
}
7377

7478
var property = response.GetType().GetProperty(parameter);
7579
if (property != null)
7680
{
77-
if (AWSServiceHelper.ParameterAttributeMap.TryGetValue(parameter, out var attribute))
81+
if (this.awsServiceHelper.ParameterAttributeMap.TryGetValue(parameter, out var attribute))
7882
{
7983
activity.SetTag(attribute, property.GetValue(response));
8084
}
@@ -95,7 +99,7 @@ private static void AddResponseSpecificInformation(Activity activity, IExecution
9599
"IL2075",
96100
Justification = "The reflected properties were already used by the AWS SDK's marshallers so the properties could not have been trimmed.")]
97101
#endif
98-
private static void AddBedrockAgentResponseAttribute(Activity activity, AmazonWebServiceResponse response, string parameter)
102+
private void AddBedrockAgentResponseAttribute(Activity activity, AmazonWebServiceResponse response, string parameter)
99103
{
100104
var responseObject = response.GetType().GetProperty(Utils.RemoveSuffix(parameter, "Id"));
101105
if (responseObject != null)
@@ -106,7 +110,7 @@ private static void AddBedrockAgentResponseAttribute(Activity activity, AmazonWe
106110
var property = attributeObject.GetType().GetProperty(parameter);
107111
if (property != null)
108112
{
109-
if (AWSServiceHelper.ParameterAttributeMap.TryGetValue(parameter, out var attribute))
113+
if (this.awsServiceHelper.ParameterAttributeMap.TryGetValue(parameter, out var attribute))
110114
{
111115
activity.SetTag(attribute, property.GetValue(attributeObject));
112116
}
@@ -121,7 +125,7 @@ private static void AddBedrockAgentResponseAttribute(Activity activity, AmazonWe
121125
"IL2075",
122126
Justification = "The reflected properties were already used by the AWS SDK's marshallers so the properties could not have been trimmed.")]
123127
#endif
124-
private static void AddRequestSpecificInformation(Activity activity, IRequestContext requestContext)
128+
private void AddRequestSpecificInformation(Activity activity, IRequestContext requestContext)
125129
{
126130
var service = requestContext.ServiceMetaData.ServiceId;
127131

@@ -145,7 +149,7 @@ private static void AddRequestSpecificInformation(Activity activity, IRequestCon
145149
var property = request.GetType().GetProperty(parameter);
146150
if (property != null)
147151
{
148-
if (AWSServiceHelper.ParameterAttributeMap.TryGetValue(parameter, out var attribute))
152+
if (this.awsServiceHelper.ParameterAttributeMap.TryGetValue(parameter, out var attribute))
149153
{
150154
activity.SetTag(attribute, property.GetValue(request));
151155
}
@@ -161,7 +165,7 @@ private static void AddRequestSpecificInformation(Activity activity, IRequestCon
161165

162166
if (AWSServiceType.IsDynamoDbService(service))
163167
{
164-
activity.SetTag(SemanticConventions.AttributeDbSystem, AWSSemanticConventions.AttributeValueDynamoDb);
168+
this.awsSemanticConventions.TagBuilder.SetTagAttributeDbSystemToDynamoDb(activity);
165169
}
166170
else if (AWSServiceType.IsSqsService(service))
167171
{
@@ -175,18 +179,18 @@ private static void AddRequestSpecificInformation(Activity activity, IRequestCon
175179
}
176180
else if (AWSServiceType.IsBedrockRuntimeService(service))
177181
{
178-
activity.SetTag(AWSSemanticConventions.AttributeGenAiSystem, AWSSemanticConventions.AttributeAWSBedrock);
182+
this.awsSemanticConventions.TagBuilder.SetTagAttributeGenAiSystemToBedrock(activity);
179183
}
180184
}
181185

182-
private static void ProcessEndRequest(Activity? activity, IExecutionContext executionContext)
186+
private void ProcessEndRequest(Activity? activity, IExecutionContext executionContext)
183187
{
184188
if (activity == null || !activity.IsAllDataRequested)
185189
{
186190
return;
187191
}
188192

189-
AddResponseSpecificInformation(activity, executionContext);
193+
this.AddResponseSpecificInformation(activity, executionContext);
190194
}
191195

192196
private Activity? ProcessBeginRequest(IExecutionContext executionContext)
@@ -205,7 +209,7 @@ private static void ProcessEndRequest(Activity? activity, IExecutionContext exec
205209
return null;
206210
}
207211

208-
AddRequestSpecificInformation(currentActivity, executionContext.RequestContext);
212+
this.AddRequestSpecificInformation(currentActivity, executionContext.RequestContext);
209213
return currentActivity;
210214
}
211215
}

src/OpenTelemetry.Instrumentation.AWS/OpenTelemetry.Instrumentation.AWS.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
<TargetFrameworks Condition="$(OS) == 'Windows_NT'">$(TargetFrameworks);$(NetFrameworkMinimumSupportedVersion)</TargetFrameworks>
77
<Description>AWS client instrumentation for OpenTelemetry .NET.</Description>
88
<MinVerTagPrefix>Instrumentation.AWS-</MinVerTagPrefix>
9+
<DefineConstants>INSTRUMENTATION_AWS;$(DefineConstants)</DefineConstants>
910
</PropertyGroup>
1011

1112
<!-- Do not run Package Baseline Validation as this package has never released a stable version.
@@ -25,9 +26,9 @@
2526
</ItemGroup>
2627

2728
<ItemGroup>
29+
<Compile Include="$(RepoRoot)\src\Shared\AWS\*.cs" Link="Includes\AWS\%(Filename).cs" />
2830
<Compile Include="$(RepoRoot)\src\Shared\AssemblyVersionExtensions.cs" Link="Includes\AssemblyVersionExtensions.cs" />
2931
<Compile Include="$(RepoRoot)\src\Shared\Guard.cs" Link="Includes\Guard.cs" />
30-
<Compile Include="$(RepoRoot)\src\Shared\SemanticConventions.cs" Link="Includes\SemanticConventions.cs" />
3132
</ItemGroup>
3233

3334
</Project>

src/OpenTelemetry.Instrumentation.AWS/README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,48 @@ public void ConfigureServices(IServiceCollection services)
3333
.AddOtlpExporter());
3434
}
3535
```
36+
37+
## Semantic Conventions
38+
39+
_For an overview on Semantic Conventions, see
40+
[OpenTelemetery - Semantic Conventions](https://opentelemetry.io/docs/concepts/semantic-conventions/)_.
41+
42+
While this library is intended for production use, it relies on several
43+
Semantic Conventions that are still considered Experimental, meaning
44+
they may undergo additional changes before becoming Stable. This can impact
45+
the aggregation and analysis of telemetry signals in environments with
46+
multiple applications or microservices.
47+
48+
For example, a microservice using an older version of the Semantic Conventions
49+
for Http Attributes may emit `"http.method"` with a value of GET, while a
50+
different microservice, using a new version of Semantic Convention may instead
51+
emit the GET as `"http.request.method"`.
52+
53+
Future versions the OpenTelemetry.*.AWS libraries will include updates to the
54+
Semantic Convention, which may break compatibility with a previous version.
55+
56+
The default will remain as `V1_28_0` until the next major version bump.
57+
58+
To opt in to automatic upgrades, you can use `SemanticConventionVersion.Latest`
59+
or you can specify a specific version:
60+
61+
```csharp
62+
using OpenTelemetry;
63+
using OpenTelemetry.AWS;
64+
using OpenTelemetry.Contrib.Extensions.AWSXRay.Trace;
65+
using OpenTelemetry.Trace;
66+
67+
public void ConfigureServices(IServiceCollection services)
68+
{
69+
services.AddControllers();
70+
services.AddOpenTelemetryTracing((builder) => builder
71+
.AddAWSInstrumentation(opt => {
72+
// pin to a specific Semantic Convention version
73+
opt.SemanticConventionVersion = SemanticConventionVersion.V1_29_0;
74+
});
75+
}
76+
```
77+
78+
**NOTE:** Once a Semantic Convention becomes Stable, OpenTelemetry.*.AWS
79+
libraries will remain on that version until the
80+
next major version bump.

0 commit comments

Comments
 (0)