From 9a226fc042c82cad8eed2b329b2ddffcee483749 Mon Sep 17 00:00:00 2001 From: support Date: Sat, 25 Nov 2023 21:12:20 +0100 Subject: [PATCH] Add new settings EnableContextLoggingMiddleware --- .../Configuration/AppConfig.cs | 5 ++ .../Orders/CaptureCommandHandlerTests.cs | 5 +- .../PartiallyRefundCommandHandlerTests.cs | 5 +- .../Orders/RefundCommandHandlerTests.cs | 5 +- .../Orders/VoidCommandHandlerTests.cs | 5 +- .../BackgroundService/EndAuctionsTaskTests.cs | 4 +- .../QueuedMessagesSendScheduleTaskTests.cs | 2 +- .../Middleware/ContextLoggingMiddleware.cs | 29 +++++++++++ .../Grand.Web.Common/Startup/LoggerStartup.cs | 52 +++++++++++++++++++ src/Web/Grand.Web/App_Data/appsettings.json | 37 ++++++------- src/Web/Grand.Web/Program.cs | 4 +- 11 files changed, 122 insertions(+), 31 deletions(-) create mode 100644 src/Web/Grand.Web.Common/Middleware/ContextLoggingMiddleware.cs create mode 100644 src/Web/Grand.Web.Common/Startup/LoggerStartup.cs diff --git a/src/Core/Grand.Infrastructure/Configuration/AppConfig.cs b/src/Core/Grand.Infrastructure/Configuration/AppConfig.cs index 3687f4331..19353c2df 100644 --- a/src/Core/Grand.Infrastructure/Configuration/AppConfig.cs +++ b/src/Core/Grand.Infrastructure/Configuration/AppConfig.cs @@ -43,6 +43,11 @@ public class AppConfig /// public long? MaxRequestBodySize { get; set; } + /// + /// Gets or sets the value to enable a middleware for logging additional information about CurrentCustomer and store + /// + public bool EnableContextLoggingMiddleware { get; set; } + /// /// Gets or sets a value indicating - (Serilog) use middleware for smarter HTTP request logging /// diff --git a/src/Tests/Grand.Business.Checkout.Tests/Commands/Handlers/Orders/CaptureCommandHandlerTests.cs b/src/Tests/Grand.Business.Checkout.Tests/Commands/Handlers/Orders/CaptureCommandHandlerTests.cs index 903bff86d..b5b74f807 100644 --- a/src/Tests/Grand.Business.Checkout.Tests/Commands/Handlers/Orders/CaptureCommandHandlerTests.cs +++ b/src/Tests/Grand.Business.Checkout.Tests/Commands/Handlers/Orders/CaptureCommandHandlerTests.cs @@ -6,6 +6,7 @@ using Grand.Business.Core.Queries.Checkout.Orders; using Grand.Domain.Payments; using MediatR; +using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -20,13 +21,13 @@ public class CaptureCommandHandlerTests private Mock _paymentTransactionMock; private Mock _orderServiceMock; private Mock _mediatorMock; - private Mock _loggerMock; + private Mock> _loggerMock; [TestInitialize] public void Init() { _mediatorMock = new Mock(); - _loggerMock = new Mock(); + _loggerMock = new Mock>(); _orderServiceMock = new Mock(); _paymentServiceMock = new Mock(); _paymentTransactionMock = new Mock(); diff --git a/src/Tests/Grand.Business.Checkout.Tests/Commands/Handlers/Orders/PartiallyRefundCommandHandlerTests.cs b/src/Tests/Grand.Business.Checkout.Tests/Commands/Handlers/Orders/PartiallyRefundCommandHandlerTests.cs index 7e842271f..ccc2786dd 100644 --- a/src/Tests/Grand.Business.Checkout.Tests/Commands/Handlers/Orders/PartiallyRefundCommandHandlerTests.cs +++ b/src/Tests/Grand.Business.Checkout.Tests/Commands/Handlers/Orders/PartiallyRefundCommandHandlerTests.cs @@ -9,6 +9,7 @@ using Grand.Domain.Orders; using Grand.Domain.Payments; using MediatR; +using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -23,7 +24,7 @@ public class PartiallyRefundCommandHandlerTests private Mock _orderServiceMock; private Mock _mediatorMock; private Mock _messageProviderServiceMock; - private Mock _loggerMock; + private Mock> _loggerMock; [TestInitialize] public void Init() @@ -33,7 +34,7 @@ public void Init() _paymentTransactionMock = new Mock(); _messageProviderServiceMock = new Mock(); _paymentServiceMock = new Mock(); - _loggerMock = new Mock(); + _loggerMock = new Mock>(); _handler = new PartiallyRefundCommandHandler(_paymentServiceMock.Object, _paymentTransactionMock.Object, _mediatorMock.Object, _messageProviderServiceMock.Object, _loggerMock.Object, _orderServiceMock.Object, new Domain.Localization.LanguageSettings()); } diff --git a/src/Tests/Grand.Business.Checkout.Tests/Commands/Handlers/Orders/RefundCommandHandlerTests.cs b/src/Tests/Grand.Business.Checkout.Tests/Commands/Handlers/Orders/RefundCommandHandlerTests.cs index 18247bf25..c30dfd91f 100644 --- a/src/Tests/Grand.Business.Checkout.Tests/Commands/Handlers/Orders/RefundCommandHandlerTests.cs +++ b/src/Tests/Grand.Business.Checkout.Tests/Commands/Handlers/Orders/RefundCommandHandlerTests.cs @@ -9,6 +9,7 @@ using Grand.Domain.Orders; using Grand.Domain.Payments; using MediatR; +using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -23,7 +24,7 @@ public class RefundCommandHandlerTests private Mock _orderServiceMock; private Mock _mediatorMock; private Mock _messageProviderServiceMock; - private Mock _loggerMock; + private Mock> _loggerMock; [TestInitialize] public void Init() @@ -33,7 +34,7 @@ public void Init() _paymentTransactionMock = new Mock(); _messageProviderServiceMock = new Mock(); _paymentServiceMock = new Mock(); - _loggerMock = new Mock(); + _loggerMock = new Mock>(); _handler = new RefundCommandHandler(_mediatorMock.Object, _paymentServiceMock.Object, _paymentTransactionMock.Object, _orderServiceMock.Object, _messageProviderServiceMock.Object, _loggerMock.Object, new Domain.Localization.LanguageSettings()); } diff --git a/src/Tests/Grand.Business.Checkout.Tests/Commands/Handlers/Orders/VoidCommandHandlerTests.cs b/src/Tests/Grand.Business.Checkout.Tests/Commands/Handlers/Orders/VoidCommandHandlerTests.cs index b55f8313c..856538406 100644 --- a/src/Tests/Grand.Business.Checkout.Tests/Commands/Handlers/Orders/VoidCommandHandlerTests.cs +++ b/src/Tests/Grand.Business.Checkout.Tests/Commands/Handlers/Orders/VoidCommandHandlerTests.cs @@ -9,6 +9,7 @@ using Grand.Domain.Orders; using Grand.Domain.Payments; using MediatR; +using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -23,7 +24,7 @@ public class VoidCommandHandlerTests private Mock _orderServiceMock; private Mock _mediatorMock; private Mock _messageProviderServiceMock; - private Mock _loggerMock; + private Mock> _loggerMock; [TestInitialize] public void Init() @@ -33,7 +34,7 @@ public void Init() _paymentTransactionMock = new Mock(); _messageProviderServiceMock = new Mock(); _paymentServiceMock = new Mock(); - _loggerMock = new Mock(); + _loggerMock = new Mock>(); _handler = new VoidCommandHandler( _orderServiceMock.Object, diff --git a/src/Tests/Grand.Business.System.Tests/Services/BackgroundService/EndAuctionsTaskTests.cs b/src/Tests/Grand.Business.System.Tests/Services/BackgroundService/EndAuctionsTaskTests.cs index 97cc040bb..03f653798 100644 --- a/src/Tests/Grand.Business.System.Tests/Services/BackgroundService/EndAuctionsTaskTests.cs +++ b/src/Tests/Grand.Business.System.Tests/Services/BackgroundService/EndAuctionsTaskTests.cs @@ -64,7 +64,7 @@ public async Task Execute_HasWarnings_InvokeExpectedMethos() .ReturnsAsync((new List() { "warning" }, null)); await _task.Execute(); - _loggerMock.Verify(c => c.InsertLog(Domain.Logging.LogLevel.Error, It.IsAny(), It.IsAny(), It.IsAny(), null, null, null), Times.Once); + _loggerMock.Verify(c => c.LogInformation(It.IsAny(), It.IsAny(), It.IsAny(), null, null, null), Times.Once); } [TestMethod] @@ -78,7 +78,7 @@ public async Task Execute_Valid_InvokeExpectedMethos() .ReturnsAsync((new List(), null)); await _task.Execute(); - _loggerMock.Verify(c => c.InsertLog(Domain.Logging.LogLevel.Error, It.IsAny(), It.IsAny(), It.IsAny(), null, null, null), Times.Never); + _loggerMock.Verify(c => c.LogError(It.IsAny(), It.IsAny(), It.IsAny(), null, null, null), Times.Never); _auctionMock.Verify(c => c.UpdateBid(It.IsAny()), Times.Once); _auctionMock.Verify(c => c.UpdateAuctionEnded(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); _messageProviderMock.Verify(c => c.SendAuctionEndedStoreOwnerMessage(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); diff --git a/src/Tests/Grand.Business.System.Tests/Services/BackgroundService/QueuedMessagesSendScheduleTaskTests.cs b/src/Tests/Grand.Business.System.Tests/Services/BackgroundService/QueuedMessagesSendScheduleTaskTests.cs index 14805e5a7..2bf967d4f 100644 --- a/src/Tests/Grand.Business.System.Tests/Services/BackgroundService/QueuedMessagesSendScheduleTaskTests.cs +++ b/src/Tests/Grand.Business.System.Tests/Services/BackgroundService/QueuedMessagesSendScheduleTaskTests.cs @@ -59,7 +59,7 @@ public async Task Execute_ThrowExecption_InovekExpectedMethodsAndInsertLog() It.IsAny(), It.IsAny(), It.IsAny>())).ThrowsAsync(new Exception()); await _task.Execute(); - _loggerMock.Verify(c => c.InsertLog(Domain.Logging.LogLevel.Error, It.IsAny(), It.IsAny(), It.IsAny(), null, null, null), Times.Once); + _loggerMock.Verify(c => c.LogError(It.IsAny(), It.IsAny(), It.IsAny(), null, null, null), Times.Once); _queuedEmailServiceMock.Verify(c => c.UpdateQueuedEmail(It.IsAny()), Times.Once); } } diff --git a/src/Web/Grand.Web.Common/Middleware/ContextLoggingMiddleware.cs b/src/Web/Grand.Web.Common/Middleware/ContextLoggingMiddleware.cs new file mode 100644 index 000000000..4acc34ada --- /dev/null +++ b/src/Web/Grand.Web.Common/Middleware/ContextLoggingMiddleware.cs @@ -0,0 +1,29 @@ +using Grand.Infrastructure; +using Microsoft.ApplicationInsights.DataContracts; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; + +namespace Grand.Web.Common.Middleware; + +public class ContextLoggingMiddleware +{ + private readonly RequestDelegate _next; + + public ContextLoggingMiddleware(RequestDelegate next) + { + _next = next; + } + + public async Task InvokeAsync(HttpContext context) + { + var workContext = context.RequestServices.GetRequiredService(); + + var requestTelemetry = context.Features.Get(); + requestTelemetry.Properties.TryAdd("Customer", workContext?.CurrentCustomer?.Email); + requestTelemetry.Properties.TryAdd("Store", workContext?.CurrentStore?.Name); + requestTelemetry.Properties.TryAdd("Currency", workContext?.WorkingCurrency?.Name); + requestTelemetry.Properties.TryAdd("Language", workContext?.WorkingLanguage?.Name); + + await _next(context); + } +} \ No newline at end of file diff --git a/src/Web/Grand.Web.Common/Startup/LoggerStartup.cs b/src/Web/Grand.Web.Common/Startup/LoggerStartup.cs new file mode 100644 index 000000000..2d2879335 --- /dev/null +++ b/src/Web/Grand.Web.Common/Startup/LoggerStartup.cs @@ -0,0 +1,52 @@ +using Grand.Domain.Data; +using Grand.Infrastructure; +using Grand.Infrastructure.Configuration; +using Grand.Web.Common.Middleware; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +namespace Grand.Web.Common.Startup +{ + /// + /// Represents object for the configuring logger middleware on application startup + /// + public class LoggerStartup : IStartupApplication + { + /// + /// Add and configure any of the middleware + /// + /// Collection of service descriptors + /// Configuration root of the application + public void ConfigureServices(IServiceCollection services, IConfiguration configuration) + { + + } + + /// + /// Configure the using of added middleware + /// + /// Builder for configuring an application's request pipeline + /// WebHostEnvironment + public void Configure(IApplicationBuilder application, IWebHostEnvironment webHostEnvironment) + { + //check whether database is installed + if (!DataSettingsManager.DatabaseIsInstalled()) + return; + + var appConfig = application.ApplicationServices.GetRequiredService(); + + //set context logging + if(appConfig.EnableContextLoggingMiddleware) + application.UseMiddleware(); + } + + /// + /// Gets order of this startup configuration implementation + /// + public int Priority => 501; + public bool BeforeConfigure => false; + + } +} diff --git a/src/Web/Grand.Web/App_Data/appsettings.json b/src/Web/Grand.Web/App_Data/appsettings.json index 3de040396..f4bc6ced6 100644 --- a/src/Web/Grand.Web/App_Data/appsettings.json +++ b/src/Web/Grand.Web/App_Data/appsettings.json @@ -28,7 +28,10 @@ //Gets or sets the maximum allowed size of any request body in bytes //the default value is 30MB "MaxRequestBodySize": null, //max 2147483648 - + + //Gets or sets the value to enable a middleware for logging additional information about CurrentCustomer and CurrentStore + "EnableContextLoggingMiddleware": false, + //(Serilog) Request logging - The package includes middleware for smarter HTTP request logging. "UseSerilogRequestLogging": false }, @@ -133,7 +136,7 @@ "UseResponseCompression": false, //Gets or sets a value indicating whether mini profiler should be displayed in public store (used for debugging) - "DisplayMiniProfilerInPublicStore": true, + "DisplayMiniProfilerInPublicStore": false, //Indicates whether to ignore InstallUrlMiddleware "IgnoreInstallUrlMiddleware": false, @@ -245,26 +248,24 @@ "SystemModel": true }, "UseSwagger": false, - //Settings only for advanced users + "Logging": { + "LogLevel": { + "Default": "Information", + "System": "Information" + } + }, "Serilog": { - "Using": [ "Serilog.Sinks.File" ] - //, - //"MinimumLevel": { - // "Default": "Warning" - // } - //, - //"WriteTo": [ - // { - // "Name": "File", - // "Args": { "path": "logs/log.txt" } - // } - // ] + "Using": [ "Serilog.Sinks.Console" ], + "MinimumLevel": "Information", + "WriteTo": [ + { "Name": "Console" } + ] }, - "ApplicationInsights": { - "Enabled": false, - "ConnectionString": "" + "Enabled": true, + "InstrumentationKey": "b6efc68b-61cd-4463-bd86-c4355532f338", + "EnableAdaptiveSampling": false } //https://docs.microsoft.com/en-us/azure/azure-monitor/app/asp-net-core //The following configuration allows ApplicationInsights to capture diff --git a/src/Web/Grand.Web/Program.cs b/src/Web/Grand.Web/Program.cs index d965f93fc..b463e2b72 100644 --- a/src/Web/Grand.Web/Program.cs +++ b/src/Web/Grand.Web/Program.cs @@ -6,7 +6,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; using Serilog; using StartupBase = Grand.Infrastructure.StartupBase; @@ -18,7 +17,8 @@ options.ValidateOnBuild = false; }); -builder.Logging.AddConsole(); +builder.Services.AddLogging(); + //use serilog builder.Host.UseSerilog();