Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieving HttpContext in a Custom NLog Target

I may me missing something basic here - but is it possible to retrieve the HttpContext.Current in a custom NLog event?

I am trying to give each request a unique Guid so that I can correlate logging messages to a single event (i.e, tie together each log event for a single request). So, I want to store this Guid in HttpContext.Current.Items, then retrieve it in the NLog target and include it in the log message.

Here is my example target where I'd like to access HttpContext.Current:

[Target("AzureTableTarget")]
public class AzureTableTarget : TargetWithLayout
{

    public AzureTableTarget()
    {
        _appSettings = IoCResolver.Get<IAppSettings>();
    }

    protected override void Write(LogEventInfo logEvent)
    {
        var correlationId = HttpContext.Current; //This is always null

        var batchOperation = new TableBatchOperation();
        CxLogEventBuilder.Build(_appSettings, logEvent).ForEach(batchOperation.Insert);
        _loggingTable.ExecuteBatchAsync(batchOperation);
    }
}
like image 699
MattW Avatar asked Feb 23 '14 18:02

MattW


1 Answers

Nowadays it's easier to retrieve the HTTP Context in a NLog target (works for ASP.NET and ASP.NET Core)

  1. Install NLog.Web (ASP.NET) or NLog.Web.AspNetCore (ASP.NET Core) package
  2. For ASP.NET core, follow the ASP.NET Core - NLog setup
  3. Inherit from AspNetLayoutRendererBase (namespace NLog.Web.LayoutRenderers)
  4. Get the request by calling var context = HttpContextAccessor.HttpContext;

Example:

[LayoutRenderer("aspnet-sessionid")]
[ThreadSafe]
public class AspNetSessionIdLayoutRenderer : AspNetLayoutRendererBase
{
    protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent)
    {
        var context = HttpContextAccessor.HttpContext;
        var contextSession = context?.Session();
        if (contextSession == null)
        {
             InternalLogger.Debug("HttpContext Session Lookup returned null");
             return;
        }

        builder.Append(contextSession.SessionID); // ASP.NET Core: contextSession.Id
    }
}

PS: there are currently many predefined renderers for ASP.NET (Core): https://nlog-project.org/config/?tab=layout-renderers&search=aspnet

like image 66
Julian Avatar answered Oct 16 '22 08:10

Julian