es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Clases base de registro de bucle indefinido de Serilog

¿Cómo puedo evitar crear un bucle con Serilog Sinks que quiero registrar?
El problema es que las clases base “MyTcpServer” y “MyTcpClient” utilizan Serilog.
Pero dado que TcpSink también utiliza las mismas clases, el envío de una entrada de registro dará lugar a un bucle infinito.

¿Cómo puedo evitar esto?

“`
Main()
{
Serilog.Log.Logger = new LoggerConfiguration()
.WriteTo.TcpSink() //esto es un TcpListener/Servidor que escucha en el puerto 1234
.WriteTo.Console()
.CreateLogger();

MyTcpServer AnotherServer = new MyTcpServer(4321);
}

public class MyTcpServer
{
///esta clase contiene Log.Verbose|Debug|Error
private List<mytcpclient> clients;
}

public class MyTcpClient
{
///esta clase contiene 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);
}
}
“`

Tags:  ,

Answer

  1. Avatar for davy.ai

    Para evitar crear un bucle con los Sinks de Serilog, como en el fragmento de código dado donde tanto la clase TcpServer como la clase TcpClient utilizan Serilog, una solución es envolver el TcpSink en una clase que bloquee los intentos de registro de las clases TcpServer y TcpClient. Aquí tienes un ejemplo de implementación:

    public class TcpSinkWrapper : ILogEventSink
    {
        private readonly TcpSink tcpSink;
    
        public TcpSinkWrapper(TcpSink tcpSink)
        {
            this.tcpSink = tcpSink;
        }
    
        public void Emit(LogEvent logEvent)
        {
            // Comprobar si el origen del evento son las clases TcpServer o TcpClient
            var sourceType = logEvent.Properties.TryGetValue("SourceContext", out var sourceContext)
                ? sourceContext.ToString().ToLowerInvariant()
                : string.Empty;
    
            if (sourceType.Contains("tcpserv") || sourceType.Contains("tcpcli"))
            {
                // Bloquear los eventos de registro que se originan en las clases TcpServer o TcpClient
                return;
            }
    
            // De lo contrario, emitir el evento utilizando el TcpSink
            tcpSink.Emit(logEvent);
        }
    }
    
    // Actualizar la configuración del registro para utilizar la clase wrapper en lugar del TcpSink directamente
    Serilog.Log.Logger = new LoggerConfiguration()
        .WriteTo.Sink(new TcpSinkWrapper(new TcpSink(port: 1234)))
        .WriteTo.Console()
        .CreateLogger();
    

    En esta solución, creamos una clase envolvente TcpSinkWrapper que toma una instancia de TcpSink como argumento del constructor. En el método Emit, comprobamos si el origen del evento es alguna de las clases TcpServer o TcpClient examinando la propiedad SourceContext del LogEvent. Si lo es, descartamos el evento y retornamos temprano. De lo contrario, pasamos el evento a la instancia envuelta de TcpSink para emitirlo de forma normal.

    Finalmente, actualizamos la configuración del logger para utilizar la clase envolvente en lugar del TcpSink directamente.

Comments are closed.