You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何var声明的Serilog Logger无输出?必须用Log.logger静态实例吗?

Serilog实例注入ILogger不生效的原因及解决办法

问题描述

我在.NET环境中编写了如下Serilog配置代码:

var logger =  new LoggerConfiguration()
                .Enrich.WithProperty("Assembly", assembly?.Name)
                .Enrich.FromLogContext()
                .MinimumLevel.Debug()
                .MinimumLevel.Override("Microsoft", LogEventLevel.Debug)
                .WriteTo.Console(
                    theme: Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code,
                    formatProvider: CultureInfo.CurrentCulture,
                    outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff}][{Level:u3}] {Message:lj} <s:{SourceContext}>{NewLine}{Exception}",
                    restrictedToMinimumLevel: LogEventLevel.Debug)
                .WriteTo.File(
                    path: "Logs/log-.log",
                    outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff}][{Level:u3}] {Message:lj} <s:{SourceContext}>{NewLine}{Exception}",
                    rollingInterval: RollingInterval.Day,
                    restrictedToMinimumLevel: LogEventLevel.Debug,
                    formatProvider: CultureInfo.CurrentCulture)
                .WriteTo.Sink(new WebSocketSink(logChannel), LogEventLevel.Debug)
                .WriteTo.Seq("http://localhost:5341")
                .CreateLogger();

将该logger实例注入到依赖ILogger<MyService>的MyService类时,日志语句既不输出到控制台也不写入文件:

public class MyService(IDeviceIO devIO, ILogger<MyService> logger) : IMyService
{
    /// <inheritdoc/>
    public void OpenDevice(string host)
    {
        logger.LogInformation("Device is being opened!");
        devIO.Open(host);
    }
    // ...
}

但改成Log.Logger = new LoggerConfiguration()...后,日志开始正常输出到控制台和文件。请问为何用var logger = ...声明的实例不行?必须始终使用Log.Logger静态实例吗?

原因分析

核心问题是你仅创建了Serilog的Logger实例,但没有将其注册到.NET的依赖注入容器中,也未让.NET的日志系统桥接至该实例。

当你通过ILogger<MyService>注入时,默认获取的是.NET原生LoggerProvider提供的实例,而非你自行创建的Serilog实例。只有将Serilog配置为.NET日志系统的底层实现后,注入的ILogger<T>才会委托Serilog处理日志输出。

而Log.Logger是Serilog的全局静态日志实例,设置它之后,Serilog与.NET日志系统的桥接组件(如Serilog.Extensions.Logging)会默认使用该全局实例,因此日志能正常输出,但这并非最优方案——全局静态实例不利于测试和依赖隔离。

正确解决方式

无需依赖Log.Logger静态实例,只需将你创建的Serilog实例注册到DI容器,并替换.NET默认日志系统即可,步骤如下:

  1. 确保已安装Serilog.Extensions.Logging包(这是Serilog与.NET日志系统的桥接包)
  2. 在DI配置代码中(例如Program.cs),将Serilog实例注册为日志提供者:
// 创建自定义配置的Serilog实例
var logger = new LoggerConfiguration()
    // 此处保留你的原有配置代码
    .CreateLogger();

// 注册到DI容器,替换默认日志系统
builder.Services.AddLogging(loggingBuilder =>
{
    // 清除所有默认的日志提供者
    loggingBuilder.ClearProviders();
    // 添加Serilog作为唯一的日志提供者
    loggingBuilder.AddSerilog(logger);
});

完成上述配置后,注入ILogger<MyService>时,获取到的就是绑定了你自定义配置的Serilog实例的日志对象,日志会正常输出到你指定的控制台、文件等目标。

另外需要注意:创建的Serilog实例需保持生命周期,避免被GC回收——不过通过AddSerilog注册到DI容器后,容器会自动管理其生命周期,无需额外担心。

内容的提问来源于stack exchange,提问作者BND

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 22:14:52