mirror of
https://github.com/GeyserMC/Geyser.git
synced 2025-12-19 14:59:27 +00:00
Fix missing console logs with Geyser-Standalone gui present (#5376)
* Fix missing console logs with gui present * Properly redirect stdout & stderr & also redirect JUL
This commit is contained in:
@@ -40,4 +40,6 @@ tasks.named<JavaExec>("run") {
|
||||
dir.mkdirs()
|
||||
jvmArgs("-Dio.netty.leakDetection.level=PARANOID")
|
||||
workingDir = dir
|
||||
|
||||
standardInput = System.`in`
|
||||
}
|
||||
|
||||
@@ -32,12 +32,9 @@ import com.fasterxml.jackson.databind.introspect.AnnotatedField;
|
||||
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
|
||||
import io.netty.util.ResourceLeakDetector;
|
||||
import lombok.Getter;
|
||||
import net.minecrell.terminalconsole.TerminalConsoleAppender;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.core.Appender;
|
||||
import org.apache.logging.log4j.core.Logger;
|
||||
import org.apache.logging.log4j.core.appender.ConsoleAppender;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
@@ -92,6 +89,9 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
||||
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.DISABLED); // Can eat performance
|
||||
}
|
||||
|
||||
System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager");
|
||||
GeyserStandaloneLogger.setupStreams();
|
||||
|
||||
GeyserStandaloneBootstrap bootstrap = new GeyserStandaloneBootstrap();
|
||||
// Set defaults
|
||||
boolean useGuiOpts = bootstrap.useGui;
|
||||
@@ -175,17 +175,10 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
||||
@Override
|
||||
public void onGeyserInitialize() {
|
||||
log4jLogger = (Logger) LogManager.getRootLogger();
|
||||
for (Appender appender : log4jLogger.getAppenders().values()) {
|
||||
// Remove the appender that is not in use
|
||||
// Prevents multiple appenders/double logging and removes harmless errors
|
||||
if ((useGui && appender instanceof TerminalConsoleAppender) || (!useGui && appender instanceof ConsoleAppender)) {
|
||||
log4jLogger.removeAppender(appender);
|
||||
}
|
||||
}
|
||||
|
||||
if (useGui && gui == null) {
|
||||
gui = new GeyserStandaloneGUI(geyserLogger);
|
||||
gui.redirectSystemStreams();
|
||||
gui.addGuiAppender();
|
||||
gui.startUpdateThread();
|
||||
}
|
||||
|
||||
@@ -198,7 +191,7 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
||||
public void onGeyserEnable() {
|
||||
try {
|
||||
File configFile = FileUtils.fileOrCopiedFromResource(new File(configFilename), "config.yml",
|
||||
(x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
|
||||
(x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
|
||||
geyserConfig = FileUtils.loadConfig(configFile, GeyserStandaloneConfiguration.class);
|
||||
|
||||
handleArgsConfigOptions();
|
||||
@@ -246,9 +239,7 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
||||
|
||||
geyserPingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
|
||||
|
||||
if (!useGui) {
|
||||
geyserLogger.start(); // Throws an error otherwise
|
||||
}
|
||||
geyserLogger.start();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -261,7 +252,8 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
||||
Class<?> graphicsEnv = Class.forName("java.awt.GraphicsEnvironment");
|
||||
Method isHeadless = graphicsEnv.getDeclaredMethod("isHeadless");
|
||||
return (boolean) isHeadless.invoke(null);
|
||||
} catch (Exception ignore) { }
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -347,12 +339,12 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
||||
|
||||
// Get the ignored properties
|
||||
Set<String> ignoredProperties = OBJECT_MAPPER.getSerializationConfig().getAnnotationIntrospector()
|
||||
.findPropertyIgnoralByName(OBJECT_MAPPER.getSerializationConfig() ,beanDescription.getClassInfo()).getIgnored();
|
||||
.findPropertyIgnoralByName(OBJECT_MAPPER.getSerializationConfig(), beanDescription.getClassInfo()).getIgnored();
|
||||
|
||||
// Filter properties removing the ignored ones
|
||||
return properties.stream()
|
||||
.filter(property -> !ignoredProperties.contains(property.getName()))
|
||||
.collect(Collectors.toList());
|
||||
.filter(property -> !ignoredProperties.contains(property.getName()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,7 +28,10 @@ package org.geysermc.geyser.platform.standalone;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.minecrell.terminalconsole.SimpleTerminalConsole;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.core.config.Configurator;
|
||||
import org.apache.logging.log4j.io.IoBuilder;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.GeyserLogger;
|
||||
import org.geysermc.geyser.command.GeyserCommandSource;
|
||||
@@ -39,6 +42,15 @@ import org.jline.reader.LineReaderBuilder;
|
||||
|
||||
@Slf4j
|
||||
public class GeyserStandaloneLogger extends SimpleTerminalConsole implements GeyserLogger, GeyserCommandSource {
|
||||
private static final Logger logger = LogManager.getLogger("GeyserConsole");
|
||||
|
||||
/**
|
||||
* Sets up {@code System.out} and {@code System.err} to redirect to log4j.
|
||||
*/
|
||||
public static void setupStreams() {
|
||||
System.setOut(IoBuilder.forLogger(logger).setLevel(Level.INFO).buildPrintStream());
|
||||
System.setErr(IoBuilder.forLogger(logger).setLevel(Level.ERROR).buildPrintStream());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LineReader buildReader(LineReaderBuilder builder) {
|
||||
|
||||
@@ -25,7 +25,14 @@
|
||||
|
||||
package org.geysermc.geyser.platform.standalone.gui;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.core.LogEvent;
|
||||
import org.apache.logging.log4j.core.Logger;
|
||||
import org.apache.logging.log4j.core.appender.AbstractAppender;
|
||||
import org.apache.logging.log4j.core.config.NullConfiguration;
|
||||
import org.apache.logging.log4j.core.config.Property;
|
||||
import org.apache.logging.log4j.core.layout.PatternLayout;
|
||||
import org.apache.logging.log4j.core.pattern.PatternFormatter;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.GeyserLogger;
|
||||
import org.geysermc.geyser.command.CommandRegistry;
|
||||
@@ -36,11 +43,16 @@ import javax.swing.*;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
import javax.swing.text.Document;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ComponentAdapter;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -83,7 +95,8 @@ public class GeyserStandaloneGUI {
|
||||
// Remove Java UI look
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (Exception ignored) { }
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
// Show a confirm dialog on close
|
||||
frame.addWindowListener(new WindowAdapter() {
|
||||
@@ -181,7 +194,8 @@ public class GeyserStandaloneGUI {
|
||||
openButton.addActionListener(e -> {
|
||||
try {
|
||||
Desktop.getDesktop().open(new File("./"));
|
||||
} catch (IOException ignored) { }
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
});
|
||||
fileMenu.add(openButton);
|
||||
|
||||
@@ -245,29 +259,8 @@ public class GeyserStandaloneGUI {
|
||||
/**
|
||||
* Redirect the default io streams to the text pane
|
||||
*/
|
||||
public void redirectSystemStreams() {
|
||||
// Setup a new output stream to forward it to the text pane
|
||||
OutputStream out = new OutputStream() {
|
||||
@Override
|
||||
public void write(final int b) {
|
||||
appendConsole(String.valueOf((char) b));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte @NonNull [] b, int off, int len) {
|
||||
appendConsole(new String(b, off, len));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte @NonNull[] b) {
|
||||
write(b, 0, b.length);
|
||||
}
|
||||
};
|
||||
|
||||
// Override the system output streams
|
||||
System.setOut(new PrintStream(out, true));
|
||||
System.setErr(new PrintStream(out, true));
|
||||
|
||||
public void addGuiAppender() {
|
||||
new GUIAppender().start();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -354,4 +347,30 @@ public class GeyserStandaloneGUI {
|
||||
commandInput.setText(""); // clear the input
|
||||
}
|
||||
}
|
||||
|
||||
private class GUIAppender extends AbstractAppender {
|
||||
private static final List<PatternFormatter> FORMATTERS = PatternLayout.createPatternParser(new NullConfiguration())
|
||||
.parse(
|
||||
"[%d{HH:mm:ss} %style{%highlight{%level}{FATAL=red, ERROR=red, WARN=yellow bright, INFO=cyan bright, DEBUG=green, TRACE=white}}] %minecraftFormatting{%msg}%n",
|
||||
true,
|
||||
false,
|
||||
false
|
||||
);
|
||||
|
||||
protected GUIAppender() {
|
||||
super("GUIAppender", null, null, false, Property.EMPTY_ARRAY);
|
||||
|
||||
((Logger) LogManager.getRootLogger()).addAppender(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void append(LogEvent event) {
|
||||
StringBuilder formatted = new StringBuilder();
|
||||
for (PatternFormatter formatter : FORMATTERS) {
|
||||
formatter.format(event, formatted);
|
||||
}
|
||||
|
||||
appendConsole(formatted.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
<TerminalConsole name="TerminalConsole">
|
||||
<PatternLayout pattern="[%d{HH:mm:ss} %style{%highlight{%level}{FATAL=red, ERROR=red, WARN=yellow bright, INFO=cyan bright, DEBUG=green, TRACE=white}}] %minecraftFormatting{%msg}%n"/>
|
||||
</TerminalConsole>
|
||||
<Console name="Console" target="SYSTEM_OUT" follow="true">
|
||||
<PatternLayout pattern="[%d{HH:mm:ss} %style{%highlight{%level}{FATAL=red, ERROR=red, WARN=yellow bright, INFO=cyan bright, DEBUG=green, TRACE=white}}] %minecraftFormatting{%msg}%n"/>
|
||||
</Console>
|
||||
<RollingRandomAccessFile name="File" fileName="logs/latest.log" filePattern="logs/%d{yyyy-MM-dd}-%i.log.gz">
|
||||
<PatternLayout pattern="[%d{HH:mm:ss.SSS} %t/%level] %minecraftFormatting{%msg}{strip}%n"/>
|
||||
<Policies>
|
||||
@@ -18,7 +15,6 @@
|
||||
<Loggers>
|
||||
<Root level="INFO" >
|
||||
<AppenderRef ref="TerminalConsole"/>
|
||||
<AppenderRef ref="Console"/>
|
||||
<AppenderRef ref="File"/>
|
||||
<filters>
|
||||
<MarkerFilter marker="packet_logging" onMatch="DENY" onMismatch="ACCEPT" />
|
||||
|
||||
@@ -91,6 +91,8 @@ netty-transport-native-io_uring = { group = "io.netty.incubator", name = "netty-
|
||||
log4j-api = { group = "org.apache.logging.log4j", name = "log4j-api", version.ref = "log4j" }
|
||||
log4j-core = { group = "org.apache.logging.log4j", name = "log4j-core", version.ref = "log4j" }
|
||||
log4j-slf4j2-impl = { group = "org.apache.logging.log4j", name = "log4j-slf4j2-impl", version.ref = "log4j" }
|
||||
log4j-iostreams = { group = "org.apache.logging.log4j", name = "log4j-iostreams", version.ref = "log4j" }
|
||||
log4j-jul = { group = "org.apache.logging.log4j", name = "log4j-jul", version.ref = "log4j" }
|
||||
|
||||
jline-terminal = { group = "org.jline", name = "jline-terminal", version.ref = "jline" }
|
||||
jline-terminal-jna = { group = "org.jline", name = "jline-terminal-jna", version.ref = "jline" }
|
||||
@@ -160,6 +162,6 @@ runpaper = { id = "xyz.jpenilla.run-paper", version.ref = "runtask" }
|
||||
jackson = [ "jackson-annotations", "jackson-databind", "jackson-dataformat-yaml" ]
|
||||
fastutil = [ "fastutil-int-int-maps", "fastutil-int-long-maps", "fastutil-int-byte-maps", "fastutil-int-boolean-maps", "fastutil-object-int-maps", "fastutil-object-object-maps" ]
|
||||
adventure = [ "adventure-text-serializer-gson", "adventure-text-serializer-legacy", "adventure-text-serializer-plain" ]
|
||||
log4j = [ "log4j-api", "log4j-core", "log4j-slf4j2-impl" ]
|
||||
log4j = [ "log4j-api", "log4j-core", "log4j-slf4j2-impl", "log4j-iostreams", "log4j-jul" ]
|
||||
jline = [ "jline-terminal", "jline-terminal-jna", "jline-reader" ]
|
||||
protocol = [ "protocol-common", "protocol-codec", "protocol-connection" ]
|
||||
|
||||
Reference in New Issue
Block a user