Skip to content

Commit d310c47

Browse files
authored
Merge pull request #18 from serilog/dev
2.1.0 Release
2 parents 5b9a17e + 34b372a commit d310c47

File tree

13 files changed

+251
-68
lines changed

13 files changed

+251
-68
lines changed

Diff for: Build.ps1

+28-6
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,51 @@
1+
echo "build: Build started"
2+
13
Push-Location $PSScriptRoot
24

3-
if(Test-Path .\artifacts) { Remove-Item .\artifacts -Force -Recurse }
5+
if(Test-Path .\artifacts) {
6+
echo "build: Cleaning .\artifacts"
7+
Remove-Item .\artifacts -Force -Recurse
8+
}
49

510
& dotnet restore --no-cache
611

712
$branch = @{ $true = $env:APPVEYOR_REPO_BRANCH; $false = $(git symbolic-ref --short -q HEAD) }[$env:APPVEYOR_REPO_BRANCH -ne $NULL];
813
$revision = @{ $true = "{0:00000}" -f [convert]::ToInt32("0" + $env:APPVEYOR_BUILD_NUMBER, 10); $false = "local" }[$env:APPVEYOR_BUILD_NUMBER -ne $NULL];
9-
$suffix = @{ $true = ""; $false = "$branch-$revision"}[$branch -eq "master" -and $revision -ne "local"]
14+
$suffix = @{ $true = ""; $false = "$($branch.Substring(0, [math]::Min(10,$branch.Length)))-$revision"}[$branch -eq "master" -and $revision -ne "local"]
1015

11-
foreach ($src in ls src/Serilog.*) {
16+
echo "build: Version suffix is $suffix"
17+
18+
foreach ($src in ls src/*) {
1219
Push-Location $src
1320

14-
& dotnet pack -c Release -o ..\..\.\artifacts --version-suffix=$suffix
21+
echo "build: Packaging project in $src"
22+
23+
& dotnet pack -c Release -o ..\..\artifacts --version-suffix=$suffix
1524
if($LASTEXITCODE -ne 0) { exit 1 }
1625

1726
Pop-Location
1827
}
1928

20-
foreach ($test in ls test/Serilog.*.Tests) {
29+
foreach ($test in ls test/*.PerformanceTests) {
2130
Push-Location $test
2231

23-
& dotnet test -c Release
32+
echo "build: Building performance test project in $test"
33+
34+
& dotnet build -c Release
2435
if($LASTEXITCODE -ne 0) { exit 2 }
2536

2637
Pop-Location
2738
}
2839

40+
foreach ($test in ls test/*.Tests) {
41+
Push-Location $test
42+
43+
echo "build: Testing project in $test"
44+
45+
& dotnet test -c Release
46+
if($LASTEXITCODE -ne 0) { exit 3 }
47+
48+
Pop-Location
49+
}
50+
2951
Pop-Location

Diff for: CHANGES.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2.1.0
2+
* #14 - MinimumLevel.Override()
3+
* #15 - Overload selection fix
4+
5+
2.0.0
6+
* Initial version
7+

Diff for: README.md

+28-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Configuration is read from the `Serilog` section.
2121
}
2222
```
2323

24-
This example relies on the _Serilog.Sinks.Literate_, _Serilog.Sinks.File_, _Serilog.Enrichers.Environment_ and _Serilog.Sinks.Thread_ packages also being installed.
24+
This example relies on the _Serilog.Sinks.Literate_, _Serilog.Sinks.File_, _Serilog.Enrichers.Environment_ and _Serilog.Enrichers.Thread_ packages also being installed.
2525

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

@@ -64,3 +64,30 @@ To use this package in .NET 4.x applications, add `preserveCompilationContext` t
6464
}
6565
},
6666
```
67+
68+
### Level overrides
69+
70+
The `MinimumLevel` configuration property can be set to a single value as in the sample above, or, levels can be overridden per logging source.
71+
72+
This is useful in ASP.NET Core applications, which will often specify minimum level as:
73+
74+
```json
75+
"MinimumLevel": {
76+
"Default": "Information",
77+
"Override": {
78+
"Microsoft": "Warning",
79+
"System": "Warning"
80+
}
81+
}
82+
```
83+
84+
### Environment variables
85+
86+
If your application enables the environment variable configuration source (`AddEnvironmentVariables()`) you can add or override Serilog configuration through the environment.
87+
88+
For example, to set the minimum log level using the _Windows_ command prompt:
89+
90+
```
91+
set Serilog:MinimumLevel=Debug
92+
dotnet run
93+
```

Diff for: sample/Sample/Program.cs

+7-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
using Serilog;
55
using System.IO;
66

7+
using Serilog.Core;
8+
79
namespace Sample
810
{
911
public class Program
@@ -21,7 +23,11 @@ public static void Main(string[] args)
2123

2224
do
2325
{
24-
logger.Information("Hello, world!");
26+
logger.ForContext<Program>().Information("Hello, world!");
27+
logger.ForContext(Constants.SourceContextPropertyName, "Microsoft").Warning("Hello, world!");
28+
logger.ForContext(Constants.SourceContextPropertyName, "MyApp.Something.Tricky").Verbose("Hello, world!");
29+
30+
Console.WriteLine();
2531
}
2632
while (Console.ReadKey().KeyChar != 'q');
2733
}

Diff for: sample/Sample/appsettings.json

+13-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
{
22
"Serilog": {
33
"Using": ["Serilog.Sinks.Literate"],
4-
"MinimumLevel": "Debug",
4+
"MinimumLevel": {
5+
"Default": "Debug",
6+
"Override": {
7+
"Microsoft": "Warning",
8+
"MyApp.Something.Tricky": "Verbose"
9+
}
10+
},
511
"WriteTo": [
6-
{ "Name": "LiterateConsole" },
12+
{
13+
"Name": "LiterateConsole",
14+
"Args": {
15+
"outputTemplate": "[{Timestamp:HH:mm:ss} {SourceContext} [{Level}] {Message}{NewLine}{Exception}"
16+
}
17+
},
718
{
819
"Name": "File",
920
"Args": {

Diff for: sample/Sample/project.lock.json

+3-5
Original file line numberDiff line numberDiff line change
@@ -2349,13 +2349,12 @@
23492349
"lib/netstandard1.3/_._": {}
23502350
}
23512351
},
2352-
"Serilog.Settings.Configuration/2.0.0-rc": {
2352+
"Serilog.Settings.Configuration/2.1.0": {
23532353
"type": "project",
23542354
"framework": ".NETStandard,Version=v1.6",
23552355
"dependencies": {
23562356
"Microsoft.Extensions.Configuration.Abstractions": "1.0.0",
23572357
"Microsoft.Extensions.DependencyModel": "1.0.0",
2358-
"Newtonsoft.Json": "9.0.1",
23592358
"Serilog": "2.0.0"
23602359
},
23612360
"compile": {
@@ -2673,13 +2672,12 @@
26732672
"lib/net45/_._": {}
26742673
}
26752674
},
2676-
"Serilog.Settings.Configuration/2.0.0-rc": {
2675+
"Serilog.Settings.Configuration/2.1.0": {
26772676
"type": "project",
26782677
"framework": ".NETFramework,Version=v4.5.1",
26792678
"dependencies": {
26802679
"Microsoft.Extensions.Configuration.Abstractions": "1.0.0",
26812680
"Microsoft.Extensions.DependencyModel": "1.0.0",
2682-
"Newtonsoft.Json": "9.0.1",
26832681
"Serilog": "2.0.0",
26842682
"System.Runtime": "4.0.10"
26852683
},
@@ -7561,7 +7559,7 @@
75617559
"ref/xamarinwatchos10/_._"
75627560
]
75637561
},
7564-
"Serilog.Settings.Configuration/2.0.0-rc": {
7562+
"Serilog.Settings.Configuration/2.1.0": {
75657563
"type": "project",
75667564
"path": "../../src/Serilog.Settings.Configuration/project.json",
75677565
"msbuildProject": "../../src/Serilog.Settings.Configuration/Serilog.Settings.Configuration.xproj"

Diff for: src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs

+42-22
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ Dictionary<string, Dictionary<string, string>> GetMethodCalls(IConfigurationSect
8080
else
8181
{
8282
var name = child.GetSection("Name");
83-
if (name == null)
84-
throw new InvalidOperationException("The configuration value in Serilog.WriteTo has no Name element.");
83+
if (name.Value == null)
84+
throw new InvalidOperationException($"The configuration value in {name.Path} has no Name element.");
8585

8686
var callArgs = new Dictionary<string, string>();
8787
var args = child.GetSection("Args");
@@ -100,25 +100,39 @@ Dictionary<string, Dictionary<string, string>> GetMethodCalls(IConfigurationSect
100100

101101
void ApplyMinimumLevel(LoggerConfiguration loggerConfiguration)
102102
{
103+
var applyMinimumLevelAction =
104+
new Action<IConfigurationSection, Action<LoggerMinimumLevelConfiguration, LoggingLevelSwitch>>(
105+
(directive, applyConfigAction) =>
106+
{
107+
LogEventLevel minimumLevel;
108+
if (!Enum.TryParse(directive.Value, out minimumLevel))
109+
throw new InvalidOperationException($"The value {directive.Value} is not a valid Serilog level.");
110+
111+
var levelSwitch = new LoggingLevelSwitch(minimumLevel);
112+
applyConfigAction(loggerConfiguration.MinimumLevel, levelSwitch);
113+
114+
ChangeToken.OnChange(
115+
directive.GetReloadToken,
116+
() =>
117+
{
118+
if (Enum.TryParse(directive.Value, out minimumLevel))
119+
levelSwitch.MinimumLevel = minimumLevel;
120+
else
121+
SelfLog.WriteLine($"The value {directive.Value} is not a valid Serilog level.");
122+
});
123+
});
124+
103125
var minimumLevelDirective = _configuration.GetSection("MinimumLevel");
104-
if (minimumLevelDirective?.Value != null)
105-
{
106-
LogEventLevel minimumLevel;
107-
if (!Enum.TryParse(minimumLevelDirective.Value, out minimumLevel))
108-
throw new InvalidOperationException($"The value {minimumLevelDirective.Value} is not a valid Serilog level.");
109126

110-
var levelSwitch = new LoggingLevelSwitch(minimumLevel);
111-
loggerConfiguration.MinimumLevel.ControlledBy(levelSwitch);
127+
var defaultMinLevelDirective = minimumLevelDirective.Value != null ? minimumLevelDirective : minimumLevelDirective.GetSection("Default");
128+
if (defaultMinLevelDirective.Value != null)
129+
{
130+
applyMinimumLevelAction(defaultMinLevelDirective, (configuration, levelSwitch) => configuration.ControlledBy(levelSwitch));
131+
}
112132

113-
ChangeToken.OnChange(
114-
() => minimumLevelDirective.GetReloadToken(),
115-
() =>
116-
{
117-
if (Enum.TryParse(minimumLevelDirective.Value, out minimumLevel))
118-
levelSwitch.MinimumLevel = minimumLevel;
119-
else
120-
SelfLog.WriteLine($"The value {minimumLevelDirective.Value} is not a valid Serilog level.");
121-
});
133+
foreach (var overrideDirective in minimumLevelDirective.GetSection("Override").GetChildren())
134+
{
135+
applyMinimumLevelAction(overrideDirective, (configuration, levelSwitch) => configuration.Override(overrideDirective.Key, levelSwitch));
122136
}
123137
}
124138

@@ -165,10 +179,7 @@ static void CallConfigurationMethods(Dictionary<string, Dictionary<string, strin
165179
{
166180
foreach (var method in methods)
167181
{
168-
var methodInfo = configurationMethods
169-
.Where(m => m.Name == method.Key && m.GetParameters().Skip(1).All(p => p.HasDefaultValue || method.Value.Any(s => s.Key == p.Name)))
170-
.OrderByDescending(m => m.GetParameters().Length)
171-
.FirstOrDefault();
182+
var methodInfo = SelectConfigurationMethod(configurationMethods, method.Key, method.Value);
172183

173184
if (methodInfo != null)
174185
{
@@ -183,6 +194,15 @@ static void CallConfigurationMethods(Dictionary<string, Dictionary<string, strin
183194
}
184195
}
185196

197+
internal static MethodInfo SelectConfigurationMethod(IEnumerable<MethodInfo> candidateMethods, string name, Dictionary<string, string> suppliedArgumentValues)
198+
{
199+
return candidateMethods
200+
.Where(m => m.Name == name &&
201+
m.GetParameters().Skip(1).All(p => p.HasDefaultValue || suppliedArgumentValues.Any(s => s.Key == p.Name)))
202+
.OrderByDescending(m => m.GetParameters().Count(p => suppliedArgumentValues.Any(s => s.Key == p.Name)))
203+
.FirstOrDefault();
204+
}
205+
186206
static readonly Dictionary<Type, Func<string, object>> ExtendedTypeConversions = new Dictionary<Type, Func<string, object>>
187207
{
188208
{ typeof(Uri), s => new Uri(s) },

Diff for: src/Serilog.Settings.Configuration/project.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"version": "2.0.0-*",
2+
"version": "2.1.0-*",
33
"description": "Microsoft.Extensions.Configuration (appsettings.json) support for Serilog.",
44
"authors": [ "Serilog Contributors" ],
55
"packOptions": {
@@ -9,7 +9,6 @@
99
"iconUrl": "http://serilog.net/images/serilog-configuration-nuget.png"
1010
},
1111
"dependencies": {
12-
"Newtonsoft.Json": "9.0.1",
1312
"Microsoft.Extensions.Configuration.Abstractions": "1.0.0",
1413
"Microsoft.Extensions.DependencyModel": "1.0.0",
1514
"Serilog": "2.0.0"

Diff for: src/Serilog.Settings.Configuration/project.lock.json

-1
Original file line numberDiff line numberDiff line change
@@ -3037,7 +3037,6 @@
30373037
"": [
30383038
"Microsoft.Extensions.Configuration.Abstractions >= 1.0.0",
30393039
"Microsoft.Extensions.DependencyModel >= 1.0.0",
3040-
"Newtonsoft.Json >= 9.0.1",
30413040
"Serilog >= 2.0.0"
30423041
],
30433042
".NETFramework,Version=v4.5.1": [
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System.Collections.Generic;
2+
using Serilog.Settings.Configuration;
3+
using Serilog.Formatting;
4+
using Serilog.Formatting.Json;
5+
using Xunit;
6+
using System.Reflection;
7+
using System.Linq;
8+
9+
namespace Serilog.Settings.Configuration.Tests
10+
{
11+
public class ConfigurationReaderTests
12+
{
13+
[Fact]
14+
public void StringValuesConvertToDefaultInstancesIfTargetIsInterface()
15+
{
16+
var result = ConfigurationReader.ConvertToType("Serilog.Formatting.Json.JsonFormatter, Serilog", typeof(ITextFormatter));
17+
Assert.IsType<JsonFormatter>(result);
18+
}
19+
20+
[Fact]
21+
public void CallableMethodsAreSelected()
22+
{
23+
var options = typeof(DummyLoggerConfigurationExtensions).GetTypeInfo().DeclaredMethods.ToList();
24+
Assert.Equal(2, options.Count(mi => mi.Name == "DummyRollingFile"));
25+
var suppliedArguments = new Dictionary<string, string>
26+
{
27+
{"pathFormat", "C:\\" }
28+
};
29+
30+
var selected = ConfigurationReader.SelectConfigurationMethod(options, "DummyRollingFile", suppliedArguments);
31+
Assert.Equal(typeof(string), selected.GetParameters()[1].ParameterType);
32+
}
33+
34+
[Fact]
35+
public void MethodsAreSelectedBasedOnCountOfMatchedArguments()
36+
{
37+
var options = typeof(DummyLoggerConfigurationExtensions).GetTypeInfo().DeclaredMethods.ToList();
38+
Assert.Equal(2, options.Count(mi => mi.Name == "DummyRollingFile"));
39+
var suppliedArguments = new Dictionary<string, string>()
40+
{
41+
{ "pathFormat", "C:\\" },
42+
{ "formatter", "SomeFormatter, SomeAssembly" }
43+
};
44+
45+
var selected = ConfigurationReader.SelectConfigurationMethod(options, "DummyRollingFile", suppliedArguments);
46+
Assert.Equal(typeof(ITextFormatter), selected.GetParameters()[1].ParameterType);
47+
}
48+
}
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System;
2+
using Serilog.Configuration;
3+
using Serilog.Events;
4+
using Serilog.Formatting;
5+
6+
namespace Serilog.Settings.Configuration.Tests
7+
{
8+
static class DummyLoggerConfigurationExtensions
9+
{
10+
public static LoggerConfiguration DummyRollingFile(
11+
LoggerSinkConfiguration loggerSinkConfiguration,
12+
string pathFormat,
13+
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
14+
string outputTemplate = null,
15+
IFormatProvider formatProvider = null)
16+
{
17+
return null;
18+
}
19+
20+
public static LoggerConfiguration DummyRollingFile(
21+
LoggerSinkConfiguration loggerSinkConfiguration,
22+
ITextFormatter formatter,
23+
string pathFormat,
24+
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum)
25+
{
26+
return null;
27+
}
28+
}
29+
}

0 commit comments

Comments
 (0)