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() {
|
||||
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.logging.CrashHandler;
|
||||
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.logging.LogLevel;
|
||||
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.
|
||||
* This also causes messages to be buffered.
|
||||
* <p>
|
||||
* 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
|
||||
* @since v1-alpha1
|
||||
* @since v1-alpha4
|
||||
* -- GETTER --
|
||||
* Gets the value for {@link #loggerPollingSpeed}.
|
||||
*
|
||||
* @return variable value
|
||||
* @see #loggerPollingSpeed
|
||||
* @since v1-alpha1
|
||||
* @since v1-alpha4
|
||||
*/
|
||||
private int loggerPollingSpeed;
|
||||
|
||||
|
@ -327,7 +332,7 @@ public final class EngineConfiguration extends Configuration {
|
|||
|
||||
// Start logging thread automatically
|
||||
if (optimizeLogging && Engine.getInstance().getState() == EngineState.RUNNING)
|
||||
Logger.startLoggingThread();
|
||||
LoggingThread.startThread();
|
||||
}
|
||||
case "optimizeEvents" -> optimizeEvents = parser.getBoolean(group + property);
|
||||
case "optimizeSubsystemInitialization" -> optimizeSubsystemInitialization = parser.getBoolean(group + property);
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
@ -32,7 +32,7 @@ import org.jetbrains.annotations.Nullable;
|
|||
* @param issuerOrigin Origin of the issuer.
|
||||
* @param issuerMetadata Metadata about the issuer.
|
||||
* @param message Message of the log call.
|
||||
* @see Logger#startLoggingThread()
|
||||
* @see LoggingThread#startThread()
|
||||
* @since v1-alpha1
|
||||
*/
|
||||
@SuppressWarnings({ "unused" })
|
||||
|
|
|
@ -21,18 +21,17 @@ package de.staropensource.sosengine.base.logging;
|
|||
|
||||
import de.staropensource.sosengine.base.Engine;
|
||||
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.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.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.LogRule;
|
||||
import de.staropensource.sosengine.base.type.logging.LogRuleType;
|
||||
import de.staropensource.sosengine.base.utility.PlaceholderEngine;
|
||||
import de.staropensource.sosengine.base.implementation.shortcode.EmptyShortcodeConverter;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
@ -53,20 +52,6 @@ import java.util.Scanner;
|
|||
*/
|
||||
@SuppressWarnings({ "JavadocDeclaration" })
|
||||
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.
|
||||
*
|
||||
|
@ -116,46 +101,6 @@ public final class 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.
|
||||
*
|
||||
|
|
|
@ -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