过滤器Serilog根据上下文源记录到不同的接收器?

Dav*_*all 19 c# logging serilog .net-core asp.net-core

我有一个.NET Core 2.0应用程序,我成功地使用Serilog进行日志记录.现在,我想将一些数据库性能统计信息记录到一个单独的接收器(它们不用于调试,这基本上是应用程序中所有其他日志记录的目的,因此我希望将它们分开)并认为这可以完成通过创建数据库统计记录器Log.ForContext<MyClass>().

我不知道我应该如何配置Serilog 使用我的appsettings.json将我的"调试日志"记录到一个接收器并将我的数据库统计信息记录到另一个接收器?我希望可以这样做:

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

"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();
Run Code Online (Sandbox Code Playgroud)

hel*_*rve 16

我今天完成了这项工作,并认为我会提供一个正确的答案,因为它花了我很多帖子,问题和其他页面来解决这个问题.

拥有所有日志很有用,但我还想单独记录我的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
  }
Run Code Online (Sandbox Code Playgroud)

顶级WriteTo是第一个简单的全局接收器.所有日志事件都写入此内容.如果Filter在与此相同的级别上添加部分,则会影响所有已配置的WriteTo元素.

然后我将另一个配置WriteToLogger(不File),但Argsfor for看起来不同,并且有一个与顶层configureLogger具有相同目的的元素,Serilog也就是说,它是子记录器的顶层.这意味着您可以轻松地将配置拆分为单独的文件,并在配置构建器中另外添加(参见下图).

从这里开始,此子记录器的工作方式相同:您可以配置多个WriteTos,Filter此级别的元素将仅影响此子记录器.

只需"Name": "Logger"在顶层WriteTo部分添加更多元素,并分别为每个元素设置过滤器.

注意 同样重要的是要注意,即使您在配置中执行所有这些操作而不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" ],
    ...
Run Code Online (Sandbox Code Playgroud)

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.')"
        }
      }
    ]
  }
}
Run Code Online (Sandbox Code Playgroud)

然后调整我的IWebHost构建器以包含其他配置:

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

这样,它更容易理解,阅读和维护.

  • 这并没有完全解决我的问题,但已经是最完整的,几乎是我正在寻找的,我可以通过谷歌找到的响应。谢谢你! (3认同)
  • 是的。“Hangfire”是一个特定的接收器,很像“File”或“AppInsights”之类的东西。“Logger”就像配置中用于设置子记录器的保留字,您可以在其中指定更多特定的接收器。也许可以将此处的“Logger”视为代码中的“ILoggerFactory”的等效项。 (2认同)

EM0*_*EM0 7

我必须做类似的事情,但是用代码,而不是 JSON。使用记录器作为接收器,如https://github.com/serilog/serilog/wiki/Configuration-Basics底部所述,可以达到目的。

就我而言,我想将所有内容记录到文件和控制台,除了来自特定源的消息应该只发送到文件:

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();
Run Code Online (Sandbox Code Playgroud)


vin*_*eel 5

下面仅将实体框架日志写入文件,但我们需要安装 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
                }
              }
            ]
          }
        }
      }
    ]
  }
Run Code Online (Sandbox Code Playgroud)