Compare commits
5 commits
390a5cd227
...
4bbc1fd683
Author | SHA1 | Date | |
---|---|---|---|
4bbc1fd683 | |||
770c9b5c6e | |||
c9bf6126a0 | |||
e21ea102c7 | |||
21973ffe6c |
5 changed files with 159 additions and 64 deletions
|
@ -344,7 +344,7 @@ public final class Engine extends SubsystemClass {
|
||||||
public void startThreads() {
|
public void startThreads() {
|
||||||
logger.diag("Starting threads");
|
logger.diag("Starting threads");
|
||||||
|
|
||||||
Logger.startLoggingThread();
|
LoggingThread.startThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -24,6 +24,7 @@ import de.staropensource.sosengine.base.implementable.Configuration;
|
||||||
import de.staropensource.sosengine.base.implementable.helper.EventHelper;
|
import de.staropensource.sosengine.base.implementable.helper.EventHelper;
|
||||||
import de.staropensource.sosengine.base.logging.CrashHandler;
|
import de.staropensource.sosengine.base.logging.CrashHandler;
|
||||||
import de.staropensource.sosengine.base.logging.Logger;
|
import de.staropensource.sosengine.base.logging.Logger;
|
||||||
|
import de.staropensource.sosengine.base.logging.LoggingThread;
|
||||||
import de.staropensource.sosengine.base.type.EngineState;
|
import de.staropensource.sosengine.base.type.EngineState;
|
||||||
import de.staropensource.sosengine.base.type.logging.LogLevel;
|
import de.staropensource.sosengine.base.type.logging.LogLevel;
|
||||||
import de.staropensource.sosengine.base.type.vector.Vec2f;
|
import de.staropensource.sosengine.base.type.vector.Vec2f;
|
||||||
|
@ -217,16 +218,20 @@ public final class EngineConfiguration extends Configuration {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains how fast the logging thread will poll for queued messages.
|
* Contains how fast the logging thread will poll for queued messages.
|
||||||
|
* This also causes messages to be buffered.
|
||||||
|
* <p>
|
||||||
* Only applies if {@code optimizeLogging} is turned on.
|
* Only applies if {@code optimizeLogging} is turned on.
|
||||||
|
* Values below {@code 1} will poll for queued messages as fast as it can.
|
||||||
|
* This however has pretty much no benefit. Leave it at {@code 5}, it works quite well.
|
||||||
*
|
*
|
||||||
* @see #optimizeLogging
|
* @see #optimizeLogging
|
||||||
* @since v1-alpha1
|
* @since v1-alpha4
|
||||||
* -- GETTER --
|
* -- GETTER --
|
||||||
* Gets the value for {@link #loggerPollingSpeed}.
|
* Gets the value for {@link #loggerPollingSpeed}.
|
||||||
*
|
*
|
||||||
* @return variable value
|
* @return variable value
|
||||||
* @see #loggerPollingSpeed
|
* @see #loggerPollingSpeed
|
||||||
* @since v1-alpha1
|
* @since v1-alpha4
|
||||||
*/
|
*/
|
||||||
private int loggerPollingSpeed;
|
private int loggerPollingSpeed;
|
||||||
|
|
||||||
|
@ -327,7 +332,7 @@ public final class EngineConfiguration extends Configuration {
|
||||||
|
|
||||||
// Start logging thread automatically
|
// Start logging thread automatically
|
||||||
if (optimizeLogging && Engine.getInstance().getState() == EngineState.RUNNING)
|
if (optimizeLogging && Engine.getInstance().getState() == EngineState.RUNNING)
|
||||||
Logger.startLoggingThread();
|
LoggingThread.startThread();
|
||||||
}
|
}
|
||||||
case "optimizeEvents" -> optimizeEvents = parser.getBoolean(group + property);
|
case "optimizeEvents" -> optimizeEvents = parser.getBoolean(group + property);
|
||||||
case "optimizeSubsystemInitialization" -> optimizeSubsystemInitialization = parser.getBoolean(group + property);
|
case "optimizeSubsystemInitialization" -> optimizeSubsystemInitialization = parser.getBoolean(group + property);
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
package de.staropensource.sosengine.base.internal.type;
|
package de.staropensource.sosengine.base.internal.type;
|
||||||
|
|
||||||
import de.staropensource.sosengine.base.logging.Logger;
|
import de.staropensource.sosengine.base.logging.LoggingThread;
|
||||||
import de.staropensource.sosengine.base.type.logging.LogLevel;
|
import de.staropensource.sosengine.base.type.logging.LogLevel;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
@ -32,7 +32,7 @@ import org.jetbrains.annotations.Nullable;
|
||||||
* @param issuerOrigin Origin of the issuer.
|
* @param issuerOrigin Origin of the issuer.
|
||||||
* @param issuerMetadata Metadata about the issuer.
|
* @param issuerMetadata Metadata about the issuer.
|
||||||
* @param message Message of the log call.
|
* @param message Message of the log call.
|
||||||
* @see Logger#startLoggingThread()
|
* @see LoggingThread#startThread()
|
||||||
* @since v1-alpha1
|
* @since v1-alpha1
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "unused" })
|
@SuppressWarnings({ "unused" })
|
||||||
|
|
|
@ -21,18 +21,17 @@ 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.event.LogEvent;
|
||||||
import de.staropensource.sosengine.base.implementable.LoggingAdapter;
|
import de.staropensource.sosengine.base.implementable.LoggingAdapter;
|
||||||
import de.staropensource.sosengine.base.implementable.helper.EventHelper;
|
import de.staropensource.sosengine.base.implementable.helper.EventHelper;
|
||||||
import de.staropensource.sosengine.base.event.LogEvent;
|
import de.staropensource.sosengine.base.implementation.logging.PlainLoggingAdapter;
|
||||||
|
import de.staropensource.sosengine.base.implementation.shortcode.EmptyShortcodeConverter;
|
||||||
import de.staropensource.sosengine.base.internal.implementation.placeholder.logger.*;
|
import de.staropensource.sosengine.base.internal.implementation.placeholder.logger.*;
|
||||||
import de.staropensource.sosengine.base.internal.type.QueuedLogMessage;
|
import de.staropensource.sosengine.base.internal.type.QueuedLogMessage;
|
||||||
import de.staropensource.sosengine.base.implementation.logging.PlainLoggingAdapter;
|
|
||||||
import de.staropensource.sosengine.base.type.EngineState;
|
|
||||||
import de.staropensource.sosengine.base.type.logging.LogLevel;
|
import de.staropensource.sosengine.base.type.logging.LogLevel;
|
||||||
import de.staropensource.sosengine.base.type.logging.LogRule;
|
import de.staropensource.sosengine.base.type.logging.LogRule;
|
||||||
import de.staropensource.sosengine.base.type.logging.LogRuleType;
|
import de.staropensource.sosengine.base.type.logging.LogRuleType;
|
||||||
import de.staropensource.sosengine.base.utility.PlaceholderEngine;
|
import de.staropensource.sosengine.base.utility.PlaceholderEngine;
|
||||||
import de.staropensource.sosengine.base.implementation.shortcode.EmptyShortcodeConverter;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
@ -53,20 +52,6 @@ import java.util.Scanner;
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "JavadocDeclaration" })
|
@SuppressWarnings({ "JavadocDeclaration" })
|
||||||
public final class Logger {
|
public final class Logger {
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains a reference to the logging thread.
|
|
||||||
*
|
|
||||||
* @since v1-alpha1
|
|
||||||
* -- GETTER --
|
|
||||||
* Returns a reference the logging thread.
|
|
||||||
*
|
|
||||||
* @return logging thread reference
|
|
||||||
* @since v1-alpha1
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private static @Nullable Thread loggingThread;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains a list of {@link QueuedLogMessage}s.
|
* Contains a list of {@link QueuedLogMessage}s.
|
||||||
*
|
*
|
||||||
|
@ -116,46 +101,6 @@ public final class Logger {
|
||||||
*/
|
*/
|
||||||
public Logger() {}
|
public Logger() {}
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts the logging thread.
|
|
||||||
*
|
|
||||||
* @since v1-alpha1
|
|
||||||
* @see #getLoggingThread()
|
|
||||||
*/
|
|
||||||
public static void startLoggingThread() {
|
|
||||||
if (loggingThread == null) {
|
|
||||||
// Logging thread not defined, create and start new one
|
|
||||||
Runnable threadLogic = () -> {
|
|
||||||
while (true) { // Run in loop
|
|
||||||
// Stop thread when engine is shutting down
|
|
||||||
if (Engine.getInstance().getState() == EngineState.SHUTDOWN
|
|
||||||
|| Engine.getInstance().getState() == EngineState.CRASHED
|
|
||||||
|| !EngineConfiguration.getInstance().isOptimizeLogging())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Process all log messages
|
|
||||||
flushLogMessages();
|
|
||||||
|
|
||||||
// Sleep for whatever has been configured
|
|
||||||
long sleepDuration = System.currentTimeMillis() + EngineConfiguration.getInstance().getLoggerPollingSpeed();
|
|
||||||
while (System.currentTimeMillis() < sleepDuration)
|
|
||||||
Thread.onSpinWait();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
loggingThread = Thread
|
|
||||||
.ofPlatform()
|
|
||||||
.daemon()
|
|
||||||
.name("Logging thread")
|
|
||||||
.group(Engine.getThreadGroup())
|
|
||||||
.stackSize(10)
|
|
||||||
.start(threadLogic);
|
|
||||||
} else
|
|
||||||
// Restart logging thread if dead
|
|
||||||
if (!loggingThread.isAlive())
|
|
||||||
loggingThread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints all queued log messages.
|
* Prints all queued log messages.
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,145 @@
|
||||||
|
/*
|
||||||
|
* STAROPENSOURCE ENGINE SOURCE FILE
|
||||||
|
* Copyright (c) 2024 The StarOpenSource Engine Authors
|
||||||
|
* 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.logging;
|
||||||
|
|
||||||
|
import de.staropensource.sosengine.base.Engine;
|
||||||
|
import de.staropensource.sosengine.base.EngineConfiguration;
|
||||||
|
import de.staropensource.sosengine.base.type.EngineState;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controls the logging thread of the engine.
|
||||||
|
*
|
||||||
|
* @since v1-alpha4
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@SuppressWarnings({ "JavadocDeclaration" })
|
||||||
|
public class LoggingThread {
|
||||||
|
/**
|
||||||
|
* Contains the {@link LoggerInstance} for this instance.
|
||||||
|
*
|
||||||
|
* @see LoggerInstance
|
||||||
|
* @since v1-alpha4
|
||||||
|
*/
|
||||||
|
protected static final @NotNull LoggerInstance logger = new LoggerInstance.Builder().setClazz(LoggingThread.class).setOrigin("ENGINE").build();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the logic of the logging thread.
|
||||||
|
*
|
||||||
|
* @since v1-alpha4
|
||||||
|
*/
|
||||||
|
private static final @NotNull Runnable loggingThreadLogic = () -> {
|
||||||
|
while (!Thread.currentThread().isInterrupted()) {
|
||||||
|
// Stop thread when engine is shutting down
|
||||||
|
if (Engine.getInstance().getState() == EngineState.SHUTDOWN
|
||||||
|
|| Engine.getInstance().getState() == EngineState.CRASHED
|
||||||
|
|| !EngineConfiguration.getInstance().isOptimizeLogging())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Process all log messages
|
||||||
|
Logger.flushLogMessages();
|
||||||
|
|
||||||
|
// Sleep for whatever has been configured
|
||||||
|
if (EngineConfiguration.getInstance().getLoggerPollingSpeed() > 0) {
|
||||||
|
long sleepDuration = System.currentTimeMillis() + EngineConfiguration.getInstance().getLoggerPollingSpeed();
|
||||||
|
while (System.currentTimeMillis() < sleepDuration)
|
||||||
|
Thread.onSpinWait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains a reference to the logging thread.
|
||||||
|
*
|
||||||
|
* @since v1-alpha4
|
||||||
|
*/
|
||||||
|
private static Thread loggingThread;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs this class.
|
||||||
|
*
|
||||||
|
* @since v1-alpha4
|
||||||
|
*/
|
||||||
|
public LoggingThread() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reconstructs the {@link #loggingThread} thread.
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException if the logging thread's state is not {@link Thread.State#TERMINATED}
|
||||||
|
* @since v1-alpha4
|
||||||
|
*/
|
||||||
|
private static void reconstructThread() throws IllegalStateException {
|
||||||
|
if (loggingThread != null && loggingThread.getState() != Thread.State.TERMINATED)
|
||||||
|
throw new IllegalStateException("The logging thread needs to be terminated before reconstruction");
|
||||||
|
|
||||||
|
loggingThread = Thread
|
||||||
|
.ofPlatform()
|
||||||
|
.daemon()
|
||||||
|
.name("Logging thread")
|
||||||
|
.group(Engine.getThreadGroup())
|
||||||
|
.stackSize(10)
|
||||||
|
.unstarted(loggingThreadLogic);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the logging thread.
|
||||||
|
*
|
||||||
|
* @since v1-alpha4
|
||||||
|
* @throws IllegalStateException if thread reconstruction fails because the thread isn't {@link Thread.State#TERMINATED}, see {@link #reconstructThread()}
|
||||||
|
* @see #loggingThread
|
||||||
|
*/
|
||||||
|
public static void startThread() {
|
||||||
|
if (loggingThread == null)
|
||||||
|
reconstructThread();
|
||||||
|
|
||||||
|
if (loggingThread.isAlive()) {
|
||||||
|
// Executing the thread restart logic prevents blocking the current thread
|
||||||
|
// while still ensuring that the logging thread is properly restarted
|
||||||
|
Thread
|
||||||
|
.ofVirtual()
|
||||||
|
.name("Logging thread restart thread")
|
||||||
|
.start(() -> {
|
||||||
|
logger.diag("Restarting the logging thread");
|
||||||
|
|
||||||
|
loggingThread.interrupt();
|
||||||
|
|
||||||
|
// Make sure that the logging thread is dead before reconstructing and starting it
|
||||||
|
while (loggingThread.isAlive())
|
||||||
|
Thread.onSpinWait();
|
||||||
|
|
||||||
|
reconstructThread();
|
||||||
|
loggingThread.start();
|
||||||
|
});
|
||||||
|
} else
|
||||||
|
loggingThread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link Thread.State} of the logging thread.
|
||||||
|
*
|
||||||
|
* @return logging thread state
|
||||||
|
* @since v1-alpha4
|
||||||
|
* @see Thread.State
|
||||||
|
*/
|
||||||
|
public static @NotNull Thread.State getState() {
|
||||||
|
return loggingThread.getState();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue