在Blazor Server中通过DI使用两个配置不同的NLog Logger
在Blazor Server中配置并注入两个独立的NLog Logger(数据库+控制台)
问题背景
需要在Blazor Server应用中使用两个配置不同的NLog Logger:一个将日志写入数据库,另一个输出到控制台,并且通过依赖注入将它们作为独立的ILogger实例在服务中使用。
已有的NLog.config配置片段:
<targets> <target name="databaseTarget" xsi:type="Database" dbProvider="Oracle.ManagedDataAccess.Client.OracleConnection, Oracle.ManagedDataAccess" connectionString="${configsetting:name=DatabaseConfiguration.ConnectionString}" commandType="Text"> <commandText> INSERT INTO SCHEMA.LOG ("Timestamp", "Level", "Logger", "Message", "Exception", "User", "CustomData") VALUES ( TO_TIMESTAMP_TZ(:timestamp, 'YYYY-MM-DD HH24:MI:SS.FF3'), :loglevel, :whichlogger, :message, :whatexception, :userx, :customdata) </commandText> <parameter name=":timestamp" layout="${date:format=yyyy-MM-dd HH\:mm\:ss.fff}" /> <parameter name=":loglevel" layout="${level}" /> <parameter name=":whichlogger" layout="${logger}" /> <parameter name=":message" layout="${message:raw=true}" /> <parameter name=":whatexception" layout="${exception:tostring}" /> <parameter name=":userx" layout="${event-properties:item=userx}" /> <parameter name=":customdata" layout="${event-properties:item=customdata}" /> </target> <target name="consoleTarget" xsi:type="ColoredConsole" layout="${longdate} ${uppercase:${level}} ${message} ${all-event-properties}" /> </targets> <extensions> <add assembly="NLog.Database"/> <add assembly="NLog.Web.AspNetCore"/> </extensions> <rules> <logger name="DatabaseLogger" minlevel="Trace" writeTo="dataBaseTarget" /> <logger name="ConsoleLogger" minlevel="Trace" writeTo="consoleTarget" /> </rules>
1. 将两个Logger注册到ServiceCollection
基于你提供的初始化代码,需要扩展配置,创建对应NLog规则名称的Logger实例,并注册到依赖注入容器中。
方法一:使用.NET 8+ 键控服务(Keyed Services)
这种方式直接注册ILogger实例,通过键名区分:
builder.Logging.ClearProviders(); builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); builder.Host.UseNLog(new NLogAspNetCoreOptions()); // 构建临时服务提供者获取LoggerFactory var tempProvider = builder.Services.BuildServiceProvider(); var loggerFactory = tempProvider.GetRequiredService<ILoggerFactory>(); // 创建对应NLog配置名称的Logger实例 var databaseLogger = loggerFactory.CreateLogger("DatabaseLogger"); var consoleLogger = loggerFactory.CreateLogger("ConsoleLogger"); // 将Logger注册为键控单例服务 builder.Services.AddKeyedSingleton<ILogger>(databaseLogger, "DatabaseLogger"); builder.Services.AddKeyedSingleton<ILogger>(consoleLogger, "ConsoleLogger");
方法二:使用包装类(兼容.NET 7及以下)
如果你的项目基于.NET 7或更早版本,不支持键控服务,可以通过包装类来区分:
第一步:定义Logger包装类
public class DatabaseLoggerWrapper { public ILogger Logger { get; } public DatabaseLoggerWrapper(ILoggerFactory loggerFactory) { Logger = loggerFactory.CreateLogger("DatabaseLogger"); } } public class ConsoleLoggerWrapper { public ILogger Logger { get; } public ConsoleLoggerWrapper(ILoggerFactory loggerFactory) { Logger = loggerFactory.CreateLogger("ConsoleLogger"); } }
第二步:注册包装类到DI容器
builder.Logging.ClearProviders(); builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); builder.Host.UseNLog(new NLogAspNetCoreOptions()); // 注册包装类 builder.Services.AddScoped<DatabaseLoggerWrapper>(); builder.Services.AddScoped<ConsoleLoggerWrapper>();
2. 在服务中注入并使用Logger
根据你选择的注册方式,对应不同的注入方式:
对应键控服务的注入方式
private readonly ILogger _databaseLogger; private readonly ILogger _consoleLogger; // 使用[FromKeyedServices]特性指定要注入的Logger键名 public MyService([FromKeyedServices("DatabaseLogger")] ILogger databaseLogger, [FromKeyedServices("ConsoleLogger")] ILogger consoleLogger) { _databaseLogger = databaseLogger; _consoleLogger = consoleLogger; _databaseLogger.LogInformation("这条日志会写入数据库"); _consoleLogger.LogInformation("这条日志会输出到控制台"); }
对应包装类的注入方式
private readonly ILogger _databaseLogger; private readonly ILogger _consoleLogger; public MyService(DatabaseLoggerWrapper databaseLoggerWrapper, ConsoleLoggerWrapper consoleLoggerWrapper) { _databaseLogger = databaseLoggerWrapper.Logger; _consoleLogger = consoleLoggerWrapper.Logger; _databaseLogger.LogInformation("这条日志会写入数据库"); _consoleLogger.LogInformation("这条日志会输出到控制台"); }
内容的提问来源于stack exchange,提问作者To Wa
相关产品推荐
相关产品推荐

