From fb82c9c4b01838fe683abe5d29f3592586503eb4 Mon Sep 17 00:00:00 2001 From: JeremyStarTM Date: Mon, 19 Aug 2024 20:17:55 +0200 Subject: [PATCH] Rework logger placeholder replacement, add newline support This commit reworks how placeholders work in Logger.java and adds support for printing multiple lines. --- .../staropensource/sosengine/base/Engine.java | 4 +- .../sosengine/base/EngineConfiguration.java | 2 +- .../placeholders/logger/LogMessage.java | 56 ------------ .../sosengine/base/logging/InitLogger.java | 3 +- .../sosengine/base/logging/Logger.java | 88 ++++++++++++++----- 5 files changed, 72 insertions(+), 81 deletions(-) delete mode 100644 base/src/main/java/de/staropensource/sosengine/base/internal/placeholders/logger/LogMessage.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 27c6dae..64f8c2d 100644 --- a/base/src/main/java/de/staropensource/sosengine/base/Engine.java +++ b/base/src/main/java/de/staropensource/sosengine/base/Engine.java @@ -176,6 +176,7 @@ public final class Engine extends SubsystemClass { cacheEvents(); // Cache event listeners startThreads(); // Start threads + logger.verb("Completing early initialization stage"); state = EngineState.STARTUP; // Perform automatic subsystem initialization @@ -191,6 +192,7 @@ public final class Engine extends SubsystemClass { } }); + logger.verb("Completing late initialization stage"); state = EngineState.RUNNING; logger.info("Initialized sos!engine %engine_version% (commit %engine_git_commit_id_long%-%engine_git_branch%, dirty %engine_git_dirty%) in " + initTime + "ms"); } @@ -384,7 +386,7 @@ public final class Engine extends SubsystemClass { } // Initialize subsystems - logger.info("Initializing engine subsystems"); + logger.verb("Initializing engine subsystems"); long initTime; for (DependencySubsystemVector vector : subsystems) { logger.diag("Initializing subsystem " + vector.getMainClass().getName() + " (" + vector.getMainClass().getClass().getName() + ")"); diff --git a/base/src/main/java/de/staropensource/sosengine/base/EngineConfiguration.java b/base/src/main/java/de/staropensource/sosengine/base/EngineConfiguration.java index 4166739..0a36a15 100644 --- a/base/src/main/java/de/staropensource/sosengine/base/EngineConfiguration.java +++ b/base/src/main/java/de/staropensource/sosengine/base/EngineConfiguration.java @@ -358,7 +358,7 @@ public final class EngineConfiguration extends Configuration { optimizeSubsystemInitialization = true; loggerLevel = LogLevel.INFORMATIONAL; - loggerTemplate = "%log_color_primary%[%time_hour%:%time_minute%:%time_second%] [%log_level% %log_path%%log_metadata%] %log_color_secondary%%log_message%"; + loggerTemplate = "%log_color_primary%[%time_hour%:%time_minute%:%time_second%] [%log_level% %log_path%%log_metadata%] %log_message_prefix%%log_color_primary%%log_color_secondary%%log_message%"; loggerImmediateShutdown = false; loggerForceStandardOutput = false; loggerPollingSpeed = 5; diff --git a/base/src/main/java/de/staropensource/sosengine/base/internal/placeholders/logger/LogMessage.java b/base/src/main/java/de/staropensource/sosengine/base/internal/placeholders/logger/LogMessage.java deleted file mode 100644 index 698de48..0000000 --- a/base/src/main/java/de/staropensource/sosengine/base/internal/placeholders/logger/LogMessage.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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.internal.placeholders.logger; - -import de.staropensource.sosengine.base.classes.Placeholder; -import org.jetbrains.annotations.NotNull; - -/** - * Implements the {@code log_message} placeholder. - * - * @see Placeholder - * @since v1-alpha0 - */ -@SuppressWarnings({ "unused" }) -public final class LogMessage implements Placeholder { - /** - * The message to use. - * - * @since v1-alpha0 - */ - @NotNull - private final String message; - - /** - * Constructs this class. - * - * @param message message to use - * @since v1-alpha0 - */ - public LogMessage(@NotNull String message) { - this.message = message; - } - - /** {@inheritDoc} */ - @Override - public @NotNull String replace(@NotNull String text) { - return text.replace("%log_message%", message); - } -} 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 index 685224a..cbc227a 100644 --- a/base/src/main/java/de/staropensource/sosengine/base/logging/InitLogger.java +++ b/base/src/main/java/de/staropensource/sosengine/base/logging/InitLogger.java @@ -20,7 +20,6 @@ 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; @@ -70,7 +69,7 @@ public final class InitLogger { // 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); + base = base.replace("%log_message%", message.replace("\n", "")); // Invoke LoggerImpl#postPlaceholder base = Logger.getLoggerImplementation().postPlaceholder(level, issuerClass, issuerOrigin, issuerMetadata, message, base); diff --git a/base/src/main/java/de/staropensource/sosengine/base/logging/Logger.java b/base/src/main/java/de/staropensource/sosengine/base/logging/Logger.java index 6ff0d1d..efab376 100644 --- a/base/src/main/java/de/staropensource/sosengine/base/logging/Logger.java +++ b/base/src/main/java/de/staropensource/sosengine/base/logging/Logger.java @@ -22,7 +22,6 @@ package de.staropensource.sosengine.base.logging; import de.staropensource.sosengine.base.Engine; import de.staropensource.sosengine.base.EngineConfiguration; import de.staropensource.sosengine.base.classes.LoggerImplementation; -import de.staropensource.sosengine.base.classes.Placeholder; import de.staropensource.sosengine.base.classes.helpers.EventHelper; import de.staropensource.sosengine.base.events.LogEvent; import de.staropensource.sosengine.base.internal.placeholders.logger.*; @@ -33,6 +32,7 @@ import de.staropensource.sosengine.base.types.logging.LogLevel; import de.staropensource.sosengine.base.types.logging.LogRule; import de.staropensource.sosengine.base.types.logging.LogRuleType; import de.staropensource.sosengine.base.utility.PlaceholderEngine; +import de.staropensource.sosengine.base.utility.converter.EmptyShortcodeConverter; import lombok.Getter; import lombok.Setter; import org.jetbrains.annotations.NotNull; @@ -41,6 +41,7 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; +import java.util.Scanner; /** * Provides the engine's logging infrastructure, except for @@ -186,7 +187,7 @@ public final class Logger { * @since v1-alpha1 */ private static void processLogMessage(@NotNull LogLevel level, @NotNull Class issuerClass, @NotNull String issuerOrigin, @Nullable String issuerMetadata, @NotNull String message) { - // Evaluate all active rules + // Evaluate active rules for (LogRule rule : activeRules) { if (rule.evaluate(level, issuerClass, issuerOrigin, issuerMetadata, message)) { if (rule.getType() == LogRuleType.WHITELIST) break; // Continue processing @@ -195,28 +196,73 @@ public final class Logger { } // Invoke LoggerImpl#prePlaceholder - String base = loggerImplementation.prePlaceholder(level, issuerClass, issuerOrigin, issuerMetadata, message, EngineConfiguration.getInstance().getLoggerTemplate()); - if (base == null) - base = EngineConfiguration.getInstance().getLoggerTemplate(); - - // Create list of temporary placeholders - List<@NotNull Placeholder> temporaryPlaceholders = new ArrayList<>(); - temporaryPlaceholders.add(new LogMessage(message)); // log_message is out of order to allow for placeholder usage - - temporaryPlaceholders.add(new LogClass(issuerClass)); - temporaryPlaceholders.add(new LogColorPrimary(level)); - temporaryPlaceholders.add(new LogColorSecondary(level)); - temporaryPlaceholders.add(new LogMetadata(issuerMetadata)); - temporaryPlaceholders.add(new LogOrigin(issuerOrigin)); - temporaryPlaceholders.add(new de.staropensource.sosengine.base.internal.placeholders.logger.LogLevel(level)); - temporaryPlaceholders.add(new LogPackage(issuerClass)); - temporaryPlaceholders.add(new LogPath(issuerClass)); + String format = loggerImplementation.prePlaceholder(level, issuerClass, issuerOrigin, issuerMetadata, message, EngineConfiguration.getInstance().getLoggerTemplate()); + if (format == null) + format = EngineConfiguration.getInstance().getLoggerTemplate(); // Replace placeholders - base = PlaceholderEngine.getInstance().process(base, temporaryPlaceholders); + // Using PlaceholderEngine + format = PlaceholderEngine.getInstance().process(format); + // Logger placeholders (no colors) + format = new LogClass(issuerClass).replace(format); + format = new de.staropensource.sosengine.base.internal.placeholders.logger.LogLevel(level).replace(format); + format = new LogMetadata(issuerMetadata).replace(format); + format = new LogOrigin(issuerOrigin).replace(format); + format = new LogPackage(issuerClass).replace(format); + format = new LogPath(issuerClass).replace(format); + + // Handle newlines + if (message.contains("\n")) + try (Scanner scanner = new Scanner(message)) { + int indexPrefix = format.indexOf("%log_message_prefix%"); + int indexMessage = format.indexOf("%log_message%"); + StringBuilder formatNew = new StringBuilder(); + String prefix; + String suffix; + String formatShadow; + + if (indexMessage == -1) + crash(Logger.class, "ENGINE", null, "The log format must contain %log_message%"); + + prefix = indexPrefix == -1 ? "" : format.substring(indexPrefix + 20, indexMessage); + suffix = format.substring(indexMessage + 13); + formatShadow = " " + .repeat(new EmptyShortcodeConverter( + format.substring(0, indexPrefix == -1 ? indexMessage : indexPrefix) + .replace("%log_color_primary%", "") + .replace("%log_color_secondary%", ""), false + ).getClean().length()); + + int a = 1 + 1; + + while (scanner.hasNextLine()) { + if (formatNew.isEmpty()) + formatNew.append(format, 0, indexPrefix == -1 ? indexMessage : indexPrefix); + else + formatNew + .append("\n") + .append(formatShadow); + + formatNew + .append(prefix) + .append(scanner.nextLine()) + .append(suffix); + } + + format = formatNew.toString(); + } + else + // No newline found, use performance-efficient replacing + format = format + .replace("%log_message_prefix%", "") + .replace("%log_message%", message); + + // Replace placeholders involving colors + format = new LogColorPrimary(level).replace(format); + format = new LogColorSecondary(level).replace(format); // Invoke LoggerImpl#postPlaceholder - base = loggerImplementation.postPlaceholder(level, issuerClass, issuerOrigin, issuerMetadata, message, base); + format = loggerImplementation.postPlaceholder(level, issuerClass, issuerOrigin, issuerMetadata, message, format); // Call event if (!(issuerClass.getName().equals("de.staropensource.sosengine.slf4j_compat.CompatibilityLogger") @@ -224,7 +270,7 @@ public final class Logger { new LogEvent().callEvent(level, issuerClass, issuerOrigin, issuerMetadata, message); // Print log message by invoking LoggerImpl#print - loggerImplementation.print(level, issuerClass, issuerOrigin, issuerMetadata, message, base); + loggerImplementation.print(level, issuerClass, issuerOrigin, issuerMetadata, message, format); } /**