Init emergency loggers to notify user about very early failures

"Very early failures" include exclusively lack of being able to navigate to given --path, as everything else is postponed until we get core loggers up and running. We should print the information to the user and abort the program at the minimum in this case.

Until now ASF silently ignored those errors and proceeded like usual, this is unwanted, if --path is wrong then it's on user to fix it.
This commit is contained in:
Archi
2021-12-04 02:33:23 +01:00
parent a184fc555b
commit 94c214af96
2 changed files with 67 additions and 23 deletions

View File

@@ -149,30 +149,21 @@ internal static class Logging {
internal static void InitCoreLoggers(bool uniqueInstance) {
try {
if ((Directory.GetCurrentDirectory() != AppContext.BaseDirectory) && File.Exists(NLogConfigurationFile)) {
IsUsingCustomConfiguration = true;
LogManager.Configuration = new XmlLoggingConfiguration(NLogConfigurationFile);
}
} catch (Exception e) {
ASF.ArchiLogger.LogGenericException(e);
}
if (LogManager.Configuration != null) {
IsUsingCustomConfiguration = true;
if (IsUsingCustomConfiguration) {
InitConsoleLoggers();
LogManager.ConfigurationChanged += OnConfigurationChanged;
return;
}
ConfigurationItemFactory.Default.ParseMessageTemplates = false;
LoggingConfiguration config = new();
#pragma warning disable CA2000 // False positive, we're adding this disposable object to the global scope, so we can't dispose it
ColoredConsoleTarget coloredConsoleTarget = new("ColoredConsole") { Layout = GeneralLayout };
#pragma warning restore CA2000 // False positive, we're adding this disposable object to the global scope, so we can't dispose it
config.AddTarget(coloredConsoleTarget);
config.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, coloredConsoleTarget));
if (uniqueInstance) {
try {
if (!Directory.Exists(SharedInfo.ArchivalLogsDirectory)) {
@@ -196,14 +187,36 @@ internal static class Logging {
};
#pragma warning restore CA2000 // False positive, we're adding this disposable object to the global scope, so we can't dispose it
config.AddTarget(fileTarget);
config.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, fileTarget));
LogManager.Configuration.AddTarget(fileTarget);
LogManager.Configuration.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, fileTarget));
LogManager.ReconfigExistingLoggers();
}
LogManager.Configuration = config;
InitConsoleLoggers();
}
internal static void InitEmergencyLoggers() {
if (LogManager.Configuration != null) {
IsUsingCustomConfiguration = true;
return;
}
// This is a temporary, bare, file-less configuration that must work until we're able to initialize it properly
ConfigurationItemFactory.Default.ParseMessageTemplates = false;
LoggingConfiguration config = new();
#pragma warning disable CA2000 // False positive, we're adding this disposable object to the global scope, so we can't dispose it
ColoredConsoleTarget coloredConsoleTarget = new("ColoredConsole") { Layout = GeneralLayout };
#pragma warning restore CA2000 // False positive, we're adding this disposable object to the global scope, so we can't dispose it
config.AddTarget(coloredConsoleTarget);
config.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, coloredConsoleTarget));
LogManager.Configuration = config;
}
internal static void InitHistoryLogger() {
if (LogManager.Configuration == null) {
return;

View File

@@ -119,7 +119,7 @@ internal static class Program {
NetworkGroup = networkGroup;
}
private static void HandlePathArgument(string path) {
private static bool HandlePathArgument(string path) {
if (string.IsNullOrEmpty(path)) {
throw new ArgumentNullException(nameof(path));
}
@@ -134,6 +134,8 @@ internal static class Program {
}
} catch (Exception e) {
ASF.ArchiLogger.LogGenericException(e);
return false;
}
}
@@ -141,7 +143,11 @@ internal static class Program {
Directory.SetCurrentDirectory(path);
} catch (Exception e) {
ASF.ArchiLogger.LogGenericException(e);
return false;
}
return true;
}
private static async Task Init(IReadOnlyCollection<string>? args) {
@@ -192,6 +198,9 @@ internal static class Program {
}
private static async Task<bool> InitCore(IReadOnlyCollection<string>? args) {
// Init emergency loggers used for failures before setting up ones according to preference of the user
Logging.InitEmergencyLoggers();
Directory.SetCurrentDirectory(SharedInfo.HomeDirectory);
// Allow loading configs from source tree if it's a debug build
@@ -212,15 +221,24 @@ internal static class Program {
}
// Parse environment variables
ParseEnvironmentVariables();
if (!ParseEnvironmentVariables()) {
await Task.Delay(SharedInfo.InformationDelay).ConfigureAwait(false);
return false;
}
// Parse args
if (args?.Count > 0) {
ParseArgs(args);
if (!ParseArgs(args)) {
await Task.Delay(SharedInfo.InformationDelay).ConfigureAwait(false);
return false;
}
}
bool uniqueInstance = await OS.RegisterProcess().ConfigureAwait(false);
// Init core loggers according to user's preferences
Logging.InitCoreLoggers(uniqueInstance);
if (!uniqueInstance) {
@@ -498,7 +516,7 @@ internal static class Program {
e.SetObserved();
}
private static void ParseArgs(IReadOnlyCollection<string> args) {
private static bool ParseArgs(IReadOnlyCollection<string> args) {
if ((args == null) || (args.Count == 0)) {
throw new ArgumentNullException(nameof(args));
}
@@ -558,7 +576,10 @@ internal static class Program {
HandleNetworkGroupArgument(arg);
} else if (pathNext) {
pathNext = false;
HandlePathArgument(arg);
if (!HandlePathArgument(arg)) {
return false;
}
} else {
switch (arg.Length) {
case > 16 when arg.StartsWith("--NETWORK-GROUP=", StringComparison.OrdinalIgnoreCase):
@@ -570,7 +591,9 @@ internal static class Program {
break;
case > 7 when arg.StartsWith("--PATH=", StringComparison.OrdinalIgnoreCase):
HandlePathArgument(arg[7..]);
if (!HandlePathArgument(arg[7..])) {
return false;
}
break;
default:
@@ -583,9 +606,11 @@ internal static class Program {
break;
}
}
return true;
}
private static void ParseEnvironmentVariables() {
private static bool ParseEnvironmentVariables() {
// We're using a single try-catch block here, as a failure for getting one variable will result in the same failure for all other ones
try {
string? envCryptKey = Environment.GetEnvironmentVariable(SharedInfo.EnvironmentVariableCryptKey);
@@ -606,11 +631,17 @@ internal static class Program {
if (!string.IsNullOrEmpty(envPath)) {
// ReSharper disable once RedundantSuppressNullableWarningExpression - required for .NET Framework
HandlePathArgument(envPath!);
if (!HandlePathArgument(envPath!)) {
return false;
}
}
} catch (Exception e) {
ASF.ArchiLogger.LogGenericException(e);
return false;
}
return true;
}
private static async Task Shutdown(byte exitCode = 0) {