簡體   English   中英

NLog 多個記錄器在同一個 class

[英]NLog multiple loggers in same class

我有一個 class 應該像往常一樣記錄,但有時它應該記錄到特定目標(例如文件)。

這是我的 NLog 配置文件:

nlog.config

<?xml version="1.0" encoding="utf-8" ?>
<!-- XSD manual extracted from package NLog.Schema: https://www.nuget.org/packages/NLog.Schema-->
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      internalLogFile="C:\Logs\logfile.log"
      internalLogLevel="Info" >

  <targets>
    <target xsi:type="File" name="logfile" fileName="C:\Logs\logfile.log"
            layout="${longdate}|${level}|${message} |${all-event-properties} ${exception:format=tostring}" />
    <target xsi:type="Console" name="logconsole"
            layout="${longdate}|${level}|${message} |${all-event-properties} ${exception:format=tostring}" />
  </targets>

  <!-- rules to map from logger name to target -->
  <rules>
    <logger name="*" minlevel="Trace" writeTo="logfile,logconsole" />
  </rules>
</nlog>

和額外的.config

<?xml version="1.0" encoding="utf-8" ?>
<!-- XSD manual extracted from package NLog.Schema: https://www.nuget.org/packages/NLog.Schema-->
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      internalLogFile="C:\Logs\extra.log"
      internalLogLevel="Info" >

  <targets>
    <target xsi:type="File" name="extra" fileName="C:\Logs\extra.log"
            layout="${longdate}|${level}|${message} |${all-event-properties} ${exception:format=tostring}" />
  </targets>

  <!-- rules to map from logger name to target -->
  <rules>
    <logger name="*" minlevel="Trace" writeTo="extra" />
  </rules>
</nlog>

我正在嘗試這樣的事情:

public class Program
{

    private static IConfiguration _configuration;

    public static void Main(string[] args)
    {
        var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
        try
        {
            logger.Debug("init main");
            var environment = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT") ?? "Production";

            _configuration = new ConfigurationBuilder()
                .AddEnvironmentVariables()
                .AddJsonFile("appsettings.json", false)
                .AddJsonFile($"appsettings.{environment}.json", true)
                .Build();
            CreateHostBuilder(args).Build().Run();
        }
        catch (Exception exception)
        {
            //NLog: catch setup errors
            logger.Error(exception, "Stopped program because of exception");
            throw;
        }
        finally
        {
            // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
            NLog.LogManager.Shutdown();
        }
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host
        .CreateDefaultBuilder(args)
        .ConfigureLogging(logBuilder =>
        {
            logBuilder.ClearProviders();
            logBuilder.SetMinimumLevel(LogLevel.Trace);
        })
        .ConfigureServices((hostContext, services) =>
        {
            //serviceConfig
        })
        .UseNLog()
        .UseWindowsService();
}

class 我想要兩個記錄器:

public class MyClass
{
    private readonly ILogger<MyClass> _logger;
    private readonly Logger _extraLogger;

    public MyClass(ILogger<MyClass> logger)
    {
        _logger = logger;
        _extraLogger = NLogBuilder.ConfigureNLog("extra.config").GetLogger("extra");
    }

    public void doBothTypesOfLogging()
    {
        var msg = "Hello";
        _extraLogger.Info(msg);
        _logger.LogInformation("Message sendt");
    }
}

但這使得應用程序(甚至其他類)完成的所有日志記錄最終都在由 extra.config 定義的extra.log文件中。 例如。 msg"Message sendt"都以該文件結尾。

我想要的是擁有

logfile.log中的"Message sendt"

msg中的extra.log

這有可能嗎?

為什么要在同一個 class 上創建兩個日志? 如果您的 class 上有一個子組件,您想單獨記錄它,那么沒關系,您只需要一個適當的配置文件......但是,通常,這將是一種代碼味道。

你可以用一個配置做你想做的一切:

<?xml version="1.0" encoding="utf-8" ?>
<!-- XSD manual extracted from package NLog.Schema: https://www.nuget.org/packages/NLog.Schema-->
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      internalLogFile="C:\Logs\logfile.log"
      internalLogLevel="Info" >

  <targets>
    <target xsi:type="File" name="logfile" fileName="C:\Logs\logfile.log"
            layout="${longdate}|${level}|${message} |${all-event-properties} ${exception:format=tostring}" />
    <target xsi:type="Console" name="logconsole"
            layout="${longdate}|${level}|${message} |${all-event-properties} ${exception:format=tostring}" />
<target xsi:type="File" name="extra" fileName="C:\Logs\extra.log"
        layout="${longdate}|${level}|${message} |${all-event-properties} ${exception:format=tostring}" />
  </targets>

  <!-- rules to map from logger name to target -->
  <rules>
    <logger name="extra" minlevel="Trace" writeTo="extra" final="true" />
    <logger name="*" minlevel="Trace" writeTo="logfile,logconsole" />
  </rules>
</nlog>

注意“extra”日志規則中的“final”屬性。 它將防止將額外的日志寫入其他日志。

無需使用不同的配置創建此記錄器。 只需執行以下操作:

public class MyClass
{
    private readonly ILogger<MyClass> _logger;
    private readonly Logger _extraLogger = LogManager.GetLogger("extra");

    public MyClass(ILogger<MyClass> logger)
    {
        _logger = logger;
    }

    public void doBothTypesOfLogging()
    {
        var msg = "Hello";
        _extraLogger.Info(msg);
        _logger.LogInformation("Message sendt");
    }
}

但我認為你應該重新考慮是否真的需要兩個記錄器來處理同一個 class。

更新


根據您的需要,您可以通過使用開箱即用的 NLog 功能並遵循更加 nlogish 的模式來大大簡化您的代碼。 配置文件幾乎相同,只是將“extra”記錄器的規則更改為“syslog”,因為我們將在代碼中更改它的名稱:

<?xml version="1.0" encoding="utf-8" ?>
<!-- XSD manual extracted from package NLog.Schema: https://www.nuget.org/packages/NLog.Schema-->
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      internalLogFile="C:\Logs\logfile.log"
      internalLogLevel="Info" >

  <targets>
    <target xsi:type="File" name="logfile" fileName="C:\Logs\logfile.log"
            layout="${longdate}|${level}|${message} |${all-event-properties} ${exception:format=tostring}" />
    <target xsi:type="Console" name="logconsole"
            layout="${longdate}|${level}|${message} |${all-event-properties} ${exception:format=tostring}" />
    <!-- This will probably be a network target -->
    <target xsi:type="File" name="extra" fileName="C:\Logs\extra.log"
            layout="${longdate}|${level}|${message} |${all-event-properties} ${exception:format=tostring}" />
  </targets>

  <!-- rules to map from logger name to target -->
  <rules>
    <logger name="syslog" minlevel="Trace" writeTo="extra" final="true" />
    <logger name="*" minlevel="Trace" writeTo="logfile,logconsole" />
  </rules>
</nlog>

我們將把“syslog”記錄器放在一個幫助器 static class 中的 static 變量中:

public static class CommonLoggers
{
    public static Logger SysLogger { get; private set; } = LogManager.GetLogger("syslog");
   // you can put other centralized loggers here if you want
}

然后,您應該將 class 代碼更改為:

public class MyClass
{
    // the "correct" pattern is to use a logger that follows the class name
    // put this in each class you create
    private static Logger logger = LogManager.GetCurrentClassLogger();
    
    // nothing to do on the constructor (can be removed as it's redundant)
    public MyClass() { }

    public void doBothTypesOfLogging() {
        var msg = "Hello";
        CommonLoggers.SysLogger.Info(msg);
        logger.Info("Message sent");
    }
}

重要的部分是要了解 NLog 規則用於過濾 output 給定記錄器名稱,您可以執行以下操作,例如:

  <rules>
    <logger name="SomeNamespace.Somewhere.*" minlevel="Trace" writeTo="extra"  final="true"/>
    <logger name="SomeNamespace.SomewhereElse.MyClass" minlevel="Info" writeTo="some_other_target" />
    <logger name="*" minlevel="error" writeTo="logfile" />
    <logger name="*" minlevel="info" writeTo="logconsole" />
  </rules>

這樣,您可以將“SomeNamespace.Somewhere.*”中所有類的所有日志跟蹤到“額外”目標。 將“MyClass”的所有 INFO 日志寫入“some_other_target”。 將 ERROR 消息發送到“logfile”,將 INFO 消息發送到“logconsole”。

閱讀有關規則、目標和過濾器的文檔將對您有很大幫助!

這是一篇好文章: https://www.codeproject.com/Articles/4051307/NLog-Rules-and-filters

官方文檔: https://github.com/nlog/nlog/wiki/Configuration-file#rules

還有這個精彩的 SO 問題: 最有用的 NLog 配置

快樂閱讀!

而不是直接使用 NLog LogManager,那么我建議你留在 ILogger-path 上,但像這樣調用ILoggerFactory

public class MyClass
{
    private readonly ILogger _logger;
    private readonly ILogger _extraLogger;

    public MyClass(ILoggerFactory logfactory)
    {
        _logger = logfactory.CreateLogger(GetType().ToString());
        _extraLogger = logfactory.CreateLogger("extra");
    }

    public void doBothTypesOfLogging()
    {
        var msg = "Hello";
        _extraLogger.LogInformation(msg);
        _logger.LogInformation("Message sendt");
    }
}

但我同意接受的答案,即應該使用單個NLog.config

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM