如何避免使用要记录的Serilog Sinks创建循环。问题是基类";MyTcpServer";以及";MyTcpClient";使用序列号。但由于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接收器中使用的一种常见方法是使用静态SelfLog
写入某些TextWriter
。例如
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服务器内使用上下文记录器,仍然会出现堆栈溢出。