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

如何在Windows Service中正确初始化Serilog以实现全局调用?

在Windows Service中正确使用Serilog的实现方式

其实你当前的思路方向是对的——在Main方法里初始化Serilog是可行的,但有几个关键细节需要调整,才能确保从服务启动到停止的整个生命周期里,无论是Main方法还是服务类内部,都能稳定使用日志功能,还能避免日志丢失。

核心修正点与完整代码示例

1. 提前初始化+异常兜底

把Serilog的初始化放在Main方法的最开头,并用try-catch-finally包裹服务启动逻辑,确保即使启动失败,错误日志能被记录,且日志资源能被正确释放。

using Serilog;

public static class Program
{
    public static void Main(string[] args)
    {
        // 第一步:优先初始化Serilog,必须在所有日志调用之前执行
        Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Information() // 可根据需求调整日志级别
            .WriteTo.RollingFile(@"C:\Logs\MyService\log-{Date}.txt") // 替换为你的实际日志路径
            .CreateLogger();

        try
        {
            Log.Information("Service host initialization started");
            RunService();
        }
        catch (Exception ex)
        {
            Log.Fatal(ex, "Service terminated unexpectedly during startup");
        }
        finally
        {
            // 无论成功失败,都要冲刷日志队列并关闭Serilog
            Log.CloseAndFlush();
        }
    }

    private static void RunService()
    {
        MyService daemon = new MyService();
        Log.Information("Service instance created");
        
        ServiceBase[] services = new ServiceBase[] { daemon };
        Log.Information("About to start service execution");
        ServiceBase.Run(services);
    }
}

2. 服务类中完善日志生命周期

在服务的OnStop方法中添加日志冲刷逻辑,确保服务停止时的最后一批日志能被写入文件,不会丢失:

public class MyService : ServiceBase
{
    protected override void OnStart(string[] args)
    {
        Log.Information("Service started successfully");
        // 这里添加服务启动后的业务初始化逻辑
    }

    protected override void OnStop()
    {
        Log.Information("Service is stopping, starting cleanup");
        // 这里添加服务停止前的资源清理逻辑
        
        // 冲刷停止时的日志,确保所有待写入的日志都落地
        Log.CloseAndFlush();
    }

    protected override void OnSessionChange(SessionChangeDescription changeDescription)
    {
        // 用占位符格式化日志,提升可读性和结构化
        Log.Information("Session change detected: {ChangeReason}", changeDescription.Reason);
    }
}

关键注意事项

  • 初始化顺序:Serilog的Log.Logger赋值必须是第一个执行的逻辑,避免静态构造函数或其他提前执行的代码调用日志时出现空引用。
  • 日志冲刷:Log.CloseAndFlush()会等待所有待处理的日志写入完成,必须在服务退出前调用——Main里的finally和服务的OnStop双重调用是为了兜底,确保万无一失。
  • RollingFile过时提醒:如果你使用的是Serilog 2.x及以上版本,RollingFile方法已被标记为过时,推荐使用WriteTo.File配置滚动策略:
    .WriteTo.File(
        path: @"C:\Logs\MyService\log-.txt",
        rollingInterval: RollingInterval.Day, // 按天滚动
        rollOnFileSizeLimit: true, // 文件达到上限时滚动
        fileSizeLimitBytes: 10 * 1024 * 1024, // 单文件上限10MB
        retainedFileCountLimit: 30 // 保留最近30天的日志
    )
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:42:20