From 6a77f8de1575bf5f68e4555a1f93ecb41af0d43c Mon Sep 17 00:00:00 2001 From: Matthew Sainsbury Date: Tue, 7 Oct 2025 10:37:12 -0700 Subject: [PATCH 1/7] initial changes --- .../Models/RemoteDependencyData.cs | 20 +++++++++++++++---- .../src/Internals/ActivityTagsProcessor.cs | 3 +++ .../src/Internals/AzMonListExtensions.cs | 19 ++++++++++++++---- .../src/Internals/SemanticConventions.cs | 11 ++++++++++ 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Customizations/Models/RemoteDependencyData.cs b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Customizations/Models/RemoteDependencyData.cs index d09c636d9ed3..79ddd09b638b 100644 --- a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Customizations/Models/RemoteDependencyData.cs +++ b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Customizations/Models/RemoteDependencyData.cs @@ -28,7 +28,7 @@ public RemoteDependencyData(int version, Activity activity, ref ActivityTagsProc SetHttpDependencyPropertiesAndDependencyName(activity, ref activityTagsProcessor.MappedTags, isNewSchemaVersion, out dependencyName); break; case OperationType.Db: - SetDbDependencyProperties(ref activityTagsProcessor.MappedTags); + SetDbDependencyProperties(ref activityTagsProcessor.MappedTags, isNewSchemaVersion); break; case OperationType.Messaging: SetMessagingDependencyProperties(activity, ref activityTagsProcessor.MappedTags); @@ -86,11 +86,23 @@ private void SetHttpDependencyPropertiesAndDependencyName(Activity activity, ref ResultCode = resultCode?.Truncate(SchemaConstants.RemoteDependencyData_ResultCode_MaxLength) ?? "0"; } - private void SetDbDependencyProperties(ref AzMonList dbTagObjects) + private void SetDbDependencyProperties(ref AzMonList dbTagObjects, bool isNewSchemaVersion) { - var dbAttributeTagObjects = AzMonList.GetTagValues(ref dbTagObjects, SemanticConventions.AttributeDbStatement, SemanticConventions.AttributeDbSystem); + string statementAttributeKey; + string statementSystemKey; + if (isNewSchemaVersion) + { + statementAttributeKey = SemanticConventions.AttributeDbQueryText; + statementSystemKey = SemanticConventions.AttributeDbSystemName; + } + else + { + statementAttributeKey = SemanticConventions.AttributeDbStatement; + statementSystemKey = SemanticConventions.AttributeDbSystem; + } + var dbAttributeTagObjects = AzMonList.GetTagValues(ref dbTagObjects, statementAttributeKey, statementSystemKey); Data = dbAttributeTagObjects[0]?.ToString().Truncate(SchemaConstants.RemoteDependencyData_Data_MaxLength); - var (DbName, DbTarget) = dbTagObjects.GetDbDependencyTargetAndName(); + var (DbName, DbTarget) = dbTagObjects.GetDbDependencyTargetAndName(isNewSchemaVersion); Target = DbTarget?.Truncate(SchemaConstants.RemoteDependencyData_Target_MaxLength); Type = AzMonListExtensions.s_dbSystems.Contains(dbAttributeTagObjects[1]?.ToString()) ? "SQL" : dbAttributeTagObjects[1]?.ToString().Truncate(SchemaConstants.RemoteDependencyData_Type_MaxLength); diff --git a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/ActivityTagsProcessor.cs b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/ActivityTagsProcessor.cs index 10ebc1e47364..4ff3521cb90a 100644 --- a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/ActivityTagsProcessor.cs +++ b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/ActivityTagsProcessor.cs @@ -100,6 +100,9 @@ public void CategorizeTags(Activity activity) case SemanticConventions.AttributeDbSystem: activityType = OperationType.Db; break; + case SemanticConventions.AttributeDbSystemName: + activityType = OperationType.Db | OperationType.V2; + break; case SemanticConventions.AttributeMessagingSystem: activityType = OperationType.Messaging; break; diff --git a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/AzMonListExtensions.cs b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/AzMonListExtensions.cs index 132777870ce7..3e1cf821d100 100644 --- a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/AzMonListExtensions.cs +++ b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/AzMonListExtensions.cs @@ -329,9 +329,20 @@ internal static string GetDefaultDbPort(string? dbSystem) /// /// Gets Database dependency target and name from activity tag objects. /// - internal static (string? DbName, string? DbTarget) GetDbDependencyTargetAndName(this AzMonList tagObjects) + internal static (string? DbName, string? DbTarget) GetDbDependencyTargetAndName(this AzMonList tagObjects, bool isNewSchemaVersion) { - var peerServiceAndDbSystem = AzMonList.GetTagValues(ref tagObjects, SemanticConventions.AttributePeerService, SemanticConventions.AttributeDbSystem); + + string statementDbNameKey; + string statementDbSystemKey; + if (isNewSchemaVersion) { + statementDbNameKey = SemanticConventions.AttributeDbNamespace; + statementDbSystemKey = SemanticConventions.AttributeDbSystemName; + } else { + statementDbNameKey = SemanticConventions.AttributeDbName; + statementDbSystemKey = SemanticConventions.AttributeDbSystem; + } + + var peerServiceAndDbSystem = AzMonList.GetTagValues(ref tagObjects, SemanticConventions.AttributePeerService, statementDbSystemKey); string? target = peerServiceAndDbSystem[0]?.ToString(); var defaultPort = GetDefaultDbPort(peerServiceAndDbSystem[1]?.ToString()); @@ -340,7 +351,7 @@ internal static (string? DbName, string? DbTarget) GetDbDependencyTargetAndName( target = tagObjects.GetTargetUsingServerAttributes(defaultPort) ?? tagObjects.GetTargetUsingNetPeerAttributes(defaultPort); } - var dbName = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeDbName)?.ToString(); + var dbName = AzMonList.GetTagValue(ref tagObjects, statementDbNameKey)?.ToString(); bool isTargetEmpty = string.IsNullOrWhiteSpace(target); bool isDbNameEmpty = string.IsNullOrWhiteSpace(dbName); if (!isTargetEmpty && !isDbNameEmpty) @@ -353,7 +364,7 @@ internal static (string? DbName, string? DbTarget) GetDbDependencyTargetAndName( } else if (isTargetEmpty && isDbNameEmpty) { - target = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeDbSystem)?.ToString(); + target = AzMonList.GetTagValue(ref tagObjects, statementDbSystemKey)?.ToString(); } return (DbName: dbName, DbTarget: target); diff --git a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/SemanticConventions.cs b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/SemanticConventions.cs index e558d2e328c6..c3db8146993e 100644 --- a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/SemanticConventions.cs +++ b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/SemanticConventions.cs @@ -164,5 +164,16 @@ internal static class SemanticConventions // Messaging v1.21.0 https://github.com/open-telemetry/opentelemetry-specification/blob/v1.21.0/specification/trace/semantic_conventions/messaging.md public const string AttributeMessagingDestinationName = "messaging.destination.name"; public const string AttributeNetworkProtocolName = "network.protocol.name"; + + // Database v1.36.0 https://github.com/open-telemetry/semantic-conventions/tree/v1.36.0/docs/database + public const string AttributeDbCollectionName = "db.collection.name"; + public const string AttributeDbOperationName = "db.operation.name"; + public const string AttributeDbSystemName = "db.system.name"; + public const string AttributeDbNamespace = "db.namespace"; + public const string AttributeDbResponseStatusCode = "db.response.status_code"; + public const string AttributeDbOperationBatchSize = "db.operation.batch.size"; + public const string AttributeDbQuerySummary = "db.query.summary"; + public const string AttributeDbQueryText = "db.query.text"; + public const string AttributeDbStoredProcedureName = "db.stored_procedure.name"; } } From 16419d7e6b620428c59503a0a1829c6fd63ccc32 Mon Sep 17 00:00:00 2001 From: Matthew Sainsbury Date: Tue, 7 Oct 2025 10:53:02 -0700 Subject: [PATCH 2/7] initial go at tests --- .../src/Internals/AzMonListExtensions.cs | 3 +- .../src/Internals/AzMonNewListExtensions.cs | 2 +- .../AzMonListExtensionsTests.cs | 8 ++--- .../RemoteDependencyDataTests.cs | 36 ++++++++++++++++++- 4 files changed, 41 insertions(+), 8 deletions(-) diff --git a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/AzMonListExtensions.cs b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/AzMonListExtensions.cs index 3e1cf821d100..357f1d9d88cb 100644 --- a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/AzMonListExtensions.cs +++ b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/AzMonListExtensions.cs @@ -331,7 +331,6 @@ internal static string GetDefaultDbPort(string? dbSystem) /// internal static (string? DbName, string? DbTarget) GetDbDependencyTargetAndName(this AzMonList tagObjects, bool isNewSchemaVersion) { - string statementDbNameKey; string statementDbSystemKey; if (isNewSchemaVersion) { @@ -380,7 +379,7 @@ internal static (string? DbName, string? DbTarget) GetDbDependencyTargetAndName( case OperationType.Http: return tagObjects.GetHttpDependencyTarget(); case OperationType.Db: - return tagObjects.GetDbDependencyTargetAndName().DbTarget; + return tagObjects.GetDbDependencyTargetAndName(type.HasFlag(OperationType.V2)).DbTarget; case OperationType.Messaging: return tagObjects.GetMessagingUrlAndSourceOrTarget(ActivityKind.Producer).SourceOrTarget; default: diff --git a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/AzMonNewListExtensions.cs b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/AzMonNewListExtensions.cs index b6e8477ac4bf..1a41e56fe957 100644 --- a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/AzMonNewListExtensions.cs +++ b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/AzMonNewListExtensions.cs @@ -142,7 +142,7 @@ internal static (string? MessagingUrl, string? SourceOrTarget) GetMessagingUrlAn case OperationType.Http: return tagObjects.GetNewSchemaHttpDependencyTarget(); case OperationType.Db: - return tagObjects.GetDbDependencyTargetAndName().DbTarget; + return tagObjects.GetDbDependencyTargetAndName(type.HasFlag(OperationType.V2)).DbTarget; default: return null; } diff --git a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/AzMonListExtensionsTests.cs b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/AzMonListExtensionsTests.cs index b3005681b2f9..f6e751fc8abd 100644 --- a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/AzMonListExtensionsTests.cs +++ b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/AzMonListExtensionsTests.cs @@ -566,7 +566,7 @@ public void DbNameIsAppendedToTargetDerivedFromNetAttributesforDBDependencyTarge AzMonList.Add(ref mappedTags, new KeyValuePair(SemanticConventions.AttributeServerSocketAddress, serverSocketAddress)); AzMonList.Add(ref mappedTags, new KeyValuePair(SemanticConventions.AttributeDbName, "DbName")); - Assert.Equal(expectedTarget, mappedTags.GetDbDependencyTargetAndName().DbTarget); + Assert.Equal(expectedTarget, mappedTags.GetDbDependencyTargetAndName(false).DbTarget); } [Fact] @@ -574,7 +574,7 @@ public void DbDependencyTargetIsSetToDbNameWhenNetAttributesAreNotPresent() { var mappedTags = AzMonList.Initialize(); AzMonList.Add(ref mappedTags, new KeyValuePair(SemanticConventions.AttributeDbName, "DbName")); - Assert.Equal("DbName", mappedTags.GetDbDependencyTargetAndName().DbTarget); + Assert.Equal("DbName", mappedTags.GetDbDependencyTargetAndName(false).DbTarget); } [Fact] @@ -582,14 +582,14 @@ public void DbDependencyTargetIsSetToDbSystemWhenNetAndDbNameAttributesAreNotPre { var mappedTags = AzMonList.Initialize(); AzMonList.Add(ref mappedTags, new KeyValuePair(SemanticConventions.AttributeDbSystem, "DbSystem")); - Assert.Equal("DbSystem", mappedTags.GetDbDependencyTargetAndName().DbTarget); + Assert.Equal("DbSystem", mappedTags.GetDbDependencyTargetAndName(false).DbTarget); } [Fact] public void DbDependencyTargetIsSetToNullByDefault() { var mappedTags = AzMonList.Initialize(); - Assert.Null(mappedTags.GetDbDependencyTargetAndName().DbTarget); + Assert.Null(mappedTags.GetDbDependencyTargetAndName(false).DbTarget); } } } diff --git a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/RemoteDependencyDataTests.cs b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/RemoteDependencyDataTests.cs index a9ff8b9873a0..5b0816d7950e 100644 --- a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/RemoteDependencyDataTests.cs +++ b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/RemoteDependencyDataTests.cs @@ -136,7 +136,7 @@ public void ValidateHttpRemoteDependencyData() } [Fact] - public void ValidateDbRemoteDependencyData() + public void ValidateOldDbRemoteDependencyData() { using ActivitySource activitySource = new ActivitySource(ActivitySourceName); using var activity = activitySource.StartActivity( @@ -169,6 +169,40 @@ public void ValidateDbRemoteDependencyData() Assert.True(remoteDependencyData.Measurements.Count == 0); } + [Fact] + public void ValidateNewDbRemoteDependencyData() + { + using ActivitySource activitySource = new ActivitySource(ActivitySourceName); + using var activity = activitySource.StartActivity( + ActivityName, + ActivityKind.Client, + parentContext: new ActivityContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.Recorded), + startTime: DateTime.UtcNow); + Assert.NotNull(activity); + activity.Stop(); + + activity.SetStatus(ActivityStatusCode.Ok); + activity.SetTag(SemanticConventions.AttributeDbNamespace, "mysqlserver"); + activity.SetTag(SemanticConventions.AttributeDbSystemName, "mssql"); + activity.SetTag(SemanticConventions.AttributePeerService, "localhost"); // only adding test via peer.service. all possible combinations are covered in AzMonListExtensionsTests. + activity.SetTag(SemanticConventions.AttributeDbQueryText, "Select * from table"); + + var activityTagsProcessor = TraceHelper.EnumerateActivityTags(activity); + + var remoteDependencyData = new RemoteDependencyData(2, activity, ref activityTagsProcessor); + + Assert.Equal(ActivityName, remoteDependencyData.Name); + Assert.Equal(activity.Context.SpanId.ToHexString(), remoteDependencyData.Id); + Assert.Equal("Select * from table", remoteDependencyData.Data); + Assert.Equal("localhost | mysqlserver", remoteDependencyData.Target); + Assert.Null(remoteDependencyData.ResultCode); + Assert.Equal(activity.Duration.ToString("c", CultureInfo.InvariantCulture), remoteDependencyData.Duration); + Assert.Equal(activity.Status != ActivityStatusCode.Error, remoteDependencyData.Success); + Assert.True(remoteDependencyData.Properties.Count == 1); + Assert.True(remoteDependencyData.Properties.Contains(new KeyValuePair(SemanticConventions.AttributeDbName, "mysqlserver" ))); + Assert.True(remoteDependencyData.Measurements.Count == 0); + } + [Fact] public void HttpDependencyNameIsActivityDisplayNameByDefault() { From 0ba86dbce88b39ce622240e17955c29ec1c06544 Mon Sep 17 00:00:00 2001 From: Matthew Sainsbury Date: Tue, 7 Oct 2025 11:20:13 -0700 Subject: [PATCH 3/7] fix test --- .../src/Internals/ActivityTagsProcessor.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/ActivityTagsProcessor.cs b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/ActivityTagsProcessor.cs index 4ff3521cb90a..2aeb1f03ecf1 100644 --- a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/ActivityTagsProcessor.cs +++ b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/ActivityTagsProcessor.cs @@ -11,8 +11,11 @@ internal struct ActivityTagsProcessor { private static readonly string[] s_semantics = { SemanticConventions.AttributeDbStatement, + SemanticConventions.AttributeDbQueryText, SemanticConventions.AttributeDbSystem, + SemanticConventions.AttributeDbSystemName, SemanticConventions.AttributeDbName, + SemanticConventions.AttributeDbNamespace, // required - HTTP SemanticConventions.AttributeHttpMethod, From 26b9160b5875f14f4c0e62809a48c3c1f091ecfd Mon Sep 17 00:00:00 2001 From: Matthew Sainsbury Date: Tue, 7 Oct 2025 11:42:49 -0700 Subject: [PATCH 4/7] add tags tests --- .../TagsTests.cs | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/TagsTests.cs b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/TagsTests.cs index 0d4975a5fd12..97b57852e894 100644 --- a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/TagsTests.cs +++ b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/TagsTests.cs @@ -116,7 +116,7 @@ public void TagObjects_Mapped() } [Fact] - public void TagObjects_Mapped_HonorsNewSchema() + public void TagObjects_Mapped_HonorsNewHTTPSchema() { var activityTagsProcessor = new ActivityTagsProcessor(); @@ -140,6 +140,30 @@ public void TagObjects_Mapped_HonorsNewSchema() Assert.Equal("/test", AzMonList.GetTagValue(ref activityTagsProcessor.MappedTags, SemanticConventions.AttributeUrlPath)); } + [Fact] + public void TagObjects_Mapped_HonorsNewDBSchema() + { + var activityTagsProcessor = new ActivityTagsProcessor(); + + IEnumerable> tagObjects = new Dictionary + { + [SemanticConventions.AttributeDbNamespace] = "mysqlserver", + [SemanticConventions.AttributeDbSystemName] = "mssql", + [SemanticConventions.AttributePeerService] = "localhost", + [SemanticConventions.AttributeDbQueryText] = "Select * from table", + }; + + using var activity = CreateTestActivity(tagObjects); + activityTagsProcessor.CategorizeTags(activity); + + Assert.Equal(OperationType.Db | OperationType.V2, activityTagsProcessor.activityType); + Assert.Equal(5, activityTagsProcessor.MappedTags.Length); + Assert.Equal("mysqlserver", AzMonList.GetTagValue(ref activityTagsProcessor.MappedTags, SemanticConventions.AttributeDbNamespace)); + Assert.Equal("mssql", AzMonList.GetTagValue(ref activityTagsProcessor.MappedTags, SemanticConventions.AttributeDbSystemName)); + Assert.Equal("localhost", AzMonList.GetTagValue(ref activityTagsProcessor.MappedTags, SemanticConventions.AttributePeerService)); + Assert.Equal("Select * from table", AzMonList.GetTagValue(ref activityTagsProcessor.MappedTags, SemanticConventions.AttributeDbQueryText)); + } + [Fact] public void TagObjects_Mapped_UnMapped() { From d4b7d7bcec26615cfb36668682cb0de7e5331889 Mon Sep 17 00:00:00 2001 From: Matthew Sainsbury Date: Tue, 7 Oct 2025 11:57:31 -0700 Subject: [PATCH 5/7] fix tests --- .../AzMonListExtensionsTests.cs | 14 +++++++------- .../TagsTests.cs | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/AzMonListExtensionsTests.cs b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/AzMonListExtensionsTests.cs index f6e751fc8abd..bd485bf9696c 100644 --- a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/AzMonListExtensionsTests.cs +++ b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/AzMonListExtensionsTests.cs @@ -564,32 +564,32 @@ public void DbNameIsAppendedToTargetDerivedFromNetAttributesforDBDependencyTarge AzMonList.Add(ref mappedTags, new KeyValuePair(SemanticConventions.AttributeServerAddress, serverAddress)); AzMonList.Add(ref mappedTags, new KeyValuePair(SemanticConventions.AttributeServerPort, serverPort)); AzMonList.Add(ref mappedTags, new KeyValuePair(SemanticConventions.AttributeServerSocketAddress, serverSocketAddress)); - AzMonList.Add(ref mappedTags, new KeyValuePair(SemanticConventions.AttributeDbName, "DbName")); + AzMonList.Add(ref mappedTags, new KeyValuePair(SemanticConventions.AttributeDbNamespace, "DbName")); - Assert.Equal(expectedTarget, mappedTags.GetDbDependencyTargetAndName(false).DbTarget); + Assert.Equal(expectedTarget, mappedTags.GetDbDependencyTargetAndName(true).DbTarget); } [Fact] public void DbDependencyTargetIsSetToDbNameWhenNetAttributesAreNotPresent() { var mappedTags = AzMonList.Initialize(); - AzMonList.Add(ref mappedTags, new KeyValuePair(SemanticConventions.AttributeDbName, "DbName")); - Assert.Equal("DbName", mappedTags.GetDbDependencyTargetAndName(false).DbTarget); + AzMonList.Add(ref mappedTags, new KeyValuePair(SemanticConventions.AttributeDbNamespace, "DbName")); + Assert.Equal("DbName", mappedTags.GetDbDependencyTargetAndName(true).DbTarget); } [Fact] public void DbDependencyTargetIsSetToDbSystemWhenNetAndDbNameAttributesAreNotPresent() { var mappedTags = AzMonList.Initialize(); - AzMonList.Add(ref mappedTags, new KeyValuePair(SemanticConventions.AttributeDbSystem, "DbSystem")); - Assert.Equal("DbSystem", mappedTags.GetDbDependencyTargetAndName(false).DbTarget); + AzMonList.Add(ref mappedTags, new KeyValuePair(SemanticConventions.AttributeDbSystemName, "DbSystem")); + Assert.Equal("DbSystem", mappedTags.GetDbDependencyTargetAndName(true).DbTarget); } [Fact] public void DbDependencyTargetIsSetToNullByDefault() { var mappedTags = AzMonList.Initialize(); - Assert.Null(mappedTags.GetDbDependencyTargetAndName(false).DbTarget); + Assert.Null(mappedTags.GetDbDependencyTargetAndName(true).DbTarget); } } } diff --git a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/TagsTests.cs b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/TagsTests.cs index 97b57852e894..ce9a36ca2c3b 100644 --- a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/TagsTests.cs +++ b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/TagsTests.cs @@ -157,7 +157,7 @@ public void TagObjects_Mapped_HonorsNewDBSchema() activityTagsProcessor.CategorizeTags(activity); Assert.Equal(OperationType.Db | OperationType.V2, activityTagsProcessor.activityType); - Assert.Equal(5, activityTagsProcessor.MappedTags.Length); + Assert.Equal(4, activityTagsProcessor.MappedTags.Length); Assert.Equal("mysqlserver", AzMonList.GetTagValue(ref activityTagsProcessor.MappedTags, SemanticConventions.AttributeDbNamespace)); Assert.Equal("mssql", AzMonList.GetTagValue(ref activityTagsProcessor.MappedTags, SemanticConventions.AttributeDbSystemName)); Assert.Equal("localhost", AzMonList.GetTagValue(ref activityTagsProcessor.MappedTags, SemanticConventions.AttributePeerService)); From f3c3c36883e67b22c02ad353958392e6d6a0b72e Mon Sep 17 00:00:00 2001 From: Matthew Sainsbury Date: Tue, 7 Oct 2025 12:06:57 -0700 Subject: [PATCH 6/7] update changelog --- sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/CHANGELOG.md b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/CHANGELOG.md index daa94e377a68..6b3b7b5060d8 100644 --- a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/CHANGELOG.md +++ b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/CHANGELOG.md @@ -17,6 +17,8 @@ `Sdk.CreateTracerProviderBuilder().AddAzureMonitorTraceExporter(...)` path. ([#52720](https://github.com/Azure/azure-sdk-for-net/pull/52720)) +* Added handling of stable database client span semantic conventions + ### Breaking Changes ### Bugs Fixed From 58141059439dcf6a8e0bafa00dd27b48d669644f Mon Sep 17 00:00:00 2001 From: Matthew Sainsbury Date: Tue, 7 Oct 2025 14:31:30 -0700 Subject: [PATCH 7/7] PR feedback --- .../Azure.Monitor.OpenTelemetry.Exporter/CHANGELOG.md | 1 + .../src/Internals/ActivityTagsProcessor.cs | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/CHANGELOG.md b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/CHANGELOG.md index 6b3b7b5060d8..92810b74e6bb 100644 --- a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/CHANGELOG.md +++ b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/CHANGELOG.md @@ -18,6 +18,7 @@ ([#52720](https://github.com/Azure/azure-sdk-for-net/pull/52720)) * Added handling of stable database client span semantic conventions + ([#53050](https://github.com/Azure/azure-sdk-for-net/pull/53050)) ### Breaking Changes diff --git a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/ActivityTagsProcessor.cs b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/ActivityTagsProcessor.cs index 2aeb1f03ecf1..36a70956518a 100644 --- a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/ActivityTagsProcessor.cs +++ b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/ActivityTagsProcessor.cs @@ -100,12 +100,12 @@ public void CategorizeTags(Activity activity) case SemanticConventions.AttributeHttpRequestMethod: activityType = OperationType.Http | OperationType.V2; break; - case SemanticConventions.AttributeDbSystem: - activityType = OperationType.Db; - break; case SemanticConventions.AttributeDbSystemName: activityType = OperationType.Db | OperationType.V2; break; + case SemanticConventions.AttributeDbSystem: + activityType = OperationType.Db; + break; case SemanticConventions.AttributeMessagingSystem: activityType = OperationType.Messaging; break;