diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..acd3bc6
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,41 @@
+# If this file is renamed, the incrementing run attempt number will be reset.
+
+name: CI
+
+on:
+ push:
+ branches: [ "dev", "main" ]
+ pull_request:
+ branches: [ "dev", "main" ]
+
+env:
+ CI_BUILD_NUMBER_BASE: ${{ github.run_number }}
+ CI_TARGET_BRANCH: ${{ github.head_ref || github.ref_name }}
+
+jobs:
+ build:
+
+ # The build must run on Windows so that .NET Framework targets can be built and tested.
+ runs-on: windows-latest
+
+ permissions:
+ contents: write
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Setup
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: 9.0.x
+ - name: Compute build number
+ shell: bash
+ run: |
+ echo "CI_BUILD_NUMBER=$(($CI_BUILD_NUMBER_BASE+2300))" >> $GITHUB_ENV
+ - name: Build and Publish
+ env:
+ DOTNET_CLI_TELEMETRY_OPTOUT: true
+ NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ shell: pwsh
+ run: |
+ ./Build.ps1
diff --git a/.gitignore b/.gitignore
index 0173fad..4b9f99e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -286,3 +286,6 @@ __pycache__/
*.odx.cs
*.xsd.cs
/samples/WebApplicationSample/logs/
+
+.DS_Store
+
diff --git a/Build.ps1 b/Build.ps1
index cce9432..e798284 100644
--- a/Build.ps1
+++ b/Build.ps1
@@ -1,56 +1,79 @@
-echo "build: Build started"
+Write-Output "build: Tool versions follow"
+
+dotnet --version
+dotnet --list-sdks
+
+Write-Output "build: Build started"
Push-Location $PSScriptRoot
+try {
+ if(Test-Path .\artifacts) {
+ Write-Output "build: Cleaning ./artifacts"
+ Remove-Item ./artifacts -Force -Recurse
+ }
-if(Test-Path .\artifacts) {
- echo "build: Cleaning .\artifacts"
- Remove-Item .\artifacts -Force -Recurse
-}
+ & dotnet restore --no-cache
+
+ $dbp = [Xml] (Get-Content .\Directory.Version.props)
+ $versionPrefix = $dbp.Project.PropertyGroup.VersionPrefix
+
+ Write-Output "build: Package version prefix is $versionPrefix"
+
+ $branch = @{ $true = $env:CI_TARGET_BRANCH; $false = $(git symbolic-ref --short -q HEAD) }[$NULL -ne $env:CI_TARGET_BRANCH];
+ $revision = @{ $true = "{0:00000}" -f [convert]::ToInt32("0" + $env:CI_BUILD_NUMBER, 10); $false = "local" }[$NULL -ne $env:CI_BUILD_NUMBER];
+ $suffix = @{ $true = ""; $false = "$($branch.Substring(0, [math]::Min(10,$branch.Length)) -replace '([^a-zA-Z0-9\-]*)', '')-$revision"}[$branch -eq "main" -and $revision -ne "local"]
+ $commitHash = $(git rev-parse --short HEAD)
+ $buildSuffix = @{ $true = "$($suffix)-$($commitHash)"; $false = "$($branch)-$($commitHash)" }[$suffix -ne ""]
-& dotnet restore --no-cache
+ Write-Output "build: Package version suffix is $suffix"
+ Write-Output "build: Build version suffix is $buildSuffix"
-$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 "main" -and $revision -ne "local"]
+ & dotnet build -c Release --version-suffix=$buildSuffix /p:ContinuousIntegrationBuild=true
+ if($LASTEXITCODE -ne 0) { throw "Build failed" }
-echo "build: Version suffix is $suffix"
+ foreach ($src in Get-ChildItem src/*) {
+ Push-Location $src
-foreach ($src in ls src/*) {
- Push-Location $src
+ Write-Output "build: Packaging project in $src"
- echo "build: Packaging project in $src"
+ if ($suffix) {
+ & dotnet pack -c Release --no-build --no-restore -o ../../artifacts --version-suffix=$suffix
+ } else {
+ & dotnet pack -c Release --no-build --no-restore -o ../../artifacts
+ }
+ if($LASTEXITCODE -ne 0) { throw "Packaging failed" }
- if($suffix) {
- & dotnet pack -c Release --include-source -o ..\..\artifacts --version-suffix=$suffix
- } else {
- & dotnet pack -c Release --include-source -o ..\..\artifacts
+ Pop-Location
}
-
- if($LASTEXITCODE -ne 0) { exit 1 }
- Pop-Location
-}
+ foreach ($test in Get-ChildItem test/*.Tests) {
+ Push-Location $test
-foreach ($test in ls test/*.PerformanceTests) {
- Push-Location $test
+ Write-Output "build: Testing project in $test"
- echo "build: Building performance test project in $test"
+ & dotnet test -c Release --no-build --no-restore
+ if($LASTEXITCODE -ne 0) { throw "Testing failed" }
- & dotnet build -c Release
- if($LASTEXITCODE -ne 0) { exit 2 }
+ Pop-Location
+ }
- Pop-Location
-}
+ if ($env:NUGET_API_KEY) {
+ # GitHub Actions will only supply this to branch builds and not PRs. We publish
+ # builds from any branch this action targets (i.e. main and dev).
-foreach ($test in ls test/*.Tests) {
- Push-Location $test
+ Write-Output "build: Publishing NuGet packages"
- echo "build: Testing project in $test"
+ foreach ($nupkg in Get-ChildItem artifacts/*.nupkg) {
+ & dotnet nuget push -k $env:NUGET_API_KEY -s https://api.nuget.org/v3/index.json "$nupkg"
+ if($LASTEXITCODE -ne 0) { throw "Publishing failed" }
+ }
- & dotnet test -c Release
- if($LASTEXITCODE -ne 0) { exit 3 }
+ if (!($suffix)) {
+ Write-Output "build: Creating release for version $versionPrefix"
+ iex "gh release create v$versionPrefix --title v$versionPrefix --generate-notes $(get-item ./artifacts/*.nupkg) $(get-item ./artifacts/*.snupkg)"
+ }
+ }
+} finally {
Pop-Location
}
-
-Pop-Location
diff --git a/Directory.Build.props b/Directory.Build.props
new file mode 100644
index 0000000..c114992
--- /dev/null
+++ b/Directory.Build.props
@@ -0,0 +1,25 @@
+
+
+
+
+ latest
+ True
+
+ true
+ $(MSBuildThisFileDirectory)assets/Serilog.snk
+ false
+ enable
+ enable
+ true
+ true
+ true
+ true
+ snupkg
+
+
+
+
+
+
+
diff --git a/Directory.Version.props b/Directory.Version.props
new file mode 100644
index 0000000..c8c7b22
--- /dev/null
+++ b/Directory.Version.props
@@ -0,0 +1,6 @@
+
+
+
+ 9.0.0
+
+
diff --git a/README.md b/README.md
index 096f513..9f0008a 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,11 @@
-# Serilog.Extensions.Hosting [](https://ci.appveyor.com/project/serilog/serilog-extensions-hosting) [](https://www.nuget.org/packages/Serilog.Extensions.Hosting/)
+# Serilog.Extensions.Hosting [](https://github.com/serilog/serilog-extensions-hosting/actions) [](https://www.nuget.org/packages/Serilog.Extensions.Hosting/)
Serilog logging for _Microsoft.Extensions.Hosting_. This package routes framework log messages through Serilog, so you can get information about the framework's internal operations written to the same Serilog sinks as your application events.
-**ASP.NET Core** applications should consider [using _Serilog.AspNetCore_ instead](https://github.com/serilog/serilog-aspnetcore), which bundles this package and includes other ASP.NET Core-specific features.
+**Versioning:** This package tracks the versioning and target framework support of its
+[_Microsoft.Extensions.Hosting_](https://nuget.org/packages/Microsoft.Extensions.Hosting) dependency. Most users should choose the version of _Serilog.Extensions.Hosting_ that matches
+their application's target framework. I.e. if you're targeting .NET 7.x, choose a 7.x version of _Serilog.Extensions.Hosting_. If
+you're targeting .NET 8.x, choose an 8.x _Serilog.Extensions.Hosting_ version, and so on.
### Instructions
@@ -13,46 +16,37 @@ dotnet add package Serilog.Extensions.Hosting
dotnet add package Serilog.Sinks.Console
```
-**Next**, in your application's _Program.cs_ file, configure Serilog first. A `try`/`catch` block will ensure any configuration issues are appropriately logged:
+**Next**, in your application's _Program.cs_ file, configure Serilog first. A `try`/`catch` block will ensure any configuration issues are appropriately logged. Call `AddSerilog()` on the host application builder:
```csharp
-public class Program
+using Serilog;
+
+Log.Logger = new LoggerConfiguration()
+ .Enrich.FromLogContext()
+ .WriteTo.Console()
+ .CreateLogger();
+
+try
{
- public static int Main(string[] args)
- {
- Log.Logger = new LoggerConfiguration()
- .MinimumLevel.Debug()
- .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
- .Enrich.FromLogContext()
- .WriteTo.Console()
- .CreateLogger();
-
- try
- {
- Log.Information("Starting host");
- BuildHost(args).Run();
- return 0;
- }
- catch (Exception ex)
- {
- Log.Fatal(ex, "Host terminated unexpectedly");
- return 1;
- }
- finally
- {
- Log.CloseAndFlush();
- }
- }
-```
+ Log.Information("Starting host");
-**Then**, add `UseSerilog()` to the host builder in `BuildHost()`.
+ var builder = Host.CreateApplicationBuilder(args);
+ builder.Services.AddHostedService();
+ builder.Services.AddSerilog();
-```csharp
- public static IHost BuildHost(string[] args) =>
- new HostBuilder()
- .ConfigureServices(services => services.AddSingleton())
- .UseSerilog() // <- Add this line
- .Build();
+ var app = builder.Build();
+
+ await app.RunAsync();
+ return 0;
+}
+catch (Exception ex)
+{
+ Log.Fatal(ex, "Host terminated unexpectedly");
+ return 1;
+}
+finally
+{
+ await Log.CloseAndFlushAsync();
}
```
@@ -71,24 +65,18 @@ A more complete example, showing _appsettings.json_ configuration, can be found
With _Serilog.Extensions.Hosting_ installed and configured, you can write log messages directly through Serilog or any `ILogger` interface injected by .NET. All loggers will use the same underlying implementation, levels, and destinations.
-**Tip:** change the minimum level for `Microsoft` to `Warning`
-
### Inline initialization
You can alternatively configure Serilog using a delegate as shown below:
```csharp
// dotnet add package Serilog.Settings.Configuration
- .UseSerilog((hostingContext, services, loggerConfiguration) => loggerConfiguration
- .ReadFrom.Configuration(hostingContext.Configuration)
- .Enrich.FromLogContext()
- .WriteTo.Console())
+builder.Services.AddSerilog((services, loggerConfiguration) => loggerConfiguration
+ .ReadFrom.Configuration(builder.Configuration)
+ .Enrich.FromLogContext()
+ .WriteTo.Console())
```
-This has the advantage of making the `hostingContext`'s `Configuration` object available for configuration of the logger, but at the expense of ignoring `Exception`s raised earlier in program startup.
+This has the advantage of making `builder`'s `Configuration` object available for configuration of the logger, but at the expense of ignoring `Exception`s raised earlier in program startup.
If this method is used, `Log.Logger` is assigned implicitly, and closed when the app is shut down.
-
-### Versioning
-
-This package tracks the versioning and target framework support of its [_Microsoft.Extensions.Hosting_](https://nuget.org/packages/Microsoft.Extensions.Hosting) dependency.
diff --git a/appveyor.yml b/appveyor.yml
deleted file mode 100644
index aa80e5e..0000000
--- a/appveyor.yml
+++ /dev/null
@@ -1,28 +0,0 @@
-version: '{build}'
-skip_tags: true
-image: Visual Studio 2022
-test: off
-build_script:
-- pwsh: |
- Invoke-WebRequest "https://dot.net/v1/dotnet-install.ps1" -OutFile "./dotnet-install.ps1"
- ./dotnet-install.ps1 -JSonFile global.json -Architecture x64 -InstallDir 'C:\Program Files\dotnet'
- ./Build.ps1
-artifacts:
-- path: artifacts/Serilog.*.nupkg
-skip_commits:
- files:
- - README.md
-deploy:
-- provider: NuGet
- skip_symbols: true
- api_key:
- secure: EN9f+XXE3fW+ebL4wxrIbafdtbNvRfddBN8UUixvctYh4qMBHzr1JdnM83QsM1zo
- on:
- branch: /^(main|dev)$/
-- provider: GitHub
- auth_token:
- secure: p4LpVhBKxGS5WqucHxFQ5c7C8cP74kbNB0Z8k9Oxx/PMaDQ1+ibmoexNqVU5ZlmX
- artifact: /Serilog.*\.nupkg/
- tag: v$(appveyor_build_version)
- on:
- branch: main
diff --git a/build.sh b/build.sh
deleted file mode 100644
index 433a9b4..0000000
--- a/build.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-dotnet --info
-dotnet restore
-
-for path in src/**/*.csproj; do
- dotnet build -f netstandard2.0 -c Release ${path}
-done
-
-for path in test/*.Tests/*.csproj; do
- dotnet test -f netcoreapp2.0 -c Release ${path}
-done
diff --git a/global.json b/global.json
index d079f83..db8627a 100644
--- a/global.json
+++ b/global.json
@@ -1,7 +1,7 @@
{
"sdk": {
+ "version": "9.0.100",
"allowPrerelease": false,
- "version": "8.0.100",
"rollForward": "latestFeature"
}
}
diff --git a/samples/SimpleServiceSample/PrintTimeService.cs b/samples/SimpleServiceSample/PrintTimeService.cs
index f88e137..5a1434a 100644
--- a/samples/SimpleServiceSample/PrintTimeService.cs
+++ b/samples/SimpleServiceSample/PrintTimeService.cs
@@ -4,24 +4,23 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
-namespace SimpleServiceSample
+namespace SimpleServiceSample;
+
+public class PrintTimeService : BackgroundService
{
- public class PrintTimeService : BackgroundService
- {
- private readonly ILogger _logger;
+ private readonly ILogger _logger;
- public PrintTimeService(ILogger logger)
- {
- _logger = logger;
- }
+ public PrintTimeService(ILogger logger)
+ {
+ _logger = logger;
+ }
- protected override async Task ExecuteAsync(CancellationToken stoppingToken)
+ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
+ {
+ while (!stoppingToken.IsCancellationRequested)
{
- while (!stoppingToken.IsCancellationRequested)
- {
- _logger.LogInformation("The current time is: {CurrentTime}", DateTimeOffset.UtcNow);
- await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
- }
+ _logger.LogInformation("The current time is: {CurrentTime}", DateTimeOffset.UtcNow);
+ await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
}
}
}
diff --git a/samples/SimpleServiceSample/Program.cs b/samples/SimpleServiceSample/Program.cs
index ee7319f..f6a8a3e 100644
--- a/samples/SimpleServiceSample/Program.cs
+++ b/samples/SimpleServiceSample/Program.cs
@@ -2,42 +2,39 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
+using SimpleServiceSample;
-namespace SimpleServiceSample
+Log.Logger = new LoggerConfiguration()
+ .Enrich.FromLogContext()
+ .WriteTo.Console()
+ .CreateBootstrapLogger();
+
+try
{
- public static class Program
- {
- public static int Main(string[] args)
- {
- Log.Logger = new LoggerConfiguration()
- .Enrich.FromLogContext()
- .WriteTo.Console()
- .CreateBootstrapLogger();
+ Log.Information("Getting the motors running...");
+
+ var builder = Host.CreateApplicationBuilder(args);
+
+ builder.Services.AddHostedService();
- try
- {
- Log.Information("Getting the motors running...");
- CreateHostBuilder(args).Build().Run();
- return 0;
- }
- catch (Exception ex)
- {
- Log.Fatal(ex, "Host terminated unexpectedly");
- return 1;
- }
- finally
- {
- Log.CloseAndFlush();
- }
- }
+ builder.Services.AddSerilog((services, loggerConfiguration) => loggerConfiguration
+ .ReadFrom.Configuration(builder.Configuration)
+ .ReadFrom.Services(services)
+ .Enrich.FromLogContext()
+ .WriteTo.Console());
- public static IHostBuilder CreateHostBuilder(string[] args) =>
- Host.CreateDefaultBuilder(args)
- .ConfigureServices(services => services.AddHostedService())
- .UseSerilog((context, services, loggerConfiguration) => loggerConfiguration
- .ReadFrom.Configuration(context.Configuration)
- .ReadFrom.Services(services)
- .Enrich.FromLogContext()
- .WriteTo.Console());
- }
+ var app = builder.Build();
+
+ await app.RunAsync();
+
+ return 0;
+}
+catch (Exception ex)
+{
+ Log.Fatal(ex, "Host terminated unexpectedly");
+ return 1;
+}
+finally
+{
+ await Log.CloseAndFlushAsync();
}
diff --git a/samples/SimpleServiceSample/SimpleServiceSample.csproj b/samples/SimpleServiceSample/SimpleServiceSample.csproj
index 3451be2..9890c70 100644
--- a/samples/SimpleServiceSample/SimpleServiceSample.csproj
+++ b/samples/SimpleServiceSample/SimpleServiceSample.csproj
@@ -1,7 +1,8 @@
- net8.0
+ net9.0
+ false
@@ -9,9 +10,9 @@
-
-
-
+
+
+
diff --git a/samples/WebApplicationSample/Program.cs b/samples/WebApplicationSample/Program.cs
index 4cf73b8..a6c7b6a 100644
--- a/samples/WebApplicationSample/Program.cs
+++ b/samples/WebApplicationSample/Program.cs
@@ -1,44 +1,45 @@
using System;
+using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Hosting;
using Serilog;
-namespace WebApplicationSample
+
+Log.Logger = new LoggerConfiguration()
+ .WriteTo.Console()
+ .CreateBootstrapLogger();
+
+ Log.Information("Starting up!");
+
+try
{
- public static class Program
- {
- public static int Main(string[] args)
- {
- Log.Logger = new LoggerConfiguration()
- .WriteTo.Console()
- .CreateBootstrapLogger();
-
- Log.Information("Starting up!");
+ var builder = WebApplication.CreateBuilder();
- try
- {
- CreateHostBuilder(args).Build().Run();
+ builder.Services.AddSerilog((services, loggerConfiguration) => loggerConfiguration
+ .WriteTo.Console()
+ .ReadFrom.Configuration(builder.Configuration)
+ .ReadFrom.Services(services));
- Log.Information("Stopped cleanly");
- return 0;
- }
- catch (Exception ex)
- {
- Log.Fatal(ex, "An unhandled exception occured during bootstrapping");
- return 1;
- }
- finally
- {
- Log.CloseAndFlush();
- }
- }
+ var app = builder.Build();
- public static IHostBuilder CreateHostBuilder(string[] args) =>
- Host.CreateDefaultBuilder(args)
- .UseSerilog((context, services, configuration) => configuration
- .WriteTo.Console()
- .ReadFrom.Configuration(context.Configuration)
- .ReadFrom.Services(services))
- .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); });
- }
-}
\ No newline at end of file
+ app.MapGet("/", () =>
+ {
+ Log.Information("Saying hello");
+ return "Hello World!";
+ });
+
+ await app.RunAsync();
+
+ Log.Information("Stopped cleanly");
+ return 0;
+}
+catch (Exception ex)
+{
+ Log.Fatal(ex, "An unhandled exception occured during bootstrapping");
+ return 1;
+}
+finally
+{
+ await Log.CloseAndFlushAsync();
+}
diff --git a/samples/WebApplicationSample/Startup.cs b/samples/WebApplicationSample/Startup.cs
deleted file mode 100644
index 4fe346d..0000000
--- a/samples/WebApplicationSample/Startup.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.Http;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Hosting;
-using Serilog;
-
-namespace WebApplicationSample
-{
- public class Startup
- {
- // This method gets called by the runtime. Use this method to add services to the container.
- // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
- public void ConfigureServices(IServiceCollection services)
- {
- }
-
- // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
- public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
- {
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- }
-
- app.UseRouting();
-
- app.UseEndpoints(endpoints =>
- {
- endpoints.MapGet("/", async context =>
- {
- Log.Information("Saying hello");
- await context.Response.WriteAsync("Hello World!");
- });
- });
- }
- }
-}
\ No newline at end of file
diff --git a/samples/WebApplicationSample/WebApplicationSample.csproj b/samples/WebApplicationSample/WebApplicationSample.csproj
index 8fbe382..ff0965f 100644
--- a/samples/WebApplicationSample/WebApplicationSample.csproj
+++ b/samples/WebApplicationSample/WebApplicationSample.csproj
@@ -1,7 +1,8 @@
- net8.0
+ net9.0
+ false
@@ -9,9 +10,9 @@
-
-
-
+
+
+
diff --git a/samples/WebApplicationSample/appsettings.json b/samples/WebApplicationSample/appsettings.json
index 633356d..5521089 100644
--- a/samples/WebApplicationSample/appsettings.json
+++ b/samples/WebApplicationSample/appsettings.json
@@ -3,8 +3,9 @@
"MinimumLevel": {
"Default": "Information",
"Override": {
- "Microsoft": "Warning",
- "Microsoft.Hosting.Lifetime": "Information"
+ "Microsoft.AspNetCore.Hosting": "Information",
+ "Microsoft.AspNetCore.Mvc": "Warning",
+ "Microsoft.AspNetCore.Routing": "Warning"
}
},
"WriteTo": [
diff --git a/serilog-extensions-hosting.sln b/serilog-extensions-hosting.sln
index 2208752..37c65ef 100644
--- a/serilog-extensions-hosting.sln
+++ b/serilog-extensions-hosting.sln
@@ -11,11 +11,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{F240
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "assets", "assets", "{9C21B9DF-AEDD-4AA6-BEA4-912DEF3E5B8E}"
ProjectSection(SolutionItems) = preProject
- appveyor.yml = appveyor.yml
- Build.ps1 = Build.ps1
- global.json = global.json
README.md = README.md
assets\Serilog.snk = assets\Serilog.snk
+ Build.ps1 = Build.ps1
+ global.json = global.json
+ Directory.Version.props = Directory.Version.props
+ Directory.Build.props = Directory.Build.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serilog.Extensions.Hosting", "src\Serilog.Extensions.Hosting\Serilog.Extensions.Hosting.csproj", "{0549D23F-986B-4FB2-BACE-16FD7A7BC9EF}"
@@ -26,6 +27,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SimpleServiceSample", "samp
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApplicationSample", "samples\WebApplicationSample\WebApplicationSample.csproj", "{1ACDCA67-F404-45AB-9348-98E55E03CB8C}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{5C68E1CE-D650-4500-B32C-21EDD0AAA0A7}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{10168223-6AEF-4B08-B6FD-50C6FD3B6E84}"
+ ProjectSection(SolutionItems) = preProject
+ .github\workflows\ci.yml = .github\workflows\ci.yml
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -57,6 +65,7 @@ Global
{AD51759B-CD58-473F-9620-0B0E56A123A1} = {E30F638E-BBBE-4AD1-93CE-48CC69CFEFE1}
{E5A82756-4619-4E6B-8B26-6D83E00E99F0} = {F2407211-6043-439C-8E06-3641634332E7}
{1ACDCA67-F404-45AB-9348-98E55E03CB8C} = {F2407211-6043-439C-8E06-3641634332E7}
+ {10168223-6AEF-4B08-B6FD-50C6FD3B6E84} = {5C68E1CE-D650-4500-B32C-21EDD0AAA0A7}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {811E61C5-3871-4633-AFAE-B35B619C8A10}
diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/AmbientDiagnosticContextCollector.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/AmbientDiagnosticContextCollector.cs
index 68010ee..a96545a 100644
--- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/AmbientDiagnosticContextCollector.cs
+++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/AmbientDiagnosticContextCollector.cs
@@ -12,35 +12,30 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System;
-using System.Threading;
+namespace Serilog.Extensions.Hosting;
-namespace Serilog.Extensions.Hosting
+class AmbientDiagnosticContextCollector : IDisposable
{
- class AmbientDiagnosticContextCollector : IDisposable
- {
- static readonly AsyncLocal AmbientCollector =
- new AsyncLocal();
+ static readonly AsyncLocal AmbientCollector = new();
- // The indirection here ensures that completing collection cleans up the collector in all
- // execution contexts. Via @benaadams' addition to `HttpContextAccessor` :-)
- DiagnosticContextCollector _collector;
+ // The indirection here ensures that completing collection cleans up the collector in all
+ // execution contexts. Via @benaadams' addition to `HttpContextAccessor` :-)
+ DiagnosticContextCollector? _collector;
- public static DiagnosticContextCollector Current => AmbientCollector.Value?._collector;
+ public static DiagnosticContextCollector? Current => AmbientCollector.Value?._collector;
- public static DiagnosticContextCollector Begin()
- {
- var value = new AmbientDiagnosticContextCollector();
- value._collector = new DiagnosticContextCollector(value);
- AmbientCollector.Value = value;
- return value._collector;
- }
+ public static DiagnosticContextCollector Begin()
+ {
+ var value = new AmbientDiagnosticContextCollector();
+ value._collector = new DiagnosticContextCollector(value);
+ AmbientCollector.Value = value;
+ return value._collector;
+ }
- public void Dispose()
- {
- _collector = null;
- if (AmbientCollector.Value == this)
- AmbientCollector.Value = null;
- }
+ public void Dispose()
+ {
+ _collector = null;
+ if (AmbientCollector.Value == this)
+ AmbientCollector.Value = null;
}
}
diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/CachingReloadableLogger.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/CachingReloadableLogger.cs
index 3a8fee6..3b9d058 100644
--- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/CachingReloadableLogger.cs
+++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/CachingReloadableLogger.cs
@@ -12,534 +12,540 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#if !NO_RELOADABLE_LOGGER
-
-using System;
-using System.Collections.Generic;
-using System.Threading;
+using System.Diagnostics.CodeAnalysis;
using Serilog.Core;
using Serilog.Events;
-namespace Serilog.Extensions.Hosting
+namespace Serilog.Extensions.Hosting;
+
+class CachingReloadableLogger : LoggerBase, ILogger, IReloadableLogger
{
- class CachingReloadableLogger : ILogger, IReloadableLogger
+ readonly ReloadableLogger _reloadableLogger;
+ readonly Func _configure;
+ readonly IReloadableLogger _parent;
+
+ ILogger _root;
+ ILogger? _cached;
+ bool _frozen;
+
+ public CachingReloadableLogger(ReloadableLogger reloadableLogger, ILogger root, IReloadableLogger parent, Func configure)
{
- readonly ReloadableLogger _reloadableLogger;
- readonly Func _configure;
- readonly IReloadableLogger _parent;
-
- ILogger _root, _cached;
- bool _frozen;
+ _reloadableLogger = reloadableLogger;
+ _parent = parent;
+ _configure = configure;
+ _root = root;
+ _cached = null;
+ _frozen = false;
+ }
+
+ public ILogger ReloadLogger()
+ {
+ return _configure(_parent.ReloadLogger());
+ }
- public CachingReloadableLogger(ReloadableLogger reloadableLogger, ILogger root, IReloadableLogger parent, Func configure)
+ public ILogger ForContext(ILogEventEnricher enricher)
+ {
+ if (enricher == null!) return this;
+
+ if (_frozen)
+ return _cached!.ForContext(enricher);
+
+ if (_reloadableLogger.CreateChild(
+ _root,
+ this,
+ _cached,
+ p => p.ForContext(enricher),
+ out var child,
+ out var newRoot,
+ out var newCached,
+ out var frozen))
{
- _reloadableLogger = reloadableLogger;
- _parent = parent;
- _configure = configure;
- _root = root;
- _cached = null;
- _frozen = false;
+ Update(newRoot, newCached, frozen);
}
- public ILogger ReloadLogger()
+ return child;
+ }
+
+ public ILogger ForContext(IEnumerable enrichers)
+ {
+ if (enrichers == null!) return this;
+
+ if (_frozen)
+ return _cached!.ForContext(enrichers);
+
+ if (_reloadableLogger.CreateChild(
+ _root,
+ this,
+ _cached,
+ p => p.ForContext(enrichers),
+ out var child,
+ out var newRoot,
+ out var newCached,
+ out var frozen))
{
- return _configure(_parent.ReloadLogger());
+ Update(newRoot, newCached, frozen);
}
- public ILogger ForContext(ILogEventEnricher enricher)
- {
- if (enricher == null) return this;
-
- if (_frozen)
- return _cached.ForContext(enricher);
+ return child;
+ }
+ public ILogger ForContext(string propertyName, object? value, bool destructureObjects = false)
+ {
+ if (propertyName == null!) return this;
+
+ if (_frozen)
+ return _cached!.ForContext(propertyName, value, destructureObjects);
+
+ ILogger child;
+ if (value == null || value is string || value.GetType().IsPrimitive || value.GetType().IsEnum)
+ {
+ // Safe to extend the lifetime of `value` by closing over it.
+ // This ensures `SourceContext` is passed through appropriately and triggers minimum level overrides.
if (_reloadableLogger.CreateChild(
_root,
this,
- _cached,
- p => p.ForContext(enricher),
- out var child,
+ _cached,
+ p => p.ForContext(propertyName, value, destructureObjects),
+ out child,
out var newRoot,
out var newCached,
out var frozen))
{
Update(newRoot, newCached, frozen);
}
-
- return child;
}
-
- public ILogger ForContext(IEnumerable enrichers)
+ else
{
- if (enrichers == null) return this;
-
- if (_frozen)
- return _cached.ForContext(enrichers);
+ // It's not safe to extend the lifetime of `value` or pass it unexpectedly between threads.
+ // Changes to destructuring configuration won't be picked up by the cached logger.
+ var eager = ReloadLogger();
+ if (!eager.BindProperty(propertyName, value, destructureObjects, out var property))
+ return this;
+ var enricher = new FixedPropertyEnricher(property);
+
if (_reloadableLogger.CreateChild(
_root,
this,
- _cached,
- p => p.ForContext(enrichers),
- out var child,
+ _cached,
+ p => p.ForContext(enricher),
+ out child,
out var newRoot,
out var newCached,
out var frozen))
{
Update(newRoot, newCached, frozen);
}
+ }
- return child;
+ return child;
+ }
+
+ public ILogger ForContext()
+ {
+ if (_frozen)
+ return _cached!.ForContext();
+
+ if (_reloadableLogger.CreateChild(
+ _root,
+ this,
+ _cached,
+ p => p.ForContext(),
+ out var child,
+ out var newRoot,
+ out var newCached,
+ out var frozen))
+ {
+ Update(newRoot, newCached, frozen);
}
- public ILogger ForContext(string propertyName, object value, bool destructureObjects = false)
+ return child;
+ }
+
+ public ILogger ForContext(Type source)
+ {
+ if (_frozen)
+ return _cached!.ForContext(source);
+
+ if (_reloadableLogger.CreateChild(
+ _root,
+ this,
+ _cached,
+ p => p.ForContext(source),
+ out var child,
+ out var newRoot,
+ out var newCached,
+ out var frozen))
{
- if (propertyName == null) return this;
-
- if (_frozen)
- return _cached.ForContext(propertyName, value, destructureObjects);
+ Update(newRoot, newCached, frozen);
+ }
- ILogger child;
- if (value == null || value is string || value.GetType().IsPrimitive || value.GetType().IsEnum)
- {
- // Safe to extend the lifetime of `value` by closing over it.
- // This ensures `SourceContext` is passed through appropriately and triggers minimum level overrides.
- if (_reloadableLogger.CreateChild(
- _root,
- this,
- _cached,
- p => p.ForContext(propertyName, value, destructureObjects),
- out child,
- out var newRoot,
- out var newCached,
- out var frozen))
- {
- Update(newRoot, newCached, frozen);
- }
- }
- else
- {
- // It's not safe to extend the lifetime of `value` or pass it unexpectedly between threads.
- // Changes to destructuring configuration won't be picked up by the cached logger.
- var eager = ReloadLogger();
- if (!eager.BindProperty(propertyName, value, destructureObjects, out var property))
- return this;
+ return child;
+ }
- var enricher = new FixedPropertyEnricher(property);
+ void Update(ILogger newRoot, ILogger? newCached, bool frozen)
+ {
+ _root = newRoot;
+ _cached = newCached;
- if (_reloadableLogger.CreateChild(
- _root,
- this,
- _cached,
- p => p.ForContext(enricher),
- out child,
- out var newRoot,
- out var newCached,
- out var frozen))
- {
- Update(newRoot, newCached, frozen);
- }
- }
+ // https://github.com/dotnet/runtime/issues/20500#issuecomment-284774431
+ // Publish `_cached` and then `_frozen`. This is useful here because it means that once the logger is frozen - which
+ // we always expect - reads don't require any synchronization/interlocked instructions.
+#if FEATURE_MBPW
+ Interlocked.MemoryBarrierProcessWide();
+#else
+ Thread.MemoryBarrier();
+#endif
+ _frozen = frozen;
- return child;
- }
+#if FEATURE_MBPW
+ Interlocked.MemoryBarrierProcessWide();
+#else
+ Thread.MemoryBarrier();
+#endif
+ }
- public ILogger ForContext()
+ public override void Write(LogEvent logEvent)
+ {
+ if (_frozen)
{
- if (_frozen)
- return _cached.ForContext();
-
- if (_reloadableLogger.CreateChild(
- _root,
- this,
- _cached,
- p => p.ForContext(),
- out var child,
- out var newRoot,
- out var newCached,
- out var frozen))
- {
- Update(newRoot, newCached, frozen);
- }
-
- return child;
+ _cached!.Write(logEvent);
+ return;
}
- public ILogger ForContext(Type source)
+ if (_reloadableLogger.InvokeWrite(
+ _root,
+ _cached,
+ this,
+ logEvent,
+ out var newRoot,
+ out var newCached,
+ out var frozen))
{
- if (_frozen)
- return _cached.ForContext(source);
-
- if (_reloadableLogger.CreateChild(
- _root,
- this,
- _cached,
- p => p.ForContext(source),
- out var child,
- out var newRoot,
- out var newCached,
- out var frozen))
- {
- Update(newRoot, newCached, frozen);
- }
-
- return child;
+ Update(newRoot, newCached, frozen);
}
+ }
- void Update(ILogger newRoot, ILogger newCached, bool frozen)
+ public override void Write(LogEventLevel level, string messageTemplate)
+ {
+ if (_frozen)
{
- _root = newRoot;
- _cached = newCached;
-
- // https://github.com/dotnet/runtime/issues/20500#issuecomment-284774431
- // Publish `_cached` and then `_frozen`. This is useful here because it means that once the logger is frozen - which
- // we always expect - reads don't require any synchronization/interlocked instructions.
- Interlocked.MemoryBarrierProcessWide();
-
- _frozen = frozen;
-
- Interlocked.MemoryBarrierProcessWide();
+ _cached!.Write(level, messageTemplate);
+ return;
}
- public void Write(LogEvent logEvent)
+ if (_reloadableLogger.InvokeWrite(
+ _root,
+ _cached,
+ this,
+ level,
+ messageTemplate,
+ out var newRoot,
+ out var newCached,
+ out var frozen))
{
- if (_frozen)
- {
- _cached.Write(logEvent);
- return;
- }
-
- if (_reloadableLogger.InvokeWrite(
- _root,
- _cached,
- this,
- logEvent,
- out var newRoot,
- out var newCached,
- out var frozen))
- {
- Update(newRoot, newCached, frozen);
- }
+ Update(newRoot, newCached, frozen);
}
+ }
- public void Write(LogEventLevel level, string messageTemplate)
+ public override void Write(LogEventLevel level, string messageTemplate, T propertyValue)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- _cached.Write(level, messageTemplate);
- return;
- }
-
- if (_reloadableLogger.InvokeWrite(
- _root,
- _cached,
- this,
- level,
- messageTemplate,
- out var newRoot,
- out var newCached,
- out var frozen))
- {
- Update(newRoot, newCached, frozen);
- }
+ _cached!.Write(level, messageTemplate, propertyValue);
+ return;
}
- public void Write(LogEventLevel level, string messageTemplate, T propertyValue)
+ if (_reloadableLogger.InvokeWrite(
+ _root,
+ _cached,
+ this,
+ level,
+ messageTemplate,
+ propertyValue,
+ out var newRoot,
+ out var newCached,
+ out var frozen))
{
- if (_frozen)
- {
- _cached.Write(level, messageTemplate, propertyValue);
- return;
- }
-
- if (_reloadableLogger.InvokeWrite(
- _root,
- _cached,
- this,
- level,
- messageTemplate,
- propertyValue,
- out var newRoot,
- out var newCached,
- out var frozen))
- {
- Update(newRoot, newCached, frozen);
- }
+ Update(newRoot, newCached, frozen);
}
+ }
- public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ public override void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- _cached.Write(level, messageTemplate, propertyValue0, propertyValue1);
- return;
- }
+ _cached!.Write(level, messageTemplate, propertyValue0, propertyValue1);
+ return;
+ }
- if (_reloadableLogger.InvokeWrite(
- _root,
- _cached,
- this,
- level,
- messageTemplate,
- propertyValue0,
- propertyValue1,
- out var newRoot,
- out var newCached,
- out var frozen))
- {
- Update(newRoot, newCached, frozen);
- }
+ if (_reloadableLogger.InvokeWrite(
+ _root,
+ _cached,
+ this,
+ level,
+ messageTemplate,
+ propertyValue0,
+ propertyValue1,
+ out var newRoot,
+ out var newCached,
+ out var frozen))
+ {
+ Update(newRoot, newCached, frozen);
}
+ }
- public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
+ public override void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- _cached.Write(level, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
- return;
- }
+ _cached!.Write(level, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
+ return;
+ }
- if (_reloadableLogger.InvokeWrite(
- _root,
- _cached,
- this,
- level,
- messageTemplate,
- propertyValue0,
- propertyValue1,
- propertyValue2,
- out var newRoot,
- out var newCached,
- out var frozen))
- {
- Update(newRoot, newCached, frozen);
- }
+ if (_reloadableLogger.InvokeWrite(
+ _root,
+ _cached,
+ this,
+ level,
+ messageTemplate,
+ propertyValue0,
+ propertyValue1,
+ propertyValue2,
+ out var newRoot,
+ out var newCached,
+ out var frozen))
+ {
+ Update(newRoot, newCached, frozen);
}
+ }
- public void Write(LogEventLevel level, string messageTemplate, params object[] propertyValues)
+ public override void Write(LogEventLevel level, string messageTemplate, params object?[]? propertyValues)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- _cached.Write(level, messageTemplate, propertyValues);
- return;
- }
+ _cached!.Write(level, messageTemplate, propertyValues);
+ return;
+ }
- if (_reloadableLogger.InvokeWrite(
- _root,
- _cached,
- this,
- level,
- messageTemplate,
- propertyValues,
- out var newRoot,
- out var newCached,
- out var frozen))
- {
- Update(newRoot, newCached, frozen);
- }
+ if (_reloadableLogger.InvokeWrite(
+ _root,
+ _cached,
+ this,
+ level,
+ messageTemplate,
+ propertyValues,
+ out var newRoot,
+ out var newCached,
+ out var frozen))
+ {
+ Update(newRoot, newCached, frozen);
}
+ }
- public void Write(LogEventLevel level, Exception exception, string messageTemplate)
+ public override void Write(LogEventLevel level, Exception? exception, string messageTemplate)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- _cached.Write(level, exception, messageTemplate);
- return;
- }
+ _cached!.Write(level, exception, messageTemplate);
+ return;
+ }
- if (_reloadableLogger.InvokeWrite(
- _root,
- _cached,
- this,
- level,
- exception,
- messageTemplate,
- out var newRoot,
- out var newCached,
- out var frozen))
- {
- Update(newRoot, newCached, frozen);
- }
+ if (_reloadableLogger.InvokeWrite(
+ _root,
+ _cached,
+ this,
+ level,
+ exception,
+ messageTemplate,
+ out var newRoot,
+ out var newCached,
+ out var frozen))
+ {
+ Update(newRoot, newCached, frozen);
}
+ }
- public void Write(LogEventLevel level, Exception exception, string messageTemplate, T propertyValue)
+ public override void Write(LogEventLevel level, Exception? exception, string messageTemplate, T propertyValue)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- _cached.Write(level, exception, messageTemplate, propertyValue);
- return;
- }
+ _cached!.Write(level, exception, messageTemplate, propertyValue);
+ return;
+ }
- if (_reloadableLogger.InvokeWrite(
- _root,
- _cached,
- this,
- level,
- exception,
- messageTemplate,
- propertyValue,
- out var newRoot,
- out var newCached,
- out var frozen))
- {
- Update(newRoot, newCached, frozen);
- }
+ if (_reloadableLogger.InvokeWrite(
+ _root,
+ _cached,
+ this,
+ level,
+ exception,
+ messageTemplate,
+ propertyValue,
+ out var newRoot,
+ out var newCached,
+ out var frozen))
+ {
+ Update(newRoot, newCached, frozen);
}
+ }
- public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0,
- T1 propertyValue1)
+ public override void Write(LogEventLevel level, Exception? exception, string messageTemplate, T0 propertyValue0,
+ T1 propertyValue1)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- _cached.Write(level, exception, messageTemplate, propertyValue0, propertyValue1);
- return;
- }
+ _cached!.Write(level, exception, messageTemplate, propertyValue0, propertyValue1);
+ return;
+ }
- if (_reloadableLogger.InvokeWrite(
- _root,
- _cached,
- this,
- level,
- exception,
- messageTemplate,
- propertyValue0,
- propertyValue1,
- out var newRoot,
- out var newCached,
- out var frozen))
- {
- Update(newRoot, newCached, frozen);
- }
+ if (_reloadableLogger.InvokeWrite(
+ _root,
+ _cached,
+ this,
+ level,
+ exception,
+ messageTemplate,
+ propertyValue0,
+ propertyValue1,
+ out var newRoot,
+ out var newCached,
+ out var frozen))
+ {
+ Update(newRoot, newCached, frozen);
}
+ }
- public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0,
- T1 propertyValue1, T2 propertyValue2)
+ public override void Write(LogEventLevel level, Exception? exception, string messageTemplate, T0 propertyValue0,
+ T1 propertyValue1, T2 propertyValue2)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- _cached.Write(level, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
- return;
- }
+ _cached!.Write(level, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
+ return;
+ }
- if (_reloadableLogger.InvokeWrite(
- _root,
- _cached,
- this,
- level,
- exception,
- messageTemplate,
- propertyValue0,
- propertyValue1,
- propertyValue2,
- out var newRoot,
- out var newCached,
- out var frozen))
- {
- Update(newRoot, newCached, frozen);
- }
+ if (_reloadableLogger.InvokeWrite(
+ _root,
+ _cached,
+ this,
+ level,
+ exception,
+ messageTemplate,
+ propertyValue0,
+ propertyValue1,
+ propertyValue2,
+ out var newRoot,
+ out var newCached,
+ out var frozen))
+ {
+ Update(newRoot, newCached, frozen);
}
+ }
- public void Write(LogEventLevel level, Exception exception, string messageTemplate, params object[] propertyValues)
+ public override void Write(LogEventLevel level, Exception? exception, string messageTemplate, params object?[]? propertyValues)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- _cached.Write(level, exception, messageTemplate, propertyValues);
- return;
- }
+ _cached!.Write(level, exception, messageTemplate, propertyValues);
+ return;
+ }
- if (_reloadableLogger.InvokeWrite(
- _root,
- _cached,
- this,
- level,
- exception,
- messageTemplate,
- propertyValues,
- out var newRoot,
- out var newCached,
- out var frozen))
- {
- Update(newRoot, newCached, frozen);
- }
+ if (_reloadableLogger.InvokeWrite(
+ _root,
+ _cached,
+ this,
+ level,
+ exception,
+ messageTemplate,
+ propertyValues,
+ out var newRoot,
+ out var newCached,
+ out var frozen))
+ {
+ Update(newRoot, newCached, frozen);
}
+ }
- public bool IsEnabled(LogEventLevel level)
+ public bool IsEnabled(LogEventLevel level)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- return _cached.IsEnabled(level);
- }
+ return _cached!.IsEnabled(level);
+ }
- if (_reloadableLogger.InvokeIsEnabled(
- _root,
- _cached,
- this,
- level,
- out var isEnabled,
- out var newRoot,
- out var newCached,
- out var frozen))
- {
- Update(newRoot, newCached, frozen);
- }
+ if (_reloadableLogger.InvokeIsEnabled(
+ _root,
+ _cached,
+ this,
+ level,
+ out var isEnabled,
+ out var newRoot,
+ out var newCached,
+ out var frozen))
+ {
+ Update(newRoot, newCached, frozen);
+ }
- return isEnabled;
+ return isEnabled;
+ }
+
+ public bool BindMessageTemplate(string messageTemplate, object?[]? propertyValues,
+ [NotNullWhen(true)]
+ out MessageTemplate? parsedTemplate,
+ [NotNullWhen(true)]
+ out IEnumerable? boundProperties)
+ {
+ if (_frozen)
+ {
+ return _cached!.BindMessageTemplate(messageTemplate, propertyValues, out parsedTemplate, out boundProperties);
}
-
- public bool BindMessageTemplate(string messageTemplate, object[] propertyValues, out MessageTemplate parsedTemplate,
- out IEnumerable boundProperties)
+
+ if (_reloadableLogger.InvokeBindMessageTemplate(
+ _root,
+ _cached,
+ this,
+ messageTemplate,
+ propertyValues,
+ out parsedTemplate,
+ out boundProperties,
+ out var canBind,
+ out var newRoot,
+ out var newCached,
+ out var frozen))
{
- if (_frozen)
- {
- return _cached.BindMessageTemplate(messageTemplate, propertyValues, out parsedTemplate, out boundProperties);
- }
+ Update(newRoot, newCached, frozen);
+ }
- if (_reloadableLogger.InvokeBindMessageTemplate(
- _root,
- _cached,
- this,
- messageTemplate,
- propertyValues,
- out parsedTemplate,
- out boundProperties,
- out var canBind,
- out var newRoot,
- out var newCached,
- out var frozen))
- {
- Update(newRoot, newCached, frozen);
- }
+ return canBind;
+ }
- return canBind;
+ public bool BindProperty(string? propertyName, object? value, bool destructureObjects,
+ [NotNullWhen(true)]
+ out LogEventProperty? property)
+ {
+ if (_frozen)
+ {
+ return _cached!.BindProperty(propertyName, value, destructureObjects, out property);
}
- public bool BindProperty(string propertyName, object value, bool destructureObjects, out LogEventProperty property)
+ if (_reloadableLogger.InvokeBindProperty(
+ _root,
+ _cached,
+ this,
+ propertyName,
+ value,
+ destructureObjects,
+ out property,
+ out var canBind,
+ out var newRoot,
+ out var newCached,
+ out var frozen))
{
- if (_frozen)
- {
- return _cached.BindProperty(propertyName, value, destructureObjects, out property);
- }
-
- if (_reloadableLogger.InvokeBindProperty(
- _root,
- _cached,
- this,
- propertyName,
- value,
- destructureObjects,
- out property,
- out var canBind,
- out var newRoot,
- out var newCached,
- out var frozen))
- {
- Update(newRoot, newCached, frozen);
- }
-
- return canBind;
+ Update(newRoot, newCached, frozen);
}
+
+ return canBind;
}
}
-
-#endif
diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContext.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContext.cs
index 44462ac..af9b99f 100644
--- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContext.cs
+++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContext.cs
@@ -15,53 +15,52 @@
using System;
using System.Threading;
-namespace Serilog.Extensions.Hosting
+namespace Serilog.Extensions.Hosting;
+
+///
+/// Implements an ambient diagnostic context using .
+///
+/// Consumers should use to set context properties.
+public sealed class DiagnosticContext : IDiagnosticContext
{
+ readonly ILogger? _logger;
+
///
- /// Implements an ambient diagnostic context using .
+ /// Construct a .
///
- /// Consumers should use to set context properties.
- public sealed class DiagnosticContext : IDiagnosticContext
+ /// A logger for binding properties in the context, or null to use .
+ public DiagnosticContext(ILogger? logger)
{
- readonly ILogger _logger;
+ _logger = logger;
+ }
- ///
- /// Construct a .
- ///
- /// A logger for binding properties in the context, or null to use .
- public DiagnosticContext(ILogger logger)
- {
- _logger = logger;
- }
+ ///
+ /// Start collecting properties to associate with the current diagnostic context. This will replace
+ /// the active collector, if any.
+ ///
+ /// A collector that will receive properties added in the current diagnostic context.
+ public DiagnosticContextCollector BeginCollection()
+ {
+ return AmbientDiagnosticContextCollector.Begin();
+ }
- ///
- /// Start collecting properties to associate with the current diagnostic context. This will replace
- /// the active collector, if any.
- ///
- /// A collector that will receive properties added in the current diagnostic context.
- public DiagnosticContextCollector BeginCollection()
- {
- return AmbientDiagnosticContextCollector.Begin();
- }
+ ///
+ public void Set(string propertyName, object value, bool destructureObjects = false)
+ {
+ if (propertyName == null) throw new ArgumentNullException(nameof(propertyName));
- ///
- public void Set(string propertyName, object value, bool destructureObjects = false)
+ var collector = AmbientDiagnosticContextCollector.Current;
+ if (collector != null &&
+ (_logger ?? Log.Logger).BindProperty(propertyName, value, destructureObjects, out var property))
{
- if (propertyName == null) throw new ArgumentNullException(nameof(propertyName));
-
- var collector = AmbientDiagnosticContextCollector.Current;
- if (collector != null &&
- (_logger ?? Log.Logger).BindProperty(propertyName, value, destructureObjects, out var property))
- {
- collector.AddOrUpdate(property);
- }
+ collector.AddOrUpdate(property);
}
+ }
- ///
- public void SetException(Exception exception)
- {
- var collector = AmbientDiagnosticContextCollector.Current;
- collector?.SetException(exception);
- }
+ ///
+ public void SetException(Exception exception)
+ {
+ var collector = AmbientDiagnosticContextCollector.Current;
+ collector?.SetException(exception);
}
}
diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContextCollector.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContextCollector.cs
index 63c6339..6ade4ff 100644
--- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContextCollector.cs
+++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContextCollector.cs
@@ -1,107 +1,104 @@
-using System;
-using System.Collections.Generic;
-using Serilog.Events;
+using Serilog.Events;
-namespace Serilog.Extensions.Hosting
+namespace Serilog.Extensions.Hosting;
+
+///
+/// A container that receives properties added to a diagnostic context.
+///
+public sealed class DiagnosticContextCollector : IDisposable
{
+ readonly IDisposable _chainedDisposable;
+ readonly object _propertiesLock = new();
+ Exception? _exception;
+ Dictionary? _properties = new();
+
///
- /// A container that receives properties added to a diagnostic context.
+ /// Construct a .
///
- public sealed class DiagnosticContextCollector : IDisposable
+ /// An object that will be disposed to signal completion/disposal of
+ /// the collector.
+ public DiagnosticContextCollector(IDisposable chainedDisposable)
{
- readonly IDisposable _chainedDisposable;
- readonly object _propertiesLock = new object();
- Exception _exception;
- Dictionary _properties = new Dictionary();
+ _chainedDisposable = chainedDisposable ?? throw new ArgumentNullException(nameof(chainedDisposable));
+ }
- ///
- /// Construct a .
- ///
- /// An object that will be disposed to signal completion/disposal of
- /// the collector.
- public DiagnosticContextCollector(IDisposable chainedDisposable)
- {
- _chainedDisposable = chainedDisposable ?? throw new ArgumentNullException(nameof(chainedDisposable));
- }
+ ///
+ /// Add the property to the context.
+ ///
+ /// The property to add.
+ public void AddOrUpdate(LogEventProperty property)
+ {
+ if (property == null) throw new ArgumentNullException(nameof(property));
- ///
- /// Add the property to the context.
- ///
- /// The property to add.
- public void AddOrUpdate(LogEventProperty property)
+ lock (_propertiesLock)
{
- if (property == null) throw new ArgumentNullException(nameof(property));
-
- lock (_propertiesLock)
- {
- if (_properties == null) return;
- _properties[property.Name] = property;
- }
+ if (_properties == null) return;
+ _properties[property.Name] = property;
}
+ }
- ///
- /// Set the exception associated with the current diagnostic context.
- ///
- ///
- /// Passing an exception to the diagnostic context is useful when unhandled exceptions are handled before reaching Serilog's
- /// RequestLoggingMiddleware. One example is using https://www.nuget.org/packages/Hellang.Middleware.ProblemDetails to transform
- /// exceptions to ProblemDetails responses.
- ///
- ///
- /// If an unhandled exception reaches Serilog's RequestLoggingMiddleware, then the unhandled exception takes precedence.
- /// If null is given, it clears any previously assigned exception.
- ///
- /// The exception to log.
- public void SetException(Exception exception)
+ ///
+ /// Set the exception associated with the current diagnostic context.
+ ///
+ ///
+ /// Passing an exception to the diagnostic context is useful when unhandled exceptions are handled before reaching Serilog's
+ /// RequestLoggingMiddleware. One example is using https://www.nuget.org/packages/Hellang.Middleware.ProblemDetails to transform
+ /// exceptions to ProblemDetails responses.
+ ///
+ ///
+ /// If an unhandled exception reaches Serilog's RequestLoggingMiddleware, then the unhandled exception takes precedence.
+ /// If null is given, it clears any previously assigned exception.
+ ///
+ /// The exception to log.
+ public void SetException(Exception exception)
+ {
+ lock (_propertiesLock)
{
- lock (_propertiesLock)
- {
- if (_properties == null) return;
- _exception = exception;
- }
+ if (_properties == null) return;
+ _exception = exception;
}
+ }
- ///
- /// Complete the context and retrieve the properties added to it, if any. This will
- /// stop collection and remove the collector from the original execution context and
- /// any of its children.
- ///
- /// The collected properties, or null if no collection is active.
- /// True if properties could be collected.
- ///
- [Obsolete("Replaced by TryComplete(out IEnumerable properties, out Exception exception).")]
- public bool TryComplete(out IEnumerable properties)
- {
- return TryComplete(out properties, out _);
- }
+ ///
+ /// Complete the context and retrieve the properties added to it, if any. This will
+ /// stop collection and remove the collector from the original execution context and
+ /// any of its children.
+ ///
+ /// The collected properties, or null if no collection is active.
+ /// True if properties could be collected.
+ ///
+ [Obsolete("Replaced by TryComplete(out IEnumerable properties, out Exception exception).")]
+ public bool TryComplete(out IEnumerable? properties)
+ {
+ return TryComplete(out properties, out _);
+ }
- ///
- /// Complete the context and retrieve the properties and exception added to it, if any. This will
- /// stop collection and remove the collector from the original execution context and
- /// any of its children.
- ///
- /// The collected properties, or null if no collection is active.
- /// The collected exception, or null if none has been collected or if no collection is active.
- /// True if properties could be collected.
- ///
- ///
- public bool TryComplete(out IEnumerable properties, out Exception exception)
+ ///
+ /// Complete the context and retrieve the properties and exception added to it, if any. This will
+ /// stop collection and remove the collector from the original execution context and
+ /// any of its children.
+ ///
+ /// The collected properties, or null if no collection is active.
+ /// The collected exception, or null if none has been collected or if no collection is active.
+ /// True if properties could be collected.
+ ///
+ ///
+ public bool TryComplete(out IEnumerable? properties, out Exception? exception)
+ {
+ lock (_propertiesLock)
{
- lock (_propertiesLock)
- {
- properties = _properties?.Values;
- exception = _exception;
- _properties = null;
- _exception = null;
- Dispose();
- return properties != null;
- }
+ properties = _properties?.Values;
+ exception = _exception;
+ _properties = null;
+ _exception = null;
+ Dispose();
+ return properties != null;
}
+ }
- ///
- public void Dispose()
- {
- _chainedDisposable.Dispose();
- }
+ ///
+ public void Dispose()
+ {
+ _chainedDisposable.Dispose();
}
}
diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/FixedPropertyEnricher.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/FixedPropertyEnricher.cs
index 3543173..d552194 100644
--- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/FixedPropertyEnricher.cs
+++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/FixedPropertyEnricher.cs
@@ -15,20 +15,19 @@
using Serilog.Core;
using Serilog.Events;
-namespace Serilog.Extensions.Hosting
+namespace Serilog.Extensions.Hosting;
+
+class FixedPropertyEnricher : ILogEventEnricher
{
- class FixedPropertyEnricher : ILogEventEnricher
- {
- readonly LogEventProperty _property;
+ readonly LogEventProperty _property;
- public FixedPropertyEnricher(LogEventProperty property)
- {
- _property = property;
- }
+ public FixedPropertyEnricher(LogEventProperty property)
+ {
+ _property = property;
+ }
- public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
- {
- logEvent.AddPropertyIfAbsent(_property);
- }
+ public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
+ {
+ logEvent.AddPropertyIfAbsent(_property);
}
}
diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/IReloadableLogger.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/IReloadableLogger.cs
index 07b4cf9..a3c2de4 100644
--- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/IReloadableLogger.cs
+++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/IReloadableLogger.cs
@@ -12,10 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-namespace Serilog.Extensions.Hosting
+namespace Serilog.Extensions.Hosting;
+
+interface IReloadableLogger
{
- interface IReloadableLogger
- {
- ILogger ReloadLogger();
- }
+ ILogger ReloadLogger();
}
\ No newline at end of file
diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/InjectedLoggerSettings.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/InjectedLoggerSettings.cs
index 97e37ea..f190089 100644
--- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/InjectedLoggerSettings.cs
+++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/InjectedLoggerSettings.cs
@@ -3,37 +3,36 @@
using Serilog.Configuration;
using Serilog.Core;
-namespace Serilog.Extensions.Hosting
+namespace Serilog.Extensions.Hosting;
+
+class InjectedLoggerSettings : ILoggerSettings
{
- class InjectedLoggerSettings : ILoggerSettings
+ readonly IServiceProvider _services;
+
+ public InjectedLoggerSettings(IServiceProvider services)
+ {
+ _services = services ?? throw new ArgumentNullException(nameof(services));
+ }
+
+ public void Configure(LoggerConfiguration loggerConfiguration)
{
- readonly IServiceProvider _services;
-
- public InjectedLoggerSettings(IServiceProvider services)
- {
- _services = services ?? throw new ArgumentNullException(nameof(services));
- }
-
- public void Configure(LoggerConfiguration loggerConfiguration)
- {
- var levelSwitch = _services.GetService();
- if (levelSwitch != null)
- loggerConfiguration.MinimumLevel.ControlledBy(levelSwitch);
-
- foreach (var settings in _services.GetServices())
- loggerConfiguration.ReadFrom.Settings(settings);
-
- foreach (var policy in _services.GetServices())
- loggerConfiguration.Destructure.With(policy);
-
- foreach (var enricher in _services.GetServices())
- loggerConfiguration.Enrich.With(enricher);
-
- foreach (var filter in _services.GetServices())
- loggerConfiguration.Filter.With(filter);
-
- foreach (var sink in _services.GetServices())
- loggerConfiguration.WriteTo.Sink(sink);
- }
+ var levelSwitch = _services.GetService();
+ if (levelSwitch != null)
+ loggerConfiguration.MinimumLevel.ControlledBy(levelSwitch);
+
+ foreach (var settings in _services.GetServices())
+ loggerConfiguration.ReadFrom.Settings(settings);
+
+ foreach (var policy in _services.GetServices())
+ loggerConfiguration.Destructure.With(policy);
+
+ foreach (var enricher in _services.GetServices())
+ loggerConfiguration.Enrich.With(enricher);
+
+ foreach (var filter in _services.GetServices())
+ loggerConfiguration.Filter.With(filter);
+
+ foreach (var sink in _services.GetServices())
+ loggerConfiguration.WriteTo.Sink(sink);
}
}
diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/LoggerBase.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/LoggerBase.cs
new file mode 100644
index 0000000..c52256b
--- /dev/null
+++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/LoggerBase.cs
@@ -0,0 +1,918 @@
+// Copyright 2020 Serilog Contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using Serilog.Core;
+using Serilog.Events;
+
+namespace Serilog.Extensions.Hosting;
+
+///
+/// Implements default methods for caching/reloadable loggers.
+///
+public abstract class LoggerBase
+{
+ static readonly object[] NoPropertyValues = [];
+
+ internal LoggerBase()
+ {
+ }
+
+ ///
+ /// Write an event to the log.
+ ///
+ /// The event to write.
+ public abstract void Write(LogEvent logEvent);
+
+ ///
+ /// Write a log event with the specified level.
+ ///
+ /// The level of the event.
+ /// Message template describing the event.
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public abstract void Write(LogEventLevel level, string messageTemplate);
+
+ ///
+ /// Write a log event with the specified level.
+ ///
+ /// The level of the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public abstract void Write(LogEventLevel level, string messageTemplate, T propertyValue);
+
+ ///
+ /// Write a log event with the specified level.
+ ///
+ /// The level of the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public abstract void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1);
+
+ ///
+ /// Write a log event with the specified level.
+ ///
+ /// The level of the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public abstract void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2);
+
+ ///
+ /// Write a log event with the specified level.
+ ///
+ /// The level of the event.
+ ///
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public abstract void Write(LogEventLevel level, string messageTemplate, params object?[]? propertyValues);
+
+ ///
+ /// Write a log event with the specified level and associated exception.
+ ///
+ /// The level of the event.
+ /// Exception related to the event.
+ /// Message template describing the event.
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public abstract void Write(LogEventLevel level, Exception? exception, string messageTemplate);
+
+ ///
+ /// Write a log event with the specified level and associated exception.
+ ///
+ /// The level of the event.
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public abstract void Write(LogEventLevel level, Exception? exception, string messageTemplate, T propertyValue);
+
+ ///
+ /// Write a log event with the specified level and associated exception.
+ ///
+ /// The level of the event.
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public abstract void Write(LogEventLevel level, Exception? exception, string messageTemplate, T0 propertyValue0,
+ T1 propertyValue1);
+
+ ///
+ /// Write a log event with the specified level and associated exception.
+ ///
+ /// The level of the event.
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public abstract void Write(LogEventLevel level, Exception? exception, string messageTemplate,
+ T0 propertyValue0, T1 propertyValue1, T2 propertyValue2);
+
+ ///
+ /// Write a log event with the specified level and associated exception.
+ ///
+ /// The level of the event.
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Objects positionally formatted into the message template.
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public abstract void Write(LogEventLevel level, Exception? exception, string messageTemplate, params object?[]? propertyValues);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ ///
+ /// Log.Verbose("Staring into space, wondering if we're alone.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Verbose(string messageTemplate)
+ => Write(LogEventLevel.Verbose, messageTemplate, NoPropertyValues);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Verbose("Staring into space, wondering if we're alone.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Verbose(string messageTemplate, T propertyValue)
+ => Write(LogEventLevel.Verbose, messageTemplate, propertyValue);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Verbose("Staring into space, wondering if we're alone.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ => Write(LogEventLevel.Verbose, messageTemplate, propertyValue0, propertyValue1);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Verbose("Staring into space, wondering if we're alone.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ => Write(LogEventLevel.Verbose, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Message template describing the event.
+ /// Objects positionally formatted into the message template.
+ ///
+ /// Log.Verbose("Staring into space, wondering if we're alone.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Verbose(string messageTemplate, params object?[]? propertyValues)
+ => Verbose((Exception?)null, messageTemplate, propertyValues);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ ///
+ /// Log.Verbose(ex, "Staring into space, wondering where this comet came from.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Verbose(Exception? exception, string messageTemplate)
+ => Write(LogEventLevel.Verbose, exception, messageTemplate, NoPropertyValues);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Verbose(ex, "Staring into space, wondering where this comet came from.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Verbose(Exception? exception, string messageTemplate, T propertyValue)
+ => Write(LogEventLevel.Verbose, exception, messageTemplate, propertyValue);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Verbose(ex, "Staring into space, wondering where this comet came from.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Verbose(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ => Write(LogEventLevel.Verbose, exception, messageTemplate, propertyValue0, propertyValue1);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Verbose(ex, "Staring into space, wondering where this comet came from.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Verbose(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ => Write(LogEventLevel.Verbose, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Objects positionally formatted into the message template.
+ ///
+ /// Log.Verbose(ex, "Staring into space, wondering where this comet came from.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Verbose(Exception? exception, string messageTemplate, params object?[]? propertyValues)
+ => Write(LogEventLevel.Verbose, exception, messageTemplate, propertyValues);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ ///
+ /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Debug(string messageTemplate)
+ => Write(LogEventLevel.Debug, messageTemplate, NoPropertyValues);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Debug(string messageTemplate, T propertyValue)
+ => Write(LogEventLevel.Debug, messageTemplate, propertyValue);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ => Write(LogEventLevel.Debug, messageTemplate, propertyValue0, propertyValue1);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ => Write(LogEventLevel.Debug, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Message template describing the event.
+ /// Objects positionally formatted into the message template.
+ ///
+ /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Debug(string messageTemplate, params object?[]? propertyValues)
+ => Debug((Exception?)null, messageTemplate, propertyValues);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ ///
+ /// Log.Debug(ex, "Swallowing a mundane exception.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Debug(Exception? exception, string messageTemplate)
+ => Write(LogEventLevel.Debug, exception, messageTemplate, NoPropertyValues);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Debug(ex, "Swallowing a mundane exception.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Debug(Exception? exception, string messageTemplate, T propertyValue)
+ => Write(LogEventLevel.Debug, exception, messageTemplate, propertyValue);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Debug(ex, "Swallowing a mundane exception.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Debug(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ => Write(LogEventLevel.Debug, exception, messageTemplate, propertyValue0, propertyValue1);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Debug(ex, "Swallowing a mundane exception.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Debug(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ => Write(LogEventLevel.Debug, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Objects positionally formatted into the message template.
+ ///
+ /// Log.Debug(ex, "Swallowing a mundane exception.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Debug(Exception? exception, string messageTemplate, params object?[]? propertyValues)
+ => Write(LogEventLevel.Debug, exception, messageTemplate, propertyValues);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ ///
+ /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Information(string messageTemplate)
+ => Write(LogEventLevel.Information, messageTemplate, NoPropertyValues);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Information(string messageTemplate, T propertyValue)
+ => Write(LogEventLevel.Information, messageTemplate, propertyValue);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ => Write(LogEventLevel.Information, messageTemplate, propertyValue0, propertyValue1);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ => Write(LogEventLevel.Information, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Message template describing the event.
+ /// Objects positionally formatted into the message template.
+ ///
+ /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Information(string messageTemplate, params object?[]? propertyValues)
+ => Information((Exception?)null, messageTemplate, propertyValues);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ ///
+ /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Information(Exception? exception, string messageTemplate)
+ => Write(LogEventLevel.Information, exception, messageTemplate, NoPropertyValues);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Information(Exception? exception, string messageTemplate, T propertyValue)
+ => Write(LogEventLevel.Information, exception, messageTemplate, propertyValue);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Information(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ => Write(LogEventLevel.Information, exception, messageTemplate, propertyValue0, propertyValue1);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Information(Exception? exception, string messageTemplate, T0 propertyValue0,
+ T1 propertyValue1, T2 propertyValue2)
+ => Write(LogEventLevel.Information, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Objects positionally formatted into the message template.
+ ///
+ /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Information(Exception? exception, string messageTemplate, params object?[]? propertyValues)
+ => Write(LogEventLevel.Information, exception, messageTemplate, propertyValues);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ ///
+ /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Warning(string messageTemplate)
+ => Write(LogEventLevel.Warning, messageTemplate, NoPropertyValues);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Warning(string messageTemplate, T propertyValue)
+ => Write(LogEventLevel.Warning, messageTemplate, propertyValue);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ => Write(LogEventLevel.Warning, messageTemplate, propertyValue0, propertyValue1);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ => Write(LogEventLevel.Warning, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Message template describing the event.
+ /// Objects positionally formatted into the message template.
+ ///
+ /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Warning(string messageTemplate, params object?[]? propertyValues)
+ => Warning((Exception?)null, messageTemplate, propertyValues);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ ///
+ /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Warning(Exception? exception, string messageTemplate)
+ => Write(LogEventLevel.Warning, exception, messageTemplate, NoPropertyValues);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Warning(Exception? exception, string messageTemplate, T propertyValue)
+ => Write(LogEventLevel.Warning, exception, messageTemplate, propertyValue);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Warning(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ => Write(LogEventLevel.Warning, exception, messageTemplate, propertyValue0, propertyValue1);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Warning(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ => Write(LogEventLevel.Warning, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Objects positionally formatted into the message template.
+ ///
+ /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Warning(Exception? exception, string messageTemplate, params object?[]? propertyValues)
+ => Write(LogEventLevel.Warning, exception, messageTemplate, propertyValues);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ ///
+ /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Error(string messageTemplate)
+ => Write(LogEventLevel.Error, messageTemplate, NoPropertyValues);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Error(string messageTemplate, T propertyValue)
+ => Write(LogEventLevel.Error, messageTemplate, propertyValue);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ => Write(LogEventLevel.Error, messageTemplate, propertyValue0, propertyValue1);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ => Write(LogEventLevel.Error, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Message template describing the event.
+ /// Objects positionally formatted into the message template.
+ ///
+ /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Error(string messageTemplate, params object?[]? propertyValues)
+ => Error((Exception?)null, messageTemplate, propertyValues);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ ///
+ /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Error(Exception? exception, string messageTemplate)
+ => Write(LogEventLevel.Error, exception, messageTemplate, NoPropertyValues);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Error(Exception? exception, string messageTemplate, T propertyValue)
+ => Write(LogEventLevel.Error, exception, messageTemplate, propertyValue);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Error(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ => Write(LogEventLevel.Error, exception, messageTemplate, propertyValue0, propertyValue1);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Error(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ => Write(LogEventLevel.Error, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Objects positionally formatted into the message template.
+ ///
+ /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length);
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Error(Exception? exception, string messageTemplate, params object?[]? propertyValues)
+ => Write(LogEventLevel.Error, exception, messageTemplate, propertyValues);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ ///
+ /// Log.Fatal("Process terminating.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Fatal(string messageTemplate)
+ => Write(LogEventLevel.Fatal, messageTemplate, NoPropertyValues);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Fatal("Process terminating.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Fatal(string messageTemplate, T propertyValue)
+ => Write(LogEventLevel.Fatal, messageTemplate, propertyValue);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Fatal("Process terminating.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ => Write(LogEventLevel.Fatal, messageTemplate, propertyValue0, propertyValue1);
+
+ ///
+ /// Write a log event with the level.
+ ///
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Fatal("Process terminating.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ => Write(LogEventLevel.Fatal, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Message template describing the event.
+ /// Objects positionally formatted into the message template.
+ ///
+ /// Log.Fatal("Process terminating.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Fatal(string messageTemplate, params object?[]? propertyValues)
+ => Fatal((Exception?)null, messageTemplate, propertyValues);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ ///
+ /// Log.Fatal(ex, "Process terminating.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Fatal(Exception? exception, string messageTemplate)
+ => Write(LogEventLevel.Fatal, exception, messageTemplate, NoPropertyValues);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Fatal(ex, "Process terminating.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Fatal(Exception? exception, string messageTemplate, T propertyValue)
+ => Write(LogEventLevel.Fatal, exception, messageTemplate, propertyValue);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Fatal(ex, "Process terminating.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Fatal(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ => Write(LogEventLevel.Fatal, exception, messageTemplate, propertyValue0, propertyValue1);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ /// Object positionally formatted into the message template.
+ ///
+ /// Log.Fatal(ex, "Process terminating.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Fatal(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ => Write(LogEventLevel.Fatal, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
+
+ ///
+ /// Write a log event with the level and associated exception.
+ ///
+ /// Exception related to the event.
+ /// Message template describing the event.
+ /// Objects positionally formatted into the message template.
+ ///
+ /// Log.Fatal(ex, "Process terminating.");
+ ///
+ [MessageTemplateFormatMethod("messageTemplate")]
+ public void Fatal(Exception? exception, string messageTemplate, params object?[]? propertyValues)
+ => Write(LogEventLevel.Fatal, exception, messageTemplate, propertyValues);
+}
\ No newline at end of file
diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/NullEnricher.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/NullEnricher.cs
index af13dfc..ea6ace3 100644
--- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/NullEnricher.cs
+++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/NullEnricher.cs
@@ -15,14 +15,13 @@
using Serilog.Core;
using Serilog.Events;
-namespace Serilog.Extensions.Hosting
+namespace Serilog.Extensions.Hosting;
+
+// Does nothing, but makes it easy to create an `ILogger` from a Serilog `Logger`
+// that will not dispose the underlying pipeline when disposed itself.
+class NullEnricher : ILogEventEnricher
{
- // Does nothing, but makes it easy to create an `ILogger` from a Serilog `Logger`
- // that will not dispose the underlying pipeline when disposed itself.
- class NullEnricher : ILogEventEnricher
+ public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
- public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
- {
- }
}
}
\ No newline at end of file
diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/ReloadableLogger.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/ReloadableLogger.cs
index 6ec1d37..74d0169 100644
--- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/ReloadableLogger.cs
+++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/ReloadableLogger.cs
@@ -12,675 +12,677 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#if !NO_RELOADABLE_LOGGER
-
-using System;
-using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
-using System.Threading;
using Serilog.Core;
using Serilog.Events;
// ReSharper disable MemberCanBePrivate.Global
-namespace Serilog.Extensions.Hosting
+namespace Serilog.Extensions.Hosting;
+
+///
+/// A Serilog that can be reconfigured without invalidating existing
+/// instances derived from it.
+///
+public sealed class ReloadableLogger : LoggerBase, ILogger, IReloadableLogger, IDisposable
{
+ readonly object _sync = new();
+ Logger _logger;
+
+ // One-way; if the value is `true` it can never again be made `false`, allowing "double-checked" reads. If
+ // `true`, `_logger` is final and a memory barrier ensures the final value is seen by all threads.
+ bool _frozen;
+
+ // Unsure whether this should be exposed; currently going for minimal API surface.
+ internal ReloadableLogger(Logger initial)
+ {
+ _logger = initial ?? throw new ArgumentNullException(nameof(initial));
+ }
+
+ ILogger IReloadableLogger.ReloadLogger()
+ {
+ return _logger;
+ }
+
///
- /// A Serilog that can be reconfigured without invalidating existing
- /// instances derived from it.
+ /// Reload the logger using the supplied configuration delegate.
///
- public sealed class ReloadableLogger : ILogger, IReloadableLogger, IDisposable
+ /// A callback in which the logger is reconfigured.
+ /// is null.
+ public void Reload(Func configure)
{
- readonly object _sync = new object();
- Logger _logger;
+ if (configure == null) throw new ArgumentNullException(nameof(configure));
- // One-way; if the value is `true` it can never again be made `false`, allowing "double-checked" reads. If
- // `true`, `_logger` is final and a memory barrier ensures the final value is seen by all threads.
- bool _frozen;
-
- // Unsure whether this should be exposed; currently going for minimal API surface.
- internal ReloadableLogger(Logger initial)
+ lock (_sync)
{
- _logger = initial ?? throw new ArgumentNullException(nameof(initial));
- }
-
- ILogger IReloadableLogger.ReloadLogger()
- {
- return _logger;
+ _logger.Dispose();
+ _logger = configure(new LoggerConfiguration()).CreateLogger();
}
+ }
- ///
- /// Reload the logger using the supplied configuration delegate.
- ///
- /// A callback in which the logger is reconfigured.
- /// is null.
- public void Reload(Func configure)
+ ///
+ /// Freeze the logger, so that no further reconfiguration is possible. Once the logger is frozen, logging through
+ /// new contextual loggers will have no additional cost, and logging directly through this logger will not require
+ /// any synchronization.
+ ///
+ /// The configured with the final settings.
+ /// The logger is already frozen.
+ public Logger Freeze()
+ {
+ lock (_sync)
{
- if (configure == null) throw new ArgumentNullException(nameof(configure));
+ if (_frozen)
+ throw new InvalidOperationException("The logger is already frozen.");
+
+ _frozen = true;
+
+ // https://github.com/dotnet/runtime/issues/20500#issuecomment-284774431
+ // Publish `_logger` and `_frozen`. This is useful here because it means that once the logger is frozen - which
+ // we always expect - reads don't require any synchronization/interlocked instructions.
+#if FEATURE_MBPW
+ Interlocked.MemoryBarrierProcessWide();
+#else
+ Thread.MemoryBarrier();
+#endif
- lock (_sync)
- {
- _logger.Dispose();
- _logger = configure(new LoggerConfiguration()).CreateLogger();
- }
+ return _logger;
}
+ }
- ///
- /// Freeze the logger, so that no further reconfiguration is possible. Once the logger is frozen, logging through
- /// new contextual loggers will have no additional cost, and logging directly through this logger will not require
- /// any synchronization.
- ///
- /// The configured with the final settings.
- /// The logger is already frozen.
- public Logger Freeze()
- {
- lock (_sync)
- {
- if (_frozen)
- throw new InvalidOperationException("The logger is already frozen.");
+ ///
+ public void Dispose()
+ {
+ lock (_sync)
+ _logger.Dispose();
+ }
- _frozen = true;
+ ///
+ public ILogger ForContext(ILogEventEnricher enricher)
+ {
+ if (enricher == null!) return this;
+
+ if (_frozen)
+ return _logger.ForContext(enricher);
- // https://github.com/dotnet/runtime/issues/20500#issuecomment-284774431
- // Publish `_logger` and `_frozen`. This is useful here because it means that once the logger is frozen - which
- // we always expect - reads don't require any synchronization/interlocked instructions.
- Interlocked.MemoryBarrierProcessWide();
-
- return _logger;
- }
- }
+ lock (_sync)
+ return new CachingReloadableLogger(this, _logger, this, p => p.ForContext(enricher));
+ }
- ///
- public void Dispose()
+ ///
+ public ILogger ForContext(IEnumerable enrichers)
+ {
+ if (enrichers == null!) return this;
+
+ if (_frozen)
+ return _logger.ForContext(enrichers);
+
+ lock (_sync)
+ return new CachingReloadableLogger(this, _logger, this, p => p.ForContext(enrichers));
+ }
+
+ ///
+ public ILogger ForContext(string propertyName, object? value, bool destructureObjects = false)
+ {
+ if (propertyName == null!) return this;
+
+ if (_frozen)
+ return _logger.ForContext(propertyName, value, destructureObjects);
+
+ lock (_sync)
+ return new CachingReloadableLogger(this, _logger, this, p => p.ForContext(propertyName, value, destructureObjects));
+ }
+
+ ///
+ public ILogger ForContext()
+ {
+ if (_frozen)
+ return _logger.ForContext();
+
+ lock (_sync)
+ return new CachingReloadableLogger(this, _logger, this, p => p.ForContext());
+ }
+
+ ///
+ public ILogger ForContext(Type source)
+ {
+ if (source == null!) return this;
+
+ if (_frozen)
+ return _logger.ForContext(source);
+
+ lock (_sync)
+ return new CachingReloadableLogger(this, _logger, this, p => p.ForContext(source));
+ }
+
+ ///
+ public override void Write(LogEvent logEvent)
+ {
+ if (_frozen)
{
- lock (_sync)
- _logger.Dispose();
+ _logger.Write(logEvent);
+ return;
}
- ///
- public ILogger ForContext(ILogEventEnricher enricher)
+ lock (_sync)
{
- if (enricher == null) return this;
-
- if (_frozen)
- return _logger.ForContext(enricher);
-
- lock (_sync)
- return new CachingReloadableLogger(this, _logger, this, p => p.ForContext(enricher));
+ _logger.Write(logEvent);
}
+ }
- ///
- public ILogger ForContext(IEnumerable enrichers)
+ ///
+ public override void Write(LogEventLevel level, string messageTemplate)
+ {
+ if (_frozen)
{
- if (enrichers == null) return this;
-
- if (_frozen)
- return _logger.ForContext(enrichers);
+ _logger.Write(level, messageTemplate);
+ return;
+ }
- lock (_sync)
- return new CachingReloadableLogger(this, _logger, this, p => p.ForContext(enrichers));
+ lock (_sync)
+ {
+ _logger.Write(level, messageTemplate);
}
+ }
- ///
- public ILogger ForContext(string propertyName, object value, bool destructureObjects = false)
+ ///
+ public override void Write(LogEventLevel level, string messageTemplate, T propertyValue)
+ {
+ if (_frozen)
{
- if (propertyName == null) return this;
-
- if (_frozen)
- return _logger.ForContext(propertyName, value, destructureObjects);
+ _logger.Write(level, messageTemplate, propertyValue);
+ return;
+ }
- lock (_sync)
- return new CachingReloadableLogger(this, _logger, this, p => p.ForContext(propertyName, value, destructureObjects));
+ lock (_sync)
+ {
+ _logger.Write(level, messageTemplate, propertyValue);
}
+ }
- ///
- public ILogger ForContext()
+ ///
+ public override void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ if (_frozen)
{
- if (_frozen)
- return _logger.ForContext();
+ _logger.Write(level, messageTemplate, propertyValue0, propertyValue1);
+ return;
+ }
- lock (_sync)
- return new CachingReloadableLogger(this, _logger, this, p => p.ForContext());
+ lock (_sync)
+ {
+ _logger.Write(level, messageTemplate, propertyValue0, propertyValue1);
}
+ }
- ///
- public ILogger ForContext(Type source)
+ ///
+ public override void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ if (_frozen)
{
- if (source == null) return this;
-
- if (_frozen)
- return _logger.ForContext(source);
+ _logger.Write(level, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
+ return;
+ }
- lock (_sync)
- return new CachingReloadableLogger(this, _logger, this, p => p.ForContext(source));
+ lock (_sync)
+ {
+ _logger.Write(level, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
}
+ }
- ///
- public void Write(LogEvent logEvent)
+ ///
+ public override void Write(LogEventLevel level, string messageTemplate, params object?[]? propertyValues)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- _logger.Write(logEvent);
- return;
- }
+ _logger.Write(level, messageTemplate, propertyValues);
+ return;
+ }
- lock (_sync)
- {
- _logger.Write(logEvent);
- }
+ lock (_sync)
+ {
+ _logger.Write(level, messageTemplate, propertyValues);
}
+ }
- ///
- public void Write(LogEventLevel level, string messageTemplate)
+ ///
+ public override void Write(LogEventLevel level, Exception? exception, string messageTemplate)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- _logger.Write(level, messageTemplate);
- return;
- }
+ _logger.Write(level, exception, messageTemplate);
+ return;
+ }
- lock (_sync)
- {
- _logger.Write(level, messageTemplate);
- }
+ lock (_sync)
+ {
+ _logger.Write(level, exception, messageTemplate);
}
+ }
- ///
- public void Write(LogEventLevel level, string messageTemplate, T propertyValue)
+ ///
+ public override void Write(LogEventLevel level, Exception? exception, string messageTemplate, T propertyValue)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- _logger.Write(level, messageTemplate, propertyValue);
- return;
- }
+ _logger.Write(level, exception, messageTemplate, propertyValue);
+ return;
+ }
- lock (_sync)
- {
- _logger.Write(level, messageTemplate, propertyValue);
- }
+ lock (_sync)
+ {
+ _logger.Write(level, exception, messageTemplate, propertyValue);
}
+ }
- ///
- public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ ///
+ public override void Write(LogEventLevel level, Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- _logger.Write(level, messageTemplate, propertyValue0, propertyValue1);
- return;
- }
+ _logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1);
+ return;
+ }
- lock (_sync)
- {
- _logger.Write(level, messageTemplate, propertyValue0, propertyValue1);
- }
+ lock (_sync)
+ {
+ _logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1);
}
+ }
- ///
- public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
+ ///
+ public override void Write(LogEventLevel level, Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- _logger.Write(level, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
- return;
- }
+ _logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
+ return;
+ }
- lock (_sync)
- {
- _logger.Write(level, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
- }
+ lock (_sync)
+ {
+ _logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
}
+ }
- ///
- public void Write(LogEventLevel level, string messageTemplate, params object[] propertyValues)
+ ///
+ public override void Write(LogEventLevel level, Exception? exception, string messageTemplate, params object?[]? propertyValues)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- _logger.Write(level, messageTemplate, propertyValues);
- return;
- }
+ _logger.Write(level, exception, messageTemplate, propertyValues);
+ return;
+ }
- lock (_sync)
- {
- _logger.Write(level, messageTemplate, propertyValues);
- }
+ lock (_sync)
+ {
+ _logger.Write(level, exception, messageTemplate, propertyValues);
}
+ }
- ///
- public void Write(LogEventLevel level, Exception exception, string messageTemplate)
+ ///
+ public bool IsEnabled(LogEventLevel level)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- _logger.Write(level, exception, messageTemplate);
- return;
- }
+ return _logger.IsEnabled(level);
+ }
- lock (_sync)
- {
- _logger.Write(level, exception, messageTemplate);
- }
+ lock (_sync)
+ {
+ return _logger.IsEnabled(level);
}
+ }
- ///
- public void Write(LogEventLevel level, Exception exception, string messageTemplate, T propertyValue)
+ ///
+ public bool BindMessageTemplate(string messageTemplate, object?[]? propertyValues,
+ [NotNullWhen(true)]
+ out MessageTemplate? parsedTemplate,
+ [NotNullWhen(true)]
+ out IEnumerable? boundProperties)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- _logger.Write(level, exception, messageTemplate, propertyValue);
- return;
- }
+ return _logger.BindMessageTemplate(messageTemplate, propertyValues, out parsedTemplate, out boundProperties);
+ }
- lock (_sync)
- {
- _logger.Write(level, exception, messageTemplate, propertyValue);
- }
+ lock (_sync)
+ {
+ return _logger.BindMessageTemplate(messageTemplate, propertyValues, out parsedTemplate, out boundProperties);
}
+ }
- ///
- public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ ///
+ public bool BindProperty(string? propertyName, object? value, bool destructureObjects, [NotNullWhen(true)] out LogEventProperty? property)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- _logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1);
- return;
- }
+ return _logger.BindProperty(propertyName, value, destructureObjects, out property);
+ }
- lock (_sync)
- {
- _logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1);
- }
+ lock (_sync)
+ {
+ return _logger.BindProperty(propertyName, value, destructureObjects, out property);
}
+ }
- ///
- public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
+ // `newRoot` is null when the second returned tuple argument is `false`, but the signature of the method doesn't currently
+ // allow this to be expressed.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ (ILogger, bool) UpdateForCaller(ILogger root, ILogger? cached, IReloadableLogger caller, out ILogger newRoot, out ILogger? newCached, out bool frozen)
+ {
+ // Synchronization on `_sync` is not required in this method; it will be called without a lock
+ // if `_frozen` and under a lock if not.
+
+ if (_frozen)
{
- if (_frozen)
- {
- _logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
- return;
- }
+ // If we're frozen, then the caller hasn't observed this yet and should update. We could optimize a little here
+ // and only signal an update if the cached logger is stale (as per the next condition below).
+ newRoot = _logger;
+ newCached = caller.ReloadLogger();
+ frozen = true;
+ return (newCached, true);
+ }
- lock (_sync)
- {
- _logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
- }
+ if (cached != null! && root == _logger)
+ {
+ newRoot = default!;
+ newCached = default;
+ frozen = false;
+ return (cached, false);
+ }
+
+ newRoot = _logger;
+ newCached = caller.ReloadLogger();
+ frozen = false;
+ return (newCached, true);
+ }
+
+ internal bool InvokeIsEnabled(ILogger root, ILogger? cached, IReloadableLogger caller, LogEventLevel level, out bool isEnabled, out ILogger newRoot, out ILogger? newCached, out bool frozen)
+ {
+ if (_frozen)
+ {
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ isEnabled = logger.IsEnabled(level);
+ return update;
}
- ///
- public void Write(LogEventLevel level, Exception exception, string messageTemplate, params object[] propertyValues)
+ lock (_sync)
{
- if (_frozen)
- {
- _logger.Write(level, exception, messageTemplate, propertyValues);
- return;
- }
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ isEnabled = logger.IsEnabled(level);
+ return update;
+ }
+ }
+
+ internal bool InvokeBindMessageTemplate(ILogger root, ILogger? cached, IReloadableLogger caller, string messageTemplate,
+ object?[]? propertyValues, [NotNullWhen(true)] out MessageTemplate? parsedTemplate, [NotNullWhen(true)] out IEnumerable? boundProperties,
+ out bool canBind, out ILogger newRoot, out ILogger? newCached, out bool frozen)
+ {
+ if (_frozen)
+ {
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ canBind = logger.BindMessageTemplate(messageTemplate, propertyValues, out parsedTemplate, out boundProperties);
+ return update;
+ }
- lock (_sync)
- {
- _logger.Write(level, exception, messageTemplate, propertyValues);
- }
+ lock (_sync)
+ {
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ canBind = logger.BindMessageTemplate(messageTemplate, propertyValues, out parsedTemplate, out boundProperties);
+ return update;
+ }
+ }
+
+ internal bool InvokeBindProperty(ILogger root, ILogger? cached, IReloadableLogger caller, string? propertyName,
+ object? propertyValue, bool destructureObjects, [NotNullWhen(true)] out LogEventProperty? property,
+ out bool canBind, out ILogger newRoot, out ILogger? newCached, out bool frozen)
+ {
+ if (_frozen)
+ {
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ canBind = logger.BindProperty(propertyName, propertyValue, destructureObjects, out property);
+ return update;
}
- ///
- public bool IsEnabled(LogEventLevel level)
+ lock (_sync)
{
- if (_frozen)
- {
- return _logger.IsEnabled(level);
- }
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ canBind = logger.BindProperty(propertyName, propertyValue, destructureObjects, out property);
+ return update;
+ }
+ }
- lock (_sync)
- {
- return _logger.IsEnabled(level);
- }
+ internal bool InvokeWrite(ILogger root, ILogger? cached, IReloadableLogger caller, LogEvent logEvent, out ILogger newRoot, out ILogger? newCached, out bool frozen)
+ {
+ if (_frozen)
+ {
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ logger.Write(logEvent);
+ return update;
}
-
- ///
- public bool BindMessageTemplate(string messageTemplate, object[] propertyValues, out MessageTemplate parsedTemplate,
- out IEnumerable boundProperties)
+
+ lock (_sync)
{
- if (_frozen)
- {
- return _logger.BindMessageTemplate(messageTemplate, propertyValues, out parsedTemplate, out boundProperties);
- }
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ logger.Write(logEvent);
+ return update;
+ }
+ }
- lock (_sync)
- {
- return _logger.BindMessageTemplate(messageTemplate, propertyValues, out parsedTemplate, out boundProperties);
- }
+ internal bool InvokeWrite(ILogger root, ILogger? cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate,
+ out ILogger newRoot, out ILogger? newCached, out bool frozen)
+ {
+ if (_frozen)
+ {
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ logger.Write(level, messageTemplate);
+ return update;
}
- ///
- public bool BindProperty(string propertyName, object value, bool destructureObjects, out LogEventProperty property)
+ lock (_sync)
{
- if (_frozen)
- {
- return _logger.BindProperty(propertyName, value, destructureObjects, out property);
- }
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ logger.Write(level, messageTemplate);
+ return update;
+ }
+ }
- lock (_sync)
- {
- return _logger.BindProperty(propertyName, value, destructureObjects, out property);
- }
+ internal bool InvokeWrite(ILogger root, ILogger? cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate,
+ T propertyValue,
+ out ILogger newRoot, out ILogger? newCached, out bool frozen)
+ {
+ if (_frozen)
+ {
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ logger.Write(level, messageTemplate, propertyValue);
+ return update;
}
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- (ILogger, bool) UpdateForCaller(ILogger root, ILogger cached, IReloadableLogger caller, out ILogger newRoot, out ILogger newCached, out bool frozen)
+ lock (_sync)
{
- // Synchronization on `_sync` is not required in this method; it will be called without a lock
- // if `_frozen` and under a lock if not.
-
- if (_frozen)
- {
- // If we're frozen, then the caller hasn't observed this yet and should update. We could optimize a little here
- // and only signal an update if the cached logger is stale (as per the next condition below).
- newRoot = _logger;
- newCached = caller.ReloadLogger();
- frozen = true;
- return (newCached, true);
- }
-
- if (cached != null && root == _logger)
- {
- newRoot = default;
- newCached = default;
- frozen = false;
- return (cached, false);
- }
-
- newRoot = _logger;
- newCached = caller.ReloadLogger();
- frozen = false;
- return (newCached, true);
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ logger.Write(level, messageTemplate, propertyValue);
+ return update;
}
-
- internal bool InvokeIsEnabled(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, out bool isEnabled, out ILogger newRoot, out ILogger newCached, out bool frozen)
+ }
+
+ internal bool InvokeWrite(ILogger root, ILogger? cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate,
+ T0 propertyValue0, T1 propertyValue1,
+ out ILogger newRoot, out ILogger? newCached, out bool frozen)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- isEnabled = logger.IsEnabled(level);
- return update;
- }
-
- lock (_sync)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- isEnabled = logger.IsEnabled(level);
- return update;
- }
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ logger.Write(level, messageTemplate, propertyValue0, propertyValue1);
+ return update;
}
-
- internal bool InvokeBindMessageTemplate(ILogger root, ILogger cached, IReloadableLogger caller, string messageTemplate,
- object[] propertyValues, out MessageTemplate parsedTemplate, out IEnumerable boundProperties,
- out bool canBind, out ILogger newRoot, out ILogger newCached, out bool frozen)
+
+ lock (_sync)
{
- if (_frozen)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- canBind = logger.BindMessageTemplate(messageTemplate, propertyValues, out parsedTemplate, out boundProperties);
- return update;
- }
-
- lock (_sync)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- canBind = logger.BindMessageTemplate(messageTemplate, propertyValues, out parsedTemplate, out boundProperties);
- return update;
- }
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ logger.Write(level, messageTemplate, propertyValue0, propertyValue1);
+ return update;
}
-
- internal bool InvokeBindProperty(ILogger root, ILogger cached, IReloadableLogger caller, string propertyName,
- object propertyValue, bool destructureObjects, out LogEventProperty property,
- out bool canBind, out ILogger newRoot, out ILogger newCached, out bool frozen)
+ }
+
+ internal bool InvokeWrite(ILogger root, ILogger? cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate,
+ T0 propertyValue0, T1 propertyValue1, T2 propertyValue2,
+ out ILogger newRoot, out ILogger? newCached, out bool frozen)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- canBind = logger.BindProperty(propertyName, propertyValue, destructureObjects, out property);
- return update;
- }
-
- lock (_sync)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- canBind = logger.BindProperty(propertyName, propertyValue, destructureObjects, out property);
- return update;
- }
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ logger.Write(level, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
+ return update;
}
- internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEvent logEvent, out ILogger newRoot, out ILogger newCached, out bool frozen)
+ lock (_sync)
{
- if (_frozen)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- logger.Write(logEvent);
- return update;
- }
-
- lock (_sync)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- logger.Write(logEvent);
- return update;
- }
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ logger.Write(level, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
+ return update;
}
+ }
- internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate,
- out ILogger newRoot, out ILogger newCached, out bool frozen)
+ internal bool InvokeWrite(ILogger root, ILogger? cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate,
+ object?[]? propertyValues,
+ out ILogger newRoot, out ILogger? newCached, out bool frozen)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- logger.Write(level, messageTemplate);
- return update;
- }
-
- lock (_sync)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- logger.Write(level, messageTemplate);
- return update;
- }
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ logger.Write(level, messageTemplate, propertyValues);
+ return update;
}
- internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate,
- T propertyValue,
- out ILogger newRoot, out ILogger newCached, out bool frozen)
+ lock (_sync)
{
- if (_frozen)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- logger.Write(level, messageTemplate, propertyValue);
- return update;
- }
-
- lock (_sync)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- logger.Write(level, messageTemplate, propertyValue);
- return update;
- }
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ logger.Write(level, messageTemplate, propertyValues);
+ return update;
}
-
- internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate,
- T0 propertyValue0, T1 propertyValue1,
- out ILogger newRoot, out ILogger newCached, out bool frozen)
+ }
+
+ internal bool InvokeWrite(ILogger root, ILogger? cached, IReloadableLogger caller, LogEventLevel level, Exception? exception, string messageTemplate,
+ out ILogger newRoot, out ILogger? newCached, out bool frozen)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- logger.Write(level, messageTemplate, propertyValue0, propertyValue1);
- return update;
- }
-
- lock (_sync)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- logger.Write(level, messageTemplate, propertyValue0, propertyValue1);
- return update;
- }
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ logger.Write(level, exception, messageTemplate);
+ return update;
}
-
- internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate,
- T0 propertyValue0, T1 propertyValue1, T2 propertyValue2,
- out ILogger newRoot, out ILogger newCached, out bool frozen)
+
+ lock (_sync)
{
- if (_frozen)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- logger.Write(level, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
- return update;
- }
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ logger.Write(level, exception, messageTemplate);
+ return update;
+ }
+ }
- lock (_sync)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- logger.Write(level, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
- return update;
- }
+ internal bool InvokeWrite(ILogger root, ILogger? cached, IReloadableLogger caller, LogEventLevel level, Exception? exception, string messageTemplate,
+ T propertyValue,
+ out ILogger newRoot, out ILogger? newCached, out bool frozen)
+ {
+ if (_frozen)
+ {
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ logger.Write(level, exception, messageTemplate, propertyValue);
+ return update;
}
- internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate,
- object[] propertyValues,
- out ILogger newRoot, out ILogger newCached, out bool frozen)
+ lock (_sync)
{
- if (_frozen)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- logger.Write(level, messageTemplate, propertyValues);
- return update;
- }
-
- lock (_sync)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- logger.Write(level, messageTemplate, propertyValues);
- return update;
- }
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ logger.Write(level, exception, messageTemplate, propertyValue);
+ return update;
}
-
- internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, Exception exception, string messageTemplate,
- out ILogger newRoot, out ILogger newCached, out bool frozen)
+ }
+
+ internal bool InvokeWrite(ILogger root, ILogger? cached, IReloadableLogger caller, LogEventLevel level, Exception? exception, string messageTemplate,
+ T0 propertyValue0, T1 propertyValue1,
+ out ILogger newRoot, out ILogger? newCached, out bool frozen)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- logger.Write(level, exception, messageTemplate);
- return update;
- }
-
- lock (_sync)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- logger.Write(level, exception, messageTemplate);
- return update;
- }
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1);
+ return update;
}
- internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, Exception exception, string messageTemplate,
- T propertyValue,
- out ILogger newRoot, out ILogger newCached, out bool frozen)
+ lock (_sync)
{
- if (_frozen)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- logger.Write(level, exception, messageTemplate, propertyValue);
- return update;
- }
-
- lock (_sync)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- logger.Write(level, exception, messageTemplate, propertyValue);
- return update;
- }
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1);
+ return update;
}
-
- internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, Exception exception, string messageTemplate,
- T0 propertyValue0, T1 propertyValue1,
- out ILogger newRoot, out ILogger newCached, out bool frozen)
+ }
+
+ internal bool InvokeWrite(ILogger root, ILogger? cached, IReloadableLogger caller, LogEventLevel level, Exception? exception, string messageTemplate,
+ T0 propertyValue0, T1 propertyValue1, T2 propertyValue2,
+ out ILogger newRoot, out ILogger? newCached, out bool frozen)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1);
- return update;
- }
-
- lock (_sync)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1);
- return update;
- }
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
+ return update;
}
-
- internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, Exception exception, string messageTemplate,
- T0 propertyValue0, T1 propertyValue1, T2 propertyValue2,
- out ILogger newRoot, out ILogger newCached, out bool frozen)
+
+ lock (_sync)
{
- if (_frozen)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
- return update;
- }
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
+ return update;
+ }
+ }
- lock (_sync)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2);
- return update;
- }
+ internal bool InvokeWrite(ILogger root, ILogger? cached, IReloadableLogger caller, LogEventLevel level, Exception? exception, string messageTemplate,
+ object?[]? propertyValues,
+ out ILogger newRoot, out ILogger? newCached, out bool frozen)
+ {
+ if (_frozen)
+ {
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ logger.Write(level, exception, messageTemplate, propertyValues);
+ return update;
}
- internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, Exception exception, string messageTemplate,
- object[] propertyValues,
- out ILogger newRoot, out ILogger newCached, out bool frozen)
+ lock (_sync)
{
- if (_frozen)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- logger.Write(level, exception, messageTemplate, propertyValues);
- return update;
- }
-
- lock (_sync)
- {
- var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
- logger.Write(level, exception, messageTemplate, propertyValues);
- return update;
- }
- }
-
- internal bool CreateChild(
- ILogger root,
- IReloadableLogger parent,
- ILogger cachedParent,
- Func configureChild,
- out ILogger child,
- out ILogger newRoot,
- out ILogger newCached,
- out bool frozen)
+ var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen);
+ logger.Write(level, exception, messageTemplate, propertyValues);
+ return update;
+ }
+ }
+
+ internal bool CreateChild(
+ ILogger root,
+ IReloadableLogger parent,
+ ILogger? cachedParent,
+ Func configureChild,
+ out ILogger child,
+ out ILogger newRoot,
+ out ILogger? newCached,
+ out bool frozen)
+ {
+ if (_frozen)
{
- if (_frozen)
- {
- var (logger, _) = UpdateForCaller(root, cachedParent, parent, out newRoot, out newCached, out frozen);
- child = configureChild(logger);
- return true; // Always an update, since the caller has not observed that the reloadable logger is frozen.
- }
-
- // No synchronization, here - a lot of loggers are created and thrown away again without ever being used,
- // so we just return a lazy wrapper.
- child = new CachingReloadableLogger(this, root, parent, configureChild);
- newRoot = default;
- newCached = default;
- frozen = default;
- return false;
+ var (logger, _) = UpdateForCaller(root, cachedParent, parent, out newRoot, out newCached, out frozen);
+ child = configureChild(logger);
+ return true; // Always an update, since the caller has not observed that the reloadable logger is frozen.
}
+
+ // No synchronization, here - a lot of loggers are created and thrown away again without ever being used,
+ // so we just return a lazy wrapper.
+ child = new CachingReloadableLogger(this, root, parent, configureChild);
+ newRoot = default!;
+ newCached = default;
+ frozen = default;
+ return false;
}
}
-
-#endif
diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/SerilogLoggerFactory.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/SerilogLoggerFactory.cs
deleted file mode 100644
index 1b100b9..0000000
--- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/SerilogLoggerFactory.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2018 Serilog Contributors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-using System;
-using System.ComponentModel;
-using Microsoft.Extensions.Logging;
-using Serilog.Debugging;
-using Serilog.Extensions.Logging;
-
-// To line up with the convention used elsewhere in the *.Extensions libraries, this
-// should have been Serilog.Extensions.Hosting.
-// ReSharper disable once CheckNamespace
-namespace Serilog.Hosting
-{
- ///
- /// Implements so that we can inject Serilog Logger.
- ///
- [Obsolete("Replaced with Serilog.Extensions.Logging.SerilogLoggerFactory")]
- [EditorBrowsable(EditorBrowsableState.Never)]
- public class SerilogLoggerFactory : ILoggerFactory
- {
- 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.
- public SerilogLoggerFactory(ILogger logger = null, bool dispose = false)
- {
- _provider = new SerilogLoggerProvider(logger, 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);
- }
-
- ///
- /// Adds an to the logging system.
- ///
- /// The .
- public void AddProvider(ILoggerProvider provider)
- {
- SelfLog.WriteLine("Ignoring add logger provider {0}", provider);
- }
- }
-}
diff --git a/src/Serilog.Extensions.Hosting/IDiagnosticContext.cs b/src/Serilog.Extensions.Hosting/IDiagnosticContext.cs
index 79da237..c867cf7 100644
--- a/src/Serilog.Extensions.Hosting/IDiagnosticContext.cs
+++ b/src/Serilog.Extensions.Hosting/IDiagnosticContext.cs
@@ -14,32 +14,31 @@
using System;
-namespace Serilog
+namespace Serilog;
+
+///
+/// Collects diagnostic information for packaging into wide events.
+///
+public interface IDiagnosticContext
{
///
- /// Collects diagnostic information for packaging into wide events.
+ /// Set the specified property on the current diagnostic context. The property will be collected
+ /// and attached to the event emitted at the completion of the context.
///
- public interface IDiagnosticContext
- {
- ///
- /// Set the specified property on the current diagnostic context. The property will be collected
- /// and attached to the event emitted at the completion of the context.
- ///
- /// The name of the property. Must be non-empty.
- /// The property value.
- /// If true, the value will be serialized as structured
- /// data if possible; if false, the object will be recorded as a scalar or simple array.
- void Set(string propertyName, object value, bool destructureObjects = false);
+ /// The name of the property. Must be non-empty.
+ /// The property value.
+ /// If true, the value will be serialized as structured
+ /// data if possible; if false, the object will be recorded as a scalar or simple array.
+ void Set(string propertyName, object value, bool destructureObjects = false);
- ///
- /// Set the specified exception on the current diagnostic context.
- ///
- ///
- /// This method is useful when unhandled exceptions do not reach Serilog.AspNetCore.RequestLoggingMiddleware,
- /// such as when using Hellang.Middleware.ProblemDetails
- /// to transform exceptions to ProblemDetails responses.
- ///
- /// The exception to log. If null is given, it clears any previously assigned exception.
- void SetException(Exception exception);
- }
+ ///
+ /// Set the specified exception on the current diagnostic context.
+ ///
+ ///
+ /// This method is useful when unhandled exceptions do not reach Serilog.AspNetCore.RequestLoggingMiddleware,
+ /// such as when using Hellang.Middleware.ProblemDetails
+ /// to transform exceptions to ProblemDetails responses.
+ ///
+ /// The exception to log. If null is given, it clears any previously assigned exception.
+ void SetException(Exception exception);
}
diff --git a/src/Serilog.Extensions.Hosting/LoggerConfigurationExtensions.cs b/src/Serilog.Extensions.Hosting/LoggerConfigurationExtensions.cs
index 51a02d1..8511c34 100644
--- a/src/Serilog.Extensions.Hosting/LoggerConfigurationExtensions.cs
+++ b/src/Serilog.Extensions.Hosting/LoggerConfigurationExtensions.cs
@@ -18,26 +18,25 @@
using Serilog.Extensions.Hosting;
using System;
-namespace Serilog
+namespace Serilog;
+
+///
+/// Extends .
+///
+public static class LoggerConfigurationExtensions
{
///
- /// Extends .
+ /// Create a for use during host bootstrapping. The
+ ///
+ /// configuration overload will detect when is set to a instance, and
+ /// reconfigure/freeze it so that s created during host bootstrapping continue to work once
+ /// logger configuration (with access to host services) is completed.
///
- public static class LoggerConfigurationExtensions
+ ///
+ ///
+ public static ReloadableLogger CreateBootstrapLogger(this LoggerConfiguration loggerConfiguration)
{
- ///
- /// Create a for use during host bootstrapping. The
- ///
- /// configuration overload will detect when is set to a instance, and
- /// reconfigure/freeze it so that s created during host bootstrapping continue to work once
- /// logger configuration (with access to host services) is completed.
- ///
- ///
- ///
- public static ReloadableLogger CreateBootstrapLogger(this LoggerConfiguration loggerConfiguration)
- {
- return new ReloadableLogger(loggerConfiguration.CreateLogger());
- }
+ return new ReloadableLogger(loggerConfiguration.CreateLogger());
}
}
diff --git a/src/Serilog.Extensions.Hosting/LoggerSettingsConfigurationExtensions.cs b/src/Serilog.Extensions.Hosting/LoggerSettingsConfigurationExtensions.cs
index 4e9c62c..46abd8d 100644
--- a/src/Serilog.Extensions.Hosting/LoggerSettingsConfigurationExtensions.cs
+++ b/src/Serilog.Extensions.Hosting/LoggerSettingsConfigurationExtensions.cs
@@ -17,27 +17,26 @@
using Serilog.Core;
using Serilog.Extensions.Hosting;
-namespace Serilog
+namespace Serilog;
+
+///
+/// Extends with methods for consuming host services.
+///
+public static class LoggerSettingsConfigurationExtensions
{
///
- /// Extends with methods for consuming host services.
+ /// Configure the logger using components from the . If present, the logger will
+ /// receive implementations/instances of , ,
+ /// , , , and
+ /// .
///
- public static class LoggerSettingsConfigurationExtensions
+ /// The `ReadFrom` configuration object.
+ /// A from which services will be requested.
+ /// A to support method chaining.
+ public static LoggerConfiguration Services(
+ this LoggerSettingsConfiguration loggerSettingsConfiguration,
+ IServiceProvider services)
{
- ///
- /// Configure the logger using components from the . If present, the logger will
- /// receive implementations/instances of , ,
- /// , , , and
- /// .
- ///
- /// The `ReadFrom` configuration object.
- /// A from which services will be requested.
- /// A to support method chaining.
- public static LoggerConfiguration Services(
- this LoggerSettingsConfiguration loggerSettingsConfiguration,
- IServiceProvider services)
- {
- return loggerSettingsConfiguration.Settings(new InjectedLoggerSettings(services));
- }
+ return loggerSettingsConfiguration.Settings(new InjectedLoggerSettings(services));
}
}
\ No newline at end of file
diff --git a/src/Serilog.Extensions.Hosting/Properties/AssemblyInfo.cs b/src/Serilog.Extensions.Hosting/Properties/AssemblyInfo.cs
index 8ec980f..22cba5d 100644
--- a/src/Serilog.Extensions.Hosting/Properties/AssemblyInfo.cs
+++ b/src/Serilog.Extensions.Hosting/Properties/AssemblyInfo.cs
@@ -1,7 +1,4 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-
-[assembly: AssemblyVersion("7.0.0.0")]
+using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Serilog.Extensions.Hosting.Tests, PublicKey=" +
"0024000004800000940000000602000000240000525341310004000001000100fb8d13fd344a1c" +
diff --git a/src/Serilog.Extensions.Hosting/Serilog.Extensions.Hosting.csproj b/src/Serilog.Extensions.Hosting/Serilog.Extensions.Hosting.csproj
index edeb7db..12ff5b6 100644
--- a/src/Serilog.Extensions.Hosting/Serilog.Extensions.Hosting.csproj
+++ b/src/Serilog.Extensions.Hosting/Serilog.Extensions.Hosting.csproj
@@ -2,45 +2,42 @@
Serilog support for .NET Core logging in hosted services
-
- 8.0.0
Microsoft;Serilog Contributors
- net462;netstandard2.0;net6.0;net7.0;net8.0
- 8
- true
- true
- ../../assets/Serilog.snk
- true
- true
+ net462;netstandard2.0;netstandard2.1;net8.0;net9.0
serilog;aspnet;aspnetcore;hosting
icon.png
https://github.com/serilog/serilog-extensions-hosting
Apache-2.0
- https://github.com/serilog/serilog-extensions-hosting
- git
- false
Serilog
README.md
-
- $(DefineConstants);NO_RELOADABLE_LOGGER
+
+ $(DefineConstants);FEATURE_MBPW
+
+
+
+ $(DefineConstants);FEATURE_MBPW
+
+
+
+ $(DefineConstants);FEATURE_MBPW
-
-
+
+
-
-
-
-
+
+
+
+
diff --git a/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs b/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs
index 7f0ab0d..b30c340 100644
--- a/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs
+++ b/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs
@@ -18,104 +18,103 @@
using Serilog.Extensions.Logging;
// ReSharper disable MemberCanBePrivate.Global
-namespace Serilog
+namespace Serilog;
+
+///
+/// Extends with Serilog configuration methods.
+///
+public static class SerilogHostBuilderExtensions
{
///
- /// Extends with Serilog configuration methods.
+ /// Sets Serilog as the logging provider.
///
- public static class SerilogHostBuilderExtensions
+ /// The host builder 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.
+ /// A registered in the Serilog pipeline using the
+ /// WriteTo.Providers() configuration method, enabling other s to receive events. By
+ /// default, only Serilog sinks will receive events.
+ /// The host builder.
+ public static IHostBuilder UseSerilog(
+ this IHostBuilder builder,
+ ILogger? logger = null,
+ bool dispose = false,
+ LoggerProviderCollection? providers = null)
{
- ///
- /// Sets Serilog as the logging provider.
- ///
- /// The host builder 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.
- /// A registered in the Serilog pipeline using the
- /// WriteTo.Providers() configuration method, enabling other s to receive events. By
- /// default, only Serilog sinks will receive events.
- /// The host builder.
- public static IHostBuilder UseSerilog(
- this IHostBuilder builder,
- ILogger logger = null,
- bool dispose = false,
- LoggerProviderCollection providers = null)
+ if (builder == null) throw new ArgumentNullException(nameof(builder));
+
+ builder.ConfigureServices((_, collection) =>
{
- if (builder == null) throw new ArgumentNullException(nameof(builder));
+ collection.AddSerilog(logger, dispose, providers);
+ });
+
+ return builder;
+ }
- builder.ConfigureServices((_, collection) =>
- {
- collection.AddSerilog(logger, dispose, providers);
- });
+ /// Sets Serilog as the logging provider.
+ ///
+ /// A is supplied so that configuration and hosting information can be used.
+ /// The logger will be shut down when application services are disposed.
+ ///
+ /// The host builder to configure.
+ /// The delegate for configuring the that will be used to construct a .
+ /// Indicates whether to preserve the value of .
+ /// By default, Serilog does not write events to s registered through
+ /// the Microsoft.Extensions.Logging API. Normally, equivalent Serilog sinks are used in place of providers. Specify
+ /// true to write events to all providers.
+ /// The host builder.
+ public static IHostBuilder UseSerilog(
+ this IHostBuilder builder,
+ Action configureLogger,
+ bool preserveStaticLogger = false,
+ bool writeToProviders = false)
+ {
+ if (builder == null) throw new ArgumentNullException(nameof(builder));
+ if (configureLogger == null) throw new ArgumentNullException(nameof(configureLogger));
+ return UseSerilog(
+ builder,
+ (hostBuilderContext, services, loggerConfiguration) =>
+ configureLogger(hostBuilderContext, loggerConfiguration),
+ preserveStaticLogger: preserveStaticLogger,
+ writeToProviders: writeToProviders);
+ }
- return builder;
- }
+ /// Sets Serilog as the logging provider.
+ ///
+ /// A is supplied so that configuration and hosting information can be used.
+ /// The logger will be shut down when application services are disposed.
+ ///
+ /// The host builder to configure.
+ /// The delegate for configuring the that will be used to construct a .
+ /// Indicates whether to preserve the value of .
+ /// By default, Serilog does not write events to s registered through
+ /// the Microsoft.Extensions.Logging API. Normally, equivalent Serilog sinks are used in place of providers. Specify
+ /// true to write events to all providers.
+ /// If the static is a bootstrap logger (see
+ /// LoggerConfigurationExtensions.CreateBootstrapLogger()), and is
+ /// not specified, the the bootstrap logger will be reconfigured through the supplied delegate, rather than being
+ /// replaced entirely or ignored.
+ /// The host builder.
+ public static IHostBuilder UseSerilog(
+ this IHostBuilder builder,
+ Action configureLogger,
+ bool preserveStaticLogger = false,
+ bool writeToProviders = false)
+ {
+ if (builder == null) throw new ArgumentNullException(nameof(builder));
+ if (configureLogger == null) throw new ArgumentNullException(nameof(configureLogger));
- /// Sets Serilog as the logging provider.
- ///
- /// A is supplied so that configuration and hosting information can be used.
- /// The logger will be shut down when application services are disposed.
- ///
- /// The host builder to configure.
- /// The delegate for configuring the that will be used to construct a .
- /// Indicates whether to preserve the value of .
- /// By default, Serilog does not write events to s registered through
- /// the Microsoft.Extensions.Logging API. Normally, equivalent Serilog sinks are used in place of providers. Specify
- /// true to write events to all providers.
- /// The host builder.
- public static IHostBuilder UseSerilog(
- this IHostBuilder builder,
- Action configureLogger,
- bool preserveStaticLogger = false,
- bool writeToProviders = false)
+ builder.ConfigureServices((context, collection) =>
{
- if (builder == null) throw new ArgumentNullException(nameof(builder));
- if (configureLogger == null) throw new ArgumentNullException(nameof(configureLogger));
- return UseSerilog(
- builder,
- (hostBuilderContext, services, loggerConfiguration) =>
- configureLogger(hostBuilderContext, loggerConfiguration),
+ collection.AddSerilog(
+ (services, loggerConfiguration) =>
+ configureLogger(context, services, loggerConfiguration),
preserveStaticLogger: preserveStaticLogger,
writeToProviders: writeToProviders);
- }
+ });
- /// Sets Serilog as the logging provider.
- ///
- /// A is supplied so that configuration and hosting information can be used.
- /// The logger will be shut down when application services are disposed.
- ///
- /// The host builder to configure.
- /// The delegate for configuring the that will be used to construct a .
- /// Indicates whether to preserve the value of .
- /// By default, Serilog does not write events to s registered through
- /// the Microsoft.Extensions.Logging API. Normally, equivalent Serilog sinks are used in place of providers. Specify
- /// true to write events to all providers.
- /// If the static is a bootstrap logger (see
- /// LoggerConfigurationExtensions.CreateBootstrapLogger()), and is
- /// not specified, the the bootstrap logger will be reconfigured through the supplied delegate, rather than being
- /// replaced entirely or ignored.
- /// The host builder.
- public static IHostBuilder UseSerilog(
- this IHostBuilder builder,
- Action configureLogger,
- bool preserveStaticLogger = false,
- bool writeToProviders = false)
- {
- if (builder == null) throw new ArgumentNullException(nameof(builder));
- if (configureLogger == null) throw new ArgumentNullException(nameof(configureLogger));
-
- builder.ConfigureServices((context, collection) =>
- {
- collection.AddSerilog(
- (services, loggerConfiguration) =>
- configureLogger(context, services, loggerConfiguration),
- preserveStaticLogger: preserveStaticLogger,
- writeToProviders: writeToProviders);
- });
-
- return builder;
- }
+ return builder;
}
}
diff --git a/src/Serilog.Extensions.Hosting/SerilogServiceCollectionExtensions.cs b/src/Serilog.Extensions.Hosting/SerilogServiceCollectionExtensions.cs
index e6055c0..cdc7e35 100644
--- a/src/Serilog.Extensions.Hosting/SerilogServiceCollectionExtensions.cs
+++ b/src/Serilog.Extensions.Hosting/SerilogServiceCollectionExtensions.cs
@@ -12,230 +12,221 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System;
using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Serilog.Extensions.Hosting;
using Serilog.Extensions.Logging;
// ReSharper disable MemberCanBePrivate.Global
-namespace Serilog
+namespace Serilog;
+
+///
+/// Extends with Serilog configuration methods.
+///
+public static class SerilogServiceCollectionExtensions
{
+ // Used internally to pass information through the container. We need to do this because if `logger` is the
+ // root logger, registering it as a singleton may lead to disposal along with the container by MEDI. This isn't
+ // always desirable, i.e. we may be handed a logger and `dispose: false`, so wrapping it keeps us in control
+ // of when the logger is disposed.
+ class RegisteredLogger
+ {
+ public RegisteredLogger(ILogger logger)
+ {
+ Logger = logger;
+ }
+
+ public ILogger Logger { get; }
+ }
+
///
- /// Extends with Serilog configuration methods.
+ /// Sets Serilog as the logging provider.
///
- public static class SerilogServiceCollectionExtensions
+ /// The service collection to use.
+ /// 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 registered in the Serilog pipeline using the
+ /// WriteTo.Providers() configuration method, enabling other s to receive events. By
+ /// default, only Serilog sinks will receive events.
+ /// The service collection.
+ public static IServiceCollection AddSerilog(
+ this IServiceCollection collection,
+ ILogger? logger = null,
+ bool dispose = false,
+ LoggerProviderCollection? providers = null)
{
- // Used internally to pass information through the container. We need to do this because if `logger` is the
- // root logger, registering it as a singleton may lead to disposal along with the container by MEDI. This isn't
- // always desirable, i.e. we may be handed a logger and `dispose: false`, so wrapping it keeps us in control
- // of when the logger is disposed.
- class RegisteredLogger
+ if (collection == null) throw new ArgumentNullException(nameof(collection));
+
+ if (providers != null)
{
- public RegisteredLogger(ILogger logger)
+ collection.AddSingleton(services =>
{
- Logger = logger;
- }
-
- public ILogger Logger { get; }
+ var factory = new SerilogLoggerFactory(logger, dispose, providers);
+
+ foreach (var provider in services.GetServices())
+ factory.AddProvider(provider);
+
+ return factory;
+ });
+ }
+ else
+ {
+ collection.AddSingleton(_ => new SerilogLoggerFactory(logger, dispose));
}
- ///
- /// Sets Serilog as the logging provider.
- ///
- /// The service collection to use.
- /// 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 registered in the Serilog pipeline using the
- /// WriteTo.Providers() configuration method, enabling other s to receive events. By
- /// default, only Serilog sinks will receive events.
- /// The service collection.
- public static IServiceCollection AddSerilog(
- this IServiceCollection collection,
- ILogger logger = null,
- bool dispose = false,
- LoggerProviderCollection providers = null)
+ if (logger != null)
{
- if (collection == null) throw new ArgumentNullException(nameof(collection));
+ // This won't (and shouldn't) take ownership of the logger.
+ collection.AddSingleton(logger);
- if (providers != null)
- {
- collection.AddSingleton(services =>
- {
- var factory = new SerilogLoggerFactory(logger, dispose, providers);
+ // Still need to use RegisteredLogger as it is used by ConfigureDiagnosticContext.
+ collection.AddSingleton(new RegisteredLogger(logger));
+ }
+ bool useRegisteredLogger = logger != null;
+ ConfigureDiagnosticContext(collection, useRegisteredLogger);
+
+ return collection;
+ }
+
+ /// Sets Serilog as the logging provider.
+ /// The service collection to use.
+ /// The delegate for configuring the that will be used to construct a .
+ /// Indicates whether to preserve the value of .
+ /// By default, Serilog does not write events to s registered through
+ /// the Microsoft.Extensions.Logging API. Normally, equivalent Serilog sinks are used in place of providers. Specify
+ /// true to write events to all providers.
+ /// The service collection.
+ public static IServiceCollection AddSerilog(
+ this IServiceCollection collection,
+ Action configureLogger,
+ bool preserveStaticLogger = false,
+ bool writeToProviders = false)
+ {
+ if (collection == null) throw new ArgumentNullException(nameof(collection));
+ if (configureLogger == null) throw new ArgumentNullException(nameof(configureLogger));
+ return AddSerilog(
+ collection,
+ (_, loggerConfiguration) =>
+ configureLogger(loggerConfiguration),
+ preserveStaticLogger: preserveStaticLogger,
+ writeToProviders: writeToProviders);
+ }
+
+ /// Sets Serilog as the logging provider.
+ /// The service collection to use.
+ /// The delegate for configuring the that will be used to construct a .
+ /// Indicates whether to preserve the value of .
+ /// By default, Serilog does not write events to s registered through
+ /// the Microsoft.Extensions.Logging API. Normally, equivalent Serilog sinks are used in place of providers. Specify
+ /// true to write events to all providers.
+ /// If the static is a bootstrap logger (see
+ /// LoggerConfigurationExtensions.CreateBootstrapLogger()), and is
+ /// not specified, the the bootstrap logger will be reconfigured through the supplied delegate, rather than being
+ /// replaced entirely or ignored.
+ /// The service collection.
+ public static IServiceCollection AddSerilog(
+ this IServiceCollection collection,
+ Action configureLogger,
+ bool preserveStaticLogger = false,
+ bool writeToProviders = false)
+ {
+ if (collection == null) throw new ArgumentNullException(nameof(collection));
+ if (configureLogger == null) throw new ArgumentNullException(nameof(configureLogger));
- foreach (var provider in services.GetServices())
- factory.AddProvider(provider);
+ // This check is eager; replacing the bootstrap logger after calling this method is not supported.
+ var reloadable = Log.Logger as ReloadableLogger;
+ var useReload = reloadable != null && !preserveStaticLogger;
- return factory;
+ LoggerProviderCollection? loggerProviders = null;
+ if (writeToProviders)
+ {
+ loggerProviders = new LoggerProviderCollection();
+ }
+
+ collection.AddSingleton(services =>
+ {
+ ILogger logger;
+ if (useReload)
+ {
+ reloadable!.Reload(cfg =>
+ {
+ if (loggerProviders != null)
+ cfg.WriteTo.Providers(loggerProviders);
+
+ configureLogger(services, cfg);
+ return cfg;
});
+
+ logger = reloadable.Freeze();
}
else
{
- collection.AddSingleton(services => new SerilogLoggerFactory(logger, dispose));
- }
+ var loggerConfiguration = new LoggerConfiguration();
- if (logger != null)
- {
- // This won't (and shouldn't) take ownership of the logger.
- collection.AddSingleton(logger);
+ if (loggerProviders != null)
+ loggerConfiguration.WriteTo.Providers(loggerProviders);
- // Still need to use RegisteredLogger as it is used by ConfigureDiagnosticContext.
- collection.AddSingleton(new RegisteredLogger(logger));
+ configureLogger(services, loggerConfiguration);
+ logger = loggerConfiguration.CreateLogger();
}
- bool useRegisteredLogger = logger != null;
- ConfigureDiagnosticContext(collection, useRegisteredLogger);
- return collection;
- }
+ return new RegisteredLogger(logger);
+ });
- /// Sets Serilog as the logging provider.
- /// The service collection to use.
- /// The delegate for configuring the that will be used to construct a .
- /// Indicates whether to preserve the value of .
- /// By default, Serilog does not write events to s registered through
- /// the Microsoft.Extensions.Logging API. Normally, equivalent Serilog sinks are used in place of providers. Specify
- /// true to write events to all providers.
- /// The service collection.
- public static IServiceCollection AddSerilog(
- this IServiceCollection collection,
- Action configureLogger,
- bool preserveStaticLogger = false,
- bool writeToProviders = false)
+ collection.AddSingleton(services =>
{
- if (collection == null) throw new ArgumentNullException(nameof(collection));
- if (configureLogger == null) throw new ArgumentNullException(nameof(configureLogger));
- return AddSerilog(
- collection,
- (services, loggerConfiguration) =>
- configureLogger(loggerConfiguration),
- preserveStaticLogger: preserveStaticLogger,
- writeToProviders: writeToProviders);
- }
+ // How can we register the logger, here, but not have MEDI dispose it?
+ // Using the `NullEnricher` hack to prevent disposal.
+ var logger = services.GetRequiredService().Logger;
+ return logger.ForContext(new NullEnricher());
+ });
- /// Sets Serilog as the logging provider.
- /// The service collection to use.
- /// The delegate for configuring the that will be used to construct a .
- /// Indicates whether to preserve the value of .
- /// By default, Serilog does not write events to s registered through
- /// the Microsoft.Extensions.Logging API. Normally, equivalent Serilog sinks are used in place of providers. Specify
- /// true to write events to all providers.
- /// If the static is a bootstrap logger (see
- /// LoggerConfigurationExtensions.CreateBootstrapLogger()), and is
- /// not specified, the the bootstrap logger will be reconfigured through the supplied delegate, rather than being
- /// replaced entirely or ignored.
- /// The service collection.
- public static IServiceCollection AddSerilog(
- this IServiceCollection collection,
- Action configureLogger,
- bool preserveStaticLogger = false,
- bool writeToProviders = false)
+ collection.AddSingleton(services =>
{
- if (collection == null) throw new ArgumentNullException(nameof(collection));
- if (configureLogger == null) throw new ArgumentNullException(nameof(configureLogger));
-
- // This check is eager; replacing the bootstrap logger after calling this method is not supported.
-#if !NO_RELOADABLE_LOGGER
- var reloadable = Log.Logger as ReloadableLogger;
- var useReload = reloadable != null && !preserveStaticLogger;
-#else
- const bool useReload = false;
-#endif
-
- LoggerProviderCollection loggerProviders = null;
- if (writeToProviders)
+ var logger = services.GetRequiredService().Logger;
+
+ ILogger? registeredLogger = null;
+ if (preserveStaticLogger)
{
- loggerProviders = new LoggerProviderCollection();
+ registeredLogger = logger;
}
-
- collection.AddSingleton(services =>
+ else
{
- ILogger logger;
-#if !NO_RELOADABLE_LOGGER
- if (useReload)
- {
- reloadable!.Reload(cfg =>
- {
- if (loggerProviders != null)
- cfg.WriteTo.Providers(loggerProviders);
-
- configureLogger(services, cfg);
- return cfg;
- });
-
- logger = reloadable.Freeze();
- }
- else
-#endif
- {
- var loggerConfiguration = new LoggerConfiguration();
-
- if (loggerProviders != null)
- loggerConfiguration.WriteTo.Providers(loggerProviders);
-
- configureLogger(services, loggerConfiguration);
- logger = loggerConfiguration.CreateLogger();
- }
+ // Passing a `null` logger to `SerilogLoggerFactory` results in disposal via
+ // `Log.CloseAndFlush()`, which additionally replaces the static logger with a no-op.
+ Log.Logger = logger;
+ }
- return new RegisteredLogger(logger);
- });
+ var factory = new SerilogLoggerFactory(registeredLogger, !useReload, loggerProviders);
- collection.AddSingleton(services =>
- {
- // How can we register the logger, here, but not have MEDI dispose it?
- // Using the `NullEnricher` hack to prevent disposal.
- var logger = services.GetRequiredService().Logger;
- return logger.ForContext(new NullEnricher());
- });
-
- collection.AddSingleton(services =>
+ if (writeToProviders)
{
- var logger = services.GetRequiredService().Logger;
-
- ILogger registeredLogger = null;
- if (preserveStaticLogger)
- {
- registeredLogger = logger;
- }
- else
- {
- // Passing a `null` logger to `SerilogLoggerFactory` results in disposal via
- // `Log.CloseAndFlush()`, which additionally replaces the static logger with a no-op.
- Log.Logger = logger;
- }
+ foreach (var provider in services.GetServices())
+ factory.AddProvider(provider);
+ }
- var factory = new SerilogLoggerFactory(registeredLogger, !useReload, loggerProviders);
+ return factory;
+ });
- if (writeToProviders)
- {
- foreach (var provider in services.GetServices())
- factory.AddProvider(provider);
- }
+ ConfigureDiagnosticContext(collection, preserveStaticLogger);
- return factory;
- });
+ return collection;
+ }
- ConfigureDiagnosticContext(collection, preserveStaticLogger);
-
- return collection;
- }
+ static void ConfigureDiagnosticContext(IServiceCollection collection, bool useRegisteredLogger)
+ {
+ if (collection == null) throw new ArgumentNullException(nameof(collection));
- static void ConfigureDiagnosticContext(IServiceCollection collection, bool useRegisteredLogger)
+ // Registered to provide two services...
+ // Consumed by e.g. middleware
+ collection.AddSingleton(services =>
{
- if (collection == null) throw new ArgumentNullException(nameof(collection));
-
- // Registered to provide two services...
- // Consumed by e.g. middleware
- collection.AddSingleton(services =>
- {
- ILogger logger = useRegisteredLogger ? services.GetRequiredService().Logger : null;
- return new DiagnosticContext(logger);
- });
- // Consumed by user code
- collection.AddSingleton(services => services.GetRequiredService());
- }
+ ILogger? logger = useRegisteredLogger ? services.GetRequiredService().Logger : null;
+ return new DiagnosticContext(logger);
+ });
+ // Consumed by user code
+ collection.AddSingleton(services => services.GetRequiredService());
}
}
diff --git a/test/Serilog.Extensions.Hosting.Tests/DiagnosticContextTests.cs b/test/Serilog.Extensions.Hosting.Tests/DiagnosticContextTests.cs
index 3281065..ba36bc7 100644
--- a/test/Serilog.Extensions.Hosting.Tests/DiagnosticContextTests.cs
+++ b/test/Serilog.Extensions.Hosting.Tests/DiagnosticContextTests.cs
@@ -1,121 +1,117 @@
-using System;
-using System.Linq;
-using System.Threading.Tasks;
-using Serilog.Events;
+using Serilog.Events;
using Serilog.Extensions.Hosting.Tests.Support;
using Xunit;
// ReSharper disable PossibleNullReferenceException
-namespace Serilog.Extensions.Hosting.Tests
+namespace Serilog.Extensions.Hosting.Tests;
+
+public class DiagnosticContextTests
{
- public class DiagnosticContextTests
+ [Fact]
+ public void SetIsSafeWhenNoContextIsActive()
+ {
+ var dc = new DiagnosticContext(Some.Logger());
+ dc.Set(Some.String("name"), Some.Int32());
+ }
+
+ [Fact]
+ public void SetExceptionIsSafeWhenNoContextIsActive()
+ {
+ var dc = new DiagnosticContext(Some.Logger());
+ dc.SetException(new Exception("test"));
+ }
+
+ [Fact]
+ public async Task PropertiesAreCollectedInAnActiveContext()
+ {
+ var dc = new DiagnosticContext(Some.Logger());
+
+ var collector = dc.BeginCollection();
+ dc.Set(Some.String("first"), Some.Int32());
+ await Task.Delay(TimeSpan.FromMilliseconds(10));
+ dc.Set(Some.String("second"), Some.Int32());
+
+ Assert.True(collector.TryComplete(out var properties, out var exception));
+ Assert.Equal(2, properties!.Count());
+ Assert.Null(exception);
+
+ Assert.False(collector.TryComplete(out _, out _));
+
+ collector.Dispose();
+
+ dc.Set(Some.String("third"), Some.Int32());
+ Assert.False(collector.TryComplete(out _, out _));
+ }
+
+ [Fact]
+ public void ExceptionIsCollectedInAnActiveContext()
+ {
+ var dc = new DiagnosticContext(Some.Logger());
+ var collector = dc.BeginCollection();
+
+ var setException = new Exception("before collect");
+ dc.SetException(setException);
+
+ Assert.True(collector.TryComplete(out _, out var collectedException));
+ Assert.Same(setException, collectedException);
+ }
+
+ [Fact]
+ public void ExceptionIsNotCollectedAfterTryComplete()
+ {
+ var dc = new DiagnosticContext(Some.Logger());
+ var collector = dc.BeginCollection();
+ collector.TryComplete(out _, out _);
+ dc.SetException(new Exception(Some.String("after collect")));
+
+ var tryComplete2 = collector.TryComplete(out _, out var collectedException2);
+
+ Assert.False(tryComplete2);
+ Assert.Null(collectedException2);
+ }
+
+ [Fact]
+ public void ExceptionIsNotCollectedAfterDispose()
{
- [Fact]
- public void SetIsSafeWhenNoContextIsActive()
- {
- var dc = new DiagnosticContext(Some.Logger());
- dc.Set(Some.String("name"), Some.Int32());
- }
-
- [Fact]
- public void SetExceptionIsSafeWhenNoContextIsActive()
- {
- var dc = new DiagnosticContext(Some.Logger());
- dc.SetException(new Exception("test"));
- }
-
- [Fact]
- public async Task PropertiesAreCollectedInAnActiveContext()
- {
- var dc = new DiagnosticContext(Some.Logger());
-
- var collector = dc.BeginCollection();
- dc.Set(Some.String("first"), Some.Int32());
- await Task.Delay(TimeSpan.FromMilliseconds(10));
- dc.Set(Some.String("second"), Some.Int32());
-
- Assert.True(collector.TryComplete(out var properties, out var exception));
- Assert.Equal(2, properties.Count());
- Assert.Null(exception);
-
- Assert.False(collector.TryComplete(out _, out _));
-
- collector.Dispose();
-
- dc.Set(Some.String("third"), Some.Int32());
- Assert.False(collector.TryComplete(out _, out _));
- }
-
- [Fact]
- public void ExceptionIsCollectedInAnActiveContext()
- {
- var dc = new DiagnosticContext(Some.Logger());
- var collector = dc.BeginCollection();
-
- var setException = new Exception("before collect");
- dc.SetException(setException);
-
- Assert.True(collector.TryComplete(out _, out var collectedException));
- Assert.Same(setException, collectedException);
- }
-
- [Fact]
- public void ExceptionIsNotCollectedAfterTryComplete()
- {
- var dc = new DiagnosticContext(Some.Logger());
- var collector = dc.BeginCollection();
- collector.TryComplete(out _, out _);
- dc.SetException(new Exception(Some.String("after collect")));
-
- var tryComplete2 = collector.TryComplete(out _, out var collectedException2);
-
- Assert.False(tryComplete2);
- Assert.Null(collectedException2);
- }
-
- [Fact]
- public void ExceptionIsNotCollectedAfterDispose()
- {
- var dc = new DiagnosticContext(Some.Logger());
- var collector = dc.BeginCollection();
- collector.Dispose();
-
- dc.SetException(new Exception("after dispose"));
-
- var tryComplete = collector.TryComplete(out _, out var collectedException);
-
- Assert.True(tryComplete);
- Assert.Null(collectedException);
- }
-
- [Fact]
- public void ExistingPropertiesCanBeUpdated()
- {
- var dc = new DiagnosticContext(Some.Logger());
-
- var collector = dc.BeginCollection();
- dc.Set("name", 10);
- dc.Set("name", 20);
-
- Assert.True(collector.TryComplete(out var properties, out var exception));
- var prop = Assert.Single(properties);
- var scalar = Assert.IsType(prop.Value);
- Assert.Equal(20, scalar.Value);
- Assert.Null(exception);
- }
-
- [Fact]
- public void ExistingExceptionCanBeUpdated()
- {
- var dc = new DiagnosticContext(Some.Logger());
- var collector = dc.BeginCollection();
-
- dc.SetException(new Exception("ex1"));
- dc.SetException(new Exception("ex2"));
-
- Assert.True(collector.TryComplete(out _, out var collectedException));
- Assert.Equal("ex2", collectedException.Message);
- }
+ var dc = new DiagnosticContext(Some.Logger());
+ var collector = dc.BeginCollection();
+ collector.Dispose();
+
+ dc.SetException(new Exception("after dispose"));
+
+ var tryComplete = collector.TryComplete(out _, out var collectedException);
+
+ Assert.True(tryComplete);
+ Assert.Null(collectedException);
+ }
+
+ [Fact]
+ public void ExistingPropertiesCanBeUpdated()
+ {
+ var dc = new DiagnosticContext(Some.Logger());
+
+ var collector = dc.BeginCollection();
+ dc.Set("name", 10);
+ dc.Set("name", 20);
+
+ Assert.True(collector.TryComplete(out var properties, out var exception));
+ var prop = Assert.Single(properties!);
+ var scalar = Assert.IsType(prop.Value);
+ Assert.Equal(20, scalar.Value);
+ Assert.Null(exception);
+ }
+
+ [Fact]
+ public void ExistingExceptionCanBeUpdated()
+ {
+ var dc = new DiagnosticContext(Some.Logger());
+ var collector = dc.BeginCollection();
+
+ dc.SetException(new Exception("ex1"));
+ dc.SetException(new Exception("ex2"));
+
+ Assert.True(collector.TryComplete(out _, out var collectedException));
+ Assert.Equal("ex2", collectedException!.Message);
}
}
diff --git a/test/Serilog.Extensions.Hosting.Tests/LoggerSettingsConfigurationExtensionsTests.cs b/test/Serilog.Extensions.Hosting.Tests/LoggerSettingsConfigurationExtensionsTests.cs
index 54a8154..70f6ab8 100644
--- a/test/Serilog.Extensions.Hosting.Tests/LoggerSettingsConfigurationExtensionsTests.cs
+++ b/test/Serilog.Extensions.Hosting.Tests/LoggerSettingsConfigurationExtensionsTests.cs
@@ -5,27 +5,26 @@
using Serilog.Extensions.Hosting.Tests.Support;
using Xunit;
-namespace Serilog.Extensions.Hosting.Tests
+namespace Serilog.Extensions.Hosting.Tests;
+
+public class LoggerSettingsConfigurationExtensionsTests
{
- public class LoggerSettingsConfigurationExtensionsTests
+ [Fact]
+ public void SinksAreInjectedFromTheServiceProvider()
{
- [Fact]
- public void SinksAreInjectedFromTheServiceProvider()
- {
- var emittedEvents = new List();
-
- var serviceCollection = new ServiceCollection();
- serviceCollection.AddSingleton(new ListSink(emittedEvents));
- using var services = serviceCollection.BuildServiceProvider();
+ var emittedEvents = new List();
+
+ var serviceCollection = new ServiceCollection();
+ serviceCollection.AddSingleton(new ListSink(emittedEvents));
+ using var services = serviceCollection.BuildServiceProvider();
+
+ using var logger = new LoggerConfiguration()
+ .ReadFrom.Services(services)
+ .CreateLogger();
+
+ logger.Information("Hello, world!");
- using var logger = new LoggerConfiguration()
- .ReadFrom.Services(services)
- .CreateLogger();
-
- logger.Information("Hello, world!");
-
- var evt = Assert.Single(emittedEvents);
- Assert.Equal("Hello, world!", evt!.MessageTemplate.Text);
- }
+ var evt = Assert.Single(emittedEvents);
+ Assert.Equal("Hello, world!", evt!.MessageTemplate.Text);
}
}
\ No newline at end of file
diff --git a/test/Serilog.Extensions.Hosting.Tests/ReloadableLoggerTests.cs b/test/Serilog.Extensions.Hosting.Tests/ReloadableLoggerTests.cs
index 10b807a..cd24597 100644
--- a/test/Serilog.Extensions.Hosting.Tests/ReloadableLoggerTests.cs
+++ b/test/Serilog.Extensions.Hosting.Tests/ReloadableLoggerTests.cs
@@ -1,108 +1,101 @@
-#if !NO_RELOADABLE_LOGGER
-
-using System.Collections.Generic;
-using System.Linq;
-using Serilog.Core;
+using Serilog.Core;
using Serilog.Events;
using Serilog.Extensions.Hosting.Tests.Support;
using Xunit;
-namespace Serilog.Extensions.Hosting.Tests
+namespace Serilog.Extensions.Hosting.Tests;
+
+public class ReloadableLoggerTests
{
- public class ReloadableLoggerTests
+ [Fact]
+ public void AFrozenLoggerYieldsSerilogLoggers()
{
- [Fact]
- public void AFrozenLoggerYieldsSerilogLoggers()
- {
- var logger = new ReloadableLogger(new LoggerConfiguration().CreateLogger());
- var contextual = logger.ForContext();
+ var logger = new ReloadableLogger(new LoggerConfiguration().CreateLogger());
+ var contextual = logger.ForContext();
- var nested = contextual.ForContext("test", "test");
- Assert.IsNotType(nested);
+ var nested = contextual.ForContext("test", "test");
+ Assert.IsNotType(nested);
- logger.Freeze();
+ logger.Freeze();
- nested = contextual.ForContext("test", "test");
- Assert.IsType(nested);
- }
-
- [Fact]
- public void CachingReloadableLoggerRemainsUsableAfterFreezing()
- {
- var logger = new LoggerConfiguration().CreateBootstrapLogger();
- var contextual = logger.ForContext();
- contextual.Information("First");
- logger.Reload(c => c);
- logger.Freeze();
- contextual.Information("Second");
- contextual.Information("Third");
- contextual.Information("Fourth"); // No crash :-)
- }
+ nested = contextual.ForContext("test", "test");
+ Assert.IsType(nested);
+ }
+
+ [Fact]
+ public void CachingReloadableLoggerRemainsUsableAfterFreezing()
+ {
+ var logger = new LoggerConfiguration().CreateBootstrapLogger();
+ var contextual = logger.ForContext();
+ contextual.Information("First");
+ logger.Reload(c => c);
+ logger.Freeze();
+ contextual.Information("Second");
+ contextual.Information("Third");
+ contextual.Information("Fourth"); // No crash :-)
+ }
- [Fact]
- public void ReloadableLoggerRespectsMinimumLevelOverrides()
- {
- var emittedEvents = new List();
- var logger = new LoggerConfiguration()
- .MinimumLevel.Override("Test", LogEventLevel.Warning)
- .WriteTo.Sink(new ListSink(emittedEvents))
- .CreateBootstrapLogger();
+ [Fact]
+ public void ReloadableLoggerRespectsMinimumLevelOverrides()
+ {
+ var emittedEvents = new List();
+ var logger = new LoggerConfiguration()
+ .MinimumLevel.Override("Test", LogEventLevel.Warning)
+ .WriteTo.Sink(new ListSink(emittedEvents))
+ .CreateBootstrapLogger();
- var limited = logger
- .ForContext("X", 1)
- .ForContext(Constants.SourceContextPropertyName, "Test.Stuff");
-
- var notLimited = logger.ForContext();
-
- foreach (var context in new[] { limited, notLimited })
- {
- // Suppressed by both sinks
- context.Debug("First");
+ var limited = logger
+ .ForContext("X", 1)
+ .ForContext(Constants.SourceContextPropertyName, "Test.Stuff");
+
+ var notLimited = logger.ForContext();
+
+ foreach (var context in new[] { limited, notLimited })
+ {
+ // Suppressed by both sinks
+ context.Debug("First");
- // Suppressed by the limited logger
- context.Information("Second");
-
- // Emitted by both loggers
- context.Warning("Third");
- }
+ // Suppressed by the limited logger
+ context.Information("Second");
- Assert.Equal(3, emittedEvents.Count);
- Assert.Equal(2, emittedEvents.Count(le => le.Level == LogEventLevel.Warning));
+ // Emitted by both loggers
+ context.Warning("Third");
}
+
+ Assert.Equal(3, emittedEvents.Count);
+ Assert.Equal(2, emittedEvents.Count(le => le.Level == LogEventLevel.Warning));
+ }
- [Fact]
- public void ReloadableLoggersRecordEnrichment()
- {
- var emittedEvents = new List();
-
- var logger = new LoggerConfiguration()
- .WriteTo.Sink(new ListSink(emittedEvents))
- .CreateBootstrapLogger();
+ [Fact]
+ public void ReloadableLoggersRecordEnrichment()
+ {
+ var emittedEvents = new List();
+
+ var logger = new LoggerConfiguration()
+ .WriteTo.Sink(new ListSink(emittedEvents))
+ .CreateBootstrapLogger();
- var outer = logger
- .ForContext("A", new object());
- var inner = outer.ForContext("B", "test");
-
- inner.Information("First");
-
- logger.Reload(lc => lc.WriteTo.Sink(new ListSink(emittedEvents)));
-
- inner.Information("Second");
+ var outer = logger
+ .ForContext("A", new object());
+ var inner = outer.ForContext("B", "test");
+
+ inner.Information("First");
+
+ logger.Reload(lc => lc.WriteTo.Sink(new ListSink(emittedEvents)));
+
+ inner.Information("Second");
- logger.Freeze();
-
- inner.Information("Third");
-
- outer.ForContext("B", "test").Information("Fourth");
-
- logger.ForContext("A", new object())
- .ForContext("B", "test")
- .Information("Fifth");
-
- Assert.Equal(5, emittedEvents.Count);
- Assert.All(emittedEvents, e => Assert.Equal(2, e.Properties.Count));
- }
+ logger.Freeze();
+
+ inner.Information("Third");
+
+ outer.ForContext("B", "test").Information("Fourth");
+
+ logger.ForContext("A", new object())
+ .ForContext("B", "test")
+ .Information("Fifth");
+
+ Assert.Equal(5, emittedEvents.Count);
+ Assert.All(emittedEvents, e => Assert.Equal(2, e.Properties.Count));
}
}
-
-#endif
diff --git a/test/Serilog.Extensions.Hosting.Tests/Serilog.Extensions.Hosting.Tests.csproj b/test/Serilog.Extensions.Hosting.Tests/Serilog.Extensions.Hosting.Tests.csproj
index 39904a4..2d764f6 100644
--- a/test/Serilog.Extensions.Hosting.Tests/Serilog.Extensions.Hosting.Tests.csproj
+++ b/test/Serilog.Extensions.Hosting.Tests/Serilog.Extensions.Hosting.Tests.csproj
@@ -1,26 +1,21 @@
- net4.8;net6.0;net7.0;net8.0
- ../../assets/Serilog.snk
- true
- true
- latest
+
+ net4.8;net6.0;net8.0;net9.0
+ false
-
- $(DefineConstants);NO_RELOADABLE_LOGGER
-
-
-
-
-
-
+
+
+
+
-
+
diff --git a/test/Serilog.Extensions.Hosting.Tests/SerilogHostBuilderExtensionsTests.cs b/test/Serilog.Extensions.Hosting.Tests/SerilogHostBuilderExtensionsTests.cs
index c9ba14b..02aed72 100644
--- a/test/Serilog.Extensions.Hosting.Tests/SerilogHostBuilderExtensionsTests.cs
+++ b/test/Serilog.Extensions.Hosting.Tests/SerilogHostBuilderExtensionsTests.cs
@@ -1,109 +1,108 @@
-using System;
-using System.Collections.Generic;
-using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Xunit;
-namespace Serilog.Extensions.Hosting.Tests
+namespace Serilog.Extensions.Hosting.Tests;
+
+public class SerilogHostBuilderExtensionsTests
{
- public class SerilogHostBuilderExtensionsTests
+ [Fact]
+ public void ServicesAreRegisteredWhenCallingUseSerilog()
+ {
+ // Arrange
+ var collection = new ServiceCollection();
+ IHostBuilder builder = new FakeHostBuilder(collection);
+
+ // Act
+ builder.UseSerilog();
+
+ // Assert
+ IServiceProvider provider = collection.BuildServiceProvider();
+ provider.GetRequiredService();
+ provider.GetRequiredService();
+ }
+
+ [Fact]
+ public void ServicesAreRegisteredWhenCallingUseSerilogWithLogger()
+ {
+ // Arrange
+ var collection = new ServiceCollection();
+ IHostBuilder builder = new FakeHostBuilder(collection);
+ ILogger logger = new LoggerConfiguration().CreateLogger();
+
+ // Act
+ builder.UseSerilog(logger);
+
+ // Assert
+ IServiceProvider provider = collection.BuildServiceProvider();
+ provider.GetRequiredService();
+ provider.GetRequiredService();
+ provider.GetRequiredService();
+ }
+
+ [Fact]
+ public void ServicesAreRegisteredWhenCallingUseSerilogWithConfigureDelegate()
+ {
+ // Arrange
+ var collection = new ServiceCollection();
+ IHostBuilder builder = new FakeHostBuilder(collection);
+
+ // Act
+ builder.UseSerilog((_, _) => { });
+
+ // Assert
+ IServiceProvider provider = collection.BuildServiceProvider();
+ provider.GetRequiredService();
+ provider.GetRequiredService();
+ provider.GetRequiredService();
+ }
+
+ class FakeHostBuilder : IHostBuilder
{
- [Fact]
- public void ServicesAreRegisteredWhenCallingUseSerilog()
+ readonly IServiceCollection _collection;
+
+ public FakeHostBuilder(IServiceCollection collection) => _collection = collection;
+
+ public IHostBuilder ConfigureHostConfiguration(Action configureDelegate)
{
- // Arrange
- var collection = new ServiceCollection();
- IHostBuilder builder = new FakeHostBuilder(collection);
+ throw new NotImplementedException();
+ }
- // Act
- builder.UseSerilog();
+ public IHostBuilder ConfigureAppConfiguration(Action configureDelegate)
+ {
+ throw new NotImplementedException();
+ }
- // Assert
- IServiceProvider provider = collection.BuildServiceProvider();
- provider.GetRequiredService();
- provider.GetRequiredService();
+ public IHostBuilder ConfigureServices(Action configureDelegate)
+ {
+ configureDelegate(null!, _collection);
+ return this;
}
- [Fact]
- public void ServicesAreRegisteredWhenCallingUseSerilogWithLogger()
+ public IHostBuilder UseServiceProviderFactory(IServiceProviderFactory factory)
+ where TContainerBuilder: notnull
{
- // Arrange
- var collection = new ServiceCollection();
- IHostBuilder builder = new FakeHostBuilder(collection);
- ILogger logger = new LoggerConfiguration().CreateLogger();
-
- // Act
- builder.UseSerilog(logger);
-
- // Assert
- IServiceProvider provider = collection.BuildServiceProvider();
- provider.GetRequiredService();
- provider.GetRequiredService();
- provider.GetRequiredService();
+ throw new NotImplementedException();
}
- [Fact]
- public void ServicesAreRegisteredWhenCallingUseSerilogWithConfigureDelegate()
+ public IHostBuilder UseServiceProviderFactory(Func> factory)
+ where TContainerBuilder: notnull
{
- // Arrange
- var collection = new ServiceCollection();
- IHostBuilder builder = new FakeHostBuilder(collection);
-
- // Act
- builder.UseSerilog((_, _) => { });
-
- // Assert
- IServiceProvider provider = collection.BuildServiceProvider();
- provider.GetRequiredService();
- provider.GetRequiredService();
- provider.GetRequiredService();
+ throw new NotImplementedException();
}
- private class FakeHostBuilder : IHostBuilder
+ public IHostBuilder ConfigureContainer(Action configureDelegate)
{
- private readonly IServiceCollection _collection;
-
- public FakeHostBuilder(IServiceCollection collection) => _collection = collection;
-
- public IHostBuilder ConfigureHostConfiguration(Action configureDelegate)
- {
- throw new NotImplementedException();
- }
-
- public IHostBuilder ConfigureAppConfiguration(Action configureDelegate)
- {
- throw new NotImplementedException();
- }
-
- public IHostBuilder ConfigureServices(Action configureDelegate)
- {
- configureDelegate(null, _collection);
- return this;
- }
-
- public IHostBuilder UseServiceProviderFactory(IServiceProviderFactory factory)
- {
- throw new NotImplementedException();
- }
-
- public IHostBuilder UseServiceProviderFactory(Func> factory)
- {
- throw new NotImplementedException();
- }
-
- public IHostBuilder ConfigureContainer(Action configureDelegate)
- {
- throw new NotImplementedException();
- }
-
- public IHost Build()
- {
- throw new NotImplementedException();
- }
-
- public IDictionary