Plugin Logging
Adding proper logging to your plugin can help both yourself and users of your plugin to find bugs and issues quickly. This page serves as a general overview on the different types of loggers you can use in your plugin, when to use each type, and other tips and tricks!
Different types of loggers
Section titled “Different types of loggers”Paper plugins (through their main class, the class extending JavaPlugin)
have direct access to three different types of logger classes.
The java.util logger
Section titled “The java.util logger”The java.util.logging.Logger (accessible via
JavaPlugin#getLogger()),
commonly referred to as the java.util logger, is a simple Java built-in logger class. It allows for standard
level-based logging, as well as a way to log exception stacktraces directly.
Example usage:
@Overridepublic void onEnable() { int id = loadDatabaseId(); try { getLogger().info("Starting database load for id = %d".formatted(id)); initDatabase(id); } catch (SQLException e) { getLogger().log(Level.SEVERE, "Failed to init database", e); }}The SLF4J logger
Section titled “The SLF4J logger”SLF4J is a “Simple Logging Facade for Java” that serves as an abstraction for multiple logging
frameworks to implement. You can obtain a SLF4J Logger instance via the
JavaPlugin#getSLF4JLogger() method.
SLF4J also allows for level-based logging, however it provides a nicer interface for parameterized logging (log messages with parameters) and better usability when printing exception stacktraces. It additionally supports markers, which can be very useful for advanced logging setups.
Example usage:
@Overridepublic void onEnable() { int id = loadDatabaseId(); try { getSLF4JLogger().info("Starting database load for id = {}", id); initDatabase(id); } catch (SQLException e) { getSLF4JLogger().error("Failed to init database", e); }}The SLF4J logger is generally shorter and easier to use than the java.util logger.
The component logger
Section titled “The component logger”Adventure’s ComponentLogger
is an extension of the SLF4J logger (meaning it inherits all of its features) which additionally provides support
for printing Components directly. This includes support for colored
log output in supported environments. An instance of it can be retrieved via the
JavaPlugin#getComponentLogger()
method.
Example usage:
@Overridepublic void onEnable() { int id = loadDatabaseId(); try { getComponentLogger().info( MiniMessage.miniMessage().deserialize("Starting database load for <red>id<gray> = <aqua>{}</red>"), id ); initDatabase(id); } catch (SQLException e) { getComponentLogger().error("Failed to init database", e); }}The component logger is the only way you can properly out components to console. The following code fragment would yield the below console output:
Component output = constructComponent();getComponentLogger().warn("Component: {}", output);
Whereas the java.util or regular SLF4J logger would simply call #toString() on the component,
resulting in basically unusable output:

Which logger should you use?
Section titled “Which logger should you use?”Nowadays, the overall recommendation is to use the SLF4J logger, as it is the simplest, most feature-complete logger. The component logger should be used if you frequently interact with and may need to log Adventure components.