Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configure NLogProviderOptions from appsettings.json #248

Merged
merged 3 commits into from
Jan 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions examples/NetCore2/ConsoleExample/ConsoleExample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,19 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.1.0" />
<PackageReference Include="NLog.Schema" Version="4.5.11" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\src\NLog.Extensions.Logging\NLog.Extensions.Logging.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="nlog.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
Expand Down
3,106 changes: 0 additions & 3,106 deletions examples/NetCore2/ConsoleExample/NLog.xsd

This file was deleted.

31 changes: 17 additions & 14 deletions examples/NetCore2/ConsoleExample/Program.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using Microsoft.Extensions.DependencyInjection;
using System;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NLog;
using NLog.Extensions.Logging;
using System;
using LogLevel = Microsoft.Extensions.Logging.LogLevel;

namespace ConsoleExample
{
Expand Down Expand Up @@ -44,21 +44,20 @@ private static IServiceProvider BuildDi()
// Runner is the custom class
services.AddTransient<Runner>();

services.AddSingleton<ILoggerFactory, LoggerFactory>();
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
services.AddLogging(builder => builder.SetMinimumLevel(LogLevel.Trace));
var config = new ConfigurationBuilder()
.SetBasePath(System.IO.Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.Build();

var serviceProvider = services.BuildServiceProvider();

var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();

// configure NLog
loggerFactory.AddNLog(new NLogProviderOptions
// configure Logging with NLog
services.AddLogging(loggingBuilder =>
{
CaptureMessageTemplates = true,
CaptureMessageProperties = true
loggingBuilder.ClearProviders();
loggingBuilder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
loggingBuilder.AddNLog(config);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this is DI-proof.

I think it's a good change to move to the Factory instead of Provider, that's the one we could also bootstrap from DI. See #253

Copy link
Contributor Author

@snakefoot snakefoot Oct 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please explain DI-proof? Adding the NLogLoggerProvider as provider to the official LoggerFactory is the nice way of being part of Microsoft Logging Extensions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like to change the call, if we need a new dependency. But is a bit debatable if the config is here an dependency or not.

Copy link
Contributor Author

@snakefoot snakefoot Oct 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was planning that NLogLoggingProvider.Options and NLog-LoggingConfiguration was loaded from IConfiguration. So it would be natural to receive the config when doing AddNLog.

But not that skilled with DI and fluent-interface, so any help with creating a great interface is very welcome.

});

var serviceProvider = services.BuildServiceProvider();
return serviceProvider;
}
}
Expand All @@ -75,6 +74,10 @@ public Runner(ILogger<Runner> logger)
public void DoAction(string name)
{
_logger.LogDebug(20, "Doing hard work! {Action}", name);
_logger.LogInformation(21, "Doing hard work! {Action}", name);
_logger.LogWarning(22, "Doing hard work! {Action}", name);
_logger.LogError(23, "Doing hard work! {Action}", name);
_logger.LogCritical(24, "Doing hard work! {Action}", name);
}
}
}
9 changes: 9 additions & 0 deletions examples/NetCore2/ConsoleExample/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Logging": {
"NLog": {
"IncludeScopes": false,
"ParseMessageTemplates": true,
"CaptureMessageProperties": true
}
}
}
12 changes: 11 additions & 1 deletion src/NLog.Extensions.Hosting/Extensions/ConfigureExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,17 @@ public static IHostBuilder UseNLog(this IHostBuilder builder, NLogProviderOption
ConfigurationItemFactory.Default.RegisterItemsFromAssembly(typeof(ConfigureExtensions).GetTypeInfo()
.Assembly);

services.AddSingleton(new LoggerFactory().AddNLog(options));
services.AddSingleton<ILoggerProvider>(serviceProvider =>
{
var provider = new NLogLoggerProvider(options ?? new NLogProviderOptions());
if (hostbuilder.Configuration != null)
{
// TODO ConfigSettingLayoutRenderer.DefaultConfiguration = hostbuilder.Configuration;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when should be do this TODO?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Next PR. You just requested me to split this into more PRs

if (options == null)
provider.Configure(hostbuilder.Configuration?.GetSection("Logging:NLog"));
}
return provider;
});
});

return builder;
Expand Down
5 changes: 2 additions & 3 deletions src/NLog.Extensions.Hosting/NLog.Extensions.Hosting.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<DebugType>full</DebugType>
<DebugSymbols>true</DebugSymbols>
<DebugType Condition=" '$(Configuration)' == 'Debug' ">Full</DebugType>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<GenerateDocumentationFile>true</GenerateDocumentationFile>

Expand All @@ -28,7 +27,7 @@
<AssemblyOriginatorKeyFile>..\NLog.snk</AssemblyOriginatorKeyFile>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="2.1.0" />
</ItemGroup>
Expand Down
85 changes: 78 additions & 7 deletions src/NLog.Extensions.Logging/Extensions/ConfigureExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
using System;
using System.Linq;
using System.Reflection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using NLog.Common;
using NLog.Config;

namespace NLog.Extensions.Logging
{
/// <summary>
/// Helpers for .NET Core
/// Helpers for configuring NLog for Microsoft Extension Logging (MEL)
/// </summary>
public static class ConfigureExtensions
{
/// <summary>
/// Enable NLog as logging provider in .NET Core.
/// Enable NLog as logging provider for Microsoft Extension Logging
/// </summary>
/// <param name="factory"></param>
/// <returns>ILoggerFactory for chaining</returns>
public static ILoggerFactory AddNLog(this ILoggerFactory factory)
{
return AddNLog(factory, null);
return factory.AddNLog(NLogProviderOptions.Default);
}

/// <summary>
/// Enable NLog as logging provider in .NET Core.
/// Enable NLog as logging provider for Microsoft Extension Logging
/// </summary>
/// <param name="factory"></param>
/// <param name="options">NLog options</param>
Expand All @@ -33,19 +35,45 @@ public static ILoggerFactory AddNLog(this ILoggerFactory factory, NLogProviderOp
return factory;
}

/// <summary>
/// Enable NLog as logging provider for Microsoft Extension Logging
/// </summary>
/// <param name="factory"></param>
/// <param name="configuration"></param>
/// <returns>ILoggerFactory for chaining</returns>
public static ILoggerFactory AddNLog(this ILoggerFactory factory, IConfiguration configuration)
{
var provider = CreateNLogProvider(configuration);
factory.AddProvider(provider);
return factory;
}

#if !NETCORE1_0
/// <summary>
/// Enable NLog as logging provider in .NET Core.
/// Enable NLog as logging provider for Microsoft Extension Logging
/// </summary>
/// <param name="factory"></param>
/// <returns>ILoggerFactory for chaining</returns>
public static ILoggingBuilder AddNLog(this ILoggingBuilder factory)
{
return AddNLog(factory, null);
return factory.AddNLog(NLogProviderOptions.Default);
}

/// <summary>
/// Enable NLog as logging provider in .NET Core.
/// Enable NLog as logging provider for Microsoft Extension Logging
/// </summary>
/// <param name="factory"></param>
/// <param name="configuration">Configuration</param>
/// <returns>ILoggerFactory for chaining</returns>
public static ILoggingBuilder AddNLog(this ILoggingBuilder factory, IConfiguration configuration)
{
var provider = CreateNLogProvider(configuration);
factory.AddProvider(provider);
return factory;
}

/// <summary>
/// Enable NLog as logging provider for Microsoft Extension Logging
/// </summary>
/// <param name="factory"></param>
/// <param name="options">NLog options</param>
Expand Down Expand Up @@ -83,5 +111,48 @@ public static LoggingConfiguration ConfigureNLog(this ILoggerFactory loggerFacto
LogManager.Configuration = config;
return config;
}

/// <summary>
/// Factory method for <see cref="NLogLoggerProvider"/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this isn't a factory method? (IMO factory method should be called "Create")

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope it is an extension-method with fluent-interface.

/// </summary>
/// <param name="nlogProvider"></param>
/// <param name="configurationSection">Microsoft Extension Configuration</param>
/// <returns></returns>
public static NLogLoggerProvider Configure(this NLogLoggerProvider nlogProvider, IConfigurationSection configurationSection)
{
if (configurationSection == null)
return nlogProvider;

var configProps = nlogProvider.Options.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(p => p.SetMethod?.IsPublic == true).ToDictionary(p => p.Name, StringComparer.OrdinalIgnoreCase);
foreach (var configValue in configurationSection.GetChildren())
{
if (configProps.TryGetValue(configValue.Key, out var propertyInfo))
{
try
{
var result = Convert.ChangeType(configValue.Value, propertyInfo.PropertyType);
propertyInfo.SetMethod.Invoke(nlogProvider.Options, new[] { result });
}
catch (Exception ex)
{
InternalLogger.Warn(ex, "NLogProviderOptions: Property {0} could not be assigned value: {1}", configValue.Key, configValue.Value);
}
}
}

return nlogProvider;
}

private static NLogLoggerProvider CreateNLogProvider(IConfiguration configuration)
{
var provider = new NLogLoggerProvider(new NLogProviderOptions());
if (configuration != null)
{
// TODO ConfigSettingLayoutRenderer.DefaultConfiguration = configuration;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this TODO for this PR, or do we need a Github issue?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Next PR. You just requested me to split this into more PRs

provider.Configure(configuration.GetSection("Logging:NLog"));
}

return provider;
}
}
}
23 changes: 20 additions & 3 deletions src/NLog.Extensions.Logging/Logging/NLogLoggerProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,17 @@ namespace NLog.Extensions.Logging
#endif
public class NLogLoggerProvider : Microsoft.Extensions.Logging.ILoggerProvider
{
private NLogBeginScopeParser _beginScopeParser;

/// <summary>
/// NLog options
/// </summary>
public NLogProviderOptions Options { get; set; }
private NLogBeginScopeParser _beginScopeParser;

/// <summary>
/// NLog Factory
/// </summary>
public LogFactory LogFactory { get; }

/// <summary>
/// New provider with default options, see <see cref="Options"/>
Expand All @@ -34,7 +40,18 @@ public NLogLoggerProvider()
/// </summary>
/// <param name="options"></param>
public NLogLoggerProvider(NLogProviderOptions options)
:this(options, null)
{
}

/// <summary>
/// New provider with options
/// </summary>
/// <param name="options"></param>
/// <param name="logFactory">Optional isolated NLog LogFactory</param>
public NLogLoggerProvider(NLogProviderOptions options, LogFactory logFactory)
{
LogFactory = logFactory ?? LogManager.LogFactory;
Options = options ?? NLogProviderOptions.Default;
_beginScopeParser = new NLogBeginScopeParser(options);
RegisterHiddenAssembliesForCallSite();
Expand All @@ -50,7 +67,7 @@ public Microsoft.Extensions.Logging.ILogger CreateLogger(string name)
var beginScopeParser = ((Options?.CaptureMessageProperties ?? true) && (Options?.IncludeScopes ?? true))
? (_beginScopeParser ?? System.Threading.Interlocked.CompareExchange(ref _beginScopeParser, new NLogBeginScopeParser(Options), null))
: null;
return new NLogLogger(LogManager.GetLogger(name), Options, beginScopeParser);
return new NLogLogger(LogFactory.GetLogger(name), Options, beginScopeParser);
}

/// <summary>
Expand All @@ -70,7 +87,7 @@ protected virtual void Dispose(bool disposing)
{
if (disposing)
{
LogManager.Flush();
LogFactory.Flush();
}
}

Expand Down
23 changes: 13 additions & 10 deletions src/NLog.Extensions.Logging/NLog.Extensions.Logging.csproj
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>

<TargetFrameworks>net451;net461;netstandard1.3;netstandard1.5;netstandard2.0</TargetFrameworks>
<DebugType>full</DebugType>
<DebugSymbols>true</DebugSymbols>
<DebugType Condition=" '$(Configuration)' == 'Debug' ">Full</DebugType>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<GenerateDocumentationFile>true</GenerateDocumentationFile>

Expand All @@ -17,7 +16,7 @@

For ASP.NET Core, use NLog.Web.AspNetCore: https://www.nuget.org/packages/NLog.Web.AspNetCore
</Description>
<PackageTags>NLog;Microsoft.Extensions.Logging;log;logfiles;netcore;nlog</PackageTags>
<PackageTags>NLog;Microsoft.Extensions.Logging;log;logfiles;netcore</PackageTags>
<PackageReleaseNotes>

- Fixed null-reference-exception when parsing empty scope-property collection (@snakefoot)
Expand Down Expand Up @@ -63,29 +62,33 @@ Full changelog: https://github.com/NLog/NLog.Extensions.Logging/blob/master/CHAN
<DefineConstants>$(DefineConstants);NETSTANDARD</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="[4.5.10,5.0.0-beta01)" />
<PackageReference Include="NLog" Version="[4.5.11,5.0.0-beta01)" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net451' ">
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="1.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="1.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="1.0.0" />
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.0" />
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="1.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="1.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="1.0.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.5' ">
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="1.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="1.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="1.0.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.0" />
</ItemGroup>

<PropertyGroup>
<AssemblyTitle>$(Title)</AssemblyTitle>
</PropertyGroup>
</Project>

Loading