在我们的项目中,我们有一些类属性需要在记录时进行审查。每个要审查的属性都具有自定义属性;我们称其为
CensorMeAttribute
。
因此,我们想要审查的任何属性都可以实现为:
[CensorMe]
public string Secret { get; set; }
我们目前覆盖 NLog 的内置 JSON 格式化程序/转换器,以便按照 NLog 的 wiki 文章
如何使用结构化日志记录: 提供的指南来审查
CensorMe
属性的值
NLog.IJsonConverter
:public class CensorJsonConverter : NLog.IJsonConverter
以及适合我们用例的逻辑。
Program.cs
中,我们当前重写了 JSON 转换器并在此静态方法中启用 NLog 作为日志记录提供程序:private static void AddNLog(HostBuilderContext context, ILoggingBuilder loggingBuilder)
{
NLog.Config.ConfigurationItemFactory.Default.JsonConverter = new CensorJsonConverter();
var config = new NLogLoggingConfiguration(context.Configuration.GetSection("NLog"));
loggingBuilder.AddNLog(config);
}
这里,对
loggingBuilder.AddNLog(config)
的调用就是对ILoggingBuilder.AddNLog(LoggingConfiguration)
的调用。
通过此实现,
Secret
被记录为 \"Secret\":\"***\"
而不是 \"Secret\":\"actual secret value\"
。 这是我们想要保留的所需日志记录输出。
NLog.Config.ConfigurationItemFactory.Default.JsonConverter
已过时。解决方法消息显示:
改为使用 LogFactory.ServiceRepository.ResolveInstance(typeof(IJsonConverter))。
我在
ResolveInstance()
属性上找不到任何 LogFactory.ServiceRepository
方法。有 RegisterService()
方法,该方法注册单例对象的实例以在 NLog 中使用(ServiceRepository
文档)。因此我尝试的是更换线路
NLog.[...].JsonConverter = new CensorJsonConverter();
致电
config.LogFactory.ServiceRepository.RegisterService([...]);
如下:
private static void AddNLog(HostBuilderContext context, ILoggingBuilder loggingBuilder)
{
var config = new NLogLoggingConfiguration(context.Configuration.GetSection("NLog"));
config.LogFactory.ServiceRepository.RegisterService(
typeof(CensorJsonConverter),
new CensorJsonConverter());
loggingBuilder.AddNLog(config);
}
通过此实现,
Secret
将记录为 \"Secret\":\"actual secret value\"
。这不是所需的日志输出。
NLog.Config.ConfigurationItemFactory.Default.JsonConverter
?或者是否有另一种方法可以在使用或不使用 NLog 的情况下实现对
CensorMe
属性的类似处理?
private static void AddNLog(HostBuilderContext context, ILoggingBuilder loggingBuilder)
{
LogManager.Setup()
.SetupExtensions(e => e.RegisterNLogWeb().RegisterConfigSettings(context.Configuration))
.SetupSerialization(s => s.RegisterJsonConverter(new CensorJsonConverter())
.LoadConfigurationFromSection(context.Configuration);
loggingBuilder.AddNLogWeb();
}
请注意,如果您将秘密包装在继承自 IFormattable
的自定义类型中,那么 NLog 将默认忽略属性并只执行
ToString()
(无需自定义 JsonConverter)
public struct SecretValue : IFormattable
{
public string Value;
string IFormattable.ToString(string format, IFormatProvider formatProvider) => ToString();
public override string ToString() => string.IsNullOrEmpty(Value) ? "" : "*****";
}
另请参阅:https://github.com/NLog/NLog/wiki/How-to-use-structed-logging#customize-object-reflection