Serilog 缓存记录器/反向审计日志记录

问题描述 投票:0回答:1

我的作业调度程序运行作业,每个作业都有自己的记录器。如果作业成功,则记录其累积的日志事件,而如果失败,则丢弃该作业(及其日志事件)。

这可以使用 hacky 自定义 MEL 日志记录,但我正在努力转换为 Serilog。我正在使用控制台、postgres 和 seq 接收器。

这类似于审计日志记录;但是,虽然有人在日志刷新后提交事务,但这里“阻止”记录直到将来的某个时刻。所以几乎是相反的。 总结:

照常记录,例如
    _logger.Debug("Foo {Bar}", 42)
  • 日志事件被缓存(即不发送到接收器)
  • 当请求时,缓存的日志事件将被耗尽(即发送到接收器)
  • 我研究了自定义 ILogger、
async

接收器包装器和 batching 接收器包装器 - 但我不确定该走哪条路。 有什么指点吗?

.net-core serilog
1个回答
0
投票

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();
  }

}

到目前为止似乎对我有用。如果有人发现任何问题或有更好的方法,请告诉我?谢谢!

© www.soinside.com 2019 - 2024. All rights reserved.