根据方法参数使用不同的日志文件
本文关键字:日志 文件 方法 参数 | 更新日期: 2023-09-27 18:19:15
我有一个函数:processData(string taskName)我想生成多个日志文件,其中包含taskName参数在他们的路径使用NLog
例如:
processData("task1")应该只记录到C:'log_task1.txt
processData("task2")应该只记录到C:'log_task2.txt
processData("task3")应该只记录到C:'log_task3.txt
等等
注意:我事先不知道参数的值。这只是一个例子
在NLog配置中,为每个日志文件创建不同的规则:
<targets>
<target name="logfile1"
xsi:type="File"
fileName="C:'log_task1.log" />
<target name="logfile2"
xsi:type="File"
fileName="C:'log_task2.log" />
<target name="logfile3"
xsi:type="File"
fileName="C:'log_task3.log" />
</targets>
<rules>
<logger name="task1"
minlevel="Trace"
writeTo="logfile1" />
<logger name="task2"
minlevel="Trace"
writeTo="logfile2" />
<logger name="task3"
minlevel="Trace"
writeTo="logfile3" />
</rules>
然后,在你的方法中,使用相应的NLog记录器:
public void ProcessData(string param)
{
var logger = NLog.LogManager.GetLogger(param);
}
如果你事先不知道参数的值,你可以在运行时以编程方式创建NLog配置(但不要忘记只允许白名单参数值,以防止攻击者在选择的位置覆盖现有文件)。这里描述了如何通过编程方式配置NLog:
NLog Configuration API
代码应该是这样的(只是写下来没有测试):
public void AddLogTarget(string param)
{
if (NLog.LogManager.Configuration.FindTargetByName(param) == null)
{
var target = new FileTarget
{
Name = param,
FileName = @"C:'" + param + ".log"
};
NLog.LogManager.Configuration.AddTarget(param, target);
NLog.LogManager.Configuration.LoggingRules.Add(new LoggingRule(param, LogLevel.Debug, target));
}
}
有一个选项可能有效,但是使用它需要您付出一些努力。
NLog能够通过大多数LayoutRenderers命名日志文件。在您的情况下,您可以这样配置您的File目标:
<target name="FileTarget" xsi:type="File" fileName="${gdc:item=Task}.log" layout=${longdate} | ${logger} | ${level} | ${message}" />
然后,在执行任务时,可以根据任务名称设置GlobalDiagnosticContext:
void processData(String taskName)
{
GlobalDiagnosticContext.Set("Task", taskName);
log.Info("Hello from processData. This should be in {0}.log", taskName);
GlobalDiagnosticContext.Remove("Task");
}
这将导致所有被写入的日志消息被写入所需的日志文件。
如果您的应用程序是单线程的,这可能工作得很好,所以您不必担心同时执行processData之间的冲突。
如果您正在使用线程,您可能会以同样的方式使用ThreadDiagnosticContext获得良好的结果。
另一个想法是手动创建LogEventInfo对象并使用Log方法自己记录它们。像这样:
var LogEventInfo le = new LogEventInfo(LogLevel.Info, logger.Name, "Hello!");
le.Properties["Task"] = taskName;
logger.Log(le);
在这种情况下,你将使用EventContext LayoutRenderer来构建日志文件名:
<target name="FileTarget" xsi:type="File" fileName="${event-context:item=Task}.log" layout=${longdate} | ${logger} | ${level} | ${message}" />
你可以包装NLog记录器,或者你可以写一个扩展方法,这样你就不必在每个日志站点都建立一个LogEventInfo对象。
例如:public static class NLogExtensions
{
public static void Log(this Logger logger, string task, LogLevel level, string message)
{
var LogEventInfo le = new LogEventInfo(level, logger.Name, message);
le.Properties["Task"] = task;
logger.Log(typeof(NLogExtensions), le);
}
}
使用Type作为第一个参数的Log签名是为了保证呼叫局点信息的正常记录。
查看我的回答,这里有一个关于通过扩展方法"包装"NLog的简短讨论:
NLog可以通过c#扩展方法保存callsite信息吗?