使用Serilog.Sinks.GoogleCloudLogging如何将SqlException日志级别提升为Fatal?
问题:将SqlException日志统一提升为Fatal级别(Serilog + GoogleCloudLogging)
我在.NET应用中使用Serilog搭配Serilog.Sinks.GoogleCloudLogging将日志发送至Datadog,希望自动将所有SqlException日志提升为Fatal(或Critical)级别,无论其初始日志级别为Error或Warning。
我尝试过三种方式但均未成功,Datadog中仍显示原始日志级别:
- 自定义增强器:创建增强器检测并修改SqlException日志事件,但Google Cloud Logging中的日志级别未改变,代码如下:
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) { if (logEvent.Exception is SqlException) { logEvent = new LogEvent(logEvent.Timestamp, LogEventLevel.Fatal, logEvent.Exception, logEvent.MessageTemplate, logEvent.Properties.Select(p => new LogEventProperty(p.Key, p.Value)) ); } }
- 过滤器:应用过滤器尝试提升级别,但接收器中无效果
- ExceptionHandlingMiddleware:通过全局中间件捕获异常修改级别,Google Cloud仍显示Error级别
请问使用Serilog.Sinks.GoogleCloudLogging时,是否有办法将所有SqlException日志条目修改为Fatal级别?
解决方案
核心原因:之前的方法为什么无效?
- 自定义增强器:Serilog的
Enrich仅用于添加日志属性,无法修改日志事件本身的级别。你在增强器中重新赋值logEvent只是修改了局部变量,原日志事件并未被改变。 - 普通过滤器:仅用于决定是否记录日志,不具备修改级别能力。
- ExceptionHandlingMiddleware:如果中间件中用
_logger.LogError(ex, ...)记录日志,级别已被固定为Error,后续Serilog无法修改已生成的LogEvent级别。
方法1:自定义包装Sink(最直接)
创建一个Sink包装类,拦截所有日志事件,判断是否包含SqlException,修改级别后再传递给GoogleCloudLoggingSink:
public class RewriteLevelSink : ILogEventSink { private readonly ILogEventSink _innerSink; public RewriteLevelSink(ILogEventSink innerSink) { _innerSink = innerSink; } public void Emit(LogEvent logEvent) { if (logEvent.Exception is SqlException) { // 创建新的LogEvent,替换级别为Fatal var rewrittenEvent = new LogEvent( logEvent.Timestamp, LogEventLevel.Fatal, logEvent.Exception, logEvent.MessageTemplate, logEvent.Properties.Select(p => new LogEventProperty(p.Key, p.Value)) ); _innerSink.Emit(rewrittenEvent); } else { _innerSink.Emit(logEvent); } } }
Serilog配置时使用这个包装Sink:
Log.Logger = new LoggerConfiguration() .WriteTo.Sink(new RewriteLevelSink( new GoogleCloudLoggingSink(new GoogleCloudLoggingSinkOptions { // 填写你的Google Cloud Logging配置 ProjectId = "your-project-id", LogId = "your-log-id" }) )) .CreateLogger();
方法2:使用Serilog.Expressions(更灵活)
先安装Serilog.Expressions包,然后通过transform参数直接修改日志级别:
Log.Logger = new LoggerConfiguration() .WriteTo.GoogleCloudLogging( options => { // 填写你的Google Cloud Logging配置 options.ProjectId = "your-project-id"; options.LogId = "your-log-id"; }, transform: logEvent => logEvent.Exception is SqlException ? new LogEvent( logEvent.Timestamp, LogEventLevel.Fatal, logEvent.Exception, logEvent.MessageTemplate, logEvent.Properties.Select(p => new LogEventProperty(p.Key, p.Value)) ) : logEvent ) .CreateLogger();
方法3:使用WriteTo.Map分支处理
通过Map操作按是否为SqlException分支处理日志,重写级别后再转发到接收器:
Log.Logger = new LoggerConfiguration() .WriteTo.Map( logEvent => logEvent.Exception is SqlException, (isSqlException, writeTo) => { var sinkOptions = new GoogleCloudLoggingSinkOptions { ProjectId = "your-project-id", LogId = "your-log-id" }; if (isSqlException) { // 重写级别为Fatal后发送 writeTo.Sink(new RewriteLevelSink(new GoogleCloudLoggingSink(sinkOptions))); } else { // 正常发送原级别日志 writeTo.Sink(new GoogleCloudLoggingSink(sinkOptions)); } }) .CreateLogger();
内容的提问来源于stack exchange,提问作者Matheus Tonon
相关产品推荐
相关产品推荐

