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);
}
}