【发布时间】:2019-12-31 04:33:34
【问题描述】:
我编写了一个 Dotnetty 服务器并使用 Nlog 作为日志框架。每个连接都有自己的 ID,我想将此 ID 与其他数据(消息、日期时间等)一起记录到 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);
}
}
}
我有其他类似的处理程序来处理数据并记录它们。
【问题讨论】:
标签: c# multithreading netty nlog mdc