如何在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
相关产品推荐
相关产品推荐

