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

基于Serilog实现含动态激活功能的双日志记录器技术指导请求

Serilog 单日志器实现双日志需求方案

核心思路

单个Serilog日志器即可满足需求:通过多Sink配置+动态启用/禁用Sink实现。设置两个文件Sink:

  • 一个始终启用,仅记录Information及以上级别到logs_information.log
  • 另一个通过按钮控制启用状态,记录Debug及以上级别到logs_debug.log,启用时自动覆盖Information及以上日志的写入(Serilog会将符合级别的日志发送到所有匹配的Sink)

AppSettings.json 配置示例

先在配置文件中定义基础结构,全局最低日志级别设为Debug(确保Debug日志能被捕获):

{
  "Serilog": {
    "MinimumLevel": "Debug",
    "WriteTo": [
      {
        "Name": "File",
        "Args": {
          "path": "./logs/logs_information.log",
          "rollingInterval": "Day",
          "restrictedToMinimumLevel": "Information",
          "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}"
        }
      }
    ]
  }
}

注:Debug Sink用代码控制启用,避免配置文件静态开关限制灵活性。

代码实现步骤

1. 定义日志开关控制器

桌面应用可用全局变量,ASP.NET Core建议用单例服务维护开关状态:

// 桌面应用全局开关示例
private bool _isDebugLoggerEnabled = false;

// ASP.NET Core 单例服务示例
public interface IDebugLogToggle
{
    bool IsEnabled { get; set; }
}

public class DebugLogToggle : IDebugLogToggle
{
    public bool IsEnabled { get; set; } = false;
}

2. 初始化Serilog日志器

在应用启动时配置日志器,给Debug Sink添加启用条件判断:

// 桌面应用初始化示例
public void InitializeApp()
{
    var config = new LoggerConfiguration()
        .ReadFrom.Configuration(new ConfigurationBuilder()
            .AddJsonFile("AppSettings.json")
            .Build())
        // 添加动态控制的Debug日志Sink
        .WriteTo.Enabled(
            () => _isDebugLoggerEnabled, 
            sink => sink.File(
                "./logs/logs_debug.log", 
                restrictedToMinimumLevel: LogEventLevel.Debug,
                rollingInterval: RollingInterval.Day,
                outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}"));

    Log.Logger = config.CreateLogger();
}

// ASP.NET Core Program.cs 配置示例
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<IDebugLogToggle, DebugLogToggle>();

builder.Host.UseSerilog((context, services, logConfig) =>
{
    var toggle = services.GetRequiredService<IDebugLogToggle>();
    logConfig
        .ReadFrom.Configuration(context.Configuration)
        .WriteTo.Enabled(
            () => toggle.IsEnabled,
            sink => sink.File(
                "./logs/logs_debug.log",
                restrictedToMinimumLevel: LogEventLevel.Debug,
                rollingInterval: RollingInterval.Day));
});

3. 按钮控制开关逻辑

在按钮点击事件中切换开关状态,无需重新创建日志器(Enabled()方法会在每次写日志时检查条件,立即生效):

// 桌面应用按钮点击事件
private void ToggleDebugLogButton_Click(object sender, EventArgs e)
{
    _isDebugLoggerEnabled = !_isDebugLoggerEnabled;
    ToggleDebugLogButton.Text = _isDebugLoggerEnabled ? "关闭Debug日志" : "开启Debug日志";
}

// ASP.NET Core API 示例
[ApiController]
[Route("api/log")]
public class LogController : ControllerBase
{
    private readonly IDebugLogToggle _toggle;

    public LogController(IDebugLogToggle toggle)
    {
        _toggle = toggle;
    }

    [HttpPost("toggle-debug")]
    public IActionResult ToggleDebugLog()
    {
        _toggle.IsEnabled = !_toggle.IsEnabled;
        return Ok(new { Enabled = _toggle.IsEnabled });
    }
}

实用建议

  • 日志分割:用rollingInterval: Day按天分割日志,也可结合fileSizeLimitBytes设置单文件大小上限,避免文件过大
  • 日志格式:统一outputTemplate格式,包含时间戳、日志级别、消息、异常信息,方便后续排查问题
  • 线程安全:开关变量的读写要注意线程安全,多线程场景下建议用Interlocked.Exchange或加锁
  • 测试验证:分别测试开关关闭/开启状态:
    • 关闭时:Debug级日志无输出,Information及以上仅写入logs_information.log
    • 开启时:Debug及以上日志同时写入两个文件
  • 避免重复配置:用ReadFrom.Configuration()读取appsettings中的Info Sink,代码中不要重复添加,减少冗余

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 14:30:53