Don't fire DiagnosticSource.StopActivity in some cases (#9595)
- Don't fire the event if DiagnosticSource.StartActivity was never called. This avoids allocating the anonymous object and extra strings.
This commit is contained in:
parent
f0ea4fc8a1
commit
667f7ca491
|
|
@ -62,6 +62,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal
|
||||||
public long StartTimestamp { get; set; }
|
public long StartTimestamp { get; set; }
|
||||||
public bool EventLogEnabled { get; set; }
|
public bool EventLogEnabled { get; set; }
|
||||||
public Activity Activity { get; set; }
|
public Activity Activity { get; set; }
|
||||||
|
internal bool HasDiagnosticListener { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,8 @@ namespace Microsoft.AspNetCore.Hosting.Internal
|
||||||
|
|
||||||
if (loggingEnabled || (diagnosticListenerEnabled && _diagnosticListener.IsEnabled(ActivityName, httpContext)))
|
if (loggingEnabled || (diagnosticListenerEnabled && _diagnosticListener.IsEnabled(ActivityName, httpContext)))
|
||||||
{
|
{
|
||||||
context.Activity = StartActivity(httpContext);
|
context.Activity = StartActivity(httpContext, out var hasDiagnosticListener);
|
||||||
|
context.HasDiagnosticListener = hasDiagnosticListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (diagnosticListenerEnabled)
|
if (diagnosticListenerEnabled)
|
||||||
|
|
@ -132,7 +133,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal
|
||||||
// Always stop activity if it was started
|
// Always stop activity if it was started
|
||||||
if (activity != null)
|
if (activity != null)
|
||||||
{
|
{
|
||||||
StopActivity(httpContext, activity);
|
StopActivity(httpContext, activity, context.HasDiagnosticListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.EventLogEnabled && exception != null)
|
if (context.EventLogEnabled && exception != null)
|
||||||
|
|
@ -229,9 +230,10 @@ namespace Microsoft.AspNetCore.Hosting.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
private Activity StartActivity(HttpContext httpContext)
|
private Activity StartActivity(HttpContext httpContext, out bool hasDiagnosticListener)
|
||||||
{
|
{
|
||||||
var activity = new Activity(ActivityName);
|
var activity = new Activity(ActivityName);
|
||||||
|
hasDiagnosticListener = false;
|
||||||
|
|
||||||
var headers = httpContext.Request.Headers;
|
var headers = httpContext.Request.Headers;
|
||||||
if (!headers.TryGetValue(HeaderNames.TraceParent, out var requestId))
|
if (!headers.TryGetValue(HeaderNames.TraceParent, out var requestId))
|
||||||
|
|
@ -266,6 +268,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal
|
||||||
|
|
||||||
if (_diagnosticListener.IsEnabled(ActivityStartKey))
|
if (_diagnosticListener.IsEnabled(ActivityStartKey))
|
||||||
{
|
{
|
||||||
|
hasDiagnosticListener = true;
|
||||||
_diagnosticListener.StartActivity(activity, new { HttpContext = httpContext });
|
_diagnosticListener.StartActivity(activity, new { HttpContext = httpContext });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -277,9 +280,16 @@ namespace Microsoft.AspNetCore.Hosting.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
private void StopActivity(HttpContext httpContext, Activity activity)
|
private void StopActivity(HttpContext httpContext, Activity activity, bool hasDiagnosticListener)
|
||||||
{
|
{
|
||||||
_diagnosticListener.StopActivity(activity, new { HttpContext = httpContext });
|
if (hasDiagnosticListener)
|
||||||
|
{
|
||||||
|
_diagnosticListener.StopActivity(activity, new { HttpContext = httpContext });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
activity.Stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,51 @@ namespace Microsoft.AspNetCore.Hosting.Tests
|
||||||
Assert.Equal(Activity.Current.Id, pairs["ActivityId"].ToString());
|
Assert.Equal(Activity.Current.Id, pairs["ActivityId"].ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ActivityStopDoesNotFireIfNoListenerAttachedForStart()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var diagnosticSource = new DiagnosticListener("DummySource");
|
||||||
|
var logger = new LoggerWithScopes(isEnabled: true);
|
||||||
|
var hostingApplication = CreateApplication(out var features, diagnosticSource: diagnosticSource, logger: logger);
|
||||||
|
var startFired = false;
|
||||||
|
var stopFired = false;
|
||||||
|
|
||||||
|
diagnosticSource.Subscribe(new CallbackDiagnosticListener(pair =>
|
||||||
|
{
|
||||||
|
// This should not fire
|
||||||
|
if (pair.Key == "Microsoft.AspNetCore.Hosting.HttpRequestIn.Start")
|
||||||
|
{
|
||||||
|
startFired = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This should not fire
|
||||||
|
if (pair.Key == "Microsoft.AspNetCore.Hosting.HttpRequestIn.Stop")
|
||||||
|
{
|
||||||
|
stopFired = true;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
(s, o, arg3) =>
|
||||||
|
{
|
||||||
|
// The events are off
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var context = hostingApplication.CreateContext(features);
|
||||||
|
|
||||||
|
Assert.Single(logger.Scopes);
|
||||||
|
var pairs = ((IReadOnlyList<KeyValuePair<string, object>>)logger.Scopes[0]).ToDictionary(p => p.Key, p => p.Value);
|
||||||
|
Assert.Equal(Activity.Current.Id, pairs["ActivityId"].ToString());
|
||||||
|
|
||||||
|
hostingApplication.DisposeContext(context, exception: null);
|
||||||
|
|
||||||
|
Assert.False(startFired);
|
||||||
|
Assert.False(stopFired);
|
||||||
|
Assert.Null(Activity.Current);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ActivityIsNotCreatedWhenIsEnabledForActivityIsFalse()
|
public void ActivityIsNotCreatedWhenIsEnabledForActivityIsFalse()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue