Skip to content

Commit

Permalink
LogManager.Setup() - SetupBuilderExtension with LoadConfigurationFrom…
Browse files Browse the repository at this point in the history
…AppSettings (#540)
  • Loading branch information
snakefoot committed Jun 21, 2020
1 parent 677d278 commit e0b1503
Show file tree
Hide file tree
Showing 5 changed files with 251 additions and 11 deletions.
Expand Up @@ -3,6 +3,7 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using NLog.Extensions.Logging;
using NLog.Web;

namespace NLog.Web.AspNetCore2.Example
Expand All @@ -11,7 +12,13 @@ public static class Program
{
public static void Main(string[] args)
{
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
var config = new ConfigurationBuilder().Build();

var logger = LogManager.Setup()
.RegisterNLogWeb(config)
.LoadConfigurationFromFile("nlog.config")
.GetCurrentClassLogger();

try
{
logger.Debug("init main");
Expand Down
6 changes: 5 additions & 1 deletion examples/ASP.NET Core 3/ASP.NET Core 3 - VS2019/Program.cs
Expand Up @@ -6,6 +6,7 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NLog;
using NLog.Web;

namespace ASP.NET_Core_3___VS2019
Expand All @@ -14,7 +15,10 @@ public class Program
{
public static void Main(string[] args)
{
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
var logger = LogManager.Setup()
.LoadConfigurationFromAppSettings()
.GetCurrentClassLogger();

try
{
logger.Debug("init main");
Expand Down
103 changes: 103 additions & 0 deletions src/NLog.Web.AspNetCore/Config/SetupBuilderExtensions.cs
@@ -0,0 +1,103 @@
using System;
#if !ASP_NET_CORE1 && !ASP_NET_CORE2
using System.IO;
using System.Linq;
#endif
using Microsoft.Extensions.Configuration;
using NLog.Config;
using NLog.Extensions.Logging;

namespace NLog.Web
{
/// <summary>
/// Extension methods to setup LogFactory options
/// </summary>
public static class SetupBuilderExtensions
{
#if !ASP_NET_CORE1 && !ASP_NET_CORE2
/// <summary>
/// Loads NLog LoggingConfiguration from appsettings.json from the NLog-section
/// </summary>
public static ISetupBuilder LoadConfigurationFromAppSettings(this ISetupBuilder setupBuilder, string basePath = null, string environment = null, string nlogConfigSection = "NLog", bool optional = true, bool reloadOnChange = false)
{
environment = environment ?? GetAspNetCoreEnvironment("DOTNET_ENVIRONMENT") ?? GetAspNetCoreEnvironment("ASPNETCORE_ENVIRONMENT") ?? "Production";

var builder = new ConfigurationBuilder()
// Host Configuration
.SetBasePath(basePath ?? Directory.GetCurrentDirectory())
.AddEnvironmentVariables(prefix: "ASPNETCORE_")
.AddEnvironmentVariables(prefix: "DOTNET_")
// App Configuration
.AddJsonFile("appsettings.json", optional, reloadOnChange)
.AddJsonFile($"appsettings.{environment}.json", optional: true, reloadOnChange: reloadOnChange)
.AddEnvironmentVariables();

var config = builder.Build();
if (!string.IsNullOrEmpty(nlogConfigSection) && config.GetSection(nlogConfigSection)?.GetChildren().Any() == true)
{
return setupBuilder.SetupExtensions(e => e.RegisterNLogWeb()).LoadConfigurationFromSection(config, nlogConfigSection);
}
else
{
setupBuilder.SetupExtensions(e => e.RegisterNLogWeb().RegisterConfigSettings(config));

if (!string.IsNullOrEmpty(basePath))
{
if (!string.IsNullOrEmpty(environment))
{
setupBuilder.LoadConfigurationFromFile(Path.Combine(basePath, $"nlog.{environment}.config"), optional: true);
}

setupBuilder.LoadConfigurationFromFile(Path.Combine(basePath, "nlog.config"), optional: true);
}
else if (!string.IsNullOrEmpty(environment))
{
setupBuilder.LoadConfigurationFromFile($"nlog.{environment}.config", optional: true);
}

return setupBuilder.LoadConfigurationFromFile(); // No effect, if config already loaded
}
}

private static string GetAspNetCoreEnvironment(string variableName)
{
try
{
var environment = Environment.GetEnvironmentVariable(variableName);
if (string.IsNullOrWhiteSpace(environment))
return null;

return environment.Trim();
}
catch (Exception ex)
{
NLog.Common.InternalLogger.Error(ex, "Failed to lookup environment variable {0}", variableName);
return null;
}
}
#endif

/// <summary>
/// Convience method to register aspnet-layoutrenders in NLog.Web as one-liner before loading NLog.config
/// </summary>
/// <remarks>
/// If not providing <paramref name="serviceProvider"/>, then output from aspnet-layoutrenderers will remain empty
/// </remarks>
public static ISetupBuilder RegisterNLogWeb(this ISetupBuilder setupBuilder, IConfiguration configuration = null, IServiceProvider serviceProvider = null)
{
setupBuilder.SetupExtensions(e => e.RegisterNLogWeb(serviceProvider));

if (configuration == null && serviceProvider != null)
{
configuration = serviceProvider.GetService(typeof(IConfiguration)) as IConfiguration;
}

if (configuration != null)
{
setupBuilder.SetupExtensions(e => e.RegisterConfigSettings(configuration));
}

return setupBuilder;
}
}
}
40 changes: 40 additions & 0 deletions src/NLog.Web.AspNetCore/Config/SetupExtensionsBuilderExtensions.cs
@@ -0,0 +1,40 @@
using System;
using System.Reflection;
using Microsoft.Extensions.Configuration;
using NLog.Config;
using NLog.Extensions.Logging;
using NLog.Web.DependencyInjection;

namespace NLog.Web
{
/// <summary>
/// Extension methods to setup NLog extensions, so they are known when loading NLog LoggingConfiguration
/// </summary>
public static class SetupExtensionsBuilderExtensions
{
/// <summary>
/// Replace with version from NLog.Extension.Logging when it has been released with NLog 4.7
/// </summary>
internal static ISetupExtensionsBuilder RegisterConfigSettings(this ISetupExtensionsBuilder setupBuilder, IConfiguration configuration)
{
ConfigSettingLayoutRenderer.DefaultConfiguration = configuration;
return setupBuilder.RegisterLayoutRenderer<ConfigSettingLayoutRenderer>("configsetting");
}

/// <summary>
/// Register the NLog.Web.AspNetCore LayoutRenderers
/// </summary>
/// <remarks>
/// If not providing <paramref name="serviceProvider"/>, then output from aspnet-layoutrenderers will remain empty
/// </remarks>
public static ISetupExtensionsBuilder RegisterNLogWeb(this ISetupExtensionsBuilder setupBuilder, IServiceProvider serviceProvider = null)
{
if (serviceProvider != null)
{
ServiceLocator.ServiceProvider = serviceProvider;
}

return setupBuilder.RegisterAssembly(typeof(NLogAspNetCoreOptions).GetTypeInfo().Assembly);
}
}
}
104 changes: 95 additions & 9 deletions tests/NLog.Web.AspNetCore.Tests/AspNetCoreTests.cs
Expand Up @@ -5,7 +5,6 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Castle.Core.Logging;
using Xunit;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
Expand All @@ -16,7 +15,6 @@
using NLog.Config;
using NLog.Layouts;
using NLog.Targets;
using NLog.Web.Tests.LayoutRenderers;
using ILoggerFactory = Microsoft.Extensions.Logging.ILoggerFactory;

namespace NLog.Web.Tests
Expand Down Expand Up @@ -44,7 +42,7 @@ public void UseNLogShouldLogTest()

var configuration = CreateConfigWithMemoryTarget(out var target, "${logger}|${message}");

LogManager.Configuration = configuration;
LogManager.Setup().RegisterNLogWeb(serviceProvider: webhost.Services).LoadConfiguration(configuration);

var logger = loggerFact.CreateLogger("logger1");

Expand All @@ -54,9 +52,100 @@ public void UseNLogShouldLogTest()

Assert.Single(logged);
Assert.Equal("logger1|error1", logged.First());
}

#if !ASP_NET_CORE1 && !ASP_NET_CORE2
[Fact]
public void LoadConfigurationFromAppSettingsShouldLogTest()
{
var tempPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), nameof(AspNetCoreTests), Guid.NewGuid().ToString()).Replace("\\", "/");
var appSettings = System.IO.Path.Combine(tempPath, "appsettings.json");

try
{
// Arrange
System.IO.Directory.CreateDirectory(tempPath);
System.IO.File.AppendAllText(appSettings, @"{
""basepath"": """ + tempPath + @""",
""NLog"": {
""throwConfigExceptions"": true,
""targets"": {
""logfile"": {
""type"": ""File"",
""fileName"": ""${configsetting:basepath}/hello.txt"",
""layout"": ""${message}""
}
},
""rules"": [
{
""logger"": ""*"",
""minLevel"": ""Debug"",
""writeTo"": ""logfile""
}
]
}
}");

// Act
var logFactory = new LogFactory();
var logger = logFactory.Setup().LoadConfigurationFromAppSettings(basePath: tempPath).GetCurrentClassLogger();
logger.Info("Hello World");

// Assert
var fileOutput = System.IO.File.ReadAllText(System.IO.Path.Combine(tempPath, "hello.txt"));
Assert.Contains("Hello World", fileOutput);
}
finally
{
if (System.IO.Directory.Exists(tempPath))
{
System.IO.Directory.Delete(tempPath, true);
}
}
}

[Fact]
public void LoadConfigurationFromAppSettingsShouldLogTest2()
{
var tempPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), nameof(AspNetCoreTests), Guid.NewGuid().ToString()).Replace("\\", "/");
var appSettings = System.IO.Path.Combine(tempPath, "appsettings.json");

try
{
// Arrange
System.IO.Directory.CreateDirectory(tempPath);
System.IO.File.AppendAllText(appSettings, @"{
""basepath"": """ + tempPath + @"""
}");

System.IO.File.AppendAllText(System.IO.Path.Combine(tempPath, "nlog.config"), @"<nlog>
<targets>
<target type=""file"" name=""logfile"" layout=""${message}"" fileName=""${configsetting:basepath}/hello.txt"" />
</targets>
<rules>
<logger name=""*"" minLevel=""Debug"" writeTo=""logfile"" />
</rules>
</nlog>");

// Act
var logFactory = new LogFactory();
var logger = logFactory.Setup().LoadConfigurationFromAppSettings(basePath: tempPath).GetCurrentClassLogger();
logger.Info("Hello World");

// Assert
var fileOutput = System.IO.File.ReadAllText(System.IO.Path.Combine(tempPath, "hello.txt"));
Assert.Contains("Hello World", fileOutput);
}
finally
{
if (System.IO.Directory.Exists(tempPath))
{
System.IO.Directory.Delete(tempPath, true);
}
}
}
#endif

private static LoggingConfiguration CreateConfigWithMemoryTarget(out MemoryTarget target, Layout layout)
{
var configuration = new LoggingConfiguration();
Expand All @@ -66,7 +155,6 @@ private static LoggingConfiguration CreateConfigWithMemoryTarget(out MemoryTarge
return configuration;
}


[Fact]
public void UseAspNetWithoutRegister()
{
Expand All @@ -79,7 +167,7 @@ public void UseAspNetWithoutRegister()

var configuration = CreateConfigWithMemoryTarget(out var target, "${logger}|${message}|${aspnet-item:key1}");

LogManager.Configuration = configuration;
LogManager.Setup().RegisterNLogWeb(serviceProvider: webhost.Services).LoadConfiguration(configuration);

var httpContext = webhost.Services.GetService<IHttpContextAccessor>().HttpContext = new DefaultHttpContext();
httpContext.Items["key1"] = "value1";
Expand All @@ -100,18 +188,16 @@ public void UseAspNetWithoutRegister()
//clear so next time it's rebuild
ConfigurationItemFactory.Default = null;
}

}


[Fact]
public void RegisterHttpContext()
{
var webhost = CreateWebHost();
Assert.NotNull(webhost.Services.GetService<IHttpContextAccessor>());
}

#if ASP_NET_CORE2
#if !ASP_NET_CORE1
[Fact]
public void SkipRegisterHttpContext()
{
Expand All @@ -126,7 +212,7 @@ public void SkipRegisterHttpContext()
/// <returns></returns>
private static IWebHost CreateWebHost(NLogAspNetCoreOptions options = null)
{
#if ASP_NET_CORE2 || ASP_NET_CORE3
#if !ASP_NET_CORE1
var webhost =
Microsoft.AspNetCore.WebHost.CreateDefaultBuilder()
.Configure(c => c.New()) //.New needed, otherwise:
Expand Down

0 comments on commit e0b1503

Please sign in to comment.