SharpLogContext encapsulates Microsoft's logger scopes mechanism, giving more freedom in scopes' lifetime management.
| Name | Package | Description |
|---|---|---|
| Main Package | SharpLogContext | Stores log data throught async calls and threads |
| ASP.NetCore | SharpLogContext.NetCore | Initializes SharpLogContext for all HTTP requests |
| MassTransit | SharpLogContext.MassTransit | Initializes SharpLogContext before message processing |
SharpLogContext adds static class LogContext with AsyncLocal root context.
Initialize it by calling LogContext.Initialize().
Unlike logging scopes, sharing values only with the underlying calls, LogContext items can be accessed from the outside, even in exception handlers and .NET Core middleware.
LogContext.Initialize();
try
{
LogContext.Current.AddScoped("foo", true);
_logger.LogInfo("foo"); //attaches "foo: true" to log state
throw new Exception();
}
catch(Exception ex)
{
_logger.LogErrorScoped(ex); //also attaches "foo: true" to log state
}Use SharpLogContext logger extensions methods to attach log context items to your log messages.
Method names end with Scoped suffix;
using Microsoft.Extensions.Logging;
using SharpLogContext;
..
private readonly ILogger _logger;
..
_logger.LogInfoScoped("Log message");
_logger.LogDebugScoped("Log message");Determine scope for particular log items if you don't want them to be visible from the outer space.
Use LogContext.Current.CreateScope() method;
LogContext.Current.Add("1", 1);
using (LogContext.Current.CreateScope("2", 2))
{
Console.WriteLine(LogContext.Current.GetValues());
//Returns {"1", 1}, {"2", 2}
}
Console.WriteLine(LogContext.Current.GetValues());
//Returns {"1", 1}NLog.config example
<?xml version="1.0" encoding="utf-8"?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target name="mainLogFile" xsi:type="File"
fileName="${basedir}/logs/${shortdate}/${logger}.json">
<layout xsi:type="JsonLayout">
<attribute layout="${event-properties:foo}" name="foo"/>
</layout>
</target>
</targets>
<rules>
<logger minlevel="Trace" name="*" writeTo="mainLogFile"/>
</rules>
</nlog>Add app.UseLogContext() in the beginning of request pipeline in Startup.cs
public void Configure(IApplicationBuilder app)
{
app.UseLogContext();
...
}Add log items anywhere in your controllers
public class FooController : ControllerBase
{
[HttpGet]
public void Get()
{
LogContext.Current.Add("foo", true);
}
}Access your log items in the middleware
public class FooMiddleware
{
private readonly RequestDelegate _next;
public FooMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
await _next(context);
var foo = LogContext.Current["foo"];
}
}Stores log data throughout MassTransit consumer message processing
Call .AddLogContext() on your IBusControl
var bus = Bus.Factory.CreateUsingInMemory(...);
bus.AddLogContext();
await bus.StartAsync();or on any IBusFactoryConfigurator
services.AddMassTransit(x =>
{
x.UsingInMemory((context, cfg) =>
{
cfg.ConfigureEndpoints(context);
cfg.AddLogContext();
});
}And start using LogContext
class FooConsumer : IConsumer<Foo>
{
public async Task Consume(ConsumeContext<Foo> context)
{
LogContext.Current.Add("foo", 1);
}
}