diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..112f424
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,23 @@
+root = true
+
+[*]
+trim_trailing_whitespace = true
+insert_final_newline = true
+indent_style = space
+indent_size = 4
+charset = utf-8
+end_of_line = lf
+
+[*.{csproj,json,config,yml,props}]
+indent_size = 2
+
+[*.sh]
+end_of_line = lf
+
+[*.{cmd, bat}]
+end_of_line = crlf
+
+# C# formatting settings - Namespace options
+csharp_style_namespace_declarations = file_scoped:suggestion
+
+csharp_style_prefer_switch_expression = true:suggestion
\ No newline at end of file
diff --git a/Build.ps1 b/Build.ps1
index 41fbf5d..a674b52 100644
--- a/Build.ps1
+++ b/Build.ps1
@@ -11,7 +11,7 @@ if(Test-Path .\artifacts) {
$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.Substring(0, [math]::Min(10,$branch.Length)))-$revision"}[$branch -eq "master" -and $revision -ne "local"]
+$suffix = @{ $true = ""; $false = "$($branch.Substring(0, [math]::Min(10,$branch.Length)))-$revision"}[$branch -eq "main" -and $revision -ne "local"]
echo "build: Version suffix is $suffix"
@@ -25,8 +25,8 @@ foreach ($src in ls src/*) {
} else {
& dotnet pack -c Release --include-source -o ..\..\artifacts
}
-
- if($LASTEXITCODE -ne 0) { exit 1 }
+
+ if($LASTEXITCODE -ne 0) { exit 1 }
Pop-Location
}
diff --git a/Directory.Build.props b/Directory.Build.props
new file mode 100644
index 0000000..2b620bc
--- /dev/null
+++ b/Directory.Build.props
@@ -0,0 +1,12 @@
+
+
+
+ latest
+ True
+ true
+ $(MSBuildThisFileDirectory)assets/Serilog.snk
+ true
+ enable
+
+
+
diff --git a/Directory.Build.targets b/Directory.Build.targets
new file mode 100644
index 0000000..faf2349
--- /dev/null
+++ b/Directory.Build.targets
@@ -0,0 +1,3 @@
+
+
+
diff --git a/README.md b/README.md
index 905fc55..bbed04e 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# 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/)
+# 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.
@@ -16,9 +16,9 @@ The package implements `AddSerilog()` on `ILoggingBuilder` and `ILoggerFactory`
**First**, install the _Serilog.Extensions.Logging_ [NuGet package](https://www.nuget.org/packages/Serilog.Extensions.Logging) into your web or console app. You will need a way to view the log messages - _Serilog.Sinks.Console_ writes these to the console.
-```powershell
-Install-Package Serilog.Extensions.Logging -DependencyVersion Highest
-Install-Package Serilog.Sinks.Console
+```sh
+dotnet add package Serilog.Extensions.Logging
+dotnet add package Serilog.Sinks.Console
```
**Next**, in your application's `Startup` method, configure Serilog first:
@@ -34,7 +34,7 @@ public class Startup
.Enrich.FromLogContext()
.WriteTo.Console()
.CreateLogger();
-
+
// Other startup code
```
@@ -46,7 +46,7 @@ call `AddSerilog()` on the provided `loggingBuilder`.
{
services.AddLogging(loggingBuilder =>
loggingBuilder.AddSerilog(dispose: true));
-
+
// Other services ...
}
```
@@ -60,7 +60,7 @@ call `AddSerilog()` on the provided `loggingBuilder`.
IApplicationLifetime appLifetime)
{
loggerfactory.AddSerilog();
-
+
// Ensure any buffered events are sent at shutdown
appLifetime.ApplicationStopped.Register(Log.CloseAndFlush);
```
@@ -69,7 +69,7 @@ That's it! With the level bumped up a little you should see log output like:
```
[22:14:44.646 DBG] RouteCollection.RouteAsync
- Routes:
+ Routes:
Microsoft.AspNet.Mvc.Routing.AttributeRoute
{controller=Home}/{action=Index}/{id?}
Handled? True
@@ -89,7 +89,7 @@ _Microsoft.Extensions.Logging_ provides the `BeginScope` API, which can be used
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
+```csharp
using (_logger.BeginScope("Transaction")) {
_logger.LogInformation("Beginning...");
_logger.LogInformation("Completed in {DurationMs}ms...", 30);
@@ -101,7 +101,7 @@ using (_logger.BeginScope("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
+```csharp
// WRONG! Prefer the dictionary approach below instead
using (_logger.BeginScope("TransactionId: {TransactionId}, ResponseJson: {ResponseJson}", 12345, jsonString)) {
_logger.LogInformation("Completed in {DurationMs}ms...", 30);
@@ -119,11 +119,12 @@ 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.
+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 Serilog will output the key/value pairs as structured properties _without_ the `Scope` property, as in this example:
-```cs
+```csharp
var scopeProps = new Dictionary {
{ "TransactionId", 12345 },
{ "ResponseJson", jsonString },
@@ -143,6 +144,10 @@ using (_logger.BeginScope(scopeProps) {
// }
```
+### Versioning
+
+This package tracks the versioning and target framework support of its [_Microsoft.Extensions.Logging_](https://nuget.org/packages/Microsoft.Extensions.Logging) dependency.
+
### 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).
diff --git a/appveyor.yml b/appveyor.yml
index 628e491..3e4a484 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,6 +1,6 @@
version: '{build}'
skip_tags: true
-image: Visual Studio 2019
+image: Visual Studio 2022
install:
- ps: mkdir -Force ".\build\" | Out-Null
build_script:
@@ -11,15 +11,15 @@ artifacts:
deploy:
- provider: NuGet
api_key:
- secure: kYR3BYzJm3wSFbFjPhgTzuDHHcE8ApoNUmHvJvunWZ39nyrqVk6J6srjzYVQ7/gX
+ secure: EN9f+XXE3fW+ebL4wxrIbafdtbNvRfddBN8UUixvctYh4qMBHzr1JdnM83QsM1zo
skip_symbols: true
on:
- branch: /^(master|dev)$/
+ branch: /^(main|dev)$/
- provider: GitHub
auth_token:
secure: p4LpVhBKxGS5WqucHxFQ5c7C8cP74kbNB0Z8k9Oxx/PMaDQ1+ibmoexNqVU5ZlmX
artifact: /Serilog.*\.nupkg/
tag: v$(appveyor_build_version)
on:
- branch: master
+ branch: main
diff --git a/global.json b/global.json
deleted file mode 100644
index e3bbb00..0000000
--- a/global.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "sdk": {
- "allowPrerelease": false,
- "version": "3.1.100",
- "rollForward": "latestFeature"
- }
-}
diff --git a/samples/Sample/Program.cs b/samples/Sample/Program.cs
index 03014b7..d70b9aa 100644
--- a/samples/Sample/Program.cs
+++ b/samples/Sample/Program.cs
@@ -1,79 +1,68 @@
-using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Serilog;
using Serilog.Extensions.Logging;
-namespace Sample
-{
- public class Program
- {
- public static void Main(string[] args)
- {
- // Creating a `LoggerProviderCollection` lets Serilog optionally write
- // events through other dynamically-added MEL ILoggerProviders.
- var providers = new LoggerProviderCollection();
+// Creating a `LoggerProviderCollection` lets Serilog optionally write
+// events through other dynamically-added MEL ILoggerProviders.
+var providers = new LoggerProviderCollection();
- Log.Logger = new LoggerConfiguration()
- .MinimumLevel.Debug()
- .WriteTo.Console()
- .WriteTo.Providers(providers)
- .CreateLogger();
+Log.Logger = new LoggerConfiguration()
+ .MinimumLevel.Debug()
+ .WriteTo.Console()
+ .WriteTo.Providers(providers)
+ .CreateLogger();
- var services = new ServiceCollection();
+var services = new ServiceCollection();
- services.AddSingleton(providers);
- services.AddSingleton(sc =>
- {
- var providerCollection = sc.GetService();
- var factory = new SerilogLoggerFactory(null, true, providerCollection);
+services.AddSingleton(providers);
+services.AddSingleton(sc =>
+{
+ var providerCollection = sc.GetService();
+ var factory = new SerilogLoggerFactory(null, true, providerCollection);
- foreach (var provider in sc.GetServices())
- factory.AddProvider(provider);
+ foreach (var provider in sc.GetServices())
+ factory.AddProvider(provider);
- return factory;
- });
+ return factory;
+});
- services.AddLogging(l => l.AddConsole());
+services.AddLogging(l => l.AddConsole());
- var serviceProvider = services.BuildServiceProvider();
- var logger = serviceProvider.GetRequiredService>();
+var serviceProvider = services.BuildServiceProvider();
+var logger = serviceProvider.GetRequiredService>();
- var startTime = DateTimeOffset.UtcNow;
- logger.LogInformation(1, "Started at {StartTime} and 0x{Hello:X} is hex of 42", startTime, 42);
+var startTime = DateTimeOffset.UtcNow;
+logger.LogInformation(1, "Started at {StartTime} and 0x{Hello:X} is hex of 42", startTime, 42);
- try
- {
- throw new Exception("Boom!");
- }
- catch (Exception ex)
- {
- logger.LogCritical("Unexpected critical error starting application", ex);
- logger.Log(LogLevel.Critical, 0, "Unexpected critical error", ex, null);
- // This write should not log anything
- logger.Log(LogLevel.Critical, 0, null, null, null);
- logger.LogError("Unexpected error", ex);
- logger.LogWarning("Unexpected warning", ex);
- }
+try
+{
+ throw new Exception("Boom!");
+}
+catch (Exception ex)
+{
+ logger.LogCritical(ex, "Unexpected critical error starting application");
+ logger.Log(LogLevel.Critical, 0, "Unexpected critical error", ex, null!);
+ // This write should not log anything
+ logger.Log(LogLevel.Critical, 0, null!, null, null!);
+ logger.LogError(ex, "Unexpected error");
+ logger.LogWarning(ex, "Unexpected warning");
+}
- using (logger.BeginScope("Main"))
- {
- logger.LogInformation("Waiting for user input");
- var key = Console.Read();
- logger.LogInformation("User pressed {@KeyInfo}", new { Key = key, KeyChar = (char)key });
- }
+using (logger.BeginScope("Main"))
+{
+ logger.LogInformation("Waiting for user input");
+ var key = Console.Read();
+ logger.LogInformation("User pressed {@KeyInfo}", new { Key = key, KeyChar = (char)key });
+}
- var endTime = DateTimeOffset.UtcNow;
- logger.LogInformation(2, "Stopping at {StopTime}", endTime);
+var endTime = DateTimeOffset.UtcNow;
+logger.LogInformation(2, "Stopping at {StopTime}", endTime);
- logger.LogInformation("Stopping");
+logger.LogInformation("Stopping");
- logger.LogInformation(Environment.NewLine);
- logger.LogInformation("{Result,-10:l}{StartTime,15:l}{EndTime,15:l}{Duration,15:l}", "RESULT", "START TIME", "END TIME", "DURATION(ms)");
- logger.LogInformation("{Result,-10:l}{StartTime,15:l}{EndTime,15:l}{Duration,15:l}", "------", "----- ----", "--- ----", "------------");
- logger.LogInformation("{Result,-10:l}{StartTime,15:mm:s tt}{EndTime,15:mm:s tt}{Duration,15}", "SUCCESS", startTime, endTime, (endTime - startTime).TotalMilliseconds);
+logger.LogInformation("{Result,-10:l}{StartTime,15:l}{EndTime,15:l}{Duration,15:l}", "RESULT", "START TIME", "END TIME", "DURATION(ms)");
+logger.LogInformation("{Result,-10:l}{StartTime,15:l}{EndTime,15:l}{Duration,15:l}", "------", "----- ----", "--- ----", "------------");
+logger.LogInformation("{Result,-10:l}{StartTime,15:mm:s tt}{EndTime,15:mm:s tt}{Duration,15}", "SUCCESS", startTime, endTime, (endTime - startTime).TotalMilliseconds);
- serviceProvider.Dispose();
- }
- }
-}
+serviceProvider.Dispose();
diff --git a/samples/Sample/Sample.csproj b/samples/Sample/Sample.csproj
index c557b8a..ef89f43 100644
--- a/samples/Sample/Sample.csproj
+++ b/samples/Sample/Sample.csproj
@@ -1,10 +1,10 @@
- netcoreapp2.0
+ net7.0
Sample
Exe
- Sample
+ enable
@@ -12,10 +12,9 @@
-
-
-
-
+
+
+
-
\ No newline at end of file
+
diff --git a/serilog-extensions-logging.sln b/serilog-extensions-logging.sln
index c53414c..9e91f73 100644
--- a/serilog-extensions-logging.sln
+++ b/serilog-extensions-logging.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.29209.62
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.33424.131
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A1893BD1-333D-4DFE-A0F0-DDBB2FE526E0}"
EndProject
@@ -17,9 +17,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample", "samples\Sample\Sa
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "assets", "assets", "{9C21B9DF-AEDD-4AA6-BEA4-912DEF3E5B8E}"
ProjectSection(SolutionItems) = preProject
+ .editorconfig = .editorconfig
appveyor.yml = appveyor.yml
Build.ps1 = Build.ps1
- global.json = global.json
+ Directory.Build.props = Directory.Build.props
+ Directory.Build.targets = Directory.Build.targets
README.md = README.md
assets\Serilog.snk = assets\Serilog.snk
EndProjectSection
diff --git a/serilog-extensions-logging.sln.DotSettings b/serilog-extensions-logging.sln.DotSettings
index c2fd9da..23a0f99 100644
--- a/serilog-extensions-logging.sln.DotSettings
+++ b/serilog-extensions-logging.sln.DotSettings
@@ -1,12 +1,2 @@
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
\ No newline at end of file
+ True
\ No newline at end of file
diff --git a/src/Serilog.Extensions.Logging/Extensions/Logging/CachingMessageTemplateParser.cs b/src/Serilog.Extensions.Logging/Extensions/Logging/CachingMessageTemplateParser.cs
index d47e84f..8966ef7 100644
--- a/src/Serilog.Extensions.Logging/Extensions/Logging/CachingMessageTemplateParser.cs
+++ b/src/Serilog.Extensions.Logging/Extensions/Logging/CachingMessageTemplateParser.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Serilog Contributors
+// 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.
@@ -13,55 +13,53 @@
// limitations under the License.
-using System;
using Serilog.Events;
using Serilog.Parsing;
using System.Collections;
-namespace Serilog.Extensions.Logging
+namespace Serilog.Extensions.Logging;
+
+class CachingMessageTemplateParser
{
- class CachingMessageTemplateParser
- {
- readonly MessageTemplateParser _innerParser = new MessageTemplateParser();
-
- readonly object _templatesLock = new object();
- readonly Hashtable _templates = new Hashtable();
+ readonly MessageTemplateParser _innerParser = new();
- const int MaxCacheItems = 1000;
- const int MaxCachedTemplateLength = 1024;
+ readonly object _templatesLock = new();
+ readonly Hashtable _templates = new();
- public MessageTemplate Parse(string messageTemplate)
- {
- if (messageTemplate == null) throw new ArgumentNullException(nameof(messageTemplate));
+ const int MaxCacheItems = 1000;
+ const int MaxCachedTemplateLength = 1024;
- if (messageTemplate.Length > MaxCachedTemplateLength)
- return _innerParser.Parse(messageTemplate);
+ public MessageTemplate Parse(string messageTemplate)
+ {
+ if (messageTemplate == null) throw new ArgumentNullException(nameof(messageTemplate));
- // ReSharper disable once InconsistentlySynchronizedField
- // ignored warning because this is by design
- var result = (MessageTemplate)_templates[messageTemplate];
- if (result != null)
- return result;
+ if (messageTemplate.Length > MaxCachedTemplateLength)
+ return _innerParser.Parse(messageTemplate);
- result = _innerParser.Parse(messageTemplate);
+ // ReSharper disable once InconsistentlySynchronizedField
+ // ignored warning because this is by design
+ var result = (MessageTemplate?)_templates[messageTemplate];
+ if (result != null)
+ return result;
- 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.
+ result = _innerParser.Parse(messageTemplate);
- // 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.
+ 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.
- if (_templates.Count == MaxCacheItems)
- _templates.Clear();
+ // 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.
- _templates[messageTemplate] = result;
- }
+ if (_templates.Count == MaxCacheItems)
+ _templates.Clear();
- return result;
+ _templates[messageTemplate] = result;
}
+
+ return result;
}
}
diff --git a/src/Serilog.Extensions.Logging/Extensions/Logging/LevelConvert.cs b/src/Serilog.Extensions.Logging/Extensions/Logging/LevelConvert.cs
index 58354e0..a77494e 100644
--- a/src/Serilog.Extensions.Logging/Extensions/Logging/LevelConvert.cs
+++ b/src/Serilog.Extensions.Logging/Extensions/Logging/LevelConvert.cs
@@ -1,4 +1,4 @@
-// Copyright 2019 Serilog Contributors
+// Copyright 2019 Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -17,65 +17,49 @@
// ReSharper disable RedundantCaseLabel
-namespace Serilog.Extensions.Logging
+namespace Serilog.Extensions.Logging;
+
+///
+/// Converts between Serilog and Microsoft.Extensions.Logging level enum values.
+///
+public static class LevelConvert
{
///
- /// Converts between Serilog and Microsoft.Extensions.Logging level enum values.
+ /// Convert to the equivalent Serilog .
///
- public static class LevelConvert
+ /// A Microsoft.Extensions.Logging .
+ /// The Serilog equivalent of .
+ /// The value has no Serilog equivalent. It is mapped to
+ /// as the closest approximation, but this has entirely
+ /// different semantics.
+ public static LogEventLevel ToSerilogLevel(LogLevel logLevel)
{
- ///
- /// Convert to the equivalent Serilog .
- ///
- /// A Microsoft.Extensions.Logging .
- /// The Serilog equivalent of .
- /// The value has no Serilog equivalent. It is mapped to
- /// as the closest approximation, but this has entirely
- /// different semantics.
- public static LogEventLevel ToSerilogLevel(LogLevel logLevel)
+ return logLevel switch
{
- switch (logLevel)
- {
- case LogLevel.None:
- case LogLevel.Critical:
- return LogEventLevel.Fatal;
- case LogLevel.Error:
- return LogEventLevel.Error;
- case LogLevel.Warning:
- return LogEventLevel.Warning;
- case LogLevel.Information:
- return LogEventLevel.Information;
- case LogLevel.Debug:
- return LogEventLevel.Debug;
- case LogLevel.Trace:
- default:
- return LogEventLevel.Verbose;
- }
- }
+ LogLevel.None or LogLevel.Critical => LogEventLevel.Fatal,
+ LogLevel.Error => LogEventLevel.Error,
+ LogLevel.Warning => LogEventLevel.Warning,
+ LogLevel.Information => LogEventLevel.Information,
+ LogLevel.Debug => LogEventLevel.Debug,
+ _ => LogEventLevel.Verbose,
+ };
+ }
- ///
- /// Convert to the equivalent Microsoft.Extensions.Logging .
- ///
- /// A Serilog .
- /// The Microsoft.Extensions.Logging equivalent of .
- public static LogLevel ToExtensionsLevel(LogEventLevel logEventLevel)
+ ///
+ /// Convert to the equivalent Microsoft.Extensions.Logging .
+ ///
+ /// A Serilog .
+ /// The Microsoft.Extensions.Logging equivalent of .
+ public static LogLevel ToExtensionsLevel(LogEventLevel logEventLevel)
+ {
+ return logEventLevel switch
{
- switch (logEventLevel)
- {
- case LogEventLevel.Fatal:
- return LogLevel.Critical;
- case LogEventLevel.Error:
- return LogLevel.Error;
- case LogEventLevel.Warning:
- return LogLevel.Warning;
- case LogEventLevel.Information:
- return LogLevel.Information;
- case LogEventLevel.Debug:
- return LogLevel.Debug;
- case LogEventLevel.Verbose:
- default:
- return LogLevel.Trace;
- }
- }
+ LogEventLevel.Fatal => LogLevel.Critical,
+ LogEventLevel.Error => LogLevel.Error,
+ LogEventLevel.Warning => LogLevel.Warning,
+ LogEventLevel.Information => LogLevel.Information,
+ LogEventLevel.Debug => LogLevel.Debug,
+ _ => LogLevel.Trace,
+ };
}
}
diff --git a/src/Serilog.Extensions.Logging/Extensions/Logging/LoggerProviderCollection.cs b/src/Serilog.Extensions.Logging/Extensions/Logging/LoggerProviderCollection.cs
index 7a0e08b..b944040 100644
--- a/src/Serilog.Extensions.Logging/Extensions/Logging/LoggerProviderCollection.cs
+++ b/src/Serilog.Extensions.Logging/Extensions/Logging/LoggerProviderCollection.cs
@@ -13,55 +13,50 @@
// limitations under the License.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
using Microsoft.Extensions.Logging;
-namespace Serilog.Extensions.Logging
+namespace Serilog.Extensions.Logging;
+
+///
+/// A dynamically-modifiable collection of s.
+///
+public class LoggerProviderCollection : IDisposable
{
+ volatile ILoggerProvider[] _providers = Array.Empty();
+
///
- /// A dynamically-modifiable collection of s.
+ /// Add to the collection.
///
- public class LoggerProviderCollection : IDisposable
+ /// A logger provider.
+ public void AddProvider(ILoggerProvider provider)
{
- volatile ILoggerProvider[] _providers = Array.Empty();
-
- ///
- /// Add to the collection.
- ///
- /// A logger provider.
- public void AddProvider(ILoggerProvider provider)
- {
- if (provider == null) throw new ArgumentNullException(nameof(provider));
+ if (provider == null) throw new ArgumentNullException(nameof(provider));
- ILoggerProvider[] existing, added;
+ ILoggerProvider[] existing, added;
- do
- {
- existing = _providers;
- added = existing.Concat(new[] { provider }).ToArray();
- }
+ 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);
+ while (Interlocked.CompareExchange(ref _providers, added, existing) != existing);
#pragma warning restore 420
- }
-
- ///
- /// Get the currently-active providers.
- ///
- ///
- /// If the collection has been disposed, we'll leave the individual
- /// providers with the job of throwing .
- ///
- public IEnumerable Providers => _providers;
+ }
- ///
- public void Dispose()
- {
- foreach (var provider in _providers)
- provider.Dispose();
- }
+ ///
+ /// Get the currently-active providers.
+ ///
+ ///
+ /// If the collection has been disposed, we'll leave the individual
+ /// providers with the job of throwing .
+ ///
+ public IEnumerable Providers => _providers;
+
+ ///
+ public void Dispose()
+ {
+ foreach (var provider in _providers)
+ provider.Dispose();
}
}
diff --git a/src/Serilog.Extensions.Logging/Extensions/Logging/LoggerProviderCollectionSink.cs b/src/Serilog.Extensions.Logging/Extensions/Logging/LoggerProviderCollectionSink.cs
index afe4a29..0febb52 100644
--- a/src/Serilog.Extensions.Logging/Extensions/Logging/LoggerProviderCollectionSink.cs
+++ b/src/Serilog.Extensions.Logging/Extensions/Logging/LoggerProviderCollectionSink.cs
@@ -1,4 +1,4 @@
-// Copyright 2019 Serilog Contributors
+// Copyright 2019 Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,65 +12,63 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System;
using Microsoft.Extensions.Logging;
using Serilog.Core;
using Serilog.Events;
-namespace Serilog.Extensions.Logging
+namespace Serilog.Extensions.Logging;
+
+class LoggerProviderCollectionSink : ILogEventSink, IDisposable
{
- class LoggerProviderCollectionSink : ILogEventSink, IDisposable
+ readonly LoggerProviderCollection _providers;
+
+ public LoggerProviderCollectionSink(LoggerProviderCollection providers)
+ {
+ _providers = providers ?? throw new ArgumentNullException(nameof(providers));
+ }
+
+ public void Emit(LogEvent logEvent)
{
- readonly LoggerProviderCollection _providers;
+ string categoryName = "None";
+ EventId eventId = default;
- public LoggerProviderCollectionSink(LoggerProviderCollection providers)
+ if (logEvent.Properties.TryGetValue("SourceContext", out var sourceContextProperty) &&
+ sourceContextProperty is ScalarValue sourceContextValue &&
+ sourceContextValue.Value is string sourceContext)
{
- _providers = providers ?? throw new ArgumentNullException(nameof(providers));
+ categoryName = sourceContext;
}
-
- public void Emit(LogEvent logEvent)
+ if (logEvent.Properties.TryGetValue("EventId", out var eventIdPropertyValue) && eventIdPropertyValue is StructureValue structuredEventId)
{
- string categoryName = null;
- EventId eventId = default;
-
- if (logEvent.Properties.TryGetValue("SourceContext", out var sourceContextProperty) &&
- sourceContextProperty is ScalarValue sourceContextValue &&
- sourceContextValue.Value is string sourceContext)
+ string? name = null;
+ var id = 0;
+ foreach (var item in structuredEventId.Properties)
{
- categoryName = sourceContext;
+ 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;
}
- 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);
- }
+ eventId = new EventId(id, name);
+ }
- var level = LevelConvert.ToExtensionsLevel(logEvent.Level);
- var slv = new SerilogLogValues(logEvent.MessageTemplate, logEvent.Properties);
+ var level = LevelConvert.ToExtensionsLevel(logEvent.Level);
+ var slv = new SerilogLogValues(logEvent.MessageTemplate, logEvent.Properties);
- foreach (var provider in _providers.Providers)
- {
- var logger = provider.CreateLogger(categoryName);
+ foreach (var provider in _providers.Providers)
+ {
+ var logger = provider.CreateLogger(categoryName);
- logger.Log(
- level,
- eventId,
- slv,
- logEvent.Exception,
- (s, e) => s.ToString());
- }
+ logger.Log(
+ level,
+ eventId,
+ slv,
+ logEvent.Exception,
+ (s, e) => s.ToString());
}
+ }
- public void Dispose()
- {
- _providers.Dispose();
- }
+ public void Dispose()
+ {
+ _providers.Dispose();
}
}
diff --git a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogValues.cs b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogValues.cs
index c6f8058..20253f8 100644
--- a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogValues.cs
+++ b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogValues.cs
@@ -13,50 +13,47 @@
// limitations under the License.
using Serilog.Events;
-using System;
using System.Collections;
-using System.Collections.Generic;
-namespace Serilog.Extensions.Logging
+namespace Serilog.Extensions.Logging;
+
+readonly struct SerilogLogValues : IReadOnlyList>
{
- readonly struct SerilogLogValues : IReadOnlyList>
+ // Note, this struct is only used in a very limited context internally, so we ignore
+ // the possibility of fields being null via the default struct initialization.
+
+ readonly MessageTemplate _messageTemplate;
+ readonly IReadOnlyDictionary _properties;
+ readonly KeyValuePair[] _values;
+
+ public SerilogLogValues(MessageTemplate messageTemplate, IReadOnlyDictionary properties)
{
- // Note, this struct is only used in a very limited context internally, so we ignore
- // the possibility of fields being null via the default struct initialization.
+ _messageTemplate = messageTemplate ?? throw new ArgumentNullException(nameof(messageTemplate));
- private readonly MessageTemplate _messageTemplate;
- private readonly IReadOnlyDictionary _properties;
- private readonly KeyValuePair[] _values;
+ // The dictionary is needed for rendering through the message template
+ _properties = properties ?? throw new ArgumentNullException(nameof(properties));
- public SerilogLogValues(MessageTemplate messageTemplate, IReadOnlyDictionary properties)
+ // The array is needed because the IReadOnlyList interface expects indexed access
+ _values = new KeyValuePair[_properties.Count + 1];
+ var i = 0;
+ foreach (var p in properties)
{
- _messageTemplate = messageTemplate ?? throw new ArgumentNullException(nameof(messageTemplate));
-
- // The dictionary is needed for rendering through the message template
- _properties = properties ?? throw new ArgumentNullException(nameof(properties));
-
- // The array is needed because the IReadOnlyList interface expects indexed access
- _values = new KeyValuePair[_properties.Count + 1];
- var i = 0;
- foreach (var p in properties)
- {
- _values[i] = new KeyValuePair(p.Key, (p.Value is ScalarValue sv) ? sv.Value : p.Value);
- ++i;
- }
- _values[i] = new KeyValuePair("{OriginalFormat}", _messageTemplate.Text);
+ _values[i] = new KeyValuePair(p.Key, (p.Value is ScalarValue sv) ? sv.Value : p.Value);
+ ++i;
}
+ _values[i] = new KeyValuePair("{OriginalFormat}", _messageTemplate.Text);
+ }
- public KeyValuePair this[int index]
- {
- get => _values[index];
- }
+ public KeyValuePair this[int index]
+ {
+ get => _values[index];
+ }
- public int Count => _properties.Count + 1;
+ public int Count => _properties.Count + 1;
- public IEnumerator> GetEnumerator() => ((IEnumerable>)_values).GetEnumerator();
+ public IEnumerator> GetEnumerator() => ((IEnumerable>)_values).GetEnumerator();
- public override string ToString() => _messageTemplate.Render(_properties);
+ public override string ToString() => _messageTemplate.Render(_properties);
- IEnumerator IEnumerable.GetEnumerator() => _values.GetEnumerator();
- }
+ IEnumerator IEnumerable.GetEnumerator() => _values.GetEnumerator();
}
diff --git a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs
index 1b1f895..edcef30 100644
--- a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs
+++ b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs
@@ -2,173 +2,190 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.Extensions.Logging;
-using System;
-using System.Collections.Generic;
-using System.Linq;
using Serilog.Core;
using Serilog.Events;
using FrameworkLogger = Microsoft.Extensions.Logging.ILogger;
using System.Reflection;
using Serilog.Debugging;
+using System.Collections.Concurrent;
-namespace Serilog.Extensions.Logging
+namespace Serilog.Extensions.Logging;
+
+class SerilogLogger : FrameworkLogger
{
- class SerilogLogger : FrameworkLogger
+ internal static readonly ConcurrentDictionary DestructureDictionary = new();
+ internal static readonly ConcurrentDictionary StringifyDictionary = new();
+
+ internal static string GetKeyWithoutFirstSymbol(ConcurrentDictionary source, string key)
{
- readonly SerilogLoggerProvider _provider;
- readonly ILogger _logger;
+ if (source.TryGetValue(key, out var value))
+ return value;
+ if (source.Count < 1000)
+ return source.GetOrAdd(key, k => k.Substring(1));
+ return key.Substring(1);
+ }
- static readonly CachingMessageTemplateParser MessageTemplateParser = new CachingMessageTemplateParser();
+ readonly SerilogLoggerProvider _provider;
+ readonly ILogger _logger;
- // It's rare to see large event ids, as they are category-specific
- static readonly LogEventProperty[] LowEventIdValues = Enumerable.Range(0, 48)
- .Select(n => new LogEventProperty("Id", new ScalarValue(n)))
- .ToArray();
+ static readonly CachingMessageTemplateParser MessageTemplateParser = new();
- public SerilogLogger(
- SerilogLoggerProvider provider,
- ILogger logger = null,
- string name = null)
- {
- _provider = provider ?? throw new ArgumentNullException(nameof(provider));
- _logger = logger;
+ // It's rare to see large event ids, as they are category-specific
+ static readonly LogEventProperty[] LowEventIdValues = Enumerable.Range(0, 48)
+ .Select(n => new LogEventProperty("Id", new ScalarValue(n)))
+ .ToArray();
- // If a logger was passed, the provider has already added itself as an enricher
- _logger = _logger ?? Serilog.Log.Logger.ForContext(new[] { provider });
+ public SerilogLogger(
+ SerilogLoggerProvider provider,
+ ILogger? logger = null,
+ string? name = null)
+ {
+ _provider = provider ?? throw new ArgumentNullException(nameof(provider));
- if (name != null)
- {
- _logger = _logger.ForContext(Constants.SourceContextPropertyName, name);
- }
- }
+ // If a logger was passed, the provider has already added itself as an enricher
+ _logger = logger ?? Serilog.Log.Logger.ForContext(new[] { provider });
- public bool IsEnabled(LogLevel logLevel)
+ if (name != null)
{
- return _logger.IsEnabled(LevelConvert.ToSerilogLevel(logLevel));
+ _logger = _logger.ForContext(Constants.SourceContextPropertyName, name);
}
+ }
+
+ public bool IsEnabled(LogLevel logLevel)
+ {
+ return logLevel != LogLevel.None && _logger.IsEnabled(LevelConvert.ToSerilogLevel(logLevel));
+ }
- public IDisposable BeginScope(TState state)
+ public IDisposable BeginScope(TState state) where TState : notnull
+ {
+ return _provider.BeginScope(state);
+ }
+
+ public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter)
+ {
+ if (logLevel == LogLevel.None)
{
- return _provider.BeginScope(state);
+ return;
}
-
- public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter)
+ var level = LevelConvert.ToSerilogLevel(logLevel);
+ if (!_logger.IsEnabled(level))
{
- var level = LevelConvert.ToSerilogLevel(logLevel);
- if (!_logger.IsEnabled(level))
- {
- return;
- }
-
- try
- {
- Write(level, eventId, state, exception, formatter);
- }
- catch (Exception ex)
- {
- SelfLog.WriteLine($"Failed to write event through {typeof(SerilogLogger).Name}: {ex}");
- }
+ return;
}
- void Write(LogEventLevel level, EventId eventId, TState state, Exception exception, Func formatter)
+ LogEvent? evt = null;
+ try
{
- var logger = _logger;
- string messageTemplate = null;
+ evt = PrepareWrite(level, eventId, state, exception, formatter);
+ }
+ catch (Exception ex)
+ {
+ SelfLog.WriteLine($"Failed to write event through {nameof(SerilogLogger)}: {ex}");
+ }
- var properties = new List();
+ // Do not swallow exceptions from here because Serilog takes care of them in case of WriteTo and throws them back to the caller in case of AuditTo.
+ if (evt != null)
+ _logger.Write(evt);
+ }
- if (state is IEnumerable> structure)
- {
- foreach (var property in structure)
- {
- if (property.Key == SerilogLoggerProvider.OriginalFormatPropertyName && property.Value is string value)
- {
- messageTemplate = value;
- }
- else if (property.Key.StartsWith("@"))
- {
- 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(), true, out var stringified))
- properties.Add(stringified);
- }
- else
- {
- if (logger.BindProperty(property.Key, property.Value, false, out var bound))
- properties.Add(bound);
- }
- }
+ LogEvent PrepareWrite(LogEventLevel level, EventId eventId, TState state, Exception? exception, Func formatter)
+ {
+ string? messageTemplate = null;
- var stateType = state.GetType();
- var stateTypeInfo = stateType.GetTypeInfo();
- // Imperfect, but at least eliminates `1 names
- if (messageTemplate == null && !stateTypeInfo.IsGenericType)
- {
- messageTemplate = "{" + stateType.Name + ":l}";
- if (logger.BindProperty(stateType.Name, AsLoggableValue(state, formatter), false, out var stateTypeProperty))
- properties.Add(stateTypeProperty);
- }
- }
+ var properties = new List();
- if (messageTemplate == null)
+ if (state is IEnumerable> structure)
+ {
+ foreach (var property in structure)
{
- string propertyName = null;
- if (state != null)
+ if (property.Key == SerilogLoggerProvider.OriginalFormatPropertyName && property.Value is string value)
{
- propertyName = "State";
- messageTemplate = "{State:l}";
+ messageTemplate = value;
}
- else if (formatter != null)
+ else if (property.Key.StartsWith("@"))
{
- propertyName = "Message";
- messageTemplate = "{Message:l}";
+ if (_logger.BindProperty(GetKeyWithoutFirstSymbol(DestructureDictionary, property.Key), property.Value, true, out var destructured))
+ properties.Add(destructured);
}
-
- if (propertyName != null)
+ else if (property.Key.StartsWith("$"))
+ {
+ if (_logger.BindProperty(GetKeyWithoutFirstSymbol(StringifyDictionary, property.Key), property.Value?.ToString(), true, out var stringified))
+ properties.Add(stringified);
+ }
+ else
{
- if (logger.BindProperty(propertyName, AsLoggableValue(state, formatter), false, out var property))
- properties.Add(property);
+ if (_logger.BindProperty(property.Key, property.Value, false, out var bound))
+ properties.Add(bound);
}
}
- if (eventId.Id != 0 || eventId.Name != null)
- properties.Add(CreateEventIdProperty(eventId));
-
- var parsedTemplate = MessageTemplateParser.Parse(messageTemplate ?? "");
- var evt = new LogEvent(DateTimeOffset.Now, level, exception, parsedTemplate, properties);
- logger.Write(evt);
- }
-
- static object AsLoggableValue(TState state, Func formatter)
- {
- object sobj = state;
- if (formatter != null)
- sobj = formatter(state, null);
- return sobj;
+ var stateType = state.GetType();
+ var stateTypeInfo = stateType.GetTypeInfo();
+ // Imperfect, but at least eliminates `1 names
+ if (messageTemplate == null && !stateTypeInfo.IsGenericType)
+ {
+ messageTemplate = "{" + stateType.Name + ":l}";
+ if (_logger.BindProperty(stateType.Name, AsLoggableValue(state, formatter), false, out var stateTypeProperty))
+ properties.Add(stateTypeProperty);
+ }
}
- internal static LogEventProperty CreateEventIdProperty(EventId eventId)
+ if (messageTemplate == null)
{
- var properties = new List(2);
-
- if (eventId.Id != 0)
+ string? propertyName = null;
+ if (state != null)
{
- if (eventId.Id >= 0 && eventId.Id < LowEventIdValues.Length)
- // Avoid some allocations
- properties.Add(LowEventIdValues[eventId.Id]);
- else
- properties.Add(new LogEventProperty("Id", new ScalarValue(eventId.Id)));
+ propertyName = "State";
+ messageTemplate = "{State:l}";
+ }
+ // `formatter` was originally accepted as nullable, so despite the new annotation, this check should still
+ // be made.
+ else if (formatter != null!)
+ {
+ propertyName = "Message";
+ messageTemplate = "{Message:l}";
}
- if (eventId.Name != null)
+ if (propertyName != null)
{
- properties.Add(new LogEventProperty("Name", new ScalarValue(eventId.Name)));
+ if (_logger.BindProperty(propertyName, AsLoggableValue(state, formatter!), false, out var property))
+ properties.Add(property);
}
+ }
+
+ if (eventId.Id != 0 || eventId.Name != null)
+ properties.Add(CreateEventIdProperty(eventId));
+
+ var parsedTemplate = MessageTemplateParser.Parse(messageTemplate ?? "");
+ return new LogEvent(DateTimeOffset.Now, level, exception, parsedTemplate, properties);
+ }
+
+ static object? AsLoggableValue(TState state, Func? formatter)
+ {
+ object? stateObj = state;
+ if (formatter != null)
+ stateObj = formatter(state, null);
+ return stateObj;
+ }
+
+ internal static LogEventProperty CreateEventIdProperty(EventId eventId)
+ {
+ var properties = new List(2);
+
+ if (eventId.Id != 0)
+ {
+ if (eventId.Id >= 0 && eventId.Id < LowEventIdValues.Length)
+ // Avoid some allocations
+ properties.Add(LowEventIdValues[eventId.Id]);
+ else
+ properties.Add(new LogEventProperty("Id", new ScalarValue(eventId.Id)));
+ }
- return new LogEventProperty("EventId", new StructureValue(properties));
+ if (eventId.Name != null)
+ {
+ properties.Add(new LogEventProperty("Name", new ScalarValue(eventId.Name)));
}
+
+ return new LogEventProperty("EventId", new StructureValue(properties));
}
}
diff --git a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerFactory.cs b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerFactory.cs
index cf25f06..b85dbcb 100644
--- a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerFactory.cs
+++ b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerFactory.cs
@@ -1,4 +1,4 @@
-// Copyright 2019 Serilog Contributors
+// Copyright 2019 Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,65 +12,63 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System;
using Microsoft.Extensions.Logging;
using Serilog.Debugging;
-namespace Serilog.Extensions.Logging
+namespace Serilog.Extensions.Logging;
+
+///
+/// A complete Serilog-backed implementation of the .NET Core logging infrastructure.
+///
+public class SerilogLoggerFactory : ILoggerFactory
{
+ readonly LoggerProviderCollection? _providerCollection;
+ readonly SerilogLoggerProvider _provider;
+
///
- /// A complete Serilog-backed implementation of the .NET Core logging infrastructure.
+ /// Initializes a new instance of the class.
///
- public class SerilogLoggerFactory : ILoggerFactory
+ /// The Serilog logger; if not supplied, the static will be used.
+ /// 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.
+ /// A , for use with WriteTo.Providers() .
+ public SerilogLoggerFactory(ILogger? logger = null, bool dispose = false, LoggerProviderCollection? providerCollection = null)
{
- readonly LoggerProviderCollection _providerCollection;
- readonly SerilogLoggerProvider _provider;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The Serilog logger; if not supplied, the static will be used.
- /// 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.
- /// A , for use with WriteTo.Providers() .
- public SerilogLoggerFactory(ILogger logger = null, bool dispose = false, LoggerProviderCollection providerCollection = null)
- {
- _provider = new SerilogLoggerProvider(logger, dispose);
- _providerCollection = providerCollection;
- }
+ _provider = new SerilogLoggerProvider(logger, dispose);
+ _providerCollection = providerCollection;
+ }
- ///
- /// Disposes the provider.
- ///
- public void Dispose()
- {
- _provider.Dispose();
- }
+ ///
+ /// Disposes the provider.
+ ///
+ public void Dispose()
+ {
+ _provider.Dispose();
+ }
- ///
- /// Creates a new instance.
- ///
- /// The category name for messages produced by the logger.
- ///
- /// The .
- ///
- public Microsoft.Extensions.Logging.ILogger CreateLogger(string categoryName)
- {
- return _provider.CreateLogger(categoryName);
- }
+ ///
+ /// Creates a new instance.
+ ///
+ /// The category name for messages produced by the logger.
+ ///
+ /// The .
+ ///
+ public Microsoft.Extensions.Logging.ILogger CreateLogger(string categoryName)
+ {
+ return _provider.CreateLogger(categoryName);
+ }
- ///
- /// Adds an to the logging system.
- ///
- /// The .
- public void AddProvider(ILoggerProvider provider)
- {
- if (provider == null) throw new ArgumentNullException(nameof(provider));
- if (_providerCollection != null)
- _providerCollection.AddProvider(provider);
- else
- SelfLog.WriteLine("Ignoring added logger provider {0}", provider);
- }
+ ///
+ /// Adds an to the logging system.
+ ///
+ /// The .
+ public void AddProvider(ILoggerProvider provider)
+ {
+ if (provider == null) throw new ArgumentNullException(nameof(provider));
+ if (_providerCollection != null)
+ _providerCollection.AddProvider(provider);
+ else
+ SelfLog.WriteLine("Ignoring added logger provider {0}", provider);
}
}
diff --git a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerProvider.cs b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerProvider.cs
index d51c2c0..3fead38 100644
--- a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerProvider.cs
+++ b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerProvider.cs
@@ -1,102 +1,98 @@
// 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.Core;
using Serilog.Events;
using FrameworkLogger = Microsoft.Extensions.Logging.ILogger;
-using System.Collections.Generic;
-using System.Threading;
using Serilog.Context;
-namespace Serilog.Extensions.Logging
+namespace Serilog.Extensions.Logging;
+
+///
+/// An that pipes events through Serilog.
+///
+[ProviderAlias("Serilog")]
+public class SerilogLoggerProvider : ILoggerProvider, ILogEventEnricher
{
+ internal const string OriginalFormatPropertyName = "{OriginalFormat}";
+ internal const string ScopePropertyName = "Scope";
+
+ // May be null; if it is, Log.Logger will be lazily used
+ readonly ILogger? _logger;
+ readonly Action? _dispose;
+
///
- /// An that pipes events through Serilog.
+ /// Construct a .
///
- [ProviderAlias("Serilog")]
- public class SerilogLoggerProvider : ILoggerProvider, ILogEventEnricher
+ /// A Serilog logger to pipe events through; if null, the static class will be used.
+ /// If true, the provided logger or static log class will be disposed/closed when the provider is disposed.
+ public SerilogLoggerProvider(ILogger? logger = null, bool dispose = false)
{
- internal const string OriginalFormatPropertyName = "{OriginalFormat}";
- internal const string ScopePropertyName = "Scope";
-
- // May be null; if it is, Log.Logger will be lazily used
- readonly ILogger _logger;
- readonly Action _dispose;
+ if (logger != null)
+ _logger = logger.ForContext(new[] { this });
- ///
- /// Construct a .
- ///
- /// A Serilog logger to pipe events through; if null, the static class will be used.
- /// If true, the provided logger or static log class will be disposed/closed when the provider is disposed.
- public SerilogLoggerProvider(ILogger logger = null, bool dispose = false)
+ if (dispose)
{
if (logger != null)
- _logger = logger.ForContext(new[] { this });
-
- if (dispose)
- {
- if (logger != null)
- _dispose = () => (logger as IDisposable)?.Dispose();
- else
- _dispose = Log.CloseAndFlush;
- }
+ _dispose = () => (logger as IDisposable)?.Dispose();
+ else
+ _dispose = Log.CloseAndFlush;
}
+ }
- ///
- public FrameworkLogger CreateLogger(string name)
- {
- return new SerilogLogger(this, _logger, name);
- }
+ ///
+ public FrameworkLogger CreateLogger(string name)
+ {
+ return new SerilogLogger(this, _logger, name);
+ }
- ///
- public IDisposable BeginScope(T state)
- {
- if (CurrentScope != null)
- return new SerilogLoggerScope(this, state);
+ ///
+ public IDisposable BeginScope(T state)
+ {
+ if (CurrentScope != null)
+ return new SerilogLoggerScope(this, state);
- // The outermost scope pushes and pops the Serilog `LogContext` - once
- // this enricher is on the stack, the `CurrentScope` property takes care
- // of the rest of the `BeginScope()` stack.
- var popSerilogContext = LogContext.Push(this);
- return new SerilogLoggerScope(this, state, popSerilogContext);
- }
+ // The outermost scope pushes and pops the Serilog `LogContext` - once
+ // this enricher is on the stack, the `CurrentScope` property takes care
+ // of the rest of the `BeginScope()` stack.
+ var popSerilogContext = LogContext.Push(this);
+ return new SerilogLoggerScope(this, state, popSerilogContext);
+ }
- ///
- public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
+ ///
+ public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
+ {
+ List? scopeItems = null;
+ for (var scope = CurrentScope; scope != null; scope = scope.Parent)
{
- List scopeItems = null;
- for (var scope = CurrentScope; scope != null; scope = scope.Parent)
- {
- scope.EnrichAndCreateScopeItem(logEvent, propertyFactory, out LogEventPropertyValue scopeItem);
+ scope.EnrichAndCreateScopeItem(logEvent, propertyFactory, out var scopeItem);
- if (scopeItem != null)
- {
- scopeItems = scopeItems ?? new List();
- scopeItems.Add(scopeItem);
- }
- }
-
- if (scopeItems != null)
+ if (scopeItem != null)
{
- scopeItems.Reverse();
- logEvent.AddPropertyIfAbsent(new LogEventProperty(ScopePropertyName, new SequenceValue(scopeItems)));
+ scopeItems ??= new List();
+ scopeItems.Add(scopeItem);
}
}
- readonly AsyncLocal _value = new AsyncLocal();
-
- internal SerilogLoggerScope CurrentScope
+ if (scopeItems != null)
{
- get => _value.Value;
- set => _value.Value = value;
+ scopeItems.Reverse();
+ logEvent.AddPropertyIfAbsent(new LogEventProperty(ScopePropertyName, new SequenceValue(scopeItems)));
}
+ }
- ///
- public void Dispose()
- {
- _dispose?.Invoke();
- }
+ readonly AsyncLocal _value = new();
+
+ internal SerilogLoggerScope? CurrentScope
+ {
+ get => _value.Value;
+ set => _value.Value = value;
+ }
+
+ ///
+ public void Dispose()
+ {
+ _dispose?.Invoke();
}
}
diff --git a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerScope.cs b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerScope.cs
index dd0803c..9d13190 100644
--- a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerScope.cs
+++ b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerScope.cs
@@ -1,98 +1,109 @@
// 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 Serilog.Core;
using Serilog.Events;
-namespace Serilog.Extensions.Logging
+namespace Serilog.Extensions.Logging;
+
+class SerilogLoggerScope : IDisposable
{
- class SerilogLoggerScope : IDisposable
+ const string NoName = "None";
+
+ readonly SerilogLoggerProvider _provider;
+ readonly object? _state;
+ readonly IDisposable? _chainedDisposable;
+
+ // An optimization only, no problem if there are data races on this.
+ bool _disposed;
+
+ public SerilogLoggerScope(SerilogLoggerProvider provider, object? state, IDisposable? chainedDisposable = null)
{
- const string NoName = "None";
+ _provider = provider;
+ _state = state;
- readonly SerilogLoggerProvider _provider;
- readonly object _state;
- readonly IDisposable _chainedDisposable;
+ Parent = _provider.CurrentScope;
+ _provider.CurrentScope = this;
+ _chainedDisposable = chainedDisposable;
+ }
- // An optimization only, no problem if there are data races on this.
- bool _disposed;
+ public SerilogLoggerScope? Parent { get; }
- public SerilogLoggerScope(SerilogLoggerProvider provider, object state, IDisposable chainedDisposable = null)
+ public void Dispose()
+ {
+ if (!_disposed)
{
- _provider = provider;
- _state = state;
+ _disposed = true;
- Parent = _provider.CurrentScope;
- _provider.CurrentScope = this;
- _chainedDisposable = chainedDisposable;
+ // In case one of the parent scopes has been disposed out-of-order, don't
+ // just blindly reinstate our own parent.
+ for (var scan = _provider.CurrentScope; scan != null; scan = scan.Parent)
+ {
+ if (ReferenceEquals(scan, this))
+ _provider.CurrentScope = Parent;
+ }
+
+ _chainedDisposable?.Dispose();
}
+ }
- public SerilogLoggerScope Parent { get; }
-
- public void Dispose()
+ public void EnrichAndCreateScopeItem(LogEvent logEvent, ILogEventPropertyFactory propertyFactory, out LogEventPropertyValue? scopeItem)
+ {
+ void AddProperty(KeyValuePair stateProperty)
{
- if (!_disposed)
+ var key = stateProperty.Key;
+ var destructureObject = false;
+ var value = stateProperty.Value;
+
+ if (key.StartsWith("@"))
{
- _disposed = true;
+ key = SerilogLogger.GetKeyWithoutFirstSymbol(SerilogLogger.DestructureDictionary, key);
+ destructureObject = true;
+ }
+ else if (key.StartsWith("$"))
+ {
+ key = SerilogLogger.GetKeyWithoutFirstSymbol(SerilogLogger.StringifyDictionary, key);
+ value = value?.ToString();
+ }
- // In case one of the parent scopes has been disposed out-of-order, don't
- // just blindly reinstate our own parent.
- for (var scan = _provider.CurrentScope; scan != null; scan = scan.Parent)
- {
- if (ReferenceEquals(scan, this))
- _provider.CurrentScope = Parent;
- }
+ var property = propertyFactory.CreateProperty(key, value, destructureObject);
+ logEvent.AddPropertyIfAbsent(property);
+ }
- _chainedDisposable?.Dispose();
- }
+ if (_state == null)
+ {
+ scopeItem = null;
+ return;
}
- public void EnrichAndCreateScopeItem(LogEvent logEvent, ILogEventPropertyFactory propertyFactory, out LogEventPropertyValue scopeItem)
+ // Eliminates boxing of Dictionary.Enumerator for the most common use case
+ if (_state is Dictionary dictionary)
{
- if (_state == null)
- {
- scopeItem = null;
- return;
- }
+ scopeItem = null; // Unless it's `FormattedLogValues`, these are treated as property bags rather than scope items.
- if (_state is IEnumerable> stateProperties)
+ foreach (var stateProperty in dictionary)
{
- scopeItem = null; // Unless it's `FormattedLogValues`, these are treated as property bags rather than scope items.
-
- foreach (var stateProperty in stateProperties)
- {
- if (stateProperty.Key == SerilogLoggerProvider.OriginalFormatPropertyName && stateProperty.Value is string)
- {
- scopeItem = new ScalarValue(_state.ToString());
- continue;
- }
-
- var key = stateProperty.Key;
- var destructureObject = false;
- var value = stateProperty.Value;
-
- if (key.StartsWith("@"))
- {
- key = key.Substring(1);
- destructureObject = true;
- }
-
- if (key.StartsWith("$"))
- {
- key = key.Substring(1);
- value = value?.ToString();
- }
-
- var property = propertyFactory.CreateProperty(key, value, destructureObject);
- logEvent.AddPropertyIfAbsent(property);
- }
+ if (stateProperty.Key == SerilogLoggerProvider.OriginalFormatPropertyName && stateProperty.Value is string)
+ scopeItem = new ScalarValue(_state.ToString());
+ else
+ AddProperty(stateProperty);
}
- else
+ }
+ else if (_state is IEnumerable> stateProperties)
+ {
+ scopeItem = null; // Unless it's `FormattedLogValues`, these are treated as property bags rather than scope items.
+
+ foreach (var stateProperty in stateProperties)
{
- scopeItem = propertyFactory.CreateProperty(NoName, _state).Value;
+ if (stateProperty.Key == SerilogLoggerProvider.OriginalFormatPropertyName && stateProperty.Value is string)
+ scopeItem = new ScalarValue(_state.ToString());
+ else
+ AddProperty(stateProperty);
}
}
+ else
+ {
+ scopeItem = propertyFactory.CreateProperty(NoName, _state).Value;
+ }
}
}
diff --git a/src/Serilog.Extensions.Logging/LoggerSinkConfigurationExtensions.cs b/src/Serilog.Extensions.Logging/LoggerSinkConfigurationExtensions.cs
index 85064db..afbea79 100644
--- a/src/Serilog.Extensions.Logging/LoggerSinkConfigurationExtensions.cs
+++ b/src/Serilog.Extensions.Logging/LoggerSinkConfigurationExtensions.cs
@@ -1,4 +1,4 @@
-// Copyright 2019 Serilog Contributors
+// Copyright 2019 Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,38 +12,36 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System;
using Serilog.Configuration;
using Serilog.Core;
using Serilog.Events;
using Serilog.Extensions.Logging;
-namespace Serilog
+namespace Serilog;
+
+///
+/// Extensions for .
+///
+public static class LoggerSinkConfigurationExtensions
{
///
- /// Extensions for .
+ /// Write Serilog events to the providers in .
///
- public static class LoggerSinkConfigurationExtensions
+ /// The `WriteTo` object.
+ /// A to write events to.
+ /// The minimum level for
+ /// events passed through the sink. Ignored when is specified.
+ /// A switch allowing the pass-through minimum level
+ /// to be changed at runtime.
+ /// A to allow method chaining.
+ public static LoggerConfiguration Providers(
+ this LoggerSinkConfiguration configuration,
+ LoggerProviderCollection providers,
+ LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
+ LoggingLevelSwitch? levelSwitch = null)
{
- ///
- /// Write Serilog events to the providers in .
- ///
- /// The `WriteTo` object.
- /// A to write events to.
- /// The minimum level for
- /// events passed through the sink. Ignored when is specified.
- /// A switch allowing the pass-through minimum level
- /// to be changed at runtime.
- /// A to allow method chaining.
- public static LoggerConfiguration Providers(
- this LoggerSinkConfiguration configuration,
- LoggerProviderCollection providers,
- LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
- LoggingLevelSwitch levelSwitch = null)
- {
- if (configuration == null) throw new ArgumentNullException(nameof(configuration));
- if (providers == null) throw new ArgumentNullException(nameof(providers));
- return configuration.Sink(new LoggerProviderCollectionSink(providers), restrictedToMinimumLevel, levelSwitch);
- }
+ if (configuration == null) throw new ArgumentNullException(nameof(configuration));
+ if (providers == null) throw new ArgumentNullException(nameof(providers));
+ return configuration.Sink(new LoggerProviderCollectionSink(providers), restrictedToMinimumLevel, levelSwitch);
}
}
diff --git a/src/Serilog.Extensions.Logging/Properties/AssemblyInfo.cs b/src/Serilog.Extensions.Logging/Properties/AssemblyInfo.cs
index 37885a5..50afb45 100644
--- a/src/Serilog.Extensions.Logging/Properties/AssemblyInfo.cs
+++ b/src/Serilog.Extensions.Logging/Properties/AssemblyInfo.cs
@@ -1,7 +1,12 @@
-using System.Reflection;
+global using System;
+global using System.Collections.Generic;
+global using System.Linq;
+global using System.Threading;
+
+using System.Reflection;
using System.Runtime.CompilerServices;
-[assembly: AssemblyVersion("2.0.0.0")]
+[assembly: AssemblyVersion("7.0.0.0")]
[assembly: InternalsVisibleTo("Serilog.Extensions.Logging.Tests, PublicKey=" +
"0024000004800000940000000602000000240000525341310004000001000100fb8d13fd344a1c" +
diff --git a/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj b/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj
index f6d4bc1..33d764b 100644
--- a/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj
+++ b/src/Serilog.Extensions.Logging/Serilog.Extensions.Logging.csproj
@@ -2,33 +2,37 @@
Low-level Serilog provider for Microsoft.Extensions.Logging
- 3.1.0
+
+ 7.0.0
Microsoft;Serilog Contributors
- netstandard2.0
- true
+
+ net462;netstandard2.0;netstandard2.1;net6.0;net7.0
true
- Serilog.Extensions.Logging
- ../../assets/Serilog.snk
- true
- true
- Serilog.Extensions.Logging
serilog;Microsoft.Extensions.Logging
serilog-extension-nuget.png
https://github.com/serilog/serilog-extensions-logging
Apache-2.0
- https://github.com/serilog/serilog-extensions-logging
- git
false
Serilog
+ git
+ embedded
+ true
+ true
+ True
+ README.md
+
+ NU5118
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/src/Serilog.Extensions.Logging/SerilogLoggerFactoryExtensions.cs b/src/Serilog.Extensions.Logging/SerilogLoggerFactoryExtensions.cs
index 5292603..b9eb557 100644
--- a/src/Serilog.Extensions.Logging/SerilogLoggerFactoryExtensions.cs
+++ b/src/Serilog.Extensions.Logging/SerilogLoggerFactoryExtensions.cs
@@ -1,36 +1,34 @@
// 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;
-namespace Serilog
+namespace Serilog;
+
+///
+/// Extends with Serilog configuration methods.
+///
+public static class SerilogLoggerFactoryExtensions
{
///
- /// Extends with Serilog configuration methods.
+ /// Add Serilog to the logging pipeline.
///
- public static class SerilogLoggerFactoryExtensions
+ /// The logger factory to configure.
+ /// The Serilog logger; if not supplied, the static will be used.
+ /// 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.
+ /// Reference to the supplied .
+ public static ILoggerFactory AddSerilog(
+ this ILoggerFactory factory,
+ ILogger? logger = null,
+ bool dispose = false)
{
- ///
- /// Add Serilog to the logging pipeline.
- ///
- /// The logger factory to configure.
- /// The Serilog logger; if not supplied, the static will be used.
- /// 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.
- /// Reference to the supplied .
- public static ILoggerFactory AddSerilog(
- this ILoggerFactory factory,
- ILogger logger = null,
- bool dispose = false)
- {
- if (factory == null) throw new ArgumentNullException(nameof(factory));
+ if (factory == null) throw new ArgumentNullException(nameof(factory));
- factory.AddProvider(new SerilogLoggerProvider(logger, dispose));
+ factory.AddProvider(new SerilogLoggerProvider(logger, dispose));
- return factory;
- }
+ return factory;
}
-}
\ No newline at end of file
+}
diff --git a/src/Serilog.Extensions.Logging/SerilogLoggingBuilderExtensions.cs b/src/Serilog.Extensions.Logging/SerilogLoggingBuilderExtensions.cs
index 2cf0008..1757de0 100644
--- a/src/Serilog.Extensions.Logging/SerilogLoggingBuilderExtensions.cs
+++ b/src/Serilog.Extensions.Logging/SerilogLoggingBuilderExtensions.cs
@@ -1,4 +1,4 @@
-// Copyright 2017 Serilog Contributors
+// Copyright 2017 Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,43 +12,41 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Serilog.Extensions.Logging;
-namespace Serilog
+namespace Serilog;
+
+///
+/// Extends with Serilog configuration methods.
+///
+public static class SerilogLoggingBuilderExtensions
{
///
- /// Extends with Serilog configuration methods.
+ /// Add Serilog to the logging pipeline.
///
- public static class SerilogLoggingBuilderExtensions
+ /// The to add logging provider to.
+ /// The Serilog logger; if not supplied, the static will be used.
+ /// 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.
+ /// Reference to the supplied .
+ public static ILoggingBuilder AddSerilog(this ILoggingBuilder builder, ILogger? logger = null, bool dispose = false)
{
- ///
- /// Add Serilog to the logging pipeline.
- ///
- /// The to add logging provider to.
- /// The Serilog logger; if not supplied, the static will be used.
- /// 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.
- /// 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));
+ if (builder == null) throw new ArgumentNullException(nameof(builder));
- if (dispose)
- {
- builder.Services.AddSingleton(services => new SerilogLoggerProvider(logger, true));
- }
- else
- {
- builder.AddProvider(new SerilogLoggerProvider(logger));
- }
+ if (dispose)
+ {
+ builder.Services.AddSingleton(services => new SerilogLoggerProvider(logger, true));
+ }
+ else
+ {
+ builder.AddProvider(new SerilogLoggerProvider(logger));
+ }
- builder.AddFilter(null, LogLevel.Trace);
+ builder.AddFilter(null, LogLevel.Trace);
- return builder;
- }
+ return builder;
}
}
diff --git a/test/Serilog.Extensions.Logging.Benchmarks/LogEventBenchmark.cs b/test/Serilog.Extensions.Logging.Benchmarks/LogEventBenchmark.cs
new file mode 100644
index 0000000..995d462
--- /dev/null
+++ b/test/Serilog.Extensions.Logging.Benchmarks/LogEventBenchmark.cs
@@ -0,0 +1,65 @@
+// Copyright 2019 Serilog Contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Running;
+using Microsoft.Extensions.Logging;
+using Xunit;
+using IMelLogger = Microsoft.Extensions.Logging.ILogger;
+
+#pragma warning disable xUnit1013 // Public method should be marked as test
+
+namespace Serilog.Extensions.Logging.Benchmarks
+{
+ [MemoryDiagnoser]
+ public class LogEventBenchmark
+ {
+ private class Person
+ {
+ public string? Name { get; set; }
+ public int Age { get; set; }
+ public override string ToString() => "Fixed text";
+ }
+
+ readonly IMelLogger _melLogger;
+ readonly Person _bob, _alice;
+
+ public LogEventBenchmark()
+ {
+ var underlyingLogger = new LoggerConfiguration().CreateLogger();
+ _melLogger = new SerilogLoggerProvider(underlyingLogger).CreateLogger(GetType().FullName!);
+ _bob = new Person { Name = "Bob", Age = 42 };
+ _alice = new Person { Name = "Alice", Age = 42 };
+ }
+
+ [Fact]
+ public void Benchmark()
+ {
+ BenchmarkRunner.Run();
+ }
+
+ [Benchmark]
+ public void LogInformation()
+ {
+ _melLogger.LogInformation("Hi {@User} from {$Me}", _bob, _alice);
+ }
+
+ [Benchmark]
+ public void LogInformationScoped()
+ {
+ using (var scope = _melLogger.BeginScope("Hi {@User} from {$Me}", _bob, _alice))
+ _melLogger.LogInformation("Hi");
+ }
+ }
+}
diff --git a/test/Serilog.Extensions.Logging.Benchmarks/LogEventConstructionBenchmark.cs b/test/Serilog.Extensions.Logging.Benchmarks/LogEventConstructionBenchmark.cs
index 51cae2e..415867a 100644
--- a/test/Serilog.Extensions.Logging.Benchmarks/LogEventConstructionBenchmark.cs
+++ b/test/Serilog.Extensions.Logging.Benchmarks/LogEventConstructionBenchmark.cs
@@ -1,4 +1,4 @@
-// Copyright 2019 Serilog Contributors
+// Copyright 2019 Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using Microsoft.Extensions.Logging;
@@ -21,83 +20,82 @@
using Serilog.Extensions.Logging.Benchmarks.Support;
using Xunit;
-namespace Serilog.Extensions.Logging.Benchmarks
+namespace Serilog.Extensions.Logging.Benchmarks;
+
+[MemoryDiagnoser]
+public class LogEventConstructionBenchmark
{
- [MemoryDiagnoser]
- public class LogEventConstructionBenchmark
+ readonly IMelLogger _melLogger;
+ readonly ILogger _serilogContextualLogger;
+ readonly CapturingSink _sink;
+ const int LowId = 10, HighId = 101;
+ const string Template = "This is an event";
+
+ public LogEventConstructionBenchmark()
{
- readonly IMelLogger _melLogger;
- readonly ILogger _serilogContextualLogger;
- readonly CapturingSink _sink;
- const int LowId = 10, HighId = 101;
- const string Template = "This is an event";
+ _sink = new CapturingSink();
+ var underlyingLogger = new LoggerConfiguration().WriteTo.Sink(_sink).CreateLogger();
+ _serilogContextualLogger = underlyingLogger.ForContext();
+ _melLogger = new SerilogLoggerProvider(underlyingLogger).CreateLogger(GetType().FullName!);
+ }
- public LogEventConstructionBenchmark()
+ static void VerifyEventId(LogEvent? evt, int? expectedId)
+ {
+ if (evt == null) throw new ArgumentNullException(nameof(evt));
+ if (expectedId == null)
{
- _sink = new CapturingSink();
- var underlyingLogger = new LoggerConfiguration().WriteTo.Sink(_sink).CreateLogger();
- _serilogContextualLogger = underlyingLogger.ForContext();
- _melLogger = new SerilogLoggerProvider(underlyingLogger).CreateLogger(GetType().FullName);
+ Assert.False(evt.Properties.TryGetValue("EventId", out _));
}
-
- static void VerifyEventId(LogEvent evt, int? expectedId)
+ else
{
- if (evt == null) throw new ArgumentNullException(nameof(evt));
- if (expectedId == null)
- {
- Assert.False(evt.Properties.TryGetValue("EventId", out _));
- }
- else
- {
- Assert.True(evt.Properties.TryGetValue("EventId", out var eventIdValue));
- var structure = Assert.IsType(eventIdValue);
- var idValue = Assert.Single(structure.Properties, p => p.Name == "Id")?.Value;
- var scalar = Assert.IsType(idValue);
- Assert.Equal(expectedId.Value, scalar.Value);
- }
+ Assert.True(evt.Properties.TryGetValue("EventId", out var eventIdValue));
+ var structure = Assert.IsType(eventIdValue);
+ var idValue = Assert.Single(structure.Properties, p => p.Name == "Id")?.Value;
+ var scalar = Assert.IsType(idValue);
+ Assert.Equal(expectedId.Value, scalar.Value);
}
+ }
- [Fact]
- public void Verify()
- {
- VerifyEventId(Native(), null);
- VerifyEventId(NoId(), null);
- VerifyEventId(LowNumbered(), LowId);
- VerifyEventId(HighNumbered(), HighId);
- }
+ [Fact]
+ public void Verify()
+ {
+ VerifyEventId(Native(), null);
+ VerifyEventId(NoId(), null);
+ VerifyEventId(LowNumbered(), LowId);
+ VerifyEventId(HighNumbered(), HighId);
+ }
- [Fact]
- public void Benchmark()
- {
- BenchmarkRunner.Run();
- }
+ [Fact]
+ public void Benchmark()
+ {
+ BenchmarkRunner.Run();
+ }
- [Benchmark(Baseline = true)]
- public LogEvent Native()
- {
- _serilogContextualLogger.Information(Template);
- return _sink.Collect();
- }
+ [Benchmark(Baseline = true)]
+ public LogEvent? Native()
+ {
+ _serilogContextualLogger.Information(Template);
+ return _sink.Collect();
+ }
- [Benchmark]
- public LogEvent NoId()
- {
- _melLogger.LogInformation(Template);
- return _sink.Collect();
- }
+ [Benchmark]
+ public LogEvent? NoId()
+ {
+ _melLogger.LogInformation(Template);
+ return _sink.Collect();
+ }
- [Benchmark]
- public LogEvent LowNumbered()
- {
- _melLogger.LogInformation(LowId, Template);
- return _sink.Collect();
- }
+ [Benchmark]
+ public LogEvent? LowNumbered()
+ {
+ _melLogger.LogInformation(LowId, Template);
+ return _sink.Collect();
+ }
- [Benchmark]
- public LogEvent HighNumbered()
- {
- _melLogger.LogInformation(HighId, Template);
- return _sink.Collect();
- }
+ [Benchmark]
+ public LogEvent? HighNumbered()
+ {
+ _melLogger.LogInformation(HighId, Template);
+ return _sink.Collect();
}
}
diff --git a/test/Serilog.Extensions.Logging.Benchmarks/Serilog.Extensions.Logging.Benchmarks.csproj b/test/Serilog.Extensions.Logging.Benchmarks/Serilog.Extensions.Logging.Benchmarks.csproj
index 7840f21..24fdb78 100644
--- a/test/Serilog.Extensions.Logging.Benchmarks/Serilog.Extensions.Logging.Benchmarks.csproj
+++ b/test/Serilog.Extensions.Logging.Benchmarks/Serilog.Extensions.Logging.Benchmarks.csproj
@@ -1,8 +1,8 @@
-
+
- netcoreapp2.2
- true
+ net7.0
+ enable
@@ -10,17 +10,10 @@
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
-
-
-
+
+
+
+
diff --git a/test/Serilog.Extensions.Logging.Benchmarks/Support/CapturingSink.cs b/test/Serilog.Extensions.Logging.Benchmarks/Support/CapturingSink.cs
index 3913561..555ea88 100644
--- a/test/Serilog.Extensions.Logging.Benchmarks/Support/CapturingSink.cs
+++ b/test/Serilog.Extensions.Logging.Benchmarks/Support/CapturingSink.cs
@@ -1,4 +1,4 @@
-// Copyright 2019 Serilog Contributors
+// Copyright 2019 Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -15,22 +15,21 @@
using Serilog.Core;
using Serilog.Events;
-namespace Serilog.Extensions.Logging.Benchmarks.Support
+namespace Serilog.Extensions.Logging.Benchmarks.Support;
+
+class CapturingSink : ILogEventSink
{
- class CapturingSink : ILogEventSink
- {
- LogEvent _emitted;
+ LogEvent? _emitted;
- public void Emit(LogEvent logEvent)
- {
- _emitted = logEvent;
- }
+ public void Emit(LogEvent logEvent)
+ {
+ _emitted = logEvent;
+ }
- public LogEvent Collect()
- {
- var collected = _emitted;
- _emitted = null;
- return collected;
- }
+ public LogEvent? Collect()
+ {
+ var collected = _emitted;
+ _emitted = null;
+ return collected;
}
}
diff --git a/test/Serilog.Extensions.Logging.Tests/ApiApprovalTests.cs b/test/Serilog.Extensions.Logging.Tests/ApiApprovalTests.cs
new file mode 100644
index 0000000..68575f6
--- /dev/null
+++ b/test/Serilog.Extensions.Logging.Tests/ApiApprovalTests.cs
@@ -0,0 +1,26 @@
+#if NET7_0
+
+using PublicApiGenerator;
+using Shouldly;
+using Xunit;
+
+namespace Serilog.Extensions.Logging.Tests;
+
+public class ApiApprovalTests
+{
+ [Fact]
+ public void PublicApi_Should_Not_Change_Unintentionally()
+ {
+ var assembly = typeof(LoggerSinkConfigurationExtensions).Assembly;
+ var publicApi = assembly.GeneratePublicApi(
+ new()
+ {
+ IncludeAssemblyAttributes = false,
+ ExcludeAttributes = new[] { "System.Diagnostics.DebuggerDisplayAttribute" },
+ });
+
+ publicApi.ShouldMatchApproved(options => options.WithFilenameGenerator((_, _, fileType, fileExtension) => $"{assembly.GetName().Name!}.{fileType}.{fileExtension}"));
+ }
+}
+
+#endif
diff --git a/test/Serilog.Extensions.Logging.Tests/LoggerProviderCollectionSinkTests.cs b/test/Serilog.Extensions.Logging.Tests/LoggerProviderCollectionSinkTests.cs
index 0be1b4c..dad17b5 100644
--- a/test/Serilog.Extensions.Logging.Tests/LoggerProviderCollectionSinkTests.cs
+++ b/test/Serilog.Extensions.Logging.Tests/LoggerProviderCollectionSinkTests.cs
@@ -1,85 +1,83 @@
// 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
+namespace Serilog.Extensions.Logging.Tests;
+
+public class LoggerProviderCollectionSinkTests
{
- 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()
{
- 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);
- }
+ 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/Serilog.Extensions.Logging.Tests.csproj b/test/Serilog.Extensions.Logging.Tests/Serilog.Extensions.Logging.Tests.csproj
index e1a144a..94c27dc 100644
--- a/test/Serilog.Extensions.Logging.Tests/Serilog.Extensions.Logging.Tests.csproj
+++ b/test/Serilog.Extensions.Logging.Tests/Serilog.Extensions.Logging.Tests.csproj
@@ -1,13 +1,8 @@
- netcoreapp2.0;net472
- Serilog.Extensions.Logging.Tests
- ../../assets/Serilog.snk
- true
- true
- Serilog.Extensions.Logging.Tests
- true
+ net7.0;net472
+ enable
@@ -15,9 +10,11 @@
-
-
-
+
+
+
+
+
diff --git a/test/Serilog.Extensions.Logging.Tests/Serilog.Extensions.Logging.approved.txt b/test/Serilog.Extensions.Logging.Tests/Serilog.Extensions.Logging.approved.txt
new file mode 100644
index 0000000..83cb966
--- /dev/null
+++ b/test/Serilog.Extensions.Logging.Tests/Serilog.Extensions.Logging.approved.txt
@@ -0,0 +1,46 @@
+namespace Serilog.Extensions.Logging
+{
+ public static class LevelConvert
+ {
+ public static Microsoft.Extensions.Logging.LogLevel ToExtensionsLevel(Serilog.Events.LogEventLevel logEventLevel) { }
+ public static Serilog.Events.LogEventLevel ToSerilogLevel(Microsoft.Extensions.Logging.LogLevel logLevel) { }
+ }
+ public class LoggerProviderCollection : System.IDisposable
+ {
+ public LoggerProviderCollection() { }
+ public System.Collections.Generic.IEnumerable Providers { get; }
+ public void AddProvider(Microsoft.Extensions.Logging.ILoggerProvider provider) { }
+ public void Dispose() { }
+ }
+ public class SerilogLoggerFactory : Microsoft.Extensions.Logging.ILoggerFactory, System.IDisposable
+ {
+ public SerilogLoggerFactory(Serilog.ILogger? logger = null, bool dispose = false, Serilog.Extensions.Logging.LoggerProviderCollection? providerCollection = null) { }
+ public void AddProvider(Microsoft.Extensions.Logging.ILoggerProvider provider) { }
+ public Microsoft.Extensions.Logging.ILogger CreateLogger(string categoryName) { }
+ public void Dispose() { }
+ }
+ [Microsoft.Extensions.Logging.ProviderAlias("Serilog")]
+ public class SerilogLoggerProvider : Microsoft.Extensions.Logging.ILoggerProvider, Serilog.Core.ILogEventEnricher, System.IDisposable
+ {
+ public SerilogLoggerProvider(Serilog.ILogger? logger = null, bool dispose = false) { }
+ public System.IDisposable BeginScope(T state) { }
+ public Microsoft.Extensions.Logging.ILogger CreateLogger(string name) { }
+ public void Dispose() { }
+ public void Enrich(Serilog.Events.LogEvent logEvent, Serilog.Core.ILogEventPropertyFactory propertyFactory) { }
+ }
+}
+namespace Serilog
+{
+ public static class LoggerSinkConfigurationExtensions
+ {
+ public static Serilog.LoggerConfiguration Providers(this Serilog.Configuration.LoggerSinkConfiguration configuration, Serilog.Extensions.Logging.LoggerProviderCollection providers, Serilog.Events.LogEventLevel restrictedToMinimumLevel = 0, Serilog.Core.LoggingLevelSwitch? levelSwitch = null) { }
+ }
+ public static class SerilogLoggerFactoryExtensions
+ {
+ public static Microsoft.Extensions.Logging.ILoggerFactory AddSerilog(this Microsoft.Extensions.Logging.ILoggerFactory factory, Serilog.ILogger? logger = null, bool dispose = false) { }
+ }
+ public static class SerilogLoggingBuilderExtensions
+ {
+ public static Microsoft.Extensions.Logging.ILoggingBuilder AddSerilog(this Microsoft.Extensions.Logging.ILoggingBuilder builder, Serilog.ILogger? logger = null, bool dispose = false) { }
+ }
+}
\ No newline at end of file
diff --git a/test/Serilog.Extensions.Logging.Tests/SerilogLogValuesTests.cs b/test/Serilog.Extensions.Logging.Tests/SerilogLogValuesTests.cs
index d5a777e..a1f3025 100644
--- a/test/Serilog.Extensions.Logging.Tests/SerilogLogValuesTests.cs
+++ b/test/Serilog.Extensions.Logging.Tests/SerilogLogValuesTests.cs
@@ -1,53 +1,50 @@
using Serilog.Events;
using Serilog.Parsing;
-using System.Collections.Generic;
-using System.Linq;
using Xunit;
-namespace Serilog.Extensions.Logging.Tests
+namespace Serilog.Extensions.Logging.Tests;
+
+public class SerilogLogValuesTests
{
- public class SerilogLogValuesTests
+ [Fact]
+ public void OriginalFormatIsExposed()
{
- [Fact]
- public void OriginalFormatIsExposed()
- {
- const string format = "Hello, {Name}!";
- var mt = new MessageTemplateParser().Parse(format);
- var lv = new SerilogLogValues(mt, new Dictionary());
- var kvp = lv.Single();
- Assert.Equal("{OriginalFormat}", kvp.Key);
- Assert.Equal(format, kvp.Value);
- }
+ const string format = "Hello, {Name}!";
+ var mt = new MessageTemplateParser().Parse(format);
+ var lv = new SerilogLogValues(mt, new Dictionary());
+ var kvp = lv.Single();
+ Assert.Equal("{OriginalFormat}", kvp.Key);
+ Assert.Equal(format, kvp.Value);
+ }
- [Fact]
- public void ScalarPropertiesAreSimplified()
- {
- const string name = "Scalar";
- var scalar = 15;
- var lv = new SerilogLogValues(MessageTemplate.Empty, new Dictionary { [name] = new ScalarValue(scalar) });
- var kvp = lv.Single(p => p.Key == name);
- var sv = Assert.IsType(kvp.Value);
- Assert.Equal(scalar, sv);
- }
+ [Fact]
+ public void ScalarPropertiesAreSimplified()
+ {
+ const string name = "Scalar";
+ var scalar = 15;
+ var lv = new SerilogLogValues(MessageTemplate.Empty, new Dictionary { [name] = new ScalarValue(scalar) });
+ var kvp = lv.Single(p => p.Key == name);
+ var sv = Assert.IsType(kvp.Value);
+ Assert.Equal(scalar, sv);
+ }
- [Fact]
- public void NonscalarPropertiesAreWrapped()
- {
- const string name = "Sequence";
- var seq = new SequenceValue(Enumerable.Empty());
- var lv = new SerilogLogValues(MessageTemplate.Empty, new Dictionary { [name] = seq });
- var kvp = lv.Single(p => p.Key == name);
- var sv = Assert.IsType(kvp.Value);
- Assert.Equal(seq, sv);
- }
+ [Fact]
+ public void NonscalarPropertiesAreWrapped()
+ {
+ const string name = "Sequence";
+ var seq = new SequenceValue(Enumerable.Empty());
+ var lv = new SerilogLogValues(MessageTemplate.Empty, new Dictionary { [name] = seq });
+ var kvp = lv.Single(p => p.Key == name);
+ var sv = Assert.IsType(kvp.Value);
+ Assert.Equal(seq, sv);
+ }
- [Fact]
- public void MessageTemplatesAreRendered()
- {
- const string format = "Hello, {Name}!";
- var mt = new MessageTemplateParser().Parse(format);
- var lv = new SerilogLogValues(mt, new Dictionary { ["Name"] = new ScalarValue("World") });
- Assert.Equal("Hello, \"World\"!", lv.ToString());
- }
+ [Fact]
+ public void MessageTemplatesAreRendered()
+ {
+ const string format = "Hello, {Name}!";
+ var mt = new MessageTemplateParser().Parse(format);
+ var lv = new SerilogLogValues(mt, new Dictionary { ["Name"] = new ScalarValue("World") });
+ Assert.Equal("Hello, \"World\"!", lv.ToString());
}
}
diff --git a/test/Serilog.Extensions.Logging.Tests/SerilogLoggerTests.cs b/test/Serilog.Extensions.Logging.Tests/SerilogLoggerTests.cs
index f37e9eb..94da8bb 100644
--- a/test/Serilog.Extensions.Logging.Tests/SerilogLoggerTests.cs
+++ b/test/Serilog.Extensions.Logging.Tests/SerilogLoggerTests.cs
@@ -1,454 +1,496 @@
-// Copyright (c) .NET Foundation. All rights reserved.
+// 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;
using Serilog.Events;
using Microsoft.Extensions.Logging;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
using Serilog.Debugging;
using Serilog.Extensions.Logging.Tests.Support;
using Xunit;
+using Serilog.Core;
-namespace Serilog.Extensions.Logging.Tests
+namespace Serilog.Extensions.Logging.Tests;
+
+public class SerilogLoggerTest
{
- public class SerilogLoggerTest
+ const string Name = "test";
+ const string TestMessage = "This is a test";
+
+ static Tuple SetUp(LogLevel logLevel)
{
- const string Name = "test";
- const string TestMessage = "This is a test";
+ var sink = new SerilogSink();
- static Tuple SetUp(LogLevel logLevel)
- {
- var sink = new SerilogSink();
+ var serilogLogger = new LoggerConfiguration()
+ .WriteTo.Sink(sink)
+ .MinimumLevel.Is(LevelConvert.ToSerilogLevel(logLevel))
+ .CreateLogger();
- var serilogLogger = new LoggerConfiguration()
- .WriteTo.Sink(sink)
- .MinimumLevel.Is(LevelConvert.ToSerilogLevel(logLevel))
- .CreateLogger();
+ var provider = new SerilogLoggerProvider(serilogLogger);
+ var logger = (SerilogLogger)provider.CreateLogger(Name);
- var provider = new SerilogLoggerProvider(serilogLogger);
- var logger = (SerilogLogger)provider.CreateLogger(Name);
+ return new Tuple(logger, sink);
+ }
- return new Tuple(logger, sink);
- }
+ [Fact]
+ public void LogsWhenNullFilterGiven()
+ {
+ var (logger, sink) = SetUp(LogLevel.Trace);
- [Fact]
- public void LogsWhenNullFilterGiven()
- {
- var (logger, sink) = SetUp(LogLevel.Trace);
+ logger.Log(LogLevel.Information, 0, TestMessage, null!, null!);
- logger.Log(LogLevel.Information, 0, TestMessage, null, null);
+ Assert.Single(sink.Writes);
+ }
- Assert.Equal(1, sink.Writes.Count);
- }
+ [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!);
+ logger.Log(LogLevel.None, 0, TestMessage, null!, null!);
+
+ Assert.Equal(6, sink.Writes.Count);
+ Assert.Equal(LogEventLevel.Verbose, sink.Writes[0].Level);
+ Assert.Equal(LogEventLevel.Debug, sink.Writes[1].Level);
+ Assert.Equal(LogEventLevel.Information, sink.Writes[2].Level);
+ Assert.Equal(LogEventLevel.Warning, sink.Writes[3].Level);
+ Assert.Equal(LogEventLevel.Error, sink.Writes[4].Level);
+ Assert.Equal(LogEventLevel.Fatal, sink.Writes[5].Level);
+ }
- [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(LogEventLevel.Verbose, sink.Writes[0].Level);
- Assert.Equal(LogEventLevel.Debug, sink.Writes[1].Level);
- Assert.Equal(LogEventLevel.Information, sink.Writes[2].Level);
- Assert.Equal(LogEventLevel.Warning, sink.Writes[3].Level);
- Assert.Equal(LogEventLevel.Error, sink.Writes[4].Level);
- Assert.Equal(LogEventLevel.Fatal, sink.Writes[5].Level);
- }
- [Theory]
- [InlineData(LogLevel.Trace, LogLevel.Trace, 1)]
- [InlineData(LogLevel.Trace, LogLevel.Debug, 1)]
- [InlineData(LogLevel.Trace, LogLevel.Information, 1)]
- [InlineData(LogLevel.Trace, LogLevel.Warning, 1)]
- [InlineData(LogLevel.Trace, LogLevel.Error, 1)]
- [InlineData(LogLevel.Trace, LogLevel.Critical, 1)]
- [InlineData(LogLevel.Debug, LogLevel.Trace, 0)]
- [InlineData(LogLevel.Debug, LogLevel.Debug, 1)]
- [InlineData(LogLevel.Debug, LogLevel.Information, 1)]
- [InlineData(LogLevel.Debug, LogLevel.Warning, 1)]
- [InlineData(LogLevel.Debug, LogLevel.Error, 1)]
- [InlineData(LogLevel.Debug, LogLevel.Critical, 1)]
- [InlineData(LogLevel.Information, LogLevel.Trace, 0)]
- [InlineData(LogLevel.Information, LogLevel.Debug, 0)]
- [InlineData(LogLevel.Information, LogLevel.Information, 1)]
- [InlineData(LogLevel.Information, LogLevel.Warning, 1)]
- [InlineData(LogLevel.Information, LogLevel.Error, 1)]
- [InlineData(LogLevel.Information, LogLevel.Critical, 1)]
- [InlineData(LogLevel.Warning, LogLevel.Trace, 0)]
- [InlineData(LogLevel.Warning, LogLevel.Debug, 0)]
- [InlineData(LogLevel.Warning, LogLevel.Information, 0)]
- [InlineData(LogLevel.Warning, LogLevel.Warning, 1)]
- [InlineData(LogLevel.Warning, LogLevel.Error, 1)]
- [InlineData(LogLevel.Warning, LogLevel.Critical, 1)]
- [InlineData(LogLevel.Error, LogLevel.Trace, 0)]
- [InlineData(LogLevel.Error, LogLevel.Debug, 0)]
- [InlineData(LogLevel.Error, LogLevel.Information, 0)]
- [InlineData(LogLevel.Error, LogLevel.Warning, 0)]
- [InlineData(LogLevel.Error, LogLevel.Error, 1)]
- [InlineData(LogLevel.Error, LogLevel.Critical, 1)]
- [InlineData(LogLevel.Critical, LogLevel.Trace, 0)]
- [InlineData(LogLevel.Critical, LogLevel.Debug, 0)]
- [InlineData(LogLevel.Critical, LogLevel.Information, 0)]
- [InlineData(LogLevel.Critical, LogLevel.Warning, 0)]
- [InlineData(LogLevel.Critical, LogLevel.Error, 0)]
- [InlineData(LogLevel.Critical, LogLevel.Critical, 1)]
- public void LogsWhenEnabled(LogLevel minLevel, LogLevel logLevel, int expected)
- {
- var (logger, sink) = SetUp(minLevel);
+ [Theory]
+ [InlineData(LogLevel.Trace, true)]
+ [InlineData(LogLevel.Debug, true)]
+ [InlineData(LogLevel.Information, true)]
+ [InlineData(LogLevel.Warning, true)]
+ [InlineData(LogLevel.Error, true)]
+ [InlineData(LogLevel.Critical, true)]
+ [InlineData(LogLevel.None, false)]
+ public void IsEnabledCorrect(LogLevel logLevel, bool isEnabled)
+ {
+ var (logger, _) = SetUp(LogLevel.Trace);
- logger.Log(logLevel, 0, TestMessage, null, null);
+ Assert.Equal(isEnabled, logger.IsEnabled(logLevel));
+ }
- Assert.Equal(expected, sink.Writes.Count);
- }
+ [Theory]
+ [InlineData(LogLevel.Trace, LogLevel.Trace, 1)]
+ [InlineData(LogLevel.Trace, LogLevel.Debug, 1)]
+ [InlineData(LogLevel.Trace, LogLevel.Information, 1)]
+ [InlineData(LogLevel.Trace, LogLevel.Warning, 1)]
+ [InlineData(LogLevel.Trace, LogLevel.Error, 1)]
+ [InlineData(LogLevel.Trace, LogLevel.Critical, 1)]
+ [InlineData(LogLevel.Trace, LogLevel.None, 0)]
+ [InlineData(LogLevel.Debug, LogLevel.Trace, 0)]
+ [InlineData(LogLevel.Debug, LogLevel.Debug, 1)]
+ [InlineData(LogLevel.Debug, LogLevel.Information, 1)]
+ [InlineData(LogLevel.Debug, LogLevel.Warning, 1)]
+ [InlineData(LogLevel.Debug, LogLevel.Error, 1)]
+ [InlineData(LogLevel.Debug, LogLevel.Critical, 1)]
+ [InlineData(LogLevel.Debug, LogLevel.None, 0)]
+ [InlineData(LogLevel.Information, LogLevel.Trace, 0)]
+ [InlineData(LogLevel.Information, LogLevel.Debug, 0)]
+ [InlineData(LogLevel.Information, LogLevel.Information, 1)]
+ [InlineData(LogLevel.Information, LogLevel.Warning, 1)]
+ [InlineData(LogLevel.Information, LogLevel.Error, 1)]
+ [InlineData(LogLevel.Information, LogLevel.Critical, 1)]
+ [InlineData(LogLevel.Information, LogLevel.None, 0)]
+ [InlineData(LogLevel.Warning, LogLevel.Trace, 0)]
+ [InlineData(LogLevel.Warning, LogLevel.Debug, 0)]
+ [InlineData(LogLevel.Warning, LogLevel.Information, 0)]
+ [InlineData(LogLevel.Warning, LogLevel.Warning, 1)]
+ [InlineData(LogLevel.Warning, LogLevel.Error, 1)]
+ [InlineData(LogLevel.Warning, LogLevel.Critical, 1)]
+ [InlineData(LogLevel.Warning, LogLevel.None, 0)]
+ [InlineData(LogLevel.Error, LogLevel.Trace, 0)]
+ [InlineData(LogLevel.Error, LogLevel.Debug, 0)]
+ [InlineData(LogLevel.Error, LogLevel.Information, 0)]
+ [InlineData(LogLevel.Error, LogLevel.Warning, 0)]
+ [InlineData(LogLevel.Error, LogLevel.Error, 1)]
+ [InlineData(LogLevel.Error, LogLevel.Critical, 1)]
+ [InlineData(LogLevel.Error, LogLevel.None, 0)]
+ [InlineData(LogLevel.Critical, LogLevel.Trace, 0)]
+ [InlineData(LogLevel.Critical, LogLevel.Debug, 0)]
+ [InlineData(LogLevel.Critical, LogLevel.Information, 0)]
+ [InlineData(LogLevel.Critical, LogLevel.Warning, 0)]
+ [InlineData(LogLevel.Critical, LogLevel.Error, 0)]
+ [InlineData(LogLevel.Critical, LogLevel.Critical, 1)]
+ [InlineData(LogLevel.Critical, LogLevel.None, 0)]
+ public void LogsWhenEnabled(LogLevel minLevel, LogLevel logLevel, int expected)
+ {
+ var (logger, sink) = SetUp(minLevel);
- [Fact]
- public void LogsCorrectMessage()
- {
- var (logger, sink) = SetUp(LogLevel.Trace);
+ logger.Log(logLevel, 0, TestMessage, null!, null!);
- logger.Log(LogLevel.Information, 0, null, null, null);
- logger.Log(LogLevel.Information, 0, TestMessage, null, null);
- logger.Log(LogLevel.Information, 0, null, null, (_, __) => TestMessage);
+ Assert.Equal(expected, sink.Writes.Count);
+ }
- Assert.Equal(3, sink.Writes.Count);
+ [Fact]
+ public void LogsCorrectMessage()
+ {
+ var (logger, sink) = SetUp(LogLevel.Trace);
- Assert.Equal(1, sink.Writes[0].Properties.Count);
- Assert.Empty(sink.Writes[0].RenderMessage());
+ logger.Log(LogLevel.Information, 0, null!, null!, null!);
+ logger.Log(LogLevel.Information, 0, TestMessage, null!, null!);
+ logger.Log(LogLevel.Information, 0, null!, null!, (_, __) => TestMessage);
- Assert.Equal(2, sink.Writes[1].Properties.Count);
- Assert.True(sink.Writes[1].Properties.ContainsKey("State"));
- Assert.Equal(TestMessage, sink.Writes[1].RenderMessage());
+ Assert.Equal(3, sink.Writes.Count);
- Assert.Equal(2, sink.Writes[2].Properties.Count);
- Assert.True(sink.Writes[2].Properties.ContainsKey("Message"));
- Assert.Equal(TestMessage, sink.Writes[2].RenderMessage());
- }
+ Assert.Equal(1, sink.Writes[0].Properties.Count);
+ Assert.Empty(sink.Writes[0].RenderMessage());
- [Fact]
- public void CarriesException()
- {
- var (logger, sink) = SetUp(LogLevel.Trace);
+ Assert.Equal(2, sink.Writes[1].Properties.Count);
+ Assert.True(sink.Writes[1].Properties.ContainsKey("State"));
+ Assert.Equal(TestMessage, sink.Writes[1].RenderMessage());
- var exception = new Exception();
+ Assert.Equal(2, sink.Writes[2].Properties.Count);
+ Assert.True(sink.Writes[2].Properties.ContainsKey("Message"));
+ Assert.Equal(TestMessage, sink.Writes[2].RenderMessage());
+ }
- logger.Log(LogLevel.Information, 0, "Test", exception, null);
+ [Fact]
+ public void CarriesException()
+ {
+ var (logger, sink) = SetUp(LogLevel.Trace);
- Assert.Equal(1, sink.Writes.Count);
- Assert.Same(exception, sink.Writes[0].Exception);
- }
+ var exception = new Exception();
- [Fact]
- public void SingleScopeProperty()
- {
- var (logger, sink) = SetUp(LogLevel.Trace);
+ logger.Log(LogLevel.Information, 0, "Test", exception, null!);
- using (logger.BeginScope(new FoodScope("pizza")))
- {
- logger.Log(LogLevel.Information, 0, TestMessage, null, null);
- }
+ Assert.Single(sink.Writes);
+ Assert.Same(exception, sink.Writes[0].Exception);
+ }
- Assert.Equal(1, sink.Writes.Count);
- Assert.True(sink.Writes[0].Properties.ContainsKey("Name"));
- Assert.Equal("\"pizza\"", sink.Writes[0].Properties["Name"].ToString());
- }
+ [Fact]
+ public void SingleScopeProperty()
+ {
+ var (logger, sink) = SetUp(LogLevel.Trace);
- [Fact]
- public void StringifyScopeProperty()
+ using (logger.BeginScope(new FoodScope("pizza")))
{
- var (logger, sink) = SetUp(LogLevel.Trace);
+ logger.Log(LogLevel.Information, 0, TestMessage, null!, null!);
+ }
- using (logger.BeginScope("{$values}", new [] { 1, 2, 3, 4 }))
- {
- logger.Log(LogLevel.Information, 0, TestMessage, null, null);
- }
+ Assert.Single(sink.Writes);
+ Assert.True(sink.Writes[0].Properties.ContainsKey("Name"));
+ Assert.Equal("\"pizza\"", sink.Writes[0].Properties["Name"].ToString());
+ }
- 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 StringifyScopeProperty()
+ {
+ var (logger, sink) = SetUp(LogLevel.Trace);
- [Fact]
- public void NestedScopeSameProperty()
+ using (logger.BeginScope("{$values}", new [] { 1, 2, 3, 4 }))
{
- var (logger, sink) = SetUp(LogLevel.Trace);
+ logger.Log(LogLevel.Information, 0, TestMessage, null!, null!);
+ }
- using (logger.BeginScope(new FoodScope("avocado")))
- {
- using (logger.BeginScope(new FoodScope("bacon")))
- {
- logger.Log(LogLevel.Information, 0, TestMessage, null, null);
- }
- }
+ Assert.Single(sink.Writes);
+ Assert.True(sink.Writes[0].Properties.ContainsKey("values"));
+ Assert.Equal("\"System.Int32[]\"", sink.Writes[0].Properties["values"].ToString());
+ }
- // Should retain the property of the most specific scope
- Assert.Equal(1, sink.Writes.Count);
- Assert.True(sink.Writes[0].Properties.ContainsKey("Name"));
- Assert.Equal("\"bacon\"", sink.Writes[0].Properties["Name"].ToString());
- }
+ [Fact]
+ public void NestedScopeSameProperty()
+ {
+ var (logger, sink) = SetUp(LogLevel.Trace);
- [Fact]
- public void NestedScopesDifferentProperties()
+ using (logger.BeginScope(new FoodScope("avocado")))
{
- var (logger, sink) = SetUp(LogLevel.Trace);
-
- using (logger.BeginScope(new FoodScope("spaghetti")))
+ using (logger.BeginScope(new FoodScope("bacon")))
{
- using (logger.BeginScope(new LuckyScope(7)))
- {
- logger.Log(LogLevel.Information, 0, TestMessage, null, null);
- }
+ logger.Log(LogLevel.Information, 0, TestMessage, null!, null!);
}
-
- Assert.Equal(1, sink.Writes.Count);
- Assert.True(sink.Writes[0].Properties.ContainsKey("Name"));
- Assert.Equal("\"spaghetti\"", sink.Writes[0].Properties["Name"].ToString());
- Assert.True(sink.Writes[0].Properties.ContainsKey("LuckyNumber"));
- Assert.Equal("7", sink.Writes[0].Properties["LuckyNumber"].ToString());
}
- [Fact]
- public void CarriesMessageTemplateProperties()
+ // Should retain the property of the most specific scope
+ Assert.Single(sink.Writes);
+ Assert.True(sink.Writes[0].Properties.ContainsKey("Name"));
+ Assert.Equal("\"bacon\"", sink.Writes[0].Properties["Name"].ToString());
+ }
+
+ [Fact]
+ public void NestedScopesDifferentProperties()
+ {
+ var (logger, sink) = SetUp(LogLevel.Trace);
+
+ using (logger.BeginScope(new FoodScope("spaghetti")))
{
- var selfLog = new StringWriter();
- SelfLog.Enable(selfLog);
+ using (logger.BeginScope(new LuckyScope(7)))
+ {
+ logger.Log(LogLevel.Information, 0, TestMessage, null!, null!);
+ }
+ }
- var (logger, sink) = SetUp(LogLevel.Trace);
+ Assert.Single(sink.Writes);
+ Assert.True(sink.Writes[0].Properties.ContainsKey("Name"));
+ Assert.Equal("\"spaghetti\"", sink.Writes[0].Properties["Name"].ToString());
+ Assert.True(sink.Writes[0].Properties.ContainsKey("LuckyNumber"));
+ Assert.Equal("7", sink.Writes[0].Properties["LuckyNumber"].ToString());
+ }
- logger.LogInformation("Hello, {Recipient}", "World");
+ [Fact]
+ public void CarriesMessageTemplateProperties()
+ {
+ var selfLog = new StringWriter();
+ SelfLog.Enable(selfLog);
- Assert.True(sink.Writes[0].Properties.ContainsKey("Recipient"));
- Assert.Equal("\"World\"", sink.Writes[0].Properties["Recipient"].ToString());
- Assert.Equal("Hello, {Recipient}", sink.Writes[0].MessageTemplate.Text);
+ var (logger, sink) = SetUp(LogLevel.Trace);
- SelfLog.Disable();
- Assert.Empty(selfLog.ToString());
- }
+ logger.LogInformation("Hello, {Recipient}", "World");
- [Fact]
- public void CarriesMessageTemplatePropertiesWhenStringificationIsUsed()
- {
- var selfLog = new StringWriter();
- SelfLog.Enable(selfLog);
- var (logger, sink) = SetUp(LogLevel.Trace);
- var array = new[] { 1, 2, 3, 4 };
+ Assert.True(sink.Writes[0].Properties.ContainsKey("Recipient"));
+ Assert.Equal("\"World\"", sink.Writes[0].Properties["Recipient"].ToString());
+ Assert.Equal("Hello, {Recipient}", sink.Writes[0].MessageTemplate.Text);
- logger.LogInformation("{$array}", array);
+ SelfLog.Disable();
+ Assert.Empty(selfLog.ToString());
+ }
- 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);
+ [Fact]
+ public void CarriesMessageTemplatePropertiesWhenStringificationIsUsed()
+ {
+ var selfLog = new StringWriter();
+ SelfLog.Enable(selfLog);
+ var (logger, sink) = SetUp(LogLevel.Trace);
+ var array = new[] { 1, 2, 3, 4 };
- SelfLog.Disable();
- Assert.Empty(selfLog.ToString());
- }
+ logger.LogInformation("{$array}", array);
- [Fact]
- public void CarriesEventIdIfNonzero()
- {
- var (logger, sink) = SetUp(LogLevel.Trace);
+ 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);
- const int expected = 42;
+ SelfLog.Disable();
+ Assert.Empty(selfLog.ToString());
+ }
- logger.Log(LogLevel.Information, expected, "Test", null, null);
+ [Fact]
+ public void CarriesEventIdIfNonzero()
+ {
+ var (logger, sink) = SetUp(LogLevel.Trace);
- Assert.Equal(1, sink.Writes.Count);
+ const int expected = 42;
- var eventId = (StructureValue) sink.Writes[0].Properties["EventId"];
- var id = (ScalarValue) eventId.Properties.Single(p => p.Name == "Id").Value;
- Assert.Equal(42, id.Value);
- }
+ logger.Log(LogLevel.Information, expected, "Test", null!, null!);
- [Fact]
- public void WhenDisposeIsFalseProvidedLoggerIsNotDisposed()
- {
- var logger = new DisposeTrackingLogger();
- // ReSharper disable once RedundantArgumentDefaultValue
- var provider = new SerilogLoggerProvider(logger, false);
- provider.Dispose();
- Assert.False(logger.IsDisposed);
- }
+ Assert.Single(sink.Writes);
- [Fact]
- public void WhenDisposeIsTrueProvidedLoggerIsDisposed()
- {
- var logger = new DisposeTrackingLogger();
- var provider = new SerilogLoggerProvider(logger, true);
- provider.Dispose();
- Assert.True(logger.IsDisposed);
- }
+ var eventId = (StructureValue) sink.Writes[0].Properties["EventId"];
+ var id = (ScalarValue) eventId.Properties.Single(p => p.Name == "Id").Value;
+ Assert.Equal(42, id.Value);
+ }
- [Fact]
- public void BeginScopeDestructuresObjectsWhenDestructurerIsUsedInMessageTemplate()
- {
- var (logger, sink) = SetUp(LogLevel.Trace);
+ [Fact]
+ public void WhenDisposeIsFalseProvidedLoggerIsNotDisposed()
+ {
+ var logger = new DisposeTrackingLogger();
+ // ReSharper disable once RedundantArgumentDefaultValue
+ var provider = new SerilogLoggerProvider(logger, false);
+ provider.Dispose();
+ Assert.False(logger.IsDisposed);
+ }
- using (logger.BeginScope("{@Person}", new Person { FirstName = "John", LastName = "Smith" }))
- {
- logger.Log(LogLevel.Information, 0, TestMessage, null, null);
- }
+ [Fact]
+ public void WhenDisposeIsTrueProvidedLoggerIsDisposed()
+ {
+ var logger = new DisposeTrackingLogger();
+ var provider = new SerilogLoggerProvider(logger, true);
+ provider.Dispose();
+ Assert.True(logger.IsDisposed);
+ }
- Assert.Equal(1, sink.Writes.Count);
- Assert.True(sink.Writes[0].Properties.ContainsKey("Person"));
+ [Fact]
+ public void BeginScopeDestructuresObjectsWhenDestructurerIsUsedInMessageTemplate()
+ {
+ var (logger, sink) = SetUp(LogLevel.Trace);
- var person = (StructureValue)sink.Writes[0].Properties["Person"];
- var firstName = (ScalarValue)person.Properties.Single(p => p.Name == "FirstName").Value;
- var lastName = (ScalarValue)person.Properties.Single(p => p.Name == "LastName").Value;
- Assert.Equal("John", firstName.Value);
- Assert.Equal("Smith", lastName.Value);
+ using (logger.BeginScope("{@Person}", new Person { FirstName = "John", LastName = "Smith" }))
+ {
+ logger.Log(LogLevel.Information, 0, TestMessage, null!, null!);
}
- [Fact]
- public void BeginScopeDestructuresObjectsWhenDestructurerIsUsedInDictionary()
- {
- var (logger, sink) = SetUp(LogLevel.Trace);
-
- using (logger.BeginScope(new Dictionary {{ "@Person", new Person { FirstName = "John", LastName = "Smith" }}}))
- {
- logger.Log(LogLevel.Information, 0, TestMessage, null, null);
- }
+ Assert.Single(sink.Writes);
+ Assert.True(sink.Writes[0].Properties.ContainsKey("Person"));
- Assert.Equal(1, sink.Writes.Count);
- Assert.True(sink.Writes[0].Properties.ContainsKey("Person"));
+ var person = (StructureValue)sink.Writes[0].Properties["Person"];
+ var firstName = (ScalarValue)person.Properties.Single(p => p.Name == "FirstName").Value;
+ var lastName = (ScalarValue)person.Properties.Single(p => p.Name == "LastName").Value;
+ Assert.Equal("John", firstName.Value);
+ Assert.Equal("Smith", lastName.Value);
+ }
- var person = (StructureValue)sink.Writes[0].Properties["Person"];
- var firstName = (ScalarValue)person.Properties.Single(p => p.Name == "FirstName").Value;
- var lastName = (ScalarValue)person.Properties.Single(p => p.Name == "LastName").Value;
- Assert.Equal("John", firstName.Value);
- Assert.Equal("Smith", lastName.Value);
- }
+ [Fact]
+ public void BeginScopeDestructuresObjectsWhenDestructurerIsUsedInDictionary()
+ {
+ var (logger, sink) = SetUp(LogLevel.Trace);
- [Fact]
- public void BeginScopeDoesNotModifyKeyWhenDestructurerIsNotUsedInMessageTemplate()
+ using (logger.BeginScope(new Dictionary {{ "@Person", new Person { FirstName = "John", LastName = "Smith" }}}))
{
- var (logger, sink) = SetUp(LogLevel.Trace);
+ logger.Log(LogLevel.Information, 0, TestMessage, null!, null!);
+ }
- using (logger.BeginScope("{FirstName}", "John"))
- {
- logger.Log(LogLevel.Information, 0, TestMessage, null, null);
- }
+ Assert.Single(sink.Writes);
+ Assert.True(sink.Writes[0].Properties.ContainsKey("Person"));
- Assert.Equal(1, sink.Writes.Count);
- Assert.True(sink.Writes[0].Properties.ContainsKey("FirstName"));
- }
+ var person = (StructureValue)sink.Writes[0].Properties["Person"];
+ var firstName = (ScalarValue)person.Properties.Single(p => p.Name == "FirstName").Value;
+ var lastName = (ScalarValue)person.Properties.Single(p => p.Name == "LastName").Value;
+ Assert.Equal("John", firstName.Value);
+ Assert.Equal("Smith", lastName.Value);
+ }
+
+ [Fact]
+ public void BeginScopeDoesNotModifyKeyWhenDestructurerIsNotUsedInMessageTemplate()
+ {
+ var (logger, sink) = SetUp(LogLevel.Trace);
- [Fact]
- public void BeginScopeDoesNotModifyKeyWhenDestructurerIsNotUsedInDictionary()
+ using (logger.BeginScope("{FirstName}", "John"))
{
- var (logger, sink) = SetUp(LogLevel.Trace);
+ logger.Log(LogLevel.Information, 0, TestMessage, null!, null!);
+ }
- using (logger.BeginScope(new Dictionary { { "FirstName", "John"}}))
- {
- logger.Log(LogLevel.Information, 0, TestMessage, null, null);
- }
+ Assert.Single(sink.Writes);
+ Assert.True(sink.Writes[0].Properties.ContainsKey("FirstName"));
+ }
- Assert.Equal(1, sink.Writes.Count);
- Assert.True(sink.Writes[0].Properties.ContainsKey("FirstName"));
- }
+ [Fact]
+ public void BeginScopeDoesNotModifyKeyWhenDestructurerIsNotUsedInDictionary()
+ {
+ var (logger, sink) = SetUp(LogLevel.Trace);
- [Fact]
- public void NamedScopesAreCaptured()
+ using (logger.BeginScope(new Dictionary { { "FirstName", "John"}}))
{
- var (logger, sink) = SetUp(LogLevel.Trace);
+ logger.Log(LogLevel.Information, 0, TestMessage, null!, null!);
+ }
- using (logger.BeginScope("Outer"))
- using (logger.BeginScope("Inner"))
- {
- logger.Log(LogLevel.Information, 0, TestMessage, null, null);
- }
+ Assert.Single(sink.Writes);
+ Assert.True(sink.Writes[0].Properties.ContainsKey("FirstName"));
+ }
- Assert.Equal(1, sink.Writes.Count);
+ [Fact]
+ public void NamedScopesAreCaptured()
+ {
+ var (logger, sink) = SetUp(LogLevel.Trace);
- Assert.True(sink.Writes[0].Properties.TryGetValue(SerilogLoggerProvider.ScopePropertyName, out var scopeValue));
- var sequence = Assert.IsType(scopeValue);
- var items = sequence.Elements.Select(e => Assert.IsType(e).Value).Cast().ToArray();
- Assert.Equal(2, items.Length);
- Assert.Equal("Outer", items[0]);
- Assert.Equal("Inner", items[1]);
+ using (logger.BeginScope("Outer"))
+ using (logger.BeginScope("Inner"))
+ {
+ logger.Log(LogLevel.Information, 0, TestMessage, null!, null!);
}
- class FoodScope : IEnumerable>
- {
- readonly string _name;
+ Assert.Single(sink.Writes);
- public FoodScope(string name)
- {
- _name = name;
- }
+ Assert.True(sink.Writes[0].Properties.TryGetValue(SerilogLoggerProvider.ScopePropertyName, out var scopeValue));
+ var sequence = Assert.IsType(scopeValue);
+ var items = sequence.Elements.Select(e => Assert.IsType(e).Value).Cast().ToArray();
+ Assert.Equal(2, items.Length);
+ Assert.Equal("Outer", items[0]);
+ Assert.Equal("Inner", items[1]);
+ }
- public IEnumerator> GetEnumerator()
- {
- yield return new KeyValuePair("Name", _name);
- }
+ class FoodScope : IEnumerable>
+ {
+ readonly string _name;
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
+ public FoodScope(string name)
+ {
+ _name = name;
}
- class LuckyScope : IEnumerable>
+ public IEnumerator> GetEnumerator()
{
- readonly int _luckyNumber;
+ yield return new KeyValuePair("Name", _name);
+ }
- public LuckyScope(int luckyNumber)
- {
- _luckyNumber = luckyNumber;
- }
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
- public IEnumerator> GetEnumerator()
- {
- yield return new KeyValuePair("LuckyNumber", _luckyNumber);
- }
+ class LuckyScope : IEnumerable>
+ {
+ readonly int _luckyNumber;
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
+ public LuckyScope(int luckyNumber)
+ {
+ _luckyNumber = luckyNumber;
}
- class Person
+ public IEnumerator> GetEnumerator()
{
- // ReSharper disable once UnusedAutoPropertyAccessor.Local
- public string FirstName { get; set; }
-
- // ReSharper disable once UnusedAutoPropertyAccessor.Local
- public string LastName { get; set; }
+ yield return new KeyValuePair("LuckyNumber", _luckyNumber);
}
- [Theory]
- [InlineData(1)]
- [InlineData(10)]
- [InlineData(48)]
- [InlineData(100)]
- public void LowAndHighNumberedEventIdsAreMapped(int id)
+ IEnumerator IEnumerable.GetEnumerator()
{
- var orig = new EventId(id, "test");
- var mapped = SerilogLogger.CreateEventIdProperty(orig);
- var value = Assert.IsType(mapped.Value);
- Assert.Equal(2, value.Properties.Count);
- var idValue = value.Properties.Single(p => p.Name == "Id").Value;
- var scalar = Assert.IsType(idValue);
- Assert.Equal(id, scalar.Value);
+ return GetEnumerator();
}
-
- [Fact]
- public void MismatchedMessageTemplateParameterCountIsHandled()
- {
- var (logger, sink) = SetUp(LogLevel.Trace);
+ }
- logger.LogInformation("Some test message with {Two} {Properties}", "OneProperty");
+ class Person
+ {
+ // ReSharper disable once UnusedAutoPropertyAccessor.Local
+ public string? FirstName { get; set; }
+
+ // ReSharper disable once UnusedAutoPropertyAccessor.Local
+ public string? LastName { get; set; }
+ }
+
+ [Theory]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(48)]
+ [InlineData(100)]
+ public void LowAndHighNumberedEventIdsAreMapped(int id)
+ {
+ var orig = new EventId(id, "test");
+ var mapped = SerilogLogger.CreateEventIdProperty(orig);
+ var value = Assert.IsType(mapped.Value);
+ Assert.Equal(2, value.Properties.Count);
+ var idValue = value.Properties.Single(p => p.Name == "Id").Value;
+ 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);
+ Assert.Empty(sink.Writes);
+ }
+
+ [Fact]
+ public void ExceptionFromAuditSinkIsUnhandled()
+ {
+ var serilogLogger = new LoggerConfiguration()
+ .AuditTo.Sink(new MySink())
+ .CreateLogger();
+
+ var provider = new SerilogLoggerProvider(serilogLogger);
+ var logger = provider.CreateLogger(Name);
+
+ var ex = Assert.Throws(() => logger.LogInformation("Normal text"));
+ Assert.IsType(ex.InnerException);
+ Assert.Equal("Oops", ex.InnerException.Message);
+ }
+
+ private class MySink : ILogEventSink
+ {
+ public void Emit(LogEvent logEvent)
+ {
+ throw new NotImplementedException("Oops");
}
}
}
diff --git a/test/Serilog.Extensions.Logging.Tests/Support/DisposeTrackingLogger.cs b/test/Serilog.Extensions.Logging.Tests/Support/DisposeTrackingLogger.cs
index d833c0c..8effbfc 100644
--- a/test/Serilog.Extensions.Logging.Tests/Support/DisposeTrackingLogger.cs
+++ b/test/Serilog.Extensions.Logging.Tests/Support/DisposeTrackingLogger.cs
@@ -1,354 +1,352 @@
-using System;
-using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using Serilog.Core;
using Serilog.Events;
-namespace Serilog.Extensions.Logging.Tests.Support
+namespace Serilog.Extensions.Logging.Tests.Support;
+
+sealed class DisposeTrackingLogger : ILogger, IDisposable
{
- public class DisposeTrackingLogger : ILogger, IDisposable
- {
- public bool IsDisposed { get; set; }
-
- public ILogger ForContext(ILogEventEnricher enricher)
- {
- return new LoggerConfiguration().CreateLogger();
- }
-
- public ILogger ForContext(IEnumerable enrichers)
- {
- return new LoggerConfiguration().CreateLogger();
- }
-
- public ILogger ForContext(string propertyName, object value, bool destructureObjects = false)
- {
- return new LoggerConfiguration().CreateLogger();
- }
-
- public ILogger ForContext()
- {
- return new LoggerConfiguration().CreateLogger();
- }
-
- public ILogger ForContext(Type source)
- {
- return new LoggerConfiguration().CreateLogger();
- }
-
- public void Write(LogEvent logEvent)
- {
- }
-
- public void Write(LogEventLevel level, string messageTemplate)
- {
- }
-
- public void Write(LogEventLevel level, string messageTemplate, T propertyValue)
- {
- }
-
- public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
- {
- }
-
- public void Write(LogEventLevel level, string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Write(LogEventLevel level, Exception exception, string messageTemplate)
- {
- }
-
- public void Write(LogEventLevel level, Exception exception, string messageTemplate, T propertyValue)
- {
- }
-
- public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0,
- T1 propertyValue1)
- {
- }
-
- public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0,
- T1 propertyValue1, T2 propertyValue2)
- {
- }
-
- public void Write(LogEventLevel level, Exception exception, string messageTemplate, params object[] propertyValues)
- {
- }
-
- public bool IsEnabled(LogEventLevel level)
- {
- return false;
- }
-
- public void Verbose(string messageTemplate)
- {
- }
-
- public void Verbose(string messageTemplate, T propertyValue)
- {
- }
-
- public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
- {
- }
-
- public void Verbose(string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Verbose(Exception exception, string messageTemplate)
- {
- }
-
- public void Verbose(Exception exception, string messageTemplate, T propertyValue)
- {
- }
-
- public void Verbose(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Verbose(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
- {
- }
-
- public void Verbose(Exception exception, string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Debug(string messageTemplate)
- {
- }
-
- public void Debug(string messageTemplate, T propertyValue)
- {
- }
-
- public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
- {
- }
-
- public void Debug(string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Debug(Exception exception, string messageTemplate)
- {
- }
-
- public void Debug(Exception exception, string messageTemplate, T propertyValue)
- {
- }
-
- public void Debug(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Debug(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
- {
- }
-
- public void Debug(Exception exception, string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Information(string messageTemplate)
- {
- }
-
- public void Information(string messageTemplate, T propertyValue)
- {
- }
-
- public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
- {
- }
-
- public void Information(string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Information(Exception exception, string messageTemplate)
- {
- }
-
- public void Information(Exception exception, string messageTemplate, T propertyValue)
- {
- }
-
- public void Information(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Information(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
- {
- }
-
- public void Information(Exception exception, string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Warning(string messageTemplate)
- {
- }
-
- public void Warning(string messageTemplate, T propertyValue)
- {
- }
-
- public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
- {
- }
-
- public void Warning(string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Warning(Exception exception, string messageTemplate)
- {
- }
-
- public void Warning(Exception exception, string messageTemplate, T propertyValue)
- {
- }
-
- public void Warning(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Warning(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
- {
- }
-
- public void Warning(Exception exception, string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Error(string messageTemplate)
- {
- }
-
- public void Error(string messageTemplate, T propertyValue)
- {
- }
-
- public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
- {
- }
-
- public void Error(string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Error(Exception exception, string messageTemplate)
- {
- }
-
- public void Error(Exception exception, string messageTemplate, T propertyValue)
- {
- }
-
- public void Error(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Error(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
- {
- }
-
- public void Error(Exception exception, string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Fatal(string messageTemplate)
- {
- }
-
- public void Fatal(string messageTemplate, T propertyValue)
- {
- }
-
- public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
- {
- }
-
- public void Fatal(string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Fatal(Exception exception, string messageTemplate)
- {
- }
-
- public void Fatal(Exception exception, string messageTemplate, T propertyValue)
- {
- }
-
- public void Fatal(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Fatal(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
- {
- }
-
- public void Fatal(Exception exception, string messageTemplate, params object[] propertyValues)
- {
- }
-
- public bool BindMessageTemplate(string messageTemplate, object[] propertyValues, out MessageTemplate parsedTemplate,
- out IEnumerable boundProperties)
- {
- parsedTemplate = null;
- boundProperties = null;
- return false;
- }
-
- public bool BindProperty(string propertyName, object value, bool destructureObjects, out LogEventProperty property)
- {
- property = null;
- return false;
- }
-
- public void Dispose()
- {
- IsDisposed = true;
- }
+ public bool IsDisposed { get; private set; }
+
+ public ILogger ForContext(ILogEventEnricher enricher)
+ {
+ return new LoggerConfiguration().CreateLogger();
+ }
+
+ public ILogger ForContext(IEnumerable enrichers)
+ {
+ return new LoggerConfiguration().CreateLogger();
+ }
+
+ public ILogger ForContext(string propertyName, object? value, bool destructureObjects = false)
+ {
+ return new LoggerConfiguration().CreateLogger();
+ }
+
+ public ILogger ForContext()
+ {
+ return new LoggerConfiguration().CreateLogger();
+ }
+
+ public ILogger ForContext(Type source)
+ {
+ return new LoggerConfiguration().CreateLogger();
+ }
+
+ public void Write(LogEvent logEvent)
+ {
+ }
+
+ public void Write(LogEventLevel level, string messageTemplate)
+ {
+ }
+
+ public void Write(LogEventLevel level, string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ }
+
+ public void Write(LogEventLevel level, string messageTemplate, params object?[]? propertyValues)
+ {
+ }
+
+ public void Write(LogEventLevel level, Exception? exception, string messageTemplate)
+ {
+ }
+
+ public void Write(LogEventLevel level, Exception? exception, string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Write(LogEventLevel level, Exception? exception, string messageTemplate, T0 propertyValue0,
+ T1 propertyValue1)
+ {
+ }
+
+ public void Write(LogEventLevel level, Exception? exception, string messageTemplate, T0 propertyValue0,
+ T1 propertyValue1, T2 propertyValue2)
+ {
+ }
+
+ public void Write(LogEventLevel level, Exception? exception, string messageTemplate, params object?[]? propertyValues)
+ {
+ }
+
+ public bool IsEnabled(LogEventLevel level)
+ {
+ return false;
+ }
+
+ public void Verbose(string messageTemplate)
+ {
+ }
+
+ public void Verbose(string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ {
+ }
+
+ public void Verbose(string messageTemplate, params object?[]? propertyValues)
+ {
+ }
+
+ public void Verbose(Exception? exception, string messageTemplate)
+ {
+ }
+
+ public void Verbose(Exception? exception, string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Verbose(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Verbose(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ }
+
+ public void Verbose(Exception? exception, string messageTemplate, params object?[]? propertyValues)
+ {
+ }
+
+ public void Debug(string messageTemplate)
+ {
+ }
+
+ public void Debug(string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ {
+ }
+
+ public void Debug(string messageTemplate, params object?[]? propertyValues)
+ {
+ }
+
+ public void Debug(Exception? exception, string messageTemplate)
+ {
+ }
+
+ public void Debug(Exception? exception, string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Debug(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Debug(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ }
+
+ public void Debug(Exception? exception, string messageTemplate, params object?[]? propertyValues)
+ {
+ }
+
+ public void Information(string messageTemplate)
+ {
+ }
+
+ public void Information(string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ {
+ }
+
+ public void Information(string messageTemplate, params object?[]? propertyValues)
+ {
+ }
+
+ public void Information(Exception? exception, string messageTemplate)
+ {
+ }
+
+ public void Information(Exception? exception, string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Information(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Information(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ }
+
+ public void Information(Exception? exception, string messageTemplate, params object?[]? propertyValues)
+ {
+ }
+
+ public void Warning(string messageTemplate)
+ {
+ }
+
+ public void Warning(string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ {
+ }
+
+ public void Warning(string messageTemplate, params object?[]? propertyValues)
+ {
+ }
+
+ public void Warning(Exception? exception, string messageTemplate)
+ {
+ }
+
+ public void Warning(Exception? exception, string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Warning(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Warning(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ }
+
+ public void Warning(Exception? exception, string messageTemplate, params object?[]? propertyValues)
+ {
+ }
+
+ public void Error(string messageTemplate)
+ {
+ }
+
+ public void Error(string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ {
+ }
+
+ public void Error(string messageTemplate, params object?[]? propertyValues)
+ {
+ }
+
+ public void Error(Exception? exception, string messageTemplate)
+ {
+ }
+
+ public void Error(Exception? exception, string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Error(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Error(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ }
+
+ public void Error(Exception? exception, string messageTemplate, params object?[]? propertyValues)
+ {
+ }
+
+ public void Fatal(string messageTemplate)
+ {
+ }
+
+ public void Fatal(string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ {
+ }
+
+ public void Fatal(string messageTemplate, params object?[]? propertyValues)
+ {
+ }
+
+ public void Fatal(Exception? exception, string messageTemplate)
+ {
+ }
+
+ public void Fatal(Exception? exception, string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Fatal(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Fatal(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ }
+
+ public void Fatal(Exception? exception, string messageTemplate, params object?[]? propertyValues)
+ {
+ }
+
+ public bool BindMessageTemplate(string messageTemplate, object?[]? propertyValues, [NotNullWhen(true)] out MessageTemplate? parsedTemplate,
+ [NotNullWhen(true)] out IEnumerable? boundProperties)
+ {
+ parsedTemplate = null;
+ boundProperties = null;
+ return false;
+ }
+
+ public bool BindProperty(string? propertyName, object? value, bool destructureObjects, [NotNullWhen(true)] out LogEventProperty? property)
+ {
+ property = null;
+ return false;
+ }
+
+ public void Dispose()
+ {
+ IsDisposed = true;
}
}
diff --git a/test/Serilog.Extensions.Logging.Tests/Support/ExtensionsProvider.cs b/test/Serilog.Extensions.Logging.Tests/Support/ExtensionsProvider.cs
index 583293c..a27d0bd 100644
--- a/test/Serilog.Extensions.Logging.Tests/Support/ExtensionsProvider.cs
+++ b/test/Serilog.Extensions.Logging.Tests/Support/ExtensionsProvider.cs
@@ -1,45 +1,42 @@
// 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
+namespace Serilog.Extensions.Logging.Tests.Support;
+
+sealed class ExtensionsProvider : ILoggerProvider, Microsoft.Extensions.Logging.ILogger
{
- public class ExtensionsProvider : ILoggerProvider, Microsoft.Extensions.Logging.ILogger
+ readonly LogLevel _enabledLevel;
+
+ public List<(LogLevel logLevel, EventId eventId, object? state, Exception? exception, string message)> Writes { get; } = new();
+
+ public ExtensionsProvider(LogLevel enabledLevel)
+ {
+ _enabledLevel = enabledLevel;
+ }
+
+ public Microsoft.Extensions.Logging.ILogger CreateLogger(string categoryName)
+ {
+ return this;
+ }
+
+ public IDisposable BeginScope(TState state) where TState: notnull
+ {
+ 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()
{
- 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
+}
diff --git a/test/Serilog.Extensions.Logging.Tests/Support/SerilogSink.cs b/test/Serilog.Extensions.Logging.Tests/Support/SerilogSink.cs
index cd7d5d7..d26aac5 100644
--- a/test/Serilog.Extensions.Logging.Tests/Support/SerilogSink.cs
+++ b/test/Serilog.Extensions.Logging.Tests/Support/SerilogSink.cs
@@ -1,19 +1,17 @@
-// Copyright (c) .NET Foundation. All rights reserved.
+// 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.Collections.Generic;
using Serilog.Core;
using Serilog.Events;
-namespace Serilog.Extensions.Logging.Tests.Support
+namespace Serilog.Extensions.Logging.Tests.Support;
+
+public class SerilogSink : ILogEventSink
{
- public class SerilogSink : ILogEventSink
- {
- public List Writes { get; set; } = new List();
+ public List Writes { get; set; } = new();
- public void Emit(LogEvent logEvent)
- {
- Writes.Add(logEvent);
- }
+ public void Emit(LogEvent logEvent)
+ {
+ Writes.Add(logEvent);
}
-}
\ No newline at end of file
+}