From 77c90d4f732d6c0782fe921817221eacd4688ab8 Mon Sep 17 00:00:00 2001 From: Alan West <3676547+alanwest@users.noreply.github.com> Date: Mon, 28 Oct 2024 14:38:21 -0700 Subject: [PATCH 1/4] Add error.type and db.response.status_code attributes --- .../Implementation/SqlClientDiagnosticListener.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlClientDiagnosticListener.cs b/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlClientDiagnosticListener.cs index b16f71402a..d64b556347 100644 --- a/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlClientDiagnosticListener.cs +++ b/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlClientDiagnosticListener.cs @@ -4,10 +4,11 @@ #if !NETFRAMEWORK using System.Data; using System.Diagnostics; -using OpenTelemetry.Trace; #if NET using System.Diagnostics.CodeAnalysis; #endif +using System.Globalization; +using OpenTelemetry.Trace; namespace OpenTelemetry.Instrumentation.SqlClient.Implementation; @@ -32,6 +33,7 @@ internal sealed class SqlClientDiagnosticListener : ListenerHandler private readonly PropertyFetcher commandTypeFetcher = new("CommandType"); private readonly PropertyFetcher commandTextFetcher = new("CommandText"); private readonly PropertyFetcher exceptionFetcher = new("Exception"); + private readonly PropertyFetcher exceptionNumberFetcher = new("Number"); private readonly SqlClientTraceInstrumentationOptions options; public SqlClientDiagnosticListener(string sourceName, SqlClientTraceInstrumentationOptions? options) @@ -210,6 +212,13 @@ public override void OnEventWritten(string name, object? payload) { if (this.exceptionFetcher.TryFetch(payload, out Exception? exception) && exception != null) { + activity.AddTag(SemanticConventions.AttributeErrorType, exception.GetType().FullName); + + if (this.exceptionNumberFetcher.TryFetch(exception, out var exceptionNumber)) + { + activity.AddTag(SemanticConventions.AttributeDbResponseStatusCode, exceptionNumber.ToString(CultureInfo.InvariantCulture)); + } + activity.SetStatus(ActivityStatusCode.Error, exception.Message); if (this.options.RecordException) From b6e9cff7940ca8e4dc2183ea48bd8ae3bb271607 Mon Sep 17 00:00:00 2001 From: unknown <3676547+alanwest@users.noreply.github.com> Date: Wed, 30 Oct 2024 12:10:51 -0700 Subject: [PATCH 2/4] Fix --- src/Shared/SemanticConventions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Shared/SemanticConventions.cs b/src/Shared/SemanticConventions.cs index cd3847cc2a..fe87612551 100644 --- a/src/Shared/SemanticConventions.cs +++ b/src/Shared/SemanticConventions.cs @@ -141,7 +141,7 @@ internal static class SemanticConventions public const string AttributeDbCollectionName = "db.collection.name"; public const string AttributeDbNamespace = "db.namespace"; public const string AttributeDbOperationName = "db.operation.name"; - public const string AttributeResponseStatusCode = "db.response.status_code"; + 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"; From c35133f89d805a360af5d1a83419b93d800225ea Mon Sep 17 00:00:00 2001 From: unknown <3676547+alanwest@users.noreply.github.com> Date: Wed, 30 Oct 2024 16:12:44 -0700 Subject: [PATCH 3/4] .NET Framework --- .../SqlEventSourceListener.netfx.cs | 10 ++++++++-- .../SqlClientIntegrationTests.cs | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlEventSourceListener.netfx.cs b/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlEventSourceListener.netfx.cs index 19a6f7526d..371cae85a3 100644 --- a/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlEventSourceListener.netfx.cs +++ b/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlEventSourceListener.netfx.cs @@ -175,8 +175,14 @@ private void OnEndExecute(EventWrittenEventArgs eventData) { if ((compositeState & 0b010) == 0b010) { - var errorText = $"SqlExceptionNumber {eventData.Payload[2]} thrown."; - activity.SetStatus(ActivityStatusCode.Error, errorText); + var errorNumber = $"{eventData.Payload[2]}"; + activity.SetStatus(ActivityStatusCode.Error, errorNumber); + activity.SetTag(SemanticConventions.AttributeDbResponseStatusCode, errorNumber); + + var exceptionType = eventData.EventSource.Name == MdsEventSourceName + ? "Microsoft.Data.SqlClient.SqlException" + : "System.Data.SqlClient.SqlException"; + activity.SetTag(SemanticConventions.AttributeErrorType, exceptionType); } else { diff --git a/test/OpenTelemetry.Instrumentation.SqlClient.Tests/SqlClientIntegrationTests.cs b/test/OpenTelemetry.Instrumentation.SqlClient.Tests/SqlClientIntegrationTests.cs index 9086c31490..a22e70cac9 100644 --- a/test/OpenTelemetry.Instrumentation.SqlClient.Tests/SqlClientIntegrationTests.cs +++ b/test/OpenTelemetry.Instrumentation.SqlClient.Tests/SqlClientIntegrationTests.cs @@ -93,6 +93,23 @@ public void SuccessfulCommandTest( SqlClientTests.VerifyActivityData(commandType, commandText, captureStoredProcedureCommandName, captureTextCommandContent, isFailure, recordException, shouldEnrich, activity); SqlClientTests.VerifySamplingParameters(sampler.LatestSamplingParameters); + + if (isFailure) + { +#if NET + var status = activity.GetStatus(); + Assert.Equal(ActivityStatusCode.Error, activity.Status); + Assert.Equal("Divide by zero error encountered.", activity.StatusDescription); + Assert.EndsWith("SqlException", activity.GetTagValue(SemanticConventions.AttributeErrorType) as string); + Assert.Equal("8134", activity.GetTagValue(SemanticConventions.AttributeDbResponseStatusCode)); +#else + var status = activity.GetStatus(); + Assert.Equal(ActivityStatusCode.Error, activity.Status); + Assert.Equal("8134", activity.StatusDescription); + Assert.EndsWith("SqlException", activity.GetTagValue(SemanticConventions.AttributeErrorType) as string); + Assert.Equal("8134", activity.GetTagValue(SemanticConventions.AttributeDbResponseStatusCode)); +#endif + } } private string GetConnectionString() From 35f20b7f131cd3425acd51af20b2f4ab2bc9ad48 Mon Sep 17 00:00:00 2001 From: unknown <3676547+alanwest@users.noreply.github.com> Date: Wed, 30 Oct 2024 16:18:48 -0700 Subject: [PATCH 4/4] Update changelog --- src/OpenTelemetry.Instrumentation.SqlClient/CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/OpenTelemetry.Instrumentation.SqlClient/CHANGELOG.md b/src/OpenTelemetry.Instrumentation.SqlClient/CHANGELOG.md index bfc0dc4d1e..c71a82625a 100644 --- a/src/OpenTelemetry.Instrumentation.SqlClient/CHANGELOG.md +++ b/src/OpenTelemetry.Instrumentation.SqlClient/CHANGELOG.md @@ -25,7 +25,8 @@ semantic conventions for [spans](https://github.com/open-telemetry/semantic-conventions/blob/v1.28.0/docs/database/database-spans.md). ([#2229](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/2229), - [#2277](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/2277)) + [#2277](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/2277), + [#2262](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/2262)) * **Breaking change**: The `peer.service` and `server.socket.address` attributes are no longer emitted. Users should rely on the `server.address` attribute for the same information. Note that `server.address` is only included when