如何使用NLog保存在两个不同的文件中?

时间:2018-11-29 12:41:03

标签: c# .net asp.net-mvc nlog quartz.net

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

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;

2 个答案:

答案 0 :(得分:1)

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

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;

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

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

有关我添加的loggerNamePattern属性,请参见NLog documentation

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

答案 1 :(得分:0)

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

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

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

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

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

最后致电ReconfigExistingLoggers。 (请参见ReconfigExistingLoggersthis answerthis forum entry

NLog.LogManager.ReconfigExistingLoggers();

这些作业很可能是并发的,因此需要locking mechanism

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

这里是完整样本。

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

<?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 image description here