我已经提到了Update NLog target filename at runtime和许多其他链接,但在我看来似乎没有任何作用。我使用
初始化记录器private Logger logger = LogManager.GetCurrentClassLogger();
所有日志消息都排队,然后使用计时器清空。
this.messageQueue = new ConcurrentQueue<NotificationMessagePacket>();
this.timer = new System.Timers.Timer(1000);
this.timer.Elapsed += (o, e) =>
{
if (!isWriting)
{
lock (_lockObject)
{
isWriting = true;
NotificationMessagePacket packet;
while (this.messageQueue.TryDequeue(out packet) && packet != null)
{
try
{
if (!string.IsNullOrWhiteSpace(packet.DetailMessage))
this.Infolog(packet);
}
catch (Exception ex)
{
ObjectUtils.EventLogWriteError("NotificationMessagePacket emptying error : " + ex.ToString(),
EventLogEntryType.Warning);
}
}
}
isWriting = false;
}
};
this.timer.Start();
我尝试使用以下代码重置目标文件名:
LoggingConfiguration configuration = LogManager.Configuration;
var wrapper = (AsyncTargetWrapper)configuration.FindTargetByName("log");
var target = (FileTarget)wrapper.WrappedTarget;
string path = Path.Combine(basePath, "Test", "Log", string.Concat(DateTime.Now.ToString("dd"), "_", DateTime.Now.ToString("MMMM"), "_", DateTime.Now.Year + @"\AppLogs.txt"));
if (!string.IsNullOrEmpty(message.ProcessId))
path = Path.Combine(basePath, "Test", "Log", string.Concat(DateTime.Now.ToString("dd"), "_", DateTime.Now.ToString("MMMM"), "_", DateTime.Now.Year + @"\" + message.ProcessId + ".txt"));
target.FileName = path;
target.ConcurrentWrites = false;
LogManager.Configuration = configuration;
LogManager.ReconfigExistingLoggers();
但是有时日志消息未写入适当的文件。
我在您的配置中看到message.ProcessId
。看来您正在更改每个日志事件的配置。那不是线程安全的!参见How Thread-Safe is NLog?
。
好消息,也无需更改配置。您可以使用上下文类在配置中注入值。对于全局,有GDC,但也有线程和消息级别的上下文。 (以及其他here)。
您可以像这样设置配置:
// Set GDC
GlobalDiagnosticsContext.Set("basepath","somepath");
// Create config
var config = new LoggingConfiguration();
FileTarget fileTarget1 = new FileTarget();
fileTarget1.FileName = @"${gdc:basepath}\Test\Log\${Date:format:dd_MMMM_yyyy}\AppLogs.txt";
FileTarget fileTargetWithProcessId = new FileTarget();
fileTargetWithProcessId.FileName = @"${gdc:basepath}\Test\Log\${Date:format:dd_MMMM_yyyy}\${event-properties:ProcessId}.txt";
var hasProcessIdProperty = "${event-properties:item=ProcessId}!=''";
var rule1 = new LoggingRule()
{
// log without processid to fileTarget1
Targets = { fileTarget1 },
Filters = { new ConditionBasedFilter()
{
Condition = hasProcessIdProperty,
Action = FilterResult.Ignore,
DefaultFilterResult = FilterResult.Log
} }
};
var rule2 = new LoggingRule()
{
// log only with processid to fileTarget1
Targets = { fileTargetWithProcessId },
Filters = { new ConditionBasedFilter()
{
// Log with property processid
Condition = hasProcessIdProperty,
Action = FilterResult.Log,
DefaultFilterResult = FilterResult.Ignore
} }
};
// Enable trace to fatal (so all levels)
rule1.SetLoggingLevels(LogLevel.Trace, LogLevel.Fatal);
rule2.SetLoggingLevels(LogLevel.Trace, LogLevel.Fatal);
config.LoggingRules.Add(rule1);
config.LoggingRules.Add(rule2);
LogManager.Configuration = config; // apply
并这样登录:
var logger = LogManager.GetCurrentClassLogger();
logger.Info("I go to AppLogs.txt");
logger.WithProperty("ProcessId", message.ProcessId).Info("I go to processid logs");
您也可以使用一个目标,并使用“ if else”($ {when}),设置起来比较麻烦。
如果对此有疑问,请检查How to see NLog diagnostics and errors