From 6aed05af06f2feac552ae8292f5a5ed474b10d67 Mon Sep 17 00:00:00 2001 From: sam Date: Wed, 22 May 2024 02:31:05 +0200 Subject: [PATCH] feat(core): add optional SQL query logging --- Foxchat.Chat/Database/ChatContext.cs | 10 +++++++--- Foxchat.Chat/Program.cs | 3 ++- Foxchat.Chat/chat.ini | 11 +++++++--- Foxchat.Core/CoreConfig.cs | 13 ++++++++---- .../Extensions/ServiceCollectionExtensions.cs | 20 ++++++++++--------- Foxchat.Identity/Database/IdentityContext.cs | 14 ++++++++----- Foxchat.Identity/Program.cs | 3 ++- Foxchat.Identity/identity.ini | 13 +++++++----- 8 files changed, 56 insertions(+), 31 deletions(-) diff --git a/Foxchat.Chat/Database/ChatContext.cs b/Foxchat.Chat/Database/ChatContext.cs index efbe8a1..f8ac2a5 100644 --- a/Foxchat.Chat/Database/ChatContext.cs +++ b/Foxchat.Chat/Database/ChatContext.cs @@ -1,6 +1,7 @@ using Foxchat.Chat.Database.Models; using Foxchat.Core; using Foxchat.Core.Database; +using Foxchat.Core.Extensions; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; using Npgsql; @@ -10,6 +11,7 @@ namespace Foxchat.Chat.Database; public class ChatContext : IDatabaseContext { private readonly NpgsqlDataSource _dataSource; + private readonly ILoggerFactory? _loggerFactory; public override DbSet Instance { get; set; } public DbSet IdentityInstances { get; set; } @@ -18,7 +20,7 @@ public class ChatContext : IDatabaseContext public DbSet Channels { get; set; } public DbSet Messages { get; set; } - public ChatContext(InstanceConfig config) + public ChatContext(InstanceConfig config, ILoggerFactory? loggerFactory) { var connString = new NpgsqlConnectionStringBuilder(config.Database.Url) { @@ -29,12 +31,14 @@ public class ChatContext : IDatabaseContext var dataSourceBuilder = new NpgsqlDataSourceBuilder(connString); dataSourceBuilder.UseNodaTime(); _dataSource = dataSourceBuilder.Build(); + _loggerFactory = loggerFactory; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder .UseNpgsql(_dataSource, o => o.UseNodaTime()) - .UseSnakeCaseNamingConvention(); + .UseSnakeCaseNamingConvention() + .UseLoggerFactory(_loggerFactory); protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) { @@ -73,6 +77,6 @@ public class DesignTimeIdentityContextFactory : IDesignTimeDbContextFactory() ?? new(); - return new ChatContext(config); + return new ChatContext(config, null); } } \ No newline at end of file diff --git a/Foxchat.Chat/Program.cs b/Foxchat.Chat/Program.cs index 263167d..fa2bbb6 100644 --- a/Foxchat.Chat/Program.cs +++ b/Foxchat.Chat/Program.cs @@ -4,13 +4,14 @@ using Foxchat.Core; using Foxchat.Chat; using Foxchat.Chat.Database; using Foxchat.Chat.Extensions; +using Foxchat.Core.Extensions; using Newtonsoft.Json; var builder = WebApplication.CreateBuilder(args); var config = builder.AddConfiguration("chat.ini"); -builder.AddSerilog(config.LogEventLevel); +builder.AddSerilog(); await BuildInfo.ReadBuildInfo(); Log.Information("Starting Foxchat.Chat {Version} ({Hash})", BuildInfo.Version, BuildInfo.Hash); diff --git a/Foxchat.Chat/chat.ini b/Foxchat.Chat/chat.ini index 21a32a0..906acdb 100644 --- a/Foxchat.Chat/chat.ini +++ b/Foxchat.Chat/chat.ini @@ -2,9 +2,6 @@ Host = localhost Port = 7610 Domain = chat.fox.localhost -; The level to log things at. Valid settings: Verbose, Debug, Information, Warning, Error, Fatal -LogEventLevel = Debug - [Database] ; The database URL in ADO.NET format. Url = "Host=localhost;Database=foxchat_cs_chat;Username=foxchat;Password=password" @@ -13,3 +10,11 @@ Url = "Host=localhost;Database=foxchat_cs_chat;Username=foxchat;Password=passwor Timeout = 5 ; The maximum number of open connections. Defaults to 50. MaxPoolSize = 500 + +[Logging] +; The level to log things at. Valid settings: Verbose, Debug, Information, Warning, Error, Fatal +LogEventLevel = Debug +; Whether to log SQL queries. +LogQueries = true +; Optional logging to Seq +SeqLogUrl = http://localhost:5341 \ No newline at end of file diff --git a/Foxchat.Core/CoreConfig.cs b/Foxchat.Core/CoreConfig.cs index 40a97b4..236af8a 100644 --- a/Foxchat.Core/CoreConfig.cs +++ b/Foxchat.Core/CoreConfig.cs @@ -11,9 +11,7 @@ public class CoreConfig public string Address => $"{(Secure ? "https" : "http")}://{Host}:{Port}"; - public LogEventLevel LogEventLevel { get; set; } = LogEventLevel.Debug; - public string? SeqLogUrl { get; set; } - + public LoggingConfig Logging { get; set; } = new(); public DatabaseConfig Database { get; set; } = new(); public class DatabaseConfig @@ -22,4 +20,11 @@ public class CoreConfig public int? Timeout { get; set; } public int? MaxPoolSize { get; set; } } -} + + public class LoggingConfig + { + public LogEventLevel LogEventLevel { get; set; } = LogEventLevel.Debug; + public string? SeqLogUrl { get; set; } + public bool LogQueries { get; set; } = false; + } +} \ No newline at end of file diff --git a/Foxchat.Core/Extensions/ServiceCollectionExtensions.cs b/Foxchat.Core/Extensions/ServiceCollectionExtensions.cs index f5d4893..a41dd0b 100644 --- a/Foxchat.Core/Extensions/ServiceCollectionExtensions.cs +++ b/Foxchat.Core/Extensions/ServiceCollectionExtensions.cs @@ -7,30 +7,32 @@ using NodaTime; using Serilog; using Serilog.Events; -namespace Foxchat.Core; +namespace Foxchat.Core.Extensions; public static class ServiceCollectionExtensions { /// /// Adds Serilog to this service collection. This method also initializes Serilog so it should be called as early as possible, before any log calls. /// - public static void AddSerilog(this WebApplicationBuilder builder, LogEventLevel level) + public static void AddSerilog(this WebApplicationBuilder builder) { var config = builder.Configuration.Get() ?? new(); var logCfg = new LoggerConfiguration() .Enrich.FromLogContext() - .MinimumLevel.Is(level) + .MinimumLevel.Is(config.Logging.LogEventLevel) // ASP.NET's built in request logs are extremely verbose, so we use Serilog's instead. - // Serilog doesn't disable the built in logs so we do it here. + // Serilog doesn't disable the built-in logs, so we do it here. .MinimumLevel.Override("Microsoft", LogEventLevel.Information) + .MinimumLevel.Override("Microsoft.EntityFrameworkCore.Database.Command", + config.Logging.LogQueries ? LogEventLevel.Information : LogEventLevel.Warning) .MinimumLevel.Override("Microsoft.AspNetCore.Hosting", LogEventLevel.Warning) .MinimumLevel.Override("Microsoft.AspNetCore.Mvc", LogEventLevel.Warning) .MinimumLevel.Override("Microsoft.AspNetCore.Routing", LogEventLevel.Warning) .WriteTo.Console(); - if (config.SeqLogUrl != null) - logCfg.WriteTo.Seq(config.SeqLogUrl, restrictedToMinimumLevel: LogEventLevel.Verbose); + if (config.Logging.SeqLogUrl != null) + logCfg.WriteTo.Seq(config.Logging.SeqLogUrl, restrictedToMinimumLevel: LogEventLevel.Verbose); Log.Logger = logCfg.CreateLogger(); @@ -54,9 +56,9 @@ public static class ServiceCollectionExtensions return services; } - public static T AddConfiguration(this WebApplicationBuilder builder, string? configFile = null) where T : class, new() + public static T AddConfiguration(this WebApplicationBuilder builder, string? configFile = null) + where T : class, new() { - builder.Configuration.Sources.Clear(); builder.Configuration.AddConfiguration(configFile); @@ -76,4 +78,4 @@ public static class ServiceCollectionExtensions .AddIniFile(file, optional: false, reloadOnChange: true) .AddEnvironmentVariables(); } -} +} \ No newline at end of file diff --git a/Foxchat.Identity/Database/IdentityContext.cs b/Foxchat.Identity/Database/IdentityContext.cs index e983fac..efc4850 100644 --- a/Foxchat.Identity/Database/IdentityContext.cs +++ b/Foxchat.Identity/Database/IdentityContext.cs @@ -1,5 +1,6 @@ using Foxchat.Core; using Foxchat.Core.Database; +using Foxchat.Core.Extensions; using Foxchat.Identity.Database.Models; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; @@ -10,6 +11,7 @@ namespace Foxchat.Identity.Database; public class IdentityContext : IDatabaseContext { private readonly NpgsqlDataSource _dataSource; + private readonly ILoggerFactory? _loggerFactory; public override DbSet Instance { get; set; } public DbSet Accounts { get; set; } @@ -18,7 +20,7 @@ public class IdentityContext : IDatabaseContext public DbSet Tokens { get; set; } public DbSet GuildAccounts { get; set; } - public IdentityContext(InstanceConfig config) + public IdentityContext(InstanceConfig config, ILoggerFactory? loggerFactory) { var connString = new NpgsqlConnectionStringBuilder(config.Database.Url) { @@ -29,12 +31,14 @@ public class IdentityContext : IDatabaseContext var dataSourceBuilder = new NpgsqlDataSourceBuilder(connString); dataSourceBuilder.UseNodaTime(); _dataSource = dataSourceBuilder.Build(); + _loggerFactory = loggerFactory; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - => optionsBuilder - .UseNpgsql(_dataSource, o => o.UseNodaTime()) - .UseSnakeCaseNamingConvention(); + => optionsBuilder + .UseNpgsql(_dataSource, o => o.UseNodaTime()) + .UseSnakeCaseNamingConvention() + .UseLoggerFactory(_loggerFactory); protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) { @@ -67,6 +71,6 @@ public class DesignTimeIdentityContextFactory : IDesignTimeDbContextFactory() ?? new(); - return new IdentityContext(config); + return new IdentityContext(config, null); } } diff --git a/Foxchat.Identity/Program.cs b/Foxchat.Identity/Program.cs index 8e0c47e..035feb1 100644 --- a/Foxchat.Identity/Program.cs +++ b/Foxchat.Identity/Program.cs @@ -1,6 +1,7 @@ using Newtonsoft.Json.Serialization; using Serilog; using Foxchat.Core; +using Foxchat.Core.Extensions; using Foxchat.Identity; using Foxchat.Identity.Database; using Foxchat.Identity.Services; @@ -11,7 +12,7 @@ var builder = WebApplication.CreateBuilder(args); var config = builder.AddConfiguration("identity.ini"); -builder.AddSerilog(config.LogEventLevel); +builder.AddSerilog(); await BuildInfo.ReadBuildInfo(); Log.Information("Starting Foxchat.Identity {Version} ({Hash})", BuildInfo.Version, BuildInfo.Hash); diff --git a/Foxchat.Identity/identity.ini b/Foxchat.Identity/identity.ini index d4b3c40..7f4172c 100644 --- a/Foxchat.Identity/identity.ini +++ b/Foxchat.Identity/identity.ini @@ -2,11 +2,6 @@ Host = localhost Port = 7611 Domain = id.fox.localhost -; The level to log things at. Valid settings: Verbose, Debug, Information, Warning, Error, Fatal -LogEventLevel = Debug -; Optional logging to Seq -SeqLogUrl = http://localhost:5341 - [Database] ; The database URL in ADO.NET format. Url = "Host=localhost;Database=foxchat_cs_ident;Username=foxchat;Password=password" @@ -15,3 +10,11 @@ Url = "Host=localhost;Database=foxchat_cs_ident;Username=foxchat;Password=passwo Timeout = 5 ; The maximum number of open connections. Defaults to 50. MaxPoolSize = 500 + +[Logging] +; The level to log things at. Valid settings: Verbose, Debug, Information, Warning, Error, Fatal +LogEventLevel = Debug +; Whether to log SQL queries. +LogQueries = true +; Optional logging to Seq +SeqLogUrl = http://localhost:5341