Logging
Every mod has access to a built-in logger via getLogger(). Hytale uses Google Flogger for logging.
Basic Usage
Section titled “Basic Usage”import java.util.logging.Level;
// in your mod classgetLogger().atInfo().log("Server started");getLogger().atWarning().log("Something might be wrong");getLogger().atSevere().log("Critical error occurred");getLogger().at(Level.FINE).log("Debug info"); // explicit level syntaxLog Levels
Section titled “Log Levels”| Level | Use For |
|---|---|
Level.SEVERE | Errors and failures |
Level.WARNING | Potential problems |
Level.INFO | General information |
Level.CONFIG | Configuration and setup messages |
Level.FINE | Debug information (hidden by default) |
Level.FINER | Detailed debug (hidden by default) |
Level.FINEST | Trace-level debug (hidden by default) |
Convenience methods: atSevere(), atWarning(), atInfo(), atConfig(), atFine(), atFiner(), atFinest().
Formatting
Section titled “Formatting”Use %s placeholders for formatting (printf-style):
String playerName = "Steve";int count = 42;
getLogger().atInfo().log("Player %s joined", playerName);getLogger().atInfo().log("Loaded %d items", count);getLogger().atInfo().log("Player %s has %d coins", playerName, count);Logging Exceptions
Section titled “Logging Exceptions”Use withCause() to attach an exception:
try { loadConfig();} catch (Exception e) { getLogger().atSevere().withCause(e).log("Failed to load configuration");}This logs both the message and the full stack trace.
Rate Limiting
Section titled “Rate Limiting”Avoid log spam with built-in rate limiting:
import java.util.concurrent.TimeUnit;
// log only every 100th occurrencegetLogger().atWarning().every(100).log("Frequent event occurred");
// log at most once every 5 secondsgetLogger().atWarning().atMostEvery(5, TimeUnit.SECONDS).log("Rate-limited message");Stack Traces
Section titled “Stack Traces”Include a stack trace for debugging (without an exception):
import com.google.common.flogger.StackSize;
getLogger().atWarning().withStackTrace(StackSize.MEDIUM).log("How did we get here?");Stack sizes: SMALL (10 frames), MEDIUM (20), LARGE (50), FULL (all).
Conditional Logging
Section titled “Conditional Logging”For expensive operations, check if the level is enabled first:
if (getLogger().at(Level.FINE).isEnabled()) { String expensiveDebugInfo = computeDebugState(); getLogger().at(Level.FINE).log("Debug state: %s", expensiveDebugInfo);}Changing Log Level at Runtime
Section titled “Changing Log Level at Runtime”Enable debug logging dynamically:
getLogger().setLevel(Level.FINE); // enable FINE and abovegetLogger().setLevel(Level.INFO); // back to normalStatic Logger Access
Section titled “Static Logger Access”For utility classes without mod context, use HytaleLogger:
import com.hypixel.hytale.logger.HytaleLogger;
// per-class logger (recommended)private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
LOGGER.atInfo().log("Processing data");
// sub-logger for subsystemsHytaleLogger dbLogger = LOGGER.getSubLogger("database");dbLogger.atInfo().log("Connected"); // logged as "[MyClass][database]"
// global loggerHytaleLogger.getLogger().atWarning().log("Something happened");