Serilog自定义Sink的Emit方法中LogEvent缺失SourceContext属性问题
问题分析与解决方法
你遇到的SourceContext属性缺失问题,核心原因是当前使用的Logger实例没有关联SourceContext上下文,以下是具体原因和修复方案:
1. SourceContext的生成逻辑
SourceContext并非自动添加到所有LogEvent中,它仅通过以下两种方式生成:
- 调用
Logger.ForContext<T>()或Logger.ForContext("SourceContext", "自定义上下文名称"),生成带有专属上下文的Logger实例 - 在依赖注入场景(如ASP.NET Core)中注入
ILogger<T>,框架会自动为你创建携带SourceContext(值为对应类的全名)的Logger
你当前的代码中,无论API方式还是配置方式创建的都是根Logger,未通过ForContext生成带上下文的实例,因此LogEvent的Properties字典中不会包含SourceContext。
2. 修复步骤
针对API方式初始化的Logger
使用Logger时,不要直接用根实例,而是为当前类生成带上下文的Logger:
// 保留原有根Logger初始化代码 var rootLogger = new LoggerConfiguration() .MinimumLevel.Debug() .Enrich.FromLogContext() .WriteTo.MySink(DefaultOutputTemplate) .CreateLogger(); // 为当前类创建带SourceContext的Logger实例 var logger = rootLogger.ForContext<YourClassName>(); // 使用该实例记录日志,此时LogEvent中会包含SourceContext logger.LogInformation("测试日志内容");
针对配置文件方式初始化的Logger
同样需要在日志调用时生成带上下文的Logger:
// 从配置初始化根Logger后 var logger = Log.Logger.ForContext<YourClassName>(); logger.LogDebug("配置方式测试日志");
如果是ASP.NET Core等依赖注入场景,直接注入ILogger<T>即可,框架会自动处理SourceContext:
public class YourService { private readonly ILogger<YourService> _logger; public YourService(ILogger<YourService> logger) { _logger = logger; } public void DoWork() { // 此时日志的SourceContext就是YourService的类全名 _logger.LogInformation("服务执行中"); } }
3. 验证Sink中的SourceContext
修复后,可在自定义Sink的Emit方法中直接获取SourceContext:
public void Emit(LogEvent logEvent) { if (logEvent.Properties.TryGetValue("SourceContext", out var sourceContext)) { Console.WriteLine($"SourceContext: {sourceContext}"); } // 原有格式化代码 string entry = string.Empty; using (StringWriter stringWriter = new StringWriter()) { m_TextFormatter.Format(logEvent, stringWriter); entry = stringWriter.ToString(); } Console.WriteLine(entry); }
若想在输出模板中直接显示SourceContext,可修改配置或API中的输出模板:
"outputTemplate": "{SourceContext} {Message:lj}{NewLine}{Exception}"
内容的提问来源于stack exchange,提问作者Ritesh
相关产品推荐
相关产品推荐

