我的作业调度程序运行作业,每个作业都有自己的记录器。如果作业成功,则记录其累积的日志事件,而如果失败,则丢弃该作业(及其日志事件)。
这可以使用 hacky 自定义 MEL 日志记录,但我正在努力转换为 Serilog。我正在使用控制台、postgres 和 seq 接收器。
这类似于审计日志记录;但是,虽然有人在日志刷新后提交事务,但这里“阻止”记录直到将来的某个时刻。所以几乎是相反的。 总结:
照常记录,例如
_logger.Debug("Foo {Bar}", 42)
接收器包装器和 batching 接收器包装器 - 但我不确定该走哪条路。 有什么指点吗?
ICachingLoggerOfT.cs
public interface ICachingLogger<T> : ILogger where T : class
{
void Drain();
}
CachingLoggerOfT.cs
using System.Collections.Concurrent;
using Serilog;
using Serilog.Events;
public sealed class CachingLogger<T> : ICachingLogger<T>
{
private readonly ConcurrentQueue<LogEvent> _cache = new();
private readonly ILogger _logger;
public CachingLogger(ILogger logger) =>
_logger = logger?.ForContext<T>() ?? throw new ArgumentNullException(nameof(logger));
public void Write(LogEvent logEvent) // implementation for "ILogger.Write(LogEvent)"
{
ArgumentNullException.ThrowIfNull(logEvent, nameof(logEvent));
_cache.Enqueue(logEvent);
}
public void Drain()
{
// maybe lock cache from further enqueueing?
while (_cache.TryDequeue(out var logEvent))
_logger.Write(logEvent);
}
}
Program.cs
builder.Services.AddTransient(typeof(ICachingLogger<>), typeof(CachingLogger<>));
Consumer.cs
public class Consumer
{
private readonly ICachingLogger<Consumer> _logger;
public Scraper(ICachingLogger<Consumer> logger) =>
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
public void DoStuff() {
// use logger in normal way
_logger
.ForContext("Foo", "Bar")
.Information("Hello {What}", "World!");
}
public void EmitLogs() {
// when required, drain logger; will emit all cached log events
_logger.Drain();
}
}
到目前为止似乎对我有用。如果有人发现任何问题或有更好的方法,请告诉我?谢谢!