Skip to content

Commit

Permalink
Merge pull request #171 from serilog/dev
Browse files Browse the repository at this point in the history
3.1.0 Release
  • Loading branch information
nblumhardt authored Jun 2, 2019
2 parents 008a61e + 2fc93f5 commit fc0969f
Show file tree
Hide file tree
Showing 28 changed files with 812 additions and 297 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Serilog.Settings.Configuration [![Build status](https://ci.appveyor.com/api/projects/status/r2bgfimd9ocr61px/branch/master?svg=true)](https://ci.appveyor.com/project/serilog/serilog-settings-configuration/branch/master)
# Serilog.Settings.Configuration [![Build status](https://ci.appveyor.com/api/projects/status/r2bgfimd9ocr61px/branch/master?svg=true)](https://ci.appveyor.com/project/serilog/serilog-settings-configuration/branch/master) [![NuGet Version](http://img.shields.io/nuget/v/Serilog.Settings.Configuration.svg?style=flat)](https://www.nuget.org/packages/Serilog.Settings.Configuration/)

A Serilog settings provider that reads from _Microsoft.Extensions.Configuration_, .NET Core's `appsettings.json` file.

Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ artifacts:
deploy:
- provider: NuGet
api_key:
secure: bd9z4P73oltOXudAjPehwp9iDKsPtC+HbgshOrSgoyQKr5xVK+bxJQngrDJkHdY8
secure: N59tiJECUYpip6tEn0xvdmDAEiP9SIzyLEFLpwiigm/8WhJvBNs13QxzT1/3/JW/
skip_symbols: true
on:
branch: /^(master|dev)$/
Expand Down
9 changes: 6 additions & 3 deletions sample/Sample/appsettings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"Serilog": {
"Using": ["Serilog.Sinks.Console"],
"Using": [ "Serilog.Sinks.Console" ],
"LevelSwitches": { "$controlSwitch": "Verbose" },
"MinimumLevel": {
"Default": "Debug",
"Override": {
Expand All @@ -12,6 +13,7 @@
"Name": "Logger",
"Args": {
"configureLogger": {
"MinimumLevel": "Verbose",
"WriteTo": [
{
"Name": "Console",
Expand All @@ -22,7 +24,8 @@
}
]
},
"restrictedToMinimumLevel": "Debug"
"restrictedToMinimumLevel": "Verbose",
"levelSwitch": "$controlSwitch"
}
},
"WriteTo:Async": {
Expand All @@ -39,7 +42,7 @@
]
}
},
"Enrich": ["FromLogContext", "WithMachineName", "WithThreadId"],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
"Properties": {
"Application": "Sample"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
using Microsoft.Extensions.DependencyModel;
using Serilog.Configuration;
using Serilog.Settings.Configuration;
using System.Reflection;
using Serilog.Settings.Configuration.Assemblies;

namespace Serilog
{
Expand All @@ -32,28 +32,53 @@ public static class ConfigurationLoggerConfigurationExtensions
public const string DefaultSectionName = "Serilog";

/// <summary>
/// Reads logger settings from the provided configuration object using the default section name. Generally this
/// Reads logger settings from the provided configuration object using the provided section name. Generally this
/// is preferable over the other method that takes a configuration section. Only this version will populate
/// IConfiguration parameters on target methods.
/// </summary>
/// <param name="settingConfiguration">Logger setting configuration.</param>
/// <param name="configuration">A configuration object which contains a Serilog section.</param>
/// <param name="sectionName">A section name for section which contains a Serilog section.</param>
/// <param name="dependencyContext">The dependency context from which sink/enricher packages can be located. If not supplied, the platform
/// default will be used.</param>
/// <returns>An object allowing configuration to continue.</returns>
public static LoggerConfiguration Configuration(
this LoggerSettingsConfiguration settingConfiguration,
IConfiguration configuration,
string sectionName,
DependencyContext dependencyContext = null)
{
if (settingConfiguration == null) throw new ArgumentNullException(nameof(settingConfiguration));
if (configuration == null) throw new ArgumentNullException(nameof(configuration));
if (sectionName == null) throw new ArgumentNullException(nameof(sectionName));

var assemblyFinder = dependencyContext == null
? AssemblyFinder.Auto()
: AssemblyFinder.ForDependencyContext(dependencyContext);

return settingConfiguration.Settings(
new ConfigurationReader(
configuration,
dependencyContext ?? (Assembly.GetEntryAssembly() != null ? DependencyContext.Default : null)));
configuration.GetSection(sectionName),
assemblyFinder,
configuration));
}

/// <summary>
/// Reads logger settings from the provided configuration object using the default section name. Generally this
/// is preferable over the other method that takes a configuration section. Only this version will populate
/// IConfiguration parameters on target methods.
/// </summary>
/// <param name="settingConfiguration">Logger setting configuration.</param>
/// <param name="configuration">A configuration object which contains a Serilog section.</param>
/// <param name="dependencyContext">The dependency context from which sink/enricher packages can be located. If not supplied, the platform
/// default will be used.</param>
/// <returns>An object allowing configuration to continue.</returns>
public static LoggerConfiguration Configuration(
this LoggerSettingsConfiguration settingConfiguration,
IConfiguration configuration,
DependencyContext dependencyContext = null)
=> Configuration(settingConfiguration, configuration, DefaultSectionName, dependencyContext);

/// <summary>
/// Reads logger settings from the provided configuration section. Generally it is preferable to use the other
/// extension method that takes the full configuration object.
Expand All @@ -63,6 +88,7 @@ public static LoggerConfiguration Configuration(
/// <param name="dependencyContext">The dependency context from which sink/enricher packages can be located. If not supplied, the platform
/// default will be used.</param>
/// <returns>An object allowing configuration to continue.</returns>
[Obsolete("Use ReadFrom.Configuration(IConfiguration configuration, string sectionName, DependencyContext dependencyContext) instead.")]
public static LoggerConfiguration ConfigurationSection(
this LoggerSettingsConfiguration settingConfiguration,
IConfigurationSection configSection,
Expand All @@ -71,38 +97,57 @@ public static LoggerConfiguration ConfigurationSection(
if (settingConfiguration == null) throw new ArgumentNullException(nameof(settingConfiguration));
if (configSection == null) throw new ArgumentNullException(nameof(configSection));

var assemblyFinder = dependencyContext == null
? AssemblyFinder.Auto()
: AssemblyFinder.ForDependencyContext(dependencyContext);

return settingConfiguration.Settings(
new ConfigurationReader(
configSection,
dependencyContext ?? (Assembly.GetEntryAssembly() != null ? DependencyContext.Default : null)));
assemblyFinder,
configuration: null));
}

/// <summary>
/// Reads logger settings from the provided configuration object using the default section name. Generally this
/// Reads logger settings from the provided configuration object using the provided section name. Generally this
/// is preferable over the other method that takes a configuration section. Only this version will populate
/// IConfiguration parameters on target methods.
/// </summary>
/// <param name="settingConfiguration">Logger setting configuration.</param>
/// <param name="configuration">A configuration object which contains a Serilog section.</param>
/// <param name="sectionName">A section name for section which contains a Serilog section.</param>
/// <param name="configurationAssemblySource">Defines how the package identifies assemblies to scan for sinks and other Types.</param>
/// <returns>An object allowing configuration to continue.</returns>
public static LoggerConfiguration Configuration(
this LoggerSettingsConfiguration settingConfiguration,
IConfiguration configuration,
string sectionName,
ConfigurationAssemblySource configurationAssemblySource)
{
if (settingConfiguration == null) throw new ArgumentNullException(nameof(settingConfiguration));
if (configuration == null) throw new ArgumentNullException(nameof(configuration));
if (sectionName == null) throw new ArgumentNullException(nameof(sectionName));

var assemblyFinder = AssemblyFinder.ForSource(configurationAssemblySource);

if(configurationAssemblySource == ConfigurationAssemblySource.UseLoadedAssemblies)
{
return Configuration(settingConfiguration, configuration);
}
else
{
return settingConfiguration.Settings(new ConfigurationReader(configuration, null));
}
return settingConfiguration.Settings(new ConfigurationReader(configuration.GetSection(sectionName), assemblyFinder, configuration));
}

/// <summary>
/// Reads logger settings from the provided configuration object using the default section name. Generally this
/// is preferable over the other method that takes a configuration section. Only this version will populate
/// IConfiguration parameters on target methods.
/// </summary>
/// <param name="settingConfiguration">Logger setting configuration.</param>
/// <param name="configuration">A configuration object which contains a Serilog section.</param>
/// <param name="configurationAssemblySource">Defines how the package identifies assemblies to scan for sinks and other Types.</param>
/// <returns>An object allowing configuration to continue.</returns>
public static LoggerConfiguration Configuration(
this LoggerSettingsConfiguration settingConfiguration,
IConfiguration configuration,
ConfigurationAssemblySource configurationAssemblySource)
=> Configuration(settingConfiguration, configuration, DefaultSectionName, configurationAssemblySource);

/// <summary>
/// Reads logger settings from the provided configuration section. Generally it is preferable to use the other
/// extension method that takes the full configuration object.
Expand All @@ -111,6 +156,7 @@ public static LoggerConfiguration Configuration(
/// <param name="configSection">The Serilog configuration section</param>
/// <param name="configurationAssemblySource">Defines how the package identifies assemblies to scan for sinks and other Types.</param>
/// <returns>An object allowing configuration to continue.</returns>
[Obsolete("Use ReadFrom.Configuration(IConfiguration configuration, string sectionName, ConfigurationAssemblySource configurationAssemblySource) instead.")]
public static LoggerConfiguration ConfigurationSection(
this LoggerSettingsConfiguration settingConfiguration,
IConfigurationSection configSection,
Expand All @@ -119,14 +165,9 @@ public static LoggerConfiguration ConfigurationSection(
if (settingConfiguration == null) throw new ArgumentNullException(nameof(settingConfiguration));
if (configSection == null) throw new ArgumentNullException(nameof(configSection));

if (configurationAssemblySource == ConfigurationAssemblySource.UseLoadedAssemblies)
{
return Configuration(settingConfiguration, configSection);
}
else
{
return settingConfiguration.Settings(new ConfigurationReader(configSection, null));
}
var assemblyFinder = AssemblyFinder.ForSource(configurationAssemblySource);

return settingConfiguration.Settings(new ConfigurationReader(configSection, assemblyFinder, configuration: null));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<Description>Microsoft.Extensions.Configuration (appsettings.json) support for Serilog.</Description>
<VersionPrefix>3.0.1</VersionPrefix>
<VersionPrefix>3.1.0</VersionPrefix>
<Authors>Serilog Contributors</Authors>
<TargetFrameworks>netstandard2.0;net451;net461</TargetFrameworks>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
Expand All @@ -15,12 +15,16 @@
<PackageTags>serilog;json</PackageTags>
<PackageIconUrl>https://serilog.net/images/serilog-configuration-nuget.png</PackageIconUrl>
<PackageProjectUrl>https://github.com/serilog/serilog-settings-configuration</PackageProjectUrl>
<PackageLicenseUrl>https://www.apache.org/licenses/LICENSE-2.0</PackageLicenseUrl>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<RepositoryUrl>https://github.com/serilog/serilog-settings-configuration</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<RootNamespace>Serilog</RootNamespace>
</PropertyGroup>

<PropertyGroup Condition="('$(TargetFramework)' == 'net451') Or ('$(TargetFramework)' == 'net461')">
<DefineConstants>$(DefineConstants);PRIVATE_BIN</DefineConstants>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="2.0.4" />
<PackageReference Include="Serilog" Version="2.6.0" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.Extensions.DependencyModel;

namespace Serilog.Settings.Configuration.Assemblies
{
abstract class AssemblyFinder
{
public abstract IReadOnlyList<AssemblyName> FindAssembliesContainingName(string nameToFind);

protected static bool IsCaseInsensitiveMatch(string text, string textToFind)
{
return text != null && text.ToLowerInvariant().Contains(textToFind.ToLowerInvariant());
}

public static AssemblyFinder Auto()
{
// Need to check `Assembly.GetEntryAssembly()` first because
// `DependencyContext.Default` throws an exception when `Assembly.GetEntryAssembly()` returns null
if (Assembly.GetEntryAssembly() != null && DependencyContext.Default != null)
{
return new DependencyContextAssemblyFinder(DependencyContext.Default);
}
return new DllScanningAssemblyFinder();
}

public static AssemblyFinder ForSource(ConfigurationAssemblySource configurationAssemblySource)
{
switch (configurationAssemblySource)
{
case ConfigurationAssemblySource.UseLoadedAssemblies:
return Auto();
case ConfigurationAssemblySource.AlwaysScanDllFiles:
return new DllScanningAssemblyFinder();
default:
throw new ArgumentOutOfRangeException(nameof(configurationAssemblySource), configurationAssemblySource, null);
}
}

public static AssemblyFinder ForDependencyContext(DependencyContext dependencyContext)
{
return new DependencyContextAssemblyFinder(dependencyContext);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.Extensions.DependencyModel;

namespace Serilog.Settings.Configuration.Assemblies
{
sealed class DependencyContextAssemblyFinder : AssemblyFinder
{
readonly DependencyContext _dependencyContext;

public DependencyContextAssemblyFinder(DependencyContext dependencyContext)
{
_dependencyContext = dependencyContext ?? throw new ArgumentNullException(nameof(dependencyContext));
}

public override IReadOnlyList<AssemblyName> FindAssembliesContainingName(string nameToFind)
{
var query = from library in _dependencyContext.RuntimeLibraries
from assemblyName in library.GetDefaultAssemblyNames(_dependencyContext)
where IsCaseInsensitiveMatch(assemblyName.Name, nameToFind)
select assemblyName;

return query.ToList().AsReadOnly();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;

namespace Serilog.Settings.Configuration.Assemblies
{
sealed class DllScanningAssemblyFinder : AssemblyFinder
{
public override IReadOnlyList<AssemblyName> FindAssembliesContainingName(string nameToFind)
{
var probeDirs = new List<string>();

if (!string.IsNullOrEmpty(AppDomain.CurrentDomain.BaseDirectory))
{
probeDirs.Add(AppDomain.CurrentDomain.BaseDirectory);

#if PRIVATE_BIN
var privateBinPath = AppDomain.CurrentDomain.SetupInformation.PrivateBinPath;
if (!string.IsNullOrEmpty(privateBinPath))
{
foreach (var path in privateBinPath.Split(';'))
{
if (Path.IsPathRooted(path))
{
probeDirs.Add(path);
}
else
{
probeDirs.Add(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, path));
}
}
}
#endif
}
else
{
probeDirs.Add(Path.GetDirectoryName(typeof(AssemblyFinder).Assembly.Location));
}

var query = from probeDir in probeDirs
where Directory.Exists(probeDir)
from outputAssemblyPath in Directory.GetFiles(probeDir, "*.dll")
let assemblyFileName = Path.GetFileNameWithoutExtension(outputAssemblyPath)
where IsCaseInsensitiveMatch(assemblyFileName, nameToFind)
let assemblyName = TryGetAssemblyNameFrom(outputAssemblyPath)
where assemblyName != null
select assemblyName;

return query.ToList().AsReadOnly();

AssemblyName TryGetAssemblyNameFrom(string path)
{
try
{
return AssemblyName.GetAssemblyName(path);
}
catch (BadImageFormatException)
{
return null;
}
}
}
}
}
Loading

0 comments on commit fc0969f

Please sign in to comment.