我正在实现一个自定义的NLogAsyncTaskTarget
,我需要检索我使用Microsoft.Extensions.Logging.ILogger.BeginScope
添加的值:
using (var scope = logger.BeginScope(new []
{
new KeyValuePair<string, object>("userId", this.UserId)
}))
{
logger.Log(..);
}
在使用${mdlc:userId}
的布局中渲染此作品很好,但我想直接从MappedDiagnosticsLogicalContext
或ScopeContext
获得它们。
这是我尝试过的:
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);
}
如何从范围中获得userId
值?
NLog Version: 5.0.1(最新)
这个GitHub问题与这个问题有关,但我没有找到真正的解决方案。
在Target-constructor中启用选项:
- inclescopeproperties = true;
然后你可以使用GetScopeContextProperties()方法:
protected override async Task WriteAsyncTask(LogEventInfo logEvent, CancellationToken token)
{
var contextProperties = GetScopeContextProperties(logEvent);
contextProperties?.TryGetValue("userid", out var userId);
}
您还可以通过使用GetAllProperties()和执行查找(仍然需要启用inclescopeproperties)来获得所有属性的组合字典
您可以使用GetAllProperties
方法获取logEvent
的所有配置属性的字典,然后从字典中检索特定的属性。只需在NLog配置中启用目标的IncludeScopeProperties
。
完整解决方案:
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);
}
}
}
(注意:也考虑这篇文章)