diff --git a/Directory.Build.props b/Directory.Build.props
new file mode 100644
index 0000000..3dcd183
--- /dev/null
+++ b/Directory.Build.props
@@ -0,0 +1,12 @@
+
+
+ latest
+ True
+ true
+ ../../assets/Serilog.snk
+ true
+ false
+ enable
+ enable
+
+
diff --git a/README.md b/README.md
index 379d595..2c3e9e8 100644
--- a/README.md
+++ b/README.md
@@ -18,53 +18,38 @@ dotnet add package Serilog.AspNetCore
```csharp
using Serilog;
-using Serilog.Events;
-public class Program
+Log.Logger = new LoggerConfiguration()
+ .WriteTo.Console()
+ .CreateLogger();
+
+try
{
- public static int Main(string[] args)
- {
- Log.Logger = new LoggerConfiguration()
- .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
- .Enrich.FromLogContext()
- .WriteTo.Console()
- .CreateLogger();
+ Log.Information("Starting web application");
- try
- {
- Log.Information("Starting web host");
- CreateHostBuilder(args).Build().Run();
- return 0;
- }
- catch (Exception ex)
- {
- Log.Fatal(ex, "Host terminated unexpectedly");
- return 1;
- }
- finally
- {
- Log.CloseAndFlush();
- }
- }
-```
+ var builder = WebApplication.CreateBuilder(args);
+
+ builder.Host.UseSerilog(); // <-- Add this line
+
+ var app = builder.Build();
-**Then**, add `UseSerilog()` to the Generic Host in `CreateHostBuilder()`.
+ app.MapGet("/", () => "Hello World!");
-```csharp
- public static IHostBuilder CreateHostBuilder(string[] args) =>
- Host.CreateDefaultBuilder(args)
- .UseSerilog() // <-- Add this line
- .ConfigureWebHostDefaults(webBuilder =>
- {
- webBuilder.UseStartup();
- });
+ app.Run();
+}
+catch (Exception ex)
+{
+ Log.Fatal(ex, "Application terminated unexpectedly");
+}
+finally
+{
+ Log.CloseAndFlush();
}
```
-**Finally**, clean up by removing the remaining configuration for the default logger:
+The `builder.Host.UseSerilog()` call will redirect all log events through your Serilog pipeline.
- * Remove the `"Logging"` section from _appsettings.*.json_ files (this can be replaced with [Serilog configuration](https://github.com/serilog/serilog-settings-configuration) as shown in [the _Sample_ project](https://github.com/serilog/serilog-aspnetcore/blob/dev/samples/Sample/Program.cs), if required)
- * Remove `UseApplicationInsights()` (this can be replaced with the [Serilog AI sink](https://github.com/serilog/serilog-sinks-applicationinsights), if required)
+**Finally**, clean up by removing the remaining configuration for the default logger, including the `"Logging"` section from _appsettings.*.json_ files (this can be replaced with [Serilog configuration](https://github.com/serilog/serilog-settings-configuration) as shown in [the _Sample_ project](https://github.com/serilog/serilog-aspnetcore/blob/dev/samples/Sample/Program.cs), if required).
That's it! With the level bumped up a little you will see log output resembling:
@@ -118,23 +103,14 @@ To enable the middleware, first change the minimum level for `Microsoft.AspNetCo
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
```
-Then, in your application's _Startup.cs_, add the middleware with `UseSerilogRequestLogging()`:
+Then, in your application's _Program.cs_, add the middleware with `UseSerilogRequestLogging()`:
```csharp
- public void Configure(IApplicationBuilder app, IHostingEnvironment env)
- {
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- }
- else
- {
- app.UseExceptionHandler("/Home/Error");
- }
-
- app.UseSerilogRequestLogging(); // <-- Add this line
-
- // Other app configuration
+ var app = builder.Build();
+
+ app.UseSerilogRequestLogging(); // <-- Add this line
+
+ // Other app configuration
```
It's important that the `UseSerilogRequestLogging()` call appears _before_ handlers such as MVC. The middleware will not time or log components that appear before it in the pipeline. (This can be utilized to exclude noisy handlers from logging, such as `UseStaticFiles()`, by placing `UseSerilogRequestLogging()` after them.)
@@ -204,31 +180,21 @@ To use this technique, first replace the initial `CreateLogger()` call with `Cre
using Serilog;
using Serilog.Events;
-public class Program
-{
- public static int Main(string[] args)
- {
- Log.Logger = new LoggerConfiguration()
- .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
- .Enrich.FromLogContext()
- .WriteTo.Console()
- .CreateBootstrapLogger(); // <-- Change this line!
+Log.Logger = new LoggerConfiguration()
+ .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
+ .Enrich.FromLogContext()
+ .WriteTo.Console()
+ .CreateBootstrapLogger(); // <-- Change this line!
```
Then, pass a callback to `UseSerilog()` that creates the final logger:
```csharp
- public static IHostBuilder CreateHostBuilder(string[] args) =>
- Host.CreateDefaultBuilder(args)
- .UseSerilog((context, services, configuration) => configuration
- .ReadFrom.Configuration(context.Configuration)
- .ReadFrom.Services(services)
- .Enrich.FromLogContext()
- .WriteTo.Console())
- .ConfigureWebHostDefaults(webBuilder =>
- {
- webBuilder.UseStartup();
- });
+builder.Host.UseSerilog((context, services, configuration) => configuration
+ .ReadFrom.Configuration(context.Configuration)
+ .ReadFrom.Services(services)
+ .Enrich.FromLogContext()
+ .WriteTo.Console());
```
It's important to note that the final logger **completely replaces** the bootstrap logger: if you want both to log to the console, for instance, you'll need to specify `WriteTo.Console()` in both places, as the example shows.
@@ -256,7 +222,7 @@ By default, Serilog ignores providers, since there are usually equivalent Serilo
To have Serilog pass events to providers, **using two-stage initialization** as above, pass `writeToProviders: true` in the call to `UseSerilog()`:
```csharp
- .UseSerilog(
+builder.Host.UseSerilog(
(hostingContext, services, loggerConfiguration) => /* snip! */,
writeToProviders: true)
```
@@ -276,23 +242,21 @@ To write newline-delimited JSON, pass a `CompactJsonFormatter` or `RenderedCompa
The Azure Diagnostic Log Stream ships events from any files in the `D:\home\LogFiles\` folder. To enable this for your app, add a file sink to your `LoggerConfiguration`, taking care to set the `shared` and `flushToDiskInterval` parameters:
```csharp
- public static int Main(string[] args)
- {
- Log.Logger = new LoggerConfiguration()
- .MinimumLevel.Debug()
- .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
- .Enrich.FromLogContext()
- .WriteTo.Console()
- // Add this line:
- .WriteTo.File(
- System.IO.Path.Combine(Environment.GetEnvironmentVariable("HOME"), "LogFiles", "Application", "diagnostics.txt"),
- rollingInterval: RollingInterval.Day,
- fileSizeLimitBytes: 10 * 1024 * 1024,
- retainedFileCountLimit: 2,
- rollOnFileSizeLimit: true,
- shared: true,
- flushToDiskInterval: TimeSpan.FromSeconds(1))
- .CreateLogger();
+Log.Logger = new LoggerConfiguration()
+ .MinimumLevel.Debug()
+ .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
+ .Enrich.FromLogContext()
+ .WriteTo.Console()
+ // Add this line:
+ .WriteTo.File(
+ System.IO.Path.Combine(Environment.GetEnvironmentVariable("HOME"), "LogFiles", "Application", "diagnostics.txt"),
+ rollingInterval: RollingInterval.Day,
+ fileSizeLimitBytes: 10 * 1024 * 1024,
+ retainedFileCountLimit: 2,
+ rollOnFileSizeLimit: true,
+ shared: true,
+ flushToDiskInterval: TimeSpan.FromSeconds(1))
+ .CreateLogger();
```
### Pushing properties to the `ILogger`
diff --git a/appveyor.yml b/appveyor.yml
index 2d7ff52..fcd8868 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -12,7 +12,7 @@ deploy:
- provider: NuGet
skip_symbols: true
api_key:
- secure: U7I8Skf+EcC7PiqvLWpSzPqNhCg03cqDOi4OtAkb+ZelMlQj1YoKDX8r1pdQzy7H
+ secure: JZt0dILdf7cKm+rCtxfAHFGefHJHUUtt8Imm+J3+LtqTeVKODNZ7nyLjrP+QGBk5
on:
branch: /^(main|dev)$/
- provider: GitHub
diff --git a/global.json b/global.json
index 207e9f1..99ee408 100644
--- a/global.json
+++ b/global.json
@@ -1,7 +1,7 @@
{
"sdk": {
"allowPrerelease": false,
- "version": "5.0.201",
+ "version": "6.0.401",
"rollForward": "latestFeature"
}
}
diff --git a/samples/Sample/Controllers/HomeController.cs b/samples/Sample/Controllers/HomeController.cs
index 9f1308d..ec4ab25 100644
--- a/samples/Sample/Controllers/HomeController.cs
+++ b/samples/Sample/Controllers/HomeController.cs
@@ -1,47 +1,40 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
+using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Logging;
using Sample.Models;
using Serilog;
-namespace Sample.Controllers
+namespace Sample.Controllers;
+
+public class HomeController : Controller
{
- public class HomeController : Controller
+ static int _callCount;
+
+ readonly ILogger _logger;
+ readonly IDiagnosticContext _diagnosticContext;
+
+ public HomeController(ILogger logger, IDiagnosticContext diagnosticContext)
+ {
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ _diagnosticContext = diagnosticContext ?? throw new ArgumentNullException(nameof(diagnosticContext));
+ }
+
+ public IActionResult Index()
+ {
+ _logger.LogInformation("Hello, world!");
+
+ _diagnosticContext.Set("IndexCallCount", Interlocked.Increment(ref _callCount));
+
+ return View();
+ }
+
+ public IActionResult Privacy()
+ {
+ throw new InvalidOperationException("Something went wrong.");
+ }
+
+ [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
+ public IActionResult Error()
{
- static int _callCount;
-
- readonly ILogger _logger;
- readonly IDiagnosticContext _diagnosticContext;
-
- public HomeController(ILogger logger, IDiagnosticContext diagnosticContext)
- {
- _logger = logger ?? throw new ArgumentNullException(nameof(logger));
- _diagnosticContext = diagnosticContext ?? throw new ArgumentNullException(nameof(diagnosticContext));
- }
-
- public IActionResult Index()
- {
- _logger.LogInformation("Hello, world!");
-
- _diagnosticContext.Set("IndexCallCount", Interlocked.Increment(ref _callCount));
-
- return View();
- }
-
- public IActionResult Privacy()
- {
- throw new InvalidOperationException("Something went wrong.");
- }
-
- [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
- public IActionResult Error()
- {
- return View(new ErrorViewModel {RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier});
- }
+ return View(new ErrorViewModel {RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier});
}
-}
+}
\ No newline at end of file
diff --git a/samples/Sample/Models/ErrorViewModel.cs b/samples/Sample/Models/ErrorViewModel.cs
index 68f449e..3fc26f0 100644
--- a/samples/Sample/Models/ErrorViewModel.cs
+++ b/samples/Sample/Models/ErrorViewModel.cs
@@ -1,11 +1,8 @@
-using System;
+namespace Sample.Models;
-namespace Sample.Models
+public class ErrorViewModel
{
- public class ErrorViewModel
- {
- public string RequestId { get; set; }
+ public string? RequestId { get; set; }
- public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
- }
+ public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
}
\ No newline at end of file
diff --git a/samples/Sample/Program.cs b/samples/Sample/Program.cs
index 2bd5e57..c80e108 100644
--- a/samples/Sample/Program.cs
+++ b/samples/Sample/Program.cs
@@ -1,53 +1,44 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Logging;
using Serilog;
-namespace Sample
+namespace Sample;
+
+public static class Program
{
- public static class Program
+ public static int Main(string[] args)
{
- public static int Main(string[] args)
- {
- // The initial "bootstrap" logger is able to log errors during start-up. It's completely replaced by the
- // logger configured in `UseSerilog()` below, once configuration and dependency-injection have both been
- // set up successfully.
- Log.Logger = new LoggerConfiguration()
- .WriteTo.Console()
- .CreateBootstrapLogger();
-
- Log.Information("Starting up!");
+ // The initial "bootstrap" logger is able to log errors during start-up. It's completely replaced by the
+ // logger configured in `UseSerilog()` below, once configuration and dependency-injection have both been
+ // set up successfully.
+ Log.Logger = new LoggerConfiguration()
+ .WriteTo.Console()
+ .CreateBootstrapLogger();
- try
- {
- CreateHostBuilder(args).Build().Run();
+ Log.Information("Starting up!");
- Log.Information("Stopped cleanly");
- return 0;
- }
- catch (Exception ex)
- {
- Log.Fatal(ex, "An unhandled exception occured during bootstrapping");
- return 1;
- }
- finally
- {
- Log.CloseAndFlush();
- }
- }
+ try
+ {
+ CreateHostBuilder(args).Build().Run();
- public static IHostBuilder CreateHostBuilder(string[] args) =>
- Host.CreateDefaultBuilder(args)
- .UseSerilog((context, services, configuration) => configuration
- .ReadFrom.Configuration(context.Configuration)
- .ReadFrom.Services(services)
- .Enrich.FromLogContext()
- .WriteTo.Console())
- .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); });
+ Log.Information("Stopped cleanly");
+ return 0;
+ }
+ catch (Exception ex)
+ {
+ Log.Fatal(ex, "An unhandled exception occured during bootstrapping");
+ return 1;
+ }
+ finally
+ {
+ Log.CloseAndFlush();
+ }
}
-}
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseSerilog((context, services, configuration) => configuration
+ .ReadFrom.Configuration(context.Configuration)
+ .ReadFrom.Services(services)
+ .Enrich.FromLogContext()
+ .WriteTo.Console())
+ .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); });
+}
\ No newline at end of file
diff --git a/samples/Sample/Sample.csproj b/samples/Sample/Sample.csproj
index dff37ac..f32c84b 100644
--- a/samples/Sample/Sample.csproj
+++ b/samples/Sample/Sample.csproj
@@ -1,7 +1,7 @@
- net5.0
+ net6.0
diff --git a/samples/Sample/Startup.cs b/samples/Sample/Startup.cs
index 6c29268..67200ce 100644
--- a/samples/Sample/Startup.cs
+++ b/samples/Sample/Startup.cs
@@ -1,64 +1,53 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.HttpsPolicy;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Hosting;
using Serilog;
-namespace Sample
+namespace Sample;
+
+public class Startup
{
- public class Startup
+ public Startup(IConfiguration configuration)
{
- public Startup(IConfiguration configuration)
- {
- Configuration = configuration;
- }
+ Configuration = configuration;
+ }
- public IConfiguration Configuration { get; }
+ public IConfiguration Configuration { get; }
+
+ // This method gets called by the runtime. Use this method to add services to the container.
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddControllersWithViews();
+ }
- // This method gets called by the runtime. Use this method to add services to the container.
- 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())
{
- services.AddControllersWithViews();
+ app.UseDeveloperExceptionPage();
}
-
- // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
- public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ else
{
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- }
- else
- {
- app.UseExceptionHandler("/Home/Error");
- // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
- app.UseHsts();
- }
+ app.UseExceptionHandler("/Home/Error");
+ // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
+ app.UseHsts();
+ }
- app.UseHttpsRedirection();
- app.UseStaticFiles();
-
- // Write streamlined request completion events, instead of the more verbose ones from the framework.
- // To use the default framework request logging instead, remove this line and set the "Microsoft"
- // level in appsettings.json to "Information".
- app.UseSerilogRequestLogging();
+ app.UseHttpsRedirection();
+ app.UseStaticFiles();
- app.UseRouting();
+ // Write streamlined request completion events, instead of the more verbose ones from the framework.
+ // To use the default framework request logging instead, remove this line and set the "Microsoft"
+ // level in appsettings.json to "Information".
+ app.UseSerilogRequestLogging();
- app.UseAuthorization();
+ app.UseRouting();
- app.UseEndpoints(endpoints =>
- {
- endpoints.MapControllerRoute(
- name: "default",
- pattern: "{controller=Home}/{action=Index}/{id?}");
- });
- }
+ app.UseAuthorization();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllerRoute(
+ name: "default",
+ pattern: "{controller=Home}/{action=Index}/{id?}");
+ });
}
}
\ No newline at end of file
diff --git a/serilog-aspnetcore.sln b/serilog-aspnetcore.sln
index bc01e54..a9b5e42 100644
--- a/serilog-aspnetcore.sln
+++ b/serilog-aspnetcore.sln
@@ -17,6 +17,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "assets", "assets", "{9C21B9
README.md = README.md
assets\Serilog.snk = assets\Serilog.snk
Setup.ps1 = Setup.ps1
+ Directory.Build.props = Directory.Build.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serilog.AspNetCore", "src\Serilog.AspNetCore\Serilog.AspNetCore.csproj", "{0549D23F-986B-4FB2-BACE-16FD7A7BC9EF}"
diff --git a/src/Serilog.AspNetCore/AspNetCore/RequestLoggingMiddleware.cs b/src/Serilog.AspNetCore/AspNetCore/RequestLoggingMiddleware.cs
index 0c53ec8..0b0b3eb 100644
--- a/src/Serilog.AspNetCore/AspNetCore/RequestLoggingMiddleware.cs
+++ b/src/Serilog.AspNetCore/AspNetCore/RequestLoggingMiddleware.cs
@@ -17,114 +17,106 @@
using Serilog.Events;
using Serilog.Extensions.Hosting;
using Serilog.Parsing;
-using System;
using System.Diagnostics;
-using System.Linq;
-using System.Threading.Tasks;
-namespace Serilog.AspNetCore
+namespace Serilog.AspNetCore;
+
+// ReSharper disable once ClassNeverInstantiated.Global
+class RequestLoggingMiddleware
{
- // ReSharper disable once ClassNeverInstantiated.Global
- class RequestLoggingMiddleware
+ readonly RequestDelegate _next;
+ readonly DiagnosticContext _diagnosticContext;
+ readonly MessageTemplate _messageTemplate;
+ readonly Action? _enrichDiagnosticContext;
+ readonly Func _getLevel;
+ readonly Func> _getMessageTemplateProperties;
+ readonly ILogger? _logger;
+ readonly bool _includeQueryInRequestPath;
+ static readonly LogEventProperty[] NoProperties = new LogEventProperty[0];
+
+ public RequestLoggingMiddleware(RequestDelegate next, DiagnosticContext diagnosticContext, RequestLoggingOptions options)
{
- readonly RequestDelegate _next;
- readonly DiagnosticContext _diagnosticContext;
- readonly MessageTemplate _messageTemplate;
- readonly Action _enrichDiagnosticContext;
- readonly Func _getLevel;
- readonly ILogger _logger;
- readonly bool _includeQueryInRequestPath;
- static readonly LogEventProperty[] NoProperties = new LogEventProperty[0];
-
- public RequestLoggingMiddleware(RequestDelegate next, DiagnosticContext diagnosticContext, RequestLoggingOptions options)
+ if (options == null) throw new ArgumentNullException(nameof(options));
+ _next = next ?? throw new ArgumentNullException(nameof(next));
+ _diagnosticContext = diagnosticContext ?? throw new ArgumentNullException(nameof(diagnosticContext));
+
+ _getLevel = options.GetLevel;
+ _enrichDiagnosticContext = options.EnrichDiagnosticContext;
+ _messageTemplate = new MessageTemplateParser().Parse(options.MessageTemplate);
+ _logger = options.Logger?.ForContext();
+ _includeQueryInRequestPath = options.IncludeQueryInRequestPath;
+ _getMessageTemplateProperties = options.GetMessageTemplateProperties;
+ }
+
+ // ReSharper disable once UnusedMember.Global
+ public async Task Invoke(HttpContext httpContext)
+ {
+ if (httpContext == null) throw new ArgumentNullException(nameof(httpContext));
+
+ var start = Stopwatch.GetTimestamp();
+
+ var collector = _diagnosticContext.BeginCollection();
+ try
{
- if (options == null) throw new ArgumentNullException(nameof(options));
- _next = next ?? throw new ArgumentNullException(nameof(next));
- _diagnosticContext = diagnosticContext ?? throw new ArgumentNullException(nameof(diagnosticContext));
-
- _getLevel = options.GetLevel;
- _enrichDiagnosticContext = options.EnrichDiagnosticContext;
- _messageTemplate = new MessageTemplateParser().Parse(options.MessageTemplate);
- _logger = options.Logger?.ForContext();
- _includeQueryInRequestPath = options.IncludeQueryInRequestPath;
+ await _next(httpContext);
+ var elapsedMs = GetElapsedMilliseconds(start, Stopwatch.GetTimestamp());
+ var statusCode = httpContext.Response.StatusCode;
+ LogCompletion(httpContext, collector, statusCode, elapsedMs, null);
}
-
- // ReSharper disable once UnusedMember.Global
- public async Task Invoke(HttpContext httpContext)
+ catch (Exception ex)
+ // Never caught, because `LogCompletion()` returns false. This ensures e.g. the developer exception page is still
+ // shown, although it does also mean we see a duplicate "unhandled exception" event from ASP.NET Core.
+ when (LogCompletion(httpContext, collector, 500, GetElapsedMilliseconds(start, Stopwatch.GetTimestamp()), ex))
{
- if (httpContext == null) throw new ArgumentNullException(nameof(httpContext));
-
- var start = Stopwatch.GetTimestamp();
-
- var collector = _diagnosticContext.BeginCollection();
- try
- {
- await _next(httpContext);
- var elapsedMs = GetElapsedMilliseconds(start, Stopwatch.GetTimestamp());
- var statusCode = httpContext.Response.StatusCode;
- LogCompletion(httpContext, collector, statusCode, elapsedMs, null);
- }
- catch (Exception ex)
- // Never caught, because `LogCompletion()` returns false. This ensures e.g. the developer exception page is still
- // shown, although it does also mean we see a duplicate "unhandled exception" event from ASP.NET Core.
- when (LogCompletion(httpContext, collector, 500, GetElapsedMilliseconds(start, Stopwatch.GetTimestamp()), ex))
- {
- }
- finally
- {
- collector.Dispose();
- }
}
-
- bool LogCompletion(HttpContext httpContext, DiagnosticContextCollector collector, int statusCode, double elapsedMs, Exception ex)
+ finally
{
- var logger = _logger ?? Log.ForContext();
- var level = _getLevel(httpContext, elapsedMs, ex);
+ collector.Dispose();
+ }
+ }
- if (!logger.IsEnabled(level)) return false;
+ bool LogCompletion(HttpContext httpContext, DiagnosticContextCollector collector, int statusCode, double elapsedMs, Exception? ex)
+ {
+ var logger = _logger ?? Log.ForContext();
+ var level = _getLevel(httpContext, elapsedMs, ex);
- // Enrich diagnostic context
- _enrichDiagnosticContext?.Invoke(_diagnosticContext, httpContext);
+ if (!logger.IsEnabled(level)) return false;
- if (!collector.TryComplete(out var collectedProperties, out var collectedException))
- collectedProperties = NoProperties;
+ // Enrich diagnostic context
+ _enrichDiagnosticContext?.Invoke(_diagnosticContext, httpContext);
- // Last-in (correctly) wins...
- var properties = collectedProperties.Concat(new[]
- {
- new LogEventProperty("RequestMethod", new ScalarValue(httpContext.Request.Method)),
- new LogEventProperty("RequestPath", new ScalarValue(GetPath(httpContext, _includeQueryInRequestPath))),
- new LogEventProperty("StatusCode", new ScalarValue(statusCode)),
- new LogEventProperty("Elapsed", new ScalarValue(elapsedMs))
- });
+ if (!collector.TryComplete(out var collectedProperties, out var collectedException))
+ collectedProperties = NoProperties;
- var evt = new LogEvent(DateTimeOffset.Now, level, ex ?? collectedException, _messageTemplate, properties);
- logger.Write(evt);
+ // Last-in (correctly) wins...
+ var properties = collectedProperties.Concat(_getMessageTemplateProperties(httpContext, GetPath(httpContext, _includeQueryInRequestPath), elapsedMs, statusCode));
- return false;
- }
+ var evt = new LogEvent(DateTimeOffset.Now, level, ex ?? collectedException, _messageTemplate, properties);
+ logger.Write(evt);
- static double GetElapsedMilliseconds(long start, long stop)
- {
- return (stop - start) * 1000 / (double)Stopwatch.Frequency;
- }
+ return false;
+ }
- static string GetPath(HttpContext httpContext, bool includeQueryInRequestPath)
+ static double GetElapsedMilliseconds(long start, long stop)
+ {
+ return (stop - start) * 1000 / (double)Stopwatch.Frequency;
+ }
+
+ static string GetPath(HttpContext httpContext, bool includeQueryInRequestPath)
+ {
+ /*
+ In some cases, like when running integration tests with WebApplicationFactory
+ the Path returns an empty string instead of null, in that case we can't use
+ ?? as fallback.
+ */
+ var requestPath = includeQueryInRequestPath
+ ? httpContext.Features.Get()?.RawTarget
+ : httpContext.Features.Get()?.Path;
+ if (string.IsNullOrEmpty(requestPath))
{
- /*
- In some cases, like when running integration tests with WebApplicationFactory
- the Path returns an empty string instead of null, in that case we can't use
- ?? as fallback.
- */
- var requestPath = includeQueryInRequestPath
- ? httpContext.Features.Get()?.RawTarget
- : httpContext.Features.Get()?.Path;
- if (string.IsNullOrEmpty(requestPath))
- {
- requestPath = httpContext.Request.Path.ToString();
- }
-
- return requestPath;
+ requestPath = httpContext.Request.Path.ToString();
}
+
+ return requestPath!;
}
-}
+}
\ No newline at end of file
diff --git a/src/Serilog.AspNetCore/AspNetCore/RequestLoggingOptions.cs b/src/Serilog.AspNetCore/AspNetCore/RequestLoggingOptions.cs
index bd6fead..d782e6d 100644
--- a/src/Serilog.AspNetCore/AspNetCore/RequestLoggingOptions.cs
+++ b/src/Serilog.AspNetCore/AspNetCore/RequestLoggingOptions.cs
@@ -14,73 +14,86 @@
using Microsoft.AspNetCore.Http;
using Serilog.Events;
-using System;
// ReSharper disable UnusedAutoPropertyAccessor.Global
-namespace Serilog.AspNetCore
+namespace Serilog.AspNetCore;
+
+///
+/// Contains options for the .
+///
+public class RequestLoggingOptions
{
- ///
- /// Contains options for the .
- ///
- public class RequestLoggingOptions
- {
- const string DefaultRequestCompletionMessageTemplate =
- "HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms";
+ const string DefaultRequestCompletionMessageTemplate =
+ "HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms";
- static LogEventLevel DefaultGetLevel(HttpContext ctx, double _, Exception ex) =>
- ex != null
+ static LogEventLevel DefaultGetLevel(HttpContext ctx, double _, Exception? ex) =>
+ ex != null
+ ? LogEventLevel.Error
+ : ctx.Response.StatusCode > 499
? LogEventLevel.Error
- : ctx.Response.StatusCode > 499
- ? LogEventLevel.Error
- : LogEventLevel.Information;
+ : LogEventLevel.Information;
- ///
- /// Gets or sets the message template. The default value is
- /// "HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms". The
- /// template can contain any of the placeholders from the default template, names of properties
- /// added by ASP.NET Core, and names of properties added to the .
- ///
- ///
- /// The message template.
- ///
- public string MessageTemplate { get; set; }
+ static IEnumerable DefaultGetMessageTemplateProperties(HttpContext httpContext, string requestPath, double elapsedMs, int statusCode) =>
+ new[]
+ {
+ new LogEventProperty("RequestMethod", new ScalarValue(httpContext.Request.Method)),
+ new LogEventProperty("RequestPath", new ScalarValue(requestPath)),
+ new LogEventProperty("StatusCode", new ScalarValue(statusCode)),
+ new LogEventProperty("Elapsed", new ScalarValue(elapsedMs))
+ };
- ///
- /// A function returning the based on the , the number of
- /// elapsed milliseconds required for handling the request, and an if one was thrown.
- /// The default behavior returns when the response status code is greater than 499 or if the
- /// is not null.
- ///
- ///
- /// A function returning the .
- ///
- public Func GetLevel { get; set; }
+ ///
+ /// Gets or sets the message template. The default value is
+ /// "HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms". The
+ /// template can contain any of the placeholders from the default template, names of properties
+ /// added by ASP.NET Core, and names of properties added to the .
+ ///
+ ///
+ /// The message template.
+ ///
+ public string MessageTemplate { get; set; }
- ///
- /// A callback that can be used to set additional properties on the request completion event.
- ///
- public Action EnrichDiagnosticContext { get; set; }
+ ///
+ /// A function returning the based on the , the number of
+ /// elapsed milliseconds required for handling the request, and an if one was thrown.
+ /// The default behavior returns when the response status code is greater than 499 or if the
+ /// is not null.
+ ///
+ ///
+ /// A function returning the .
+ ///
+ public Func GetLevel { get; set; }
- ///
- /// The logger through which request completion events will be logged. The default is to use the
- /// static class.
- ///
- public ILogger Logger { get; set; }
+ ///
+ /// A callback that can be used to set additional properties on the request completion event.
+ ///
+ public Action? EnrichDiagnosticContext { get; set; }
- ///
- /// Include the full URL query string in the RequestPath property
- /// that is attached to request log events. The default is false.
- ///
- public bool IncludeQueryInRequestPath { get; set; }
+ ///
+ /// The logger through which request completion events will be logged. The default is to use the
+ /// static class.
+ ///
+ public ILogger? Logger { get; set; }
- ///
- /// Constructor
- ///
- public RequestLoggingOptions()
- {
- GetLevel = DefaultGetLevel;
- MessageTemplate = DefaultRequestCompletionMessageTemplate;
- }
+ ///
+ /// Include the full URL query string in the RequestPath property
+ /// that is attached to request log events. The default is false.
+ ///
+ public bool IncludeQueryInRequestPath { get; set; }
+
+ ///
+ /// A function to specify the values of the MessageTemplateProperties.
+ ///
+ public Func> GetMessageTemplateProperties { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ public RequestLoggingOptions()
+ {
+ GetLevel = DefaultGetLevel;
+ MessageTemplate = DefaultRequestCompletionMessageTemplate;
+ GetMessageTemplateProperties = DefaultGetMessageTemplateProperties;
}
-}
+}
\ No newline at end of file
diff --git a/src/Serilog.AspNetCore/AspNetCore/SerilogLoggerFactory.cs b/src/Serilog.AspNetCore/AspNetCore/SerilogLoggerFactory.cs
index b468dea..01b3686 100644
--- a/src/Serilog.AspNetCore/AspNetCore/SerilogLoggerFactory.cs
+++ b/src/Serilog.AspNetCore/AspNetCore/SerilogLoggerFactory.cs
@@ -12,62 +12,60 @@
// 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;
-namespace Serilog.AspNetCore
+namespace Serilog.AspNetCore;
+
+///
+/// Implements so that we can inject Serilog Logger.
+///
+[Obsolete("Replaced with Serilog.Extensions.Logging.SerilogLoggerFactory")]
+[EditorBrowsable(EditorBrowsableState.Never)]
+public class SerilogLoggerFactory : ILoggerFactory
{
+ private readonly SerilogLoggerProvider _provider;
+
///
- /// Implements so that we can inject Serilog Logger.
+ /// Initializes a new instance of the class.
///
- [Obsolete("Replaced with Serilog.Extensions.Logging.SerilogLoggerFactory")]
- [EditorBrowsable(EditorBrowsableState.Never)]
- public class SerilogLoggerFactory : ILoggerFactory
+ /// The Serilog logger; if not supplied, the static will be used.
+ /// When true, dispose when the framework disposes the provider. If the
+ /// logger is not specified but is true, the method will be
+ /// called on the static class instead.
+ public SerilogLoggerFactory(ILogger? logger = null, bool dispose = false)
{
- private 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);
- }
+ _provider = new(logger, dispose);
+ }
- ///
- /// Disposes the provider.
- ///
- public void Dispose()
- {
- _provider.Dispose();
- }
+ ///
+ /// Disposes the provider.
+ ///
+ public void Dispose()
+ {
+ _provider.Dispose();
+ }
- ///
- /// Creates a new instance.
- ///
- /// The category name for messages produced by the logger.
- ///
- /// The .
- ///
- public Microsoft.Extensions.Logging.ILogger CreateLogger(string categoryName)
- {
- return _provider.CreateLogger(categoryName);
- }
+ ///
+ /// Creates a new instance.
+ ///
+ /// The category name for messages produced by the logger.
+ ///
+ /// The .
+ ///
+ public Microsoft.Extensions.Logging.ILogger CreateLogger(string categoryName)
+ {
+ return _provider.CreateLogger(categoryName);
+ }
- ///
- /// Adds an to the logging system.
- ///
- /// The .
- public void AddProvider(ILoggerProvider provider)
- {
- SelfLog.WriteLine("Ignoring added logger provider {0}", provider);
- }
+ ///
+ /// Adds an to the logging system.
+ ///
+ /// The .
+ public void AddProvider(ILoggerProvider provider)
+ {
+ SelfLog.WriteLine("Ignoring added logger provider {0}", provider);
}
-}
+}
\ No newline at end of file
diff --git a/src/Serilog.AspNetCore/Serilog.AspNetCore.csproj b/src/Serilog.AspNetCore/Serilog.AspNetCore.csproj
index 6be5d5f..d468a42 100644
--- a/src/Serilog.AspNetCore/Serilog.AspNetCore.csproj
+++ b/src/Serilog.AspNetCore/Serilog.AspNetCore.csproj
@@ -2,14 +2,10 @@
Serilog support for ASP.NET Core logging
- 6.0.1
+ 6.1.0
Microsoft;Serilog Contributors
netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0
- true
true
- ../../assets/Serilog.snk
- true
- true
serilog;aspnet;aspnetcore
icon.png
https://github.com/serilog/serilog-aspnetcore
diff --git a/src/Serilog.AspNetCore/SerilogApplicationBuilderExtensions.cs b/src/Serilog.AspNetCore/SerilogApplicationBuilderExtensions.cs
index b163fc7..6427a6d 100644
--- a/src/Serilog.AspNetCore/SerilogApplicationBuilderExtensions.cs
+++ b/src/Serilog.AspNetCore/SerilogApplicationBuilderExtensions.cs
@@ -12,67 +12,64 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System;
-
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Serilog.AspNetCore;
-namespace Serilog
+namespace Serilog;
+
+///
+/// Extends with methods for configuring Serilog features.
+///
+public static class SerilogApplicationBuilderExtensions
{
///
- /// Extends with methods for configuring Serilog features.
+ /// Adds middleware for streamlined request logging. Instead of writing HTTP request information
+ /// like method, path, timing, status code and exception details
+ /// in several events, this middleware collects information during the request (including from
+ /// ), and writes a single event at request completion. Add this
+ /// in Startup.cs before any handlers whose activities should be logged.
///
- public static class SerilogApplicationBuilderExtensions
- {
- ///
- /// Adds middleware for streamlined request logging. Instead of writing HTTP request information
- /// like method, path, timing, status code and exception details
- /// in several events, this middleware collects information during the request (including from
- /// ), and writes a single event at request completion. Add this
- /// in Startup.cs before any handlers whose activities should be logged.
- ///
- /// The application builder.
- /// The message template to use when logging request completion
- /// events. The default is
- /// "HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms". The
- /// template can contain any of the placeholders from the default template, names of properties
- /// added by ASP.NET Core, and names of properties added to the .
- ///
- /// The application builder.
- public static IApplicationBuilder UseSerilogRequestLogging(
- this IApplicationBuilder app,
- string messageTemplate)
- => app.UseSerilogRequestLogging(opts => opts.MessageTemplate = messageTemplate);
+ /// The application builder.
+ /// The message template to use when logging request completion
+ /// events. The default is
+ /// "HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms". The
+ /// template can contain any of the placeholders from the default template, names of properties
+ /// added by ASP.NET Core, and names of properties added to the .
+ ///
+ /// The application builder.
+ public static IApplicationBuilder UseSerilogRequestLogging(
+ this IApplicationBuilder app,
+ string messageTemplate)
+ => app.UseSerilogRequestLogging(opts => opts.MessageTemplate = messageTemplate);
- ///
- /// Adds middleware for streamlined request logging. Instead of writing HTTP request information
- /// like method, path, timing, status code and exception details
- /// in several events, this middleware collects information during the request (including from
- /// ), and writes a single event at request completion. Add this
- /// in Startup.cs before any handlers whose activities should be logged.
- ///
- /// The application builder.
- /// A to configure the provided .
- /// The application builder.
- public static IApplicationBuilder UseSerilogRequestLogging(
- this IApplicationBuilder app,
- Action configureOptions = null)
- {
- if (app == null) throw new ArgumentNullException(nameof(app));
+ ///
+ /// Adds middleware for streamlined request logging. Instead of writing HTTP request information
+ /// like method, path, timing, status code and exception details
+ /// in several events, this middleware collects information during the request (including from
+ /// ), and writes a single event at request completion. Add this
+ /// in Startup.cs before any handlers whose activities should be logged.
+ ///
+ /// The application builder.
+ /// A to configure the provided .
+ /// The application builder.
+ public static IApplicationBuilder UseSerilogRequestLogging(
+ this IApplicationBuilder app,
+ Action? configureOptions = null)
+ {
+ if (app == null) throw new ArgumentNullException(nameof(app));
- var opts = app.ApplicationServices.GetService>()?.Value ?? new RequestLoggingOptions();
+ var opts = app.ApplicationServices.GetService>()?.Value ?? new RequestLoggingOptions();
- configureOptions?.Invoke(opts);
+ configureOptions?.Invoke(opts);
- if (opts.MessageTemplate == null)
- throw new ArgumentException($"{nameof(opts.MessageTemplate)} cannot be null.");
- if (opts.GetLevel == null)
- throw new ArgumentException($"{nameof(opts.GetLevel)} cannot be null.");
+ if (opts.MessageTemplate == null)
+ throw new ArgumentException($"{nameof(opts.MessageTemplate)} cannot be null.");
+ if (opts.GetLevel == null)
+ throw new ArgumentException($"{nameof(opts.GetLevel)} cannot be null.");
- return app.UseMiddleware(opts);
- }
+ return app.UseMiddleware(opts);
}
}
\ No newline at end of file
diff --git a/src/Serilog.AspNetCore/SerilogWebHostBuilderExtensions.cs b/src/Serilog.AspNetCore/SerilogWebHostBuilderExtensions.cs
index 7de1bef..a144808 100644
--- a/src/Serilog.AspNetCore/SerilogWebHostBuilderExtensions.cs
+++ b/src/Serilog.AspNetCore/SerilogWebHostBuilderExtensions.cs
@@ -12,154 +12,152 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
using Serilog.Extensions.Hosting;
using Serilog.Extensions.Logging;
-namespace Serilog
+namespace Serilog;
+
+///
+/// Extends with Serilog configuration methods.
+///
+public static class SerilogWebHostBuilderExtensions
{
///
- /// Extends with Serilog configuration methods.
+ /// Sets Serilog as the logging provider.
///
- public static class SerilogWebHostBuilderExtensions
- {
- ///
- /// Sets Serilog as the logging provider.
- ///
- /// The web 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 web host builder.
+ /// The web 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 web host builder.
#if HOSTBUILDER
[Obsolete("Prefer UseSerilog() on IHostBuilder")]
#endif
- public static IWebHostBuilder UseSerilog(
- this IWebHostBuilder builder,
- ILogger logger = null,
- bool dispose = false,
- LoggerProviderCollection providers = null)
- {
- if (builder == null) throw new ArgumentNullException(nameof(builder));
+ public static IWebHostBuilder UseSerilog(
+ this IWebHostBuilder builder,
+ ILogger? logger = null,
+ bool dispose = false,
+ LoggerProviderCollection? providers = null)
+ {
+ if (builder == null) throw new ArgumentNullException(nameof(builder));
- builder.ConfigureServices(collection =>
+ builder.ConfigureServices(collection =>
+ {
+ if (providers != null)
{
- if (providers != null)
+ collection.AddSingleton(services =>
{
- collection.AddSingleton(services =>
- {
- var factory = new SerilogLoggerFactory(logger, dispose, providers);
+ var factory = new SerilogLoggerFactory(logger, dispose, providers);
- foreach (var provider in services.GetServices())
- factory.AddProvider(provider);
+ foreach (var provider in services.GetServices())
+ factory.AddProvider(provider);
- return factory;
- });
- }
- else
- {
- collection.AddSingleton(services => new SerilogLoggerFactory(logger, dispose));
- }
+ return factory;
+ });
+ }
+ else
+ {
+ collection.AddSingleton(_ => new SerilogLoggerFactory(logger, dispose));
+ }
- ConfigureServices(collection, logger);
- });
+ ConfigureServices(collection, logger);
+ });
- return builder;
- }
+ 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 web 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 web host 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 web 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 web host builder.
#if HOSTBUILDER
[Obsolete("Prefer UseSerilog() on IHostBuilder")]
#endif
- public static IWebHostBuilder UseSerilog(
- this IWebHostBuilder builder,
- Action configureLogger,
- bool preserveStaticLogger = false,
- bool writeToProviders = false)
+ public static IWebHostBuilder UseSerilog(
+ this IWebHostBuilder 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) =>
{
- if (builder == null) throw new ArgumentNullException(nameof(builder));
- if (configureLogger == null) throw new ArgumentNullException(nameof(configureLogger));
+ var loggerConfiguration = new LoggerConfiguration();
- builder.ConfigureServices((context, collection) =>
+ LoggerProviderCollection? loggerProviders = null;
+ if (writeToProviders)
{
- var loggerConfiguration = new LoggerConfiguration();
+ loggerProviders = new();
+ loggerConfiguration.WriteTo.Providers(loggerProviders);
+ }
- LoggerProviderCollection loggerProviders = null;
- if (writeToProviders)
- {
- loggerProviders = new LoggerProviderCollection();
- loggerConfiguration.WriteTo.Providers(loggerProviders);
- }
+ configureLogger(context, loggerConfiguration);
+ var logger = loggerConfiguration.CreateLogger();
- configureLogger(context, loggerConfiguration);
- var logger = loggerConfiguration.CreateLogger();
-
- ILogger registeredLogger = null;
- if (preserveStaticLogger)
- {
- registeredLogger = logger;
- }
- else
+ 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;
+ }
+
+ collection.AddSingleton(services =>
+ {
+ var factory = new SerilogLoggerFactory(registeredLogger, true, loggerProviders);
+
+ if (writeToProviders)
{
- // 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);
}
- collection.AddSingleton(services =>
- {
- var factory = new SerilogLoggerFactory(registeredLogger, true, loggerProviders);
+ return factory;
+ });
- if (writeToProviders)
- {
- foreach (var provider in services.GetServices())
- factory.AddProvider(provider);
- }
+ ConfigureServices(collection, logger);
+ });
+ return builder;
+ }
- return factory;
- });
+ static void ConfigureServices(IServiceCollection collection, ILogger? logger)
+ {
+ if (collection == null) throw new ArgumentNullException(nameof(collection));
- ConfigureServices(collection, logger);
- });
- return builder;
- }
-
- static void ConfigureServices(IServiceCollection collection, ILogger logger)
+ if (logger != null)
{
- if (collection == null) throw new ArgumentNullException(nameof(collection));
-
- if (logger != null)
- {
- // This won't (and shouldn't) take ownership of the logger.
- collection.AddSingleton(logger);
- }
+ // This won't (and shouldn't) take ownership of the logger.
+ collection.AddSingleton(logger);
+ }
- // Registered to provide two services...
- var diagnosticContext = new DiagnosticContext(logger);
+ // Registered to provide two services...
+ var diagnosticContext = new DiagnosticContext(logger);
- // Consumed by e.g. middleware
- collection.AddSingleton(diagnosticContext);
+ // Consumed by e.g. middleware
+ collection.AddSingleton(diagnosticContext);
- // Consumed by user code
- collection.AddSingleton(diagnosticContext);
- }
+ // Consumed by user code
+ collection.AddSingleton(diagnosticContext);
}
-}
+}
\ No newline at end of file
diff --git a/test/Serilog.AspNetCore.Tests/Serilog.AspNetCore.Tests.csproj b/test/Serilog.AspNetCore.Tests/Serilog.AspNetCore.Tests.csproj
index c229883..240288c 100644
--- a/test/Serilog.AspNetCore.Tests/Serilog.AspNetCore.Tests.csproj
+++ b/test/Serilog.AspNetCore.Tests/Serilog.AspNetCore.Tests.csproj
@@ -1,11 +1,7 @@
- netcoreapp3.1;net5.0
- Serilog.AspNetCore.Tests
- ../../assets/Serilog.snk
- true
- true
+ netcoreapp3.1;net6.0
true
@@ -23,7 +19,7 @@
-
+
diff --git a/test/Serilog.AspNetCore.Tests/SerilogWebHostBuilderExtensionsTests.cs b/test/Serilog.AspNetCore.Tests/SerilogWebHostBuilderExtensionsTests.cs
index 0193263..842c2d1 100644
--- a/test/Serilog.AspNetCore.Tests/SerilogWebHostBuilderExtensionsTests.cs
+++ b/test/Serilog.AspNetCore.Tests/SerilogWebHostBuilderExtensionsTests.cs
@@ -1,9 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-using System;
-using System.Linq;
-using System.Threading.Tasks;
using Xunit;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
@@ -12,142 +9,174 @@
using Microsoft.AspNetCore.Http;
using Serilog.Filters;
using Serilog.AspNetCore.Tests.Support;
+using Serilog.Events;
// Newer frameworks provide IHostBuilder
#pragma warning disable CS0618
-namespace Serilog.AspNetCore.Tests
+namespace Serilog.AspNetCore.Tests;
+
+public class SerilogWebHostBuilderExtensionsTests : IClassFixture
{
- public class SerilogWebHostBuilderExtensionsTests : IClassFixture
+ readonly SerilogWebApplicationFactory _web;
+
+ public SerilogWebHostBuilderExtensionsTests(SerilogWebApplicationFactory web)
{
- readonly SerilogWebApplicationFactory _web;
+ _web = web;
+ }
- public SerilogWebHostBuilderExtensionsTests(SerilogWebApplicationFactory web)
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public async Task DisposeShouldBeHandled(bool dispose)
+ {
+ var logger = new DisposeTrackingLogger();
+ using (var web = Setup(logger, dispose))
{
- _web = web;
+ await web.CreateClient().GetAsync("/");
}
- [Theory]
- [InlineData(true)]
- [InlineData(false)]
- public async Task DisposeShouldBeHandled(bool dispose)
+ Assert.Equal(dispose, logger.IsDisposed);
+ }
+
+ [Fact]
+ public async Task RequestLoggingMiddlewareShouldEnrich()
+ {
+ var (sink, web) = Setup(options =>
{
- var logger = new DisposeTrackingLogger();
- using (var web = Setup(logger, dispose))
+ options.EnrichDiagnosticContext += (diagnosticContext, _) =>
{
- await web.CreateClient().GetAsync("/");
- }
+ diagnosticContext.Set("SomeInteger", 42);
+ };
+ });
- Assert.Equal(dispose, logger.IsDisposed);
- }
+ await web.CreateClient().GetAsync("/resource");
+
+ Assert.NotEmpty(sink.Writes);
+
+ var completionEvent = sink.Writes.First(logEvent => Matching.FromSource()(logEvent));
- [Fact]
- public async Task RequestLoggingMiddlewareShouldEnrich()
+ Assert.Equal(42, completionEvent.Properties["SomeInteger"].LiteralValue());
+ Assert.Equal("string", completionEvent.Properties["SomeString"].LiteralValue());
+ Assert.Equal("/resource", completionEvent.Properties["RequestPath"].LiteralValue());
+ Assert.Equal(200, completionEvent.Properties["StatusCode"].LiteralValue());
+ Assert.Equal("GET", completionEvent.Properties["RequestMethod"].LiteralValue());
+ Assert.True(completionEvent.Properties.ContainsKey("Elapsed"));
+ }
+
+ [Fact]
+ public async Task RequestLoggingMiddlewareShouldEnrichWithCustomisedProperties()
+ {
+ var (sink, web) = Setup(options =>
{
- var (sink, web) = Setup(options =>
- {
- options.EnrichDiagnosticContext += (diagnosticContext, httpContext) =>
+ options.MessageTemplate = "HTTP {RequestMethod} responded {Status} in {ElapsedMilliseconds:0.0000} ms";
+ options.GetMessageTemplateProperties = (ctx, _, elapsedMs, status) =>
+ new[]
{
- diagnosticContext.Set("SomeInteger", 42);
+ new LogEventProperty("RequestMethod", new ScalarValue(ctx.Request.Method)),
+ new LogEventProperty("Status", new ScalarValue(status)),
+ new LogEventProperty("ElapsedMilliseconds", new ScalarValue(elapsedMs))
};
- });
+ });
- await web.CreateClient().GetAsync("/resource");
+ await web.CreateClient().GetAsync("/resource");
- Assert.NotEmpty(sink.Writes);
+ Assert.NotEmpty(sink.Writes);
- var completionEvent = sink.Writes.First(logEvent => Matching.FromSource()(logEvent));
+ var completionEvent = sink.Writes.First(logEvent => Matching.FromSource()(logEvent));
- Assert.Equal(42, completionEvent.Properties["SomeInteger"].LiteralValue());
- Assert.Equal("string", completionEvent.Properties["SomeString"].LiteralValue());
- Assert.Equal("/resource", completionEvent.Properties["RequestPath"].LiteralValue());
- Assert.Equal(200, completionEvent.Properties["StatusCode"].LiteralValue());
- Assert.Equal("GET", completionEvent.Properties["RequestMethod"].LiteralValue());
- Assert.True(completionEvent.Properties.ContainsKey("Elapsed"));
- }
+ Assert.Equal("string", completionEvent.Properties["SomeString"].LiteralValue());
+ Assert.Equal(200, completionEvent.Properties["Status"].LiteralValue());
+ Assert.Equal("GET", completionEvent.Properties["RequestMethod"].LiteralValue());
+ Assert.True(completionEvent.Properties.ContainsKey("ElapsedMilliseconds"));
+ Assert.False(completionEvent.Properties.ContainsKey("Elapsed"));
+ }
- [Fact]
- public async Task RequestLoggingMiddlewareShouldEnrichWithCollectedExceptionIfNoUnhandledException()
+ [Fact]
+ public async Task RequestLoggingMiddlewareShouldEnrichWithCollectedExceptionIfNoUnhandledException()
+ {
+ var diagnosticContextException = new Exception("Exception set in diagnostic context");
+ var (sink, web) = Setup(options =>
{
- var diagnosticContextException = new Exception("Exception set in diagnostic context");
- var (sink, web) = Setup(options =>
+ options.EnrichDiagnosticContext += (diagnosticContext, _) =>
{
- options.EnrichDiagnosticContext += (diagnosticContext, _) =>
- {
- diagnosticContext.SetException(diagnosticContextException);
- };
- });
+ diagnosticContext.SetException(diagnosticContextException);
+ };
+ });
- await web.CreateClient().GetAsync("/resource");
+ await web.CreateClient().GetAsync("/resource");
- var completionEvent = sink.Writes.First(logEvent => Matching.FromSource()(logEvent));
+ var completionEvent = sink.Writes.First(logEvent => Matching.FromSource()(logEvent));
- Assert.Same(diagnosticContextException, completionEvent.Exception);
- }
+ Assert.Same(diagnosticContextException, completionEvent.Exception);
+ }
- [Theory]
- [InlineData(false)]
- [InlineData(true)]
- public async Task RequestLoggingMiddlewareShouldEnrichWithUnhandledExceptionEvenIfExceptionIsSetInDiagnosticContext(bool setExceptionInDiagnosticContext)
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public async Task RequestLoggingMiddlewareShouldEnrichWithUnhandledExceptionEvenIfExceptionIsSetInDiagnosticContext(bool setExceptionInDiagnosticContext)
+ {
+ var diagnosticContextException = new Exception("Exception set in diagnostic context");
+ var unhandledException = new Exception("Unhandled exception thrown in API action");
+ var (sink, web) = Setup(options =>
{
- var diagnosticContextException = new Exception("Exception set in diagnostic context");
- var unhandledException = new Exception("Unhandled exception thrown in API action");
- var (sink, web) = Setup(options =>
+ options.EnrichDiagnosticContext += (diagnosticContext, _) =>
{
- options.EnrichDiagnosticContext += (diagnosticContext, _) =>
- {
- if (setExceptionInDiagnosticContext)
- diagnosticContext.SetException(diagnosticContextException);
- };
- }, actionCallback: _ => throw unhandledException);
+ if (setExceptionInDiagnosticContext)
+ diagnosticContext.SetException(diagnosticContextException);
+ };
+ }, actionCallback: _ => throw unhandledException);
- Func act = () => web.CreateClient().GetAsync("/resource");
+ Func act = () => web.CreateClient().GetAsync("/resource");
- Exception thrownException = await Assert.ThrowsAsync(act);
- var completionEvent = sink.Writes.First(logEvent => Matching.FromSource()(logEvent));
- Assert.Same(unhandledException, completionEvent.Exception);
- Assert.Same(unhandledException, thrownException);
- }
+ var thrownException = await Assert.ThrowsAsync(act);
+ var completionEvent = sink.Writes.First(logEvent => Matching.FromSource()(logEvent));
+ Assert.Same(unhandledException, completionEvent.Exception);
+ Assert.Same(unhandledException, thrownException);
+ }
- WebApplicationFactory Setup(ILogger logger, bool dispose, Action configureOptions = null,
- Action actionCallback = null)
- {
- var web = _web.WithWebHostBuilder(
- builder => builder
- .ConfigureServices(sc => sc.Configure(options =>
+ WebApplicationFactory Setup(
+ ILogger logger,
+ bool dispose,
+ Action? configureOptions = null,
+ Action? actionCallback = null)
+ {
+ var web = _web.WithWebHostBuilder(
+ builder => builder
+ .ConfigureServices(sc => sc.Configure(options =>
+ {
+ options.Logger = logger;
+ options.EnrichDiagnosticContext += (diagnosticContext, _) =>
{
- options.Logger = logger;
- options.EnrichDiagnosticContext += (diagnosticContext, httpContext) =>
- {
- diagnosticContext.Set("SomeString", "string");
- };
- }))
- .Configure(app =>
+ diagnosticContext.Set("SomeString", "string");
+ };
+ }))
+ .Configure(app =>
+ {
+ app.UseSerilogRequestLogging(configureOptions);
+ app.Run(ctx =>
{
- app.UseSerilogRequestLogging(configureOptions);
- app.Run(ctx =>
- {
- actionCallback?.Invoke(ctx);
- return Task.CompletedTask;
- }); // 200 OK
- })
- .UseSerilog(logger, dispose));
-
- return web;
- }
+ actionCallback?.Invoke(ctx);
+ return Task.CompletedTask;
+ }); // 200 OK
+ })
+ .UseSerilog(logger, dispose));
- (SerilogSink, WebApplicationFactory) Setup(Action configureOptions = null,
- Action actionCallback = null)
- {
- var sink = new SerilogSink();
- var logger = new LoggerConfiguration()
- .Enrich.FromLogContext()
- .WriteTo.Sink(sink)
- .CreateLogger();
+ return web;
+ }
+
+ (SerilogSink, WebApplicationFactory) Setup(
+ Action? configureOptions = null,
+ Action? actionCallback = null)
+ {
+ var sink = new SerilogSink();
+ var logger = new LoggerConfiguration()
+ .Enrich.FromLogContext()
+ .WriteTo.Sink(sink)
+ .CreateLogger();
- var web = Setup(logger, true, configureOptions, actionCallback);
+ var web = Setup(logger, true, configureOptions, actionCallback);
- return (sink, web);
- }
+ return (sink, web);
}
-}
+}
\ No newline at end of file
diff --git a/test/Serilog.AspNetCore.Tests/Support/DisposeTrackingLogger.cs b/test/Serilog.AspNetCore.Tests/Support/DisposeTrackingLogger.cs
index 70d3ef0..a441089 100644
--- a/test/Serilog.AspNetCore.Tests/Support/DisposeTrackingLogger.cs
+++ b/test/Serilog.AspNetCore.Tests/Support/DisposeTrackingLogger.cs
@@ -1,354 +1,354 @@
-using System;
-using System.Collections.Generic;
-using Serilog.Core;
+using Serilog.Core;
using Serilog.Events;
-namespace Serilog.AspNetCore.Tests.Support
+namespace Serilog.AspNetCore.Tests.Support;
+
+public class DisposeTrackingLogger : ILogger, IDisposable
{
- public class DisposeTrackingLogger : ILogger, IDisposable
- {
- public bool IsDisposed { get; set; }
-
- public ILogger ForContext(ILogEventEnricher enricher)
- {
- return new LoggerConfiguration().CreateLogger();
- }
-
- public ILogger ForContext(IEnumerable enrichers)
- {
- return new LoggerConfiguration().CreateLogger();
- }
-
- public ILogger ForContext(string propertyName, object value, bool destructureObjects = false)
- {
- return new LoggerConfiguration().CreateLogger();
- }
-
- public ILogger ForContext()
- {
- return new LoggerConfiguration().CreateLogger();
- }
-
- public ILogger ForContext(Type source)
- {
- return new LoggerConfiguration().CreateLogger();
- }
-
- public void Write(LogEvent logEvent)
- {
- }
-
- public void Write(LogEventLevel level, string messageTemplate)
- {
- }
-
- public void Write(LogEventLevel level, string messageTemplate, T propertyValue)
- {
- }
-
- public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
- {
- }
-
- public void Write(LogEventLevel level, string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Write(LogEventLevel level, Exception exception, string messageTemplate)
- {
- }
-
- public void Write(LogEventLevel level, Exception exception, string messageTemplate, T propertyValue)
- {
- }
-
- public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0,
- T1 propertyValue1)
- {
- }
-
- public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0,
- T1 propertyValue1, T2 propertyValue2)
- {
- }
-
- public void Write(LogEventLevel level, Exception exception, string messageTemplate, params object[] propertyValues)
- {
- }
-
- public bool IsEnabled(LogEventLevel level)
- {
- return false;
- }
-
- public void Verbose(string messageTemplate)
- {
- }
-
- public void Verbose(string messageTemplate, T propertyValue)
- {
- }
-
- public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
- {
- }
-
- public void Verbose(string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Verbose(Exception exception, string messageTemplate)
- {
- }
-
- public void Verbose(Exception exception, string messageTemplate, T propertyValue)
- {
- }
-
- public void Verbose(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Verbose(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
- {
- }
-
- public void Verbose(Exception exception, string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Debug(string messageTemplate)
- {
- }
-
- public void Debug(string messageTemplate, T propertyValue)
- {
- }
-
- public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
- {
- }
-
- public void Debug(string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Debug(Exception exception, string messageTemplate)
- {
- }
-
- public void Debug(Exception exception, string messageTemplate, T propertyValue)
- {
- }
-
- public void Debug(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Debug(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
- {
- }
-
- public void Debug(Exception exception, string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Information(string messageTemplate)
- {
- }
-
- public void Information(string messageTemplate, T propertyValue)
- {
- }
-
- public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
- {
- }
-
- public void Information(string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Information(Exception exception, string messageTemplate)
- {
- }
-
- public void Information(Exception exception, string messageTemplate, T propertyValue)
- {
- }
-
- public void Information(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Information(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
- {
- }
-
- public void Information(Exception exception, string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Warning(string messageTemplate)
- {
- }
-
- public void Warning(string messageTemplate, T propertyValue)
- {
- }
-
- public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
- {
- }
-
- public void Warning(string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Warning(Exception exception, string messageTemplate)
- {
- }
-
- public void Warning(Exception exception, string messageTemplate, T propertyValue)
- {
- }
-
- public void Warning(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Warning(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
- {
- }
-
- public void Warning(Exception exception, string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Error(string messageTemplate)
- {
- }
-
- public void Error(string messageTemplate, T propertyValue)
- {
- }
-
- public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
- {
- }
-
- public void Error(string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Error(Exception exception, string messageTemplate)
- {
- }
-
- public void Error(Exception exception, string messageTemplate, T propertyValue)
- {
- }
-
- public void Error(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Error(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
- {
- }
-
- public void Error(Exception exception, string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Fatal(string messageTemplate)
- {
- }
-
- public void Fatal(string messageTemplate, T propertyValue)
- {
- }
-
- public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
- {
- }
-
- public void Fatal(string messageTemplate, params object[] propertyValues)
- {
- }
-
- public void Fatal(Exception exception, string messageTemplate)
- {
- }
-
- public void Fatal(Exception exception, string messageTemplate, T propertyValue)
- {
- }
-
- public void Fatal(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
- {
- }
-
- public void Fatal(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
- T2 propertyValue2)
- {
- }
-
- public void Fatal(Exception exception, string messageTemplate, params object[] propertyValues)
- {
- }
-
- public bool BindMessageTemplate(string messageTemplate, object[] propertyValues, out MessageTemplate parsedTemplate,
- out IEnumerable boundProperties)
- {
- parsedTemplate = null;
- boundProperties = null;
- return false;
- }
-
- public bool BindProperty(string propertyName, object value, bool destructureObjects, out LogEventProperty property)
- {
- property = null;
- return false;
- }
-
- public void Dispose()
- {
- IsDisposed = true;
- }
- }
-}
+ public bool IsDisposed { get; set; }
+
+ public ILogger ForContext(ILogEventEnricher enricher)
+ {
+ return new LoggerConfiguration().CreateLogger();
+ }
+
+ public ILogger ForContext(IEnumerable enrichers)
+ {
+ return new LoggerConfiguration().CreateLogger();
+ }
+
+ public ILogger ForContext(string propertyName, object value, bool destructureObjects = false)
+ {
+ return new LoggerConfiguration().CreateLogger();
+ }
+
+ public ILogger ForContext()
+ {
+ return new LoggerConfiguration().CreateLogger();
+ }
+
+ public ILogger ForContext(Type source)
+ {
+ return new LoggerConfiguration().CreateLogger();
+ }
+
+ public void Write(LogEvent logEvent)
+ {
+ }
+
+ public void Write(LogEventLevel level, string messageTemplate)
+ {
+ }
+
+ public void Write(LogEventLevel level, string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ }
+
+ public void Write(LogEventLevel level, string messageTemplate, params object[] propertyValues)
+ {
+ }
+
+ public void Write(LogEventLevel level, Exception exception, string messageTemplate)
+ {
+ }
+
+ public void Write(LogEventLevel level, Exception exception, string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0,
+ T1 propertyValue1)
+ {
+ }
+
+ public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0,
+ T1 propertyValue1, T2 propertyValue2)
+ {
+ }
+
+ public void Write(LogEventLevel level, Exception exception, string messageTemplate, params object[] propertyValues)
+ {
+ }
+
+ public bool IsEnabled(LogEventLevel level)
+ {
+ return false;
+ }
+
+ public void Verbose(string messageTemplate)
+ {
+ }
+
+ public void Verbose(string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ {
+ }
+
+ public void Verbose(string messageTemplate, params object[] propertyValues)
+ {
+ }
+
+ public void Verbose(Exception exception, string messageTemplate)
+ {
+ }
+
+ public void Verbose(Exception exception, string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Verbose(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Verbose(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ }
+
+ public void Verbose(Exception exception, string messageTemplate, params object[] propertyValues)
+ {
+ }
+
+ public void Debug(string messageTemplate)
+ {
+ }
+
+ public void Debug(string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ {
+ }
+
+ public void Debug(string messageTemplate, params object[] propertyValues)
+ {
+ }
+
+ public void Debug(Exception exception, string messageTemplate)
+ {
+ }
+
+ public void Debug(Exception exception, string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Debug(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Debug(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ }
+
+ public void Debug(Exception exception, string messageTemplate, params object[] propertyValues)
+ {
+ }
+
+ public void Information(string messageTemplate)
+ {
+ }
+
+ public void Information(string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ {
+ }
+
+ public void Information(string messageTemplate, params object[] propertyValues)
+ {
+ }
+
+ public void Information(Exception exception, string messageTemplate)
+ {
+ }
+
+ public void Information(Exception exception, string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Information(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Information(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ }
+
+ public void Information(Exception exception, string messageTemplate, params object[] propertyValues)
+ {
+ }
+
+ public void Warning(string messageTemplate)
+ {
+ }
+
+ public void Warning(string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ {
+ }
+
+ public void Warning(string messageTemplate, params object[] propertyValues)
+ {
+ }
+
+ public void Warning(Exception exception, string messageTemplate)
+ {
+ }
+
+ public void Warning(Exception exception, string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Warning(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Warning(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ }
+
+ public void Warning(Exception exception, string messageTemplate, params object[] propertyValues)
+ {
+ }
+
+ public void Error(string messageTemplate)
+ {
+ }
+
+ public void Error(string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ {
+ }
+
+ public void Error(string messageTemplate, params object[] propertyValues)
+ {
+ }
+
+ public void Error(Exception exception, string messageTemplate)
+ {
+ }
+
+ public void Error(Exception exception, string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Error(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Error(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ }
+
+ public void Error(Exception exception, string messageTemplate, params object[] propertyValues)
+ {
+ }
+
+ public void Fatal(string messageTemplate)
+ {
+ }
+
+ public void Fatal(string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
+ {
+ }
+
+ public void Fatal(string messageTemplate, params object[] propertyValues)
+ {
+ }
+
+ public void Fatal(Exception exception, string messageTemplate)
+ {
+ }
+
+ public void Fatal(Exception exception, string messageTemplate, T propertyValue)
+ {
+ }
+
+ public void Fatal(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
+ {
+ }
+
+ public void Fatal(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1,
+ T2 propertyValue2)
+ {
+ }
+
+ public void Fatal(Exception exception, string messageTemplate, params object[] propertyValues)
+ {
+ }
+
+ public bool BindMessageTemplate(
+ string messageTemplate,
+ object[] propertyValues,
+ out MessageTemplate? parsedTemplate,
+ out IEnumerable? boundProperties)
+ {
+ parsedTemplate = null;
+ boundProperties = null;
+ return false;
+ }
+
+ public bool BindProperty(string propertyName, object value, bool destructureObjects, out LogEventProperty? property)
+ {
+ property = null;
+ return false;
+ }
+
+ public void Dispose()
+ {
+ IsDisposed = true;
+ }
+}
\ No newline at end of file
diff --git a/test/Serilog.AspNetCore.Tests/Support/Extensions.cs b/test/Serilog.AspNetCore.Tests/Support/Extensions.cs
index 54e6a1f..78ac692 100644
--- a/test/Serilog.AspNetCore.Tests/Support/Extensions.cs
+++ b/test/Serilog.AspNetCore.Tests/Support/Extensions.cs
@@ -1,12 +1,11 @@
using Serilog.Events;
-namespace Serilog.AspNetCore.Tests.Support
+namespace Serilog.AspNetCore.Tests.Support;
+
+public static class Extensions
{
- public static class Extensions
+ public static object LiteralValue(this LogEventPropertyValue @this)
{
- public static object LiteralValue(this LogEventPropertyValue @this)
- {
- return ((ScalarValue)@this).Value;
- }
+ return ((ScalarValue)@this).Value;
}
-}
+}
\ No newline at end of file
diff --git a/test/Serilog.AspNetCore.Tests/Support/SerilogSink.cs b/test/Serilog.AspNetCore.Tests/Support/SerilogSink.cs
index 5af3d36..62e5966 100644
--- a/test/Serilog.AspNetCore.Tests/Support/SerilogSink.cs
+++ b/test/Serilog.AspNetCore.Tests/Support/SerilogSink.cs
@@ -1,19 +1,17 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-using System.Collections.Generic;
using Serilog.Core;
using Serilog.Events;
-namespace Serilog.AspNetCore.Tests.Support
+namespace Serilog.AspNetCore.Tests.Support;
+
+public class SerilogSink : ILogEventSink
{
- public class SerilogSink : ILogEventSink
- {
- public List Writes { get; set; } = new List();
+ public List Writes { get; set; } = new();
- public void Emit(LogEvent logEvent)
- {
- Writes.Add(logEvent);
- }
+ public void Emit(LogEvent logEvent)
+ {
+ Writes.Add(logEvent);
}
}
\ No newline at end of file
diff --git a/test/Serilog.AspNetCore.Tests/Support/SerilogWebApplicationFactory.cs b/test/Serilog.AspNetCore.Tests/Support/SerilogWebApplicationFactory.cs
index ac6a881..f4fe961 100644
--- a/test/Serilog.AspNetCore.Tests/Support/SerilogWebApplicationFactory.cs
+++ b/test/Serilog.AspNetCore.Tests/Support/SerilogWebApplicationFactory.cs
@@ -1,14 +1,13 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
-namespace Serilog.AspNetCore.Tests.Support
-{
- // ReSharper disable once ClassNeverInstantiated.Global
- public class SerilogWebApplicationFactory : WebApplicationFactory
- {
- protected override IWebHostBuilder CreateWebHostBuilder() => new WebHostBuilder().UseStartup();
- protected override void ConfigureWebHost(IWebHostBuilder builder) => builder.UseContentRoot(".");
- }
+namespace Serilog.AspNetCore.Tests.Support;
- public class TestStartup { }
+// ReSharper disable once ClassNeverInstantiated.Global
+public class SerilogWebApplicationFactory : WebApplicationFactory
+{
+ protected override IWebHostBuilder CreateWebHostBuilder() => new WebHostBuilder().UseStartup();
+ protected override void ConfigureWebHost(IWebHostBuilder builder) => builder.UseContentRoot(".");
}
+
+public class TestStartup { }
\ No newline at end of file