From 3c8db64bf709c1a2f43536e1bc6f940f4675aa68 Mon Sep 17 00:00:00 2001 From: Leonid Tsarev Date: Wed, 14 Aug 2024 14:31:06 +0300 Subject: [PATCH] Improve log and errors (#2747) * Rename SerilogHelper to SerilogWebRequestHelper * Move LoggedUser property to every log (instead of just WebRequestLogging) * Add ProjectId to logs * Improve naming on error page --- .../Controllers/ErrorPageController.cs | 4 ++-- .../DiscoverFilters/DiscoverProjectMiddleware.cs | 13 ++++++------- .../Infrastructure/Logging/LoggedUserEnricher.cs | 16 ++++++++++++++++ .../Infrastructure/Logging/SerilogExtensions.cs | 1 + ...rilogHelper.cs => SerilogWebRequestHelper.cs} | 12 +----------- src/JoinRpg.Portal/Models/ErrorViewModel.cs | 6 ++---- src/JoinRpg.Portal/Program.cs | 2 +- src/JoinRpg.Portal/Startup.cs | 4 ++-- src/JoinRpg.Portal/Views/Shared/Error.cshtml | 9 +++------ 9 files changed, 34 insertions(+), 33 deletions(-) create mode 100644 src/JoinRpg.Portal/Infrastructure/Logging/LoggedUserEnricher.cs rename src/JoinRpg.Portal/Infrastructure/Logging/{SerilogHelper.cs => SerilogWebRequestHelper.cs} (84%) diff --git a/src/JoinRpg.Portal/Controllers/ErrorPageController.cs b/src/JoinRpg.Portal/Controllers/ErrorPageController.cs index 0e09070cc..91095a176 100644 --- a/src/JoinRpg.Portal/Controllers/ErrorPageController.cs +++ b/src/JoinRpg.Portal/Controllers/ErrorPageController.cs @@ -49,8 +49,8 @@ public IActionResult Error(int statusCode) return View( new ErrorViewModel { - RequestId = Activity.Current?.Id ?? "", - AspNetTrace = HttpContext.TraceIdentifier, + ActivityId = Activity.Current?.Id, + RequestId = HttpContext.TraceIdentifier, Path = feature?.RawTarget ?? "NO PATH", } ); diff --git a/src/JoinRpg.Portal/Infrastructure/DiscoverFilters/DiscoverProjectMiddleware.cs b/src/JoinRpg.Portal/Infrastructure/DiscoverFilters/DiscoverProjectMiddleware.cs index 457787824..4b1b0c8c4 100644 --- a/src/JoinRpg.Portal/Infrastructure/DiscoverFilters/DiscoverProjectMiddleware.cs +++ b/src/JoinRpg.Portal/Infrastructure/DiscoverFilters/DiscoverProjectMiddleware.cs @@ -1,3 +1,5 @@ +using Serilog.Context; + namespace JoinRpg.Portal.Infrastructure.DiscoverFilters; /// @@ -12,15 +14,12 @@ public class DiscoverProjectMiddleware /// public async Task InvokeAsync(HttpContext context) { - var httpContextItems = context.Items; + HttpRequest request = context.Request; - if (context.Request.Path.TryExtractFromPath() is int projectIdFromPath) - { - httpContextItems[Constants.ProjectIdName] = projectIdFromPath; - } - else if (context.Request.Query.TryExtractFromQuery() is int projectIdFromQuery) + if ((request.Path.TryExtractFromPath() ?? request.Query.TryExtractFromQuery()) is int projectId) { - httpContextItems[Constants.ProjectIdName] = projectIdFromQuery; + context.Items[Constants.ProjectIdName] = projectId; + _ = LogContext.PushProperty(Constants.ProjectIdName, projectId); } await nextDelegate(context); diff --git a/src/JoinRpg.Portal/Infrastructure/Logging/LoggedUserEnricher.cs b/src/JoinRpg.Portal/Infrastructure/Logging/LoggedUserEnricher.cs new file mode 100644 index 000000000..122388375 --- /dev/null +++ b/src/JoinRpg.Portal/Infrastructure/Logging/LoggedUserEnricher.cs @@ -0,0 +1,16 @@ +using System.Security.Claims; +using Serilog.Core; +using Serilog.Events; + +namespace JoinRpg.Portal.Infrastructure.Logging; + +internal class LoggedUserEnricher(IHttpContextAccessor httpContextAccessor) : ILogEventEnricher +{ + public LoggedUserEnricher() : this(new HttpContextAccessor()) { } + public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) + { + logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty( + "LoggedUser", httpContextAccessor.HttpContext?.User.FindFirst(ClaimTypes.Email)?.Value)); + } +} + diff --git a/src/JoinRpg.Portal/Infrastructure/Logging/SerilogExtensions.cs b/src/JoinRpg.Portal/Infrastructure/Logging/SerilogExtensions.cs index 45e0822b7..9a2530ca6 100644 --- a/src/JoinRpg.Portal/Infrastructure/Logging/SerilogExtensions.cs +++ b/src/JoinRpg.Portal/Infrastructure/Logging/SerilogExtensions.cs @@ -22,6 +22,7 @@ public static void ConfigureLogger(this LoggerConfiguration loggerConfiguration, .Enrich.FromLogContext() .Enrich.WithMachineName() .Enrich.With() + .Enrich.With() .Enrich.WithProperty("AppName", "JoinRpg.Portal"); foreach (var (@namespace, logLevel) in serilogOptions.LogLevel) diff --git a/src/JoinRpg.Portal/Infrastructure/Logging/SerilogHelper.cs b/src/JoinRpg.Portal/Infrastructure/Logging/SerilogWebRequestHelper.cs similarity index 84% rename from src/JoinRpg.Portal/Infrastructure/Logging/SerilogHelper.cs rename to src/JoinRpg.Portal/Infrastructure/Logging/SerilogWebRequestHelper.cs index 09436bab8..5dabea312 100644 --- a/src/JoinRpg.Portal/Infrastructure/Logging/SerilogHelper.cs +++ b/src/JoinRpg.Portal/Infrastructure/Logging/SerilogWebRequestHelper.cs @@ -1,10 +1,9 @@ -using System.Security.Claims; using Serilog; using Serilog.Events; namespace JoinRpg.Portal.Infrastructure.Logging; -public static class SerilogHelper +public static class SerilogWebRequestHelper { public static void EnrichFromRequest(IDiagnosticContext diagnosticContext, HttpContext httpContext) { @@ -30,15 +29,6 @@ public static void EnrichFromRequest(IDiagnosticContext diagnosticContext, HttpC { diagnosticContext.Set("EndpointName", endpoint.DisplayName); } - - if (httpContext.User.Identity?.IsAuthenticated == true) - { - diagnosticContext.Set("LoggedUser", httpContext.User.FindFirst(ClaimTypes.Email)!.Value); - } - else - { - diagnosticContext.Set("LoggedUser", "null"); - } } private static bool IsHealthCheckEndpoint(HttpContext ctx) { diff --git a/src/JoinRpg.Portal/Models/ErrorViewModel.cs b/src/JoinRpg.Portal/Models/ErrorViewModel.cs index 3154ba70d..3ec3c5031 100644 --- a/src/JoinRpg.Portal/Models/ErrorViewModel.cs +++ b/src/JoinRpg.Portal/Models/ErrorViewModel.cs @@ -2,11 +2,9 @@ namespace JoinRpg.Portal.Models; public class ErrorViewModel { - public required string RequestId { get; set; } - - public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); + public required string? ActivityId { get; set; } public required string Path { get; set; } - public required string AspNetTrace { get; set; } + public required string RequestId { get; set; } } diff --git a/src/JoinRpg.Portal/Program.cs b/src/JoinRpg.Portal/Program.cs index 49e7a128f..dcb998374 100644 --- a/src/JoinRpg.Portal/Program.cs +++ b/src/JoinRpg.Portal/Program.cs @@ -34,7 +34,7 @@ public static IHostBuilder CreateHostBuilder(string[] args) => .UseSerilog((context, _, configuration) => { var loggerOptions = context.Configuration.GetSection("Logging").Get(); - configuration.ConfigureLogger(loggerOptions); + configuration.ConfigureLogger(loggerOptions!); }) .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup()); } diff --git a/src/JoinRpg.Portal/Startup.cs b/src/JoinRpg.Portal/Startup.cs index 8a198b39d..d505b8fa6 100644 --- a/src/JoinRpg.Portal/Startup.cs +++ b/src/JoinRpg.Portal/Startup.cs @@ -180,8 +180,8 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) _ = app.UseSerilogRequestLogging(opts => { - opts.EnrichDiagnosticContext = SerilogHelper.EnrichFromRequest; - opts.GetLevel = SerilogHelper.ExcludeHealthChecks; + opts.EnrichDiagnosticContext = SerilogWebRequestHelper.EnrichFromRequest; + opts.GetLevel = SerilogWebRequestHelper.ExcludeHealthChecks; }); _ = app diff --git a/src/JoinRpg.Portal/Views/Shared/Error.cshtml b/src/JoinRpg.Portal/Views/Shared/Error.cshtml index e11268c55..eb6cf67fb 100644 --- a/src/JoinRpg.Portal/Views/Shared/Error.cshtml +++ b/src/JoinRpg.Portal/Views/Shared/Error.cshtml @@ -10,15 +10,12 @@ Обратитесь в техподдержку!

-@if (Model.ShowRequestId) +@if (Model.ActivityId is not null) { -

RequestId: @Model.RequestId

+

Activity: @Model.ActivityId

} -@if (Model.AspNetTrace is not null) -{ -

TraceIdentifier: @Model.AspNetTrace

-} +

RequestId: @Model.RequestId

@if (!string.IsNullOrWhiteSpace(Model.Path)) {