NLog "final" 规则的 Serilog 替代方案

Alternative in Serilog for NLog's "final" rule

可以这样配置 NLog:

<rules>
 <logger name="Microsoft.EntityFrameworkCore.*" minlevel="Trace" writeTo="file-ef" final="true" />
 <logger name="Microsoft.*" minlevel="Trace" writeTo="file-http,console" final="true" />
 <logger name="*" minlevel="Trace" writeTo="file,console" />
</rules>

rulesfinal 关键字可以为以下对象使用单独的目标:

  1. Microsoft.EntityFrameworkCore.* 记录器
  2. 其他 Microsoft.* 个记录器
  3. 所有其他记录器

配置简单明了,我可以轻松添加另一个条件,而无需修改所有其他规则。

用 Serilog 做同样的事情我必须写下面的代码:

const string format = "[{Timestamp:HH:mm:ss.fff} {ThreadId} {Level:u3}] {Message:lj} [{SourceContext}] {NewLine}{Exception}";
Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Verbose()
            .Enrich.FromLogContext()
            .Enrich.WithThreadId()
            .WriteTo.Console(outputTemplate: format)
            .WriteTo.Logger(cfg => cfg
                .Filter.ByIncludingOnly(Matching.FromSource("Microsoft.AspNetCore"))
                .WriteTo.RollingFile(@"logs\{Date}.http.log", outputTemplate: format, retainedFileCountLimit: null, buffered: true))
            .WriteTo.Logger(cfg => cfg
                .Filter.ByIncludingOnly(Matching.FromSource("Microsoft.EntityFrameworkCore"))
                .WriteTo.RollingFile(@"logs\{Date}.ef.log", outputTemplate: format, retainedFileCountLimit: null, buffered: true))
            .WriteTo.Logger(cfg => cfg.Filter
                .ByExcluding(Matching.FromSource("Microsoft"))
                .WriteTo.RollingFile(@"logs\{Date}.log", outputTemplate: format, retainedFileCountLimit: null, buffered: true))
            .CreateLogger();

要添加另一个条件,我必须将其从所有其他过滤器中排除。

问题:我是不是遗漏了什么,或者如果有匹配的规则,没有简单的方法可以跳过其他规则?

这不是 Serilog 的 API 特别强大的场景, 但 Serilog.Sinks.Map 涵盖了这种情况。

    // Install-Package Serilog.Sinks.Map -Pre

    var isAsp = Matching.FromSource("Microsoft.AspNetCore");
    var isEF = Matching.FromSource("Microsoft.EntityFrameworkCore");
    var isMS = Matching.FromSource("Microsoft");

    Log.Logger = new LoggerConfiguration()
        .WriteTo.Map(le => isAsp(le) ? ".http" :
                            isEF(le) ? ".ef" :
                            !isMS(le) ? ".other" :
                            "",
            (slug, wt) => wt.RollingFile($"logs\{{Date}}{slug}.log"))
        .CreateLogger();