Logging in Kotlin

Here’s the translation of the Go logging example to Kotlin, with explanations in Markdown format suitable for Hugo:

import java.io.ByteArrayOutputStream
import java.time.Instant
import java.util.logging.*

fun main() {
    // The Java standard library provides straightforward tools for outputting
    // logs from Java programs, with the `java.util.logging` package for
    // free-form output.

    // Simply invoking methods like `info` from the Logger class uses the
    // *standard* logger, which is already pre-configured for reasonable
    // logging output to System.err.
    val logger = Logger.getLogger("StandardLogger")
    logger.info("standard logger")

    // Loggers can be configured with Handlers and Formatters to set
    // their output format. By default, the standard logger has a
    // SimpleFormatter. We can change its format to emit time with
    // microsecond accuracy, for example.
    val handler = ConsoleHandler()
    handler.formatter = SimpleFormatter()
    logger.addHandler(handler)
    logger.info("with custom format")

    // 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.
    val myLogger = Logger.getLogger("MyLogger")
    myLogger.info("from myLogger")

    // Loggers can have custom output targets.
    val baos = ByteArrayOutputStream()
    val bufHandler = StreamHandler(baos, SimpleFormatter())
    val bufLogger = Logger.getLogger("BufferLogger")
    bufLogger.addHandler(bufHandler)

    // This call writes the log output into baos.
    bufLogger.info("hello")
    bufHandler.flush()

    // This will actually show it on standard output.
    println("from bufLogger: ${String(baos.toByteArray())}")

    // For structured logging, we can use a third-party library like SLF4J
    // with Logback. Here's a simple example using string interpolation
    // for key-value pairs:
    val structuredLogger = Logger.getLogger("StructuredLogger")
    val message = "hello again"
    val key = "val"
    val age = 25
    structuredLogger.info("$message, key=$key, age=$age")
}

To run the program, save it as Logging.kt and use the Kotlin compiler:

$ kotlinc Logging.kt -include-runtime -d Logging.jar
$ java -jar Logging.jar

Sample output; the date and time emitted will depend on when the example ran:

Aug 22, 2023 10:45:16 AM StandardLogger info
INFO: standard logger
Aug 22, 2023 10:45:16 AM StandardLogger info
INFO: with custom format
Aug 22, 2023 10:45:16 AM MyLogger info
INFO: from myLogger
from bufLogger: Aug 22, 2023 10:45:16 AM BufferLogger info
INFO: hello

Aug 22, 2023 10:45:16 AM StructuredLogger info
INFO: hello again, key=val, age=25

This Kotlin example demonstrates various logging techniques using the java.util.logging package, which is similar to the logging capabilities in the original example. For structured logging, we’ve used string interpolation to simulate key-value pairs, as Kotlin doesn’t have a direct equivalent to the slog package. For more advanced structured logging in Kotlin, you might want to consider using a library like SLF4J with Logback.