aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Server/Program.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Jellyfin.Server/Program.cs')
-rw-r--r--Jellyfin.Server/Program.cs93
1 files changed, 61 insertions, 32 deletions
diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs
index 1dd598236..e9e852349 100644
--- a/Jellyfin.Server/Program.cs
+++ b/Jellyfin.Server/Program.cs
@@ -26,6 +26,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Serilog;
+using Serilog.Events;
using Serilog.Extensions.Logging;
using SQLitePCL;
using ILogger = Microsoft.Extensions.Logging.ILogger;
@@ -37,6 +38,16 @@ namespace Jellyfin.Server
/// </summary>
public static class Program
{
+ /// <summary>
+ /// The name of logging configuration file containing application defaults.
+ /// </summary>
+ public static readonly string LoggingConfigFileDefault = "logging.default.json";
+
+ /// <summary>
+ /// The name of the logging configuration file containing the system-specific override settings.
+ /// </summary>
+ public static readonly string LoggingConfigFileSystem = "logging.json";
+
private static readonly CancellationTokenSource _tokenSource = new CancellationTokenSource();
private static readonly ILoggerFactory _loggerFactory = new SerilogLoggerFactory();
private static ILogger _logger = NullLogger.Instance;
@@ -101,10 +112,12 @@ namespace Jellyfin.Server
// $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager
Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", appPaths.LogDirectoryPath);
- IConfiguration appConfig = await CreateConfiguration(appPaths).ConfigureAwait(false);
-
- CreateLogger(appConfig, appPaths);
+ // Create an instance of the application configuration to use for application startup
+ await InitLoggingConfigFile(appPaths).ConfigureAwait(false);
+ IConfiguration startupConfig = CreateAppConfiguration(appPaths);
+ // Initialize logging framework
+ InitializeLoggingFramework(startupConfig, appPaths);
_logger = _loggerFactory.CreateLogger("Main");
// Log uncaught exceptions to the logging instead of std error
@@ -169,22 +182,22 @@ namespace Jellyfin.Server
options,
new ManagedFileSystem(_loggerFactory.CreateLogger<ManagedFileSystem>(), appPaths),
GetImageEncoder(appPaths),
- new NetworkManager(_loggerFactory.CreateLogger<NetworkManager>()),
- appConfig);
+ new NetworkManager(_loggerFactory.CreateLogger<NetworkManager>()));
try
{
ServiceCollection serviceCollection = new ServiceCollection();
- await appHost.InitAsync(serviceCollection).ConfigureAwait(false);
+ await appHost.InitAsync(serviceCollection, startupConfig).ConfigureAwait(false);
- var host = CreateWebHostBuilder(appHost, serviceCollection).Build();
+ var webHost = CreateWebHostBuilder(appHost, serviceCollection, appPaths).Build();
// A bit hacky to re-use service provider since ASP.NET doesn't allow a custom service collection.
- appHost.ServiceProvider = host.Services;
+ appHost.ServiceProvider = webHost.Services;
appHost.FindParts();
+ Migrations.MigrationRunner.Run(appHost, _loggerFactory);
try
{
- await host.StartAsync().ConfigureAwait(false);
+ await webHost.StartAsync().ConfigureAwait(false);
}
catch
{
@@ -220,7 +233,7 @@ namespace Jellyfin.Server
}
}
- private static IWebHostBuilder CreateWebHostBuilder(ApplicationHost appHost, IServiceCollection serviceCollection)
+ private static IWebHostBuilder CreateWebHostBuilder(ApplicationHost appHost, IServiceCollection serviceCollection, IApplicationPaths appPaths)
{
return new WebHostBuilder()
.UseKestrel(options =>
@@ -260,6 +273,8 @@ namespace Jellyfin.Server
}
}
})
+ .ConfigureAppConfiguration(config => config.ConfigureAppConfiguration(appPaths))
+ .UseSerilog()
.UseContentRoot(appHost.ContentRoot)
.ConfigureServices(services =>
{
@@ -432,37 +447,51 @@ namespace Jellyfin.Server
return new ServerApplicationPaths(dataDir, logDir, configDir, cacheDir, webDir);
}
- private static async Task<IConfiguration> CreateConfiguration(IApplicationPaths appPaths)
+ /// <summary>
+ /// Initialize the logging configuration file using the bundled resource file as a default if it doesn't exist
+ /// already.
+ /// </summary>
+ private static async Task InitLoggingConfigFile(IApplicationPaths appPaths)
{
- const string ResourcePath = "Jellyfin.Server.Resources.Configuration.logging.json";
- string configPath = Path.Combine(appPaths.ConfigurationDirectoryPath, "logging.json");
-
- if (!File.Exists(configPath))
+ // Do nothing if the config file already exists
+ string configPath = Path.Combine(appPaths.ConfigurationDirectoryPath, LoggingConfigFileDefault);
+ if (File.Exists(configPath))
{
- // For some reason the csproj name is used instead of the assembly name
- await using Stream? resource = typeof(Program).Assembly.GetManifestResourceStream(ResourcePath);
- if (resource == null)
- {
- throw new InvalidOperationException(
- string.Format(
- CultureInfo.InvariantCulture,
- "Invalid resource path: '{0}'",
- ResourcePath));
- }
-
- await using Stream dst = File.Open(configPath, FileMode.CreateNew);
- await resource.CopyToAsync(dst).ConfigureAwait(false);
+ return;
}
+ // Get a stream of the resource contents
+ // NOTE: The .csproj name is used instead of the assembly name in the resource path
+ const string ResourcePath = "Jellyfin.Server.Resources.Configuration.logging.json";
+ await using Stream? resource = typeof(Program).Assembly.GetManifestResourceStream(ResourcePath)
+ ?? throw new InvalidOperationException($"Invalid resource path: '{ResourcePath}'");
+
+ // Copy the resource contents to the expected file path for the config file
+ await using Stream dst = File.Open(configPath, FileMode.CreateNew);
+ await resource.CopyToAsync(dst).ConfigureAwait(false);
+ }
+
+ private static IConfiguration CreateAppConfiguration(IApplicationPaths appPaths)
+ {
return new ConfigurationBuilder()
+ .ConfigureAppConfiguration(appPaths)
+ .Build();
+ }
+
+ private static IConfigurationBuilder ConfigureAppConfiguration(this IConfigurationBuilder config, IApplicationPaths appPaths)
+ {
+ return config
.SetBasePath(appPaths.ConfigurationDirectoryPath)
.AddInMemoryCollection(ConfigurationOptions.Configuration)
- .AddJsonFile("logging.json", false, true)
- .AddEnvironmentVariables("JELLYFIN_")
- .Build();
+ .AddJsonFile(LoggingConfigFileDefault, optional: false, reloadOnChange: true)
+ .AddJsonFile(LoggingConfigFileSystem, optional: true, reloadOnChange: true)
+ .AddEnvironmentVariables("JELLYFIN_");
}
- private static void CreateLogger(IConfiguration configuration, IApplicationPaths appPaths)
+ /// <summary>
+ /// Initialize Serilog using configuration and fall back to defaults on failure.
+ /// </summary>
+ private static void InitializeLoggingFramework(IConfiguration configuration, IApplicationPaths appPaths)
{
try
{