Skip to content

Bugfix release v3.0.1 #146

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

Merged
merged 11 commits into from
Oct 17, 2018
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
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Description>Microsoft.Extensions.Configuration (appsettings.json) support for Serilog.</Description>
<VersionPrefix>3.0.0</VersionPrefix>
<VersionPrefix>3.0.1</VersionPrefix>
<Authors>Serilog Contributors</Authors>
<TargetFrameworks>netstandard2.0;net451;net461</TargetFrameworks>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public ConfigurationReader(IConfiguration configuration, DependencyContext depen

// Generally the initial call should use IConfiguration rather than IConfigurationSection, otherwise
// IConfiguration parameters in the target methods will not be populated.
ConfigurationReader(IConfigurationSection configSection, DependencyContext dependencyContext)
public ConfigurationReader(IConfigurationSection configSection, DependencyContext dependencyContext)
{
_section = configSection ?? throw new ArgumentNullException(nameof(configSection));
_dependencyContext = dependencyContext;
Expand Down Expand Up @@ -331,7 +331,15 @@ static void CallConfigurationMethods(ILookup<string, Dictionary<string, IConfigu
select directive.Key == null ? p.DefaultValue : directive.Value.ConvertTo(p.ParameterType, declaredLevelSwitches)).ToList();

var parm = methodInfo.GetParameters().FirstOrDefault(i => i.ParameterType == typeof(IConfiguration));
if (parm != null) call[parm.Position - 1] = _configuration;
if (parm != null && !parm.HasDefaultValue)
{
if (_configuration is null)
{
throw new InvalidOperationException("Trying to invoke a configuration method accepting a `IConfiguration` argument. " +
$"This is not supported when only a `IConfigSection` has been provided. (method '{methodInfo}')");
}
call[parm.Position - 1] = _configuration;
}

call.Insert(0, receiver);

Expand All @@ -348,7 +356,11 @@ internal static MethodInfo SelectConfigurationMethod(IEnumerable<MethodInfo> can
return candidateMethods
.Where(m => m.Name == name &&
m.GetParameters().Skip(1)
.All(p => p.HasDefaultValue || suppliedArgumentValues.Any(s => s.Key.Equals(p.Name, StringComparison.OrdinalIgnoreCase))))
.All(p => p.HasDefaultValue
|| suppliedArgumentValues.Any(s => s.Key.Equals(p.Name, StringComparison.OrdinalIgnoreCase))
// parameters of type IConfiguration are implicitly populated with provided Configuration
|| p.ParameterType == typeof(IConfiguration)
))
.OrderByDescending(m =>
{
var matchingArgs = m.GetParameters().Where(p => suppliedArgumentValues.Any(s => s.Key.Equals(p.Name, StringComparison.OrdinalIgnoreCase))).ToList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -419,32 +419,77 @@ public void LoggingLevelSwitchCanBeUsedForMinimumLevelOverrides()
}

[Fact]

[Trait("BugFix", "https://github.com/serilog/serilog-settings-configuration/issues/142")]
public void SinkWithIConfigurationArguments()
{
var json = @"{
""Serilog"": {
""Using"": [""TestDummies""],
""WriteTo"": [{
""Name"": ""DummyRollingFile"",
""Args"": {""pathFormat"" : ""C:\\"",
""configurationSection"" : { ""foo"" : ""bar"" } }
""Name"": ""DummyWithConfiguration"",
""Args"": {}
}]
}
}";

// IConfiguration and IConfigurationSection arguments do not have
// default values so they will throw if they are not populated

DummyConfigurationSink.Reset();
var log = ConfigFromJson(json)
.CreateLogger();

DummyRollingFileSink.Reset();
log.Write(Some.InformationEvent());

Assert.NotNull(DummyConfigurationSink.Configuration);
}

[Fact]
[Trait("BugFix", "https://github.com/serilog/serilog-settings-configuration/issues/142")]
public void SinkWithOptionalIConfigurationArguments()
{
var json = @"{
""Serilog"": {
""Using"": [""TestDummies""],
""WriteTo"": [{
""Name"": ""DummyWithOptionalConfiguration"",
""Args"": {}
}]
}
}";

DummyConfigurationSink.Reset();
var log = ConfigFromJson(json)
.CreateLogger();

log.Write(Some.InformationEvent());

Assert.Equal(1, DummyRollingFileSink.Emitted.Count);
// null is the default value
Assert.Null(DummyConfigurationSink.Configuration);
}

[Fact]
public void SinkWithIConfigSectionArguments()
{
var json = @"{
""Serilog"": {
""Using"": [""TestDummies""],
""WriteTo"": [{
""Name"": ""DummyWithConfigSection"",
""Args"": {""configurationSection"" : { ""foo"" : ""bar"" } }
}]
}
}";

DummyConfigurationSink.Reset();
var log = ConfigFromJson(json)
.CreateLogger();

log.Write(Some.InformationEvent());

Assert.NotNull(DummyConfigurationSink.ConfigSection);
Assert.Equal("bar", DummyConfigurationSink.ConfigSection["foo"]);
}


[Fact]
public void SinkWithConfigurationBindingArgument()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System;
using Microsoft.Extensions.Configuration;
using Serilog.Events;
using Serilog.Settings.Configuration.Tests.Support;
using Xunit;

namespace Serilog.Settings.Configuration.Tests
Expand All @@ -14,5 +16,89 @@ public void ReadFromConfigurationShouldNotThrowOnEmptyConfiguration()
// should not throw
act();
}

[Fact]
[Trait("BugFix", "https://github.com/serilog/serilog-settings-configuration/issues/143")]
public void ReadFromConfigurationSectionReadsFromAnArbitrarySection()
{
LogEvent evt = null;

var json = @"{
""NotSerilog"": {
""Properties"": {
""App"": ""Test""
}
}
}";

var config = new ConfigurationBuilder()
.AddJsonString(json)
.Build();

var log = new LoggerConfiguration()
.ReadFrom.ConfigurationSection(config.GetSection("NotSerilog"))
.WriteTo.Sink(new DelegatingSink(e => evt = e))
.CreateLogger();

log.Information("Has a test property");

Assert.NotNull(evt);
Assert.Equal("Test", evt.Properties["App"].LiteralValue());
}

[Fact(Skip = "Passes when run alone, but fails when the whole suite is run - to fix")]
[Trait("BugFix", "https://github.com/serilog/serilog-settings-configuration/issues/143")]
public void ReadFromConfigurationSectionThrowsWhenTryingToCallConfigurationMethodWithIConfigurationParam()
{
var json = @"{
""NotSerilog"": {
""Using"": [""TestDummies""],
""WriteTo"": [{
""Name"": ""DummyWithConfiguration"",
""Args"": {}
}]
}
}";

var config = new ConfigurationBuilder()
.AddJsonString(json)
.Build();

var exception = Assert.Throws<InvalidOperationException>(() =>
new LoggerConfiguration()
.ReadFrom.ConfigurationSection(config.GetSection("NotSerilog"))
.CreateLogger());

Assert.Equal("Trying to invoke a configuration method accepting a `IConfiguration` argument. " +
"This is not supported when only a `IConfigSection` has been provided. " +
"(method 'Serilog.LoggerConfiguration DummyWithConfiguration(Serilog.Configuration.LoggerSinkConfiguration, Microsoft.Extensions.Configuration.IConfiguration, Microsoft.Extensions.Configuration.IConfigurationSection, System.String, Serilog.Events.LogEventLevel)')",
exception.Message);

}

[Fact]
[Trait("BugFix", "https://github.com/serilog/serilog-settings-configuration/issues/143")]
public void ReadFromConfigurationSectionDoesNotThrowWhenTryingToCallConfigurationMethodWithOptionalIConfigurationParam()
{
var json = @"{
""NotSerilog"": {
""Using"": [""TestDummies""],
""WriteTo"": [{
""Name"": ""DummyWithOptionalConfiguration"",
""Args"": {}
}]
}
}";

var config = new ConfigurationBuilder()
.AddJsonString(json)
.Build();

// this should not throw because DummyWithOptionalConfiguration accepts an optional config
new LoggerConfiguration()
.ReadFrom.ConfigurationSection(config.GetSection("NotSerilog"))
.CreateLogger();

}
}
}
46 changes: 46 additions & 0 deletions test/TestDummies/DummyConfigurationSink.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Configuration;
using Serilog.Core;
using Serilog.Events;

namespace TestDummies
{
public class DummyConfigurationSink : ILogEventSink
{
[ThreadStatic]
static List<LogEvent> _emitted;

[ThreadStatic]
static IConfiguration _configuration;

[ThreadStatic]
static IConfigurationSection _configSection;

public static List<LogEvent> Emitted => _emitted ?? (_emitted = new List<LogEvent>());

public static IConfiguration Configuration => _configuration;

public static IConfigurationSection ConfigSection => _configSection;


public DummyConfigurationSink(IConfiguration configuration, IConfigurationSection configSection)
{
_configuration = configuration;
_configSection = configSection;
}

public void Emit(LogEvent logEvent)
{
Emitted.Add(logEvent);
}

public static void Reset()
{
_emitted = null;
_configuration = null;
_configSection = null;
}

}
}
20 changes: 17 additions & 3 deletions test/TestDummies/DummyLoggerConfigurationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,28 @@ public static LoggerConfiguration DummyRollingFile(
return loggerSinkConfiguration.Sink(new DummyRollingFileSink(), restrictedToMinimumLevel);
}

public static LoggerConfiguration DummyRollingFile(
public static LoggerConfiguration DummyWithConfiguration(
this LoggerSinkConfiguration loggerSinkConfiguration,
IConfiguration appConfiguration,
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum)
{
return loggerSinkConfiguration.Sink(new DummyConfigurationSink(appConfiguration, null), restrictedToMinimumLevel);
}

public static LoggerConfiguration DummyWithOptionalConfiguration(
this LoggerSinkConfiguration loggerSinkConfiguration,
IConfiguration appConfiguration = null,
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum)
{
return loggerSinkConfiguration.Sink(new DummyConfigurationSink(appConfiguration, null), restrictedToMinimumLevel);
}

public static LoggerConfiguration DummyWithConfigSection(
this LoggerSinkConfiguration loggerSinkConfiguration,
IConfigurationSection configurationSection,
string pathFormat,
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum)
{
return loggerSinkConfiguration.Sink(new DummyRollingFileSink(), restrictedToMinimumLevel);
return loggerSinkConfiguration.Sink(new DummyConfigurationSink(null, configurationSection), restrictedToMinimumLevel);
}

public static LoggerConfiguration DummyRollingFile(
Expand Down