Używanie log4net z WebApi - Utrzymywanie tego samego identyfikatora korelacji w całej instancji

Mam klasę LoggingHandler, której używam jako programu obsługi komunikatów do logowania (za pomocą log4net) żądania i odpowiedzi do mojego WebApi

public class LoggingMessageHandler : DelegatingHandler
{
    public ILogManager LogManager { get; set; }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
    {
        var controllerType = GlobalConfiguration.Configuration.Services
            .GetHttpControllerSelector()
            .SelectController(request)
            .ControllerType;

        var requestInfo = string.Format("{0} {1}", request.Method, request.RequestUri);
        var correlationId = request.GetCorrelationId().ToString();

        var requestMessage = await request.Content.ReadAsStringAsync();

        await LogIncommingMessageAsync(controllerType, correlationId, requestInfo, requestMessage.Replace("\r\n", ""));

        var response = await base.SendAsync(request, cancellationToken);

        string responseMessage;

        if (response.IsSuccessStatusCode)
            responseMessage = await response.Content.ReadAsStringAsync();
        else
            responseMessage = response.ReasonPhrase;

        await OutgoingMessageAsync(controllerType, correlationId, requestInfo, responseMessage);

        return response;
    }

    protected async Task LogIncommingMessageAsync(Type type, string correlationId, string requestInfo, string body)
    {
        var logger = LogManager.GetLogger(type);
        await Task.Run(() => logger.Debug("{0} {1} - API Request: \r\n{2}", correlationId, requestInfo, body));
    }

    protected async Task OutgoingMessageAsync(Type type, string correlationId, string requestInfo, string body)
    {
        var logger = LogManager.GetLogger(type);
        await Task.Run(() => logger.Debug("{0} {1} - API Response: \r\n{2}", correlationId, requestInfo, body));
    }
}

ILogManager jest wstrzykiwany przez Autofac (patrz nasz moduł Autofac dalej w dół)

Moim problemem jest identyfikator korelacji;

Jak można to przekazać dalej do naszej aplikacji?

Na przykład w innym zespole, zawierającym część naszej logiki biznesowej, chcemy użyć wywołania LogManager.GetLogger, aby uzyskać dziennik dla innego typu, ale ponieważ powstał na żądanie, ponownie użyj tego samego identyfikatora korelacji, więc możesz połączyć nasze wiadomości z dziennika?

Dla jasności nasz moduł Autofac wygląda tak:

public class LoggingAutofacModule : Autofac.Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<LogManager>().As<ILogManager>().InstancePerApiRequest();
    }

    protected override void AttachToComponentRegistration(IComponentRegistry registry, IComponentRegistration registration)
    {
        registration.Preparing += OnComponentPreparing;

        var implementationType = registration.Activator.LimitType;
        var injectors = BuildInjectors(implementationType).ToArray();

        if (!injectors.Any())
            return;

        registration.Activated += (s, e) =>
        {
            foreach (var injector in injectors)
                injector(e.Context, e.Instance);
        };
    }

    private static void OnComponentPreparing(object sender, PreparingEventArgs e)
    {
        var t = e.Component.Activator.LimitType;
        e.Parameters =
            e.Parameters.Union(new[] { new ResolvedParameter((p, i) => p.ParameterType == typeof(ILogger), (p, i) => e.Context.Resolve<ILogManager>().GetLogger(t)) });
    }

    private static IEnumerable<Action<IComponentContext, object>> BuildInjectors(Type componentType)
    {
        var properties =
            componentType.GetProperties(BindingFlags.SetProperty | BindingFlags.Public | BindingFlags.Instance)
                         .Where(p => p.PropertyType == typeof(ILogger) && !p.GetIndexParameters().Any())
                         .Where(p =>
                         {
                             var accessors = p.GetAccessors(false);
                             return accessors.Length != -1 || accessors[0].ReturnType == typeof(void);
                         });

        foreach (var propertyInfo in properties)
        {
            var propInfo = propertyInfo;
            yield return (context, instance) => propInfo.SetValue(instance, context.Resolve<ILogManager>().GetLogger(componentType), null);
        }
    }
}

questionAnswers(1)

yourAnswerToTheQuestion