I wrote a Dotnetty server and used Nlog as the logging framework. Every connection has its own ID and I want to log this ID alongside other data(message, Datetime, etc...) to Sql. As Dotnetty handles multiple connections by single thread, using mdlc/ndlc to log ID caused incorrect data to log (By incorrect I mean one connection ID logged with another connection data). I can use logevent properties but I have to pass the connection ID to each class/method I want to log inside. Any suggestion ?
this is Custom Logger
public void SetFlowmeterSerial(long? flowmeterSerial)
{
MappedDiagnosticsLogicalContext.Set("Serial",flowmeterSerial);
}
public long GetSerialNumber()
{
return Convert.ToInt64(MappedDiagnosticsLogicalContext.Get("Serial"));
}
NLogConfig for database
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 Handler
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);
}
}
}
I have Other Handlers Like This For Processing Data and Log them.