diff --git a/base/src/main/java/de/staropensource/sosengine/base/classes/logging/LogRule.java b/base/src/main/java/de/staropensource/sosengine/base/classes/logging/LogRule.java new file mode 100644 index 00000000..b1a9cb0c --- /dev/null +++ b/base/src/main/java/de/staropensource/sosengine/base/classes/logging/LogRule.java @@ -0,0 +1,68 @@ +/* + * 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.classes.logging; + +import de.staropensource.sosengine.base.types.LogIssuer; +import de.staropensource.sosengine.base.types.LogLevel; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; + +/** + * Defines a rule used during logging to allow or prevent certain log calls. + * + * @since 1-alpha1 + */ +@SuppressWarnings({ "unused", "JavadocDeclaration", "JavadocBlankLines" }) +@Getter +public class LogRule { + /** + * Determines if the log rule should disallow or permit matching log calls. + * + * @see LogRuleType + * @since 1-alpha1 + * + * -- GETTER -- + * Returns if the log rule should disallow or permit matching log calls. + * + * @return rule type + * @see LogRuleType + * @since 1-alpha1 + */ + @NotNull + private final LogRuleType type; + + /** + * Constructor. + */ + public LogRule(@NotNull LogRuleType type) { + this.type = type; + } + + /** + * Evaluates the rule and returns if the rule matches. + * + * @param issuer issuer + * @param level log level + * @param message raw message + */ + public boolean evaluate(@NotNull LogIssuer issuer, @NotNull LogLevel level, @NotNull String message) { + return false; + } +} diff --git a/base/src/main/java/de/staropensource/sosengine/base/classes/logging/LogRuleType.java b/base/src/main/java/de/staropensource/sosengine/base/classes/logging/LogRuleType.java new file mode 100644 index 00000000..ea2be235 --- /dev/null +++ b/base/src/main/java/de/staropensource/sosengine/base/classes/logging/LogRuleType.java @@ -0,0 +1,43 @@ +/* + * 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.classes.logging; + +/** + * Used for determining if a {@link LogRule} should allow (whitelist) or prevent (blacklist) log call processing. + * + * @since 1-alpha1 + */ +@SuppressWarnings({ "unused" }) +public enum LogRuleType { + /** + * Indicates that log calls matching this rule will always be allowed, even if blacklisted. + * + * @since 1-alpha1 + */ + WHITELIST, + + /** + * Indicates that log calls matching this will always be disallowed except when whitelisted. + * + * @see LogRuleType#WHITELIST + * @since 1-alpha1 + */ + BLACKLIST +} 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 c973011a..ed85fcf2 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 @@ -21,6 +21,8 @@ package de.staropensource.sosengine.base.logging; import de.staropensource.sosengine.base.Engine; import de.staropensource.sosengine.base.EngineConfiguration; +import de.staropensource.sosengine.base.classes.logging.LogRule; +import de.staropensource.sosengine.base.classes.logging.LogRuleType; import de.staropensource.sosengine.base.classes.logging.LoggerImpl; import de.staropensource.sosengine.base.classes.Placeholder; import de.staropensource.sosengine.base.events.LogEvent; @@ -94,6 +96,20 @@ public final class Logger { */ private static final LinkedList queuedMessages = new LinkedList<>(); + /** + * Contains all active {@link LogRule}s. + * + * @since 1-alpha1 + * + * -- GETTER -- + * Returns all active {@link LogRule}s. + * + * @return active rules + * @since 1-alpha1 + */ + @Getter + private static final List activeRules = new ArrayList<>(); + /** * Constructor. * @@ -109,24 +125,25 @@ public final class Logger { */ public static void startLoggingThread() { if (loggingThread == null) { + // Logging thread not defined, create and start new one loggingThread = Thread.ofPlatform().start(() -> { - while (true) { + while (true) { // Run in loop + // Stop thread when engine is shutting down if (Engine.getInstance().isShuttingDown()) return; + // Process all log messages flushLogMessages(); + // Sleep for whatever has been configured try { //noinspection BusyWait Thread.sleep(EngineConfiguration.getInstance().getLoggerPollingSpeed()); - } catch (Exception ignored) { - } - - if (Engine.getInstance().isShuttingDown()) - return; + } catch (Exception ignored) {} } }); } else { + // Restart logging thread if dead if (!loggingThread.isAlive()) loggingThread.start(); } @@ -138,12 +155,15 @@ public final class Logger { * @since 1-alpha1 */ public static synchronized void flushLogMessages() { + // Only execute code if queued messages list is not empty if (!queuedMessages.isEmpty()) { + // Clone queued messages and clear original to avoid issues //noinspection unchecked LinkedList queuedMessagesCloned = (LinkedList) queuedMessages.clone(); queuedMessages.clear(); - for (QueuedLogMessage queuedLogMessage : queuedMessagesCloned) {// Check if level is allowed + // Invoke processLogMessage method for every queued message + for (QueuedLogMessage queuedLogMessage : queuedMessagesCloned) { processLogMessage(queuedLogMessage.getIssuer(), queuedLogMessage.getLevel(), queuedLogMessage.getMessage()); } } @@ -158,13 +178,22 @@ public final class Logger { * @since 1-alpha1 */ private static void processLogMessage(@NotNull LogIssuer issuer, @NotNull LogLevel level, @NotNull String message) { + // Check if level is allowed if (level.compareTo(EngineConfiguration.getInstance().getLoggerLevel()) < 0) return; + // Evaluate all active rules + for (LogRule rule : activeRules) { + if (rule.evaluate(issuer, level, message)) { + if (rule.getType() == LogRuleType.WHITELIST) break; // Continue processing + if (rule.getType() == LogRuleType.BLACKLIST) return; // Cancel processing + } + } + // Template for now, final log message later String base = EngineConfiguration.getInstance().getLoggerTemplate(); - // Execute LoggerImpl#prePlaceholder + // Invoke LoggerImpl#prePlaceholder base = loggerImplementation.prePlaceholder(level, issuer, base); // Create list of temporary placeholders @@ -183,14 +212,14 @@ public final class Logger { // Replace placeholders base = PlaceholderEngine.getInstance().process(base, temporaryPlaceholders); - // Execute LoggerImpl#postPlaceholder + // Invoke LoggerImpl#postPlaceholder base = loggerImplementation.postPlaceholder(level, issuer, base); // Call event if (!issuer.getClazz().getName().equals("de.staropensource.sosengine.slf4j_compat.CompatibilityLogger")) new LogEvent().callEvent(level, issuer, message); - // Print log message + // Print log message by invoking LoggerImpl#print loggerImplementation.print(level, issuer, base); } @@ -207,8 +236,10 @@ public final class Logger { if (Engine.getInstance() == null) return; if (EngineConfiguration.getInstance().isOptimizeLogging()) + // Optimizations enabled, add to message queue queuedMessages.add(new QueuedLogMessage(issuer, level, message)); else + // Optimizations disabled, print right away processLogMessage(issuer, level, message); }