ASP.NET Core 6中通过DI获取NLog日志实例异常问题
ASP.NET Core 6中NLog依赖注入实例日志级别异常问题解决
问题现象
- Program.cs中直接创建的NLog日志实例可正确识别Debug/Trace级别,正常写入日志文件
- 控制器通过构造函数注入的
ILogger<HomeController>实例,始终显示Debug、Trace级别未启用,无法写入配置文件 - 项目使用NLog.Extensions.Logging和NLog.Web.AspNetCore 5.2.1版本,旧版拆分Program.cs/Startup.cs的项目可正常工作
- 已尝试指定NLog配置节名称、开启NLog内部日志,问题未解决
相关代码
Program.cs 原代码
var logger = NLog.LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger(); logger.Info("Service Init"); logger.Info($" Log Level - Debug: {logger.IsEnabled(NLog.LogLevel.Debug)} Trace: {logger.IsEnabled(NLog.LogLevel.Trace)}"); try { var builder = WebApplication.CreateBuilder(args); builder.Logging.ClearProviders(); //builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); builder.Host.UseNLog(); builder.Services.AddControllersWithViews(); var app = builder.Build(); app.UseStaticFiles(); app.UseRouting(); app.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run(); } catch (Exception exc) { logger.Error(exc, "Stopped program because of exception"); throw; } finally { NLog.LogManager.Shutdown(); }
控制器构造函数
public HomeController(ILogger<HomeController> logger) { _logger = logger; }
控制器日志代码
_logger.Info($"Log Level - Debug: {_logger.IsEnabled(NLog.LogLevel.Debug)} Trace: {_logger.IsEnabled(NLog.LogLevel.Trace)}");
NLog内部日志片段
2023-01-08 08:58:50.5328 Debug ScanAssembly('NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c') 2023-01-08 08:58:50.6446 Debug ScanAssembly('NLog.Web.AspNetCore, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c') 2023-01-08 08:58:50.6610 Trace Assembly 'NLog.Web.AspNetCore, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c' will be hidden in callsite stacktrace 2023-01-08 08:58:50.9908 Debug Hide assemblies for callsite 2023-01-08 08:58:50.9914 Debug ScanAssembly('NLog.Extensions.Logging, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c') 2023-01-08 08:58:50.9914 Trace Assembly 'NLog.Extensions.Logging, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c' will be hidden in callsite stacktrace 2023-01-08 08:58:50.9914 Trace Assembly 'Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60' will be hidden in callsite stacktrace 2023-01-08 08:58:50.9914 Trace Assembly 'Microsoft.Extensions.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60' will be hidden in callsite stacktrace 2023-01-08 08:58:51.0219 Trace ParseNLogConfig
问题原因
- ASP.NET Core 6的WebApplicationBuilder模式下,
builder.Host.UseNLog()默认不会复用提前通过LogManager.Setup()加载的配置,导致DI容器中的日志实例使用默认配置而非自定义配置 - 未设置Microsoft Logging的最小级别,默认日志过滤层会拦截Debug/Trace级别的日志,即使NLog配置了对应级别也无法输出
解决方案
1. 调整Program.cs初始化顺序并启用最小日志级别
修改后的Program.cs代码:
try { var builder = WebApplication.CreateBuilder(args); // 清除默认日志提供器,设置最小级别为Trace builder.Logging.ClearProviders(); builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); // 让Host加载NLog配置,整合到DI容器 builder.Host.UseNLog(); // 获取Host初始化后的NLog实例 var logger = NLog.LogManager.GetCurrentClassLogger(); logger.Info("Service Init"); logger.Info($" Log Level - Debug: {logger.IsEnabled(NLog.LogLevel.Debug)} Trace: {logger.IsEnabled(NLog.LogLevel.Trace)}"); builder.Services.AddControllersWithViews(); var app = builder.Build(); app.UseStaticFiles(); app.UseRouting(); app.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run(); } catch (Exception exc) { var logger = NLog.LogManager.GetCurrentClassLogger(); logger.Error(exc, "Stopped program because of exception"); throw; } finally { NLog.LogManager.Shutdown(); }
2. 确保NLog配置文件启用Debug/Trace级别
如果使用appsettings.json配置NLog,确保rules中包含Trace级别:
"NLog": { "targets": { "file": { "type": "File", "fileName": "${basedir}/logs/${shortdate}.log", "layout": "${longdate} ${level} ${message} ${exception}" } }, "rules": [ { "logger": "*", "minLevel": "Trace", "writeTo": "file" } ] }
如果使用nlog.config配置,确保规则中minlevel设置为Trace:
<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <targets> <target name="file" xsi:type="File" fileName="${basedir}/logs/${shortdate}.log" layout="${longdate} ${level} ${message} ${exception}" /> </targets> <rules> <logger name="*" minlevel="Trace" writeTo="file" /> </rules> </nlog>
说明
- 将NLog初始化移到WebApplicationBuilder配置之后,确保
UseNLog()正确加载配置并注入到DI容器中 - 启用
builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace),避免Microsoft日志框架过滤Debug/Trace日志 - 移除提前调用
LogManager.Setup()的代码,防止配置冲突导致DI实例无法获取正确配置
内容的提问来源于stack exchange,提问作者Rick
相关产品推荐
相关产品推荐

