From 334a265e192755d95e8c1815ba9d345ec267366e Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Fri, 20 Aug 2021 22:26:23 +0200 Subject: [PATCH] Host: Using serilog instead of microsoft logging and adding file logs --- Kyoo.WindowsHost/SystemTrait.cs | 3 +- Kyoo/CoreModule.cs | 2 + Kyoo/Kyoo.csproj | 8 +++- Kyoo/PluginsStartup.cs | 12 ++---- Kyoo/Program.cs | 70 +++++++++++++++++++++++---------- Kyoo/settings.json | 14 ++++--- 6 files changed, 70 insertions(+), 39 deletions(-) diff --git a/Kyoo.WindowsHost/SystemTrait.cs b/Kyoo.WindowsHost/SystemTrait.cs index 22009ab1..b0b7bbbf 100644 --- a/Kyoo.WindowsHost/SystemTrait.cs +++ b/Kyoo.WindowsHost/SystemTrait.cs @@ -78,6 +78,7 @@ namespace Kyoo.Host.Windows { _options = options; + AppDomain.CurrentDomain.ProcessExit += (_, _) => Dispose(); Application.ApplicationExit += (_, _) => Dispose(); _icon = new NotifyIcon(); @@ -111,8 +112,8 @@ namespace Kyoo.Host.Windows /// protected override void Dispose(bool disposing) { - base.Dispose(disposing); _icon.Visible = false; + base.Dispose(disposing); _icon.Dispose(); } diff --git a/Kyoo/CoreModule.cs b/Kyoo/CoreModule.cs index 2d1e35e8..470ad3bd 100644 --- a/Kyoo/CoreModule.cs +++ b/Kyoo/CoreModule.cs @@ -17,6 +17,7 @@ using Microsoft.AspNetCore.StaticFiles; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Serilog; using IMetadataProvider = Kyoo.Abstractions.Controllers.IMetadataProvider; namespace Kyoo @@ -151,6 +152,7 @@ namespace Kyoo app.UseHsts(); } }, SA.Before), + SA.New(app => app.UseSerilogRequestLogging(), SA.Before), SA.New(app => app.UseResponseCompression(), SA.Routing + 1), SA.New(app => app.UseRouting(), SA.Routing), SA.New(app => app.UseEndpoints(x => x.MapControllers()), SA.Endpoint) diff --git a/Kyoo/Kyoo.csproj b/Kyoo/Kyoo.csproj index d4a573f9..c7c358cc 100644 --- a/Kyoo/Kyoo.csproj +++ b/Kyoo/Kyoo.csproj @@ -24,6 +24,11 @@ + + + + + @@ -44,8 +49,7 @@ - + diff --git a/Kyoo/PluginsStartup.cs b/Kyoo/PluginsStartup.cs index 4bcd362f..c5545842 100644 --- a/Kyoo/PluginsStartup.cs +++ b/Kyoo/PluginsStartup.cs @@ -131,19 +131,13 @@ namespace Kyoo /// This is meant to be used from . /// /// The context of the web host. - /// - /// The method used to configure the logger factory used by the plugin manager and plugins during startup. + /// + /// The logger factory used to log while the application is setting itself up. /// /// A new . public static PluginsStartup FromWebHost(WebHostBuilderContext host, - Action loggingConfiguration) + ILoggerFactory logger) { - HostBuilderContext genericHost = new(new Dictionary()) - { - Configuration = host.Configuration, - HostingEnvironment = host.HostingEnvironment - }; - ILoggerFactory logger = LoggerFactory.Create(builder => loggingConfiguration(genericHost, builder)); HostServiceProvider hostProvider = new(host.HostingEnvironment, host.Configuration, logger); PluginManager plugins = new( hostProvider, diff --git a/Kyoo/Program.cs b/Kyoo/Program.cs index f905b8ba..b74da994 100644 --- a/Kyoo/Program.cs +++ b/Kyoo/Program.cs @@ -2,11 +2,15 @@ using System; using System.IO; using System.Threading.Tasks; using Autofac.Extensions.DependencyInjection; +using JetBrains.Annotations; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using Serilog; +using Serilog.Templates; +using Serilog.Templates.Themes; using SEnvironment = System.Environment; namespace Kyoo @@ -30,6 +34,19 @@ namespace Kyoo private const string Environment = "Production"; #endif + /// + /// Initialize the bootstrap logger to use it anywhere. This is done here so it is called before any method, + /// even if the is not used and this binary is used as a dll. + /// + static Program() + { + LoggerConfiguration config = new(); + _ConfigureLogging(null, config); + Log.Logger = config.CreateBootstrapLogger().ForContext(); + + AppDomain.CurrentDomain.ProcessExit += (_, _) => Log.CloseAndFlush(); + } + /// /// Main function of the program /// @@ -67,6 +84,7 @@ namespace Kyoo private static IConfigurationBuilder SetupConfig(IConfigurationBuilder builder, string[] args) { return builder.SetBasePath(System.Environment.CurrentDirectory) + .AddJsonFile(Path.Join(AppDomain.CurrentDomain.BaseDirectory, JsonConfigPath), false, true) .AddJsonFile(JsonConfigPath, false, true) .AddEnvironmentVariables() .AddEnvironmentVariables("KYOO_") @@ -78,44 +96,54 @@ namespace Kyoo /// /// The host context that contains the configuration /// The logger builder to configure. - public static void ConfigureLogging(HostBuilderContext context, ILoggingBuilder builder) + private static void _ConfigureLogging([CanBeNull] HostBuilderContext context, LoggerConfiguration builder) { - builder.AddConfiguration(context.Configuration.GetSection("logging")) - .AddSimpleConsole(x => + if (context != null) + { + try { - x.TimestampFormat = "[hh:mm:ss] "; - }) - .AddDebug() - .AddEventSourceLogger(); + builder.ReadFrom.Configuration(context.Configuration, "logging"); + } + catch (Exception ex) + { + Log.Fatal(ex, "Could not read serilog configuration"); + } + } + + const string template = + "[{@t:HH:mm:ss} {@l:u3} {Substring(SourceContext, LastIndexOf(SourceContext, '.') + 1), 15} ({@i:10})] " + + "{@m}{#if not EndsWith(@m, '\n')}\n{#end}{@x}"; + + builder + .WriteTo.Console(new ExpressionTemplate(template, theme: TemplateTheme.Code)) + .WriteTo.Debug() + .WriteTo.RollingFile(new ExpressionTemplate(template), "logs/log-{Date}.log") + .Enrich.WithThreadId() + .Enrich.FromLogContext(); } /// /// Create a a web host /// /// Command line parameters that can be handled by kestrel - /// - /// An action to configure the logging. If it is null, will be used. - /// /// A new web host instance - public static IHostBuilder CreateWebHostBuilder(string[] args, - Action loggingConfiguration = null) + public static IHostBuilder CreateWebHostBuilder(string[] args) { IConfiguration configuration = SetupConfig(new ConfigurationBuilder(), args).Build(); - loggingConfiguration ??= ConfigureLogging; return new HostBuilder() .UseServiceProviderFactory(new AutofacServiceProviderFactory()) .UseContentRoot(AppDomain.CurrentDomain.BaseDirectory) .UseEnvironment(Environment) .ConfigureAppConfiguration(x => SetupConfig(x, args)) - .ConfigureLogging(loggingConfiguration) + .UseSerilog(_ConfigureLogging) .ConfigureServices(x => x.AddRouting()) .ConfigureWebHost(x => x .UseKestrel(options => { options.AddServerHeader = false; }) .UseIIS() .UseIISIntegration() .UseUrls(configuration.GetValue("basics:url")) - .UseStartup(host => PluginsStartup.FromWebHost(host, loggingConfiguration)) + .UseStartup(host => PluginsStartup.FromWebHost(host, new LoggerFactory().AddSerilog())) ); } @@ -140,14 +168,14 @@ namespace Kyoo if (!Directory.Exists(path)) Directory.CreateDirectory(path); SEnvironment.CurrentDirectory = path; - + if (!File.Exists(JsonConfigPath)) File.Copy(Path.Join(AppDomain.CurrentDomain.BaseDirectory, JsonConfigPath), JsonConfigPath); } - - /// - /// An useless class only used to have a logger in the main. - /// - private class Application {} } + + /// + /// An useless class only used to have a logger in the main. + /// + internal class Application {} } diff --git a/Kyoo/settings.json b/Kyoo/settings.json index de2d784e..299f0e5c 100644 --- a/Kyoo/settings.json +++ b/Kyoo/settings.json @@ -30,12 +30,14 @@ }, "logging": { - "logLevel": { - "default": "Warning", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information", - "Microsoft.EntityFrameworkCore": "None", - "Kyoo": "Trace" + "MinimumLevel": { + "Default": "Warning", + "Override": { + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information", + "Microsoft.EntityFrameworkCore": "Fatal", + "Kyoo": "Verbose" + } } },