Skip to content

Commit

Permalink
NLog.Extensions.Configuration - ConfigSetting LayoutRenderer (#245)
Browse files Browse the repository at this point in the history
  • Loading branch information
snakefoot authored and 304NotModified committed Sep 22, 2018
1 parent b37f5ac commit ca1fdb1
Show file tree
Hide file tree
Showing 11 changed files with 423 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ install:
# Restore dependencies
- dotnet restore src/NLog.Extensions.Logging
- dotnet restore src/NLog.Extensions.Hosting
- dotnet restore src/NLog.Extensions.Configuration
- dotnet restore test/NLog.Extensions.Hosting.Tests
- dotnet restore test/NLog.Extensions.Logging.Tests
- dotnet restore test/NLog.Extensions.Configuration.Tests

script:
# Run tests
- dotnet test test/NLog.Extensions.Hosting.Tests --configuration Release --framework netcoreapp2.0
- dotnet test test/NLog.Extensions.Logging.Tests --configuration Release --framework netcoreapp2.0
- dotnet test test/NLog.Extensions.Configuration.Tests --configuration Release --framework netcoreapp2.0
14 changes: 14 additions & 0 deletions NLog.Extensions.Logging.sln
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NLog.Extensions.Logging.Tes
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostingExample", "examples\NetCore2\HostingExample\HostingExample.csproj", "{07D358DF-D77A-434B-B034-95785DF7106F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NLog.Extensions.Configuration", "src\NLog.Extensions.Configuration\NLog.Extensions.Configuration.csproj", "{AE82D026-CE85-48CC-BFFE-2D5C1556CC2B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NLog.Extensions.Configuration.Tests", "test\NLog.Extensions.Configuration.Tests\NLog.Extensions.Configuration.Tests.csproj", "{78A9081B-066B-4B34-BBD7-764D53CE4AA3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -50,6 +54,14 @@ Global
{07D358DF-D77A-434B-B034-95785DF7106F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{07D358DF-D77A-434B-B034-95785DF7106F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{07D358DF-D77A-434B-B034-95785DF7106F}.Release|Any CPU.Build.0 = Release|Any CPU
{AE82D026-CE85-48CC-BFFE-2D5C1556CC2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AE82D026-CE85-48CC-BFFE-2D5C1556CC2B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AE82D026-CE85-48CC-BFFE-2D5C1556CC2B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AE82D026-CE85-48CC-BFFE-2D5C1556CC2B}.Release|Any CPU.Build.0 = Release|Any CPU
{78A9081B-066B-4B34-BBD7-764D53CE4AA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{78A9081B-066B-4B34-BBD7-764D53CE4AA3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{78A9081B-066B-4B34-BBD7-764D53CE4AA3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{78A9081B-066B-4B34-BBD7-764D53CE4AA3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -61,6 +73,8 @@ Global
{0DC000BA-2DF8-48E5-A7BC-D76CB9D3FC61} = {FBD2E07B-F25B-4D2F-AEF6-6D1E10F1E523}
{DC42BF57-6316-4FCA-AD33-48FFDAFB4712} = {FBD2E07B-F25B-4D2F-AEF6-6D1E10F1E523}
{07D358DF-D77A-434B-B034-95785DF7106F} = {BD106966-02BE-4137-B9DC-4ECE56B4C204}
{AE82D026-CE85-48CC-BFFE-2D5C1556CC2B} = {C21FD102-21B1-46DB-AD62-86692558AD01}
{78A9081B-066B-4B34-BBD7-764D53CE4AA3} = {FBD2E07B-F25B-4D2F-AEF6-6D1E10F1E523}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {46DF0C22-7B6A-4A64-BC63-7B2F6A14F334}
Expand Down
3 changes: 2 additions & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ artifacts:
test_script:
- nuget.exe install OpenCover -ExcludeVersion -DependencyVersion Ignore
- OpenCover\tools\OpenCover.Console.exe -register:user -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -f netcoreapp1.1 NLog.Extensions.Logging.Tests" -filter:"+[NLog.Extensions.Logging]* +[NLog.Extensions.Hosting]* -[NLog.Extensions.Logging.Tests]* -[NLog.Extensions.Hosting.Tests]*" -output:"coverage.xml" -oldstyle -targetdir:"test"
- OpenCover\tools\OpenCover.Console.exe -register:user -mergeoutput -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -f netcoreapp2.0 NLog.Extensions.Logging.Tests" -filter:"+[NLog.Extensions.Logging]* +[NLog.Extensions.Hosting]* -[NLog.Extensions.Logging.Tests]* -[NLog.Extensions.Hosting.Tests]*" -output:"coverage.xml" -oldstyle -targetdir:"test"
- OpenCover\tools\OpenCover.Console.exe -register:user -mergeoutput -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -f netcoreapp2.0 NLog.Extensions.Logging.Tests" -filter:"+[NLog.Extensions.Logging]* -[NLog.Extensions.Logging.Tests]*" -output:"coverage.xml" -oldstyle -targetdir:"test"
- OpenCover\tools\OpenCover.Console.exe -register:user -mergeoutput -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -f netcoreapp2.0 NLog.Extensions.Hosting.Tests" -filter:"+[NLog.Extensions.Logging]* +[NLog.Extensions.Hosting]* -[NLog.Extensions.Logging.Tests]* -[NLog.Extensions.Hosting.Tests]*" -output:"coverage.xml" -oldstyle -targetdir:"test"
- OpenCover\tools\OpenCover.Console.exe -register:user -mergeoutput -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -f netcoreapp2.0 NLog.Extensions.Configuration.Tests" -filter:"+[NLog.Extensions.Logging]* +[NLog.Extensions.Hosting]* +[NLog.Extensions.Configuration]* -[NLog.Extensions.Logging.Tests]* -[NLog.Extensions.Hosting.Tests]* -[NLog.Extensions.Configuration.Tests]*" -output:"coverage.xml" -oldstyle -targetdir:"test"
- pip install codecov
- codecov -f "coverage.xml"
- ps: .\run-sonar.ps1
Expand Down
9 changes: 9 additions & 0 deletions build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ dotnet restore .\src\NLog.Extensions.Hosting\
if (-Not $LastExitCode -eq 0)
{ exit $LastExitCode }

dotnet restore .\src\NLog.Extensions.Configuration\
if (-Not $LastExitCode -eq 0)
{ exit $LastExitCode }

msbuild /t:Pack .\src\NLog.Extensions.Logging\ /p:targetFrameworks='"net451;net461;netstandard1.3;netstandard1.5;netstandard2.0"' /p:VersionPrefix=$versionPrefix /p:VersionSuffix=$versionSuffix /p:FileVersion=$versionFile /p:ProductVersion=$versionProduct /p:Configuration=Release /p:IncludeSymbols=true /p:PackageOutputPath=..\..\artifacts /verbosity:minimal
if (-Not $LastExitCode -eq 0)
{ exit $LastExitCode }
Expand All @@ -25,4 +29,9 @@ msbuild /t:Pack .\src\NLog.Extensions.Hosting\ /p:targetFrameworks='"netstandard
if (-Not $LastExitCode -eq 0)
{ exit $LastExitCode }

msbuild /t:Pack .\src\NLog.Extensions.Configuration\ /p:targetFrameworks='"net451;net461;netstandard1.3;netstandard1.5;netstandard2.0"' /p:VersionPrefix=$versionPrefix /p:VersionSuffix=$versionSuffix /p:FileVersion=$versionFile /p:ProductVersion=$versionProduct /p:Configuration=Release /p:IncludeSymbols=true /p:PackageOutputPath=..\..\artifacts /verbosity:minimal
if (-Not $LastExitCode -eq 0)
{ exit $LastExitCode }


exit $LastExitCode
184 changes: 184 additions & 0 deletions src/NLog.Extensions.Configuration/ConfigSettingLayoutRenderer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Configuration;
using NLog.Config;
using NLog.Layouts;
using NLog.LayoutRenderers;
using System.Text;

namespace NLog.Extensions.Configuration
{
/// <summary>
/// Layout renderer that can lookup values from Microsoft Extension Configuration Container (json, xml, ini)
/// </summary>
/// <remarks>Not to be confused with NLog.AppConfig that includes ${appsetting}</remarks>
/// <example>
/// Example: appsettings.json
/// {
/// "Mode":"Prod",
/// "Options":{
/// "StorageConnectionString":"UseDevelopmentStorage=true",
/// }
/// }
///
/// Config Setting Lookup:
/// ${configsetting:name=Mode} = "Prod"
/// ${configsetting:name=Options.StorageConnectionString} = "UseDevelopmentStorage=true"
/// ${configsetting:name=Options.TableName:default=MyTable} = "MyTable"
///
/// Config Setting Lookup Cached:
/// ${configsetting:cached=True:name=Mode}
/// </example>
[LayoutRenderer("configsetting")]
public class ConfigSettingLayoutRenderer : LayoutRenderer
{
internal IConfigurationRoot _configurationRoot;

private static readonly Dictionary<string, WeakReference<IConfigurationRoot>> _cachedConfigFiles = new Dictionary<string, WeakReference<IConfigurationRoot>>();

/// <summary>
/// Global Configuration Container. Used if <see cref="FileName" /> has default value
/// </summary>
public static IConfiguration DefaultConfiguration { get; set; }

///<summary>
/// Name of the setting
///</summary>
[RequiredParameter]
[DefaultParameter]
public string Name { get => _name; set => _name = value?.Replace(".", ":"); }
private string _name;

///<summary>
/// The default value to render if the setting value is null.
///</summary>
public string Default { get; set; }

/// <summary>
/// Configuration FileName (Multiple filenames can be split using '|' pipe-character)
/// </summary>
/// <remarks>Relative paths are automatically prefixed with ${basedir}</remarks>
public Layout FileName { get; set; } = DefaultFileName;
private const string DefaultFileName = "appsettings.json|appsettings.${environment:variable=ASPNETCORE_ENVIRONMENT}.json";

/// <inheritdoc/>
protected override void InitializeLayoutRenderer()
{
_configurationRoot = null;
base.InitializeLayoutRenderer();
}

/// <inheritdoc/>
protected override void CloseLayoutRenderer()
{
_configurationRoot = null;
base.CloseLayoutRenderer();
}

/// <inheritdoc/>
protected override void Append(StringBuilder builder, LogEventInfo logEvent)
{
if (string.IsNullOrEmpty(_name))
return;

string value = null;
var configurationRoot = TryGetConfigurationRoot();
if (configurationRoot != null)
{
value = configurationRoot[_name];
}

builder.Append(value ?? Default);
}

private IConfiguration TryGetConfigurationRoot()
{
if (DefaultConfiguration != null)
{
var simpleLayout = FileName as SimpleLayout;
if (simpleLayout == null || string.IsNullOrEmpty(simpleLayout.Text) || ReferenceEquals(simpleLayout.Text, DefaultFileName))
{
if (_configurationRoot != null)
_configurationRoot = null;
return DefaultConfiguration;
}
}

if (_configurationRoot != null)
return _configurationRoot;

var fileNames = FileName?.Render(LogEventInfo.CreateNullEvent());
if (!string.IsNullOrEmpty(fileNames))
{
return _configurationRoot = LoadFileConfiguration(fileNames);
}

return null;
}

private IConfigurationRoot LoadFileConfiguration(string fileNames)
{
lock (_cachedConfigFiles)
{
if (_cachedConfigFiles.TryGetValue(fileNames, out var wearkConfigRoot) && wearkConfigRoot.TryGetTarget(out var configRoot))
{
return configRoot;
}
else
{
configRoot = BuildConfigurationRoot(fileNames);
_cachedConfigFiles[fileNames] = new WeakReference<IConfigurationRoot>(configRoot);
return configRoot;
}
}
}

private static IConfigurationRoot BuildConfigurationRoot(string fileNames)
{
var configBuilder = new ConfigurationBuilder();
string baseDir = null;
foreach (var fileName in fileNames.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries))
{
var fullPath = fileName;
if (!System.IO.Path.IsPathRooted(fullPath))
{
if (baseDir == null)
baseDir = new BaseDirLayoutRenderer().Render(LogEventInfo.CreateNullEvent()) ?? string.Empty;
fullPath = System.IO.Path.Combine(baseDir, fileName);
}

AddFileConfiguration(configBuilder, fullPath);
}

return configBuilder.Build();
}

private static void AddFileConfiguration(ConfigurationBuilder configBuilder, string fullPath)
{
if (System.IO.File.Exists(fullPath))
{
// NOTE! Decided not to monitor for changes, as it would require access to dipose this monitoring again
if (string.Equals(System.IO.Path.GetExtension(fullPath), ".json", StringComparison.OrdinalIgnoreCase))
{
configBuilder.AddJsonFile(fullPath);
}
else if (string.Equals(System.IO.Path.GetExtension(fullPath), ".xml", StringComparison.OrdinalIgnoreCase))
{
configBuilder.AddXmlFile(fullPath);
}
else if (string.Equals(System.IO.Path.GetExtension(fullPath), ".ini", StringComparison.OrdinalIgnoreCase))
{
configBuilder.AddIniFile(fullPath);
}
else
{
Common.InternalLogger.Info("configSetting - Skipping FileName with unknown file-extension: {0}", fullPath);
}
}
else
{
Common.InternalLogger.Info("configSetting - Skipping FileName as file doesnt't exists: {0}", fullPath);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net451;net461;netstandard1.3;netstandard1.5;netstandard2.0</TargetFrameworks>
<DebugType>full</DebugType>
<DebugSymbols>true</DebugSymbols>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<GenerateDocumentationFile>true</GenerateDocumentationFile>

<Product>NLog.Extensions.Configuration v$(ProductVersion)</Product>
<InformationalVersion>$(ProductVersion)</InformationalVersion>

<Company>NLog</Company>
<Authors>Julian Verdurmen;CoCo Lin</Authors>
<Description>NLog extensions for Microsoft.Extensions.Configuration</Description>
<PackageProjectUrl>https://github.com/NLog/NLog.Extensions.Logging</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/NLog/NLog.Extensions.Logging/blob/master/LICENSE</PackageLicenseUrl>
<PackageIconUrl>https://nlog-project.org/NConfig.png</PackageIconUrl>
<RepositoryUrl>https://github.com/NLog/NLog.Extensions.Logging.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>NLog;Microsoft.Extensions.Configuration;log;logfiles;netcore</PackageTags>
<PackageReleaseNotes>1.0: Initial release</PackageReleaseNotes>

<!-- SonarQube needs this -->
<ProjectGuid>{0A5EC30A-2DC6-4EB3-BF1E-2E82BA83220F}</ProjectGuid>
<SignAssembly>true</SignAssembly>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<AssemblyOriginatorKeyFile>..\NLog.snk</AssemblyOriginatorKeyFile>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
</PropertyGroup>

<PropertyGroup Condition=" '$(TargetFramework)' == 'net461' ">
<Title>NLog.Extensions.Configuration for .NET Framework 4.6.1</Title>
<DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'net451' ">
<Title>NLog.Extensions.Configuration for .NET Framework 4.5.1</Title>
<DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<Title>NLog.Extensions.Configuration for NetStandard 1.3</Title>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.5' ">
<Title>NLog.Extensions.Configuration for NetStandard 1.5</Title>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<Title>NLog.Extensions.v for NetStandard 2.0</Title>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="NLog" Version="4.5.9" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net451' ">
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="1.1.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Xml" Version="1.1.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.0" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Xml" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="1.1.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Xml" Version="1.1.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.5' ">
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="1.1.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Xml" Version="1.1.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Xml" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0" />
</ItemGroup>
</Project>
6 changes: 6 additions & 0 deletions src/NLog.Extensions.Configuration/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

[assembly: ComVisible(false)]

[assembly: InternalsVisibleTo("NLog.Extensions.Configuration.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100772391E63C104728ADCF18E2390474262559FA7F34A4215848F43288CDE875DCC92A06222E9BE0592B211FF74ADBB5D21A7AAB5522B540B1735F2F03279221056FEDBE7E534073DABEE9DB48F8ECEBCF1DC98A95576E45CBEFF5FE7C4842859451AB2DAE7A8370F1B2F7A529D2CA210E3E844D973523D73D193DF6C17F1314A6")]
Loading

0 comments on commit ca1fdb1

Please sign in to comment.