簡體   English   中英

根據上下文源將 Serilog 日志過濾到不同的接收器?

[英]Filter Serilog logs to different sinks depending on context source?

我有一個 .NET Core 2.0 應用程序,我在其中成功使用 Serilog 進行日志記錄。 現在,我想將一些數據庫性能統計信息記錄到一個單獨的接收器(它們不是用於調試,這基本上是應用程序中所有其他日志記錄的目的,所以我想將它們分開)並認為這可以完成通過使用Log.ForContext<MyClass>()創建數據庫統計記錄器。

我不知道應該如何使用我的 appsettings.json將我的“調試日志”記錄到一個接收器並將我的數據庫統計信息記錄到另一個接收器來配置 Serilog? 我希望可以做類似的事情:

"Serilog": {
  "WriteTo": [
    {
      "Name": "RollingFile",
      "pathFormat": "logs/Log-{Date}.log",
      "Filter": {
        "ByExcluding": "FromSource(MyClass)"
      }
    },
    {
      "Name": "RollingFile",
      "pathFormat": "logs/DBStat-{Date}.log",
      "Filter": {
          "ByIncludingOnly": "FromSource(MyClass)"
      }
    }
  ]
}

配置的"Filter"部分純屬我的猜測。 這可能使用我的配置文件管理器,還是我需要在我的Startup.cs文件中的代碼中執行此操作?

編輯:我已經使用 C# API 讓它工作,但仍然想使用 JSON 配置來解決它:

Log.Logger = new LoggerConfiguration()
            .WriteTo.Logger(lc => lc
                .Filter.ByExcluding(Matching.FromSource<MyClass>())
                .WriteTo.LiterateConsole())
            .WriteTo.Logger(lc => lc
                .Filter.ByExcluding(Matching.FromSource<MyClass>())
                .WriteTo.RollingFile("logs/DebugLog-{Date}.log"))
            .WriteTo.Logger(lc => lc
                .Filter.ByIncludingOnly(Matching.FromSource<MyClass>())
                .WriteTo.RollingFile("logs/DBStats-{Date}.log", outputTemplate: "{Message}{NewLine}"))
            .CreateLogger();

我今天完成了這項工作,並認為我會提供一個正確的答案,因為我花了很多帖子、問題和其他頁面來解決這個問題。

擁有所有日志很有用,但我也想單獨記錄我的 API 代碼,並省略Microsoft. 命名空間日志。 執行此操作的 JSON 配置如下所示:

  "Serilog": {
    "Using": [ "Serilog.Sinks.File" ],
    "MinimumLevel": "Debug",
    "WriteTo": [
      {
        "Name": "File",
        "Args": {
          "path": "/var/logs/system.log",
          ... //other unrelated file config
        }
      },
      {
        "Name": "Logger",
        "Args": {
          "configureLogger": {
            "WriteTo": [
              {
                "Name": "File",
                "Args": {
                  "path": "/var/logs/api.log",
                  ... //other unrelated file config
                }
              }
            ],
            "Filter": [
              {
                "Name": "ByExcluding",
                "Args": {
                  "expression": "StartsWith(SourceContext, 'Microsoft.')"
                }
              }
            ]
          }
        }
      }
    ],
    "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
    ... //Destructure and other config
  }

頂級WriteTo是第一個簡單的全局接收器。 所有日志事件都寫入此。 如果在與此相同的級別添加Filter部分,它將影響所有已配置的WriteTo元素。

然后我將另一個WriteTo配置為Logger (不是File ),但是它的Args看起來不同,並且有一個configureLogger元素,它與頂級的Serilog具有相同的用途,也就是說,它是子的頂級-記錄器。 這意味着您可以輕松地將其配置拆分為一個單獨的文件,並將其添加到配置構建器中(見底部)。

從這里開始,這個子記錄器的工作方式是一樣的:你可以配置多個WriteTo ,這個級別的Filter元素只會影響這個子記錄器。

只需將更多"Name": "Logger"元素添加到頂級WriteTo部分,並分別為每個元素設置過濾器。

注意同樣重要的是要注意,即使您在 config 中執行所有這些操作並且沒有在代碼中引用Serilog.Filters.Expressions包的一個位,您仍然必須Serilog.Filters.Expressions包添加 NuGet 引用。 如果沒有包引用,它就無法工作

關於拆分配置:

如果我必須添加更多記錄器,為了清楚起見,我肯定會將不同的記錄器拆分為單獨的文件,例如

appsettings.json:

  "Serilog": {
    "Using": [ "Serilog.Sinks.File" ],
    "MinimumLevel": "Error",
    "WriteTo": [
      {
        "Name": "File",
        "Args": {
          "path": "/var/logs/system.log",
          ...
        }
      },
      {
        "Name": "Logger",
        "Args": {
          "configureLogger": {} // leave this empty
        }
      }
    ],
    "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
    ...

apilogger.json:

{
  "Serilog:WriteTo:1:Args:configureLogger": {   //notice this key
    "WriteTo": [
      {
        "Name": "File",
        "Args": {
          "path": "/var/logs/api_separateFile.log",
          ...
        }
      }
    ],
    "Filter": [
      {
        "Name": "ByExcluding",
        "Args": {
          "expression": "StartsWith(SourceContext, 'Microsoft.')"
        }
      }
    ]
  }
}

然后調整我的IWebHost構建器以包含額外的配置:

    WebHost.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            config.AddJsonFile("apilogger.json", optional: false, reloadOnChange: false);
        })
        .UseStartup<Startup>();

這樣更容易理解、閱讀和維護。

我不得不做類似的事情,但在代碼中,而不是 JSON。使用記錄器作為接收器,如https://github.com/serilog/serilog/wiki/Configuration-Basics底部所述,成功了。

在我的例子中,我想將所有內容記錄到一個文件和控制台,除了來自特定源的消息應該 go 只到文件:

private static bool SourceContextEquals(LogEvent logEvent, Type sourceContext)
    => logEvent.Properties.GetValueOrDefault("SourceContext") is ScalarValue sv && sv.Value?.ToString() == sourceContext.FullName;

private static ILogger CreateLogger() =>
    new LoggerConfiguration()
        .WriteTo.File("mylog.log")
        .WriteTo.Logger(lc =>
            lc.Filter.ByExcluding(le => SourceContextEquals(le, typeof(TypeThatShouldLogOnlyToFile)))
           .WriteTo.Console()
        )
        .CreateLogger();

下面只將實體框架日志寫入文件,但我們需要安裝 Serilog.Filters.Expressions nuget 包

"Serilog": {
    "MinimumLevel": {
      "Default": "Debug",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning",
        "Microsoft.EntityFrameworkCore": "Information"
      }
    },
    "WriteTo": [
      {
        "Name": "Logger",
        "Args": {
          "configureLogger": {
            "Filter": [
              {
                "Name": "ByIncludingOnly",
                "Args": {
                  "expression": "StartsWith(SourceContext, 'Microsoft.EntityFrameworkCore')"
                }
              }
            ],
            "WriteTo": [
              {
                "Name": "File",
                "Args": {
                  "path": "C:\\LOGS\\TestService_EF_.json",
                  "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}",
                  "rollingInterval": "Day",
                  "retainedFileCountLimit": 7
                }
              }
            ]
          }
        }
      }
    ]
  }

暫無
暫無

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

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