简体   繁体   English

NLog使用NLog.config动态更改文件名

[英]NLog dynamically change filename using NLog.config

How to dynamically change the FileName using a variable from C#? 如何使用C#中的变量动态更改FileName? My idea is to create a log file like Log_<UserId_From_DB>_${date:format=yyyy-MM-dd}.log . 我的想法是创建一个日志文件,如Log_<UserId_From_DB>_${date:format=yyyy-MM-dd}.log Any ideas? 有任何想法吗?

Another option is to use the Global Diagnostic Context - $(GDC) : 另一种选择是使用全局诊断上下文 - $(GDC)

Set the value in C# 在C#中设置值

GlobalDiagnosticsContext.Set("UserId_From_DB","42");

In the config (nlog.config): 在config(nlog.config)中:

<target type="file" filename="Log_${gdc:item=UserId_From_DB}_${date:format=yyyy-MM-dd}.log" ..>

Please avoid modifying NLog Variables at runtime (See previous answer below). 请避免在运行时修改NLog变量(参见下面的上一个答案)。 They should be seen as readonly, because they are not threadsafe. 它们应该被视为只读,因为它们不是线程安全的。 NLog Variables will also be affected if LoggingConfiguration is reloaded. 如果重新加载LoggingConfiguration,NLog变量也会受到影响。

Previous answer with NLog Variables: NLog变量的上一个答案:

Set the value in C# 在C#中设置值

LogManager.Configuration.Variables["UserId_From_DB"] = "42";

In the config (nlog.config): 在config(nlog.config)中:

<target type="file" filename="Log_${var:UserId_From_DB}_${date:format=yyyy-MM-dd}.log" ..>

If the value is set again, the filename will automatically changed. 如果再次设置该值,文件名将自动更改。

While the posted answer works, it suffers from concurrency issues. 虽然发布的答案有效,但它会遇到并发问题。 That variable is a global variable and you may end up with conflicts. 该变量是一个全局变量,您最终可能会遇到冲突。

There is a better solution available. 有一个更好的解决方案。 There is a way to pass event properties to NLog. 有一种方法可以将事件属性传递给NLog。

Link to the relevant NLog documentation . 链接到相关的NLog文档

Let's assume you want to log an error message: 假设您要记录错误消息:

Logger myLog = LogManager.GetLogger(name);
LogLevel level = LogLevel.Error;
string message = "This is an error message!";

You turn this information into a LogEventInfo object: 您将此信息转换为LogEventInfo对象:

LogEventInfo logEvent = new LogEventInfo(level , myLog.Name, message);

You can then add properties to this event (the string indexes are free to choose): 然后,您可以向此事件添加属性(可以自由选择字符串索引):

logEvent.Properties["MySpecialValue"] = "SPECIAL";

And then you write to the log: 然后你写日志:

myLog.Log(logEvent);

The interesting thing here is that in your NLog configuration, you can use this custom property in any field that the Nlog documentation refers to as a "Layout" value . 这里有趣的是,在NLog配置中, 您可以在Nlog文档引用的任何字段中将此自定义属性用作“布局”值

You use ${event-properties:item=MySpecialValue} in the layout to access the property. 您可以在布局中使用${event-properties:item=MySpecialValue}来访问该属性。 For example: 例如:

<target xsi:type="File" 
        name="file" 
        fileName="${basedir}/logs/${event-properties:item=MySpecialValue}/my_${event-properties:item=MySpecialValue}_file.log"
        layout="${event-properties:item=MySpecialValue} ${message}" />

Following the posted example, you will get a folder named SPECIAL , inside of which is a log file named my_SPECIAL_file.log in which you find the message SPECIAL This is an error message! 在发布的示例之后,您将获得一个名为SPECIAL的文件夹,其中有一个名为my_SPECIAL_file.log的日志文件,您可以在其中找到消息SPECIAL This is an error message! . Just to prove the point that you can use this custom value in many different ways and shapes. 只是为了证明您可以在许多不同的方式和形状中使用此自定义值。


I commonly use this to make entity-specific logging (where the filename of the log equals the entity's ID value), which is essentially the same as you want to do here. 我通常使用它来进行特定于实体的日志记录(其中日志的文件名等于实体的ID值),这与您在此处要执行的操作基本相同。

As a quick tip, I tend to wrap the NLog Logger in a class of my own: 作为一个快速提示,我倾向于将NLog Logger包装在我自己的类中:

public class UserLogger
{
    private readonly Logger _log;
    private readonly User _user;

    public UserLogger(User u)
    {
        _user = u;
        _log = LogManager.GetCurrentClassLogger();
    }

    public void Error(string message)
    {
        LogEventInfo logEvent = 
                 new LogEventInfo(LogLevel.Error, _log.Name, message);

        logEvent.Properties["UserId"] = _user.Id;

        _log.Log(logEvent);
    }
}

This is just a simple example to get you started. 这只是一个简单的例子,可以帮助您入门。 The cool feature I'm using here is that I've defined the log's filename (in the Nlog.Config target) using the UserId value and thus can ensure that each user gets logged to their own unique log file. 我在这里使用的很酷的功能是我使用UserId值定义了日志的文件名(在Nlog.Config目标中),因此可以确保每个用户都登录到他们自己的唯一日志文件。

This way, you can enforce that the user ID is known when you want to log to the "user log" target. 这样,您可以强制在要登录“用户日志”目标时知道用户ID。 As an additional bonus, it also neatly decouples NLog dependencies from your calling code. 作为额外的奖励,它还可以巧妙地将NLog依赖项与您的调用代码分离。

Assuming you have a log file called mylogfile.log in your nlog.config file 假设您的nlog.config文件中有一个名为mylogfile.log的日志文件

FileTarget target = LogManager.Configuration.FindTargetByName("mylogfile.log") as FileTarget; 
String customlog = "Log_" +  GetUserId(UserId_From_DB) + "_" + DateTime.Now.ToString("yyyy-MM-dd") + ".log"; 
target.FileName = customlog; 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM