Use implicit logging scope for Activity (#22376)

* Revert "Hoist activity fields to the logging scope (#11211)"

This reverts commit f7a2d3c26c.

* Remove tests with Activity

* Remove ActivityId from HostingLogScope

* Enable propogation in CreateDefaultBuilder

* Clean up

* s/logging/loggingBuilder

* Enable Activity propogation for generichost

* Replace with runtime/pull/37892
This commit is contained in:
Sourabh Shirhatti 2020-06-22 10:12:22 -07:00 committed by GitHub
parent 36be16b640
commit c97a0020d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 18 additions and 118 deletions

View File

@ -189,12 +189,18 @@ namespace Microsoft.AspNetCore
config.AddCommandLine(args); config.AddCommandLine(args);
} }
}) })
.ConfigureLogging((hostingContext, logging) => .ConfigureLogging((hostingContext, loggingBuilder) =>
{ {
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); loggingBuilder.Configure(options =>
logging.AddConsole(); {
logging.AddDebug(); options.ActivityTrackingOptions = ActivityTrackingOptions.SpanId
logging.AddEventSourceLogger(); | ActivityTrackingOptions.TraceId
| ActivityTrackingOptions.ParentId;
});
loggingBuilder.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
loggingBuilder.AddConsole();
loggingBuilder.AddDebug();
loggingBuilder.AddEventSourceLogger();
}). }).
UseDefaultServiceProvider((context, options) => UseDefaultServiceProvider((context, options) =>
{ {

View File

@ -1,43 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Diagnostics;
namespace Microsoft.AspNetCore.Hosting
{
/// <summary>
/// Helpers for getting the right values from Activity no matter the format (w3c or hierarchical)
/// </summary>
internal static class ActivityExtensions
{
public static string GetSpanId(this Activity activity)
{
return activity.IdFormat switch
{
ActivityIdFormat.Hierarchical => activity.Id,
ActivityIdFormat.W3C => activity.SpanId.ToHexString(),
_ => null,
} ?? string.Empty;
}
public static string GetTraceId(this Activity activity)
{
return activity.IdFormat switch
{
ActivityIdFormat.Hierarchical => activity.RootId,
ActivityIdFormat.W3C => activity.TraceId.ToHexString(),
_ => null,
} ?? string.Empty;
}
public static string GetParentId(this Activity activity)
{
return activity.IdFormat switch
{
ActivityIdFormat.Hierarchical => activity.ParentId,
ActivityIdFormat.W3C => activity.ParentSpanId.ToHexString(),
_ => null,
} ?? string.Empty;
}
}
}

View File

@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.Hosting
// Scope may be relevant for a different level of logging, so we always create it // Scope may be relevant for a different level of logging, so we always create it
// see: https://github.com/aspnet/Hosting/pull/944 // see: https://github.com/aspnet/Hosting/pull/944
// Scope can be null if logging is not on. // Scope can be null if logging is not on.
context.Scope = _logger.RequestScope(httpContext, context.Activity); context.Scope = _logger.RequestScope(httpContext);
if (_logger.IsEnabled(LogLevel.Information)) if (_logger.IsEnabled(LogLevel.Information))
{ {

View File

@ -4,7 +4,6 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.Reflection; using System.Reflection;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
@ -14,9 +13,9 @@ namespace Microsoft.AspNetCore.Hosting
{ {
internal static class HostingLoggerExtensions internal static class HostingLoggerExtensions
{ {
public static IDisposable RequestScope(this ILogger logger, HttpContext httpContext, Activity activity) public static IDisposable RequestScope(this ILogger logger, HttpContext httpContext)
{ {
return logger.BeginScope(new HostingLogScope(httpContext, activity)); return logger.BeginScope(new HostingLogScope(httpContext));
} }
public static void ApplicationError(this ILogger logger, Exception exception) public static void ApplicationError(this ILogger logger, Exception exception)
@ -97,7 +96,6 @@ namespace Microsoft.AspNetCore.Hosting
{ {
private readonly string _path; private readonly string _path;
private readonly string _traceIdentifier; private readonly string _traceIdentifier;
private readonly Activity _activity;
private string _cachedToString; private string _cachedToString;
@ -105,7 +103,7 @@ namespace Microsoft.AspNetCore.Hosting
{ {
get get
{ {
return 5; return 2;
} }
} }
@ -121,31 +119,17 @@ namespace Microsoft.AspNetCore.Hosting
{ {
return new KeyValuePair<string, object>("RequestPath", _path); return new KeyValuePair<string, object>("RequestPath", _path);
} }
else if (index == 2)
{
return new KeyValuePair<string, object>("SpanId", _activity.GetSpanId());
}
else if (index == 3)
{
return new KeyValuePair<string, object>("TraceId", _activity.GetTraceId());
}
else if (index == 4)
{
return new KeyValuePair<string, object>("ParentId", _activity.GetParentId());
}
throw new ArgumentOutOfRangeException(nameof(index)); throw new ArgumentOutOfRangeException(nameof(index));
} }
} }
public HostingLogScope(HttpContext httpContext, Activity activity) public HostingLogScope(HttpContext httpContext)
{ {
_traceIdentifier = httpContext.TraceIdentifier; _traceIdentifier = httpContext.TraceIdentifier;
_path = (httpContext.Request.PathBase.HasValue _path = (httpContext.Request.PathBase.HasValue
? httpContext.Request.PathBase + httpContext.Request.Path ? httpContext.Request.PathBase + httpContext.Request.Path
: httpContext.Request.Path).ToString(); : httpContext.Request.Path).ToString();
_activity = activity;
} }
public override string ToString() public override string ToString()
@ -154,12 +138,9 @@ namespace Microsoft.AspNetCore.Hosting
{ {
_cachedToString = string.Format( _cachedToString = string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
"RequestPath:{0} RequestId:{1}, SpanId:{2}, TraceId:{3}, ParentId:{4}", "RequestPath:{0} RequestId:{1}",
_path, _path,
_traceIdentifier, _traceIdentifier);
_activity.GetSpanId(),
_activity.GetTraceId(),
_activity.GetParentId());
} }
return _cachedToString; return _cachedToString;

View File

@ -40,50 +40,6 @@ namespace Microsoft.AspNetCore.Hosting.Tests
Assert.Null(Activity.Current); Assert.Null(Activity.Current);
} }
[Fact]
public void CreateContextWithEnabledLoggerCreatesActivityAndSetsActivityInScope()
{
// Arrange
var logger = new LoggerWithScopes(isEnabled: true);
var hostingApplication = CreateApplication(out var features, logger: logger);
// 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["SpanId"].ToString());
Assert.Equal(Activity.Current.RootId, pairs["TraceId"].ToString());
Assert.Equal(string.Empty, pairs["ParentId"]?.ToString());
}
[Fact]
public void CreateContextWithEnabledLoggerAndRequestIdCreatesActivityAndSetsActivityInScope()
{
// Arrange
// Generate an id we can use for the request id header (in the correct format)
var activity = new Activity("IncomingRequest");
activity.Start();
var id = activity.Id;
activity.Stop();
var logger = new LoggerWithScopes(isEnabled: true);
var hostingApplication = CreateApplication(out var features, logger: logger, configure: context =>
{
context.Request.Headers["Request-Id"] = id;
});
// 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["SpanId"].ToString());
Assert.Equal(Activity.Current.RootId, pairs["TraceId"].ToString());
Assert.Equal(id, pairs["ParentId"].ToString());
}
[Fact] [Fact]
public void ActivityStopDoesNotFireIfNoListenerAttachedForStart() public void ActivityStopDoesNotFireIfNoListenerAttachedForStart()
{ {