Rework logger placeholder replacement, add newline support
All checks were successful
build-and-test / build (push) Successful in 1m52s
build-and-test / test (push) Successful in 1m54s
build-and-test / generate-javadoc (push) Successful in 1m58s

This commit reworks how placeholders work in Logger.java and adds support for printing multiple lines.
This commit is contained in:
JeremyStar™ 2024-08-19 20:17:55 +02:00
parent 971f81a626
commit fb82c9c4b0
Signed by: JeremyStarTM
GPG key ID: E366BAEF67E4704D
5 changed files with 72 additions and 81 deletions

View file

@ -176,6 +176,7 @@ public final class Engine extends SubsystemClass {
cacheEvents(); // Cache event listeners cacheEvents(); // Cache event listeners
startThreads(); // Start threads startThreads(); // Start threads
logger.verb("Completing early initialization stage");
state = EngineState.STARTUP; state = EngineState.STARTUP;
// Perform automatic subsystem initialization // Perform automatic subsystem initialization
@ -191,6 +192,7 @@ public final class Engine extends SubsystemClass {
} }
}); });
logger.verb("Completing late initialization stage");
state = EngineState.RUNNING; 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"); 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 // Initialize subsystems
logger.info("Initializing engine subsystems"); logger.verb("Initializing engine subsystems");
long initTime; long initTime;
for (DependencySubsystemVector vector : subsystems) { for (DependencySubsystemVector vector : subsystems) {
logger.diag("Initializing subsystem " + vector.getMainClass().getName() + " (" + vector.getMainClass().getClass().getName() + ")"); logger.diag("Initializing subsystem " + vector.getMainClass().getName() + " (" + vector.getMainClass().getClass().getName() + ")");

View file

@ -358,7 +358,7 @@ public final class EngineConfiguration extends Configuration {
optimizeSubsystemInitialization = true; optimizeSubsystemInitialization = true;
loggerLevel = LogLevel.INFORMATIONAL; loggerLevel = LogLevel.INFORMATIONAL;
loggerTemplate = "%log_color_primary%[%time_hour%:%time_minute%:%time_second%] [%log_level% %log_path%%log_metadata%] %log_color_secondary%%log_message%<reset>"; 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%<reset>";
loggerImmediateShutdown = false; loggerImmediateShutdown = false;
loggerForceStandardOutput = false; loggerForceStandardOutput = false;
loggerPollingSpeed = 5; loggerPollingSpeed = 5;

View file

@ -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 <https://www.gnu.org/licenses/>.
*/
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);
}
}

View file

@ -20,7 +20,6 @@
package de.staropensource.sosengine.base.logging; package de.staropensource.sosengine.base.logging;
import de.staropensource.sosengine.base.EngineConfiguration; 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.internal.placeholders.logger.LogPath;
import de.staropensource.sosengine.base.types.logging.LogLevel; import de.staropensource.sosengine.base.types.logging.LogLevel;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -70,7 +69,7 @@ public final class InitLogger {
// This is done manually to avoid depending on PlaceholderEngine // This is done manually to avoid depending on PlaceholderEngine
base = new de.staropensource.sosengine.base.internal.placeholders.logger.LogLevel(level).replace(base); base = new de.staropensource.sosengine.base.internal.placeholders.logger.LogLevel(level).replace(base);
base = new LogPath(issuerClass).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 // Invoke LoggerImpl#postPlaceholder
base = Logger.getLoggerImplementation().postPlaceholder(level, issuerClass, issuerOrigin, issuerMetadata, message, base); base = Logger.getLoggerImplementation().postPlaceholder(level, issuerClass, issuerOrigin, issuerMetadata, message, base);

View file

@ -22,7 +22,6 @@ package de.staropensource.sosengine.base.logging;
import de.staropensource.sosengine.base.Engine; import de.staropensource.sosengine.base.Engine;
import de.staropensource.sosengine.base.EngineConfiguration; import de.staropensource.sosengine.base.EngineConfiguration;
import de.staropensource.sosengine.base.classes.LoggerImplementation; 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.classes.helpers.EventHelper;
import de.staropensource.sosengine.base.events.LogEvent; import de.staropensource.sosengine.base.events.LogEvent;
import de.staropensource.sosengine.base.internal.placeholders.logger.*; 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.LogRule;
import de.staropensource.sosengine.base.types.logging.LogRuleType; import de.staropensource.sosengine.base.types.logging.LogRuleType;
import de.staropensource.sosengine.base.utility.PlaceholderEngine; import de.staropensource.sosengine.base.utility.PlaceholderEngine;
import de.staropensource.sosengine.base.utility.converter.EmptyShortcodeConverter;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -41,6 +41,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Scanner;
/** /**
* Provides the engine's logging infrastructure, except for * Provides the engine's logging infrastructure, except for
@ -186,7 +187,7 @@ public final class Logger {
* @since v1-alpha1 * @since v1-alpha1
*/ */
private static void processLogMessage(@NotNull LogLevel level, @NotNull Class<?> issuerClass, @NotNull String issuerOrigin, @Nullable String issuerMetadata, @NotNull String message) { 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) { for (LogRule rule : activeRules) {
if (rule.evaluate(level, issuerClass, issuerOrigin, issuerMetadata, message)) { if (rule.evaluate(level, issuerClass, issuerOrigin, issuerMetadata, message)) {
if (rule.getType() == LogRuleType.WHITELIST) break; // Continue processing if (rule.getType() == LogRuleType.WHITELIST) break; // Continue processing
@ -195,28 +196,73 @@ public final class Logger {
} }
// Invoke LoggerImpl#prePlaceholder // Invoke LoggerImpl#prePlaceholder
String base = loggerImplementation.prePlaceholder(level, issuerClass, issuerOrigin, issuerMetadata, message, EngineConfiguration.getInstance().getLoggerTemplate()); String format = loggerImplementation.prePlaceholder(level, issuerClass, issuerOrigin, issuerMetadata, message, EngineConfiguration.getInstance().getLoggerTemplate());
if (base == null) if (format == null)
base = EngineConfiguration.getInstance().getLoggerTemplate(); format = 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));
// Replace placeholders // 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 // Invoke LoggerImpl#postPlaceholder
base = loggerImplementation.postPlaceholder(level, issuerClass, issuerOrigin, issuerMetadata, message, base); format = loggerImplementation.postPlaceholder(level, issuerClass, issuerOrigin, issuerMetadata, message, format);
// Call event // Call event
if (!(issuerClass.getName().equals("de.staropensource.sosengine.slf4j_compat.CompatibilityLogger") 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); new LogEvent().callEvent(level, issuerClass, issuerOrigin, issuerMetadata, message);
// Print log message by invoking LoggerImpl#print // Print log message by invoking LoggerImpl#print
loggerImplementation.print(level, issuerClass, issuerOrigin, issuerMetadata, message, base); loggerImplementation.print(level, issuerClass, issuerOrigin, issuerMetadata, message, format);
} }
/** /**