【问题标题】:How save in two distinct files using NLog?如何使用 NLog 保存在两个不同的文件中?
【发布时间】:2018-11-29 12:41:02
【问题描述】:

我在 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;

【问题讨论】:

  • 如果您了解开发过程中的工作,您可以使用多个记录器目标。如果没有,您可以在文件名中使用标签(称为layout renderers)。您可以为每个作业使用不同的记录器,并使用 "${logger}.txt" 作为文件名。

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


【解决方案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 方式。这样,无需重新编译代码即可更轻松地添加新目标(用于新作业)。
但不知道您的解决方案是否可行。

【讨论】:

    【解决方案2】:

    如果事先不知道作业的数量并且要求每个作业一个日志文件,则可以在每个作业开始时以编程方式更新 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>
    

    样本输出

    【讨论】:

    • 不需要NLog.LogManager.Configuration.Reload();
    猜你喜欢
    • 1970-01-01
    • 2020-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多