NLog - working with scopes

Nlog

A log scope in .NET core allows us to add variables that can be shown in the log output without specifying it explicitly at every message

First, ensure it is enabled while adding NLog

.UseNLog(new NLogAspNetCoreOptions()
{
    IncludeScopes = true
});

Begin the scope by adding the variables, in this example we are going to add transactionId



using IDisposable scope = _logger.BeginScope(new Dictionary<string, object>() {
	["transactionId"] = HttpContext.TraceIdentifier
});

In the log configuration - nlog.config - add ${mdlc:transactionId} to the layout.

value="${longdate} | ${machinename} | ${mdlc:transactionId} | ${level} | ${logger} | ${message} | ${exception:format=ToString}"

For ASP.NET controller actions we can create an action filter like this:


public class LogScopeFilter(IServiceProvider serviceProvider) : IActionFilter
{
    private readonly IServiceProvider _serviceProvider = serviceProvider;

    private IDisposable _scope;

    public void OnActionExecuting(ActionExecutingContext context)
    {
        Type loggerType = typeof(ILogger<>).MakeGenericType(context.Controller.GetType());

        ILogger logger = _serviceProvider.GetRequiredService(loggerType) as ILogger;

        Dictionary<string, object> scopeState = new ()
        {
            ["transactionId"] = context.HttpContext.TraceIdentifier
        };

        if (context.ActionArguments.TryGetValue("user", out object user)) {
            scopeState["username"] = user;
        };

        _scope = logger.BeginScope(scopeState);

    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        _scope.Dispose();
    }
}

The example above also shows how to get action parameters for the scope. Next we want to use this attribute by wrapping it with TypeFilter like this:


[TypeFilter(typeof(LogScopeFilter))]
public IActionResult MyAction(string user, string otherParameter) {
	...
}

Post a Comment

Previous Post Next Post