关于c#:如何使用NLog保存在两个不同的文件中?

How save in two distinct files using NLog?

我在MVC中有一个Web应用程序,该应用程序使用NLog和Quartz运行某些作业。
我需要将作业的日志保存在另一个文件中,但是由于我只有一个LogManager到应用程序,因此我无法找到一种方法来执行此操作。
试图使用其他目标,但没有成功。
有谁知道该怎么做?
以下是我今天使用的内容:

1
2
3
4
var config = new NLog.Config.LoggingConfiguration();
var logfile = new NLog.Targets.FileTarget("logfile") { FileName = ArquivoLog, Name="logfile", CreateDirs = true, Layout = FormatoLog, ArchiveEvery = NLog.Targets.FileArchivePeriod.Day, ArchiveNumbering = NLog.Targets.ArchiveNumberingMode.DateAndSequence, MaxArchiveFiles = 31, WriteFooterOnArchivingOnly = true, KeepFileOpen = true, OpenFileCacheTimeout = 30 };
config.AddRule(LogLevel.Trace, LogLevel.Fatal, logfile);
NLog.LogManager.Configuration = config;


要通过NLog.config文件执行此操作,请参阅Andrew Tarasenko的答案。
如果要在代码中进行操作,是否尝试过以下方法?

1
2
3
4
5
6
7
8
9
var config = new NLog.Config.LoggingConfiguration();

var logfile = new NLog.Targets.FileTarget("logfile1") { FileName = ArquivoLog, Name="logfile1", CreateDirs = true, Layout = FormatoLog, ArchiveEvery = NLog.Targets.FileArchivePeriod.Day, ArchiveNumbering = NLog.Targets.ArchiveNumberingMode.DateAndSequence, MaxArchiveFiles = 31, WriteFooterOnArchivingOnly = true, KeepFileOpen = true, OpenFileCacheTimeout = 30 };
var logfile2 = new NLog.Targets.FileTarget("logfile2") { FileName = ArquivoLog, /* Name="NotReallyNeeded as it is already passed in constructor" */, CreateDirs = true, Layout = FormatoLog, ArchiveEvery = NLog.Targets.FileArchivePeriod.Day, ArchiveNumbering = NLog.Targets.ArchiveNumberingMode.DateAndSequence, MaxArchiveFiles = 31, WriteFooterOnArchivingOnly = true, KeepFileOpen = true, OpenFileCacheTimeout = 30 };

config.AddRule(LogLevel.Trace, LogLevel.Fatal, logfile1,"Job1");
config.AddRule(LogLevel.Trace, LogLevel.Fatal, logfile2,"Job2");

NLog.LogManager.Configuration = config;

然后在工作中,您应该创建一个这样的记录器

1
2
var loggerInJob1 = NLog.LogManager.GetLogger("Job1");
var loggerInJob2 = NLog.LogManager.GetLogger("Job2");

有关我添加的loggerNamePattern属性,请参阅NLog文档。

这样,每个作业的日志将保存到其他日志文件中。
我个人将采用NLog.config方式。这样一来,无需重新编译代码即可轻松添加新目标(用于新作业)。
但是不知道您的解决方案是否有可能。


如果事先不知道作业数,并且每个作业要求一个日志文件,则可以在每个作业开始时以编程方式更新NLog配置。

在作业开始时,创建一个新的NLog目标。

1
2
3
4
5
6
7
var target = new NLog.Targets.FileTarget()
{
    FileName = $"Arquivo{jobNumber}.Log",
    Name = $"logfile{jobNumber}",
    Layout ="${logger} ${longdate} ${level} ${message}",
    //add settings are required
};

然后获取现有的NLog配置,添加目标并为目标添加规则。

1
2
3
var config = NLog.LogManager.Configuration;
config.AddTarget(target);
config.AddRuleForAllLevels(target, loggerName);

最后调用ReconfigExistingLoggers。 (请参阅ReconfigExistingLoggers,此答案和此论坛条目)

1
NLog.LogManager.ReconfigExistingLoggers();

这些作业很可能是并发的,因此需要一种锁定机制。

即使存在Nlog.config文件,上面的代码也会追加到现有配置中。

这里是完整样本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
using NLog;
using System.Threading;
using System.Threading.Tasks;
using NLog.Config;

namespace ConsoleApplication2
{
class Program
{
    private static readonly object LoggerSynchronization = new object();

    static void Main(string[] args)
    {
        //create some jobs
        int numberOfJobs = 5;
        for (int i = 0; i < numberOfJobs; i++)
        {
            var jobNumber = i;
            Task.Run(() => RunJob(jobNumber));
        }

        Thread.Sleep(1000); //wait till done
    }

    private static void RunJob(int jobNumber)
    {
        var logger = SetupLog(jobNumber);

        logger.Info($"Running job {jobNumber}.");

        //do stuff here ...

    }

    private static Logger SetupLog(int jobNumber)
    {
        var loggerName = $"Job{jobNumber}";

        //create a custom target per job
        var target = new NLog.Targets.FileTarget()
        {
            FileName = $"Arquivo{jobNumber}.Log",
            Name = $"logfile{jobNumber}",
            Layout ="${logger} ${longdate} ${level} ${message}",
        };

        //add the target to the configuration
        lock (LoggerSynchronization) //avoid concurrency issues between the jobs
        {
            //check if configuration exists
            if (NLog.LogManager.Configuration == null)
            {
                NLog.LogManager.Configuration = new LoggingConfiguration();
            }

            var config = NLog.LogManager.Configuration;
            config.AddTarget(target);
            config.AddRuleForAllLevels(target, loggerName);

            NLog.LogManager.ReconfigExistingLoggers();
        }
        return NLog.LogManager.GetLogger(loggerName);
    }
}
}

并采样NLog.config

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      throwExceptions="false">

  <targets>
    <target name="console" xsi:type="ColoredConsole" layout="${logger} ${longdate} ${level} ${message}" />
  </targets>


  <rules>
    <logger name="*" writeTo="console" minlevel="Info" />
  </rules>
</nlog>

样本输出

enter