From 9f9dac11d97f547151023d30b371db781bfd4a5c Mon Sep 17 00:00:00 2001 From: Minecrell Date: Fri, 22 Sep 2017 12:46:47 +0200 Subject: [PATCH] Use Log4j2 for logging and TerminalConsoleAppender for console diff --git a/bootstrap/pom.xml b/bootstrap/pom.xml index ee76507c..e7bc7a5d 100644 --- a/bootstrap/pom.xml +++ b/bootstrap/pom.xml @@ -80,7 +80,17 @@ + + + + + + com.github.edwgiz + maven-shade-plugin.log4j2-cachefile-transformer + 2.8.1 + + diff --git a/bootstrap/src/main/java/net/md_5/bungee/BungeeCordLauncher.java b/bootstrap/src/main/java/net/md_5/bungee/BungeeCordLauncher.java index 2efe7211..f5270655 100644 --- a/bootstrap/src/main/java/net/md_5/bungee/BungeeCordLauncher.java +++ b/bootstrap/src/main/java/net/md_5/bungee/BungeeCordLauncher.java @@ -57,6 +57,9 @@ public class BungeeCordLauncher if ( !options.has( "noconsole" ) ) { + // Waterfall start - Use TerminalConsoleAppender + new io.github.waterfallmc.waterfall.console.WaterfallConsole().start(); + /* String line; while ( bungee.isRunning && ( line = bungee.getConsoleReader().readLine( ">" ) ) != null ) { @@ -65,6 +68,8 @@ public class BungeeCordLauncher bungee.getConsole().sendMessage( new ComponentBuilder( "Command not found" ).color( ChatColor.RED ).create() ); } } + */ + // Waterfall end } } } diff --git a/log4j/pom.xml b/log4j/pom.xml new file mode 100644 index 00000000..36fceb93 --- /dev/null +++ b/log4j/pom.xml @@ -0,0 +1,48 @@ + + 4.0.0 + + + io.github.waterfallmc + waterfall-parent + 1.13-SNAPSHOT + ../pom.xml + + + io.github.waterfallmc + waterfall-log4j + 1.13-SNAPSHOT + jar + + Waterfall-Log + Simplistic and performant Log4j2 based logger and console API designed for use with Waterfall and Minecraft related applications. + + + 2.11.0 + + + + + + org.apache.logging.log4j + log4j-core + ${log4j2.version} + + + org.apache.logging.log4j + log4j-iostreams + ${log4j2.version} + + + org.apache.logging.log4j + log4j-jul + ${log4j2.version} + + + com.lmax + disruptor + 3.4.2 + runtime + + + diff --git a/log4j/src/main/java/io/github/waterfallmc/waterfall/log4j/Log4JLogHandler.java b/log4j/src/main/java/io/github/waterfallmc/waterfall/log4j/Log4JLogHandler.java new file mode 100644 index 00000000..d5a1955b --- /dev/null +++ b/log4j/src/main/java/io/github/waterfallmc/waterfall/log4j/Log4JLogHandler.java @@ -0,0 +1,55 @@ +package io.github.waterfallmc.waterfall.log4j; + +import com.google.common.base.Strings; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.jul.LevelTranslator; +import org.apache.logging.log4j.message.MessageFormatMessage; + +import java.util.Map; +import java.util.MissingResourceException; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Handler; +import java.util.logging.LogRecord; + +/** + * A {@link Handler} that forwards all log messages to the Log4J logger. + * + *

We don't use Log4J's custom JUL LogManager currently, because it breaks + * adding custom handlers to JUL loggers. Some plugins may depend on that + * functionality...

+ */ +class Log4JLogHandler extends Handler { + + private final Map cache = new ConcurrentHashMap<>(); + + @Override + public void publish(LogRecord record) { + Logger logger = cache.computeIfAbsent(Strings.nullToEmpty(record.getLoggerName()), LogManager::getLogger); + + String message = record.getMessage(); + if (record.getResourceBundle() != null) { + try { + message = record.getResourceBundle().getString(message); + } catch (MissingResourceException ignored) { + } + } + + final Level level = LevelTranslator.toLevel(record.getLevel()); + if (record.getParameters() != null && record.getParameters().length > 0) { + logger.log(level, new MessageFormatMessage(message, record.getParameters()), record.getThrown()); + } else { + logger.log(level, message, record.getThrown()); + } + } + + @Override + public void flush() { + } + + @Override + public void close() { + } + +} diff --git a/log4j/src/main/java/io/github/waterfallmc/waterfall/log4j/WaterfallLogger.java b/log4j/src/main/java/io/github/waterfallmc/waterfall/log4j/WaterfallLogger.java new file mode 100644 index 00000000..a0f7ed01 --- /dev/null +++ b/log4j/src/main/java/io/github/waterfallmc/waterfall/log4j/WaterfallLogger.java @@ -0,0 +1,33 @@ +package io.github.waterfallmc.waterfall.log4j; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.io.IoBuilder; +import java.util.logging.Handler; +import java.util.logging.Logger; + +public final class WaterfallLogger { + + private WaterfallLogger() { + } + + public static Logger create() { + org.apache.logging.log4j.Logger redirect = LogManager.getRootLogger(); + System.setOut(IoBuilder.forLogger(redirect).setLevel(Level.INFO).buildPrintStream()); + System.setErr(IoBuilder.forLogger(redirect).setLevel(Level.ERROR).buildPrintStream()); + + Logger root = Logger.getLogger(""); + root.setUseParentHandlers(false); + + // Remove existing handlers + for (Handler handler : root.getHandlers()) { + root.removeHandler(handler); + } + + // Setup forward log handler + root.addHandler(new Log4JLogHandler()); + + return Logger.getLogger("BungeeCord"); + } + +} diff --git a/log4j/src/main/resources/log4j2.component.properties b/log4j/src/main/resources/log4j2.component.properties new file mode 100644 index 00000000..6ed08f31 --- /dev/null +++ b/log4j/src/main/resources/log4j2.component.properties @@ -0,0 +1 @@ +log4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector diff --git a/log4j/src/main/resources/log4j2.xml b/log4j/src/main/resources/log4j2.xml new file mode 100644 index 00000000..93ce3b14 --- /dev/null +++ b/log4j/src/main/resources/log4j2.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index 79493df2..0183bf9c 100644 --- a/pom.xml +++ b/pom.xml @@ -56,6 +56,7 @@ config event log + log4j module protocol proxy diff --git a/proxy/pom.xml b/proxy/pom.xml index 2efeaa9e..df84d6f1 100644 --- a/proxy/pom.xml +++ b/proxy/pom.xml @@ -70,7 +70,7 @@ io.github.waterfallmc - waterfall-log + waterfall-log4j ${project.version} compile @@ -98,6 +98,20 @@ 5.1.46 runtime + + + + net.minecrell + terminalconsoleappender + 1.1.1 + + + net.java.dev.jna + jna + 4.5.2 + runtime + + diff --git a/proxy/src/main/java/Test.java b/proxy/src/main/java/Test.java index 446dfe2f..f036efcd 100644 --- a/proxy/src/main/java/Test.java +++ b/proxy/src/main/java/Test.java @@ -22,6 +22,9 @@ public class Test bungee.getLogger().info( "Enabled Waterfall version " + bungee.getVersion() ); bungee.start(); + // Waterfall start - Use TerminalConsoleAppender + new io.github.waterfallmc.waterfall.console.WaterfallConsole().start(); + /* while ( bungee.isRunning ) { String line = bungee.getConsoleReader().readLine( ">" ); @@ -33,5 +36,7 @@ public class Test } } } + */ + // Waterfall end } } diff --git a/proxy/src/main/java/io/github/waterfallmc/waterfall/console/WaterfallConsole.java b/proxy/src/main/java/io/github/waterfallmc/waterfall/console/WaterfallConsole.java new file mode 100644 index 00000000..765d24bc --- /dev/null +++ b/proxy/src/main/java/io/github/waterfallmc/waterfall/console/WaterfallConsole.java @@ -0,0 +1,39 @@ +package io.github.waterfallmc.waterfall.console; + +import net.md_5.bungee.BungeeCord; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.chat.ComponentBuilder; +import net.minecrell.terminalconsole.SimpleTerminalConsole; +import org.jline.reader.LineReader; +import org.jline.reader.LineReaderBuilder; + +public final class WaterfallConsole extends SimpleTerminalConsole { + + @Override + protected LineReader buildReader(LineReaderBuilder builder) { + ProxyServer proxy = ProxyServer.getInstance(); + return super.buildReader(builder + .appName(proxy.getName()) + ); + } + + @Override + protected boolean isRunning() { + return BungeeCord.getInstance().isRunning; + } + + @Override + protected void runCommand(String command) { + ProxyServer proxy = ProxyServer.getInstance(); + if (!proxy.getPluginManager().dispatchCommand(proxy.getConsole(), command)) { + proxy.getConsole().sendMessage(new ComponentBuilder("Command not found").color(ChatColor.RED).create()); + } + } + + @Override + protected void shutdown() { + ProxyServer.getInstance().stop(); + } + +} diff --git a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java index 09d53fea..47d4c585 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java @@ -45,7 +45,6 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.Logger; -import jline.console.ConsoleReader; import lombok.Getter; import lombok.Setter; import lombok.Synchronized; @@ -78,14 +77,11 @@ import net.md_5.bungee.command.CommandEnd; import net.md_5.bungee.command.CommandIP; import net.md_5.bungee.command.CommandPerms; import net.md_5.bungee.command.CommandReload; -import net.md_5.bungee.command.ConsoleCommandCompleter; import net.md_5.bungee.command.ConsoleCommandSender; import net.md_5.bungee.compress.CompressFactory; import net.md_5.bungee.conf.Configuration; import net.md_5.bungee.conf.YamlConfig; import net.md_5.bungee.forge.ForgeConstants; -import net.md_5.bungee.log.BungeeLogger; -import net.md_5.bungee.log.LoggingOutputStream; import net.md_5.bungee.module.ModuleManager; import net.md_5.bungee.netty.PipelineUtils; import net.md_5.bungee.protocol.DefinedPacket; @@ -95,7 +91,6 @@ import net.md_5.bungee.protocol.packet.PluginMessage; import net.md_5.bungee.query.RemoteQuery; import net.md_5.bungee.scheduler.BungeeScheduler; import net.md_5.bungee.util.CaseInsensitiveMap; -import org.fusesource.jansi.AnsiConsole; /** * Main BungeeCord proxy class. @@ -151,8 +146,12 @@ public class BungeeCord extends ProxyServer private final File pluginsFolder = new File( "plugins" ); @Getter private final BungeeScheduler scheduler = new BungeeScheduler(); + // Waterfall start - Remove ConsoleReader for JLine 3 update + /* @Getter private final ConsoleReader consoleReader; + */ + // Waterfall end @Getter private final Logger logger; public final Gson gson = new GsonBuilder() @@ -194,6 +193,8 @@ public class BungeeCord extends ProxyServer } reloadMessages(); + // Waterfall start - Use TerminalConsoleAppender and Log4J + /* // This is a workaround for quite possibly the weirdest bug I have ever encountered in my life! // When jansi attempts to extract its natives, by default it tries to extract a specific version, // using the loading class's implementation version. Normally this works completely fine, @@ -212,6 +213,9 @@ public class BungeeCord extends ProxyServer logger = new BungeeLogger( "BungeeCord", "proxy.log", consoleReader ); System.setErr( new PrintStream( new LoggingOutputStream( logger, Level.SEVERE ), true ) ); System.setOut( new PrintStream( new LoggingOutputStream( logger, Level.INFO ), true ) ); + */ + logger = io.github.waterfallmc.waterfall.log4j.WaterfallLogger.create(); + // Waterfall end pluginManager = new PluginManager( this ); getPluginManager().registerCommand( null, new CommandReload() ); diff --git a/proxy/src/main/java/net/md_5/bungee/command/ConsoleCommandCompleter.java b/proxy/src/main/java/net/md_5/bungee/command/ConsoleCommandCompleter.java deleted file mode 100644 index bd52d880..00000000 --- a/proxy/src/main/java/net/md_5/bungee/command/ConsoleCommandCompleter.java +++ /dev/null @@ -1,25 +0,0 @@ -package net.md_5.bungee.command; - -import java.util.ArrayList; -import java.util.List; -import jline.console.completer.Completer; -import lombok.RequiredArgsConstructor; -import net.md_5.bungee.api.ProxyServer; - -@RequiredArgsConstructor -public class ConsoleCommandCompleter implements Completer -{ - - private final ProxyServer proxy; - - @Override - public int complete(String buffer, int cursor, List candidates) - { - List suggestions = new ArrayList<>(); - proxy.getPluginManager().dispatchCommand( proxy.getConsole(), buffer, suggestions ); - candidates.addAll( suggestions ); - - int lastSpace = buffer.lastIndexOf( ' ' ); - return ( lastSpace == -1 ) ? cursor - buffer.length() : cursor - ( buffer.length() - lastSpace - 1 ); - } -} diff --git a/proxy/src/main/java/net/md_5/bungee/module/ModuleManager.java b/proxy/src/main/java/net/md_5/bungee/module/ModuleManager.java index 10366c88..8c5cc949 100644 --- a/proxy/src/main/java/net/md_5/bungee/module/ModuleManager.java +++ b/proxy/src/main/java/net/md_5/bungee/module/ModuleManager.java @@ -42,7 +42,7 @@ public class ModuleManager ModuleVersion bungeeVersion = ModuleVersion.parse( proxy.getVersion() ); if ( bungeeVersion == null ) { - System.out.println( "Couldn't detect bungee version. Custom build?" ); + proxy.getLogger().warning( "Couldn't detect bungee version. Custom build?" ); // Waterfall - Use logger return; } -- 2.18.0