From 9dcd59fc69d6ece7c72cc059deb536378be50a62 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Wed, 10 Jul 2024 15:22:19 +1000 Subject: [PATCH 1/4] Updates for Serilog 4 --- Build.ps1 | 33 +- appveyor.yml | 34 +- .../MapLoggerConfigurationExtensions.cs | 431 +++++++++--------- .../Serilog.Sinks.Map.csproj | 65 +-- .../Sinks/Map/MappedSink`1.cs | 177 ++++--- .../Serilog.Sink.Map.Tests/MappedSinkTests.cs | 429 +++++++++-------- .../Properties/launchSettings.json | 11 - .../Serilog.Sinks.Map.Tests.csproj | 18 +- .../Support/DelegatingSink.cs | 25 +- .../Support/DisposeTrackingSink.cs | 23 +- test/Serilog.Sink.Map.Tests/Support/Some.cs | 39 +- 11 files changed, 633 insertions(+), 652 deletions(-) delete mode 100644 test/Serilog.Sink.Map.Tests/Properties/launchSettings.json diff --git a/Build.ps1 b/Build.ps1 index cea0757..e634f23 100644 --- a/Build.ps1 +++ b/Build.ps1 @@ -1,31 +1,42 @@ +Write-Output "build: Build started" + Push-Location $PSScriptRoot -if(Test-Path .\artifacts) { Remove-Item .\artifacts -Force -Recurse } +if(Test-Path .\artifacts) { + Write-Output "build: Cleaning ./artifacts" + Remove-Item ./artifacts -Force -Recurse +} & dotnet restore --no-cache -$branch = @{ $true = $env:APPVEYOR_REPO_BRANCH; $false = $(git symbolic-ref --short -q HEAD) }[$env:APPVEYOR_REPO_BRANCH -ne $NULL]; -$revision = @{ $true = "{0:00000}" -f [convert]::ToInt32("0" + $env:APPVEYOR_BUILD_NUMBER, 10); $false = "local" }[$env:APPVEYOR_BUILD_NUMBER -ne $NULL]; -$suffix = @{ $true = ""; $false = "$branch-$revision"}[$branch -eq "master" -and $revision -ne "local"] +$branch = @{ $true = $env:APPVEYOR_REPO_BRANCH; $false = $(git symbolic-ref --short -q HEAD) }[$NULL -ne $env:APPVEYOR_REPO_BRANCH]; +$revision = @{ $true = "{0:00000}" -f [convert]::ToInt32("0" + $env:APPVEYOR_BUILD_NUMBER, 10); $false = "local" }[$NULL -ne $env:APPVEYOR_BUILD_NUMBER]; +$suffix = @{ $true = ""; $false = "$($branch.Substring(0, [math]::Min(10,$branch.Length)))-$revision"}[$branch -eq "main" -and $revision -ne "local"] + +Write-Output "build: Package version suffix is $suffix" -foreach ($src in ls src/Serilog.*) { +foreach ($src in Get-ChildItem src/*) { Push-Location $src - if($suffix) { - & dotnet pack -c Release -o ..\..\.\artifacts --version-suffix=$suffix --include-source + Write-Output "build: Packaging project in $src" + + if ($suffix) { + & dotnet pack -c Release /p:ContinuousIntegrationBuild=True --include-source -o ../../artifacts --version-suffix=$suffix } else { - & dotnet pack -c Release -o ..\..\.\artifacts --include-source + & dotnet pack -c Release /p:ContinuousIntegrationBuild=True --include-source -o ../../artifacts } - if($LASTEXITCODE -ne 0) { exit 1 } + if($LASTEXITCODE -ne 0) { throw "Packaging failed" } Pop-Location } -foreach ($test in ls test/Serilog.*.Tests) { +foreach ($test in Get-ChildItem test/*.Tests) { Push-Location $test + Write-Output "build: Testing project in $test" + & dotnet test -c Release - if($LASTEXITCODE -ne 0) { exit 2 } + if($LASTEXITCODE -ne 0) { throw "Testing failed" } Pop-Location } diff --git a/appveyor.yml b/appveyor.yml index 4f33b70..51f3e15 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,22 +1,24 @@ version: '{build}' skip_tags: true -image: Visual Studio 2019 +image: + - Visual Studio 2022 build_script: -- ps: ./Build.ps1 + - pwsh: ./Build.ps1 test: off artifacts: -- path: artifacts/Serilog.*.nupkg + - path: artifacts/Serilog.*.nupkg + - path: artifacts/Serilog.*.snupkg deploy: -- provider: NuGet - api_key: - secure: K3/810hkTO6rd2AEHVkUQAadjGmDREus9k96QHu6hxrA1/wRTuAJemHMKtVVgIvf - skip_symbols: true - on: - branch: /^(master|dev)$/ -- provider: GitHub - auth_token: - secure: p4LpVhBKxGS5WqucHxFQ5c7C8cP74kbNB0Z8k9Oxx/PMaDQ1+ibmoexNqVU5ZlmX - artifact: /Serilog.*\.nupkg/ - tag: v$(appveyor_build_version) - on: - branch: master + - provider: NuGet + api_key: + secure: sDnchSg4TZIOK7oIUI6BJwFPNENTOZrGNsroGO1hehLJSvlHpFmpTwiX8+bgPD+Q + on: + branch: /^(main|dev)$/ + - provider: GitHub + auth_token: + secure: p4LpVhBKxGS5WqucHxFQ5c7C8cP74kbNB0Z8k9Oxx/PMaDQ1+ibmoexNqVU5ZlmX + artifact: /Serilog.*(\.|\.s)nupkg/ + tag: v$(appveyor_build_version) + on: + branch: main + \ No newline at end of file diff --git a/src/Serilog.Sinks.Map/MapLoggerConfigurationExtensions.cs b/src/Serilog.Sinks.Map/MapLoggerConfigurationExtensions.cs index b21b6eb..b4182dd 100644 --- a/src/Serilog.Sinks.Map/MapLoggerConfigurationExtensions.cs +++ b/src/Serilog.Sinks.Map/MapLoggerConfigurationExtensions.cs @@ -12,247 +12,246 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; +using System.Diagnostics.CodeAnalysis; using Serilog.Configuration; using Serilog.Core; using Serilog.Events; using Serilog.Sinks.Map; +// ReSharper disable MemberCanBePrivate.Global -namespace Serilog +namespace Serilog; + +/// +/// Extends Serilog configuration with methods for selecting sink instances base on a log event property. +/// +public static class MapLoggerConfigurationExtensions { /// - /// Extends Serilog configuration with methods for selecting sink instances base on a log event property. + /// Dispatch log events to a set of sinks keyed on a log event property. /// - public static class MapLoggerConfigurationExtensions + /// The logger sink configuration. + /// The name of a scalar-valued property to use as a sink selector. + /// The key value to use when the property is missing or null. + /// A null default is allowed. + /// An action to configure the target sink given a key property value. + /// Limits the number of sinks that will be held open concurrently within the map. + /// The default is to let the map grow unbounded; smaller numbers will cause sinks to be evicted when the limit is + /// exceeded. To keep no sinks open, zero may be specified. + /// The minimum log event level required + /// in order to write an event to the sink. + /// A level switch to dynamically select the minimum level for events passed to the sink. + /// Logger configuration, allowing configuration to continue. + /// A required parameter is null. + public static LoggerConfiguration Map( + this LoggerSinkConfiguration loggerSinkConfiguration, + string keyPropertyName, + string defaultKey, + Action configure, + int? sinkMapCountLimit = null, + LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, + LoggingLevelSwitch? levelSwitch = null) { - /// - /// Dispatch log events to a set of sinks keyed on a log event property. - /// - /// The logger sink configuration. - /// The name of a scalar-valued property to use as a sink selector. - /// The key value to use when the property is missing or null. - /// A null default is allowed. - /// An action to configure the target sink given a key property value. - /// Limits the number of sinks that will be held open concurrently within the map. - /// The default is to let the map grow unbounded; smaller numbers will cause sinks to be evicted when the limit is - /// exceeded. To keep no sinks open, zero may be specified. - /// The minimum log event level required - /// in order to write an event to the sink. - /// A level switch to dynamically select the minimum level for events passed to the sink. - /// Logger configuration, allowing configuration to continue. - /// A required parameter is null. - public static LoggerConfiguration Map( - this LoggerSinkConfiguration loggerSinkConfiguration, - string keyPropertyName, - string defaultKey, - Action configure, - int? sinkMapCountLimit = null, - LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, - LoggingLevelSwitch levelSwitch = null) + return Map(loggerSinkConfiguration, le => { - return Map(loggerSinkConfiguration, le => + if (le.Properties.TryGetValue(keyPropertyName, out var v) && + v is ScalarValue sv) { - if (le.Properties.TryGetValue(keyPropertyName, out var v) && - v is ScalarValue sv) - { - return sv.Value?.ToString() ?? defaultKey; - } + return sv.Value?.ToString() ?? defaultKey; + } - return defaultKey; - }, configure, sinkMapCountLimit, restrictedToMinimumLevel, levelSwitch); - } + return defaultKey; + }, configure, sinkMapCountLimit, restrictedToMinimumLevel, levelSwitch); + } - /// - /// Dispatch log events to a set of sinks keyed on a log event property. - /// - /// The logger sink configuration. - /// The name of a scalar-valued property to use as a sink selector. - /// An action to configure the target sink given a key property value. - /// The key property value to use when no appropriate value is attached to the log event. - /// Limits the number of sinks that will be held open concurrently within the map. - /// The default is to let the map grow unbounded; smaller numbers will cause sinks to be evicted when the limit is - /// exceeded. To keep no sinks open, zero may be specified. - /// The minimum log event level required - /// in order to write an event to the sink. - /// A level switch to dynamically select the minimum level for events passed to the sink. - /// Logger configuration, allowing configuration to continue. - /// A required parameter is null. - public static LoggerConfiguration Map( - this LoggerSinkConfiguration loggerSinkConfiguration, - string keyPropertyName, - TKey defaultKey, - Action configure, - int? sinkMapCountLimit = null, - LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, - LoggingLevelSwitch levelSwitch = null) - { - if (loggerSinkConfiguration == null) throw new ArgumentNullException(nameof(loggerSinkConfiguration)); - if (keyPropertyName == null) throw new ArgumentNullException(nameof(keyPropertyName)); - if (configure == null) throw new ArgumentNullException(nameof(configure)); + /// + /// Dispatch log events to a set of sinks keyed on a log event property. + /// + /// The logger sink configuration. + /// The name of a scalar-valued property to use as a sink selector. + /// An action to configure the target sink given a key property value. + /// The key property value to use when no appropriate value is attached to the log event. + /// Limits the number of sinks that will be held open concurrently within the map. + /// The default is to let the map grow unbounded; smaller numbers will cause sinks to be evicted when the limit is + /// exceeded. To keep no sinks open, zero may be specified. + /// The minimum log event level required + /// in order to write an event to the sink. + /// A level switch to dynamically select the minimum level for events passed to the sink. + /// Logger configuration, allowing configuration to continue. + /// A required parameter is null. + public static LoggerConfiguration Map( + this LoggerSinkConfiguration loggerSinkConfiguration, + string keyPropertyName, + TKey defaultKey, + Action configure, + int? sinkMapCountLimit = null, + LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, + LoggingLevelSwitch? levelSwitch = null) + { + if (loggerSinkConfiguration == null) throw new ArgumentNullException(nameof(loggerSinkConfiguration)); + if (keyPropertyName == null) throw new ArgumentNullException(nameof(keyPropertyName)); + if (configure == null) throw new ArgumentNullException(nameof(configure)); - return Map(loggerSinkConfiguration, le => + return Map(loggerSinkConfiguration, le => + { + if (le.Properties.TryGetValue(keyPropertyName, out var v) && + v is ScalarValue { Value: TKey key }) { - if (le.Properties.TryGetValue(keyPropertyName, out var v) && - v is ScalarValue sv && - sv.Value is TKey key) - { - return key; - } + return key; + } - return defaultKey; - }, configure, sinkMapCountLimit, restrictedToMinimumLevel, levelSwitch); - } + return defaultKey; + }, configure, sinkMapCountLimit, restrictedToMinimumLevel, levelSwitch); + } - /// - /// Dispatch log events to a set of sinks keyed on a log event property. - /// - /// The logger sink configuration. - /// An action to configure the target sink given a key property value. - /// A function to select a key value given a log event. - /// Limits the number of sinks that will be held open concurrently within the map. - /// The default is to let the map grow unbounded; smaller numbers will cause sinks to be evicted when the limit is - /// exceeded. To keep no sinks open, zero may be specified. - /// The minimum log event level required - /// in order to write an event to the sink. - /// A level switch to dynamically select the minimum level for events passed to the sink. - /// Logger configuration, allowing configuration to continue. - /// A required parameter is null. - public static LoggerConfiguration Map( - this LoggerSinkConfiguration loggerSinkConfiguration, - Func keySelector, - Action configure, - int? sinkMapCountLimit = null, - LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, - LoggingLevelSwitch levelSwitch = null) - { - if (loggerSinkConfiguration == null) throw new ArgumentNullException(nameof(loggerSinkConfiguration)); - if (keySelector == null) throw new ArgumentNullException(nameof(keySelector)); - if (configure == null) throw new ArgumentNullException(nameof(configure)); - if (sinkMapCountLimit.HasValue && sinkMapCountLimit.Value < 0) throw new ArgumentOutOfRangeException(nameof(sinkMapCountLimit)); + /// + /// Dispatch log events to a set of sinks keyed on a log event property. + /// + /// The logger sink configuration. + /// An action to configure the target sink given a key property value. + /// A function to select a key value given a log event. + /// Limits the number of sinks that will be held open concurrently within the map. + /// The default is to let the map grow unbounded; smaller numbers will cause sinks to be evicted when the limit is + /// exceeded. To keep no sinks open, zero may be specified. + /// The minimum log event level required + /// in order to write an event to the sink. + /// A level switch to dynamically select the minimum level for events passed to the sink. + /// Logger configuration, allowing configuration to continue. + /// A required parameter is null. + public static LoggerConfiguration Map( + this LoggerSinkConfiguration loggerSinkConfiguration, + Func keySelector, + Action configure, + int? sinkMapCountLimit = null, + LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, + LoggingLevelSwitch? levelSwitch = null) + { + if (loggerSinkConfiguration == null) throw new ArgumentNullException(nameof(loggerSinkConfiguration)); + if (keySelector == null) throw new ArgumentNullException(nameof(keySelector)); + if (configure == null) throw new ArgumentNullException(nameof(configure)); + if (sinkMapCountLimit is < 0) throw new ArgumentOutOfRangeException(nameof(sinkMapCountLimit)); - return loggerSinkConfiguration.Sink( - new MappedSink( - (LogEvent logEvent, out TKey key) => - { - key = keySelector(logEvent); - return true; - }, - configure, - sinkMapCountLimit), - restrictedToMinimumLevel, - levelSwitch); - } + return loggerSinkConfiguration.Sink( + new MappedSink( + // ReSharper disable once UseNullableAnnotationInsteadOfAttribute + (LogEvent logEvent, [MaybeNull] out TKey key) => + { + key = keySelector(logEvent); + return true; + }, + configure, + sinkMapCountLimit), + restrictedToMinimumLevel, + levelSwitch); + } - /// - /// Dispatch log events to a set of sinks keyed on a log event property. - /// - /// The logger sink configuration. - /// The name of a scalar-valued property to use as a sink selector. - /// An action to configure the target sink given a key property value. - /// Limits the number of sinks that will be held open concurrently within the map. - /// The default is to let the map grow unbounded; smaller numbers will cause sinks to be evicted when the limit is - /// exceeded. To keep no sinks open, zero may be specified. - /// The minimum log event level required - /// in order to write an event to the sink. - /// A level switch to dynamically select the minimum level for events passed to the sink. - /// Logger configuration, allowing configuration to continue. - /// A required parameter is null. - public static LoggerConfiguration Map( - this LoggerSinkConfiguration loggerSinkConfiguration, - string keyPropertyName, - Action configure, - int? sinkMapCountLimit = null, - LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, - LoggingLevelSwitch levelSwitch = null) - { - return Map( - loggerSinkConfiguration, - (LogEvent le, out string key) => + /// + /// Dispatch log events to a set of sinks keyed on a log event property. + /// + /// The logger sink configuration. + /// The name of a scalar-valued property to use as a sink selector. + /// An action to configure the target sink given a key property value. + /// Limits the number of sinks that will be held open concurrently within the map. + /// The default is to let the map grow unbounded; smaller numbers will cause sinks to be evicted when the limit is + /// exceeded. To keep no sinks open, zero may be specified. + /// The minimum log event level required + /// in order to write an event to the sink. + /// A level switch to dynamically select the minimum level for events passed to the sink. + /// Logger configuration, allowing configuration to continue. + /// A required parameter is null. + public static LoggerConfiguration Map( + this LoggerSinkConfiguration loggerSinkConfiguration, + string keyPropertyName, + Action configure, + int? sinkMapCountLimit = null, + LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, + LoggingLevelSwitch? levelSwitch = null) + { + return Map( + loggerSinkConfiguration, + (LogEvent le, out string? key) => + { + if (le.Properties.TryGetValue(keyPropertyName, out var v) && + v is ScalarValue sv) { - if (le.Properties.TryGetValue(keyPropertyName, out var v) && - v is ScalarValue sv) - { - key = sv.Value?.ToString(); - return true; - } + key = sv.Value?.ToString(); + return true; + } - key = null; - return false; - }, configure, sinkMapCountLimit, restrictedToMinimumLevel, levelSwitch); - } + key = null; + return false; + }, configure, sinkMapCountLimit, restrictedToMinimumLevel, levelSwitch); + } - /// - /// Dispatch log events to a set of sinks keyed on a log event property. - /// - /// The logger sink configuration. - /// The name of a scalar-valued property to use as a sink selector. - /// An action to configure the target sink given a key property value. - /// Limits the number of sinks that will be held open concurrently within the map. - /// The default is to let the map grow unbounded; smaller numbers will cause sinks to be evicted when the limit is - /// exceeded. To keep no sinks open, zero may be specified. - /// The minimum log event level required - /// in order to write an event to the sink. - /// A level switch to dynamically select the minimum level for events passed to the sink. - /// Logger configuration, allowing configuration to continue. - /// A required parameter is null. - public static LoggerConfiguration Map( - this LoggerSinkConfiguration loggerSinkConfiguration, - string keyPropertyName, - Action configure, - int? sinkMapCountLimit = null, - LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, - LoggingLevelSwitch levelSwitch = null) - { - if (loggerSinkConfiguration == null) throw new ArgumentNullException(nameof(loggerSinkConfiguration)); - if (keyPropertyName == null) throw new ArgumentNullException(nameof(keyPropertyName)); - if (configure == null) throw new ArgumentNullException(nameof(configure)); + /// + /// Dispatch log events to a set of sinks keyed on a log event property. + /// + /// The logger sink configuration. + /// The name of a scalar-valued property to use as a sink selector. + /// An action to configure the target sink given a key property value. + /// Limits the number of sinks that will be held open concurrently within the map. + /// The default is to let the map grow unbounded; smaller numbers will cause sinks to be evicted when the limit is + /// exceeded. To keep no sinks open, zero may be specified. + /// The minimum log event level required + /// in order to write an event to the sink. + /// A level switch to dynamically select the minimum level for events passed to the sink. + /// Logger configuration, allowing configuration to continue. + /// A required parameter is null. + public static LoggerConfiguration Map( + this LoggerSinkConfiguration loggerSinkConfiguration, + string keyPropertyName, + Action configure, + int? sinkMapCountLimit = null, + LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, + LoggingLevelSwitch? levelSwitch = null) + { + if (loggerSinkConfiguration == null) throw new ArgumentNullException(nameof(loggerSinkConfiguration)); + if (keyPropertyName == null) throw new ArgumentNullException(nameof(keyPropertyName)); + if (configure == null) throw new ArgumentNullException(nameof(configure)); - return Map( - loggerSinkConfiguration, - (LogEvent le, out TKey key) => + return Map( + loggerSinkConfiguration, + (LogEvent le, out TKey? key) => + { + if (le.Properties.TryGetValue(keyPropertyName, out var v) && + v is ScalarValue { Value: TKey k }) { - if (le.Properties.TryGetValue(keyPropertyName, out var v) && - v is ScalarValue sv && - sv.Value is TKey k) - { - key = k; - return true; - } + key = k; + return true; + } - key = default(TKey); - return false; - }, - configure, sinkMapCountLimit, restrictedToMinimumLevel, levelSwitch); - } + key = default; + return false; + }, + configure, sinkMapCountLimit, restrictedToMinimumLevel, levelSwitch); + } - /// - /// Dispatch log events to a set of sinks keyed on a log event property. - /// - /// The logger sink configuration. - /// An action to configure the target sink given a key property value. - /// A function to select a key value given a log event. - /// Limits the number of sinks that will be held open concurrently within the map. - /// The default is to let the map grow unbounded; smaller numbers will cause sinks to be evicted when the limit is - /// exceeded. To keep no sinks open, zero may be specified. - /// The minimum log event level required - /// in order to write an event to the sink. - /// A level switch to dynamically select the minimum level for events passed to the sink. - /// Logger configuration, allowing configuration to continue. - /// A required parameter is null. - public static LoggerConfiguration Map( - this LoggerSinkConfiguration loggerSinkConfiguration, - KeySelector keySelector, - Action configure, - int? sinkMapCountLimit = null, - LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, - LoggingLevelSwitch levelSwitch = null) - { - if (loggerSinkConfiguration == null) throw new ArgumentNullException(nameof(loggerSinkConfiguration)); - if (keySelector == null) throw new ArgumentNullException(nameof(keySelector)); - if (configure == null) throw new ArgumentNullException(nameof(configure)); - if (sinkMapCountLimit.HasValue && sinkMapCountLimit.Value < 0) throw new ArgumentOutOfRangeException(nameof(sinkMapCountLimit)); + /// + /// Dispatch log events to a set of sinks keyed on a log event property. + /// + /// The logger sink configuration. + /// An action to configure the target sink given a key property value. + /// A function to select a key value given a log event. + /// Limits the number of sinks that will be held open concurrently within the map. + /// The default is to let the map grow unbounded; smaller numbers will cause sinks to be evicted when the limit is + /// exceeded. To keep no sinks open, zero may be specified. + /// The minimum log event level required + /// in order to write an event to the sink. + /// A level switch to dynamically select the minimum level for events passed to the sink. + /// Logger configuration, allowing configuration to continue. + /// A required parameter is null. + public static LoggerConfiguration Map( + this LoggerSinkConfiguration loggerSinkConfiguration, + KeySelector keySelector, + Action configure, + int? sinkMapCountLimit = null, + LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, + LoggingLevelSwitch? levelSwitch = null) + { + if (loggerSinkConfiguration == null) throw new ArgumentNullException(nameof(loggerSinkConfiguration)); + if (keySelector == null) throw new ArgumentNullException(nameof(keySelector)); + if (configure == null) throw new ArgumentNullException(nameof(configure)); + if (sinkMapCountLimit is < 0) throw new ArgumentOutOfRangeException(nameof(sinkMapCountLimit)); - return loggerSinkConfiguration.Sink(new MappedSink(keySelector, configure, sinkMapCountLimit), restrictedToMinimumLevel, levelSwitch); - } + return loggerSinkConfiguration.Sink(new MappedSink(keySelector, configure, sinkMapCountLimit), restrictedToMinimumLevel, levelSwitch); } -} +} \ No newline at end of file diff --git a/src/Serilog.Sinks.Map/Serilog.Sinks.Map.csproj b/src/Serilog.Sinks.Map/Serilog.Sinks.Map.csproj index 784f076..86cebc1 100644 --- a/src/Serilog.Sinks.Map/Serilog.Sinks.Map.csproj +++ b/src/Serilog.Sinks.Map/Serilog.Sinks.Map.csproj @@ -1,32 +1,43 @@ - - A Serilog sink wrapper that dispatches events based on a property value. - 1.0.3 - Serilog - Serilog Contributors - Copyright © Serilog Contributors - netstandard1.0;netstandard2.0;net5.0 - true - true - ../../assets/Serilog.snk - true - true - serilog - icon.png - Apache-2.0 - https://github.com/serilog/serilog-sinks-map - https://github.com/serilog/serilog-sinks-map - git - true - - - - - + + A Serilog sink wrapper that dispatches events based on a property value. + 2.0.0 + Serilog + Serilog Contributors + Copyright © Serilog Contributors + + net471;net462 + + $(TargetFrameworks);net8.0;net6.0;netstandard2.0 + true + true + ../../assets/Serilog.snk + true + true + serilog + icon.png + Apache-2.0 + https://github.com/serilog/serilog-sinks-map + https://github.com/serilog/serilog-sinks-map + git + true + latest + enable + README.md + enable + - - - + + + + + + + + + diff --git a/src/Serilog.Sinks.Map/Sinks/Map/MappedSink`1.cs b/src/Serilog.Sinks.Map/Sinks/Map/MappedSink`1.cs index d7881c1..55ac9f6 100644 --- a/src/Serilog.Sinks.Map/Sinks/Map/MappedSink`1.cs +++ b/src/Serilog.Sinks.Map/Sinks/Map/MappedSink`1.cs @@ -12,134 +12,117 @@ // 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.Diagnostics.CodeAnalysis; using Serilog.Configuration; using Serilog.Core; using Serilog.Events; -namespace Serilog.Sinks.Map +namespace Serilog.Sinks.Map; + +/// +/// A function delegate to select a key value given a log event, if exists. +/// +/// The type of the key value. +/// The log event. +/// The selected key. +/// true, if a key can be selected, or false, otherwise. +public delegate bool KeySelector(LogEvent logEvent, [MaybeNull] out TKey key); + +class MappedSink : ILogEventSink, IDisposable { - /// - /// A function delegate to select a key value given a log event, if exists. - /// - /// The type of the key value. - /// The log event. - /// The selected key. - /// true, if a key can be selected, or false, otherwise. - public delegate bool KeySelector(LogEvent logEvent, out TKey key); + readonly KeySelector _keySelector; + readonly Action _configure; + readonly int? _sinkMapCountLimit; + readonly object _sync = new(); + readonly Dictionary, ILogEventSink> _sinkMap = new(); + bool _disposed; + + public MappedSink(KeySelector keySelector, + Action configure, + int? sinkMapCountLimit) + { + _keySelector = keySelector; + _configure = configure; + _sinkMapCountLimit = sinkMapCountLimit; + } - class MappedSink : ILogEventSink, IDisposable + // All writes are synchronized, even though this could be avoided in a few cases; the reasoning behind this is that + // changes in synchronization behavior between writes and with different map count limits could lead to surprises + // when using the sink with log files, which are one of the main use cases. Since most sinks already synchronize + // writes or offload work to background threads, this is a reasonable trade-off. + public void Emit(LogEvent logEvent) { - readonly KeySelector _keySelector; - readonly Action _configure; - readonly int? _sinkMapCountLimit; - readonly object _sync = new object(); - readonly Dictionary, ILogEventSink> _sinkMap = new Dictionary, ILogEventSink>(); - bool _disposed; + if (!_keySelector(logEvent, out var keyValue)) + return; - public MappedSink(KeySelector keySelector, - Action configure, - int? sinkMapCountLimit) - { - _keySelector = keySelector; - _configure = configure; - _sinkMapCountLimit = sinkMapCountLimit; - } + var key = new KeyValuePair(keyValue!, false); - // All writes are synchronized, even though this could be avoided in a few cases; the reasoning behind this is that - // changes in synchronization behavior between writes and with different map count limits could lead to surprises - // when using the sink with log files, which are one of the main use cases. Since most sinks already synchronize - // writes or offload work to background threads, this is a reasonable trade-off. - public void Emit(LogEvent logEvent) + lock (_sync) { - if (!_keySelector(logEvent, out var keyValue)) - return; - - var key = new KeyValuePair(keyValue, false); + if (_disposed) + throw new ObjectDisposedException(nameof(MappedSink), "The mapped sink has been disposed."); - lock (_sync) + if (_sinkMap.TryGetValue(key, out var existing)) { - if (_disposed) - throw new ObjectDisposedException(nameof(MappedSink), "The mapped sink has been disposed."); - - if (_sinkMap.TryGetValue(key, out var existing)) - { - existing.Emit(logEvent); - return; - } + existing.Emit(logEvent); + return; + } - var sink = CreateSink(key.Key); + var sink = LoggerSinkConfiguration.CreateSink(wt => _configure(key.Key, wt)); - if (_sinkMapCountLimit == 0) - { - using (sink as IDisposable) - sink.Emit(logEvent); - } - else if (_sinkMapCountLimit == null || _sinkMapCountLimit > _sinkMap.Count) + if (_sinkMapCountLimit == 0) + { + using (sink as IDisposable) + sink.Emit(logEvent); + } + else if (_sinkMapCountLimit == null || _sinkMapCountLimit > _sinkMap.Count) + { + // This case is a little faster as no EH nor iteration is required + _sinkMap[key] = sink; + sink.Emit(logEvent); + } + else + { + _sinkMap[key] = sink; + try { - // This case is a little faster as no EH nor iteration is required - _sinkMap[key] = sink; sink.Emit(logEvent); } - else + finally { - _sinkMap[key] = sink; - try - { - sink.Emit(logEvent); - } - finally + while (_sinkMap.Count > _sinkMapCountLimit.Value) { - while (_sinkMap.Count > _sinkMapCountLimit.Value) + foreach (var k in _sinkMap.Keys) { - foreach (var k in _sinkMap.Keys) - { - if (key.Equals(k)) - continue; + if (key.Equals(k)) + continue; - var removed = _sinkMap[k]; - _sinkMap.Remove(k); - (removed as IDisposable)?.Dispose(); - break; - } + var removed = _sinkMap[k]; + _sinkMap.Remove(k); + (removed as IDisposable)?.Dispose(); + break; } } } } } + } - ILogEventSink CreateSink(TKey key) + public void Dispose() + { + lock (_sync) { - // Allocates a few delegates, but avoids a lot more allocation in the `LoggerConfiguration`/`Logger` machinery. - ILogEventSink sink = null; - LoggerSinkConfiguration.Wrap( - new LoggerConfiguration().WriteTo, - s => sink = s, - config => _configure(key, config), - LevelAlias.Minimum, - null); + if (_disposed) + return; - return sink; - } + _disposed = true; - public void Dispose() - { - lock (_sync) + var values = _sinkMap.Values.ToArray(); + _sinkMap.Clear(); + foreach (var sink in values) { - if (_disposed) - return; - - _disposed = true; - - var values = _sinkMap.Values.ToArray(); - _sinkMap.Clear(); - foreach (var sink in values) - { - (sink as IDisposable)?.Dispose(); - } + (sink as IDisposable)?.Dispose(); } } } -} +} \ No newline at end of file diff --git a/test/Serilog.Sink.Map.Tests/MappedSinkTests.cs b/test/Serilog.Sink.Map.Tests/MappedSinkTests.cs index d12c1f2..0bae990 100644 --- a/test/Serilog.Sink.Map.Tests/MappedSinkTests.cs +++ b/test/Serilog.Sink.Map.Tests/MappedSinkTests.cs @@ -3,291 +3,290 @@ using Serilog.Sinks.Map.Tests.Support; using Xunit; -namespace Serilog.Sinks.Map.Tests +namespace Serilog.Sinks.Map.Tests; + +public class MappedSinkTests { - public class MappedSinkTests + [Fact] + public void EventsReachSinksSelectedByTheConfiguredProperty() { - [Fact] - public void EventsReachSinksSelectedByTheConfiguredProperty() - { - var a = Some.LogEvent("Hello, {Name}!", "Alice"); - var b = Some.LogEvent("Hello, {Name}!", "Bob"); + var a = Some.LogEvent("Hello, {Name}!", "Alice"); + var b = Some.LogEvent("Hello, {Name}!", "Bob"); - var received = new List<(string, LogEvent)>(); + var received = new List<(string, LogEvent)>(); - var log = new LoggerConfiguration() - .WriteTo.Map("Name", (name, wt) => wt.Sink(new DelegatingSink(e => received.Add((name, e))))) - .CreateLogger(); + var log = new LoggerConfiguration() + .WriteTo.Map("Name", (name, wt) => wt.Sink(new DelegatingSink(e => received.Add((name, e))))) + .CreateLogger(); - log.Write(a); - log.Write(b); + log.Write(a); + log.Write(b); - Assert.Equal(2, received.Count); - Assert.Equal("Alice", received[0].Item1); - Assert.Equal("Bob", received[1].Item1); - } + Assert.Equal(2, received.Count); + Assert.Equal("Alice", received[0].Item1); + Assert.Equal("Bob", received[1].Item1); + } - [Fact] - public void WithUnlimitedMapSizeSinksAreRetained() - { - var a = Some.LogEvent("Hello, {Name}!", "Alice"); - var calls = 0; + [Fact] + public void WithUnlimitedMapSizeSinksAreRetained() + { + var a = Some.LogEvent("Hello, {Name}!", "Alice"); + var calls = 0; - var log = new LoggerConfiguration() - .WriteTo.Map("Name", (name, wt) => - { - ++calls; - }) - .CreateLogger(); + var log = new LoggerConfiguration() + .WriteTo.Map("Name", (_, _) => + { + ++calls; + }) + .CreateLogger(); - log.Write(a); - log.Write(a); + log.Write(a); + log.Write(a); - Assert.Equal(1, calls); - } + Assert.Equal(1, calls); + } - [Fact] - public void WithMapSize1LastSinksIsRetained() - { - var a = Some.LogEvent("Hello, {Name}!", "Alice"); - var calls = 0; + [Fact] + public void WithMapSize1LastSinksIsRetained() + { + var a = Some.LogEvent("Hello, {Name}!", "Alice"); + var calls = 0; - var log = new LoggerConfiguration() - .WriteTo.Map("Name", (name, wt) => - { - ++calls; - }, sinkMapCountLimit: 1) - .CreateLogger(); + var log = new LoggerConfiguration() + .WriteTo.Map("Name", (_, _) => + { + ++calls; + }, sinkMapCountLimit: 1) + .CreateLogger(); - log.Write(a); - log.Write(a); + log.Write(a); + log.Write(a); - Assert.Equal(1, calls); - } + Assert.Equal(1, calls); + } - [Fact] - public void WithMapSizeNLastNSinksAreRetained() - { - var a = Some.LogEvent("Hello, {Name}!", "Alice"); - var b = Some.LogEvent("Hello, {Name}!", "Bob"); - var calls = 0; + [Fact] + public void WithMapSizeNLastNSinksAreRetained() + { + var a = Some.LogEvent("Hello, {Name}!", "Alice"); + var b = Some.LogEvent("Hello, {Name}!", "Bob"); + var calls = 0; - var log = new LoggerConfiguration() - .WriteTo.Map("Name", (name, wt) => - { - ++calls; - }, sinkMapCountLimit: 1) - .CreateLogger(); + var log = new LoggerConfiguration() + .WriteTo.Map("Name", (_, _) => + { + ++calls; + }, sinkMapCountLimit: 1) + .CreateLogger(); - log.Write(a); - log.Write(b); - log.Write(a); + log.Write(a); + log.Write(b); + log.Write(a); - Assert.Equal(3, calls); - } + Assert.Equal(3, calls); + } - [Fact] - public void WithZeroMapSizeSinksAreRecycledImmediately() - { - var a = Some.LogEvent("Hello, {Name}!", "Alice"); - var calls = 0; + [Fact] + public void WithZeroMapSizeSinksAreRecycledImmediately() + { + var a = Some.LogEvent("Hello, {Name}!", "Alice"); + var calls = 0; - var log = new LoggerConfiguration() - .WriteTo.Map("Name", (name, wt) => - { - ++calls; - }, sinkMapCountLimit: 0) - .CreateLogger(); + var log = new LoggerConfiguration() + .WriteTo.Map("Name", (_, _) => + { + ++calls; + }, sinkMapCountLimit: 0) + .CreateLogger(); - log.Write(a); - log.Write(a); + log.Write(a); + log.Write(a); - Assert.Equal(2, calls); - } + Assert.Equal(2, calls); + } - [Fact] - public void WithNoMapSizeLimitSinksAreNotDisposed() - { - var a = Some.LogEvent("Hello, {Name}!", "Alice"); + [Fact] + public void WithNoMapSizeLimitSinksAreNotDisposed() + { + var a = Some.LogEvent("Hello, {Name}!", "Alice"); - var sink = new DisposeTrackingSink(); - var log = new LoggerConfiguration() - .WriteTo.Map("Name", (name, wt) => wt.Sink(sink)) - .CreateLogger(); + var sink = new DisposeTrackingSink(); + var log = new LoggerConfiguration() + .WriteTo.Map("Name", (_, wt) => wt.Sink(sink)) + .CreateLogger(); - log.Write(a); + log.Write(a); - Assert.False(sink.IsDisposed); - } + Assert.False(sink.IsDisposed); + } - [Fact] - public void WithMapSizeZeroSinksAreImmediatelyDisposed() - { - var a = Some.LogEvent("Hello, {Name}!", "Alice"); + [Fact] + public void WithMapSizeZeroSinksAreImmediatelyDisposed() + { + var a = Some.LogEvent("Hello, {Name}!", "Alice"); - var sink = new DisposeTrackingSink(); - var log = new LoggerConfiguration() - .WriteTo.Map("Name", (name, wt) => wt.Sink(sink), sinkMapCountLimit: 0) - .CreateLogger(); + var sink = new DisposeTrackingSink(); + var log = new LoggerConfiguration() + .WriteTo.Map("Name", (_, wt) => wt.Sink(sink), sinkMapCountLimit: 0) + .CreateLogger(); - log.Write(a); + log.Write(a); - Assert.True(sink.IsDisposed); - } + Assert.True(sink.IsDisposed); + } - [Fact] - public void WhenSinkMapOverflowsUnmappedSinksAreDisposed() - { - var a = Some.LogEvent("Hello, {Name}!", "Alice"); - var b = Some.LogEvent("Hello, {Name}!", "Bob"); + [Fact] + public void WhenSinkMapOverflowsUnmappedSinksAreDisposed() + { + var a = Some.LogEvent("Hello, {Name}!", "Alice"); + var b = Some.LogEvent("Hello, {Name}!", "Bob"); - var sinkA = new DisposeTrackingSink(); - var sinkB = new DisposeTrackingSink(); - var log = new LoggerConfiguration() - .WriteTo.Map("Name", (name, wt) => wt.Sink(name == "Alice" ? sinkA : sinkB), sinkMapCountLimit: 1) - .CreateLogger(); + var sinkA = new DisposeTrackingSink(); + var sinkB = new DisposeTrackingSink(); + var log = new LoggerConfiguration() + .WriteTo.Map("Name", (name, wt) => wt.Sink(name == "Alice" ? sinkA : sinkB), sinkMapCountLimit: 1) + .CreateLogger(); - log.Write(a); - log.Write(b); + log.Write(a); + log.Write(b); - Assert.True(sinkA.IsDisposed); - Assert.False(sinkB.IsDisposed); - } + Assert.True(sinkA.IsDisposed); + Assert.False(sinkB.IsDisposed); + } - [Fact] - public void NullReferenceTypeKeysAreSupported() - { - var a = Some.LogEvent("Hello, {Name}!", new object[] { null }); + [Fact] + public void NullReferenceTypeKeysAreSupported() + { + var a = Some.LogEvent("Hello, {Name}!", new object[] { null }); - var received = new List<(string, LogEvent)>(); + var received = new List<(string, LogEvent)>(); - var log = new LoggerConfiguration() - .WriteTo.Map("Name", (name, wt) => wt.Sink(new DelegatingSink(e => received.Add((name, e))))) - .CreateLogger(); + var log = new LoggerConfiguration() + .WriteTo.Map("Name", (name, wt) => wt.Sink(new DelegatingSink(e => received.Add((name, e))))) + .CreateLogger(); - log.Write(a); + log.Write(a); - Assert.Single(received); - Assert.Null(received[0].Item1); - } + Assert.Single(received); + Assert.Null(received[0].Item1); + } - [Fact] - public void NonGenericVersionShouldNotCheckKeyType() - { - var a = Some.LogEvent("Hello, {Name}!", 123_456); + [Fact] + public void NonGenericVersionShouldNotCheckKeyType() + { + var a = Some.LogEvent("Hello, {Name}!", 123_456); - var received = new List<(string, LogEvent)>(); + var received = new List<(string, LogEvent)>(); - var log = new LoggerConfiguration() - .WriteTo.Map("Name", (name, wt) => wt.Sink(new DelegatingSink(e => received.Add((name, e))))) - .CreateLogger(); + var log = new LoggerConfiguration() + .WriteTo.Map("Name", (name, wt) => wt.Sink(new DelegatingSink(e => received.Add((name, e))))) + .CreateLogger(); - log.Write(a); + log.Write(a); - Assert.Single(received); - Assert.Equal("123456", received[0].Item1); - } + Assert.Single(received); + Assert.Equal("123456", received[0].Item1); + } - [Fact] - public void GenericVersionShouldCheckKeyType() - { - var a = Some.LogEvent("Hello, {Name}!", 123_456); - var b = Some.LogEvent("Hello, {Name}!", "Alice"); + [Fact] + public void GenericVersionShouldCheckKeyType() + { + var a = Some.LogEvent("Hello, {Name}!", 123_456); + var b = Some.LogEvent("Hello, {Name}!", "Alice"); - var received = new List<(string, LogEvent)>(); + var received = new List<(string, LogEvent)>(); - var log = new LoggerConfiguration() - .WriteTo.Map("Name", (name, wt) => wt.Sink(new DelegatingSink(e => received.Add((name, e))))) - .CreateLogger(); + var log = new LoggerConfiguration() + .WriteTo.Map("Name", (name, wt) => wt.Sink(new DelegatingSink(e => received.Add((name, e))))) + .CreateLogger(); - log.Write(a); - log.Write(b); + log.Write(a); + log.Write(b); - Assert.Single(received); - Assert.Equal("Alice", received[0].Item1); - } + Assert.Single(received); + Assert.Equal("Alice", received[0].Item1); + } - [Fact] - public void ShouldSkipEmitWhenNoAppropriateValueIsAttachedToLogEvent() - { - var a = Some.LogEvent("Hello, World!"); + [Fact] + public void ShouldSkipEmitWhenNoAppropriateValueIsAttachedToLogEvent() + { + var a = Some.LogEvent("Hello, World!"); - var calls = 0; + var calls = 0; - var log = new LoggerConfiguration() - .WriteTo.Map("Name", (_, __) => ++calls) - .CreateLogger(); + var log = new LoggerConfiguration() + .WriteTo.Map("Name", (_, _) => ++calls) + .CreateLogger(); - log.Write(a); + log.Write(a); - Assert.Equal(0, calls); - } + Assert.Equal(0, calls); + } - [Fact] - public void DefaultKeyIsUsedWhenNoAppropriateValueIsAttachedToLogEvent() - { - var a = Some.LogEvent("Hello, World!"); + [Fact] + public void DefaultKeyIsUsedWhenNoAppropriateValueIsAttachedToLogEvent() + { + var a = Some.LogEvent("Hello, World!"); - var received = new List<(string, LogEvent)>(); + var received = new List<(string, LogEvent)>(); - var log = new LoggerConfiguration() - .WriteTo.Map("Name", "anonymous", (name, wt) => wt.Sink(new DelegatingSink(e => received.Add((name, e))))) - .CreateLogger(); + var log = new LoggerConfiguration() + .WriteTo.Map("Name", "anonymous", (name, wt) => wt.Sink(new DelegatingSink(e => received.Add((name, e))))) + .CreateLogger(); - log.Write(a); + log.Write(a); - Assert.Single(received); - Assert.Equal("anonymous", received[0].Item1); - } + Assert.Single(received); + Assert.Equal("anonymous", received[0].Item1); + } - [Fact] - public void DefaultKeyIsUsedWhenNullValueIsAttachedToLogEvent() - { - var a = Some.LogEvent("Hello, {Name}!", (object)null); + [Fact] + public void DefaultKeyIsUsedWhenNullValueIsAttachedToLogEvent() + { + var a = Some.LogEvent("Hello, {Name}!", (object)null); - var received = new List<(string, LogEvent)>(); + var received = new List<(string, LogEvent)>(); - var log = new LoggerConfiguration() - .WriteTo.Map("Name", "anonymous", (name, wt) => wt.Sink(new DelegatingSink(e => received.Add((name, e))))) - .CreateLogger(); + var log = new LoggerConfiguration() + .WriteTo.Map("Name", "anonymous", (name, wt) => wt.Sink(new DelegatingSink(e => received.Add((name, e))))) + .CreateLogger(); - log.Write(a); + log.Write(a); - Assert.Single(received); - Assert.Equal("anonymous", received[0].Item1); - } + Assert.Single(received); + Assert.Equal("anonymous", received[0].Item1); + } - [Fact] - public void DefaultKeyIsUsedWhenGenericNullValueIsAttachedToLogEvent() - { - var a = Some.LogEvent("Hello, {Name}!", (object)null); + [Fact] + public void DefaultKeyIsUsedWhenGenericNullValueIsAttachedToLogEvent() + { + var a = Some.LogEvent("Hello, {Name}!", (object)null); - var received = new List<(string, LogEvent)>(); + var received = new List<(string, LogEvent)>(); - var log = new LoggerConfiguration() - .WriteTo.Map("Name", "anonymous", (name, wt) => wt.Sink(new DelegatingSink(e => received.Add((name, e))))) - .CreateLogger(); + var log = new LoggerConfiguration() + .WriteTo.Map("Name", "anonymous", (name, wt) => wt.Sink(new DelegatingSink(e => received.Add((name, e))))) + .CreateLogger(); - log.Write(a); + log.Write(a); - Assert.Single(received); - Assert.Equal("anonymous", received[0].Item1); - } + Assert.Single(received); + Assert.Equal("anonymous", received[0].Item1); + } - [Fact] - public void SinksAreDisposedWithMapSinkDispose() - { - var a = Some.LogEvent("Hello, {Name}!", "Alice"); - - var sink = new DisposeTrackingSink(); - using (var log = new LoggerConfiguration() - .WriteTo.Map("Name", (name, wt) => wt.Sink(sink)) - .CreateLogger()) - { - log.Write(a); - } + [Fact] + public void SinksAreDisposedWithMapSinkDispose() + { + var a = Some.LogEvent("Hello, {Name}!", "Alice"); - Assert.True(sink.IsDisposed); + var sink = new DisposeTrackingSink(); + using (var log = new LoggerConfiguration() + .WriteTo.Map("Name", (_, wt) => wt.Sink(sink)) + .CreateLogger()) + { + log.Write(a); } + + Assert.True(sink.IsDisposed); } -} +} \ No newline at end of file diff --git a/test/Serilog.Sink.Map.Tests/Properties/launchSettings.json b/test/Serilog.Sink.Map.Tests/Properties/launchSettings.json deleted file mode 100644 index 3ab0635..0000000 --- a/test/Serilog.Sink.Map.Tests/Properties/launchSettings.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "profiles": { - "test": { - "commandName": "test" - }, - "test-dnxcore50": { - "commandName": "test", - "sdkVersion": "dnx-coreclr-win-x86.1.0.0-rc1-final" - } - } -} \ No newline at end of file diff --git a/test/Serilog.Sink.Map.Tests/Serilog.Sinks.Map.Tests.csproj b/test/Serilog.Sink.Map.Tests/Serilog.Sinks.Map.Tests.csproj index 6455564..0745ba1 100644 --- a/test/Serilog.Sink.Map.Tests/Serilog.Sinks.Map.Tests.csproj +++ b/test/Serilog.Sink.Map.Tests/Serilog.Sinks.Map.Tests.csproj @@ -1,6 +1,6 @@  - net5.0 + net8.0 Serilog.Sinks.Map.Tests ../../assets/Serilog.snk true @@ -13,22 +13,12 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - + diff --git a/test/Serilog.Sink.Map.Tests/Support/DelegatingSink.cs b/test/Serilog.Sink.Map.Tests/Support/DelegatingSink.cs index b0c5317..d3f7b00 100644 --- a/test/Serilog.Sink.Map.Tests/Support/DelegatingSink.cs +++ b/test/Serilog.Sink.Map.Tests/Support/DelegatingSink.cs @@ -2,20 +2,19 @@ using Serilog.Core; using Serilog.Events; -namespace Serilog.Sinks.Map.Tests.Support +namespace Serilog.Sinks.Map.Tests.Support; + +public class DelegatingSink : ILogEventSink { - public class DelegatingSink : ILogEventSink - { - readonly Action _write; + readonly Action _write; - public DelegatingSink(Action write) - { - _write = write ?? throw new ArgumentNullException(nameof(write)); - } + public DelegatingSink(Action write) + { + _write = write ?? throw new ArgumentNullException(nameof(write)); + } - public void Emit(LogEvent logEvent) - { - _write(logEvent); - } + public void Emit(LogEvent logEvent) + { + _write(logEvent); } -} +} \ No newline at end of file diff --git a/test/Serilog.Sink.Map.Tests/Support/DisposeTrackingSink.cs b/test/Serilog.Sink.Map.Tests/Support/DisposeTrackingSink.cs index cc8c8ae..c591db5 100644 --- a/test/Serilog.Sink.Map.Tests/Support/DisposeTrackingSink.cs +++ b/test/Serilog.Sink.Map.Tests/Support/DisposeTrackingSink.cs @@ -2,19 +2,18 @@ using Serilog.Core; using Serilog.Events; -namespace Serilog.Sinks.Map.Tests.Support +namespace Serilog.Sinks.Map.Tests.Support; + +class DisposeTrackingSink : ILogEventSink, IDisposable { - class DisposeTrackingSink : ILogEventSink, IDisposable - { - public bool IsDisposed { get; set; } + public bool IsDisposed { get; set; } - public void Emit(LogEvent logEvent) - { - } + public void Emit(LogEvent logEvent) + { + } - public void Dispose() - { - IsDisposed = true; - } + public void Dispose() + { + IsDisposed = true; } -} +} \ No newline at end of file diff --git a/test/Serilog.Sink.Map.Tests/Support/Some.cs b/test/Serilog.Sink.Map.Tests/Support/Some.cs index c17ef51..936d511 100644 --- a/test/Serilog.Sink.Map.Tests/Support/Some.cs +++ b/test/Serilog.Sink.Map.Tests/Support/Some.cs @@ -1,32 +1,31 @@ using System; -using System.Collections.Generic; using Serilog.Events; using Xunit.Sdk; +// ReSharper disable MemberCanBePrivate.Global -namespace Serilog.Sinks.Map.Tests.Support +namespace Serilog.Sinks.Map.Tests.Support; + +static class Some { - static class Some + public static LogEvent LogEvent(string messageTemplate, params object[] propertyValues) { - public static LogEvent LogEvent(string messageTemplate, params object[] propertyValues) - { - return LogEvent(null, messageTemplate, propertyValues); - } + return LogEvent(null, messageTemplate, propertyValues); + } - public static LogEvent LogEvent(Exception exception, string messageTemplate, params object[] propertyValues) - { - return LogEvent(LogEventLevel.Information, exception, messageTemplate, propertyValues); - } + public static LogEvent LogEvent(Exception exception, string messageTemplate, params object[] propertyValues) + { + return LogEvent(LogEventLevel.Information, exception, messageTemplate, propertyValues); + } - public static LogEvent LogEvent(LogEventLevel level, Exception exception, string messageTemplate, params object[] propertyValues) - { - var log = new LoggerConfiguration().CreateLogger(); + public static LogEvent LogEvent(LogEventLevel level, Exception exception, string messageTemplate, params object[] propertyValues) + { + var log = new LoggerConfiguration().CreateLogger(); #pragma warning disable Serilog004 // Constant MessageTemplate verifier - if (!log.BindMessageTemplate(messageTemplate, propertyValues, out var template, out var properties)) + if (!log.BindMessageTemplate(messageTemplate, propertyValues, out var template, out var properties)) #pragma warning restore Serilog004 // Constant MessageTemplate verifier - { - throw new XunitException("Template could not be bound."); - } - return new LogEvent(DateTimeOffset.Now, level, exception, template, properties); + { + throw new XunitException("Template could not be bound."); } + return new LogEvent(DateTimeOffset.Now, level, exception, template, properties); } -} +} \ No newline at end of file From 5f7a9d69b7ba4dcc718b7b6552f0338eaa873a0e Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Wed, 10 Jul 2024 16:00:04 +1000 Subject: [PATCH 2/4] Don't explicitly --include-soruce --- Build.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Build.ps1 b/Build.ps1 index e634f23..99e1369 100644 --- a/Build.ps1 +++ b/Build.ps1 @@ -21,9 +21,9 @@ foreach ($src in Get-ChildItem src/*) { Write-Output "build: Packaging project in $src" if ($suffix) { - & dotnet pack -c Release /p:ContinuousIntegrationBuild=True --include-source -o ../../artifacts --version-suffix=$suffix + & dotnet pack -c Release /p:ContinuousIntegrationBuild=True -o ../../artifacts --version-suffix=$suffix } else { - & dotnet pack -c Release /p:ContinuousIntegrationBuild=True --include-source -o ../../artifacts + & dotnet pack -c Release /p:ContinuousIntegrationBuild=True -o ../../artifacts } if($LASTEXITCODE -ne 0) { throw "Packaging failed" } From 3ad35e6b83cf273cea260ece8980b4a3e08956a2 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Thu, 11 Jul 2024 08:39:14 +1000 Subject: [PATCH 3/4] Remove redundant repository metadata --- src/Serilog.Sinks.Map/Serilog.Sinks.Map.csproj | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Serilog.Sinks.Map/Serilog.Sinks.Map.csproj b/src/Serilog.Sinks.Map/Serilog.Sinks.Map.csproj index 86cebc1..5c88747 100644 --- a/src/Serilog.Sinks.Map/Serilog.Sinks.Map.csproj +++ b/src/Serilog.Sinks.Map/Serilog.Sinks.Map.csproj @@ -21,8 +21,6 @@ icon.png Apache-2.0 https://github.com/serilog/serilog-sinks-map - https://github.com/serilog/serilog-sinks-map - git true latest enable From f4793c26c7a02531703dd335361c0b18ec1ed045 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Thu, 11 Jul 2024 08:40:54 +1000 Subject: [PATCH 4/4] Generate symbol package --- src/Serilog.Sinks.Map/Serilog.Sinks.Map.csproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Serilog.Sinks.Map/Serilog.Sinks.Map.csproj b/src/Serilog.Sinks.Map/Serilog.Sinks.Map.csproj index 5c88747..85e2c82 100644 --- a/src/Serilog.Sinks.Map/Serilog.Sinks.Map.csproj +++ b/src/Serilog.Sinks.Map/Serilog.Sinks.Map.csproj @@ -26,6 +26,8 @@ enable README.md enable + snupkg + true