Skip to content

Commit

Permalink
Merge pull request serilog#872 from serilog/dev
Browse files Browse the repository at this point in the history
2.3.0 Release
  • Loading branch information
nblumhardt authored Oct 5, 2016
2 parents f6b69e9 + 673049a commit 90c0038
Show file tree
Hide file tree
Showing 16 changed files with 299 additions and 65 deletions.
1 change: 1 addition & 0 deletions Serilog.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,7 @@ II.2.12 <HandlesEvent />
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EJavaScript_002ECodeStyle_002ESettingsUpgrade_002EJsCodeFormatterSettingsUpgrader/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EJavaScript_002ECodeStyle_002ESettingsUpgrade_002EJsParsFormattingSettingsUpgrader/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EJavaScript_002ECodeStyle_002ESettingsUpgrade_002EJsWrapperSettingsUpgrader/@EntryIndexedValue">True</s:Boolean>


Expand Down
2 changes: 1 addition & 1 deletion src/Serilog/Context/LogContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public static class LogContext
#if ASYNCLOCAL
static readonly AsyncLocal<ImmutableStack<ILogEventEnricher>> Data = new AsyncLocal<ImmutableStack<ILogEventEnricher>>();
#elif REMOTING
static readonly string DataSlotName = typeof(LogContext).FullName + "@AppDomain" + AppDomain.CurrentDomain.Id;
static readonly string DataSlotName = typeof(LogContext).FullName + "@" + Guid.NewGuid();
#else // DOTNET_51
[ThreadStatic]
static ImmutableStack<ILogEventEnricher> Data;
Expand Down
7 changes: 6 additions & 1 deletion src/Serilog/Core/Sinks/RestrictedSink.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

namespace Serilog.Core.Sinks
{
class RestrictedSink : ILogEventSink
class RestrictedSink : ILogEventSink, IDisposable
{
readonly ILogEventSink _sink;
readonly LoggingLevelSwitch _levelSwitch;
Expand All @@ -39,5 +39,10 @@ public void Emit(LogEvent logEvent)

_sink.Emit(logEvent);
}

public void Dispose()
{
(_sink as IDisposable)?.Dispose();
}
}
}
52 changes: 30 additions & 22 deletions src/Serilog/Events/ScalarValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,36 +52,44 @@ public override void Render(TextWriter output, string format = null, IFormatProv
if (Value == null)
{
output.Write("null");
return;
}
else

var s = Value as string;
if (s != null)
{
var s = Value as string;
if (s != null)
if (format != "l")
{
if (format != "l")
{
output.Write("\"");
output.Write(s.Replace("\"", "\\\""));
output.Write("\"");
}
else
{
output.Write(s);
}
output.Write("\"");
output.Write(s.Replace("\"", "\\\""));
output.Write("\"");
}
else
{
var f = Value as IFormattable;
if (f != null)
{
output.Write(f.ToString(format, formatProvider ?? CultureInfo.InvariantCulture));
}
else
{
output.Write(Value.ToString());
}
output.Write(s);
}
return;
}

if (formatProvider != null)
{
var custom = (ICustomFormatter)formatProvider.GetFormat(typeof(ICustomFormatter));
if (custom != null)
{
output.Write(custom.Format(format, Value, formatProvider));
return;
}
}

var f = Value as IFormattable;
if (f != null)
{
output.Write(f.ToString(format, formatProvider ?? CultureInfo.InvariantCulture));
}
else
{
output.Write(Value.ToString());
}
}

/// <summary>
Expand Down
10 changes: 7 additions & 3 deletions src/Serilog/Parameters/PropertyValueConverter.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,14 @@ LogEventPropertyValue CreatePropertyValue(object value, Destructuring destructur
// multiple different interpretations.
if (IsValueTypeDictionary(valueType))
{
return new DictionaryValue(enumerable.Cast<dynamic>()
var typeInfo = typeof(KeyValuePair<,>).MakeGenericType(valueType.GenericTypeArguments).GetTypeInfo();
var keyProperty = typeInfo.GetDeclaredProperty("Key");
var valueProperty = typeInfo.GetDeclaredProperty("Value");

return new DictionaryValue(enumerable.Cast<object>()
.Select(kvp => new KeyValuePair<ScalarValue, LogEventPropertyValue>(
(ScalarValue)limiter.CreatePropertyValue(kvp.Key, destructuring),
limiter.CreatePropertyValue(kvp.Value, destructuring)))
(ScalarValue)limiter.CreatePropertyValue(keyProperty.GetValue(kvp), destructuring),
limiter.CreatePropertyValue(valueProperty.GetValue(kvp), destructuring)))
.Where(kvp => kvp.Key.Value != null));
}

Expand Down
53 changes: 39 additions & 14 deletions src/Serilog/Settings/KeyValuePairs/KeyValuePairSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using Serilog.Configuration;
using Serilog.Events;
Expand All @@ -28,6 +26,7 @@ namespace Serilog.Settings.KeyValuePairs
class KeyValuePairSettings : ILoggerSettings
{
const string UsingDirective = "using";
const string AuditToDirective = "audit-to";
const string WriteToDirective = "write-to";
const string MinimumLevelDirective = "minimum-level";
const string EnrichWithDirective = "enrich";
Expand All @@ -37,11 +36,12 @@ class KeyValuePairSettings : ILoggerSettings
const string EnrichWithEventEnricherPrefix = "enrich:";
const string EnrichWithPropertyDirectivePrefix = "enrich:with-property:";

const string WriteToDirectiveRegex = @"^write-to:(?<method>[A-Za-z0-9]*)(\.(?<argument>[A-Za-z0-9]*)){0,1}$";
const string AuditOrWriteToDirectiveRegex = @"^(?<directive>audit-to|write-to):(?<method>[A-Za-z0-9]*)(\.(?<argument>[A-Za-z0-9]*)){0,1}$";

readonly string[] _supportedDirectives =
{
UsingDirective,
AuditToDirective,
WriteToDirective,
MinimumLevelDirective,
EnrichWithPropertyDirective,
Expand Down Expand Up @@ -79,18 +79,21 @@ public void Configure(LoggerConfiguration loggerConfiguration)
loggerConfiguration.Enrich.WithProperty(name, enrichProperyDirective.Value);
}

var splitWriteTo = new Regex(WriteToDirectiveRegex);
var splitWriteTo = new Regex(AuditOrWriteToDirectiveRegex);

var sinkDirectives = (from wt in directives
where splitWriteTo.IsMatch(wt.Key)
let match = splitWriteTo.Match(wt.Key)
let call = new MethodArgumentValue
{
Method = match.Groups["method"].Value,
Argument = match.Groups["argument"].Value,
Value = wt.Value
}
group call by call.Method).ToList();
select new
{
Directive = match.Groups["directive"].Value,
Call = new MethodArgumentValue
{
Method = match.Groups["method"].Value,
Argument = match.Groups["argument"].Value,
Value = wt.Value
}
}).ToList();

var eventEnricherDirectives = (from er in directives
where er.Key.StartsWith(EnrichWithEventEnricherPrefix) && !er.Key.StartsWith(EnrichWithPropertyDirectivePrefix) && er.Key.Length > EnrichWithEventEnricherPrefix.Length
Expand All @@ -105,9 +108,26 @@ where er.Key.StartsWith(EnrichWithEventEnricherPrefix) && !er.Key.StartsWith(Enr
{
var configurationAssemblies = LoadConfigurationAssemblies(directives);

if (sinkDirectives.Any())
var writeToDirectives = sinkDirectives
.Where(d => d.Directive == WriteToDirective)
.Select(d => d.Call)
.GroupBy(call => call.Method)
.ToList();

if (writeToDirectives.Any())
{
ApplyDirectives(writeToDirectives, FindWriteToSinkConfigurationMethods(configurationAssemblies), loggerConfiguration.WriteTo);
}

var auditToDirectives = sinkDirectives
.Where(d => d.Directive == AuditToDirective)
.Select(d => d.Call)
.GroupBy(call => call.Method)
.ToList();

if (auditToDirectives.Any())
{
ApplyDirectives(sinkDirectives, FindSinkConfigurationMethods(configurationAssemblies), loggerConfiguration.WriteTo);
ApplyDirectives(auditToDirectives, FindAuditToSinkConfigurationMethods(configurationAssemblies), loggerConfiguration.AuditTo);
}

if (eventEnricherDirectives.Any())
Expand Down Expand Up @@ -214,11 +234,16 @@ internal static object ConvertToType(string value, Type toType)
return Convert.ChangeType(value, toType);
}

internal static IList<MethodInfo> FindSinkConfigurationMethods(IEnumerable<Assembly> configurationAssemblies)
internal static IList<MethodInfo> FindWriteToSinkConfigurationMethods(IEnumerable<Assembly> configurationAssemblies)
{
return FindConfigurationMethods(configurationAssemblies, typeof(LoggerSinkConfiguration));
}

internal static IList<MethodInfo> FindAuditToSinkConfigurationMethods(IEnumerable<Assembly> configurationAssemblies)
{
return FindConfigurationMethods(configurationAssemblies, typeof(LoggerAuditSinkConfiguration));
}

// Unlike the other configuration methods, FromLogContext is an instance method rather than an extension.

internal static LoggerConfiguration FromLogContext(LoggerEnrichmentConfiguration loggerEnrichmentConfiguration)
Expand Down
2 changes: 1 addition & 1 deletion src/Serilog/project.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "2.2.1-*",
"version": "2.3.0-*",

"description": "Simple .NET logging with fully-structured events",
"authors": [ "Serilog Contributors" ],
Expand Down
7 changes: 5 additions & 2 deletions test/Serilog.PerformanceTests/Serilog.PerformanceTests.xproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
Expand All @@ -14,5 +14,8 @@
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
</Project>
37 changes: 36 additions & 1 deletion test/Serilog.Tests/Core/MessageTemplateTests.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -163,5 +163,40 @@ public void MissingPositionalParametersRenderAsTextLikeStandardFormats()
var m = Render("{1}, {0}", "world");
Assert.Equal("{1}, \"world\"", m);
}

[Fact]
public void AnonymousTypeShouldBeRendered()
{
var anonymous = new { Test = 3M };
var m = Render("Anonymous type {value}", anonymous);
Assert.Equal("Anonymous type \"{ Test = 3 }\"", m);
}

[Fact]
public void EnumerableOfAnonymousTypeShouldBeRendered()
{
var anonymous = new { Foo = 4M, Bar = "Baz" };
var enumerable = Enumerable.Repeat("MyKey", 1).Select(v => anonymous);
var m = Render("Enumerable with anonymous type {enumerable}", enumerable);
Assert.Equal("Enumerable with anonymous type [\"{ Foo = 4, Bar = Baz }\"]", m);
}

[Fact]
public void DictionaryOfAnonymousTypeAsValueShouldBeRendered()
{
var anonymous = new { Test = 5M };
var dictionary = Enumerable.Repeat("MyKey", 1).ToDictionary(v => v, v => anonymous);
var m = Render("Dictionary with anonymous type value {dictionary}", dictionary);
Assert.Equal("Dictionary with anonymous type value [(\"MyKey\": \"{ Test = 5 }\")]", m);
}

[Fact]
public void DictionaryOfAnonymousTypeAsKeyShouldBeRendered()
{
var anonymous = new { Bar = 6M, Baz = 4M };
var dictionary = Enumerable.Repeat("MyValue", 1).ToDictionary(v => anonymous, v => v);
var m = Render("Dictionary with anonymous type key {dictionary}", dictionary);
Assert.Equal("Dictionary with anonymous type key [\"[{ Bar = 6, Baz = 4 }, MyValue]\"]", m);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Globalization;
using System;
using System.Globalization;
using System.IO;

using Serilog.Events;
Expand Down Expand Up @@ -150,5 +151,52 @@ public void AligmentAndWidthCanBeCombined()
formatter.Format(evt, sw);
Assert.Equal(" inf", sw.ToString());
}

enum Size
{
Large
}

class SizeFormatter : IFormatProvider, ICustomFormatter
{
private readonly IFormatProvider _innerFormatProvider;

public SizeFormatter(IFormatProvider innerFormatProvider)
{
_innerFormatProvider = innerFormatProvider;
}

public object GetFormat(Type formatType)
{
return formatType == typeof(ICustomFormatter) ? this : _innerFormatProvider.GetFormat(formatType);
}

public string Format(string format, object arg, IFormatProvider formatProvider)
{
if (arg is Size)
{
var size = (Size)arg;
return size == Size.Large ? "Huge" : size.ToString();
}

var formattable = arg as IFormattable;
if (formattable != null)
{
return formattable.ToString(format, _innerFormatProvider);
}

return arg.ToString();
}
}

[Fact]
public void AppliesCustomFormatterToEnums()
{
var formatter = new MessageTemplateTextFormatter("{Message}", new SizeFormatter(CultureInfo.InvariantCulture));
var evt = DelegatingSink.GetLogEvent(l => l.Information("Size {Size}", Size.Large));
var sw = new StringWriter();
formatter.Format(evt, sw);
Assert.Equal("Size Huge", sw.ToString());
}
}
}
5 changes: 4 additions & 1 deletion test/Serilog.Tests/Serilog.Tests.xproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,8 @@
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
</Project>
Loading

0 comments on commit 90c0038

Please sign in to comment.