C# Serilog:如何进一步增强appsettings.json中的过滤器表达式?

C# Serilog:如何进一步增强appsettings.json中的过滤器表达式?,c#,.net-core,serilog,C#,.net Core,Serilog,我有两个带有Serilog的记录器,它们保存到不同的文件中。我想通过appsettings.json而不是代码来创建记录器 当我通过Startup.cs配置创建日志时,我会得到一个更具体的日志,我更喜欢这样,因为它更清晰,可以让其他人检查日志并了解正在发生的事情,而不需要太多的技术知识。但是,我希望将其应用于appsettings,以便可以将代码迁移到可能使用的任何其他项目。 仅供参考:我不想覆盖日志级别 例如,通过代码,我创建了我的记录器,如下所示: Log.Logger = new Logg

我有两个带有Serilog的记录器,它们保存到不同的文件中。我想通过appsettings.json而不是代码来创建记录器

当我通过
Startup.cs
配置创建日志时,我会得到一个更具体的日志,我更喜欢这样,因为它更清晰,可以让其他人检查日志并了解正在发生的事情,而不需要太多的技术知识。但是,我希望将其应用于appsettings,以便可以将代码迁移到可能使用的任何其他项目。 仅供参考:我不想覆盖日志级别

例如,通过代码,我创建了我的记录器,如下所示:

Log.Logger = new LoggerConfiguration()
    .WriteTo.ColoredConsole()
    .WriteTo.Logger(lc => lc
    .Filter.ByExcluding(Matching.FromSource("Microsoft"))
    .WriteTo.File("Serilogs/Program_log_.txt", rollingInterval: RollingInterval.Day)
    .MinimumLevel.Information()
    .MinimumLevel.Override("Microsoft", LogEventLevel.Information))

    .WriteTo.Logger(lc => lc
    .Filter.ByIncludingOnly(Matching.FromSource("Microsoft"))
    .WriteTo.File("Serilogs/ServerTrace_log_.txt", rollingInterval: RollingInterval.Day)
    .MinimumLevel.Information()
    .MinimumLevel.Override("Microsoft", LogEventLevel.Information))

    .CreateLogger();
 "Serilog": {
    "Using": [
      "Serilog.Sinks.File",
      "Serilog.Filters.Expressions",
      "Serilog.Settings.Configuration"
    ],
    "WriteTo": [
      {
        "Name": "Logger",
        "Args": {
          "configureLogger": {
            "Filter": [
              {
                "Name": "ByIncluding",
                "Args": {
                  "expression": "SourceContext = 'Microsoft'"
                }
              }
            ],
            "WriteTo": [
              {
                "Name": "File",
                "Args": {
                  "path": "./Serilogs/server_logs_.log",
                  "rollingInterval": "Day"
                }
              }
            ]
          }
        }
      },
      {
        "Name": "Logger",
        "Args": {
          "configureLogger": {
            "Filter": [
              {
                "Name": "ByExcluding",
                "Args": {
                  "expression": "SourceContext = 'Microsoft.AspNetCore.Hosting.Internal.WebHost'"
                }
              }
            ],
            "WriteTo": [
              {
                "Name": "File",
                "Args": {
                  "path": "./Serilogs/program_logs_.log",
                  "rollingInterval": "Day"
                }
              }
            ]
          }
        }
      }
    ]
  }
这将生成两个独立的输出,我喜欢它们的格式:
文件1
:可读的自定义日志:

2019-01-18 11:18:09.873 +00:00 [INF] //Some custom log information
2019-01-18 11:18:09.875 +00:00 [INF] //Some more custom log information
2019-01-18 11:22:52.903 +00:00 [INF] User profile is available. Using '// A path' as key repository and Windows DPAPI to encrypt keys at rest.
2019-01-18 11:22:59.229 +00:00 [INF] Route matched with {action = "PollForStatusUpdate", controller = "StatusMessage"}. Executing action {apiname}.{controller}.{method}.PollForStatusUpdate ({apiname})
2019-01-18 11:22:59.505 +00:00 [INF] Executing action method {apiname}.{controller}.{method}.PollForStatusUpdate ({apiname}) with arguments (["{apiname}.{controller}.{method}.MessageResult"]) - Validation state: "Valid"
2019-01-18 11:22:59.632 +00:00 [INF] //Some custom log information
2019-01-18 11:22:59.639 +00:00 [INF] //Some more custom log information
{apiname}.{controller}.{method}.PollForStatusUpdate ({apiname}), returned result Microsoft.AspNetCore.Mvc.OkObjectResult in 516.8129ms.
2019-01-18 11:23:00.040 +00:00 [INF] Executing ObjectResult, writing value of type '{apiname}.{controller}.{method}.MessageResult'.
2019-01-18 11:23:00.048 +00:00 [INF] Executed action {apiname}.{controller}.{method}.PollForStatusUpdate ({apiname}) in 813.08940000000007ms

文件2
:堆栈跟踪,服务器信息:

2019-01-18 11:17:56.378 +00:00 [INF] User profile is available. Using '//A path' as key repository and Windows DPAPI to encrypt keys at rest.
2019-01-18 11:17:57.840 +00:00 [INF] Request starting HTTP/1.1 GET https://localhost:5001/swagger/index.html  
2019-01-18 11:17:58.074 +00:00 [INF] Request finished in 235.5796ms 200 text/html
2019-01-18 11:17:58.326 +00:00 [INF] Request starting HTTP/1.1 GET https://localhost:5001/swagger/v1/swagger.json  
2019-01-18 11:17:58.452 +00:00 [INF] Request finished in 126.2127ms 200 application/json;charset=utf-8 
2019-01-18 11:22:52.903 +00:00 [INF] User profile is available. Using 'C:\Users\msharp\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest.
2019-01-18 11:22:54.263 +00:00 [INF] Request starting HTTP/1.1 GET https://localhost:5001/swagger/index.html  
2019-01-18 11:22:54.473 +00:00 [INF] Request finished in 211.831ms 200 text/html
2019-01-18 11:22:54.737 +00:00 [INF] Request starting HTTP/1.1 GET https://localhost:5001/swagger/v1/swagger.json  
2019-01-18 11:22:54.838 +00:00 [INF] Request finished in 100.8892ms 200 application/json;charset=utf-8
2019-01-18 11:22:59.205 +00:00 [INF] Request starting HTTP/1.1 POST https://localhost:5001/api/StatusMessage/PollForStatusUpdate application/json-patch+json 180
2019-01-18 11:22:59.229 +00:00 [INF] Route matched with {action = "PollForStatusUpdate", controller = "StatusMessage"}. Executing action PureValuationsApi.Controllers.StatusMessageController.PollForStatusUpdate (PureValuationsApi)
2019-01-18 11:22:59.505 +00:00 [INF] Executing action method {apiname}.{controller}.{method}.PollForStatusUpdate ({apiname}) with arguments (["{apiname}.{controller}.{method}.MessageResult"]) - Validation state: "Valid"
2019-01-18 11:22:59.632 +00:00 [INF] //Some custom lof information
2019-01-18 11:22:59.639 +00:00 [INF] //Some more custom log information
{apiname}.{controller}.{method}.PollForStatusUpdate ({apiname}), returned result Microsoft.AspNetCore.Mvc.OkObjectResult in 516.8129ms.
2019-01-18 11:23:00.040 +00:00 [INF] Executing ObjectResult, writing value of type '{apiname}.{controller}.{method}.MessageResult'.
2019-01-18 11:23:00.048 +00:00 [INF] Executed action {apiname}.{controller}.{method}.PollForStatusUpdate ({apiname}) in 813.08940000000007ms
2019-01-18 11:23:00.052 +00:00 [INF] Request finished in 847.5964ms 200 application/json; charset=utf-8
当我使用JSON appsettings执行此操作时,看起来是这样的:

Log.Logger = new LoggerConfiguration()
    .WriteTo.ColoredConsole()
    .WriteTo.Logger(lc => lc
    .Filter.ByExcluding(Matching.FromSource("Microsoft"))
    .WriteTo.File("Serilogs/Program_log_.txt", rollingInterval: RollingInterval.Day)
    .MinimumLevel.Information()
    .MinimumLevel.Override("Microsoft", LogEventLevel.Information))

    .WriteTo.Logger(lc => lc
    .Filter.ByIncludingOnly(Matching.FromSource("Microsoft"))
    .WriteTo.File("Serilogs/ServerTrace_log_.txt", rollingInterval: RollingInterval.Day)
    .MinimumLevel.Information()
    .MinimumLevel.Override("Microsoft", LogEventLevel.Information))

    .CreateLogger();
 "Serilog": {
    "Using": [
      "Serilog.Sinks.File",
      "Serilog.Filters.Expressions",
      "Serilog.Settings.Configuration"
    ],
    "WriteTo": [
      {
        "Name": "Logger",
        "Args": {
          "configureLogger": {
            "Filter": [
              {
                "Name": "ByIncluding",
                "Args": {
                  "expression": "SourceContext = 'Microsoft'"
                }
              }
            ],
            "WriteTo": [
              {
                "Name": "File",
                "Args": {
                  "path": "./Serilogs/server_logs_.log",
                  "rollingInterval": "Day"
                }
              }
            ]
          }
        }
      },
      {
        "Name": "Logger",
        "Args": {
          "configureLogger": {
            "Filter": [
              {
                "Name": "ByExcluding",
                "Args": {
                  "expression": "SourceContext = 'Microsoft.AspNetCore.Hosting.Internal.WebHost'"
                }
              }
            ],
            "WriteTo": [
              {
                "Name": "File",
                "Args": {
                  "path": "./Serilogs/program_logs_.log",
                  "rollingInterval": "Day"
                }
              }
            ]
          }
        }
      }
    ]
  }
这将生成两个文件。
文件1
:可读的自定义日志:

2019-01-18 11:18:09.873 +00:00 [INF] //Some custom log information
2019-01-18 11:18:09.875 +00:00 [INF] //Some more custom log information
2019-01-18 11:22:52.903 +00:00 [INF] User profile is available. Using '// A path' as key repository and Windows DPAPI to encrypt keys at rest.
2019-01-18 11:22:59.229 +00:00 [INF] Route matched with {action = "PollForStatusUpdate", controller = "StatusMessage"}. Executing action {apiname}.{controller}.{method}.PollForStatusUpdate ({apiname})
2019-01-18 11:22:59.505 +00:00 [INF] Executing action method {apiname}.{controller}.{method}.PollForStatusUpdate ({apiname}) with arguments (["{apiname}.{controller}.{method}.MessageResult"]) - Validation state: "Valid"
2019-01-18 11:22:59.632 +00:00 [INF] //Some custom log information
2019-01-18 11:22:59.639 +00:00 [INF] //Some more custom log information
{apiname}.{controller}.{method}.PollForStatusUpdate ({apiname}), returned result Microsoft.AspNetCore.Mvc.OkObjectResult in 516.8129ms.
2019-01-18 11:23:00.040 +00:00 [INF] Executing ObjectResult, writing value of type '{apiname}.{controller}.{method}.MessageResult'.
2019-01-18 11:23:00.048 +00:00 [INF] Executed action {apiname}.{controller}.{method}.PollForStatusUpdate ({apiname}) in 813.08940000000007ms

文件2
:堆栈跟踪,服务器信息:

2019-01-18 11:17:56.378 +00:00 [INF] User profile is available. Using '//A path' as key repository and Windows DPAPI to encrypt keys at rest.
2019-01-18 11:17:57.840 +00:00 [INF] Request starting HTTP/1.1 GET https://localhost:5001/swagger/index.html  
2019-01-18 11:17:58.074 +00:00 [INF] Request finished in 235.5796ms 200 text/html
2019-01-18 11:17:58.326 +00:00 [INF] Request starting HTTP/1.1 GET https://localhost:5001/swagger/v1/swagger.json  
2019-01-18 11:17:58.452 +00:00 [INF] Request finished in 126.2127ms 200 application/json;charset=utf-8 
2019-01-18 11:22:52.903 +00:00 [INF] User profile is available. Using 'C:\Users\msharp\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest.
2019-01-18 11:22:54.263 +00:00 [INF] Request starting HTTP/1.1 GET https://localhost:5001/swagger/index.html  
2019-01-18 11:22:54.473 +00:00 [INF] Request finished in 211.831ms 200 text/html
2019-01-18 11:22:54.737 +00:00 [INF] Request starting HTTP/1.1 GET https://localhost:5001/swagger/v1/swagger.json  
2019-01-18 11:22:54.838 +00:00 [INF] Request finished in 100.8892ms 200 application/json;charset=utf-8
2019-01-18 11:22:59.205 +00:00 [INF] Request starting HTTP/1.1 POST https://localhost:5001/api/StatusMessage/PollForStatusUpdate application/json-patch+json 180
2019-01-18 11:22:59.229 +00:00 [INF] Route matched with {action = "PollForStatusUpdate", controller = "StatusMessage"}. Executing action PureValuationsApi.Controllers.StatusMessageController.PollForStatusUpdate (PureValuationsApi)
2019-01-18 11:22:59.505 +00:00 [INF] Executing action method {apiname}.{controller}.{method}.PollForStatusUpdate ({apiname}) with arguments (["{apiname}.{controller}.{method}.MessageResult"]) - Validation state: "Valid"
2019-01-18 11:22:59.632 +00:00 [INF] //Some custom lof information
2019-01-18 11:22:59.639 +00:00 [INF] //Some more custom log information
{apiname}.{controller}.{method}.PollForStatusUpdate ({apiname}), returned result Microsoft.AspNetCore.Mvc.OkObjectResult in 516.8129ms.
2019-01-18 11:23:00.040 +00:00 [INF] Executing ObjectResult, writing value of type '{apiname}.{controller}.{method}.MessageResult'.
2019-01-18 11:23:00.048 +00:00 [INF] Executed action {apiname}.{controller}.{method}.PollForStatusUpdate ({apiname}) in 813.08940000000007ms
2019-01-18 11:23:00.052 +00:00 [INF] Request finished in 847.5964ms 200 application/json; charset=utf-8

因此,通过应用感觉相同的技术,结果会有所不同,因为
文件1
现在包含更多的操作信息,
文件2
包含堆栈和自定义日志信息,尽管我希望它们完全分开。

我认为您的过滤器不太正确

筛选器表达式应为:

"expression": "SourceContext = 'Microsoft' or StartsWith(SourceContext, 'Microsoft.')"
(我想您可以不使用最后一个点而直接使用(SourceContext,'Microsoft')启动
StartsWith,但是对于
microsoftoristrially.MyNamespace
)这样的名称空间,这可能会不正常)

(内部
Matching.ForSource
执行
SourceContext.StartsWith(..)
类型的筛选,如图所示)

要确认,您可能需要编辑文件接收器的
outputTemplate
,以显示
SourceContext
属性并查看日志事件的来源。(默认值为
“{Timestamp:yyyy-MM-dd HH:MM:ss.fff-zzz}[{Level:u3}]{Message:lj}{NewLine}{Exception}”
)。您可以将其更改为
“{Timestamp:yyyy-MM-dd HH:MM:ss.fff-zzz}[{Level:u3}]{Message:lj}{NewLine}{Exception}”
以包含
SourceContext
属性



顺便说一下,您有一个额外的、不需要的
“Using”
指令。
“Serilog.Settings.Configuration”
是不必要的

“表达式”:“StartsWith(SourceContext,'Microsoft.')”
这样做的结果似乎与我所做的方式相同,我已更改以符合标准的要求。谢谢你。如果他们做了同样的事情,或者你可以限定多个过滤器我不好,我认为你应该做两个“同等”的微软,或者从微软开始(用一个点)。。。我将更新我的回答,但仍然没有表现出完全相同的行为,这让我觉得奇怪,因为通过该方法它感觉是一样的?您是否正确地在两个过滤器中使用完全相同的表达式(一次
仅包括
,一次
排除
)?奇怪<代码>“名称”:“ByIncludingOnly”、
“名称”:“ByIncludingOnly”、
任何替代方法似乎都会破坏它,从而重复
文件1和
文件2的日志