Search code examples
c#serilog

Serilog Indefinite Loop logging base classes


How do I avoid creating a loop with Serilog Sinks that I want to log. The problem is that the base classes "MyTcpServer" and "MyTcpClient" use Serilog. But since TcpSink also uses the same classes, sending a log entry will indefinitely loop.

How do I prevent this?

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

Solution

  • There are only two options here

    • Use MyTcpServer in TcpServerSink but don't log to TcpServerSink
    • Don't use MyTcpServer in TcpServerSink

    For the first solution make MyTcpServer dependent on ILogger rather than using static Log dependency. This way you can pass whatever logger you want or just disable logging in your sink:

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

    I personally prefer the second solution. Because you should log to Serilog sinks only events related to your application logic. TcpServerSink is not related to application logic. A common approach used in other Serilog sinks is the usage of static SelfLog that writes to someTextWriter. E.g.

    SelfLog.Out = Console.Error;
    

    And then you can use this self-log to write some info about your sink. Also instead of MyTcpServer your sink should use something like plain TcpClient. You can check a Splunk TcpSink example.