是否有方法向给定的ILogger实例添加属性?(来自Microsoft.Extensions.Logging.Abstractions)。我使用的是Serilog,通常将ILogger实例注入构造函数。因此,它也可能是利用一些Serilog API的解决方案。
我知道ILogger.BeginScope
和LogContext.PushProperty
,但它们只是将信息添加到当前的异步上下文中。我希望将信息添加到记录器本身的实例中,以便该记录器生成的任何日志都具有额外的属性。
我希望达到的目标类似于:
class Foo {
private ILogger logger;
public Foo(ILogger logger) {
logger.AddProperty("Property", "value"); // now every calls using that logger have that extra prop
_logger = logger;
}
public void Dummy() => _logger.LogDebug("logging something..."); // this log event would have the Property=value added to it automatically
}
发布于 2021-01-23 03:01:26
更新2021-08-21:您现在可以使用Serilog.Enrichers.GlobalLogContext了。
从Serilog.Enrichers.GlobalLogContext安装NuGet包:
Install-Package Serilog.Enrichers.GlobalLogContext
将Serilog名称空间添加到C#文件中:
using Serilog;
using Serilog.Context;
在记录器配置中包括全局日志上下文丰富器:
Log.Logger = new LoggerConfiguration()
.Enrich.FromGlobalLogContext()
// ... other configuration ...
.CreateLogger();
FromGlobalLogContext()
动态地将Serilog.Context.GlobalLogContext
中的属性添加到应用程序中的所有生成事件中。
然后,可以使用GlobalLogContext.PushProperty()
从全局日志上下文中添加和删除属性。
GlobalLogContext.PushProperty("AppVersion", GetThisAppVersion());
GlobalLogContext.PushProperty("OperatingSystem", GetCurrentOS());
在执行上述代码之后,写入任何Serilog接收器的任何日志事件都将自动携带属性AppVersion
和OperatingSystem
。
来源:https://github.com/augustoproiete/serilog-enrichers-globallogcontext
原始答案
实现这一目标的一种方法是创建一个自定义塞里罗格·恩里希,从一开始就连接到Serilog日志记录管道,您还可以访问整个应用程序(最好是通过依赖项注入)。
这将为您提供一种添加新属性的方法,并负责确保将这些属性应用于所有日志事件。
下面的示例是这个想法的简化版本(绝对不推荐作为- is 用于生产,而是作为伪代码来展示主要部分是如何结合在一起的基本知识):
// WARNING: This is *NOT* Production code :)
public sealed class GlobalPropertyEnricher : ILogEventEnricher
{
// TODO: Make it thread-safe
private static readonly Dictionary<string, object> _properties =
new Dictionary<string, object>();
private static readonly Lazy<GlobalPropertyEnricher> _instance =
new Lazy<GlobalPropertyEnricher>(() => new GlobalPropertyEnricher());
public static GlobalPropertyEnricher Instance => _instance.Value;
private GlobalPropertyEnricher()
{
}
public static void SetProperty(string propertyName, object value)
{
// TODO: Make it thread-safe
_properties[propertyName] = value;
}
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
// TODO: Make it thread-safe
// TODO: Properties should be cached (instead of CreateProperty) every time
foreach (var p in _properties)
{
var property = propertyFactory.CreateProperty(p.Key, p.Value);
logEvent.AddPropertyIfAbsent(property);
}
}
}
注意:为了这个例子的目的,我有一个静态类可以通过你的应用程序全局访问,但你的程序。将其注册为DI容器中的辛格尔顿实例。
通过上面丰富的示例,您可以通过GlobalPropertyEnricher.SetProperty
从任何地方添加/替换属性。例如:
GlobalPropertyEnricher.SetProperty("Name", "Augusto");
GlobalPropertyEnricher.SetProperty("Year", DateTime.UtcNow.Year);
最后,当您在Serilog管道中包含丰富器时,您设置的所有属性都将添加到应用程序中写入的每个事件日志消息中:
Log.Logger = new LoggerConfiguration()
.Enrich.With(GlobalPropertyEnricher.Instance)
.WriteTo.(...)
.CreateLogger();
https://stackoverflow.com/questions/65817012
复制相似问题