From 1627ef1d3a39d9f7ec8e7df752af379ae12f004f Mon Sep 17 00:00:00 2001 From: Nikita Kazmin Date: Sun, 16 Mar 2025 19:59:06 +0300 Subject: [PATCH 1/7] Add basic testing for tracing --- src/Npgsql/NpgsqlActivitySource.cs | 1 + test/Npgsql.Tests/TracingTests.cs | 68 ++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 test/Npgsql.Tests/TracingTests.cs diff --git a/src/Npgsql/NpgsqlActivitySource.cs b/src/Npgsql/NpgsqlActivitySource.cs index 667728a89a..9534b1bd27 100644 --- a/src/Npgsql/NpgsqlActivitySource.cs +++ b/src/Npgsql/NpgsqlActivitySource.cs @@ -117,6 +117,7 @@ internal static void SetException(Activity activity, Exception ex, bool escaped { { "exception.type", ex.GetType().FullName }, { "exception.message", ex.Message }, + // TODO: only set ex.StackTrace? { "exception.stacktrace", ex.ToString() }, { "exception.escaped", escaped } }; diff --git a/test/Npgsql.Tests/TracingTests.cs b/test/Npgsql.Tests/TracingTests.cs new file mode 100644 index 0000000000..9938e55751 --- /dev/null +++ b/test/Npgsql.Tests/TracingTests.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading.Tasks; +using NUnit.Framework; + +namespace Npgsql.Tests; + +[NonParallelizable] +public class TracingTests(MultiplexingMode multiplexingMode) : MultiplexingTestBase(multiplexingMode) +{ + [Test] + public async Task Basic([Values] bool async) + { + if (IsMultiplexing && !async) + return; + + var activities = new List(); + + using var activityListener = new ActivityListener(); + activityListener.ShouldListenTo = source => source.Name == "Npgsql"; + activityListener.Sample = (ref ActivityCreationOptions _) => ActivitySamplingResult.AllDataAndRecorded; + activityListener.ActivityStopped = activity => activities.Add(activity); + ActivitySource.AddActivityListener(activityListener); + + await using var dataSource = CreateDataSource(); + await using var conn = await OpenConnectionAsync(); + if (async) + await conn.ExecuteScalarAsync("SELECT 42"); + else + conn.ExecuteScalar("SELECT 42"); + + Assert.That(activities.Count, Is.EqualTo(1)); + var activity = activities[0]; + Assert.That(activity.DisplayName, Is.EqualTo(conn.Settings.Database)); + Assert.That(activity.OperationName, Is.EqualTo(conn.Settings.Database)); + // TODO: set status code? + Assert.That(activity.Status, Is.EqualTo(ActivityStatusCode.Unset)); + + Assert.That(activity.Events.Count(), Is.EqualTo(1)); + var firstResponseEvent = activity.Events.First(); + Assert.That(firstResponseEvent.Name, Is.EqualTo("received-first-response")); + + var queryTag = activity.TagObjects.First(x => x.Key == "db.statement"); + Assert.That(queryTag.Value, Is.EqualTo("SELECT 42")); + + var systemTag = activity.TagObjects.First(x => x.Key == "db.system"); + Assert.That(systemTag.Value, Is.EqualTo("postgresql")); + + var userTag = activity.TagObjects.First(x => x.Key == "db.user"); + Assert.That(userTag.Value, Is.EqualTo(conn.Settings.Username)); + + var dbNameTag = activity.TagObjects.First(x => x.Key == "db.name"); + Assert.That(dbNameTag.Value, Is.EqualTo(conn.Settings.Database)); + + var connStringTag = activity.TagObjects.First(x => x.Key == "db.connection_string"); + Assert.That(connStringTag.Value, Is.EqualTo(conn.ConnectionString)); + + if (!IsMultiplexing) + { + var connIDTag = activity.TagObjects.First(x => x.Key == "db.connection_id"); + Assert.That(connIDTag.Value, Is.EqualTo(conn.ProcessID)); + } + + var statusTag = activity.TagObjects.First(x => x.Key == "otel.status_code"); + Assert.That(statusTag.Value, Is.EqualTo("OK")); + } +} From c8af84195337e5e08512e110ccce58390549b793 Mon Sep 17 00:00:00 2001 From: Nikita Kazmin Date: Mon, 17 Mar 2025 14:32:51 +0300 Subject: [PATCH 2/7] Add a few more tests --- src/Npgsql/Internal/NpgsqlConnector.cs | 1 - src/Npgsql/NpgsqlCommand.cs | 10 +- test/Npgsql.Tests/TracingTests.cs | 132 ++++++++++++++++++++++++- 3 files changed, 137 insertions(+), 6 deletions(-) diff --git a/src/Npgsql/Internal/NpgsqlConnector.cs b/src/Npgsql/Internal/NpgsqlConnector.cs index 8208e7386c..dffe542ff0 100644 --- a/src/Npgsql/Internal/NpgsqlConnector.cs +++ b/src/Npgsql/Internal/NpgsqlConnector.cs @@ -1177,7 +1177,6 @@ async Task MultiplexingReadLoop() // We have a resultset for the command - hand back control to the command (which will // return it to the user) - command.TraceReceivedFirstResponse(DataSource.Configuration.TracingOptions); ReaderCompleted.Reset(); command.ExecutionCompletion.SetResult(this); diff --git a/src/Npgsql/NpgsqlCommand.cs b/src/Npgsql/NpgsqlCommand.cs index f1ef8bb832..86748a1b16 100644 --- a/src/Npgsql/NpgsqlCommand.cs +++ b/src/Npgsql/NpgsqlCommand.cs @@ -1597,6 +1597,8 @@ internal virtual async ValueTask ExecuteReader(bool async, Com connector.CurrentReader = reader; await reader.NextResultAsync(cancellationToken).ConfigureAwait(false); + TraceReceivedFirstResponse(connector.DataSource.Configuration.TracingOptions); + return reader; } } @@ -1718,12 +1720,12 @@ internal void TraceCommandStart(NpgsqlConnectionStringBuilder settings, NpgsqlTr ? tracingOptions.BatchFilter?.Invoke(WrappingBatch) ?? true : tracingOptions.CommandFilter?.Invoke(this) ?? true; - var spanName = WrappingBatch is not null - ? tracingOptions.BatchSpanNameProvider?.Invoke(WrappingBatch) - : tracingOptions.CommandSpanNameProvider?.Invoke(this); - if (enableTracing) { + var spanName = WrappingBatch is not null + ? tracingOptions.BatchSpanNameProvider?.Invoke(WrappingBatch) + : tracingOptions.CommandSpanNameProvider?.Invoke(this); + CurrentActivity = NpgsqlActivitySource.CommandStart( settings, WrappingBatch is not null ? GetBatchFullCommandText() : CommandText, diff --git a/test/Npgsql.Tests/TracingTests.cs b/test/Npgsql.Tests/TracingTests.cs index 9938e55751..efc0d42c98 100644 --- a/test/Npgsql.Tests/TracingTests.cs +++ b/test/Npgsql.Tests/TracingTests.cs @@ -24,7 +24,7 @@ public async Task Basic([Values] bool async) ActivitySource.AddActivityListener(activityListener); await using var dataSource = CreateDataSource(); - await using var conn = await OpenConnectionAsync(); + await using var conn = await dataSource.OpenConnectionAsync(); if (async) await conn.ExecuteScalarAsync("SELECT 42"); else @@ -41,6 +41,9 @@ public async Task Basic([Values] bool async) var firstResponseEvent = activity.Events.First(); Assert.That(firstResponseEvent.Name, Is.EqualTo("received-first-response")); + var expectedTagCount = conn.Settings.Port == 5432 ? 10 : 11; + Assert.That(activity.TagObjects.Count(), Is.EqualTo(expectedTagCount)); + var queryTag = activity.TagObjects.First(x => x.Key == "db.statement"); Assert.That(queryTag.Value, Is.EqualTo("SELECT 42")); @@ -65,4 +68,131 @@ public async Task Basic([Values] bool async) var statusTag = activity.TagObjects.First(x => x.Key == "otel.status_code"); Assert.That(statusTag.Value, Is.EqualTo("OK")); } + + [Test] + public async Task Error([Values] bool async) + { + if (IsMultiplexing && !async) + return; + + var activities = new List(); + + using var activityListener = new ActivityListener(); + activityListener.ShouldListenTo = source => source.Name == "Npgsql"; + activityListener.Sample = (ref ActivityCreationOptions _) => ActivitySamplingResult.AllDataAndRecorded; + activityListener.ActivityStopped = activity => activities.Add(activity); + ActivitySource.AddActivityListener(activityListener); + + await using var dataSource = CreateDataSource(); + await using var conn = await dataSource.OpenConnectionAsync(); + if (async) + Assert.ThrowsAsync(async () => await conn.ExecuteScalarAsync("SELECT * FROM non_existing_table")); + else + Assert.Throws(() => conn.ExecuteScalar("SELECT * FROM non_existing_table")); + + Assert.That(activities.Count, Is.EqualTo(1)); + var activity = activities[0]; + Assert.That(activity.DisplayName, Is.EqualTo(conn.Settings.Database)); + Assert.That(activity.OperationName, Is.EqualTo(conn.Settings.Database)); + // TODO: set status code? + Assert.That(activity.Status, Is.EqualTo(ActivityStatusCode.Unset)); + + Assert.That(activity.Events.Count(), Is.EqualTo(1)); + var exceptionEvent = activity.Events.First(); + Assert.That(exceptionEvent.Name, Is.EqualTo("exception")); + + Assert.That(exceptionEvent.Tags.Count(), Is.EqualTo(4)); + + var exceptionTypeTag = exceptionEvent.Tags.First(x => x.Key == "exception.type"); + Assert.That(exceptionTypeTag.Value, Is.EqualTo("Npgsql.PostgresException")); + + var exceptionMessageTag = exceptionEvent.Tags.First(x => x.Key == "exception.message"); + StringAssert.Contains("relation \"non_existing_table\" does not exist", (string)exceptionMessageTag.Value!); + + var exceptionStacktraceTag = exceptionEvent.Tags.First(x => x.Key == "exception.stacktrace"); + // TODO: StackTrace shouldn't contain exception message? + StringAssert.Contains("relation \"non_existing_table\" does not exist", (string)exceptionStacktraceTag.Value!); + + var exceptionEscapedTag = exceptionEvent.Tags.First(x => x.Key == "exception.escaped"); + Assert.That(exceptionEscapedTag.Value, Is.True); + + var expectedTagCount = conn.Settings.Port == 5432 ? 11 : 12; + Assert.That(activity.TagObjects.Count(), Is.EqualTo(expectedTagCount)); + + var queryTag = activity.TagObjects.First(x => x.Key == "db.statement"); + Assert.That(queryTag.Value, Is.EqualTo("SELECT * FROM non_existing_table")); + + var systemTag = activity.TagObjects.First(x => x.Key == "db.system"); + Assert.That(systemTag.Value, Is.EqualTo("postgresql")); + + var userTag = activity.TagObjects.First(x => x.Key == "db.user"); + Assert.That(userTag.Value, Is.EqualTo(conn.Settings.Username)); + + var dbNameTag = activity.TagObjects.First(x => x.Key == "db.name"); + Assert.That(dbNameTag.Value, Is.EqualTo(conn.Settings.Database)); + + var connStringTag = activity.TagObjects.First(x => x.Key == "db.connection_string"); + Assert.That(connStringTag.Value, Is.EqualTo(conn.ConnectionString)); + + if (!IsMultiplexing) + { + var connIDTag = activity.TagObjects.First(x => x.Key == "db.connection_id"); + Assert.That(connIDTag.Value, Is.EqualTo(conn.ProcessID)); + } + + var statusTag = activity.TagObjects.First(x => x.Key == "otel.status_code"); + Assert.That(statusTag.Value, Is.EqualTo("ERROR")); + + var descriptionTag = activity.TagObjects.First(x => x.Key == "otel.status_description"); + Assert.That(descriptionTag.Value, Is.EqualTo(PostgresErrorCodes.UndefinedTable)); + } + + [Test] + public async Task Configure_tracing([Values] bool async) + { + if (IsMultiplexing && !async) + return; + + var activities = new List(); + + using var activityListener = new ActivityListener(); + activityListener.ShouldListenTo = source => source.Name == "Npgsql"; + activityListener.Sample = (ref ActivityCreationOptions _) => ActivitySamplingResult.AllDataAndRecorded; + activityListener.ActivityStopped = activity => activities.Add(activity); + ActivitySource.AddActivityListener(activityListener); + + var dataSourceBuilder = CreateDataSourceBuilder(); + dataSourceBuilder.ConfigureTracing(options => + { + options + .EnableFirstResponseEvent(enable: false) + .ConfigureCommandFilter(cmd => cmd.CommandText.Contains('2')) + .ConfigureCommandSpanNameProvider(_ => "unknown_query") + .ConfigureCommandEnrichmentCallback((activity, _) => activity.AddTag("custom_tag", "custom_value")); + }); + await using var dataSource = dataSourceBuilder.Build(); + await using var conn = await dataSource.OpenConnectionAsync(); + + if (async) + await conn.ExecuteScalarAsync("SELECT 1"); + else + conn.ExecuteScalar("SELECT 1"); + + Assert.That(activities.Count, Is.EqualTo(0)); + + if (async) + await conn.ExecuteScalarAsync("SELECT 2"); + else + conn.ExecuteScalar("SELECT 2"); + + Assert.That(activities.Count, Is.EqualTo(1)); + var activity = activities[0]; + Assert.That(activity.DisplayName, Is.EqualTo("unknown_query")); + Assert.That(activity.OperationName, Is.EqualTo("unknown_query")); + + Assert.That(activity.Events.Count(), Is.EqualTo(0)); + + var customTag = activity.TagObjects.First(x => x.Key == "custom_tag"); + Assert.That(customTag.Value, Is.EqualTo("custom_value")); + } } From be733c45411fa8f5d41570f066ac2931c1cd4288 Mon Sep 17 00:00:00 2001 From: Nikita Kazmin Date: Mon, 17 Mar 2025 14:54:23 +0300 Subject: [PATCH 3/7] Also test batches --- test/Npgsql.Tests/TracingTests.cs | 54 +++++++++++++++++++------------ 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/test/Npgsql.Tests/TracingTests.cs b/test/Npgsql.Tests/TracingTests.cs index efc0d42c98..b0cb5c257b 100644 --- a/test/Npgsql.Tests/TracingTests.cs +++ b/test/Npgsql.Tests/TracingTests.cs @@ -10,7 +10,7 @@ namespace Npgsql.Tests; public class TracingTests(MultiplexingMode multiplexingMode) : MultiplexingTestBase(multiplexingMode) { [Test] - public async Task Basic([Values] bool async) + public async Task Basic([Values] bool async, [Values] bool batch) { if (IsMultiplexing && !async) return; @@ -25,10 +25,7 @@ public async Task Basic([Values] bool async) await using var dataSource = CreateDataSource(); await using var conn = await dataSource.OpenConnectionAsync(); - if (async) - await conn.ExecuteScalarAsync("SELECT 42"); - else - conn.ExecuteScalar("SELECT 42"); + await ExecuteScalar(conn, async, batch, "SELECT 42"); Assert.That(activities.Count, Is.EqualTo(1)); var activity = activities[0]; @@ -70,7 +67,7 @@ public async Task Basic([Values] bool async) } [Test] - public async Task Error([Values] bool async) + public async Task Error([Values] bool async, [Values] bool batch) { if (IsMultiplexing && !async) return; @@ -85,10 +82,7 @@ public async Task Error([Values] bool async) await using var dataSource = CreateDataSource(); await using var conn = await dataSource.OpenConnectionAsync(); - if (async) - Assert.ThrowsAsync(async () => await conn.ExecuteScalarAsync("SELECT * FROM non_existing_table")); - else - Assert.Throws(() => conn.ExecuteScalar("SELECT * FROM non_existing_table")); + Assert.ThrowsAsync(async () => await ExecuteScalar(conn, async, batch, "SELECT * FROM non_existing_table")); Assert.That(activities.Count, Is.EqualTo(1)); var activity = activities[0]; @@ -148,7 +142,7 @@ public async Task Error([Values] bool async) } [Test] - public async Task Configure_tracing([Values] bool async) + public async Task Configure_tracing([Values] bool async, [Values] bool batch) { if (IsMultiplexing && !async) return; @@ -167,23 +161,20 @@ public async Task Configure_tracing([Values] bool async) options .EnableFirstResponseEvent(enable: false) .ConfigureCommandFilter(cmd => cmd.CommandText.Contains('2')) + .ConfigureBatchFilter(batch => batch.BatchCommands[0].CommandText.Contains('2')) .ConfigureCommandSpanNameProvider(_ => "unknown_query") - .ConfigureCommandEnrichmentCallback((activity, _) => activity.AddTag("custom_tag", "custom_value")); + .ConfigureBatchSpanNameProvider(_ => "unknown_query") + .ConfigureCommandEnrichmentCallback((activity, _) => activity.AddTag("custom_tag", "custom_value")) + .ConfigureBatchEnrichmentCallback((activity, _) => activity.AddTag("custom_tag", "custom_value")); }); await using var dataSource = dataSourceBuilder.Build(); await using var conn = await dataSource.OpenConnectionAsync(); - if (async) - await conn.ExecuteScalarAsync("SELECT 1"); - else - conn.ExecuteScalar("SELECT 1"); + await ExecuteScalar(conn, async, batch, "SELECT 1"); Assert.That(activities.Count, Is.EqualTo(0)); - if (async) - await conn.ExecuteScalarAsync("SELECT 2"); - else - conn.ExecuteScalar("SELECT 2"); + await ExecuteScalar(conn, async, batch, "SELECT 2"); Assert.That(activities.Count, Is.EqualTo(1)); var activity = activities[0]; @@ -195,4 +186,27 @@ public async Task Configure_tracing([Values] bool async) var customTag = activity.TagObjects.First(x => x.Key == "custom_tag"); Assert.That(customTag.Value, Is.EqualTo("custom_value")); } + + async Task ExecuteScalar(NpgsqlConnection connection, bool async, bool isBatch, string query) + { + if (!isBatch) + { + if (async) + return await connection.ExecuteScalarAsync(query); + else + return connection.ExecuteScalar(query); + } + else + { + await using var batch = connection.CreateBatch(); + var batchCommand = batch.CreateBatchCommand(); + batchCommand.CommandText = query; + batch.BatchCommands.Add(batchCommand); + + if (async) + return await batch.ExecuteScalarAsync(); + else + return batch.ExecuteScalar(); + } + } } From ddb3b66dc7fcd67208dd37d666728dc6f3cdcad6 Mon Sep 17 00:00:00 2001 From: Nikita Kazmin Date: Mon, 17 Mar 2025 18:11:33 +0300 Subject: [PATCH 4/7] Set status on Activity --- src/Npgsql/NpgsqlActivitySource.cs | 7 +++++-- test/Npgsql.Tests/TracingTests.cs | 6 +++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Npgsql/NpgsqlActivitySource.cs b/src/Npgsql/NpgsqlActivitySource.cs index 9534b1bd27..c85504ec5d 100644 --- a/src/Npgsql/NpgsqlActivitySource.cs +++ b/src/Npgsql/NpgsqlActivitySource.cs @@ -108,23 +108,26 @@ internal static void ReceivedFirstResponse(Activity activity, NpgsqlTracingOptio internal static void CommandStop(Activity activity) { activity.SetTag("otel.status_code", "OK"); + activity.SetStatus(ActivityStatusCode.Ok); activity.Dispose(); } internal static void SetException(Activity activity, Exception ex, bool escaped = true) { + // TODO: We can instead use Activity.AddException whenever we start using .NET 9 var tags = new ActivityTagsCollection { { "exception.type", ex.GetType().FullName }, { "exception.message", ex.Message }, - // TODO: only set ex.StackTrace? { "exception.stacktrace", ex.ToString() }, { "exception.escaped", escaped } }; var activityEvent = new ActivityEvent("exception", tags: tags); activity.AddEvent(activityEvent); activity.SetTag("otel.status_code", "ERROR"); - activity.SetTag("otel.status_description", ex is PostgresException pgEx ? pgEx.SqlState : ex.Message); + var statusDescription = ex is PostgresException pgEx ? pgEx.SqlState : ex.Message; + activity.SetTag("otel.status_description", statusDescription); + activity.SetStatus(ActivityStatusCode.Error, statusDescription); activity.Dispose(); } } diff --git a/test/Npgsql.Tests/TracingTests.cs b/test/Npgsql.Tests/TracingTests.cs index b0cb5c257b..7e8685bd50 100644 --- a/test/Npgsql.Tests/TracingTests.cs +++ b/test/Npgsql.Tests/TracingTests.cs @@ -32,7 +32,7 @@ public async Task Basic([Values] bool async, [Values] bool batch) Assert.That(activity.DisplayName, Is.EqualTo(conn.Settings.Database)); Assert.That(activity.OperationName, Is.EqualTo(conn.Settings.Database)); // TODO: set status code? - Assert.That(activity.Status, Is.EqualTo(ActivityStatusCode.Unset)); + Assert.That(activity.Status, Is.EqualTo(ActivityStatusCode.Ok)); Assert.That(activity.Events.Count(), Is.EqualTo(1)); var firstResponseEvent = activity.Events.First(); @@ -88,8 +88,8 @@ public async Task Error([Values] bool async, [Values] bool batch) var activity = activities[0]; Assert.That(activity.DisplayName, Is.EqualTo(conn.Settings.Database)); Assert.That(activity.OperationName, Is.EqualTo(conn.Settings.Database)); - // TODO: set status code? - Assert.That(activity.Status, Is.EqualTo(ActivityStatusCode.Unset)); + Assert.That(activity.Status, Is.EqualTo(ActivityStatusCode.Error)); + Assert.That(activity.StatusDescription, Is.EqualTo(PostgresErrorCodes.UndefinedTable)); Assert.That(activity.Events.Count(), Is.EqualTo(1)); var exceptionEvent = activity.Events.First(); From 0ad520f06a752fb9f964e15cdca295b1755176bc Mon Sep 17 00:00:00 2001 From: Nikita Kazmin Date: Wed, 19 Mar 2025 13:21:03 +0300 Subject: [PATCH 5/7] Do not set otel tags explicitly --- src/Npgsql/NpgsqlActivitySource.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Npgsql/NpgsqlActivitySource.cs b/src/Npgsql/NpgsqlActivitySource.cs index c85504ec5d..ce762cc642 100644 --- a/src/Npgsql/NpgsqlActivitySource.cs +++ b/src/Npgsql/NpgsqlActivitySource.cs @@ -107,7 +107,6 @@ internal static void ReceivedFirstResponse(Activity activity, NpgsqlTracingOptio internal static void CommandStop(Activity activity) { - activity.SetTag("otel.status_code", "OK"); activity.SetStatus(ActivityStatusCode.Ok); activity.Dispose(); } @@ -124,9 +123,7 @@ internal static void SetException(Activity activity, Exception ex, bool escaped }; var activityEvent = new ActivityEvent("exception", tags: tags); activity.AddEvent(activityEvent); - activity.SetTag("otel.status_code", "ERROR"); var statusDescription = ex is PostgresException pgEx ? pgEx.SqlState : ex.Message; - activity.SetTag("otel.status_description", statusDescription); activity.SetStatus(ActivityStatusCode.Error, statusDescription); activity.Dispose(); } From ceea7dd1517bd95e05bc10912ffd3d27788b7706 Mon Sep 17 00:00:00 2001 From: Nikita Kazmin Date: Wed, 19 Mar 2025 13:37:10 +0300 Subject: [PATCH 6/7] Fix tests --- test/Npgsql.Tests/TracingTests.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/Npgsql.Tests/TracingTests.cs b/test/Npgsql.Tests/TracingTests.cs index 7e8685bd50..6baf11c4c5 100644 --- a/test/Npgsql.Tests/TracingTests.cs +++ b/test/Npgsql.Tests/TracingTests.cs @@ -31,14 +31,13 @@ public async Task Basic([Values] bool async, [Values] bool batch) var activity = activities[0]; Assert.That(activity.DisplayName, Is.EqualTo(conn.Settings.Database)); Assert.That(activity.OperationName, Is.EqualTo(conn.Settings.Database)); - // TODO: set status code? Assert.That(activity.Status, Is.EqualTo(ActivityStatusCode.Ok)); Assert.That(activity.Events.Count(), Is.EqualTo(1)); var firstResponseEvent = activity.Events.First(); Assert.That(firstResponseEvent.Name, Is.EqualTo("received-first-response")); - var expectedTagCount = conn.Settings.Port == 5432 ? 10 : 11; + var expectedTagCount = conn.Settings.Port == 5432 ? 8 : 9; Assert.That(activity.TagObjects.Count(), Is.EqualTo(expectedTagCount)); var queryTag = activity.TagObjects.First(x => x.Key == "db.statement"); @@ -104,13 +103,12 @@ public async Task Error([Values] bool async, [Values] bool batch) StringAssert.Contains("relation \"non_existing_table\" does not exist", (string)exceptionMessageTag.Value!); var exceptionStacktraceTag = exceptionEvent.Tags.First(x => x.Key == "exception.stacktrace"); - // TODO: StackTrace shouldn't contain exception message? StringAssert.Contains("relation \"non_existing_table\" does not exist", (string)exceptionStacktraceTag.Value!); var exceptionEscapedTag = exceptionEvent.Tags.First(x => x.Key == "exception.escaped"); Assert.That(exceptionEscapedTag.Value, Is.True); - var expectedTagCount = conn.Settings.Port == 5432 ? 11 : 12; + var expectedTagCount = conn.Settings.Port == 5432 ? 9 : 10; Assert.That(activity.TagObjects.Count(), Is.EqualTo(expectedTagCount)); var queryTag = activity.TagObjects.First(x => x.Key == "db.statement"); From e01b3967ce58a87d5fd231d2bb16d3db1e760577 Mon Sep 17 00:00:00 2001 From: Nikita Kazmin Date: Wed, 19 Mar 2025 13:57:00 +0300 Subject: [PATCH 7/7] A few more test fixes --- test/Npgsql.Tests/TracingTests.cs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/test/Npgsql.Tests/TracingTests.cs b/test/Npgsql.Tests/TracingTests.cs index 6baf11c4c5..e3ff4a7c34 100644 --- a/test/Npgsql.Tests/TracingTests.cs +++ b/test/Npgsql.Tests/TracingTests.cs @@ -37,7 +37,7 @@ public async Task Basic([Values] bool async, [Values] bool batch) var firstResponseEvent = activity.Events.First(); Assert.That(firstResponseEvent.Name, Is.EqualTo("received-first-response")); - var expectedTagCount = conn.Settings.Port == 5432 ? 8 : 9; + var expectedTagCount = conn.Settings.Port == 5432 ? 9 : 10; Assert.That(activity.TagObjects.Count(), Is.EqualTo(expectedTagCount)); var queryTag = activity.TagObjects.First(x => x.Key == "db.statement"); @@ -60,9 +60,6 @@ public async Task Basic([Values] bool async, [Values] bool batch) var connIDTag = activity.TagObjects.First(x => x.Key == "db.connection_id"); Assert.That(connIDTag.Value, Is.EqualTo(conn.ProcessID)); } - - var statusTag = activity.TagObjects.First(x => x.Key == "otel.status_code"); - Assert.That(statusTag.Value, Is.EqualTo("OK")); } [Test] @@ -131,12 +128,6 @@ public async Task Error([Values] bool async, [Values] bool batch) var connIDTag = activity.TagObjects.First(x => x.Key == "db.connection_id"); Assert.That(connIDTag.Value, Is.EqualTo(conn.ProcessID)); } - - var statusTag = activity.TagObjects.First(x => x.Key == "otel.status_code"); - Assert.That(statusTag.Value, Is.EqualTo("ERROR")); - - var descriptionTag = activity.TagObjects.First(x => x.Key == "otel.status_description"); - Assert.That(descriptionTag.Value, Is.EqualTo(PostgresErrorCodes.UndefinedTable)); } [Test]