[![Hex Docs](](
[![Coverage Status](](

# LogfmtEx

A log formatter for the logfmt format popularized by Heroku.

```elixir"I am a message", user_id: 123)
level=info msg="I am a message" ts="12:38:38.055 1973-03-12" user_id=123 pid=#PID<0.223.0> file=test/logfmt_ex_test.exs

## Installation

The package can be installed
by adding `logfmt_ex` to your list of dependencies in `mix.exs`:

def deps do
    {:logfmt_ex, "~> 0.4"}

In your app's logger configuration, specify the `LogfmtEx` module and its `format` function to be used to format your logs:

config :logger, :console,
  format: {LogfmtEx, :format}

You can customize the formatting in your config:

config :logfmt_ex, :opts,
  message_key: "msg",
  timestamp_key: "ts",
  timestamp_format: :iso8601

## Configuration

* `:delimiter` - defaults to `=`.
* `:format` - A list of atoms that defines the order in which key/value pairs will written to the log line. Defaults to `[:timestamp, :level, :message, :metadata]`. Valid parameters are
  * `:timestamp` - the timestamp of the log message
  * `:level` - the log level
  * `:message` - the log message itself
  * `:metadata` - metadata as key=value paris
  * `:node` - the node name
* `timestamp_key` - changes the key used for the timestamp field. Defaults to `timestamp`.
* `timestamp_format` - How the timestamp is formatted. Defaults to `:elixir`. The options are
  * `:elixir` - Uses the same formatting functions found in the standard elixir log formatter. Example: `"12:38:38.055 1973-03-12"`
  * `:epoch_seconds` - outputs an integer representing the number of seconds elapsed since January 1, 1970. Only useful for applications that emit logs sporadically.
  * `:iso8601` - Formats the timestamp according to ISO8601-2019. Example: `2000-02-29T23:00:07`
* `level_key` - the key used for the log level. Defaults to `level`.
* `message_key` - the key used for the message field. Defaults to `message`, but `msg` is a popular alternative.

## Encoding

Structs can be encoded via the `ValueEncoder` protocol.

defmodule User do
  defstruct [:email, :name, :id]

  defimpl LogfmtEx.ValueEncoder do
    @doc """
    As we don't want to leak PII into our logs, we encode the struct to just the user's ID.
    def encode(user), do: to_string(

Types for which the protocol is not implemented will fall back to the `to_string/1` function in the `String.Chars` protocol.
If the term being encoded does not implement that protocol, the formatter will fall back to the `Inspect` protocol.

Note that the algebra documents produced by `Kernel.inspect/1` don't lend themselves to logfmt - this fallback is provided to minimize the chance that the formatter fails, instead making a "best effort" at producing usable output. It is recommended to implement either the `LogfmtEx.ValueEncoder` or `String.Chars` protocol for any data structures that might find their way into your logs.

## Testing and Development

This library uses [asdf]( to manage runtime versions of Elixir and Erlang.
Contributions, issues, and all other feedback is more than welcome!

## Benchmarks

the `/benchmarks` folder includes benchmarks comparing `LogfmtEx` to `Logger.Formatter`.

You can run them with `mix run benchmarks/throughput.exs`.

## Alternatives

LogfmtEx is a simple logfmt formatter specifically for the Elixir console backend.
If you're looking for a library to encode and decode logfmt, take a look at [logfmt-elixir]( instead.