From c37c7701b13c241e5be581a7289091fddcf9daa9 Mon Sep 17 00:00:00 2001 From: "wei.zhao" Date: Thu, 22 May 2025 10:34:13 +0800 Subject: [PATCH 1/2] Add IHostApplicationBuilder support --- .../Extensions/ConfigureExtensions.cs | 28 +++- .../ExtensionMethodTests.cs | 126 ++++++++++++++++++ 2 files changed, 153 insertions(+), 1 deletion(-) diff --git a/src/NLog.Extensions.Hosting/Extensions/ConfigureExtensions.cs b/src/NLog.Extensions.Hosting/Extensions/ConfigureExtensions.cs index 3b51b3dd..682410a1 100644 --- a/src/NLog.Extensions.Hosting/Extensions/ConfigureExtensions.cs +++ b/src/NLog.Extensions.Hosting/Extensions/ConfigureExtensions.cs @@ -45,6 +45,32 @@ public static IHostBuilder UseNLog(this IHostBuilder builder, NLogProviderOption return builder; } +#if NET8_0_OR_GREATER + /// + /// Enable NLog as logging provider for Microsoft Extension Logging + /// + /// + /// IHostApplicationBuilder for chaining + public static IHostApplicationBuilder UseNLog(this IHostApplicationBuilder builder) + { + Guard.ThrowIfNull(builder); + return builder.UseNLog(null); + } + + /// + /// Enable NLog as logging provider for Microsoft Extension Logging + /// + /// + /// NLogProviderOptions object to configure NLog behavior + /// IHostApplicationBuilder for chaining + public static IHostApplicationBuilder UseNLog(this IHostApplicationBuilder builder, NLogProviderOptions options) + { + Guard.ThrowIfNull(builder); + builder.Services.TryAddNLogLoggingProvider((svc, addlogging) => svc.AddLogging(addlogging), builder.Configuration, options, (provider, cfg, opt) => CreateNLogLoggerProvider(provider, cfg, builder.Environment, opt)); + return builder; + } +#endif + private static void AddNLogLoggerProvider(IServiceCollection services, IConfiguration hostConfiguration, IHostEnvironment hostEnvironment, NLogProviderOptions options, Func factory) { services.TryAddNLogLoggingProvider((svc, addlogging) => svc.AddLogging(addlogging), hostConfiguration, options, (provider, cfg, opt) => factory(provider, cfg, hostEnvironment, opt)); @@ -73,7 +99,7 @@ private static NLogLoggerProvider CreateNLogLoggerProvider(IServiceProvider serv { provider.LogFactory.Setup().LoadConfigurationFromFile(nlogConfigFile, optional: true); } - + provider.LogFactory.Setup().SetupLogFactory(ext => ext.AddCallSiteHiddenAssembly(typeof(ConfigureExtensions).Assembly)); return provider; } diff --git a/test/NLog.Extensions.Hosting.Tests/ExtensionMethodTests.cs b/test/NLog.Extensions.Hosting.Tests/ExtensionMethodTests.cs index e117a59a..4098ba03 100644 --- a/test/NLog.Extensions.Hosting.Tests/ExtensionMethodTests.cs +++ b/test/NLog.Extensions.Hosting.Tests/ExtensionMethodTests.cs @@ -129,5 +129,131 @@ public void UseNLog_LoadConfigurationFromSection() Assert.Single(logged); Assert.Equal("logger1|error1|Memory", logged[0]); } + +#if NET8_0_OR_GREATER + [Fact] + public void IHostApplicationBuilder_UseNLog_ArgumentNullException() + { + IHostApplicationBuilder hostBuilder = null; + var argNulLException = Assert.Throws(() => hostBuilder.UseNLog()); + Assert.Equal("builder", argNulLException.ParamName); + } + + [Fact] + public void IHostApplicationBuilder_UseNLog_noParams_WorksWithNLog() + { + var builder = new HostApplicationBuilder(); + builder.UseNLog(); + + var actual = builder.Build(); + TestHostingResult(actual, true); + } + + [Fact] + public void IHostApplicationBuilder_UseNLog_withOptionsParam_WorksWithNLog() + { + var someParam = new NLogProviderOptions { CaptureMessageProperties = false, CaptureMessageTemplates = false }; + + var builder = new HostApplicationBuilder(); + builder.UseNLog(someParam); + + var actual = builder.Build(); + TestHostingResult(actual, true); + } + + [Fact] + public void IHostApplicationBuilder_UseNLog_withConfiguration_WorksWithNLog() + { + var memoryConfig = new Dictionary(); + memoryConfig["NLog:CaptureMessageProperties"] = "true"; + memoryConfig["NLog:CaptureMessageTemplates"] = "false"; + memoryConfig["NLog:IgnoreScopes"] = "false"; + + var someParam = new NLogProviderOptions { CaptureMessageProperties = false, CaptureMessageTemplates = false }; + + var builder = new HostApplicationBuilder(); + builder.Configuration.AddInMemoryCollection(memoryConfig); + builder.UseNLog(someParam); + + var actual = builder.Build(); + TestHostingResult(actual, true); + } + + [Fact] + public void IHostApplicationBuilder_AddNLog_withShutdownOnDispose_worksWithNLog() + { + var someParam = new NLogProviderOptions { ShutdownOnDispose = true }; + + var builder = new HostApplicationBuilder(); + builder.Logging.AddNLog(someParam); + + var actual = builder.Build(); + try + { + TestHostingResult(actual, false); + Assert.NotNull(LogManager.Configuration); + } + finally + { + actual.Dispose(); + Assert.Null(LogManager.Configuration); + } + } + + [Fact] + public void IHostApplicationBuilder_UseNLog_withAddNLog_worksWithNLog() + { + var builder = new HostApplicationBuilder(); + builder.UseNLog(); + builder.Logging.AddNLog(); + + var actual = builder.Build(); + TestHostingResult(actual, true); + } + + [Fact] + public void IHostApplicationBuilder_UseNLog_ReplaceLoggerFactory() + { + var builder = new HostApplicationBuilder(); + builder.Services.AddLogging(); + builder.UseNLog(new NLogProviderOptions() { ReplaceLoggerFactory = true, RemoveLoggerFactoryFilter = true }); + + var actual = builder.Build(); + + var loggerFactory = actual.Services.GetService(); + + Assert.Equal(typeof(NLogLoggerFactory), loggerFactory.GetType()); + } + + [Fact] + public void IHostApplicationBuilder_UseNLog_LoadConfigurationFromSection() + { + var memoryConfig = new Dictionary(); + memoryConfig["NLog:Rules:0:logger"] = "*"; + memoryConfig["NLog:Rules:0:minLevel"] = "Trace"; + memoryConfig["NLog:Rules:0:writeTo"] = "inMemory"; + memoryConfig["NLog:Targets:inMemory:type"] = "Memory"; + memoryConfig["NLog:Targets:inMemory:layout"] = "${logger}|${message}|${configsetting:NLog.Targets.inMemory.type}"; + + var builder = new HostApplicationBuilder(); + builder.Configuration.AddInMemoryCollection(memoryConfig); + builder.UseNLog(new NLogProviderOptions() { LoggingConfigurationSectionName = "NLog", ReplaceLoggerFactory = true }); + + var host = builder.Build(); + + var loggerFact = host.Services.GetService(); + var logger = loggerFact.CreateLogger("logger1"); + + ConfigSettingLayoutRenderer.DefaultConfiguration = null; // See dependency resolving is working + + logger.LogError("error1"); + + var loggerProvider = host.Services.GetService() as NLogLoggerProvider; + var logged = loggerProvider.LogFactory.Configuration.FindTargetByName("inMemory").Logs; + + Assert.Single(logged); + Assert.Equal("logger1|error1|Memory", logged[0]); + } +#endif } } \ No newline at end of file From 727439ba6e0f739362bf4c4073d1b7876bba2911 Mon Sep 17 00:00:00 2001 From: "wei.zhao" Date: Thu, 22 May 2025 17:39:50 +0800 Subject: [PATCH 2/2] Add reset after test --- test/NLog.Extensions.Hosting.Tests/ExtensionMethodTests.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/NLog.Extensions.Hosting.Tests/ExtensionMethodTests.cs b/test/NLog.Extensions.Hosting.Tests/ExtensionMethodTests.cs index 4098ba03..e67fbb46 100644 --- a/test/NLog.Extensions.Hosting.Tests/ExtensionMethodTests.cs +++ b/test/NLog.Extensions.Hosting.Tests/ExtensionMethodTests.cs @@ -128,6 +128,8 @@ public void UseNLog_LoadConfigurationFromSection() Assert.Single(logged); Assert.Equal("logger1|error1|Memory", logged[0]); + //Reset + LogManager.Configuration = null; } #if NET8_0_OR_GREATER @@ -253,6 +255,8 @@ public void IHostApplicationBuilder_UseNLog_LoadConfigurationFromSection() Assert.Single(logged); Assert.Equal("logger1|error1|Memory", logged[0]); + //Reset + LogManager.Configuration = null; } #endif }