diff --git a/src/Hosting/Hosting/src/Internal/HostingApplicationDiagnostics.cs b/src/Hosting/Hosting/src/Internal/HostingApplicationDiagnostics.cs index f7735093d20d..5b4f058d6515 100644 --- a/src/Hosting/Hosting/src/Internal/HostingApplicationDiagnostics.cs +++ b/src/Hosting/Hosting/src/Internal/HostingApplicationDiagnostics.cs @@ -24,6 +24,9 @@ internal class HostingApplicationDiagnostics private const string DeprecatedDiagnosticsEndRequestKey = "Microsoft.AspNetCore.Hosting.EndRequest"; private const string DiagnosticsUnhandledExceptionKey = "Microsoft.AspNetCore.Hosting.UnhandledException"; + private const string ActivitySourceName = "Microsoft.AspNetCore.Hosting"; + private static readonly ActivitySource _activitySource = new ActivitySource(ActivitySourceName); + private readonly DiagnosticListener _diagnosticListener; private readonly ILogger _logger; @@ -46,11 +49,13 @@ public void BeginRequest(HttpContext httpContext, HostingApplication.Context con } var diagnosticListenerEnabled = _diagnosticListener.IsEnabled(); + var diagnosticListenerActivityCreationEnabled = (diagnosticListenerEnabled && _diagnosticListener.IsEnabled(ActivityName, httpContext)); var loggingEnabled = _logger.IsEnabled(LogLevel.Critical); - if (loggingEnabled || (diagnosticListenerEnabled && _diagnosticListener.IsEnabled(ActivityName, httpContext))) + + if (loggingEnabled || diagnosticListenerActivityCreationEnabled || _activitySource.HasListeners()) { - context.Activity = StartActivity(httpContext, out var hasDiagnosticListener); + context.Activity = StartActivity(httpContext, loggingEnabled, diagnosticListenerActivityCreationEnabled, out var hasDiagnosticListener); context.HasDiagnosticListener = hasDiagnosticListener; } @@ -245,11 +250,20 @@ private static void RecordRequestStartEventLog(HttpContext httpContext) } [MethodImpl(MethodImplOptions.NoInlining)] - private Activity StartActivity(HttpContext httpContext, out bool hasDiagnosticListener) + private Activity? StartActivity(HttpContext httpContext, bool loggingEnabled, bool diagnosticListenerActivityCreationEnabled, out bool hasDiagnosticListener) { - var activity = new Activity(ActivityName); + var activity = _activitySource.CreateActivity(ActivityName, ActivityKind.Server); + if (activity is null && (loggingEnabled || diagnosticListenerActivityCreationEnabled)) + { + activity = new Activity(ActivityName); + } hasDiagnosticListener = false; + if (activity is null) + { + return null; + } + var headers = httpContext.Request.Headers; if (!headers.TryGetValue(HeaderNames.TraceParent, out var requestId)) { diff --git a/src/Hosting/Hosting/test/HostingApplicationDiagnosticsTests.cs b/src/Hosting/Hosting/test/HostingApplicationDiagnosticsTests.cs index 92f1f2f9286c..6fc75016976d 100644 --- a/src/Hosting/Hosting/test/HostingApplicationDiagnosticsTests.cs +++ b/src/Hosting/Hosting/test/HostingApplicationDiagnosticsTests.cs @@ -362,6 +362,7 @@ public void ActivityBaggagePrefersW3CBaggageHeaderName() Assert.Contains(Activity.Current.Baggage, pair => pair.Key == "Key2" && pair.Value == "value4"); } + [Fact] public void ActivityBaggagePreservesItemsOrder() { @@ -465,7 +466,7 @@ public void ActivityTraceParentAndTraceStateFromHeaders() } [Fact] - public void ActivityOnExportHookIsCalled() + public void ActivityOnImportHookIsCalled() { var diagnosticListener = new DiagnosticListener("DummySource"); var hostingApplication = CreateApplication(out var features, diagnosticListener: diagnosticListener); @@ -492,6 +493,34 @@ public void ActivityOnExportHookIsCalled() Assert.True(Activity.Current.Recorded); } + [Fact] + public void ActivityListenersAreCalled() + { + var hostingApplication = CreateApplication(out var features); + using var listener = new ActivityListener + { + ShouldListenTo = activitySource => true, + Sample = (ref ActivityCreationOptions _) => ActivitySamplingResult.AllData, + ActivityStarted = activity => + { + Assert.Equal("0123456789abcdef", Activity.Current.ParentSpanId.ToHexString()); + } + }; + + ActivitySource.AddActivityListener(listener); + + features.Set(new HttpRequestFeature() + { + Headers = new HeaderDictionary() + { + {"traceparent", "00-0123456789abcdef0123456789abcdef-0123456789abcdef-01"}, + {"tracestate", "TraceState1"}, + {"baggage", "Key1=value1, Key2=value2"} + } + }); + hostingApplication.CreateContext(features); + } + private static void AssertProperty(object o, string name) {