Added logback logging

This commit is contained in:
Nan1t 2024-05-02 16:10:40 +03:00
parent 6bbde1f578
commit e9b6c888bc
19 changed files with 124 additions and 92 deletions

View File

@ -5,7 +5,7 @@ The main goal of this project is maximum simplicity with a minimum number of sen
The limbo is empty; there is no ability to set a schematic building since this is not necessary.
You can send useful information via chat or boss bar.
No plugins, no logs. The server is fully clear. It is only able keep a lot of players while the main server is down.
No plugins, no logs. The server is fully clear. It is only able to keep a lot of players while the main server is down.
General features:
* High performance. The server doesn't save or cache any useless (for limbo) data.
@ -14,7 +14,7 @@ General features:
* Support for [BungeeGuard](https://www.spigotmc.org/resources/79601/) handshake format.
* Multiple versions support.
* Fully configurable.
* Lightweight. App size around **2MB**.
* Lightweight. App size around **3MB**.
![](https://i.imgur.com/sT8p1Gz.png)
@ -56,8 +56,8 @@ The installation process is simple.
2. Put the jar file in the folder you want.
3. Create a start script as you did for Bukkit or BungeeCord, with a command like this:
`java -jar NanoLimbo-<version>.jar`
5. The server will create `settings.yml` file, which is the server configuration.
6. Configure it as you want and restart the server.
4. The server will create `settings.yml` file, which is the server configuration.
5. Configure it as you want and restart the server.
### Player info forwarding
@ -75,7 +75,7 @@ Then add your tokens to `tokens` list.
### Contributing
Feel free to create a pull request if you found some bug or optimization opportunity, or if you want
Feel free to create a pull request if you find some bug or optimization opportunity, or if you want
to add some functionality that is suitable for a limbo server and won't significantly load the server.
### Building

View File

@ -4,8 +4,8 @@ plugins {
id 'com.github.gmazzo.buildconfig' version '3.1.0'
}
group 'ru.nanit'
version '1.7'
group 'ua.nanit'
version '1.8'
compileJava {
options.encoding = "UTF-8"
@ -24,6 +24,7 @@ dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.3'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.3'
implementation 'ch.qos.logback:logback-classic:1.5.6'
implementation 'org.spongepowered:configurate-yaml:4.1.2'
implementation 'io.netty:netty-all:4.1.101.Final'
implementation 'net.kyori:adventure-nbt:4.14.0'
@ -44,7 +45,9 @@ shadowJar {
attributes('Main-Class': 'ua.nanit.limbo.NanoLimbo')
}
minimize()
minimize {
exclude(dependency('ch.qos.logback:logback-classic:.*:.*'))
}
}
test {

View File

@ -18,7 +18,7 @@
package ua.nanit.limbo;
import ua.nanit.limbo.server.LimboServer;
import ua.nanit.limbo.server.Logger;
import ua.nanit.limbo.server.Log;
public final class NanoLimbo {
@ -26,7 +26,7 @@ public final class NanoLimbo {
try {
new LimboServer().start();
} catch (Exception e) {
Logger.error("Cannot start server: ", e);
Log.error("Cannot start server: ", e);
}
}

View File

@ -36,7 +36,7 @@ import ua.nanit.limbo.protocol.packets.play.PacketKeepAlive;
import ua.nanit.limbo.protocol.registry.State;
import ua.nanit.limbo.protocol.registry.Version;
import ua.nanit.limbo.server.LimboServer;
import ua.nanit.limbo.server.Logger;
import ua.nanit.limbo.server.Log;
import ua.nanit.limbo.util.UuidUtil;
import javax.crypto.Mac;
@ -104,7 +104,7 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
if (channel.isActive()) {
Logger.error("Unhandled exception: ", cause);
Log.error("Unhandled exception: ", cause);
}
}
@ -312,7 +312,7 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
setAddress(socketAddressHostname);
gameProfile.setUuid(uuid);
Logger.debug("Successfully verified BungeeGuard token");
Log.debug("Successfully verified BungeeGuard token");
return true;
}

View File

@ -29,7 +29,7 @@ import ua.nanit.limbo.protocol.packets.status.PacketStatusPing;
import ua.nanit.limbo.protocol.packets.status.PacketStatusRequest;
import ua.nanit.limbo.protocol.packets.status.PacketStatusResponse;
import ua.nanit.limbo.server.LimboServer;
import ua.nanit.limbo.server.Logger;
import ua.nanit.limbo.server.Log;
import ua.nanit.limbo.util.UuidUtil;
import java.util.concurrent.ThreadLocalRandom;
@ -46,7 +46,7 @@ public class PacketHandler {
conn.updateVersion(packet.getVersion());
conn.updateState(packet.getNextState());
Logger.debug("Pinged from %s [%s]", conn.getAddress(),
Log.debug("Pinged from %s [%s]", conn.getAddress(),
conn.getClientVersion().toString());
if (server.getConfig().getInfoForwarding().isLegacy()) {

View File

@ -4,7 +4,7 @@ import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.jetbrains.annotations.NotNull;
import ua.nanit.limbo.server.Logger;
import ua.nanit.limbo.server.Log;
import java.util.Arrays;
@ -45,7 +45,7 @@ public class ChannelTrafficHandler extends ChannelInboundHandlerAdapter {
private void closeConnection(ChannelHandlerContext ctx, String reason, Object... args) {
ctx.close();
Logger.info(reason, args);
Log.info(reason, args);
}
private static class PacketBucket {

View File

@ -24,7 +24,7 @@ import ua.nanit.limbo.protocol.ByteMessage;
import ua.nanit.limbo.protocol.Packet;
import ua.nanit.limbo.protocol.registry.State;
import ua.nanit.limbo.protocol.registry.Version;
import ua.nanit.limbo.server.Logger;
import ua.nanit.limbo.server.Log;
import java.util.List;
@ -47,22 +47,20 @@ public class PacketDecoder extends MessageToMessageDecoder<ByteBuf> {
Packet packet = mappings.getPacket(packetId);
if (packet != null) {
Logger.debug("Received packet %s[0x%s] (%d bytes)", packet.toString(), Integer.toHexString(packetId), msg.readableBytes());
Log.debug("Received packet %s[0x%s] (%d bytes)", packet.toString(), Integer.toHexString(packetId), msg.readableBytes());
try {
packet.decode(msg, version);
} catch (Exception e) {
if (Logger.isDebug()) {
Logger.warning("Cannot decode packet 0x%s", Integer.toHexString(packetId));
e.printStackTrace();
}
else {
Logger.warning("Cannot decode packet 0x%s: %s", Integer.toHexString(packetId), e.getMessage());
if (Log.isDebug()) {
Log.warning("Cannot decode packet 0x%s", e, Integer.toHexString(packetId));
} else {
Log.warning("Cannot decode packet 0x%s: %s", Integer.toHexString(packetId), e.getMessage());
}
}
ctx.fireChannelRead(packet);
} else {
Logger.debug("Undefined incoming packet: 0x" + Integer.toHexString(packetId));
Log.debug("Undefined incoming packet: 0x" + Integer.toHexString(packetId));
}
}

View File

@ -25,7 +25,7 @@ import ua.nanit.limbo.protocol.Packet;
import ua.nanit.limbo.protocol.PacketSnapshot;
import ua.nanit.limbo.protocol.registry.State;
import ua.nanit.limbo.protocol.registry.Version;
import ua.nanit.limbo.server.Logger;
import ua.nanit.limbo.server.Log;
public class PacketEncoder extends MessageToByteEncoder<Packet> {
@ -51,7 +51,7 @@ public class PacketEncoder extends MessageToByteEncoder<Packet> {
}
if (packetId == -1) {
Logger.warning("Undefined packet class: %s[0x%s] (%d bytes)", packet.getClass().getName(), Integer.toHexString(packetId), msg.readableBytes());
Log.warning("Undefined packet class: %s[0x%s] (%d bytes)", packet.getClass().getName(), Integer.toHexString(packetId), msg.readableBytes());
return;
}
@ -60,11 +60,11 @@ public class PacketEncoder extends MessageToByteEncoder<Packet> {
try {
packet.encode(msg, version);
if (Logger.getLevel() >= Logger.Level.DEBUG.getIndex()) {
Logger.debug("Sending %s[0x%s] packet (%d bytes)", packet.toString(), Integer.toHexString(packetId), msg.readableBytes());
if (Log.isDebug()) {
Log.debug("Sending %s[0x%s] packet (%d bytes)", packet.toString(), Integer.toHexString(packetId), msg.readableBytes());
}
} catch (Exception e) {
Logger.error("Cannot encode packet 0x%s: %s", Integer.toHexString(packetId), e.getMessage());
Log.error("Cannot encode packet 0x%s: %s", Integer.toHexString(packetId), e.getMessage());
}
}

View File

@ -20,7 +20,7 @@ package ua.nanit.limbo.connection.pipeline;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import ua.nanit.limbo.server.Logger;
import ua.nanit.limbo.server.Log;
import java.util.List;
@ -42,7 +42,7 @@ public class VarIntFrameDecoder extends ByteToMessageDecoder {
int readVarInt = reader.getReadVarInt();
int bytesRead = reader.getBytesRead();
if (readVarInt < 0) {
Logger.error("[VarIntFrameDecoder] Bad data length");
Log.error("[VarIntFrameDecoder] Bad data length");
} else if (readVarInt == 0) {
in.readerIndex(varIntEnd + 1);
} else {
@ -54,7 +54,7 @@ public class VarIntFrameDecoder extends ByteToMessageDecoder {
}
}
} else if (reader.getResult() == VarIntByteDecoder.DecodeResult.TOO_BIG) {
Logger.error("[VarIntFrameDecoder] Too big data");
Log.error("[VarIntFrameDecoder] Too big data");
}
}
}

View File

@ -40,12 +40,12 @@ public final class CommandManager extends Thread {
try {
handler.execute();
} catch (Throwable t) {
Logger.error("Cannot execute command:", t);
Log.error("Cannot execute command:", t);
}
continue;
}
Logger.info("Unknown command. Type \"help\" to get commands list");
Log.info("Unknown command. Type \"help\" to get commands list");
}
}

View File

@ -43,12 +43,12 @@ public final class Connections {
public void addConnection(ClientConnection connection) {
connections.put(connection.getUuid(), connection);
Logger.info("Player %s connected (%s) [%s]", connection.getUsername(),
Log.info("Player %s connected (%s) [%s]", connection.getUsername(),
connection.getAddress(), connection.getClientVersion());
}
public void removeConnection(ClientConnection connection) {
connections.remove(connection.getUuid());
Logger.info("Player %s disconnected", connection.getUsername());
Log.info("Player %s disconnected", connection.getUsername());
}
}

View File

@ -72,13 +72,15 @@ public final class LimboServer {
}
public void start() throws Exception {
Logger.info("Starting server...");
Log.info("Starting server...");
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.DISABLED);
config = new LimboConfig(Paths.get("./"));
config.load();
Log.setLevel(config.getDebugLevel());
packetHandler = new PacketHandler(this);
dimensionRegistry = new DimensionRegistry(this);
dimensionRegistry.load(config.getDimensionType());
@ -92,9 +94,7 @@ public final class LimboServer {
Runtime.getRuntime().addShutdownHook(new Thread(this::stop, "NanoLimbo shutdown thread"));
Logger.info("Server started on %s", config.getAddress());
Logger.setLevel(config.getDebugLevel());
Log.info("Server started on %s", config.getAddress());
commandManager = new CommandManager();
commandManager.registerAll(this);
@ -110,12 +110,12 @@ public final class LimboServer {
bossGroup = new EpollEventLoopGroup(config.getBossGroupSize());
workerGroup = new EpollEventLoopGroup(config.getWorkerGroupSize());
channelClass = EpollServerSocketChannel.class;
Logger.debug("Using Epoll transport type");
Log.debug("Using Epoll transport type");
} else {
bossGroup = new NioEventLoopGroup(config.getBossGroupSize());
workerGroup = new NioEventLoopGroup(config.getWorkerGroupSize());
channelClass = NioServerSocketChannel.class;
Logger.debug("Using Java NIO transport type");
Log.debug("Using Java NIO transport type");
}
new ServerBootstrap()
@ -132,7 +132,7 @@ public final class LimboServer {
}
private void stop() {
Logger.info("Stopping server...");
Log.info("Stopping server...");
if (keepAliveTask != null) {
keepAliveTask.cancel(true);
@ -146,7 +146,7 @@ public final class LimboServer {
workerGroup.shutdownGracefully();
}
Logger.info("Server stopped, Goodbye!");
Log.info("Server stopped, Goodbye!");
}
}

View File

@ -17,65 +17,66 @@
package ua.nanit.limbo.server;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import ch.qos.logback.classic.Logger;
import org.slf4j.LoggerFactory;
public final class Logger {
public final class Log {
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("hh:mm:ss");
private static final Logger LOGGER = (Logger) LoggerFactory.getLogger("Limbo");
private static int debugLevel = Level.INFO.getIndex();
private Logger() {}
public static int getLevel() {
return debugLevel;
}
private Log() {}
public static void info(Object msg, Object... args) {
print(Level.INFO, msg, null, args);
LOGGER.info(String.format(msg.toString(), args));
}
public static void debug(Object msg, Object... args) {
print(Level.DEBUG, msg, null, args);
LOGGER.debug(String.format(msg.toString(), args));
}
public static void warning(Object msg, Object... args) {
print(Level.WARNING, msg, null, args);
LOGGER.warn(String.format(msg.toString(), args));
}
public static void warning(Object msg, Throwable t, Object... args) {
print(Level.WARNING, msg, t, args);
LOGGER.warn(String.format(msg.toString(), args), t);
}
public static void error(Object msg, Object... args) {
print(Level.ERROR, msg, null, args);
LOGGER.error(msg.toString(), args);
}
public static void error(Object msg, Throwable t, Object... args) {
print(Level.ERROR, msg, t, args);
}
public static void print(Level level, Object msg, Throwable t, Object... args) {
if (debugLevel >= level.getIndex()) {
System.out.printf("%s: %s%n", getPrefix(level), String.format(msg.toString(), args));
if (t != null) t.printStackTrace();
}
LOGGER.error(String.format(msg.toString(), args), t);
}
public static boolean isDebug() {
return debugLevel >= Level.DEBUG.getIndex();
}
private static String getPrefix(Level level) {
return String.format("[%s] [%s]", getTime(), level.getDisplay());
}
private static String getTime() {
return LocalTime.now().format(FORMATTER);
}
static void setLevel(int level) {
debugLevel = level;
Logger logback = (Logger) LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
if (logback != null) {
logback.setLevel(convertLevel(level));
}
}
private static ch.qos.logback.classic.Level convertLevel(int level) {
switch (level) {
case 0:
return ch.qos.logback.classic.Level.ERROR;
case 1:
return ch.qos.logback.classic.Level.WARN;
case 2:
return ch.qos.logback.classic.Level.INFO;
case 3:
return ch.qos.logback.classic.Level.DEBUG;
default:
throw new IllegalStateException("Undefined log level: " + level);
}
}
public enum Level {

View File

@ -2,7 +2,7 @@ package ua.nanit.limbo.server.commands;
import ua.nanit.limbo.server.Command;
import ua.nanit.limbo.server.LimboServer;
import ua.nanit.limbo.server.Logger;
import ua.nanit.limbo.server.Log;
public class CmdConn implements Command {
@ -14,7 +14,7 @@ public class CmdConn implements Command {
@Override
public void execute() {
Logger.info("Connections: %d", server.getConnections().getCount());
Log.info("Connections: %d", server.getConnections().getCount());
}
@Override

View File

@ -2,7 +2,7 @@ package ua.nanit.limbo.server.commands;
import ua.nanit.limbo.server.Command;
import ua.nanit.limbo.server.LimboServer;
import ua.nanit.limbo.server.Logger;
import ua.nanit.limbo.server.Log;
import java.util.Map;
@ -18,10 +18,10 @@ public class CmdHelp implements Command {
public void execute() {
Map<String, Command> commands = server.getCommandManager().getCommands();
Logger.info("Available commands:");
Log.info("Available commands:");
for (Map.Entry<String, Command> entry : commands.entrySet()) {
Logger.info("%s - %s", entry.getKey(), entry.getValue().description());
Log.info("%s - %s", entry.getKey(), entry.getValue().description());
}
}

View File

@ -1,7 +1,7 @@
package ua.nanit.limbo.server.commands;
import ua.nanit.limbo.server.Command;
import ua.nanit.limbo.server.Logger;
import ua.nanit.limbo.server.Log;
public class CmdMem implements Command {
@ -14,11 +14,11 @@ public class CmdMem implements Command {
long free = runtime.freeMemory() / mb;
long max = runtime.maxMemory() / mb;
Logger.info("Memory usage:");
Logger.info("Used: %d MB", used);
Logger.info("Total: %d MB", total);
Logger.info("Free: %d MB", free);
Logger.info("Max: %d MB", max);
Log.info("Memory usage:");
Log.info("Used: %d MB", used);
Log.info("Total: %d MB", total);
Log.info("Free: %d MB", free);
Log.info("Max: %d MB", max);
}
@Override

View File

@ -1,14 +1,14 @@
package ua.nanit.limbo.server.commands;
import ua.nanit.limbo.server.Command;
import ua.nanit.limbo.server.Logger;
import ua.nanit.limbo.server.Log;
import ua.nanit.limbo.BuildConfig;
public class CmdVersion implements Command {
@Override
public void execute() {
Logger.info("Version: %s", BuildConfig.LIMBO_VERSION);
Log.info("Version: %s", BuildConfig.LIMBO_VERSION);
}
@Override

View File

@ -21,7 +21,7 @@ import net.kyori.adventure.nbt.CompoundBinaryTag;
import net.kyori.adventure.nbt.ListBinaryTag;
import net.kyori.adventure.nbt.TagStringIO;
import ua.nanit.limbo.server.LimboServer;
import ua.nanit.limbo.server.Logger;
import ua.nanit.limbo.server.Log;
import java.io.*;
import java.nio.charset.StandardCharsets;
@ -118,7 +118,7 @@ public final class DimensionRegistry {
case "the_end":
return new Dimension(1, "minecraft:the_end", theEnd);
default:
Logger.warning("Undefined dimension type: '%s'. Using THE_END as default", def);
Log.warning("Undefined dimension type: '%s'. Using THE_END as default", def);
return new Dimension(1, "minecraft:the_end", theEnd);
}
}
@ -132,7 +132,7 @@ public final class DimensionRegistry {
case "the_end":
return new Dimension(3, "minecraft:the_end", tag);
default:
Logger.warning("Undefined dimension type: '%s'. Using THE_END as default", def);
Log.warning("Undefined dimension type: '%s'. Using THE_END as default", def);
return new Dimension(3, "minecraft:the_end", tag);
}
}

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>
<configuration>
<import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
<import class="ch.qos.logback.core.ConsoleAppender"/>
<import class="ch.qos.logback.core.FileAppender"/>
<timestamp key="bySecond" datePattern="yyyy-MM-dd"/>
<appender name="STDOUT" class="ConsoleAppender">
<encoder class="PatternLayoutEncoder">
<pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} -%kvp- %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="FileAppender">
<file>logs/log-${bySecond}.txt</file>
<immediateFlush>true</immediateFlush>
<encoder class="PatternLayoutEncoder">
<pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} -%kvp- %msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="FILE"/>
<appender-ref ref="STDOUT"/>
</root>
</configuration>