Host: Using serilog instead of microsoft logging and adding file logs

This commit is contained in:
Zoe Roux 2021-08-20 22:26:23 +02:00
parent 42469bfa67
commit 334a265e19
6 changed files with 70 additions and 39 deletions

View File

@ -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
/// <inheritdoc />
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
_icon.Visible = false;
base.Dispose(disposing);
_icon.Dispose();
}

View File

@ -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<IApplicationBuilder>(app => app.UseSerilogRequestLogging(), SA.Before),
SA.New<IApplicationBuilder>(app => app.UseResponseCompression(), SA.Routing + 1),
SA.New<IApplicationBuilder>(app => app.UseRouting(), SA.Routing),
SA.New<IApplicationBuilder>(app => app.UseEndpoints(x => x.MapControllers()), SA.Endpoint)

View File

@ -24,6 +24,11 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="Serilog.AspNetCore" Version="4.1.0" />
<PackageReference Include="Serilog.Enrichers.Thread" Version="3.1.0" />
<PackageReference Include="Serilog.Expressions" Version="3.2.0" />
<PackageReference Include="Serilog.Sinks.RollingFile" Version="3.3.0" />
<PackageReference Include="System.Collections.Immutable" Version="5.0.0" />
<PackageReference Include="Autofac" Version="6.2.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.1.0" />
@ -44,8 +49,7 @@
<ProjectReference Include="../Kyoo.WebApp/Kyoo.WebApp.csproj" />
</ItemGroup>
<Target Name="BuildTranscoder" BeforeTargets="BeforeBuild"
Condition="'$(SkipTranscoder)' != 'true' And !Exists('$(TranscoderRoot)/build/$(TranscoderBinary)')">
<Target Name="BuildTranscoder" BeforeTargets="BeforeBuild" Condition="'$(SkipTranscoder)' != 'true' And !Exists('$(TranscoderRoot)/build/$(TranscoderBinary)')">
<Exec WorkingDirectory="$(TranscoderRoot)" Condition="'$(IsWindows)' != 'true'" Command="mkdir -p build %26%26 cd build %26%26 cmake .. %26%26 make -j" />
<Exec WorkingDirectory="$(TranscoderRoot)" Condition="'$(IsWindows)' == 'true'" Command="(if not exist build mkdir build) %26%26 cd build %26%26 cmake .. -G &quot;NMake Makefiles&quot; %26%26 nmake" />
</Target>

View File

@ -131,19 +131,13 @@ namespace Kyoo
/// This is meant to be used from <see cref="WebHostBuilderExtensions.UseStartup"/>.
/// </summary>
/// <param name="host">The context of the web host.</param>
/// <param name="loggingConfiguration">
/// The method used to configure the logger factory used by the plugin manager and plugins during startup.
/// <param name="logger">
/// The logger factory used to log while the application is setting itself up.
/// </param>
/// <returns>A new <see cref="PluginsStartup"/>.</returns>
public static PluginsStartup FromWebHost(WebHostBuilderContext host,
Action<HostBuilderContext, ILoggingBuilder> loggingConfiguration)
ILoggerFactory logger)
{
HostBuilderContext genericHost = new(new Dictionary<object, object>())
{
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,

View File

@ -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
/// <summary>
/// Initialize the bootstrap logger to use it anywhere. This is done here so it is called before any method,
/// even if the <see cref="Main"/> is not used and this binary is used as a dll.
/// </summary>
static Program()
{
LoggerConfiguration config = new();
_ConfigureLogging(null, config);
Log.Logger = config.CreateBootstrapLogger().ForContext<Application>();
AppDomain.CurrentDomain.ProcessExit += (_, _) => Log.CloseAndFlush();
}
/// <summary>
/// Main function of the program
/// </summary>
@ -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
/// </summary>
/// <param name="context">The host context that contains the configuration</param>
/// <param name="builder">The logger builder to configure.</param>
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();
}
/// <summary>
/// Create a a web host
/// </summary>
/// <param name="args">Command line parameters that can be handled by kestrel</param>
/// <param name="loggingConfiguration">
/// An action to configure the logging. If it is null, <see cref="ConfigureLogging"/> will be used.
/// </param>
/// <returns>A new web host instance</returns>
public static IHostBuilder CreateWebHostBuilder(string[] args,
Action<HostBuilderContext, ILoggingBuilder> 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<string>("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);
}
/// <summary>
/// An useless class only used to have a logger in the main.
/// </summary>
private class Application {}
}
/// <summary>
/// An useless class only used to have a logger in the main.
/// </summary>
internal class Application {}
}

View File

@ -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"
}
}
},