.NET日志系统架构与最佳实践全解析 1. .NET日志系统核心架构解析日志系统是.NET应用开发中不可或缺的组件它由三个核心部分组成Logger、Provider和Filter。Logger负责生成日志消息Provider决定日志的输出目的地Filter则控制哪些日志应该被记录。典型的日志记录流程如下应用程序调用ILogger接口记录日志日志系统根据配置确定日志级别是否满足记录条件满足条件的日志被传递给所有注册的Provider每个Provider按照自己的方式处理并输出日志// 基础日志记录示例 var loggerFactory LoggerFactory.Create(builder { builder.AddConsole(); builder.AddDebug(); }); var logger loggerFactory.CreateLoggerProgram(); logger.LogInformation(Application started at {StartTime}, DateTime.Now);2. 日志级别的最佳实践.NET定义了6种日志级别按严重程度从低到高依次为日志级别适用场景生产环境建议Trace最详细的调试信息禁用Debug开发调试信息按需启用Information业务流程跟踪保留关键路径Warning非预期但不影响流程的事件全部保留Error当前操作失败全部保留Critical系统级故障全部保留配置建议// appsettings.json典型配置 { Logging: { LogLevel: { Default: Information, Microsoft: Warning, System: Warning }, Console: { LogLevel: { Default: Debug } } } }关键提示生产环境应将Microsoft开头的命名空间日志级别设为Warning避免框架日志淹没业务日志3. 结构化日志高级技巧结构化日志相比传统文本日志具有显著优势使用命名占位符而非字符串拼接// 推荐做法 logger.LogInformation(Order {OrderId} created for {UserId}, orderId, userId); // 避免做法 logger.LogInformation($Order {orderId} created for {userId});利用日志作用域关联相关日志using (logger.BeginScope(new Dictionarystring, object { [TransactionId] Guid.NewGuid(), [UserId] currentUserId })) { logger.LogInformation(Processing payment); // 相关日志会自动包含TransactionId和UserId }事件ID分类管理public static class AppLogEvents { public static readonly EventId Startup new(1000, ApplicationStartup); public static readonly EventId Shutdown new(1001, ApplicationShutdown); // 业务事件 public static readonly EventId OrderCreated new(2000, OrderCreated); } // 使用示例 logger.LogInformation(AppLogEvents.OrderCreated, New order created);4. 性能优化策略日志记录不当可能成为性能瓶颈以下是关键优化点避免昂贵的参数计算// 不推荐 - 即使不记录也会执行ToString() logger.LogDebug($Processed {CalculateMetrics()}); // 推荐 - 使用延迟计算 logger.LogDebug(Processed {Metrics}, CalculateMetrics());使用编译时日志生成.NET 6[LoggerMessage(EventId 0, Level LogLevel.Information, Message User {UserId} logged in from {IPAddress})] public static partial void LogUserLogin(ILogger logger, string userId, string ipAddress);异步日志处理模式// 配置支持异步的Provider builder.Logging.AddAsyncConsole(options { options.MaxQueueLength 1000; options.FlushInterval TimeSpan.FromSeconds(1); });5. 常见问题排查指南5.1 日志不输出问题检查步骤确认日志级别设置正确检查是否添加了对应的Provider验证配置文件是否被正确加载检查日志过滤规则// 调试日志配置 var logLevel loggerFactory.Services .GetRequiredServiceIOptionsLoggerFilterOptions() .Value.MinLevel; logger.LogDebug(Current log level: {LogLevel}, logLevel);5.2 日志格式混乱解决方案统一配置日志格式化器builder.Logging.AddSimpleConsole(options { options.TimestampFormat yyyy-MM-dd HH:mm:ss ; options.IncludeScopes true; options.SingleLine true; });使用JSON结构化输出builder.Logging.AddJsonConsole(options { options.JsonWriterOptions new JsonWriterOptions { Indented true }; });5.3 日志文件过大处理方案配置日志滚动策略builder.Logging.AddFile(options { options.FileName app-; options.Extension .log; options.Periodicity PeriodicityOptions.Daily; options.RetainedFileCountLimit 7; });实现日志压缩归档services.AddHostedServiceLogArchiverBackgroundService();6. 高级应用场景6.1 分布式追踪集成builder.Logging.AddOpenTelemetry(options { options.IncludeScopes true; options.AddOtlpExporter(otlpOptions { otlpOptions.Endpoint new Uri(http://collector:4317); }); });6.2 动态日志级别调整实现无需重启的热更新var reloadToken config.GetReloadToken(); reloadToken.RegisterChangeCallback(_ { logger.LogInformation(Logging configuration reloaded); }, null);6.3 自定义日志Provider实现自定义Provider的步骤继承ILoggerProvider实现ISupportExternalScope如需作用域支持创建对应的ILogger实现public class CustomLoggerProvider : ILoggerProvider { public ILogger CreateLogger(string categoryName) new CustomLogger(); public void Dispose() { } private class CustomLogger : ILogger { public IDisposable BeginScopeTState(TState state) null; public bool IsEnabled(LogLevel logLevel) true; public void LogTState(LogLevel logLevel, EventId eventId, TState state, Exception exception, FuncTState, Exception, string formatter) { // 自定义日志处理逻辑 } } }7. 生产环境部署建议日志分离策略业务日志与应用日志分离不同级别日志分开存储关键操作单独记录审计日志安全注意事项避免记录敏感信息密码、token等实施日志访问控制考虑日志脱敏处理监控方案builder.Logging.AddApplicationInsights( configureTelemetryConfiguration: config config.ConnectionString YOUR_INSTRUMENTATION_KEY, configureApplicationInsightsLoggerOptions: options {} );性能指标监控var meter new Meter(Microsoft.Extensions.Logging, 1.0.0); var loggingCounter meter.CreateCounterint(logs-written);