Skip to content

Commit

Permalink
Merge pull request #15 from serilog/dev
Browse files Browse the repository at this point in the history
Update Dev
  • Loading branch information
rafaelsc committed Aug 4, 2020
2 parents 88c7d94 + 308208e commit 1582b86
Show file tree
Hide file tree
Showing 33 changed files with 455 additions and 463 deletions.
359 changes: 10 additions & 349 deletions Serilog.sln.DotSettings

Large diffs are not rendered by default.

50 changes: 50 additions & 0 deletions results/netcoreapp3.1/SourceContextMatchBenchmark-report-github.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Benchmark results

## Linux

``` ini

BenchmarkDotNet=v0.12.0, OS=debian 11
Intel Core i7-3840QM CPU 2.80GHz (Ivy Bridge), 1 CPU, 4 logical and 2 physical cores
.NET Core SDK=3.1.201
[Host] : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT
Job-CSERBI : .NET Core 2.1.16 (CoreCLR 4.6.28516.03, CoreFX 4.6.28516.10), X64 RyuJIT
Job-GDNCBZ : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT


```
| Method | Runtime | Mean | Error | StdDev | Ratio |
|----------------------------------- |-------------- |-----------:|---------:|---------:|------:|
| Filter_MatchingFromSource | .NET Core 2.1 | 5,799.5 ns | 51.17 ns | 45.36 ns | 1.00 |
| Filter_MatchingFromSource | .NET Core 3.1 | 3,564.5 ns | 37.43 ns | 35.01 ns | 0.61 |
| | | | | | |
| Logger_ForContext | .NET Core 2.1 | 2,519.0 ns | 15.37 ns | 13.62 ns | 1.00 |
| Logger_ForContext | .NET Core 3.1 | 961.8 ns | 4.67 ns | 4.36 ns | 0.38 |
| | | | | | |
| LevelOverrideMap_GetEffectiveLevel | .NET Core 2.1 | 1,745.7 ns | 11.95 ns | 10.60 ns | 1.00 |
| LevelOverrideMap_GetEffectiveLevel | .NET Core 3.1 | 193.8 ns | 2.35 ns | 2.20 ns | 0.11 |

## Windows

``` ini

BenchmarkDotNet=v0.12.0, OS=Windows 10.0.19041
Intel Core i7-3840QM CPU 2.80GHz (Ivy Bridge), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=3.1.300
[Host] : .NET Core 3.1.4 (CoreCLR 4.700.20.20201, CoreFX 4.700.20.22101), X64 RyuJIT
Job-KEWXME : .NET Core 2.1.16 (CoreCLR 4.6.28516.03, CoreFX 4.6.28516.10), X64 RyuJIT
Job-KKEVOV : .NET Core 3.1.4 (CoreCLR 4.700.20.20201, CoreFX 4.700.20.22101), X64 RyuJIT


```
| Method | Runtime | Mean | Error | StdDev | Ratio |
|----------------------------------- |-------------- |-----------:|----------:|----------:|------:|
| Filter_MatchingFromSource | .NET Core 2.1 | 8,088.7 ns | 120.48 ns | 112.70 ns | 1.00 |
| Filter_MatchingFromSource | .NET Core 3.1 | 3,369.0 ns | 71.49 ns | 73.42 ns | 0.42 |
| | | | | | |
| Logger_ForContext | .NET Core 2.1 | 6,322.1 ns | 98.18 ns | 91.84 ns | 1.00 |
| Logger_ForContext | .NET Core 3.1 | 785.6 ns | 9.05 ns | 8.47 ns | 0.12 |
| | | | | | |
| LevelOverrideMap_GetEffectiveLevel | .NET Core 2.1 | 5,619.1 ns | 20.98 ns | 18.60 ns | 1.00 |
| LevelOverrideMap_GetEffectiveLevel | .NET Core 3.1 | 185.4 ns | 1.63 ns | 1.44 ns | 0.03 |

1 change: 1 addition & 0 deletions run_perf_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
dotnet restore

for path in test/*.PerformanceTests/*.csproj; do
dotnet test -f netcoreapp2.1 -c Release ${path}
dotnet test -f netcoreapp3.1 -c Release ${path}
done
4 changes: 2 additions & 2 deletions src/Serilog/Capturing/PropertyValueConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ LogEventPropertyValue CreatePropertyValue(object value, Destructuring destructur
if (TryConvertCompilerGeneratedType(value, destructuring, valueType, out var compilerGeneratedResult))
return compilerGeneratedResult;

return new ScalarValue(value.ToString());
return new ScalarValue(value.ToString() ?? "");
}

bool TryConvertEnumerable(object value, Destructuring destructuring, Type valueType, out LogEventPropertyValue result)
Expand Down Expand Up @@ -299,7 +299,7 @@ bool TryConvertCompilerGeneratedType(object value, Destructuring destructuring,
LogEventPropertyValue Stringify(object value)
{
var stringified = value.ToString();
var truncated = stringified == null ? null : TruncateIfNecessary(stringified);
var truncated = stringified == null ? "" : TruncateIfNecessary(stringified);
return new ScalarValue(truncated);
}

Expand Down
6 changes: 3 additions & 3 deletions src/Serilog/Configuration/LoggerAuditSinkConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2016 Serilog Contributors
// Copyright 2016-2020 Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -25,9 +25,9 @@ public class LoggerAuditSinkConfiguration
{
readonly LoggerSinkConfiguration _sinkConfiguration;

internal LoggerAuditSinkConfiguration(LoggerConfiguration loggerConfiguration, Action<ILogEventSink> addSink, Action<LoggerConfiguration> applyInheritedConfiguration)
internal LoggerAuditSinkConfiguration(LoggerConfiguration loggerConfiguration, Action<ILogEventSink> addSink)
{
_sinkConfiguration = new LoggerSinkConfiguration(loggerConfiguration, addSink, applyInheritedConfiguration);
_sinkConfiguration = new LoggerSinkConfiguration(loggerConfiguration, addSink);
}

/// <summary>
Expand Down
23 changes: 7 additions & 16 deletions src/Serilog/Configuration/LoggerSinkConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2013-2015 Serilog Contributors
// Copyright 2013-2020 Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -17,7 +17,6 @@
using System.ComponentModel;
using System.Linq;
using Serilog.Core;
using Serilog.Core.Enrichers;
using Serilog.Core.Sinks;
using Serilog.Debugging;
using Serilog.Events;
Expand All @@ -31,13 +30,11 @@ public class LoggerSinkConfiguration
{
readonly LoggerConfiguration _loggerConfiguration;
readonly Action<ILogEventSink> _addSink;
readonly Action<LoggerConfiguration> _applyInheritedConfiguration;

internal LoggerSinkConfiguration(LoggerConfiguration loggerConfiguration, Action<ILogEventSink> addSink, Action<LoggerConfiguration> applyInheritedConfiguration)
internal LoggerSinkConfiguration(LoggerConfiguration loggerConfiguration, Action<ILogEventSink> addSink)
{
_loggerConfiguration = loggerConfiguration ?? throw new ArgumentNullException(nameof(loggerConfiguration));
_addSink = addSink ?? throw new ArgumentNullException(nameof(addSink));
_applyInheritedConfiguration = applyInheritedConfiguration ?? throw new ArgumentNullException(nameof(applyInheritedConfiguration));
}

/// <summary>
Expand Down Expand Up @@ -127,9 +124,7 @@ internal LoggerSinkConfiguration(LoggerConfiguration loggerConfiguration, Action
{
if (configureLogger == null) throw new ArgumentNullException(nameof(configureLogger));

var lc = new LoggerConfiguration();

_applyInheritedConfiguration(lc);
var lc = new LoggerConfiguration().MinimumLevel.Is(LevelAlias.Minimum);
configureLogger(lc);

var subLogger = lc.CreateLogger();
Expand Down Expand Up @@ -238,8 +233,7 @@ public LoggerConfiguration Conditional(Func<LogEvent, bool> condition, Action<Lo
var capturingConfiguration = new LoggerConfiguration();
var capturingLoggerSinkConfiguration = new LoggerSinkConfiguration(
capturingConfiguration,
sinksToWrap.Add,
loggerSinkConfiguration._applyInheritedConfiguration);
sinksToWrap.Add);

// `WriteTo.Sink()` will return the capturing configuration; this ensures chained `WriteTo` gets back
// to the capturing sink configuration, enabling `WriteTo.X().WriteTo.Y()`.
Expand All @@ -252,15 +246,12 @@ public LoggerConfiguration Conditional(Func<LogEvent, bool> condition, Action<Lo

var enclosed = sinksToWrap.Count == 1 ?
sinksToWrap.Single() :
new SafeAggregateSink(sinksToWrap);
new DisposingAggregateSink(sinksToWrap);

var wrappedSink = wrapSink(enclosed);

if (!(wrappedSink is IDisposable))
if (!(wrappedSink is IDisposable) && enclosed is IDisposable target)
{
SelfLog.WriteLine("Wrapping sink {0} does not implement IDisposable; to ensure " +
"wrapped sinks are properly flushed, wrappers should dispose " +
"their wrapped contents", wrappedSink);
wrappedSink = new DisposeDelegatingSink(wrappedSink, target);
}

return loggerSinkConfiguration.Sink(wrappedSink, restrictedToMinimumLevel, levelSwitch);
Expand Down
12 changes: 7 additions & 5 deletions src/Serilog/Core/CustomDefaultMethodImplementationAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
namespace Serilog.Core
{
#if FEATURE_DEFAULT_INTERFACE
using System;

using System;

namespace Serilog.Core
{
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Interface)]
internal sealed class CustomDefaultMethodImplementationAttribute : Attribute
sealed class CustomDefaultMethodImplementationAttribute : Attribute
{
}
#endif
}

#endif
17 changes: 11 additions & 6 deletions src/Serilog/Core/LevelOverrideMap.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2016 Serilog Contributors
// Copyright 2016-2020 Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -29,14 +29,11 @@ struct LevelOverride
public LevelOverride(string context, LoggingLevelSwitch levelSwitch)
{
Context = context;
ContextPrefix = context + ".";
LevelSwitch = levelSwitch;
}

public string Context { get; }

public string ContextPrefix { get; }

public LoggingLevelSwitch LevelSwitch { get; }
}

Expand Down Expand Up @@ -65,11 +62,19 @@ public LevelOverride(string context, LoggingLevelSwitch levelSwitch)
.ToArray();
}

public void GetEffectiveLevel(string context, out LogEventLevel minimumLevel, out LoggingLevelSwitch levelSwitch)
public void GetEffectiveLevel(
#if FEATURE_SPAN
ReadOnlySpan<char> context,
#else
string context,
#endif
out LogEventLevel minimumLevel,
out LoggingLevelSwitch levelSwitch)
{
foreach (var levelOverride in _overrides)
{
if (context.StartsWith(levelOverride.ContextPrefix) || context == levelOverride.Context)
if (context.StartsWith(levelOverride.Context) &&
(context.Length == levelOverride.Context.Length || context[levelOverride.Context.Length] == '.'))
{
minimumLevel = LevelAlias.Minimum;
levelSwitch = levelOverride.LevelSwitch;
Expand Down
4 changes: 2 additions & 2 deletions src/Serilog/Core/Sinks/AggregateSink.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2016 Serilog Contributors
// Copyright 2016-2020 Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -43,7 +43,7 @@ public void Emit(LogEvent logEvent)
catch (Exception ex)
{
SelfLog.WriteLine("Caught exception while emitting to sink {0}: {1}", sink, ex);
exceptions = exceptions ?? new List<Exception>();
exceptions ??= new List<Exception>();
exceptions.Add(ex);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/Serilog/Core/Sinks/ConditionalSink.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 Serilog Contributors
// Copyright 2019-2020 Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -15,7 +15,7 @@
using System;
using Serilog.Events;

namespace Serilog.Core.Enrichers
namespace Serilog.Core.Sinks
{
class ConditionalSink : ILogEventSink, IDisposable
{
Expand Down
41 changes: 41 additions & 0 deletions src/Serilog/Core/Sinks/DisposeDelegatingSink.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2020 Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using Serilog.Events;
using System;

namespace Serilog.Core.Sinks
{
class DisposeDelegatingSink : ILogEventSink, IDisposable
{
readonly ILogEventSink _sink;
readonly IDisposable _disposable;

public DisposeDelegatingSink(ILogEventSink sink, IDisposable disposable)
{
_sink = sink ?? throw new ArgumentNullException(nameof(sink));
_disposable = disposable ?? throw new ArgumentNullException(nameof(disposable));
}

public void Dispose()
{
_disposable.Dispose();
}

public void Emit(LogEvent logEvent)
{
_sink.Emit(logEvent);
}
}
}
73 changes: 73 additions & 0 deletions src/Serilog/Core/Sinks/DisposingAggregateSink.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright 2020 Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using Serilog.Debugging;
using System;
using System.Collections.Generic;
using System.Linq;
using Serilog.Events;

namespace Serilog.Core.Sinks
{
class DisposingAggregateSink : ILogEventSink, IDisposable
{
readonly ILogEventSink[] _sinks;

public DisposingAggregateSink(IEnumerable<ILogEventSink> sinks)
{
if (sinks == null) throw new ArgumentNullException(nameof(sinks));
_sinks = sinks.ToArray();
}

public void Emit(LogEvent logEvent)
{
List<Exception> exceptions = null;
foreach (var sink in _sinks)
{
try
{
sink.Emit(logEvent);
}
catch (Exception ex)
{
SelfLog.WriteLine("Caught exception while emitting to sink {0}: {1}", sink, ex);
exceptions ??= new List<Exception>();
exceptions.Add(ex);
}
}

if (exceptions != null)
throw new AggregateException("Failed to emit a log event.", exceptions);
}

public void Dispose()
{
if (_sinks == null) return;

foreach (var sink in _sinks)
{
if (!(sink is IDisposable disposable)) continue;

try
{
disposable.Dispose();
}
catch (Exception ex)
{
SelfLog.WriteLine("Caught exception while disposing sink {0}: {1}", sink, ex);
}
}
}
}
}
6 changes: 4 additions & 2 deletions src/Serilog/Core/Sinks/FilteringSink.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2013-2015 Serilog Contributors
// Copyright 2013-2020 Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -28,8 +28,10 @@ class FilteringSink : ILogEventSink

public FilteringSink(ILogEventSink sink, IEnumerable<ILogEventFilter> filters, bool propagateExceptions)
{
if (filters == null) throw new ArgumentNullException(nameof(filters));
_sink = sink ?? throw new ArgumentNullException(nameof(sink));
_filters = filters?.ToArray() ?? throw new ArgumentNullException(nameof(filters));

_filters = filters.ToArray();
_propagateExceptions = propagateExceptions;
}

Expand Down
2 changes: 1 addition & 1 deletion src/Serilog/Core/Sinks/RestrictedSink.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2013-2015 Serilog Contributors
// Copyright 2013-2020 Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down

0 comments on commit 1582b86

Please sign in to comment.