Skip to content

Commit cdbc7c3

Browse files
authored
Merge branch 'dev' into fix-issue/131
2 parents 268b719 + d6118bf commit cdbc7c3

21 files changed

+965
-183
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,3 +199,6 @@ FakesAssemblies/
199199
*.opt
200200

201201
project.lock.json
202+
203+
#Test files
204+
*.txt

.travis.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
language: csharp
2+
3+
matrix:
4+
include:
5+
- os: linux
6+
dist: trusty
7+
sudo: required
8+
dotnet: 2.1.4
9+
group: edge
10+
script:
11+
- ./build.sh

README.md

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,27 @@ Configuration is read from the `Serilog` section.
77
```json
88
{
99
"Serilog": {
10-
"Using": ["Serilog.Sinks.Literate"],
10+
"Using": ["Serilog.Sinks.Console"],
1111
"MinimumLevel": "Debug",
1212
"WriteTo": [
13-
{ "Name": "LiterateConsole" },
13+
{ "Name": "Console" },
1414
{ "Name": "File", "Args": { "path": "%TEMP%\\Logs\\serilog-configuration-sample.txt" } }
1515
],
1616
"Enrich": ["FromLogContext", "WithMachineName", "WithThreadId"],
17+
"Destructure": [
18+
{ "Name": "With", "Args": { "policy": "Sample.CustomPolicy, Sample" } },
19+
{ "Name": "ToMaximumDepth", "Args": { "maximumDestructuringDepth": 4 } },
20+
{ "Name": "ToMaximumStringLength", "Args": { "maximumStringLength": 100 } },
21+
{ "Name": "ToMaximumCollectionCount", "Args": { "maximumCollectionCount": 10 } }
22+
],
1723
"Properties": {
1824
"Application": "Sample"
1925
}
2026
}
2127
}
2228
```
2329

24-
This example relies on the _Serilog.Sinks.Literate_, _Serilog.Sinks.File_, _Serilog.Enrichers.Environment_, _Serilog.Settings.Configuration_ and _Serilog.Enrichers.Thread_ packages also being installed.
30+
This example relies on the _Serilog.Sinks.Console_, _Serilog.Sinks.File_, _Serilog.Enrichers.Environment_, _Serilog.Settings.Configuration_ and _Serilog.Enrichers.Thread_ packages also being installed.
2531

2632
After installing this package, use `ReadFrom.Configuration()` and pass an `IConfiguration` object.
2733

@@ -46,7 +52,7 @@ public class Program
4652
The `WriteTo` and `Enrich` sections support the same syntax, for example the following is valid if no arguments are needed by the sinks:
4753

4854
```json
49-
"WriteTo": ["LiterateConsole", "DiagnosticTrace"]
55+
"WriteTo": ["Console", "DiagnosticTrace"]
5056
```
5157

5258
Or alternatively, the long-form (`"Name":` ...) syntax from the first example can be used when arguments need to be supplied.
@@ -91,3 +97,39 @@ For example, to set the minimum log level using the _Windows_ command prompt:
9197
set Serilog:MinimumLevel=Debug
9298
dotnet run
9399
```
100+
101+
### Nested configuration sections
102+
103+
Some Serilog packages require a reference to a logger configuration object. The sample program in this project illustrates this with the following entry configuring the _Serilog.Sinks.Async_ package to wrap the _Serilog.Sinks.File_ package. The `configure` parameter references the File sink configuration:
104+
105+
```json
106+
"WriteTo:Async": {
107+
"Name": "Async",
108+
"Args": {
109+
"configure": [
110+
{
111+
"Name": "File",
112+
"Args": {
113+
"path": "%TEMP%\\Logs\\serilog-configuration-sample.txt",
114+
"outputTemplate": "{Timestamp:o} [{Level:u3}] ({Application}/{MachineName}/{ThreadId}) {Message}{NewLine}{Exception}"
115+
}
116+
}
117+
]
118+
}
119+
},
120+
```
121+
122+
### IConfiguration parameter
123+
124+
If a Serilog package requires additional external configuration information (for example, access to a `ConnectionStrings` section, which would be outside of the `Serilog` section), the sink should include an `IConfiguration` parameter in the configuration extension method. This package will automatically populate that parameter. It should not be declared in the argument list in the configuration source.
125+
126+
### Complex parameter value binding
127+
128+
When the configuration specifies a discrete value for a parameter (such as a string literal), the package will attempt to convert that value to the target method's declared CLR type of the parameter. Additional explicit handling is provided for parsing strings to `Uri` and `TimeSpan` objects and `enum` elements.
129+
130+
If the parameter value is not a discrete value, the package will use the configuration binding system provided by _Microsoft.Extensions.Options.ConfigurationExtensions_ to attempt to populate the parameter. Almost anything that can be bound by `IConfiguration.Get<T>` should work with this package. An example of this is the optional `List<Column>` parameter used to configure the .NET Standard version of the _Serilog.Sinks.MSSqlServer_ package.
131+
132+
### IConfigurationSection parameters
133+
134+
Certain Serilog packages may require configuration information that can't be easily represented by discrete values or direct binding-friendly representations. An example might be lists of values to remove from a collection of default values. In this case the method can accept an entire `IConfigurationSection` as a call parameter and this package will recognize that and populate the parameter. In this way, Serilog packages can support arbitrarily complex configuration scenarios.
135+

appveyor.yml

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,6 @@ version: '{build}'
22
skip_tags: true
33
image: Visual Studio 2017
44
configuration: Release
5-
install:
6-
- ps: mkdir -Force ".\build\" | Out-Null
7-
- ps: Invoke-WebRequest "https://raw.githubusercontent.com/dotnet/cli/rel/1.0.0/scripts/obtain/dotnet-install.ps1" -OutFile ".\build\installcli.ps1"
8-
- ps: $env:DOTNET_INSTALL_DIR = "$pwd\.dotnetcli"
9-
- ps: '& .\build\installcli.ps1 -InstallDir "$env:DOTNET_INSTALL_DIR" -NoPath -Version 1.0.1'
10-
- ps: $env:Path = "$env:DOTNET_INSTALL_DIR;$env:Path"
115
build_script:
126
- ps: ./Build.ps1
137
test: off
@@ -16,7 +10,7 @@ artifacts:
1610
deploy:
1711
- provider: NuGet
1812
api_key:
19-
secure: nvZ/z+pMS91b3kG4DgfES5AcmwwGoBYQxr9kp4XiJHj25SAlgdIxFx++1N0lFH2x
13+
secure: bd9z4P73oltOXudAjPehwp9iDKsPtC+HbgshOrSgoyQKr5xVK+bxJQngrDJkHdY8
2014
skip_symbols: true
2115
on:
2216
branch: /^(master|dev)$/
@@ -26,4 +20,4 @@ deploy:
2620
artifact: /Serilog.*\.nupkg/
2721
tag: v$(appveyor_build_version)
2822
on:
29-
branch: master
23+
branch: master

build.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/bin/bash
2+
3+
set -e
4+
dotnet --info
5+
dotnet restore
6+
7+
for path in src/**/*.csproj; do
8+
dotnet build -f netstandard2.0 -c Release ${path}
9+
done
10+
11+
for path in test/*.Tests/*.csproj; do
12+
dotnet test -f netcoreapp2.0 -c Release ${path}
13+
done
14+
15+
cd sample/Sample/
16+
dotnet build -f netcoreapp2.0 -c Release
17+
dotnet bin/Release/netcoreapp2.0/Sample.dll --run-once

sample/Sample/Program.cs

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
using Microsoft.Extensions.Configuration;
44
using Serilog;
55
using System.IO;
6-
6+
using System.Linq;
77
using Serilog.Core;
88
using Serilog.Events;
9+
using System.Collections.Generic;
910

1011
namespace Sample
1112
{
@@ -22,6 +23,8 @@ public static void Main(string[] args)
2223
.ReadFrom.Configuration(configuration)
2324
.CreateLogger();
2425

26+
logger.Information("Args: {a}", args);
27+
2528
do
2629
{
2730
logger.ForContext<Program>().Information("Hello, world!");
@@ -30,17 +33,56 @@ public static void Main(string[] args)
3033
logger.ForContext(Constants.SourceContextPropertyName, "Microsoft").Error("Hello, world!");
3134
logger.ForContext(Constants.SourceContextPropertyName, "MyApp.Something.Tricky").Verbose("Hello, world!");
3235

33-
Console.WriteLine();
36+
logger.Information("Destructure with max object nesting depth:\n{@NestedObject}",
37+
new { FiveDeep = new { Two = new { Three = new { Four = new { Five = "the end" } } } } });
38+
39+
logger.Information("Destructure with max string length:\n{@LongString}",
40+
new { TwentyChars = "0123456789abcdefghij" });
41+
42+
logger.Information("Destructure with max collection count:\n{@BigData}",
43+
new { TenItems = new[] { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" } });
44+
45+
logger.Information("Destructure with policy to strip password:\n{@LoginData}",
46+
new LoginData { Username = "BGates", Password = "isityearoflinuxyet" });
47+
48+
Console.WriteLine("\nPress \"q\" to quit, or any other key to run again.\n");
3449
}
35-
while (Console.ReadKey().KeyChar != 'q');
50+
while(!args.Contains("--run-once") && (Console.ReadKey().KeyChar != 'q'));
3651
}
3752
}
3853

54+
// The filter syntax in the sample configuration file is
55+
// processed by the Serilog.Filters.Expressions package.
3956
public class CustomFilter : ILogEventFilter
4057
{
4158
public bool IsEnabled(LogEvent logEvent)
4259
{
4360
return true;
4461
}
4562
}
63+
64+
public class LoginData
65+
{
66+
public string Username;
67+
public string Password;
68+
}
69+
70+
public class CustomPolicy : IDestructuringPolicy
71+
{
72+
public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory, out LogEventPropertyValue result)
73+
{
74+
result = null;
75+
76+
if(value is LoginData)
77+
{
78+
result = new StructureValue(
79+
new List<LogEventProperty>
80+
{
81+
new LogEventProperty("Username", new ScalarValue(((LoginData)value).Username))
82+
});
83+
}
84+
85+
return (result != null);
86+
}
87+
}
4688
}

sample/Sample/Sample.csproj

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>net46;netcoreapp1.0</TargetFrameworks>
4+
<TargetFrameworks>net46;netcoreapp2.0</TargetFrameworks>
55
<OutputType>Exe</OutputType>
66
</PropertyGroup>
77

@@ -13,8 +13,15 @@
1313
<ProjectReference Include="..\..\src\Serilog.Settings.Configuration\Serilog.Settings.Configuration.csproj" />
1414
</ItemGroup>
1515

16-
<ItemGroup>
16+
<ItemGroup Condition="'$(TargetFramework)' == 'net46'">
1717
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.1" />
18+
</ItemGroup>
19+
20+
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp2.0'">
21+
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.1" />
22+
</ItemGroup>
23+
24+
<ItemGroup>
1825
<PackageReference Include="Serilog.Sinks.Async" Version="1.0.1" />
1926
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
2027
<PackageReference Include="Serilog.Sinks.RollingFile" Version="3.0.0" />

sample/Sample/appsettings.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,24 @@
4343
"Properties": {
4444
"Application": "Sample"
4545
},
46+
"Destructure": [
47+
{
48+
"Name": "With",
49+
"Args": { "policy": "Sample.CustomPolicy, Sample" }
50+
},
51+
{
52+
"Name": "ToMaximumDepth",
53+
"Args": { "maximumDestructuringDepth": 3 }
54+
},
55+
{
56+
"Name": "ToMaximumStringLength",
57+
"Args": { "maximumStringLength": 10 }
58+
},
59+
{
60+
"Name": "ToMaximumCollectionCount",
61+
"Args": { "maximumCollectionCount": 5 }
62+
}
63+
],
4664
"Filter": [
4765
{
4866
"Name": "ByIncludingOnly",

src/Serilog.Settings.Configuration/ConfigurationLoggerConfigurationExtensions.cs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,18 @@ namespace Serilog
2626
/// </summary>
2727
public static class ConfigurationLoggerConfigurationExtensions
2828
{
29-
const string DefaultSectionName = "Serilog";
29+
/// <summary>
30+
/// Configuration section name required by this package.
31+
/// </summary>
32+
public const string DefaultSectionName = "Serilog";
3033

3134
/// <summary>
32-
/// Reads logger settings from the provided configuration object using the default section name.
35+
/// Reads logger settings from the provided configuration object using the default section name. Generally this
36+
/// is preferable over the other method that takes a configuration section. Only this version will populate
37+
/// IConfiguration parameters on target methods.
3338
/// </summary>
3439
/// <param name="settingConfiguration">Logger setting configuration.</param>
35-
/// <param name="configuration">A configuration object with a Serilog section.</param>
40+
/// <param name="configuration">A configuration object which contains a Serilog section.</param>
3641
/// <param name="dependencyContext">The dependency context from which sink/enricher packages can be located. If not supplied, the platform
3742
/// default will be used.</param>
3843
/// <returns>An object allowing configuration to continue.</returns>
@@ -42,28 +47,32 @@ public static LoggerConfiguration Configuration(
4247
DependencyContext dependencyContext = null)
4348
{
4449
if (configuration == null) throw new ArgumentNullException(nameof(configuration));
45-
return settingConfiguration.ConfigurationSection(configuration.GetSection(DefaultSectionName), dependencyContext);
50+
return settingConfiguration.Settings(
51+
new ConfigurationReader(
52+
configuration,
53+
dependencyContext ?? (Assembly.GetEntryAssembly() != null ? DependencyContext.Default : null)));
4654
}
4755

4856
/// <summary>
49-
/// Reads logger settings from the provided configuration section.
57+
/// Reads logger settings from the provided configuration section. Generally it is preferable to use the other
58+
/// extension method that takes the full configuration object.
5059
/// </summary>
5160
/// <param name="settingConfiguration">Logger setting configuration.</param>
52-
/// <param name="configuration">The Serilog configuration section</param>
61+
/// <param name="configSection">The Serilog configuration section</param>
5362
/// <param name="dependencyContext">The dependency context from which sink/enricher packages can be located. If not supplied, the platform
5463
/// default will be used.</param>
5564
/// <returns>An object allowing configuration to continue.</returns>
5665
public static LoggerConfiguration ConfigurationSection(
5766
this LoggerSettingsConfiguration settingConfiguration,
58-
IConfigurationSection configuration,
67+
IConfigurationSection configSection,
5968
DependencyContext dependencyContext = null)
6069
{
6170
if (settingConfiguration == null) throw new ArgumentNullException(nameof(settingConfiguration));
62-
if (configuration == null) throw new ArgumentNullException(nameof(configuration));
71+
if (configSection == null) throw new ArgumentNullException(nameof(configSection));
6372

6473
return settingConfiguration.Settings(
6574
new ConfigurationReader(
66-
configuration,
75+
configSection,
6776
dependencyContext ?? (Assembly.GetEntryAssembly() != null ? DependencyContext.Default : null)));
6877
}
6978
}

src/Serilog.Settings.Configuration/Serilog.Settings.Configuration.csproj

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
<PropertyGroup>
44
<Description>Microsoft.Extensions.Configuration (appsettings.json) support for Serilog.</Description>
5-
<VersionPrefix>2.6.1</VersionPrefix>
5+
<VersionPrefix>3.0.0</VersionPrefix>
66
<Authors>Serilog Contributors</Authors>
7-
<TargetFrameworks>net451;netstandard1.6</TargetFrameworks>
7+
<TargetFrameworks>netstandard2.0;net451;net461</TargetFrameworks>
88
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
99
<GenerateDocumentationFile>true</GenerateDocumentationFile>
1010
<AssemblyName>Serilog.Settings.Configuration</AssemblyName>
@@ -16,20 +16,24 @@
1616
<PackageIconUrl>https://serilog.net/images/serilog-configuration-nuget.png</PackageIconUrl>
1717
<PackageProjectUrl>https://github.com/serilog/serilog-settings-configuration</PackageProjectUrl>
1818
<PackageLicenseUrl>https://www.apache.org/licenses/LICENSE-2.0</PackageLicenseUrl>
19-
20-
<!-- Don't reference the full NETStandard.Library -->
21-
<DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
19+
<RepositoryUrl>https://github.com/serilog/serilog-settings-configuration</RepositoryUrl>
20+
<RepositoryType>git</RepositoryType>
2221
<RootNamespace>Serilog</RootNamespace>
2322
</PropertyGroup>
2423

2524
<ItemGroup>
26-
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="1.0.0" />
27-
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="1.0.0" />
25+
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="2.0.4" />
2826
<PackageReference Include="Serilog" Version="2.6.0" />
2927
</ItemGroup>
3028

31-
<PropertyGroup Condition=" '$(TargetFramework)' == 'net451' ">
32-
<DefineConstants>$(DefineConstants);APPDOMAIN</DefineConstants>
33-
</PropertyGroup>
29+
<ItemGroup Condition="'$(TargetFramework)' == 'net451'">
30+
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="1.1.2" />
31+
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.1.2" />
32+
</ItemGroup>
33+
34+
<ItemGroup Condition="('$(TargetFramework)' == 'netstandard2.0') Or ('$(TargetFramework)' == 'net461')">
35+
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="2.0.1" />
36+
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.0" />
37+
</ItemGroup>
3438

3539
</Project>

0 commit comments

Comments
 (0)