From 8f12e8b0c8fb79916b240ce584e7bc7d5a0aa7aa Mon Sep 17 00:00:00 2001 From: JeremyStarTM Date: Sat, 17 Aug 2024 12:41:53 +0200 Subject: [PATCH] Add InitLogger and startup logging --- .../staropensource/sosengine/base/Engine.java | 18 +- .../data/information/EngineInformation.java | 19 +- .../sosengine/base/logging/InitLogger.java | 201 ++++++++++++++++++ .../base/logging/LoggerInstance.java | 32 ++- .../PlainLoggerImplementation.java | 8 +- .../RawLoggerImplementation.java | 8 +- .../sosengine/base/types/EngineState.java | 23 +- 7 files changed, 274 insertions(+), 35 deletions(-) create mode 100644 base/src/main/java/de/staropensource/sosengine/base/logging/InitLogger.java diff --git a/base/src/main/java/de/staropensource/sosengine/base/Engine.java b/base/src/main/java/de/staropensource/sosengine/base/Engine.java index 39492b8..96e4bb7 100644 --- a/base/src/main/java/de/staropensource/sosengine/base/Engine.java +++ b/base/src/main/java/de/staropensource/sosengine/base/Engine.java @@ -92,7 +92,7 @@ public final class Engine extends SubsystemClass { * @see LoggerInstance * @since v1-alpha0 */ - private static LoggerInstance logger; + private static final LoggerInstance logger = new LoggerInstance.Builder().setClazz(Engine.class).setOrigin("ENGINE").setMetadata(EngineInformation.getVersioningCodename()).build(); /** * Contains the engine state. @@ -162,19 +162,18 @@ public final class Engine extends SubsystemClass { return; long initTime = Miscellaneous.measureExecutionTime(() -> { - state = EngineState.STARTUP; + state = EngineState.EARLY_STARTUP; - // Initialize engine configuration new EngineConfiguration(); EngineConfiguration.getInstance().loadConfiguration(); + logger.info("Initializing engine"); initializeClasses(); // Initialize classes populateCrashContent(); // Populate crash content cacheEvents(); // Cache event listeners startThreads(); // Start threads - // Set the logger instance - logger = new LoggerInstance.Builder().setClazz(getClass()).setOrigin("ENGINE").setMetadata(EngineInformation.getVersioningCodename()).build(); + state = EngineState.STARTUP; // Perform automatic subsystem initialization if (EngineConfiguration.getInstance().isOptimizeSubsystemInitialization()) { @@ -199,9 +198,10 @@ public final class Engine extends SubsystemClass { * @since v1-alpha0 */ private void initializeClasses() { + logger.verb("Initializing engine classes"); new PlaceholderEngine(); - EngineInformation.updateVariables(); + EngineInformation.update(); } /** @@ -212,6 +212,8 @@ public final class Engine extends SubsystemClass { */ @SuppressWarnings({ "ExtractMethodRecommender" }) private void populateCrashContent() { + logger.diag("Populating crash content"); + // Issuer Map<@NotNull String, @NotNull String> crashContentIssuer = new LinkedHashMap<>(); crashContentIssuer.put("Code part", "%issuer_origin%"); @@ -261,6 +263,8 @@ public final class Engine extends SubsystemClass { * @since v1-alpha0 */ private void cacheEvents() { + logger.diag("Caching events"); + // Internal events EventHelper.cacheEvent(InternalEngineShutdownEvent.class); @@ -278,6 +282,8 @@ public final class Engine extends SubsystemClass { * @since v1-alpha1 */ public void startThreads() { + logger.diag("Starting threads"); + Logger.startLoggingThread(); } diff --git a/base/src/main/java/de/staropensource/sosengine/base/data/information/EngineInformation.java b/base/src/main/java/de/staropensource/sosengine/base/data/information/EngineInformation.java index 8f8d5f7..b115a84 100644 --- a/base/src/main/java/de/staropensource/sosengine/base/data/information/EngineInformation.java +++ b/base/src/main/java/de/staropensource/sosengine/base/data/information/EngineInformation.java @@ -314,19 +314,20 @@ public final class EngineInformation { /** * Updates all variables. *

- * This method does not need to be invoked, as the information provided by this - * class is static (does not change) and is already populated at engine startup. + * This method does not need to be invoked manually, as the information provided by + * this class is static (does not change) and is already populated at engine startup. * * @since v1-alpha1 */ - public static synchronized void updateVariables() { + public static synchronized void update() { + logger.diag("Updating engine information"); + // Load properties from bundled gradle.properties Properties gradleProperties = new Properties(); InputStream gradleStream = EngineInformation.class.getClassLoader().getResourceAsStream("sosengine-gradle.properties"); if (gradleStream == null) { - System.out.println("Unable to load build information: The bundled gradle.properties file could not be found."); - Engine.getInstance().shutdown(69); + logger.crash("Unable to load build information: The bundled gradle.properties file could not be found."); return; } @@ -335,9 +336,7 @@ public final class EngineInformation { gradleStream.close(); } catch (IOException exception) { StackTraceParser parser = new StackTraceParser(exception); - System.out.println("Unable to load build information: InputStream 'gradleStream' failed"); - System.out.println(parser.getHeader() + "\n" + parser.getStackTrace()); - Engine.getInstance().shutdown(69); + logger.crash("Unable to load build information: InputStream 'gradleStream' failed", exception); return; } @@ -365,9 +364,7 @@ public final class EngineInformation { gitStream.close(); } catch (IOException exception) { StackTraceParser parser = new StackTraceParser(exception); - System.out.println("Unable to load build information: InputStream 'gitStream' failed"); - System.out.println(parser.getHeader() + "\n" + parser.getStackTrace()); - Engine.getInstance().shutdown(69); + logger.crash("Unable to load build information: InputStream 'gitStream' failed", exception); return; } } diff --git a/base/src/main/java/de/staropensource/sosengine/base/logging/InitLogger.java b/base/src/main/java/de/staropensource/sosengine/base/logging/InitLogger.java new file mode 100644 index 0000000..685224a --- /dev/null +++ b/base/src/main/java/de/staropensource/sosengine/base/logging/InitLogger.java @@ -0,0 +1,201 @@ +/* + * STAROPENSOURCE ENGINE SOURCE FILE + * Copyright (c) 2024 The StarOpenSource Engine Contributors + * Licensed under the GNU Affero General Public License v3 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.staropensource.sosengine.base.logging; + +import de.staropensource.sosengine.base.EngineConfiguration; +import de.staropensource.sosengine.base.internal.placeholders.logger.LogMessage; +import de.staropensource.sosengine.base.internal.placeholders.logger.LogPath; +import de.staropensource.sosengine.base.types.logging.LogLevel; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Provides logging capabilities during engine startup. + * + * @since v1-alpha4 + */ +public final class InitLogger { + /** + * Contains the logging template used during startup. + * + * @since v1-alpha4 + */ + private static final @NotNull String template = "%log_level% %log_path% %log_message%"; + + /** + * Constructs this class. + * + * @since v1-alpha4 + */ + public InitLogger() {} + + /** + * {@link Logger#log(LogLevel, Class, String, String, String)} and {@link Logger#processLogMessage(LogLevel, Class, String, String, String)} combined into one method. + * + * @param level level + * @param issuerClass class of the issuer + * @param issuerOrigin origin of the issuer + * @param issuerMetadata metadata about the issuer + * @param message message + * @since v1-alpha4 + */ + private static synchronized void log(@NotNull LogLevel level, @NotNull Class issuerClass, @NotNull String issuerOrigin, @Nullable String issuerMetadata, @NotNull String message) { + // Dismiss if level is not allowed + if (level.compareTo(EngineConfiguration.getInstance().getLoggerLevel()) < 0) + return; + + // Invoke LoggerImpl#prePlaceholder + String base = Logger.getLoggerImplementation().prePlaceholder(level, issuerClass, issuerOrigin, issuerMetadata, message, template); + if (base == null) + base = template; + + // Replace placeholders + // This is done manually to avoid depending on PlaceholderEngine + base = new de.staropensource.sosengine.base.internal.placeholders.logger.LogLevel(level).replace(base); + base = new LogPath(issuerClass).replace(base); + base = new LogMessage(message).replace(base); + + // Invoke LoggerImpl#postPlaceholder + base = Logger.getLoggerImplementation().postPlaceholder(level, issuerClass, issuerOrigin, issuerMetadata, message, base); + + // Print log message by invoking LoggerImpl#print + Logger.getLoggerImplementation().print(level, issuerClass, issuerOrigin, issuerMetadata, message, base); + } + + /** + * Prints a diagnostic message. + * + * @param issuerClass class of the issuer + * @param issuerOrigin origin of the issuer + * @param issuerMetadata metadata about the issuer + * @param message message + * @since v1-alpha4 + */ + public static void diag(@NotNull Class issuerClass, @NotNull String issuerOrigin, @Nullable String issuerMetadata, @NotNull String message) { + log(LogLevel.DIAGNOSTIC, issuerClass, issuerOrigin, issuerMetadata, message); + } + + /** + * Prints a verbose message. + * + * @param issuerClass class of the issuer + * @param issuerOrigin origin of the issuer + * @param issuerMetadata metadata about the issuer + * @param message message + * @since v1-alpha4 + */ + public static void verb(@NotNull Class issuerClass, @NotNull String issuerOrigin, @Nullable String issuerMetadata, @NotNull String message) { + log(LogLevel.VERBOSE, issuerClass, issuerOrigin, issuerMetadata, message); + } + + /** + * Prints a silent warning message. + * + * @param issuerClass class of the issuer + * @param issuerOrigin origin of the issuer + * @param issuerMetadata metadata about the issuer + * @param message message + * @since v1-alpha4 + */ + public static void sarn(@NotNull Class issuerClass, @NotNull String issuerOrigin, @Nullable String issuerMetadata, @NotNull String message) { + log(LogLevel.SILENT_WARNING, issuerClass, issuerOrigin, issuerMetadata, message); + } + + /** + * Prints an informational message. + * + * @param issuerClass class of the issuer + * @param issuerOrigin origin of the issuer + * @param issuerMetadata metadata about the issuer + * @param message message + * @since v1-alpha4 + */ + public static void info(@NotNull Class issuerClass, @NotNull String issuerOrigin, @Nullable String issuerMetadata, @NotNull String message) { + log(LogLevel.INFORMATIONAL, issuerClass, issuerOrigin, issuerMetadata, message); + } + + /** + * Prints a warning message. + * + * @param issuerClass class of the issuer + * @param issuerOrigin origin of the issuer + * @param issuerMetadata metadata about the issuer + * @param message message + * @since v1-alpha4 + */ + public static void warn(@NotNull Class issuerClass, @NotNull String issuerOrigin, @Nullable String issuerMetadata, @NotNull String message) { + log(LogLevel.WARNING, issuerClass, issuerOrigin, issuerMetadata, message); + } + + /** + * Prints an error message. + * + * @param issuerClass class of the issuer + * @param issuerOrigin origin of the issuer + * @param issuerMetadata metadata about the issuer + * @param message message + * @since v1-alpha4 + */ + public static void error(@NotNull Class issuerClass, @NotNull String issuerOrigin, @Nullable String issuerMetadata, @NotNull String message) { + log(LogLevel.ERROR, issuerClass, issuerOrigin, issuerMetadata, message); + } + + /** + * Crashes the entire engine. + * + * @param issuerClass class of the issuer + * @param issuerOrigin origin of the issuer + * @param issuerMetadata metadata about the issuer + * @param message message + * @param throwable the throwable that caused this crash + * @param handled declares the throwable has handled, not causing the engine to shutdown + * @since v1-alpha4 + */ + public static void crash(@NotNull Class issuerClass, @NotNull String issuerOrigin, @Nullable String issuerMetadata, @NotNull String message, @NotNull Throwable throwable, boolean handled) { + Logger.crash(issuerClass, issuerOrigin, issuerMetadata, message, throwable, handled); + } + + /** + * Crashes the entire engine. + * + * @param issuerClass class of the issuer + * @param issuerOrigin origin of the issuer + * @param issuerMetadata metadata about the issuer + * @param message message + * @param throwable the throwable that caused this crash + * @since v1-alpha4 + */ + public static void crash(@NotNull Class issuerClass, @NotNull String issuerOrigin, @Nullable String issuerMetadata, @NotNull String message, @NotNull Throwable throwable) { + Logger.crash(issuerClass, issuerOrigin, issuerMetadata, message, throwable); + } + + /** + * Crashes the entire engine. + * + * @param issuerClass class of the issuer + * @param issuerOrigin origin of the issuer + * @param issuerMetadata metadata about the issuer + * @param message message + * @since v1-alpha4 + */ + public static void crash(@NotNull Class issuerClass, @NotNull String issuerOrigin, @Nullable String issuerMetadata, @NotNull String message) { + Logger.crash(issuerClass, issuerOrigin, issuerMetadata, message); + } +} diff --git a/base/src/main/java/de/staropensource/sosengine/base/logging/LoggerInstance.java b/base/src/main/java/de/staropensource/sosengine/base/logging/LoggerInstance.java index 60ba727..2628bc6 100644 --- a/base/src/main/java/de/staropensource/sosengine/base/logging/LoggerInstance.java +++ b/base/src/main/java/de/staropensource/sosengine/base/logging/LoggerInstance.java @@ -19,6 +19,8 @@ package de.staropensource.sosengine.base.logging; +import de.staropensource.sosengine.base.Engine; +import de.staropensource.sosengine.base.types.EngineState; import lombok.Getter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -88,7 +90,10 @@ public final class LoggerInstance { * @since v1-alpha0 */ public void diag(@NotNull String message) { - Logger.diag(clazz, origin, metadata, message); + if (Engine.getInstance().getState() == EngineState.EARLY_STARTUP) + InitLogger.diag(clazz, origin, metadata, message); + else + Logger.diag(clazz, origin, metadata, message); } /** @@ -98,7 +103,10 @@ public final class LoggerInstance { * @since v1-alpha0 */ public void verb(@NotNull String message) { - Logger.verb(clazz, origin, metadata, message); + if (Engine.getInstance().getState() == EngineState.EARLY_STARTUP) + InitLogger.verb(clazz, origin, metadata, message); + else + Logger.verb(clazz, origin, metadata, message); } /** @@ -108,7 +116,10 @@ public final class LoggerInstance { * @since v1-alpha0 */ public void sarn(@NotNull String message) { - Logger.sarn(clazz, origin, metadata, message); + if (Engine.getInstance().getState() == EngineState.EARLY_STARTUP) + InitLogger.sarn(clazz, origin, metadata, message); + else + Logger.sarn(clazz, origin, metadata, message); } /** @@ -118,7 +129,10 @@ public final class LoggerInstance { * @since v1-alpha0 */ public void info(@NotNull String message) { - Logger.info(clazz, origin, metadata, message); + if (Engine.getInstance().getState() == EngineState.EARLY_STARTUP) + InitLogger.info(clazz, origin, metadata, message); + else + Logger.info(clazz, origin, metadata, message); } /** @@ -128,7 +142,10 @@ public final class LoggerInstance { * @since v1-alpha0 */ public void warn(@NotNull String message) { - Logger.warn(clazz, origin, metadata, message); + if (Engine.getInstance().getState() == EngineState.EARLY_STARTUP) + InitLogger.warn(clazz, origin, metadata, message); + else + Logger.warn(clazz, origin, metadata, message); } /** @@ -138,7 +155,10 @@ public final class LoggerInstance { * @since v1-alpha0 */ public void error(@NotNull String message) { - Logger.error(clazz, origin, metadata, message); + if (Engine.getInstance().getState() == EngineState.EARLY_STARTUP) + InitLogger.error(clazz, origin, metadata, message); + else + Logger.error(clazz, origin, metadata, message); } /** diff --git a/base/src/main/java/de/staropensource/sosengine/base/logging/implementation/PlainLoggerImplementation.java b/base/src/main/java/de/staropensource/sosengine/base/logging/implementation/PlainLoggerImplementation.java index 33a8a81..3c804bb 100644 --- a/base/src/main/java/de/staropensource/sosengine/base/logging/implementation/PlainLoggerImplementation.java +++ b/base/src/main/java/de/staropensource/sosengine/base/logging/implementation/PlainLoggerImplementation.java @@ -45,16 +45,14 @@ public class PlainLoggerImplementation implements LoggerImplementation { /** {@inheritDoc} */ @Override - public @NotNull String prePlaceholder(@NotNull LogLevel level, @NotNull Class issuerClass, @NotNull String issuerOrigin, @Nullable String issuerMetadata, @NotNull String message, @NotNull String format) { - // No modifications necessary - return format; + public @Nullable String prePlaceholder(@NotNull LogLevel level, @NotNull Class issuerClass, @NotNull String issuerOrigin, @Nullable String issuerMetadata, @NotNull String message, @NotNull String format) { + return null; // No modifications necessary } /** {@inheritDoc} */ @Override public @NotNull String postPlaceholder(@NotNull LogLevel level, @NotNull Class issuerClass, @NotNull String issuerOrigin, @Nullable String issuerMetadata, @NotNull String message, @NotNull String format) { - // No modifications necessary - return format; + return format; // No modifications necessary } /** {@inheritDoc} */ diff --git a/base/src/main/java/de/staropensource/sosengine/base/logging/implementation/RawLoggerImplementation.java b/base/src/main/java/de/staropensource/sosengine/base/logging/implementation/RawLoggerImplementation.java index f42cf52..3807bc3 100644 --- a/base/src/main/java/de/staropensource/sosengine/base/logging/implementation/RawLoggerImplementation.java +++ b/base/src/main/java/de/staropensource/sosengine/base/logging/implementation/RawLoggerImplementation.java @@ -45,16 +45,14 @@ public class RawLoggerImplementation implements LoggerImplementation { /** {@inheritDoc} */ @Override - public @NotNull String prePlaceholder(@NotNull LogLevel level, @NotNull Class issuerClass, @NotNull String issuerOrigin, @Nullable String issuerMetadata, @NotNull String message, @NotNull String format) { - // No modifications necessary - return format; + public @Nullable String prePlaceholder(@NotNull LogLevel level, @NotNull Class issuerClass, @NotNull String issuerOrigin, @Nullable String issuerMetadata, @NotNull String message, @NotNull String format) { + return null; // No modifications necessary } /** {@inheritDoc} */ @Override public @NotNull String postPlaceholder(@NotNull LogLevel level, @NotNull Class issuerClass, @NotNull String issuerOrigin, @Nullable String issuerMetadata, @NotNull String message, @NotNull String format) { - // No modifications necessary - return format; + return format; // No modifications necessary } /** {@inheritDoc} */ diff --git a/base/src/main/java/de/staropensource/sosengine/base/types/EngineState.java b/base/src/main/java/de/staropensource/sosengine/base/types/EngineState.java index 0af32cd..034c794 100644 --- a/base/src/main/java/de/staropensource/sosengine/base/types/EngineState.java +++ b/base/src/main/java/de/staropensource/sosengine/base/types/EngineState.java @@ -19,6 +19,9 @@ package de.staropensource.sosengine.base.types; +import de.staropensource.sosengine.base.logging.InitLogger; +import de.staropensource.sosengine.base.logging.Logger; + /** * Determines in which state the engine is currently in. * @@ -35,9 +38,25 @@ public enum EngineState { UNKNOWN, /** - * The engine is currently starting up. + * The engine is in early startup. + * The engine is largely uninitialized and + * the logging infrastructure is not yet ready + * to be used. + *

+ * This state is used to indicate that the + * {@link InitLogger} shall be used instead + * of {@link Logger}. + * + * @since v1-alpha4 + */ + EARLY_STARTUP, + + /** + * The engine is starting up. * Some parts of the engine may not be initialized - * yet and may be unsafe to access. + * yet and may be unsafe to access. The logging + * infrastructure is ready to be used though and is + * safe to access. * * @since v1-alpha2 */