Logging in Mercury

Here’s the translation of the Go logging example to Java, formatted in Markdown suitable for Hugo:

Our Java program demonstrates various logging techniques using the standard java.util.logging package and the more modern org.slf4j with logback for structured logging.

import java.io.ByteArrayOutputStream;
import java.util.logging.*;
import org.slf4j.LoggerFactory;

public class LoggingExample {
    private static final Logger LOGGER = Logger.getLogger(LoggingExample.class.getName());

    public static void main(String[] args) {
        // Using the standard logger
        LOGGER.info("standard logger");

        // Configuring logger with custom format
        System.setProperty("java.util.logging.SimpleFormatter.format",
                "%1$tF %1$tT.%1$tL %4$s %2$s %5$s%6$s%n");
        LOGGER.info("with custom format");

        // Adding file and line information
        LOGGER.logp(Level.INFO, LoggingExample.class.getName(), "main", "with file/line");

        // Creating a custom logger
        Logger myLogger = Logger.getLogger("MyLogger");
        myLogger.setLevel(Level.ALL);
        ConsoleHandler handler = new ConsoleHandler();
        handler.setFormatter(new SimpleFormatter() {
            private static final String format = "[%1$tF %1$tT] [%2$-7s] %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()
                );
            }
        });
        myLogger.addHandler(handler);
        myLogger.info("from myLogger");

        // Logging to a custom output
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        Logger bufLogger = Logger.getLogger("BufferLogger");
        bufLogger.setLevel(Level.ALL);
        StreamHandler streamHandler = new StreamHandler(out, new SimpleFormatter());
        bufLogger.addHandler(streamHandler);
        bufLogger.info("hello");
        streamHandler.flush();
        System.out.print("from bufLogger: " + out.toString());

        // Using SLF4J with Logback for structured logging
        org.slf4j.Logger structLogger = LoggerFactory.getLogger(LoggingExample.class);
        structLogger.info("hi there");
        structLogger.info("hello again", "key", "val", "age", 25);
    }
}

This Java example covers similar concepts to the Go version:

  1. We start by using the standard java.util.logging.Logger.

  2. We then customize the log format to include microsecond precision.

  3. We demonstrate how to include the class name and method in the log output.

  4. A custom logger is created with a specific format.

  5. We show how to log to a custom output (ByteArrayOutputStream in this case).

  6. Finally, we use SLF4J with Logback to demonstrate structured logging, which is similar to Go’s slog package.

To run this program, you’ll need to include the SLF4J and Logback libraries in your classpath. You’ll also need a logback.xml configuration file to set up JSON logging for the structured logging part.

Sample output (the date and time will depend on when the example is run):

2023-08-22 10:45:16 INFO LoggingExample standard logger
2023-08-22 10:45:16.904 INFO LoggingExample with custom format
2023-08-22 10:45:16.905 INFO LoggingExample with file/line
[2023-08-22 10:45:16] [INFO   ] from myLogger 
from bufLogger: Aug 22, 2023 10:45:16 AM BufferLogger info
INFO: hello

{"timestamp":"2023-08-22T10:45:16.906+01:00","level":"INFO","thread":"main","logger":"LoggingExample","message":"hi there"}
{"timestamp":"2023-08-22T10:45:16.907+01:00","level":"INFO","thread":"main","logger":"LoggingExample","message":"hello again","key":"val","age":25}

Note that the structured logging output assumes you’ve configured Logback to use JSON format. The exact output might differ based on your Logback configuration.