Skip to content
This repository has been archived by the owner on Nov 3, 2021. It is now read-only.

Commit

Permalink
First basic implementation of Combined Settings to start somewhere
Browse files Browse the repository at this point in the history
related to #1 and #5
  • Loading branch information
Thibaud DESODT committed Oct 23, 2017
1 parent ba539a8 commit a31b2b3
Show file tree
Hide file tree
Showing 13 changed files with 358 additions and 19 deletions.
6 changes: 0 additions & 6 deletions src/Serilog.Settings.Combined/Class1.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using Serilog.Configuration;
using Serilog.Settings.Combined;

namespace Serilog
{
public static class CombinedSettingsLoggerConfigurationExtensions
{
public static LoggerConfiguration Combined(this LoggerSettingsConfiguration lsc, Func<IConfigBuilder, IConfigBuilder> build)
{
var configBuilder = new ConfigBuilder();
configBuilder = (ConfigBuilder)build(configBuilder);
var enumerable = configBuilder.BuildCombinedEnumerable();

return lsc.KeyValuePairs(enumerable);
}
}
}
4 changes: 4 additions & 0 deletions src/Serilog.Settings.Combined/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Serilog.Settings.Combined.Tests")]

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>Serilog</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Serilog" Version="2.5.0" />
</ItemGroup>

</Project>
41 changes: 41 additions & 0 deletions src/Serilog.Settings.Combined/Settings/Combined/ConfigBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System.Collections.Generic;

namespace Serilog.Settings.Combined
{
class ConfigBuilder : IConfigBuilder
{
List<IEnumerable<KeyValuePair<string, string>>> _sources;

public ConfigBuilder()
{
_sources = new List<IEnumerable<KeyValuePair<string, string>>>();
}

public IEnumerable<KeyValuePair<string, string>> BuildCombinedEnumerable()
{
IEnumerable<KeyValuePair<string, string>> Combined()
{
var result = new Dictionary<string, string>();
foreach (var source in _sources)
{
foreach (var kvp in source)
{
result[kvp.Key] = kvp.Value;
}
}
return result;
}

foreach (var kvp in Combined())
{
yield return kvp;
}
}

public IConfigBuilder AddSource(IEnumerable<KeyValuePair<string, string>> source)
{
_sources.Add(source);
return this;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;

namespace Serilog.Settings.Combined
{
public static class ConfigBuilderExtensions
{
public static IConfigBuilder AddKeyValuePairs(this IConfigBuilder builder, IReadOnlyDictionary<string, string> keyValuePairs)
{
if (builder == null) throw new ArgumentNullException(nameof(builder));
if (keyValuePairs == null) throw new ArgumentNullException(nameof(keyValuePairs));

return builder.AddSource(keyValuePairs);
}

public static IConfigBuilder AddKeyValuePair(this IConfigBuilder builder, KeyValuePair<string, string> keyValuePair)
{
if (builder == null) throw new ArgumentNullException(nameof(builder));

return builder.AddSource(new[] { keyValuePair });
}

public static IConfigBuilder AddKeyValuePair(this IConfigBuilder builder, string key, string value)
{
if (key == null) throw new ArgumentNullException(nameof(key));

return builder.AddSource(new Dictionary<string, string>()
{
{key, value}
});
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Collections.Generic;

namespace Serilog.Settings.Combined
{
public interface IConfigBuilder
{
IConfigBuilder AddSource(IEnumerable<KeyValuePair<string, string>> source);
}
}
59 changes: 59 additions & 0 deletions test/Serilog.Settings.Combined.Tests/CombinedSettingsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System.Collections.Generic;
using Serilog.Events;
using Serilog.Tests.Support;
using Xunit;

namespace Serilog.Settings.Combined.Tests
{
public class CombinedSettingsTests
{
[Fact]
public void CombinedCanMergeMultipleKeyValuePairLists()
{
LogEvent evt = null;
var log = new LoggerConfiguration()
.ReadFrom.Combined(builder => builder
.AddKeyValuePairs(new Dictionary<string, string>
{
{"enrich:with-property:UntouchedProp", "initialValue"},
{"enrich:with-property:OverridenProp", "initialValue"},
})
.AddKeyValuePairs(new Dictionary<string, string>
{
{"enrich:with-property:OverridenProp", "overridenValue"},
{"enrich:with-property:NewProp", "value"},
}))
.WriteTo.Sink(new DelegatingSink(e => evt = e))
.CreateLogger();

log.Information("a message that should be enriched with properties");

Assert.NotNull(evt);
Assert.Equal("initialValue", evt.Properties["UntouchedProp"].LiteralValue());
Assert.Equal("overridenValue", evt.Properties["OverridenProp"].LiteralValue());
Assert.Equal("value", evt.Properties["NewProp"].LiteralValue());
}

[Fact]
public void CombinedCanMergeMultipleKeyValuePairs()
{
LogEvent evt = null;
var log = new LoggerConfiguration()
.ReadFrom.Combined(builder => builder
.AddKeyValuePair("enrich:with-property:UntouchedProp", "initialValue")
.AddKeyValuePair("enrich:with-property:OverridenProp", "initialValue")
.AddKeyValuePair("enrich:with-property:NewProp", "value")
.AddKeyValuePair(new KeyValuePair<string, string>("enrich:with-property:OverridenProp", "overridenValue"))
)
.WriteTo.Sink(new DelegatingSink(e => evt = e))
.CreateLogger();

log.Information("a message that should be enriched with properties");

Assert.NotNull(evt);
Assert.Equal("initialValue", evt.Properties["UntouchedProp"].LiteralValue());
Assert.Equal("overridenValue", evt.Properties["OverridenProp"].LiteralValue());
Assert.Equal("value", evt.Properties["NewProp"].LiteralValue());
}
}
}
41 changes: 41 additions & 0 deletions test/Serilog.Settings.Combined.Tests/ConfigBuilderTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System.Collections.Generic;
using System.Linq;
using Xunit;

namespace Serilog.Settings.Combined.Tests
{
public class ConfigBuilderTests
{

[Fact]
public void ConfigBuilderConsumesEnumerablesAsLateAsPossible()
{
var consumeCount = 0;

IEnumerable<KeyValuePair<string, string>> Enumerable1()
{
consumeCount++;
yield break;
}

IEnumerable<KeyValuePair<string, string>> Enumerable2()
{
consumeCount++;
yield break;
}

var builder = new ConfigBuilder();
builder.AddSource(Enumerable1());
builder.AddSource(Enumerable2());
Assert.Equal(0, consumeCount);

var combined = builder.BuildCombinedEnumerable();
Assert.Equal(0, consumeCount);

// ReSharper disable once ReturnValueOfPureMethodIsNotUsed
combined.ToList();

Assert.Equal(2, consumeCount);
}
}
}
34 changes: 34 additions & 0 deletions test/Serilog.Settings.Combined.Tests/Support/DelegatingSink.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using Serilog.Core;
using Serilog.Events;

namespace Serilog.Tests.Support
{
public class DelegatingSink : ILogEventSink
{
readonly Action<LogEvent> _write;

public DelegatingSink(Action<LogEvent> write)
{
if (write == null) throw new ArgumentNullException(nameof(write));
_write = write;
}

public void Emit(LogEvent logEvent)
{
_write(logEvent);
}

public static LogEvent GetLogEvent(Action<ILogger> writeAction)
{
LogEvent result = null;
var l = new LoggerConfiguration()
.MinimumLevel.Verbose()
.WriteTo.Sink(new DelegatingSink(le => result = le))
.CreateLogger();

writeAction(l);
return result;
}
}
}
12 changes: 12 additions & 0 deletions test/Serilog.Settings.Combined.Tests/Support/Extensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Serilog.Events;

namespace Serilog.Tests.Support
{
public static class Extensions
{
public static object LiteralValue(this LogEventPropertyValue @this)
{
return ((ScalarValue)@this).Value;
}
}
}
102 changes: 102 additions & 0 deletions test/Serilog.Settings.Combined.Tests/Support/Some.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using Serilog.Core;
using Serilog.Events;
using Serilog.Parsing;

namespace Serilog.Tests.Support
{
static class Some
{
static int Counter;

public static int Int()
{
return Interlocked.Increment(ref Counter);
}

public static decimal Decimal()
{
return Int() + 0.123m;
}

public static string String(string tag = null)
{
return (tag ?? "") + "__" + Int();
}

public static TimeSpan TimeSpan()
{
return System.TimeSpan.FromMinutes(Int());
}

public static DateTime Instant()
{
return new DateTime(2012, 10, 28) + TimeSpan();
}

public static DateTimeOffset OffsetInstant()
{
return new DateTimeOffset(Instant());
}

public static LogEvent LogEvent(string sourceContext, DateTimeOffset? timestamp = null, LogEventLevel level = LogEventLevel.Information)
{
return new LogEvent(timestamp ?? OffsetInstant(), level,
null, MessageTemplate(),
new List<LogEventProperty> { new LogEventProperty(Constants.SourceContextPropertyName, new ScalarValue(sourceContext)) });
}

public static LogEvent LogEvent(DateTimeOffset? timestamp = null, LogEventLevel level = LogEventLevel.Information)
{
return new LogEvent(timestamp ?? OffsetInstant(), level,
null, MessageTemplate(), Enumerable.Empty<LogEventProperty>());
}

public static LogEvent InformationEvent(DateTimeOffset? timestamp = null)
{
// ReSharper disable once RedundantArgumentDefaultValue
return LogEvent(timestamp, LogEventLevel.Information);
}

public static LogEvent DebugEvent(DateTimeOffset? timestamp = null)
{
return LogEvent(timestamp, LogEventLevel.Debug);
}

public static LogEvent WarningEvent(DateTimeOffset? timestamp = null)
{
return LogEvent(timestamp, LogEventLevel.Warning);
}

public static LogEventProperty LogEventProperty()
{
return new LogEventProperty(String(), new ScalarValue(Int()));
}

public static string NonexistentTempFilePath()
{
return Path.Combine(Path.GetTempPath(), Guid.NewGuid() + ".txt");
}

public static string TempFilePath()
{
return Path.GetTempFileName();
}

public static string TempFolderPath()
{
var dir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(dir);
return dir;
}

public static MessageTemplate MessageTemplate()
{
return new MessageTemplateParser().Parse(String());
}
}
}
13 changes: 0 additions & 13 deletions test/Serilog.Settings.Combined.Tests/UnitTest1.cs

This file was deleted.

0 comments on commit a31b2b3

Please sign in to comment.