作为从 NLog 切换到 Serilog 的一步,我想重定向 NLog
LogManager.GetLogger(name)
标准调用的标准接线,以桥接任何代码日志记录到 NLog,以立即转发到环境 Serilog Log.Logger
- 即我只想一个只是转发消息的配置,无需像 Log4net 那样进行缓冲。
任何人都可以编造或向我指出一个可以正确有效地执行此操作的规范片段吗?我能想到的要求:保持水平,即
Log4net.Appender.Serilog
NLog.Warn
serilog.Warning
在您的
using NLog;
using NLog.Targets;
using Serilog;
using Serilog.Events;
namespace MyNamespace
{
[Target("SerilogTarget")]
public sealed class SerilogTarget : TargetWithLayout
{
protected override void Write(LogEventInfo logEvent)
{
var log = Log.ForContext(Serilog.Core.Constants.SourceContextPropertyName, logEvent.LoggerName);
var logEventLevel = ConvertLevel(logEvent.Level);
if ((logEvent.Parameters?.Length ?? 0) == 0)
{
// NLog treats a single string as a verbatim string; Serilog treats it as a String.Format format and hence collapses doubled braces
// This is the most direct way to emit this without it being re-processed by Serilog (via @nblumhardt)
var template = new Serilog.Events.MessageTemplate(new[] { new Serilog.Parsing.TextToken(logEvent.FormattedMessage) });
log.Write(new Serilog.Events.LogEvent(DateTimeOffset.Now, logEventLevel, logEvent.Exception, template, Enumerable.Empty<Serilog.Events.LogEventProperty>()));
}
else
// Risk: tunneling an NLog format and assuming it will Just Work as a Serilog format
#pragma warning disable Serilog004 // Constant MessageTemplate verifier
log.Write(logEventLevel, logEvent.Exception, logEvent.Message, logEvent.Parameters);
#pragma warning restore Serilog004
}
static Serilog.Events.LogEventLevel ConvertLevel(LogLevel logEventLevel)
{
if (logEventLevel == LogLevel.Info)
return Serilog.Events.LogEventLevel.Information;
else if (logEventLevel == LogLevel.Trace)
return Serilog.Events.LogEventLevel.Verbose;
else if (logEventLevel == LogLevel.Debug)
return Serilog.Events.LogEventLevel.Debug;
else if (logEventLevel == LogLevel.Warn)
return Serilog.Events.LogEventLevel.Warning;
else if (logEventLevel == LogLevel.Error)
return Serilog.Events.LogEventLevel.Error;
return Serilog.Events.LogEventLevel.Fatal;
}
}
}
或
main()
中注册:
app_start
在进行任何记录之前,需要连接
// Register so it can be used by config file parsing etc
Target.Register<MyNamespace.SerilogTarget>("SerilogTarget");
,以便
Target
实际上可以触发对
LogManager.GetLogger()
的调用
SerilogTarget.Write
另请参阅:
https://github.com/nlog/nlog/wiki/How-to-write-a-custom-target
在不引起任何可避免的性能影响等的情况下执行此操作的最佳方法。
这是NLog中的最佳方式,对NLog站点没有性能影响。
public static void ReplaceAllNLogTargetsWithSingleSerilogForwarder()
{
// sic: blindly overwrite the forwarding rules every time
var target = new SerilogTarget();
var cfg = new NLog.Config.LoggingConfiguration();
cfg.AddTarget(nameof(SerilogTarget), target);
cfg.LoggingRules.Add(new NLog.Config.LoggingRule("*", LogLevel.Trace, target));
// NB assignment must happen last; rules get ingested upon assignment
LogManager.Configuration = cfg;
}
在这种情况下你不需要它。注册完整程序集时使用TargetAttribute
,但因为我们手动注册,所以不需要它。我认为这是最佳实践,但您可以忽略它。
还有
TargetAttribute
给我买了什么我习惯编写以各种方式工作的目标(手动注册、通过程序集注册、从代码配置、从 XML 配置)。我可以理解这可能会令人困惑。
使用编程配置时确实不需要这样做。但如果你有 XML 配置,你需要注册。
F#端口:
Register