Skip to content

3.0.0 Release #145

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 32 commits into from
Aug 20, 2019
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
b6abdac
Upgraded Microsoft.Extensions.Logging NuGet packages to 2.0.0
DigiBanks99 Feb 7, 2019
7030b19
Proof-of-concept AddProvider() infrastructure
nblumhardt Feb 8, 2019
e94a240
Lean a bit more on IoC to wire up the factory and providers
nblumhardt Feb 8, 2019
5c7ee2a
Removed all netcore1.3 references and dependent code. Assumed netcore…
DigiBanks99 Feb 8, 2019
1ffaa7b
Use FormattedLogValues as the event state
nblumhardt Mar 14, 2019
17bc472
Merge branch 'dev' into dev
nblumhardt Apr 23, 2019
507cc4b
Dev version bump [skip ci]
nblumhardt Apr 23, 2019
3c27e7e
move to current sdk
SimonCropp Apr 24, 2019
cf57808
image: Visual Studio 2019 Preview
SimonCropp Apr 25, 2019
6c36af7
Update global.json
SimonCropp Apr 25, 2019
7332262
Merge pull request #138 from SimonCropp/patch-1
nblumhardt May 2, 2019
31d7194
Update NuGet API Key
merbla May 2, 2019
8a9e537
Merge branch 'dev' of https://github.com/serilog/serilog-extensions-l…
nblumhardt May 16, 2019
ad31fe8
Merge upstream/dev
nblumhardt May 16, 2019
6846f43
SerilogLogValues to clean up provision of TState; re-version as 3.0.0…
nblumhardt May 16, 2019
1b3b885
Typos/Cleanup
nblumhardt May 16, 2019
e11cf7e
Use an SDK version present on AppVeyor :-)
nblumhardt May 16, 2019
c950770
LangVersion
nblumhardt May 16, 2019
d2155ce
Add usual level control params to WriteTo.Providers()
nblumhardt May 16, 2019
79127bd
Merge pull request #132 from nblumhardt/add-provider
nblumhardt May 21, 2019
3ee6f65
Merge branch 'dev' into dev
nblumhardt May 21, 2019
e85c32f
Merge pull request #131 from DigiBanks99/dev
nblumhardt May 21, 2019
a9923ae
Remove some unused build-time constants
nblumhardt May 21, 2019
0885a2a
Keyboard fumble
nblumhardt May 21, 2019
7ba9559
Merge pull request #140 from nblumhardt/remove-constants
nblumhardt May 21, 2019
3f73c40
Make the level mapping routines public
nblumhardt May 21, 2019
29bdf6c
Merge pull request #141 from nblumhardt/public-level-mapping
nblumhardt May 21, 2019
95ab1c1
Update to use VS 2019 final image
nblumhardt Aug 19, 2019
e1a4780
Merge pull request #148 from nblumhardt/toolchain-update
adamchester Aug 19, 2019
8301b4e
Cache low-numbered numeric event ids to reduce allocations
nblumhardt May 21, 2019
40a2a2d
Add some basic benchmarks
nblumhardt Aug 20, 2019
11c3c07
Merge pull request #142 from nblumhardt/event-id-caching
adamchester Aug 20, 2019
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
4 changes: 2 additions & 2 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
version: '{build}'
skip_tags: true
image: Visual Studio 2017 Preview
image: Visual Studio 2019 Preview
configuration: Release
install:
- ps: mkdir -Force ".\build\" | Out-Null
Expand All @@ -16,7 +16,7 @@ artifacts:
deploy:
- provider: NuGet
api_key:
secure: bd9z4P73oltOXudAjPehwp9iDKsPtC+HbgshOrSgoyQKr5xVK+bxJQngrDJkHdY8
secure: N59tiJECUYpip6tEn0xvdmDAEiP9SIzyLEFLpwiigm/8WhJvBNs13QxzT1/3/JW/
skip_symbols: true
on:
branch: /^(master|dev)$/
Expand Down
1 change: 0 additions & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ dotnet --info
dotnet restore

for path in src/**/*.csproj; do
dotnet build -f netstandard1.3 -c Release ${path}
dotnet build -f netstandard2.0 -c Release ${path}

done
Expand Down
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"sdk": {
"version": "2.0.0-preview2-006497"
"version": "2.2.103"
}
}
31 changes: 24 additions & 7 deletions samples/Sample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,41 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Serilog;
using Serilog.Extensions.Logging;

namespace Sample
{
public class Program
{
public static void Main(string[] args)
{
// Creating a `LoggerProviderCollection` lets Serilog optionally write
// events through other dynamically-added MEL ILoggerProviders.
var providers = new LoggerProviderCollection();

Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.LiterateConsole()
.WriteTo.Console()
.WriteTo.Providers(providers)
.CreateLogger();

var services = new ServiceCollection()
.AddLogging(builder =>
{
builder.AddSerilog();
});
var services = new ServiceCollection();

services.AddSingleton(providers);
services.AddSingleton<ILoggerFactory>(sc =>
{
var providerCollection = sc.GetService<LoggerProviderCollection>();
var factory = new SerilogLoggerFactory(null, true, providerCollection);

foreach (var provider in sc.GetServices<ILoggerProvider>())
factory.AddProvider(provider);

return factory;
});

services.AddLogging(l => l.AddConsole());

var serviceProvider = services.BuildServiceProvider();
// getting the logger using the class's name is conventional
var logger = serviceProvider.GetRequiredService<ILogger<Program>>();

var startTime = DateTimeOffset.UtcNow;
Expand Down Expand Up @@ -57,6 +72,8 @@ public static void Main(string[] args)
logger.LogInformation("{Result,-10:l}{StartTime,15:l}{EndTime,15:l}{Duration,15:l}", "RESULT", "START TIME", "END TIME", "DURATION(ms)");
logger.LogInformation("{Result,-10:l}{StartTime,15:l}{EndTime,15:l}{Duration,15:l}", "------", "----- ----", "--- ----", "------------");
logger.LogInformation("{Result,-10:l}{StartTime,15:mm:s tt}{EndTime,15:mm:s tt}{Duration,15}", "SUCCESS", startTime, endTime, (endTime - startTime).TotalMilliseconds);

serviceProvider.Dispose();
}
}
}
5 changes: 3 additions & 2 deletions samples/Sample/Sample.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net461;netcoreapp2.0</TargetFrameworks>
<TargetFrameworks>netcoreapp2.0</TargetFrameworks>
<AssemblyName>Sample</AssemblyName>
<OutputType>Exe</OutputType>
<PackageId>Sample</PackageId>
Expand All @@ -14,7 +14,8 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" />
<PackageReference Include="Serilog.Sinks.Literate" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
</ItemGroup>

</Project>
7 changes: 7 additions & 0 deletions serilog-extensions-logging.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=destructure/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Destructurer/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=enricher/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=enrichers/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Nonscalar/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Serilog/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
81 changes: 81 additions & 0 deletions src/Serilog.Extensions.Logging/Extensions/Logging/LevelConvert.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright 2019 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 Microsoft.Extensions.Logging;
using Serilog.Events;

// ReSharper disable RedundantCaseLabel

namespace Serilog.Extensions.Logging
{
/// <summary>
/// Converts between Serilog and Microsoft.Extensions.Logging level enum values.
/// </summary>
public static class LevelConvert
{
/// <summary>
/// Convert <paramref name="logLevel"/> to the equivalent Serilog <see cref="LogEventLevel"/>.
/// </summary>
/// <param name="logLevel">A Microsoft.Extensions.Logging <see cref="LogLevel"/>.</param>
/// <returns>The Serilog equivalent of <paramref name="logLevel"/>.</returns>
/// <remarks>The <see cref="LogLevel.None"/> value has no Serilog equivalent. It is mapped to
/// <see cref="LogEventLevel.Fatal"/> as the closest approximation, but this has entirely
/// different semantics.</remarks>
public static LogEventLevel ToSerilogLevel(LogLevel logLevel)
{
switch (logLevel)
{
case LogLevel.None:
case LogLevel.Critical:
return LogEventLevel.Fatal;
case LogLevel.Error:
return LogEventLevel.Error;
case LogLevel.Warning:
return LogEventLevel.Warning;
case LogLevel.Information:
return LogEventLevel.Information;
case LogLevel.Debug:
return LogEventLevel.Debug;
case LogLevel.Trace:
default:
return LogEventLevel.Verbose;
}
}

/// <summary>
/// Convert <paramref name="logEventLevel"/> to the equivalent Microsoft.Extensions.Logging <see cref="LogLevel"/>.
/// </summary>
/// <param name="logEventLevel">A Serilog <see cref="LogEventLevel"/>.</param>
/// <returns>The Microsoft.Extensions.Logging equivalent of <paramref name="logEventLevel"/>.</returns>
public static LogLevel ToExtensionsLevel(LogEventLevel logEventLevel)
{
switch (logEventLevel)
{
case LogEventLevel.Fatal:
return LogLevel.Critical;
case LogEventLevel.Error:
return LogLevel.Error;
case LogEventLevel.Warning:
return LogLevel.Warning;
case LogEventLevel.Information:
return LogLevel.Information;
case LogEventLevel.Debug:
return LogLevel.Debug;
case LogEventLevel.Verbose:
default:
return LogLevel.Trace;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright 2019 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 System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Microsoft.Extensions.Logging;

namespace Serilog.Extensions.Logging
{
/// <summary>
/// A dynamically-modifiable collection of <see cref="ILoggerProvider"/>s.
/// </summary>
public class LoggerProviderCollection : IDisposable
{
volatile ILoggerProvider[] _providers = new ILoggerProvider[0];

/// <summary>
/// Add <paramref name="provider"/> to the collection.
/// </summary>
/// <param name="provider">A logger provider.</param>
public void AddProvider(ILoggerProvider provider)
{
if (provider == null) throw new ArgumentNullException(nameof(provider));

var existing = _providers;
var added = existing.Concat(new[] {provider}).ToArray();

#pragma warning disable 420 // ref to a volatile field
while (Interlocked.CompareExchange(ref _providers, added, existing) != existing)
#pragma warning restore 420
{
existing = _providers;
added = existing.Concat(new[] { provider }).ToArray();
}
}

/// <summary>
/// Get the currently-active providers.
/// </summary>
/// <remarks>
/// If the collection has been disposed, we'll leave the individual
/// providers with the job of throwing <see cref="ObjectDisposedException"/>.
/// </remarks>
public IEnumerable<ILoggerProvider> Providers => _providers;

/// <inheritdoc cref="IDisposable"/>
public void Dispose()
{
foreach (var provider in _providers)
provider.Dispose();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2019 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 System;
using Serilog.Core;
using Serilog.Events;

namespace Serilog.Extensions.Logging
{
class LoggerProviderCollectionSink : ILogEventSink, IDisposable
{
readonly LoggerProviderCollection _providers;

public LoggerProviderCollectionSink(LoggerProviderCollection providers)
{
_providers = providers ?? throw new ArgumentNullException(nameof(providers));
}

public void Emit(LogEvent logEvent)
{
string categoryName = null;

if (logEvent.Properties.TryGetValue("SourceContext", out var sourceContextProperty) &&
sourceContextProperty is ScalarValue sourceContextValue &&
sourceContextValue.Value is string sourceContext)
{
categoryName = sourceContext;
}

var level = LevelConvert.ToExtensionsLevel(logEvent.Level);
var slv = new SerilogLogValues(logEvent.MessageTemplate, logEvent.Properties);

foreach (var provider in _providers.Providers)
{
var logger = provider.CreateLogger(categoryName);

logger.Log(
level,
default,
slv,
logEvent.Exception,
(s, e) => s.ToString());
}
}

public void Dispose()
{
_providers.Dispose();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2019 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;
using System.Collections;
using System.Collections.Generic;

namespace Serilog.Extensions.Logging
{
readonly struct SerilogLogValues : IReadOnlyList<KeyValuePair<string, object>>
{
// Note, this struct is only used in a very limited context internally, so we ignore
// the possibility of fields being null via the default struct initialization.

private readonly MessageTemplate _messageTemplate;
private readonly IReadOnlyDictionary<string, LogEventPropertyValue> _properties;
private readonly KeyValuePair<string, object>[] _values;

public SerilogLogValues(MessageTemplate messageTemplate, IReadOnlyDictionary<string, LogEventPropertyValue> properties)
{
_messageTemplate = messageTemplate ?? throw new ArgumentNullException(nameof(messageTemplate));

// The dictionary is needed for rendering through the message template
_properties = properties ?? throw new ArgumentNullException(nameof(properties));

// The array is needed because the IReadOnlyList<T> interface expects indexed access
_values = new KeyValuePair<string, object>[_properties.Count + 1];
var i = 0;
foreach (var p in properties)
{
_values[i] = new KeyValuePair<string, object>(p.Key, (p.Value is ScalarValue sv) ? sv.Value : p.Value);
++i;
}
_values[i] = new KeyValuePair<string, object>("{OriginalFormat}", _messageTemplate.Text);
}

public KeyValuePair<string, object> this[int index]
{
get => _values[index];
}

public int Count => _properties.Count + 1;

public IEnumerator<KeyValuePair<string, object>> GetEnumerator() => ((IEnumerable<KeyValuePair<string, object>>)_values).GetEnumerator();

public override string ToString() => _messageTemplate.Render(_properties);

IEnumerator IEnumerable.GetEnumerator() => _values.GetEnumerator();
}
}
Loading