From 015d4f72706a64fa0ae4604c80a2e65a96542015 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Thu, 22 Aug 2019 09:06:50 +1000 Subject: [PATCH 01/23] Dev version bump [skip ci] --- .../Serilog.Extensions.Logging.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj b/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj index 9a3e564..c73c885 100644 --- a/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj +++ b/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj @@ -2,7 +2,7 @@ Low-level Serilog provider for Microsoft.Extensions.Logging - 3.0.1 + 3.0.2 Microsoft;Serilog Contributors netstandard2.0 true From 54ff29af57c4173adf66fe26a8a852707ee9f15b Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Tue, 3 Sep 2019 17:47:52 +0300 Subject: [PATCH 02/23] small fixes --- .../Extensions/Logging/LoggerProviderCollection.cs | 12 ++++++------ .../Extensions/Logging/SerilogLoggerProvider.cs | 3 +-- .../Extensions/Logging/SerilogLoggerScope.cs | 5 ++--- .../SerilogLoggerFactoryExtensions.cs | 2 +- .../SerilogLoggingBuilderExtensions.cs | 2 +- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/Serilog.Extensions.Logging/Extensions/Logging/LoggerProviderCollection.cs b/src/Serilog.Extensions.Logging/Extensions/Logging/LoggerProviderCollection.cs index 6ecb000..7a0e08b 100644 --- a/src/Serilog.Extensions.Logging/Extensions/Logging/LoggerProviderCollection.cs +++ b/src/Serilog.Extensions.Logging/Extensions/Logging/LoggerProviderCollection.cs @@ -26,7 +26,7 @@ namespace Serilog.Extensions.Logging /// public class LoggerProviderCollection : IDisposable { - volatile ILoggerProvider[] _providers = new ILoggerProvider[0]; + volatile ILoggerProvider[] _providers = Array.Empty(); /// /// Add to the collection. @@ -36,16 +36,16 @@ public void AddProvider(ILoggerProvider provider) { if (provider == null) throw new ArgumentNullException(nameof(provider)); - var existing = _providers; - var added = existing.Concat(new[] {provider}).ToArray(); + ILoggerProvider[] existing, added; -#pragma warning disable 420 // ref to a volatile field - while (Interlocked.CompareExchange(ref _providers, added, existing) != existing) -#pragma warning restore 420 + do { existing = _providers; 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 } /// diff --git a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerProvider.cs b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerProvider.cs index f4daf8a..d51c2c0 100644 --- a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerProvider.cs +++ b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerProvider.cs @@ -69,8 +69,7 @@ public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) List scopeItems = null; for (var scope = CurrentScope; scope != null; scope = scope.Parent) { - LogEventPropertyValue scopeItem; - scope.EnrichAndCreateScopeItem(logEvent, propertyFactory, out scopeItem); + scope.EnrichAndCreateScopeItem(logEvent, propertyFactory, out LogEventPropertyValue scopeItem); if (scopeItem != null) { diff --git a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerScope.cs b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerScope.cs index 424d459..045359a 100644 --- a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerScope.cs +++ b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerScope.cs @@ -57,8 +57,7 @@ public void EnrichAndCreateScopeItem(LogEvent logEvent, ILogEventPropertyFactory return; } - var stateProperties = _state as IEnumerable>; - if (stateProperties != null) + if (_state is IEnumerable> stateProperties) { scopeItem = null; // Unless it's `FormattedLogValues`, these are treated as property bags rather than scope items. @@ -78,7 +77,7 @@ public void EnrichAndCreateScopeItem(LogEvent logEvent, ILogEventPropertyFactory key = key.Substring(1); destructureObject = true; } - + var property = propertyFactory.CreateProperty(key, stateProperty.Value, destructureObject); logEvent.AddPropertyIfAbsent(property); } diff --git a/src/Serilog.Extensions.Logging/SerilogLoggerFactoryExtensions.cs b/src/Serilog.Extensions.Logging/SerilogLoggerFactoryExtensions.cs index c2aa06d..5292603 100644 --- a/src/Serilog.Extensions.Logging/SerilogLoggerFactoryExtensions.cs +++ b/src/Serilog.Extensions.Logging/SerilogLoggerFactoryExtensions.cs @@ -20,7 +20,7 @@ public static class SerilogLoggerFactoryExtensions /// When true, dispose when the framework disposes the provider. If the /// logger is not specified but is true, the method will be /// called on the static class instead. - /// The logger factory. + /// Reference to the supplied . public static ILoggerFactory AddSerilog( this ILoggerFactory factory, ILogger logger = null, diff --git a/src/Serilog.Extensions.Logging/SerilogLoggingBuilderExtensions.cs b/src/Serilog.Extensions.Logging/SerilogLoggingBuilderExtensions.cs index 27bb6dd..2cf0008 100644 --- a/src/Serilog.Extensions.Logging/SerilogLoggingBuilderExtensions.cs +++ b/src/Serilog.Extensions.Logging/SerilogLoggingBuilderExtensions.cs @@ -32,7 +32,7 @@ public static class SerilogLoggingBuilderExtensions /// When true, dispose when the framework disposes the provider. If the /// logger is not specified but is true, the method will be /// called on the static class instead. - /// The logger factory. + /// Reference to the supplied . public static ILoggingBuilder AddSerilog(this ILoggingBuilder builder, ILogger logger = null, bool dispose = false) { if (builder == null) throw new ArgumentNullException(nameof(builder)); From d104db27fa961abcd19498f2c4ffa9c0f368d3ff Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Fri, 20 Sep 2019 14:04:44 +1000 Subject: [PATCH 03/23] Fixes #154 - changes now tracked via /releases. --- CHANGES.md | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 CHANGES.md diff --git a/CHANGES.md b/CHANGES.md deleted file mode 100644 index cb900c4..0000000 --- a/CHANGES.md +++ /dev/null @@ -1,12 +0,0 @@ -1.2.0 - - * #45 - Make the provider type public so that it can be embedded more easily in other providers - -1.1.0 - - * #41 - Provide a `dispose` flag to instruct provider to take ownership of the Serilog logger - -1.0.0 - - * Initial version - From b43f68eb0b92118b46066fa72fdc925ef0e4b158 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Thu, 3 Oct 2019 19:18:56 +0100 Subject: [PATCH 04/23] Replace deprecated PackageLicenseUrl --- .../Serilog.Extensions.Logging.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj b/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj index c73c885..1bd5926 100644 --- a/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj +++ b/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj @@ -15,7 +15,7 @@ serilog;Microsoft.Extensions.Logging http://serilog.net/images/serilog-extension-nuget.png https://github.com/serilog/serilog-extensions-logging - http://www.apache.org/licenses/LICENSE-2.0 + Apache-2.0 https://github.com/serilog/serilog-extensions-logging git false From 7e827a64415eeaa2151ef30ff1cf03c73dad22fb Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Thu, 3 Oct 2019 19:19:24 +0100 Subject: [PATCH 05/23] Replace deprecated PackageIcon --- assets/serilog-extension-nuget.png | Bin 0 -> 6006 bytes .../Serilog.Extensions.Logging.csproj | 6 +++++- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 assets/serilog-extension-nuget.png diff --git a/assets/serilog-extension-nuget.png b/assets/serilog-extension-nuget.png new file mode 100644 index 0000000000000000000000000000000000000000..75e36fb31108c7efe3ae8716841123fccbf1f8a6 GIT binary patch literal 6006 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 k*@w&#KAtcEtrue Serilog.Extensions.Logging serilog;Microsoft.Extensions.Logging - http://serilog.net/images/serilog-extension-nuget.png + serilog-extension-nuget.png https://github.com/serilog/serilog-extensions-logging Apache-2.0 https://github.com/serilog/serilog-extensions-logging @@ -23,6 +23,10 @@ 7.3 + + + + From 6982c963f655ad807f62467c5bb730ec33f6a4a2 Mon Sep 17 00:00:00 2001 From: Johannes Bickel Date: Thu, 28 Nov 2019 11:46:32 +0100 Subject: [PATCH 06/23] added stringification support --- .../Extensions/Logging/SerilogLogger.cs | 5 +++++ .../SerilogLoggerTests.cs | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs index 007e73d..e88a444 100644 --- a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs +++ b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs @@ -78,6 +78,11 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except if (logger.BindProperty(property.Key.Substring(1), property.Value, true, out var destructured)) properties.Add(destructured); } + else if (property.Key.StartsWith("$")) + { + if (logger.BindProperty(property.Key.Substring(1), property.Value?.ToString() ?? "null", true, out var stringified)) + properties.Add(stringified); + } else { if (logger.BindProperty(property.Key, property.Value, false, out var bound)) diff --git a/test/Serilog.Extensions.Logging.Tests/SerilogLoggerTests.cs b/test/Serilog.Extensions.Logging.Tests/SerilogLoggerTests.cs index d2d5bac..e255117 100644 --- a/test/Serilog.Extensions.Logging.Tests/SerilogLoggerTests.cs +++ b/test/Serilog.Extensions.Logging.Tests/SerilogLoggerTests.cs @@ -219,6 +219,24 @@ public void CarriesMessageTemplateProperties() Assert.Empty(selfLog.ToString()); } + [Fact] + public void CarriesMessageTemplatePropertiesWhenStringificationIsUsed() + { + var selfLog = new StringWriter(); + SelfLog.Enable(selfLog); + var (logger, sink) = SetUp(LogLevel.Trace); + var array = new[] { 1, 2, 3, 4 }; + + logger.LogInformation("{$array}", array); + + Assert.True(sink.Writes[0].Properties.ContainsKey("array")); + Assert.Equal("\"System.Int32[]\"", sink.Writes[0].Properties["array"].ToString()); + Assert.Equal("{$array}", sink.Writes[0].MessageTemplate.Text); + + SelfLog.Disable(); + Assert.Empty(selfLog.ToString()); + } + [Fact] public void CarriesEventIdIfNonzero() { From b201aba786de99ca6a6f577068a002e2d04f8d44 Mon Sep 17 00:00:00 2001 From: Johannes Bickel Date: Fri, 29 Nov 2019 10:37:32 +0100 Subject: [PATCH 07/23] pass null instead of text "null" --- .../Extensions/Logging/SerilogLogger.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs index e88a444..30a46e5 100644 --- a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs +++ b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs @@ -80,7 +80,7 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except } else if (property.Key.StartsWith("$")) { - if (logger.BindProperty(property.Key.Substring(1), property.Value?.ToString() ?? "null", true, out var stringified)) + if (logger.BindProperty(property.Key.Substring(1), property.Value?.ToString(), true, out var stringified)) properties.Add(stringified); } else From 73671f867044aebc18a7fafd99ebe058d44f109d Mon Sep 17 00:00:00 2001 From: Johannes Bickel Date: Thu, 5 Dec 2019 16:58:44 +0100 Subject: [PATCH 08/23] remove $ from key in logger scope to support "force stringify" --- .../Extensions/Logging/SerilogLoggerScope.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerScope.cs b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerScope.cs index 045359a..f1abc8e 100644 --- a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerScope.cs +++ b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerScope.cs @@ -78,6 +78,11 @@ public void EnrichAndCreateScopeItem(LogEvent logEvent, ILogEventPropertyFactory destructureObject = true; } + if (key.StartsWith("$")) + { + key = key.Substring(1); + } + var property = propertyFactory.CreateProperty(key, stateProperty.Value, destructureObject); logEvent.AddPropertyIfAbsent(property); } From 8428510de3e044615cee399892bfc7c19ee4ed1f Mon Sep 17 00:00:00 2001 From: Johannes Bickel Date: Wed, 11 Dec 2019 07:51:59 +0100 Subject: [PATCH 09/23] fixed stringify support in logger scope --- .../Extensions/Logging/SerilogLoggerScope.cs | 4 +++- .../SerilogLoggerTests.cs | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerScope.cs b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerScope.cs index f1abc8e..dd0803c 100644 --- a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerScope.cs +++ b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerScope.cs @@ -71,6 +71,7 @@ public void EnrichAndCreateScopeItem(LogEvent logEvent, ILogEventPropertyFactory var key = stateProperty.Key; var destructureObject = false; + var value = stateProperty.Value; if (key.StartsWith("@")) { @@ -81,9 +82,10 @@ public void EnrichAndCreateScopeItem(LogEvent logEvent, ILogEventPropertyFactory if (key.StartsWith("$")) { key = key.Substring(1); + value = value?.ToString(); } - var property = propertyFactory.CreateProperty(key, stateProperty.Value, destructureObject); + var property = propertyFactory.CreateProperty(key, value, destructureObject); logEvent.AddPropertyIfAbsent(property); } } diff --git a/test/Serilog.Extensions.Logging.Tests/SerilogLoggerTests.cs b/test/Serilog.Extensions.Logging.Tests/SerilogLoggerTests.cs index e255117..5baadf7 100644 --- a/test/Serilog.Extensions.Logging.Tests/SerilogLoggerTests.cs +++ b/test/Serilog.Extensions.Logging.Tests/SerilogLoggerTests.cs @@ -162,6 +162,21 @@ public void SingleScopeProperty() Assert.Equal("\"pizza\"", sink.Writes[0].Properties["Name"].ToString()); } + [Fact] + public void StringifyScopeProperty() + { + var (logger, sink) = SetUp(LogLevel.Trace); + + using (logger.BeginScope("{$values}", new int[] { 1, 2, 3, 4 })) + { + logger.Log(LogLevel.Information, 0, TestMessage, null, null); + } + + Assert.Equal(1, sink.Writes.Count); + Assert.True(sink.Writes[0].Properties.ContainsKey("values")); + Assert.Equal("\"System.Int32[]\"", sink.Writes[0].Properties["values"].ToString()); + } + [Fact] public void NestedScopeSameProperty() { From 09aa8eda4b9280ba8b41875cf75df57be5ab1792 Mon Sep 17 00:00:00 2001 From: Ralph Hendriks Date: Mon, 24 Feb 2020 10:01:43 +0100 Subject: [PATCH 10/23] Pin .NET Core SDK version to latest feature band Pin the .NET Core SDK version to the `3.1.1xx` feature band. Do not allow prerelease versions. Also, since C# 7.3 is the default language version for `netstandard2.0`, it is not necessary to explicitly specify it. --- global.json | 6 ++++-- .../Serilog.Extensions.Logging.csproj | 1 - 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/global.json b/global.json index 6b64107..5442449 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,7 @@ { "sdk": { - "version": "2.2.103" + "allowPrerelease": false, + "version": "3.1.100", + "rollForward": "latestPatch" } -} +} \ No newline at end of file diff --git a/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj b/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj index 7dd16b1..8acb829 100644 --- a/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj +++ b/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj @@ -20,7 +20,6 @@ git false Serilog - 7.3 From ef999bdd6c0d5f451756c899fb60aae6ec84b9c6 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Tue, 25 Feb 2020 11:21:01 +1000 Subject: [PATCH 11/23] Use caching message template parser --- .../Logging/CachingMessageTemplateParser.cs | 67 +++++++++++++++++++ .../Extensions/Logging/SerilogLogger.cs | 5 +- 2 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 src/Serilog.Extensions.Logging/Extensions/Logging/CachingMessageTemplateParser.cs diff --git a/src/Serilog.Extensions.Logging/Extensions/Logging/CachingMessageTemplateParser.cs b/src/Serilog.Extensions.Logging/Extensions/Logging/CachingMessageTemplateParser.cs new file mode 100644 index 0000000..d47e84f --- /dev/null +++ b/src/Serilog.Extensions.Logging/Extensions/Logging/CachingMessageTemplateParser.cs @@ -0,0 +1,67 @@ +// Copyright (c) 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.Events; +using Serilog.Parsing; +using System.Collections; + +namespace Serilog.Extensions.Logging +{ + class CachingMessageTemplateParser + { + readonly MessageTemplateParser _innerParser = new MessageTemplateParser(); + + readonly object _templatesLock = new object(); + readonly Hashtable _templates = new Hashtable(); + + const int MaxCacheItems = 1000; + const int MaxCachedTemplateLength = 1024; + + public MessageTemplate Parse(string messageTemplate) + { + if (messageTemplate == null) throw new ArgumentNullException(nameof(messageTemplate)); + + if (messageTemplate.Length > MaxCachedTemplateLength) + return _innerParser.Parse(messageTemplate); + + // ReSharper disable once InconsistentlySynchronizedField + // ignored warning because this is by design + var result = (MessageTemplate)_templates[messageTemplate]; + if (result != null) + return result; + + result = _innerParser.Parse(messageTemplate); + + lock (_templatesLock) + { + // Exceeding MaxCacheItems is *not* the sunny day scenario; all we're doing here is preventing out-of-memory + // conditions when the library is used incorrectly. Correct use (templates, rather than + // direct message strings) should barely, if ever, overflow this cache. + + // Changing workloads through the lifecycle of an app instance mean we can gain some ground by + // potentially dropping templates generated only in startup, or only during specific infrequent + // activities. + + if (_templates.Count == MaxCacheItems) + _templates.Clear(); + + _templates[messageTemplate] = result; + } + + return result; + } + } +} diff --git a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs index 30a46e5..ba549ae 100644 --- a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs +++ b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs @@ -9,7 +9,6 @@ using Serilog.Events; using FrameworkLogger = Microsoft.Extensions.Logging.ILogger; using System.Reflection; -using Serilog.Parsing; namespace Serilog.Extensions.Logging { @@ -18,7 +17,7 @@ class SerilogLogger : FrameworkLogger readonly SerilogLoggerProvider _provider; readonly ILogger _logger; - static readonly MessageTemplateParser MessageTemplateParser = new MessageTemplateParser(); + static readonly CachingMessageTemplateParser MessageTemplateParser = new CachingMessageTemplateParser(); // It's rare to see large event ids, as they are category-specific static readonly LogEventProperty[] LowEventIdValues = Enumerable.Range(0, 48) @@ -159,4 +158,4 @@ internal static LogEventProperty CreateEventIdProperty(EventId eventId) return new LogEventProperty("EventId", new StructureValue(properties)); } } -} \ No newline at end of file +} From cf6caad359b83fec77786842aa208c3f41cfd150 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Tue, 25 Feb 2020 11:40:31 +1000 Subject: [PATCH 12/23] Resolves #164 - suppress exceptions from FormattedLogValues --- serilog-extensions-logging.sln.DotSettings | 3 ++- .../Extensions/Logging/SerilogLogger.cs | 13 +++++++++++++ .../SerilogLoggerTests.cs | 13 ++++++++++++- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/serilog-extensions-logging.sln.DotSettings b/serilog-extensions-logging.sln.DotSettings index 4009815..c2fd9da 100644 --- a/serilog-extensions-logging.sln.DotSettings +++ b/serilog-extensions-logging.sln.DotSettings @@ -8,4 +8,5 @@ True True True - True \ No newline at end of file + True + True \ No newline at end of file diff --git a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs index 30a46e5..77f357a 100644 --- a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs +++ b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs @@ -9,6 +9,7 @@ using Serilog.Events; using FrameworkLogger = Microsoft.Extensions.Logging.ILogger; using System.Reflection; +using Serilog.Debugging; using Serilog.Parsing; namespace Serilog.Extensions.Logging @@ -60,6 +61,18 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except return; } + try + { + Write(level, eventId, state, exception, formatter); + } + catch (Exception ex) + { + SelfLog.WriteLine($"Failed to write event through {typeof(SerilogLogger).Name}: {ex}"); + } + } + + void Write(LogEventLevel level, EventId eventId, TState state, Exception exception, Func formatter) + { var logger = _logger; string messageTemplate = null; diff --git a/test/Serilog.Extensions.Logging.Tests/SerilogLoggerTests.cs b/test/Serilog.Extensions.Logging.Tests/SerilogLoggerTests.cs index 5baadf7..f37e9eb 100644 --- a/test/Serilog.Extensions.Logging.Tests/SerilogLoggerTests.cs +++ b/test/Serilog.Extensions.Logging.Tests/SerilogLoggerTests.cs @@ -167,7 +167,7 @@ public void StringifyScopeProperty() { var (logger, sink) = SetUp(LogLevel.Trace); - using (logger.BeginScope("{$values}", new int[] { 1, 2, 3, 4 })) + using (logger.BeginScope("{$values}", new [] { 1, 2, 3, 4 })) { logger.Log(LogLevel.Information, 0, TestMessage, null, null); } @@ -272,6 +272,7 @@ public void CarriesEventIdIfNonzero() public void WhenDisposeIsFalseProvidedLoggerIsNotDisposed() { var logger = new DisposeTrackingLogger(); + // ReSharper disable once RedundantArgumentDefaultValue var provider = new SerilogLoggerProvider(logger, false); provider.Dispose(); Assert.False(logger.IsDisposed); @@ -439,5 +440,15 @@ public void LowAndHighNumberedEventIdsAreMapped(int id) var scalar = Assert.IsType(idValue); Assert.Equal(id, scalar.Value); } + + [Fact] + public void MismatchedMessageTemplateParameterCountIsHandled() + { + var (logger, sink) = SetUp(LogLevel.Trace); + + logger.LogInformation("Some test message with {Two} {Properties}", "OneProperty"); + + Assert.Equal(0, sink.Writes.Count); + } } } From 430dde19fc8e4e2f9f9fbafc2713a2453285d03b Mon Sep 17 00:00:00 2001 From: Sergey Komisarchik Date: Thu, 14 May 2020 02:09:47 +0300 Subject: [PATCH 13/23] Use `latestFeature` in global.json --- global.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/global.json b/global.json index 5442449..e3bbb00 100644 --- a/global.json +++ b/global.json @@ -2,6 +2,6 @@ "sdk": { "allowPrerelease": false, "version": "3.1.100", - "rollForward": "latestPatch" + "rollForward": "latestFeature" } -} \ No newline at end of file +} From 282cefbd69dcf229953052d8cbefc2e3214ab43e Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Thu, 14 May 2020 10:13:27 +1000 Subject: [PATCH 14/23] Update NuGet.org publishing key --- appveyor.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index dc593a6..5d78f48 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,13 +1,8 @@ version: '{build}' skip_tags: true image: Visual Studio 2019 -configuration: Release install: - ps: mkdir -Force ".\build\" | Out-Null - #- ps: Invoke-WebRequest "https://raw.githubusercontent.com/dotnet/cli/release/2.0.0/scripts/obtain/dotnet-install.ps1" -OutFile ".\build\installcli.ps1" - #- ps: $env:DOTNET_INSTALL_DIR = "$pwd\.dotnetcli" - #- ps: '& .\build\installcli.ps1 -InstallDir "$env:DOTNET_INSTALL_DIR" -NoPath -Version 2.0.0-preview2-006497' - #- ps: $env:Path = "$env:DOTNET_INSTALL_DIR;$env:Path" build_script: - ps: ./Build.ps1 test: off @@ -16,7 +11,7 @@ artifacts: deploy: - provider: NuGet api_key: - secure: N59tiJECUYpip6tEn0xvdmDAEiP9SIzyLEFLpwiigm/8WhJvBNs13QxzT1/3/JW/ + secure: JAnOxPQMZRp8ousbAW4vYnVtd936AOMp4gDGucCQ1RZrDZW3J+X5QmbLO7OJKtBr skip_symbols: true on: branch: /^(master|dev)$/ From babc23b554bc96be5069f8c925456c6a2e11044f Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Thu, 14 May 2020 10:16:49 +1000 Subject: [PATCH 15/23] Another attempt at a working publishing key --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 5d78f48..488ef26 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,7 +11,7 @@ artifacts: deploy: - provider: NuGet api_key: - secure: JAnOxPQMZRp8ousbAW4vYnVtd936AOMp4gDGucCQ1RZrDZW3J+X5QmbLO7OJKtBr + secure: AA0wV/Jk8R7whwsYtDti4DvUdeQLWVPGJlGjguRr9TRw1dW13cuMCPnSEzSfGzCI skip_symbols: true on: branch: /^(master|dev)$/ From c7560378d33e650974a6e9ea5ea45ef7d39b1ac4 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Mon, 3 Aug 2020 08:43:59 +1000 Subject: [PATCH 16/23] Update README to point to Serilog.Extensions.Hosting - fixes #180 --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fe2934f..4758f5e 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,14 @@ # Serilog.Extensions.Logging [![Build status](https://ci.appveyor.com/api/projects/status/865nohxfiq1rnby0/branch/master?svg=true)](https://ci.appveyor.com/project/serilog/serilog-framework-logging/history) [![NuGet Version](http://img.shields.io/nuget/v/Serilog.Extensions.Logging.svg?style=flat)](https://www.nuget.org/packages/Serilog.Extensions.Logging/) - A Serilog provider for [Microsoft.Extensions.Logging](https://www.nuget.org/packages/Microsoft.Extensions.Logging), the logging subsystem used by ASP.NET Core. -### ASP.NET Core 2.0+ Instructions +### ASP.NET Core Instructions + +**ASP.NET Core** applications should prefer [Serilog.AspNetCore](https://github.com/serilog/serilog-aspnetcore) and `UseSerilog()` instead. + +### Non-web .NET Core Instructions -**ASP.NET Core 2.0** applications should prefer [Serilog.AspNetCore](https://github.com/serilog/serilog-aspnetcore) and `UseSerilog()` instead. +**Non-web .NET Core 2.0** applications should prefer [Serilog.Extensions.Hosting](https://github.com/serilog/serilog-extensions-hosting) and `UseSerilog()` instead. ### .NET Core 1.0, 1.1 and Default Provider Integration From 7fa8d7cd53295f3ede9851234baf4ecb247aace9 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Mon, 3 Aug 2020 08:45:03 +1000 Subject: [PATCH 17/23] Tiny README fix [skip ci] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4758f5e..2dbb39d 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A Serilog provider for [Microsoft.Extensions.Logging](https://www.nuget.org/pack ### Non-web .NET Core Instructions -**Non-web .NET Core 2.0** applications should prefer [Serilog.Extensions.Hosting](https://github.com/serilog/serilog-extensions-hosting) and `UseSerilog()` instead. +**Non-web .NET Core** applications should prefer [Serilog.Extensions.Hosting](https://github.com/serilog/serilog-extensions-hosting) and `UseSerilog()` instead. ### .NET Core 1.0, 1.1 and Default Provider Integration From a7c57d13495fd61c3c4c11fb309c1d1358f9d018 Mon Sep 17 00:00:00 2001 From: Dan Vicarel Date: Mon, 9 Nov 2020 13:14:51 -0500 Subject: [PATCH 18/23] Added notes about Log Scope usage to README The ability to pass any `IEnumerable>` to `ILogger.BeginScope` is an _extremely_ useful feature, but unfortunately it doesn't seem to be officially documented anywhere. I only discovered it while digging through this repo's source code! I assume this repo is the correct location for this information, as it only applies when one is using both Serilog and the _Microsoft.Extensions.Logging_ library, but I could see where it might be better off in the Serilog wiki. Looking forward to your feedback! --- README.md | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/README.md b/README.md index 2dbb39d..de78765 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,69 @@ That's it! With the level bumped up a little you should see log output like: [22:14:45.741 DBG] Handled. Status code: 304 File: /css/site.css ``` +### Notes on Log Scopes + +_Microsoft.Extensions.Logging_ provides the `BeginScope` API, which can be used to add arbitrary properties to log events within a certain region of code. The API comes in two forms: + +1. The method: `IDisposable BeginScope(TState state)` +2. The extension method: `IDisposable BeginScope(this ILogger logger, string messageFormat, params object[] args)` + +Using the extension method will add a `Scope` property to your log events. This is most useful for adding simple "scope strings" to your events, as in the following code: + +```cs +using (_logger.BeginScope("Transaction")) { + _logger.LogInformation("Beginning..."); + _logger.LogInformation("Completed in {DurationMs}ms...", 30); +} +// Example JSON output: +// {"@t":"2020-10-29T19:05:56.4126822Z","@m":"Beginning...","@i":"f6a328e9","SourceContext":"SomeNamespace.SomeService","Scope":["Transaction"]} +// {"@t":"2020-10-29T19:05:56.4176816Z","@m":"Completed in 30ms...","@i":"51812baa","DurationMs":30,"SourceContext":"SomeNamespace.SomeService","Scope":["Transaction"]} +``` + +If you simply want to add a "bag" of additional properties to your log events, however, this extension method approach can be overly verbose. For example, to add `TransactionId` and `ResponseJson` properties to your log events, you would have to do something like the following: + +```cs +// WRONG! Prefer the dictionary approach below instead +using (_logger.BeginScope("TransactionId: {TransactionId}, ResponseJson: {ResponseJson}", 12345, jsonString)) { + _logger.LogInformation("Completed in {DurationMs}ms...", 30); +} +// Example JSON output: +// { +// "@t":"2020-10-29T19:05:56.4176816Z", +// "@m":"Completed in 30ms...", +// "@i":"51812baa", +// "DurationMs":30, +// "SourceContext":"SomeNamespace.SomeService", +// "TransactionId": 12345, +// "ResponseJson": "{ \"Key1\": \"Value1\", \"Key2\": \"Value2\" }", +// "Scope":["TransactionId: 12345, ResponseJson: { \"Key1\": \"Value1\", \"Key2\": \"Value2\" }"] +// } +``` + +Not only does this add the unnecessary `Scope` property to your event, but it also duplicates serialized values between `Scope` and the intended properties, as you can see here with `ResponseJson`. If this were "real" JSON like an API response, then a potentially very large block of text would be duplicated within your log event! Moreover, the template string within `BeginScope` is rather arbitrary when all you want to do is add a bag of properties, and you start mixing enriching concerns with formatting concerns. + +A far better alternative is to use the `BeginScope(TState state)` method. If you provide any `IEnumerable>` to this method, then we will output the key/value pairs as structured properties _without_ the `Scope` property, as in this example: + +```cs +var scopeProps = new Dictionary { + { "TransactionId", 12345 }, + { "ResponseJson", jsonString }, +}; +using (_logger.BeginScope(scopeProps) { + _logger.LogInformation("Transaction completed in {DurationMs}ms...", 30); +} +// Example JSON output: +// { +// "@t":"2020-10-29T19:05:56.4176816Z", +// "@m":"Completed in 30ms...", +// "@i":"51812baa", +// "DurationMs":30, +// "SourceContext":"SomeNamespace.SomeService", +// "TransactionId": 12345, +// "ResponseJson": "{ \"Key1\": \"Value1\", \"Key2\": \"Value2\" }" +// } +``` + ### Credits This package evolved from an earlier package _Microsoft.Framework.Logging.Serilog_ [provided by the ASP.NET team](https://github.com/aspnet/Logging/pull/182). From 792e72376e45df312e9a8bc8f9d7a9802af1167f Mon Sep 17 00:00:00 2001 From: Dan Vicarel Date: Mon, 9 Nov 2020 16:51:18 -0500 Subject: [PATCH 19/23] Tweaked some wording in the Log Scope notes, per review --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index de78765..905fc55 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,7 @@ using (_logger.BeginScope("TransactionId: {TransactionId}, ResponseJson: {Respon Not only does this add the unnecessary `Scope` property to your event, but it also duplicates serialized values between `Scope` and the intended properties, as you can see here with `ResponseJson`. If this were "real" JSON like an API response, then a potentially very large block of text would be duplicated within your log event! Moreover, the template string within `BeginScope` is rather arbitrary when all you want to do is add a bag of properties, and you start mixing enriching concerns with formatting concerns. -A far better alternative is to use the `BeginScope(TState state)` method. If you provide any `IEnumerable>` to this method, then we will output the key/value pairs as structured properties _without_ the `Scope` property, as in this example: +A far better alternative is to use the `BeginScope(TState state)` method. If you provide any `IEnumerable>` to this method, then Serilog will output the key/value pairs as structured properties _without_ the `Scope` property, as in this example: ```cs var scopeProps = new Dictionary { From 5dbeb54d6f6f114d051f25f0275941b629751f5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Borja=20Dom=C3=ADnguez?= Date: Wed, 5 May 2021 18:17:48 +0200 Subject: [PATCH 20/23] Bump Serilog version dependency --- .../Serilog.Extensions.Logging.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj b/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj index 8acb829..a67b319 100644 --- a/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj +++ b/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj @@ -27,7 +27,7 @@ - + From a3139b8e59f584dec7bfdbfc4fa16b920a45a67b Mon Sep 17 00:00:00 2001 From: David Driscoll Date: Mon, 17 May 2021 17:28:18 -0400 Subject: [PATCH 21/23] Added EventId hydration if it was defined --- .../Logging/LoggerProviderCollectionSink.cs | 16 +++- .../LoggerProviderCollectionSinkTests.cs | 85 +++++++++++++++++++ .../Support/ExtensionsProvider.cs | 45 ++++++++++ 3 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 test/Serilog.Extensions.Logging.Tests/LoggerProviderCollectionSinkTests.cs create mode 100644 test/Serilog.Extensions.Logging.Tests/Support/ExtensionsProvider.cs diff --git a/src/Serilog.Extensions.Logging/Extensions/Logging/LoggerProviderCollectionSink.cs b/src/Serilog.Extensions.Logging/Extensions/Logging/LoggerProviderCollectionSink.cs index 94838ea..afe4a29 100644 --- a/src/Serilog.Extensions.Logging/Extensions/Logging/LoggerProviderCollectionSink.cs +++ b/src/Serilog.Extensions.Logging/Extensions/Logging/LoggerProviderCollectionSink.cs @@ -13,6 +13,7 @@ // limitations under the License. using System; +using Microsoft.Extensions.Logging; using Serilog.Core; using Serilog.Events; @@ -30,6 +31,7 @@ public LoggerProviderCollectionSink(LoggerProviderCollection providers) public void Emit(LogEvent logEvent) { string categoryName = null; + EventId eventId = default; if (logEvent.Properties.TryGetValue("SourceContext", out var sourceContextProperty) && sourceContextProperty is ScalarValue sourceContextValue && @@ -37,6 +39,18 @@ sourceContextProperty is ScalarValue sourceContextValue && { categoryName = sourceContext; } + if (logEvent.Properties.TryGetValue("EventId", out var eventIdPropertyValue) && eventIdPropertyValue is StructureValue structuredEventId) + { + string name = null; + var id = 0; + foreach (var item in structuredEventId.Properties) + { + if (item.Name == "Id" && item.Value is ScalarValue sv && sv.Value is int i) id = i; + if (item.Name == "Name" && item.Value is ScalarValue sv2 && sv2.Value is string s) name = s; + } + + eventId = new EventId(id, name); + } var level = LevelConvert.ToExtensionsLevel(logEvent.Level); var slv = new SerilogLogValues(logEvent.MessageTemplate, logEvent.Properties); @@ -47,7 +61,7 @@ sourceContextProperty is ScalarValue sourceContextValue && logger.Log( level, - default, + eventId, slv, logEvent.Exception, (s, e) => s.ToString()); diff --git a/test/Serilog.Extensions.Logging.Tests/LoggerProviderCollectionSinkTests.cs b/test/Serilog.Extensions.Logging.Tests/LoggerProviderCollectionSinkTests.cs new file mode 100644 index 0000000..0be1b4c --- /dev/null +++ b/test/Serilog.Extensions.Logging.Tests/LoggerProviderCollectionSinkTests.cs @@ -0,0 +1,85 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.Extensions.Logging; +using Serilog.Extensions.Logging.Tests.Support; +using Xunit; + +namespace Serilog.Extensions.Logging.Tests +{ + public class LoggerProviderCollectionSinkTests + { + const string Name = "test"; + const string TestMessage = "This is a test"; + + static Tuple SetUp(LogLevel logLevel) + { + var providers = new LoggerProviderCollection(); + var provider = new ExtensionsProvider(logLevel); + providers.AddProvider(provider); + var serilogLogger = new LoggerConfiguration() + .WriteTo.Providers(providers) + .MinimumLevel.Is(LevelConvert.ToSerilogLevel(logLevel)) + .CreateLogger(); + + var logger = (SerilogLogger)new SerilogLoggerProvider(serilogLogger).CreateLogger(Name); + + return new Tuple(logger, provider); + } + + [Fact] + public void LogsCorrectLevel() + { + var (logger, sink) = SetUp(LogLevel.Trace); + + logger.Log(LogLevel.Trace, 0, TestMessage, null, null); + logger.Log(LogLevel.Debug, 0, TestMessage, null, null); + logger.Log(LogLevel.Information, 0, TestMessage, null, null); + logger.Log(LogLevel.Warning, 0, TestMessage, null, null); + logger.Log(LogLevel.Error, 0, TestMessage, null, null); + logger.Log(LogLevel.Critical, 0, TestMessage, null, null); + + Assert.Equal(6, sink.Writes.Count); + Assert.Equal(LogLevel.Trace, sink.Writes[0].logLevel); + Assert.Equal(LogLevel.Debug, sink.Writes[1].logLevel); + Assert.Equal(LogLevel.Information, sink.Writes[2].logLevel); + Assert.Equal(LogLevel.Warning, sink.Writes[3].logLevel); + Assert.Equal(LogLevel.Error, sink.Writes[4].logLevel); + Assert.Equal(LogLevel.Critical, sink.Writes[5].logLevel); + } + + [Fact] + public void LogsCorrectEventId() + { + var (logger, sink) = SetUp(LogLevel.Trace); + + logger.Log(LogLevel.Trace, new EventId(1, nameof(LogLevel.Trace)), TestMessage, null, null); + logger.Log(LogLevel.Debug, new EventId(2, nameof(LogLevel.Debug)), TestMessage, null, null); + logger.Log(LogLevel.Information, new EventId(3, nameof(LogLevel.Information)), TestMessage, null, null); + logger.Log(LogLevel.Warning, new EventId(4, nameof(LogLevel.Warning)), TestMessage, null, null); + logger.Log(LogLevel.Error, new EventId(5, nameof(LogLevel.Error)), TestMessage, null, null); + logger.Log(LogLevel.Critical, new EventId(6, nameof(LogLevel.Critical)), TestMessage, null, null); + + Assert.Equal(6, sink.Writes.Count); + + Assert.Equal(1, sink.Writes[0].eventId.Id); + Assert.Equal(nameof(LogLevel.Trace), sink.Writes[0].eventId.Name); + + Assert.Equal(2, sink.Writes[1].eventId.Id); + Assert.Equal(nameof(LogLevel.Debug), sink.Writes[1].eventId.Name); + + Assert.Equal(3, sink.Writes[2].eventId.Id); + Assert.Equal(nameof(LogLevel.Information), sink.Writes[2].eventId.Name); + + Assert.Equal(4, sink.Writes[3].eventId.Id); + Assert.Equal(nameof(LogLevel.Warning), sink.Writes[3].eventId.Name); + + Assert.Equal(5, sink.Writes[4].eventId.Id); + Assert.Equal(nameof(LogLevel.Error), sink.Writes[4].eventId.Name); + + Assert.Equal(6, sink.Writes[5].eventId.Id); + Assert.Equal(nameof(LogLevel.Critical), sink.Writes[5].eventId.Name); + } + } +} diff --git a/test/Serilog.Extensions.Logging.Tests/Support/ExtensionsProvider.cs b/test/Serilog.Extensions.Logging.Tests/Support/ExtensionsProvider.cs new file mode 100644 index 0000000..583293c --- /dev/null +++ b/test/Serilog.Extensions.Logging.Tests/Support/ExtensionsProvider.cs @@ -0,0 +1,45 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using Microsoft.Extensions.Logging; +using Serilog.Events; + +namespace Serilog.Extensions.Logging.Tests.Support +{ + public class ExtensionsProvider : ILoggerProvider, Microsoft.Extensions.Logging.ILogger + { + private readonly LogLevel enabledLevel; + public List<(LogLevel logLevel, EventId eventId, object state, Exception exception, string message)> Writes { get; set; } = new List<(LogLevel logLevel, EventId eventId, object state, Exception exception, string message)>(); + + public ExtensionsProvider(LogLevel enabledLevel) + { + this.enabledLevel = enabledLevel; + } + + public Microsoft.Extensions.Logging.ILogger CreateLogger(string categoryName) + { + return this; + } + + public IDisposable BeginScope(TState state) + { + return this; + } + + public bool IsEnabled(LogLevel logLevel) + { + return enabledLevel <= logLevel; + } + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + { + Writes.Add((logLevel, eventId, state, exception, formatter(state, exception))); + } + + public void Dispose() + { + } + } +} \ No newline at end of file From 8c503a40b64cc5c67e961087d476af8dd00058fc Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Tue, 18 May 2021 09:45:33 +1000 Subject: [PATCH 22/23] Update publishing key --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 488ef26..628e491 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,7 +11,7 @@ artifacts: deploy: - provider: NuGet api_key: - secure: AA0wV/Jk8R7whwsYtDti4DvUdeQLWVPGJlGjguRr9TRw1dW13cuMCPnSEzSfGzCI + secure: kYR3BYzJm3wSFbFjPhgTzuDHHcE8ApoNUmHvJvunWZ39nyrqVk6J6srjzYVQ7/gX skip_symbols: true on: branch: /^(master|dev)$/ From 2a3afbbe360d2b85004059d03711fef3c22e9fa3 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Tue, 2 Nov 2021 07:33:23 +1000 Subject: [PATCH 23/23] Bump minor version - dependency and feature updates --- .../Serilog.Extensions.Logging.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj b/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj index a67b319..f6d4bc1 100644 --- a/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj +++ b/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj @@ -2,7 +2,7 @@ Low-level Serilog provider for Microsoft.Extensions.Logging - 3.0.2 + 3.1.0 Microsoft;Serilog Contributors netstandard2.0 true