Serilog 无限循环日志记录基础 类

Serilog Indefinite Loop logging base classes

如何避免使用要记录的 Serilog Sinks 创建循环。 问题是基础 类“MyTcpServer”和“MyTcpClient”使用 Serilog。 但由于 TcpSink 也使用相同的 类,发送日志条目将无限循环。

如何防止这种情况发生?

Main()
{
  Serilog.Log.Logger = new LoggerConfiguration()
    .WriteTo.TcpSink() //this a TcpListener/Server listening on port 1234
    .WriteTo.Console()
    .CreateLogger();

  MyTcpServer AnotherServer = new MyTcpServer(4321);
}

public class MyTcpServer
{
   ///this class contains Log.Verbose|Debug|Error
   private List<MyTcpClient> clients;
}

public class MyTcpClient
{
   ///this class contains Log.Verbose|Debug|Error
}

public class TcpServerSink : ILogEventSink
{
  MyTcpServer server;
  public TcpServerSink(int port = 1234)
  {
     server = new MyTcpServer(1234);
  }
  public void Emit(LogEvent logevent)
  {
    string str = Newtonsoft.Json.JsonConvert.Serialize(logevent);
    server.Send(str);
  }
}

这里只有两个选项

  • TcpServerSink 中使用 MyTcpServer 但不要登录到 TcpServerSink
  • 不要在 TcpServerSink
  • 中使用 MyTcpServer

对于第一个解决方案,使 MyTcpServer 依赖于 ILogger 而不是使用静态 Log 依赖。这样你就可以传递你想要的任何记录器或者只是禁用你的接收器中的日志记录:

server = new MyTcpServer(SilentLogger.Instance, 1234);

我个人更喜欢第二种方案。因为您应该只记录与您的应用程序逻辑相关的事件到 Serilog 接收器。 TcpServerSink 与应用程序逻辑无关。其他 Serilog sink 中使用的一种常见方法是使用静态 SelfLog 写入 someTextWriter。例如

SelfLog.Out = Console.Error;

然后你可以使用这个自我日志来写一些关于你的水槽的信息。另外,您的接收器应该使用普通的 TcpClient 而不是 MyTcpServer。您可以查看 Splunk TcpSink 示例。

一个值得考虑的选项是在 TCP 服务器中登录时使用 Log.ForContext<MyTcpServer>()

Log.ForContext<MyTcpServer>().Information("Hello!");

并为 TCP 接收器过滤掉这些消息:

    // dotnet add package Serilog.Expressions
    .WriteTo.Conditional(
        "SourceContext not like 'MyNamespace.MyTcpServer%'",
        wt => wt.TcpSink())
    .WriteTo.Console()

这样做的好处是可以将错误从 TCP 接收器传送到控制台,但缺点是如果您忘记在 TCP 服务器内使用上下文记录器,您仍然会堆栈溢出。