我编写了一个Dotnetty服务器,并使用Nlog作为日志记录框架。每个连接都有自己的ID,我想将此ID与其他数据(消息,Datetime等...)一起记录到Sql中。由于Dotnetty通过单线程处理多个连接,因此使用mdlc / ndlc记录ID会导致记录错误的数据(错误的意思是一个连接ID与另一个连接数据一起记录)。我可以使用logevent属性,但必须将连接ID传递给我要登录的每个类/方法。有什么建议吗?
这是自定义记录器
public void SetFlowmeterSerial(long? flowmeterSerial)
{
MappedDiagnosticsLogicalContext.Set("Serial",flowmeterSerial);
}
public long GetSerialNumber()
{
return Convert.ToInt64(MappedDiagnosticsLogicalContext.Get("Serial"));
}
数据库的NLogConfig
public static void DataBaseTarget(LogLevel min, LogLevel max, LoggingConfiguration config, string
name,string connectionString,string databaseName)
{
var greDateTime = TimeCodec.Trim(DateTime.Now,TimeSpan.TicksPerSecond);
var persianDateTime = TimeCodec.GreToPersianDateTime(greDateTime);
var sqlFormattedDateTime = greDateTime.ToString("yyyy-MM-dd HH:mm:ss.fff");
var databaseTarget = new DatabaseTarget
{
ConnectionString = connectionString,//"server=.;database=FlowMeterSimulatorLOG;integrated security=sspi",
DBProvider = "System.Data.SqlClient",
DBDatabase = databaseName,//"FlowMeterSimulatorLOG",
DBHost = ".",
CommandText =
$"insert into SystemLog (FlowMeterSerial,GreDateTime,PersianDateTime,Level,CallSite,Message,ExceptionType,ExceptionMessage,StackTrace)values(@FlowMeterSerial,'{sqlFormattedDateTime}','{persianDateTime}',@Level,@CallSite,@Message,@ExceptionType,@ExceptionMessage,@StackTrace);",
};
var param = new DatabaseParameterInfo { Name = "@Level", Layout = "${level}" };
databaseTarget.Parameters.Add(param);
param = new DatabaseParameterInfo { Name = "@CallSite", Layout = "${callsite}" };
databaseTarget.Parameters.Add(param);
param = new DatabaseParameterInfo { Name = "@Message", Layout = "${message}" };
databaseTarget.Parameters.Add(param);
param = new DatabaseParameterInfo { Name = "@ExceptionType", Layout = "${exception:format=type}" };
databaseTarget.Parameters.Add(param);
param = new DatabaseParameterInfo { Name = "@ExceptionMessage", Layout = "${exception:format=message}" };
databaseTarget.Parameters.Add(param);
param = new DatabaseParameterInfo { Name = "@StackTrace", Layout = "${exception:format=stackTrace}" };
databaseTarget.Parameters.Add(param);
param = new DatabaseParameterInfo { Name = "@FlowMeterSerial", Layout = "${mdlc:item=Serial}" };
databaseTarget.Parameters.Add(param);
config.AddRule(min, max, databaseTarget);
LogManager.Configuration = config;
}
Dotnetty处理程序
public class LogHandler : ChannelHandlerAdapter
{
private readonly CustomLogger _logger = (CustomLogger) LogManager.GetCurrentClassLogger(typeof(CustomLogger));
//private static readonly ILogger _logger = LogManager.GetCurrentClassLogger();
private long _serialNumber;
public override void ChannelRead(IChannelHandlerContext context, object message)
{
if (!(message is IByteBuffer buffer))
throw new ArgumentException();
var deviceInfo = context.Channel.GetAttribute(ProcessHandler.DeviceInfo).Get();
if (deviceInfo != null)
_serialNumber = deviceInfo.Serial;
_logger.SetFlowmeterSerial(_serialNumber);
_logger?.Debug(
$"Received: {ByteBufferUtil.HexDump(buffer)}");
base.ChannelRead(context, message);
}
public override async Task WriteAsync(IChannelHandlerContext context, object message)
{
try
{
if (!(message is IByteBuffer buffer)) throw new ArgumentException();
try
{
//_logger.SetFlowmeterSerial(_serialNumber);
_logger?.Debug(
$"Sent: {ByteBufferUtil.HexDump(buffer)}");
await base.WriteAsync(context, message).ConfigureAwait(false);
}
catch
{
if (buffer.ReferenceCount != 0) buffer.Release();
throw;
}
}
catch (Exception e)
{
context.FireExceptionCaught(e);
//await Task.FromException(e);
}
}
}
我还有其他类似的处理程序,用于处理数据并记录它们。
答案 0 :(得分:0)
我从未使用过Netty,所以只是尝试阅读文档:
https://netty.io/5.0/api/io/netty/channel/ChannelHandlerContext.html
然后,您应该使用IChannelHandlerContext
处理上下文信息(例如CorrelationId,RequestId等)。
不断尝试使NLog MDLC与活动的Netty上下文保持同步可能很脆弱。也许只是实现将netty上下文作为输入的辅助记录器方法?例如:
public override void ChannelRead(IChannelHandlerContext context, object message)
{
LogDebug(context, "Read");
base.ChannelRead(context, message);
}
public override async Task WriteAsync(IChannelHandlerContext context, object message)
{
LogDebug(context, "Write");
await base.WriteAsync(context, message).ConfigureAwait(false);
}
private void LogDebug(IChannelHandlerContext context, string mesage)
{
var deviceInfo = context.Channel.GetAttribute(ProcessHandler.DeviceInfo).Get();
if (deviceInfo != null)
_logger.WithProperty("FlowMeterSerial", deviceInfo.Serial).Debug(message);
else
_logger.Debug(mesage);
}
无论如何,这只是一个随机的建议。对Java-Netty或Dot-Netty一无所知。