当源上下文不是特定值时,最好的丰富方法
Best way to enrich when source context is anything but a specific value
当以编程方式构建稍后使用的 LoggerConfiguration
时,我希望并成功地限制了对所有源上下文值 除了 一个(Global.asax 来自旧的网络表单网站)。
但在我看来,这似乎远离了(我不喜欢那个 Invoke
调用)我认为 Serilog 库旨在作为练习,因为它非常漂亮和优雅流畅 API :
private static LoggerConfiguration GetBasicLoggerConfig()
{
return new LoggerConfiguration()
.MinimumLevel.Debug()
.Enrich.When(
logEvent => !Matching.FromSource("ASP.global_asax").Invoke(logEvent),
enrichmentConfig => enrichmentConfig.WithAnyKindOfEnricher());
}
我使用此逻辑在脱离上下文时从 运行 中排除一系列增强器,并且只希望它们在页面的生命周期内执行。但不管这种情况如何,因为我将在其他地方应用这种方法,所以我想保持简洁和简短,我最感兴趣的是这个概念本身 - "enrich by excluding a particular context".
我一直在寻找 WhenNot
或 NotMatching
之类的方法来表达 "negation" / "exclusion",但没能在图书馆找到它们。尝试使用静态 class Matching
提供的其他方法但无济于事。该项目很大,我想根据不同的上下文对整个日志记录进行个性化设置(因此最终使用了一系列 Enrich.When()
s - 并使用了大量的 enrichers,通过几个 "exclude only one context" 部分似乎 ugly/messy).
当然,如下例所示,集中声明上下文的默认值并不能解决问题,因为将有不同的上下文通过 .ForContext<T>()
声明,除了一个必须是 "catched"处于充实状态
// this does not cut it
return new LoggerConfiguration()
.MinimumLevel.Debug()
.Enrich.WithProperty(Serilog.Core.Constants.SourceContextPropertyName, "default")
.Enrich.When(Matching.FromSource("default"),
enrichmentConfig => enrichmentConfig.WithAnyKindOfEnricher());
希望我能够解释我想要达到的目标。 (为清楚起见,lambda 参数名称很长)
那么,我是不是漏掉了什么,或者还有其他方法吗?如何最好地实现这一点 "enriching by exclusion"?
稍后编辑:
- 忘了说我只记录文件(使用文件接收器)。
- 不打算集成 Seq(我知道它的优点),至少在不久的将来不会。
Serilog.Filters.Expressions 更适合这个:
// dotnet add package serilog.filters.expressions
.Enrich.When(
"SourceContext <> 'ASP.global_asax'"),
enrichmentConfig => enrichmentConfig.WithAnyKindOfEnricher());
⚠️ 下面的代码 被简化且不正确 。根据 Nicholas Blumhardt 的评论,将涉及一些额外的空检查/转换。
正确的条件应该是
logEvent.Properties.TryGetValue("SourceContext", out var ctx) && ctx is ScalarValue sv && sv.Value is string s && s.StartsWith("blah")
(但如果我们愿意,可以以某种方式提取到扩展方法)
如果您将日志记录配置定义为代码(而不是来自 JSON 文件或 AppSettings),那么,我建议您只编写普通的 C# 代码,并按照以下行做一些事情:
private static LoggerConfiguration GetBasicLoggerConfig()
{
return new LoggerConfiguration()
.MinimumLevel.Debug()
.Enrich.When(
logEvent => logEvent.Properties["SourceContext"].StartsWith("blah")
//add all the complexity you want in here
|| logEvent.Properties["SourceContext"].EndsWith("foo"),
enrichmentConfig => enrichmentConfig.WithAnyKindOfEnricher());
}
表达您要使用的复杂条件可能更容易。
如果您对 魔术字符串 "SourceContext"
感到不安,它也可以作为常量从 Serilog.Core.Constants.SourceContextPropertyName
.
中获得
如果 logEvent.Properties["SourceContext"]
感觉有点冗长,您可以通过定义 extension method 使其更具可读性,例如:
public static string GetSourceContext(this LogEvent logEvent){
return logEvent.Properties["SourceContext"];
}
另一种比我之前的答案涉及更少自定义代码的方法是使用 Serilog.Filters.Matching
提供的功能。
// snip... probably need some usings for `Serilog.Filters`
// ...
private static bool ShouldEnrichForThisSourceContext(string sourceContext)
{
// ⚠️ sourceContext is possibly null
return sourceContext.StartsWith("whatever") || sourceContext.Contains("xxx");
}
private static LoggerConfiguration GetBasicLoggerConfig()
{
return new LoggerConfiguration()
.MinimumLevel.Debug()
.Enrich.When(
Matching.WithProperty<string>(
Constants.SourceContextPropertyName,
ShouldEnrichForThisSourceContext),
enrichmentConfig => enrichmentConfig.WithAnyKindOfEnricher());
}
我现在无法访问可用的 .NET IDE,因此它可能无法完全编译,但我的想法是这样。
当以编程方式构建稍后使用的 LoggerConfiguration
时,我希望并成功地限制了对所有源上下文值 除了 一个(Global.asax 来自旧的网络表单网站)。
但在我看来,这似乎远离了(我不喜欢那个 Invoke
调用)我认为 Serilog 库旨在作为练习,因为它非常漂亮和优雅流畅 API :
private static LoggerConfiguration GetBasicLoggerConfig()
{
return new LoggerConfiguration()
.MinimumLevel.Debug()
.Enrich.When(
logEvent => !Matching.FromSource("ASP.global_asax").Invoke(logEvent),
enrichmentConfig => enrichmentConfig.WithAnyKindOfEnricher());
}
我使用此逻辑在脱离上下文时从 运行 中排除一系列增强器,并且只希望它们在页面的生命周期内执行。但不管这种情况如何,因为我将在其他地方应用这种方法,所以我想保持简洁和简短,我最感兴趣的是这个概念本身 - "enrich by excluding a particular context".
我一直在寻找 WhenNot
或 NotMatching
之类的方法来表达 "negation" / "exclusion",但没能在图书馆找到它们。尝试使用静态 class Matching
提供的其他方法但无济于事。该项目很大,我想根据不同的上下文对整个日志记录进行个性化设置(因此最终使用了一系列 Enrich.When()
s - 并使用了大量的 enrichers,通过几个 "exclude only one context" 部分似乎 ugly/messy).
当然,如下例所示,集中声明上下文的默认值并不能解决问题,因为将有不同的上下文通过 .ForContext<T>()
声明,除了一个必须是 "catched"处于充实状态
// this does not cut it
return new LoggerConfiguration()
.MinimumLevel.Debug()
.Enrich.WithProperty(Serilog.Core.Constants.SourceContextPropertyName, "default")
.Enrich.When(Matching.FromSource("default"),
enrichmentConfig => enrichmentConfig.WithAnyKindOfEnricher());
希望我能够解释我想要达到的目标。 (为清楚起见,lambda 参数名称很长)
那么,我是不是漏掉了什么,或者还有其他方法吗?如何最好地实现这一点 "enriching by exclusion"?
稍后编辑:
- 忘了说我只记录文件(使用文件接收器)。
- 不打算集成 Seq(我知道它的优点),至少在不久的将来不会。
Serilog.Filters.Expressions 更适合这个:
// dotnet add package serilog.filters.expressions
.Enrich.When(
"SourceContext <> 'ASP.global_asax'"),
enrichmentConfig => enrichmentConfig.WithAnyKindOfEnricher());
⚠️ 下面的代码 被简化且不正确 。根据 Nicholas Blumhardt 的评论,将涉及一些额外的空检查/转换。
正确的条件应该是
logEvent.Properties.TryGetValue("SourceContext", out var ctx) && ctx is ScalarValue sv && sv.Value is string s && s.StartsWith("blah")
(但如果我们愿意,可以以某种方式提取到扩展方法)
如果您将日志记录配置定义为代码(而不是来自 JSON 文件或 AppSettings),那么,我建议您只编写普通的 C# 代码,并按照以下行做一些事情:
private static LoggerConfiguration GetBasicLoggerConfig()
{
return new LoggerConfiguration()
.MinimumLevel.Debug()
.Enrich.When(
logEvent => logEvent.Properties["SourceContext"].StartsWith("blah")
//add all the complexity you want in here
|| logEvent.Properties["SourceContext"].EndsWith("foo"),
enrichmentConfig => enrichmentConfig.WithAnyKindOfEnricher());
}
表达您要使用的复杂条件可能更容易。
如果您对 魔术字符串 "SourceContext"
感到不安,它也可以作为常量从 Serilog.Core.Constants.SourceContextPropertyName
.
如果 logEvent.Properties["SourceContext"]
感觉有点冗长,您可以通过定义 extension method 使其更具可读性,例如:
public static string GetSourceContext(this LogEvent logEvent){
return logEvent.Properties["SourceContext"];
}
另一种比我之前的答案涉及更少自定义代码的方法是使用 Serilog.Filters.Matching
提供的功能。
// snip... probably need some usings for `Serilog.Filters`
// ...
private static bool ShouldEnrichForThisSourceContext(string sourceContext)
{
// ⚠️ sourceContext is possibly null
return sourceContext.StartsWith("whatever") || sourceContext.Contains("xxx");
}
private static LoggerConfiguration GetBasicLoggerConfig()
{
return new LoggerConfiguration()
.MinimumLevel.Debug()
.Enrich.When(
Matching.WithProperty<string>(
Constants.SourceContextPropertyName,
ShouldEnrichForThisSourceContext),
enrichmentConfig => enrichmentConfig.WithAnyKindOfEnricher());
}
我现在无法访问可用的 .NET IDE,因此它可能无法完全编译,但我的想法是这样。