The Java standard library provides straightforward tools for outputting logs from Java programs, with the `java.util.logging` package for free-form output and the `org.slf4j` package (a popular third-party library) for more advanced logging capabilities.
```java
import java.util.logging.*;
import java.io.*;
public class LoggingExample {
public static void main(String[] args) throws IOException {
// Simply invoking methods like info() from the Logger class uses
// the default logger, which is already pre-configured for reasonable
// logging output to the console.
Logger.getGlobal().info("standard logger");
// Loggers can be configured with handlers and formatters to set
// their output format. By default, the console handler uses a
// SimpleFormatter. We can change its format to include microseconds.
ConsoleHandler handler = new ConsoleHandler();
handler.setFormatter(new SimpleFormatter() {
private static final String format = "[%1$tF %1$tT.%1$tL] %2$s %3$s%n";
@Override
public synchronized String format(LogRecord lr) {
return String.format(format,
new java.util.Date(lr.getMillis()),
lr.getLevel().getLocalizedName(),
lr.getMessage()
);
}
});
Logger logger = Logger.getLogger("MyLogger");
logger.setUseParentHandlers(false);
logger.addHandler(handler);
logger.info("with micro");
// It also supports emitting the class name and
// method from which the log method is called.
logger.logp(Level.INFO, LoggingExample.class.getName(), "main", "with class/method");
// It may be useful to create a custom logger and
// pass it around. When creating a new logger, we
// can set a name to distinguish its output from other loggers.
Logger mylog = Logger.getLogger("CustomLogger");
mylog.info("from mylog");
// We can change the logger's name
mylog.setUseParentHandlers(false);
mylog.addHandler(new ConsoleHandler());
((ConsoleHandler)mylog.getHandlers()[0]).setFormatter(new SimpleFormatter() {
private static final String format = "mycustom: [%1$tF %1$tT] %2$s%n";
@Override
public synchronized String format(LogRecord lr) {
return String.format(format,
new java.util.Date(lr.getMillis()),
lr.getMessage()
);
}
});
mylog.info("from custom mylog");
// Loggers can have custom output targets;
// any OutputStream works.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Handler bufHandler = new StreamHandler(baos, new SimpleFormatter());
Logger buflog = Logger.getLogger("BufferLogger");
buflog.setUseParentHandlers(false);
buflog.addHandler(bufHandler);
// This call writes the log output into baos.
buflog.info("hello");
bufHandler.flush();
// This will actually show it on standard output.
System.out.print("from buflog: " + baos.toString());
// For structured logging, we can use a third-party library like SLF4J with Logback
// Here's a basic example (Note: This requires additional dependencies)
/*
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Logger slf4jLogger = LoggerFactory.getLogger(LoggingExample.class);
slf4jLogger.info("hi there");
// In addition to the message, structured logging can contain
// an arbitrary number of key-value pairs.
slf4jLogger.info("hello again", "key", "val", "age", 25);
*/
}
}