.NET 6 Windows控制台应用LoggerFactory最终日志无法显示求助
.NET 6控制台日志丢失问题解决方法
控制台日志提供器(ConsoleLoggerProvider)默认采用异步批量写入策略:日志会暂存到缓冲区,达到阈值或间隔固定时间才批量输出到控制台。当程序执行速度过快(比如循环生成大量日志后立即抛出异常),缓冲区中的日志还没来得及刷新,程序就进入终止流程——即便调用loggerFactory.Dispose(),异步写入任务也可能未完成,导致部分日志(包括异常日志)丢失。
解决方案1:强制同步刷新日志
修改控制台日志配置,禁用异步批量写入,改为同步输出,确保每条日志立即写入控制台。
修改后的代码:
using var loggerFactory = LoggerFactory.Create(builder => { builder .AddFilter("Microsoft", LogLevel.Warning) .AddFilter("System", LogLevel.Warning) .AddFilter("MyTestApp.Program", LogLevel.Debug) .AddConsole(options => { // 关键配置:强制同步写入,禁用异步缓冲 options.Synchronous = true; }); }); ILogger logger = loggerFactory.CreateLogger<Program>(); try { logger.LogInformation("Starting"); for (var i=0; i < 100; i++) { logger.LogInformation($"This is a nice long message for {i}."); } throw new Exception("boom"); } catch (Exception e) { logger.LogError(e, "An error occurred"); // 推荐用LogError携带异常参数,而非直接ToString } finally { loggerFactory.Dispose(); }
解决方案2:手动触发缓冲区刷新(临时调试用)
如果不想完全禁用异步,可通过反射调用控制台日志提供器的内部刷新方法(依赖.NET内部实现,不推荐生产环境使用):
finally { // 反射获取控制台日志提供器并调用刷新方法 var consoleProvider = loggerFactory.Services .FirstOrDefault(s => s.ServiceType == typeof(IConsoleLoggerProvider)) ?.ImplementationInstance as ConsoleLoggerProvider; consoleProvider?.GetType() .GetMethod("Flush", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic) ?.Invoke(consoleProvider, null); loggerFactory.Dispose(); }
解决方案3:使用结构化日志库(推荐)
比如Serilog,它对日志刷新的控制更灵活,默认支持立即输出:
- 安装NuGet包:
Serilog.Extensions.Logging、Serilog.Sinks.Console - 修改代码:
using Serilog; // 初始化Serilog配置 Log.Logger = new LoggerConfiguration() .MinimumLevel.Debug() .MinimumLevel.Override("Microsoft", Serilog.Events.LogEventLevel.Warning) .MinimumLevel.Override("System", Serilog.Events.LogEventLevel.Warning) .WriteTo.Console(flushToConsole: true) // 强制立即刷新日志 .CreateLogger(); // 绑定到LoggerFactory using var loggerFactory = LoggerFactory.Create(builder => { builder.AddSerilog(); }); ILogger logger = loggerFactory.CreateLogger<Program>(); try { logger.LogInformation("Starting"); for (var i=0; i < 100; i++) { logger.LogInformation($"This is a nice long message for {i}."); } throw new Exception("boom"); } catch (Exception e) { logger.LogError(e, "An error occurred"); } finally { Log.CloseAndFlush(); // 确保所有缓冲区日志输出 loggerFactory.Dispose(); }
内容的提问来源于stack exchange,提问作者Elroy Flynn
相关产品推荐
相关产品推荐

