diff --git a/src/OpenTelemetry.Instrumentation.AspNet/Implementation/HttpInListener.cs b/src/OpenTelemetry.Instrumentation.AspNet/Implementation/HttpInListener.cs index 978ac36a87..fdfa979cd8 100644 --- a/src/OpenTelemetry.Instrumentation.AspNet/Implementation/HttpInListener.cs +++ b/src/OpenTelemetry.Instrumentation.AspNet/Implementation/HttpInListener.cs @@ -162,6 +162,7 @@ private void OnException(Activity activity, HttpContext context, Exception excep } activity.SetStatus(ActivityStatusCode.Error, exception.Message); + activity.SetTag(SemanticConventions.AttributeErrorType, exception.GetType().FullName); try { diff --git a/src/Shared/SemanticConventions.cs b/src/Shared/SemanticConventions.cs index d5abbaed54..0d9fe00f87 100644 --- a/src/Shared/SemanticConventions.cs +++ b/src/Shared/SemanticConventions.cs @@ -95,6 +95,7 @@ internal static class SemanticConventions public const string AttributeExceptionType = "exception.type"; public const string AttributeExceptionMessage = "exception.message"; public const string AttributeExceptionStacktrace = "exception.stacktrace"; + public const string AttributeErrorType = "error.type"; // v1.21.0 // https://github.com/open-telemetry/semantic-conventions/blob/v1.21.0/docs/http/http-metrics.md#http-server diff --git a/test/OpenTelemetry.Instrumentation.AspNet.Tests/HttpInListenerTests.cs b/test/OpenTelemetry.Instrumentation.AspNet.Tests/HttpInListenerTests.cs index 397aa723e9..63ce675401 100644 --- a/test/OpenTelemetry.Instrumentation.AspNet.Tests/HttpInListenerTests.cs +++ b/test/OpenTelemetry.Instrumentation.AspNet.Tests/HttpInListenerTests.cs @@ -34,7 +34,7 @@ public class HttpInListenerTests [InlineData("https://localhost:1843/subroute/10", "https", "/subroute/10", null, "localhost", 1843, "GET", "GET", null, 4, "subroute/{customerId}")] [InlineData("http://localhost/api/value", "http", "/api/value", null, "localhost", 80, "GET", "GET", null, 0, null, false, "/api/value")] // Request will be filtered [InlineData("http://localhost/api/value", "http", "/api/value", null, "localhost", 80, "GET", "GET", null, 0, null, false, "{ThrowException}")] // Filter user code will throw an exception - [InlineData("http://localhost/", "http", "/", null, "localhost", 80, "GET", "GET", null, 0, null, false, null, true)] // Test RecordException option + [InlineData("http://localhost/", "http", "/", null, "localhost", 80, "GET", "GET", null, 0, null, false, null, true, "System.InvalidOperationException")] // Test RecordException option public void AspNetRequestsAreCollectedSuccessfully( string url, string expectedUrlScheme, @@ -49,7 +49,8 @@ public void AspNetRequestsAreCollectedSuccessfully( string routeTemplate, bool setStatusToErrorInEnrich = false, string? filter = null, - bool recordException = false) + bool recordException = false, + string? expectedErrorType = null) { HttpContext.Current = RouteTestHelper.BuildHttpContext(url, routeType, routeTemplate, requestMethod); @@ -133,6 +134,7 @@ public void AspNetRequestsAreCollectedSuccessfully( Assert.Equal(expectedUrlQuery, span.GetTagValue("url.query")); Assert.Equal(expectedUrlScheme, span.GetTagValue("url.scheme")); Assert.Equal("Custom User Agent v1.2.3", span.GetTagValue("user_agent.original")); + Assert.Equal(expectedErrorType, span.GetTagValue("error.type")); if (recordException) { @@ -257,7 +259,8 @@ void EnrichAction(Activity activity, string method, object obj) break; - default: + case "OnException": + Assert.True(obj is Exception); break; } }