我有一个使用 Serilog 将日志数据写入文件的应用程序。我现在尝试用
appsettings.json
中的子记录器配置我的记录器,以便我可以将某些日志过滤到不同的文件。我知道我可以在代码中配置记录器,但我想通过 appsettings.json
来完成。
基本上,我希望所有日志都转到同一个文件,除了某种类型的日志。我使用了 Serilog wiki 以及一些博客文章和 stackoverflow 条目(主要是 this)来实现我的目标。根据我所阅读的内容,使用以下内容应该允许我过滤此类日志条目:
using (LogContext.PushProperty("SpecialLogType", true)) {
_logger.LogInformation("MyLogEntry {MyParam}", myParam);
}
我配置了两个接收器,一个用于普通日志,一个用于这种特殊类型的日志。使用过滤器,我现在应该能够使用此属性过滤日志。但我无法弄清楚我到底需要如何在 appsettings.json 中配置子记录器。 现在,我的
appsettings.json
看起来像这样:
"Serilog": {
"Using": [ "Serilog.Sinks.File", "Serilog.Settings.Configuration", "Serilog.Expressions" ],
"MinimumLevel": {
"Default": "Information",
},
"WriteTo": [
{
"Name": "Logger",
"Args": {
"configureLogger": {
"Filter": [
{
"Name": "ByExcluding",
"Args": {
"expression": "@p['SpecialLogType'] = 'true'"
}
}
],
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "Logs/NormalTypeLog_.txt",
// other configuration
}
}
]
}
}
},
{
"Name": "Logger",
"Args": {
"configureLogger": {
"Filter": [
{
"Name": "ByIncludingOnly",
"Args": {
"expression": "@p['SpecialLogType'] = 'true'"
}
}
],
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "Logs/SpecialTypeLog.json",
// other configuration
}
}
]
}
}
}
]
}
我尝试了几种不同的方法,取得了一些结果,但我无法让它正常工作,希望得到一些建议。有人有什么建议吗?
编辑:很晚才发现这个问题,它也提供了替代答案:Serilog 和 Filters from Filters.Expressions in appsettings.json
所以几天后我设法解决了这个问题,并想如果任何有类似问题的人偶然发现它,我会在这里发布我的完整解决方案。
我认为我走在正确的道路上,但我的主要问题是我错误地使用了 Serilog 的表达式 包。我将在多个示例中找到的内容混合在一起,但最终没有起作用。更多阅读 wiki 和 nblumhardt 的博客文章 引导我找到了最终的解决方案。
日志可以通过属性来丰富。稍后可以在管道中使用这些属性来将日志过滤到不同的subloggers。可以通过
LogContext
类将属性添加到日志中。
using (LogContext.PushProperty("SpecialLogType", true)) {
_logger.LogInformation("This is a log entry that will be filtered to a different file");
}
要实际配置记录器,您需要创建两个子记录器。 过滤必须发生在子记录器级别。每个子记录器都必须过滤它自己的事件。顶级记录器的过滤将过滤掉所有子记录器的日志事件。过滤是通过 Serilog 的表达式 包完成的。
为了仅包含附加我的属性的日志事件,我执行了以下操作
"Name": "ByIncludingOnly",
"Args": {
"expression": "SpecialLogType is not null"
}
由于我希望所有其他事件都转到“标准”文件,因此对于我的其他子记录器,我只是排除了附加属性的所有日志事件
"Name": "ByExcluding",
"Args": {
"expression": "SpecialLogType is not null"
}
完整相关的 appsettings.json 部分
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File", "Serilog.Settings.Configuration", "Serilog.Expressions" ],
"WriteTo": [
{ "Name": "Console" },
{ "Name": "Debug" },
{
"Name": "Logger",
"Args": {
"configureLogger": {
"Filter": [
{
"Name": "ByExcluding",
"Args": {
"expression": "SpecialLogType is not null"
}
}
],
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "Logs/NormalLogEvents_.txt",
// other irrelevant file configuration
}
}
]
}
}
},
{
"Name": "Logger",
"Args": {
"configureLogger": {
"Filter": [
{
"Name": "ByIncludingOnly",
"Args": {
"expression": "SpecialLogType is not null"
}
}
],
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "Logs/SpecialLoggingType_.log",
// other irrelevant file configuration
}
}
]
}
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
}
这对我有用,我希望它可以帮助任何遇到同样问题的人。
也很有用:Serilog 设置配置自述文件
唯一的区别是,如果您使用 Serilog.Expressions 而不是 Serilog.Filters.Expressions,则必须在过滤器中使用以下表达式
Serilog.Filters.Expressions :
"Filter":
[
{
"Name": "ByIncludingOnly", "Args": { "expression": "@Level = 'Error'" }
}
]
Serilog.Expressions :
"Filter":
[
{
"Name": "ByIncludingOnly", "Args": { "expression": "@l = 'Error'" }
}
]
对我来说效果很好