Reputation: 17094
I am implementing a custom NLog AsyncTaskTarget
, and I need to retrieve values that I have added using Microsoft.Extensions.Logging.ILogger.BeginScope
:
using (var scope = logger.BeginScope(new []
{
new KeyValuePair<string, object>("userId", this.UserId)
}))
{
logger.Log(..);
}
Rendering this in a layout using ${mdlc:userId}
works fine, but I would like to get them directly from MappedDiagnosticsLogicalContext
or ScopeContext
.
This is what I've tried:
protected override async Task WriteAsyncTask(LogEventInfo logEvent, CancellationToken token)
{
// returns null
ScopeContext.TryGetProperty("userId", out var userId);
userId = MappedDiagnosticsLogicalContext.GetObject("userId");
// this works fine
var message = this.Layout.Render(logEvent);
}
How do I get the userId
value from the scope?
NLog Version: 5.0.1 (newest)
This GitHub issue is related to this problem, but I found no real solution there.
Upvotes: 4
Views: 1597
Reputation: 17094
Full solution:
using NLog;
using NLog.Targets;
class AsyncScopeTarget : AsyncTaskTarget
{
public AsyncScopeTarget()
{
this.IncludeScopeProperties = true;
}
protected override bool SerializeScopeContextProperty(LogEventInfo logEvent, string name, object value, out object serializedValue)
{
// return the original (immutable) value
serializedValue = value;
return true;
}
protected override async Task WriteAsyncTask(LogEventInfo logEvent, CancellationToken cancellationToken)
{
var scopeValues = GetScopeContextProperties(logEvent);
if (scopeValues is not null)
{
scopeValues.TryGetValue("name", out object? scopeValue);
}
}
}
(Note: Also consider this post.)
Upvotes: 1
Reputation: 19867
In your Target-constructor enable the option:
And then you can use GetScopeContextProperties() method:
protected override async Task WriteAsyncTask(LogEventInfo logEvent, CancellationToken token)
{
var contextProperties = GetScopeContextProperties(logEvent);
contextProperties?.TryGetValue("userid", out var userId);
}
You can also get a combined dictionary of all properties, by using GetAllProperties() and the do the lookup (Still need to enable IncludeScopeProperties )
Upvotes: 3
Reputation: 4537
You could use GetAllProperties
method to get dictionary of all configured properties for logEvent
, and then retrieve specific property from the dictionary. Just enable IncludeScopeProperties
of the target in NLog configuration.
Upvotes: 1