NLog更改目标文件名后写入不同的日志

问题描述 投票:0回答:1

我已经提到了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();

但是有时日志消息未写入适当的文件。

c# nlog
1个回答
0
投票

我在您的配置中看到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

© www.soinside.com 2019 - 2024. All rights reserved.