Logging in Elixir

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

Our example demonstrates various logging techniques in Elixir. Elixir provides logging capabilities through the Logger module, which is part of the standard library.

defmodule LoggingExample do
  require Logger

  def run do
    # Simply calling Logger functions logs to the console by default
    Logger.info("standard logger")

    # Configure logger to include microseconds in timestamps
    Logger.configure(metadata: [:microseconds])
    Logger.info("with micro")

    # Include file and line information in logs
    Logger.configure(metadata: [:file, :line])
    Logger.info("with file/line")

    # Create a custom logger with a prefix
    mylog = fn message ->
      Logger.info("my: #{message}")
    end
    mylog.("from mylog")

    # Change the prefix for the custom logger
    mylog = fn message ->
      Logger.info("ohmy: #{message}")
    end
    mylog.("from mylog")

    # Log to a custom IO device (in this case, a StringIO)
    {:ok, string_io} = StringIO.open("")
    Logger.configure(device: string_io)
    Logger.info("hello")
    {:ok, {_, output}} = StringIO.contents(string_io)
    IO.puts("from buflog: #{output}")

    # Reset logger to default device
    Logger.configure(device: :console)

    # Structured logging with additional metadata
    Logger.info("hi there", additional: "metadata")
    Logger.info("hello again", key: "val", age: 25)
  end
end

LoggingExample.run()

To run this program, save it as logging_example.exs and use elixir to execute it:

$ elixir logging_example.exs

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

10:45:16.000 [info]  standard logger
10:45:16.904 [info]  with micro
10:45:16.905 [info]  with file/line
    file: logging_example.exs
    line: 15
10:45:16.906 [info]  my: from mylog
10:45:16.907 [info]  ohmy: from mylog
from buflog: 10:45:16.908 [info]  hello
10:45:16.909 [info]  hi there
    additional: metadata
10:45:16.910 [info]  hello again
    age: 25
    key: val

In this Elixir example:

  1. We use the Logger module for logging, which is part of Elixir’s standard library.

  2. The Logger.configure/1 function is used to change logger settings, similar to SetFlags in the original example.

  3. Custom loggers are implemented as anonymous functions that call Logger.info/2 with a prefix.

  4. To log to a custom IO device, we use StringIO and configure the logger to use it as the device.

  5. Structured logging is achieved by passing keyword lists as additional arguments to the logging functions.

  6. Elixir’s logger automatically includes timestamps and log levels, similar to the behavior in the original example.

While the exact API differs, this Elixir code provides similar functionality to the original Go example, demonstrating various logging techniques and configurations.