NLog.Web: ActivityId id is empty in async context in ASP.NET Web API

Hi I am using the activityid in our logging for getting a correlation ID, and i followed the guide that is provided on GitHub. That states i only need to add a method in global asax, where we set the activity id.

All my api’s calls are mostly async methods and some times the activity id is empty?

NLog version: 4.6.2 NLog.Config version: 4.6.2 NLog.Schema version: 4.6.2 NLog.Web version: 4.8.1

Platform: .Net 4.5

Current NLog config (xml or C#, if relevant)

  <nlog throwConfigExceptions="true">
    <targets>
      <target name="debugger" type="Debugger" layout="${logger}::${message}" />
      <target name="database" type="Database" dbProvider="sqlserver" connectionStringName="Nlog">
        <commandText>
          INSERT INTO [dbo].[Log] (MachineName, Service, Logged, CorrelationId, Level, Message, Logger, Callsite, Exception) VALUES (@MachineName, 'My service name', @Logged, @CorrelationId, @Level, @Message, @Logger, @Callsite, @Exception);
        </commandText>
        <parameter name="@MachineName" layout="${machinename}" />
        <parameter name="@Logged" layout="${date}" />
        <parameter name="@CorrelationId" layout="${activityid}" />
        <parameter name="@Level" layout="${level}" />
        <parameter name="@Message" layout="${message}" />
        <parameter name="@Logger" layout="${logger}" />
        <parameter name="@Callsite" layout="${callsite}" />
        <parameter name="@Exception" layout="${exception:tostring}" />
      </target>
    </targets>
    <rules>
      <logger name="*" minlevel="Trace" writeTo="debugger" />
      <logger name="*" minlevel="Trace" writeTo="database" />
    </rules>
  </nlog>

I was reading about this specific problem with async calls and the global asax not being called and I found a solution to this.

I created my own DelegatingHandler that intercepts all messages sent to the service. Where i get a correlation Id and manually sets the ActivityId.

using System;
using System.Diagnostics;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

public class CorrelationHandler : DelegatingHandler
    {
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            Guid correlationId = request.GetCorrelationId();
            Trace.CorrelationManager.ActivityId = correlationId;

            return await base.SendAsync(request, cancellationToken);
        }
    }

Finally I registered my new handler in the WebApiConfig.cs file like so:


    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            ...
            // Web API message handlers
            config.MessageHandlers.Add(new CorrelationHandler());
            ...
        }
    }

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 19 (12 by maintainers)

Most upvoted comments

@304NotModified I’m very sorry for my slow work… 😦 I have set some time off to get it done this weekend. Work is taking all my time at the moment.

Hi! Thanks for opening your first issue here! Please make sure to follow the issue template - so we could help you better!