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

如何基于Serilog和ILogger动态切换日志数据库连接字符串

动态修改Serilog数据库连接字符串

我需要为Serilog动态修改数据库连接字符串。

现有配置代码

StartUp.cs中的Serilog配置

public void ConfigureServices(IServiceCollection services)
{
    var cm = new ConnectionManager(config);

    Log.Logger = new LoggerConfiguration()
        .ReadFrom.Configuration(config)
        .Enrich.FromLogContext()
        .WriteTo.MSSqlServer(
            cm.GetConnectionString(cm.GetPropertyFromConfig("Serilog", "ConnectionName")),
            sinkOptions: new MSSqlServerSinkOptions { TableName = cm.GetPropertyFromConfig("Serilog", "TableName"), SchemaName = cm.GetPropertyFromConfig("Serilog", "SchemaName") })
        .CreateLogger();

    services.AddLogging(s =>
    {
        s.ClearProviders();
        s.AddSerilog(Log.Logger, dispose: true);
    });

    services.AddTransient(provider =>
    {
        var loggerFactory = provider.GetRequiredService<ILoggerFactory>();
        const string categoryName = "Any";
        
        return loggerFactory.CreateLogger(categoryName);
    });
}

ChangeConnection.cs的初始代码

public class ChangeConnection {

    private readonly ILogger _logger;
    
    public ChangeConnection(ILogger logger){
    
        _logger = logger;
    }
    
    public void SwapConnection(string connectionString)
    {
        // 修改日志记录器的连接字符串,使后续日志写入新数据库
    }
}

调用代码示例

_logger.LogInformation("Logging to Current Database");               
    
_changeConnection.SwapConnection("new connection string");
    
_logger.LogInformation("Logging to New Database");

解决方案

Serilog的Sink实例是不可变的,无法直接修改现有Sink的连接字符串,需要重新创建Logger并替换全局实例,同时更新DI中的日志服务。

修改ChangeConnection.cs

public class ChangeConnection
{
    private readonly IConfiguration _config;
    private readonly ILoggerFactory _loggerFactory;

    // 注入配置和日志工厂,而非直接注入ILogger
    public ChangeConnection(IConfiguration config, ILoggerFactory loggerFactory)
    {
        _config = config;
        _loggerFactory = loggerFactory;
    }

    public void SwapConnection(string connectionString)
    {
        // 先关闭并刷新旧Logger,确保日志全部写入并释放资源
        var oldLogger = Log.Logger;
        Log.CloseAndFlush();

        // 基于新连接字符串创建新Logger
        var cm = new ConnectionManager(_config);
        var newLogger = new LoggerConfiguration()
            .ReadFrom.Configuration(_config)
            .Enrich.FromLogContext()
            .WriteTo.MSSqlServer(
                connectionString,
                sinkOptions: new MSSqlServerSinkOptions 
                { 
                    TableName = cm.GetPropertyFromConfig("Serilog", "TableName"), 
                    SchemaName = cm.GetPropertyFromConfig("Serilog", "SchemaName") 
                })
            .CreateLogger();

        // 更新全局Logger实例
        Log.Logger = newLogger;

        // 更新日志工厂中的Serilog提供器,确保后续创建的ILogger使用新Logger
        var existingProvider = _loggerFactory.Services.OfType<SerilogLoggerProvider>().FirstOrDefault();
        if (existingProvider != null)
        {
            _loggerFactory.RemoveProvider(existingProvider);
            _loggerFactory.AddSerilog(newLogger, dispose: true);
        }
    }
}

注意事项

  • 调用Log.CloseAndFlush()是关键,避免旧Logger占用数据库连接或丢失未写入的日志。
  • 需要在DI容器中注册ChangeConnection,确保注入的IConfiguration和ILoggerFactory可用。
  • 如果原配置中有多个Sink,重新创建Logger时要确保所有需要的Sink都被正确配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 20:25:26