Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.


Build Status Coverage Status Module Version Hex Docs Hex Download Total License Last Updated Static Analysis Status

JSON console back-end for Elixir Logger.

It can be used as drop-in replacement for default :console Logger back-end in cases where you use Google Cloud Logger, DataDog or other JSON-based log collectors. After adding this back-end you may also be interested in redirecting otp and sasl reports to Logger (see "Error Logger configuration" section).

Minimum supported Erlang/OTP version is 20.

Log Format

LoggerJSON provides three JSON formatters out of the box and allows developers to implement a custom one.


The LoggerJSON.Formatters.BasicLogger formatter provides a generic JSON formatted message with no vendor specific entries in the payload. A sample log entry from LoggerJSON.Formatters.BasicLogger looks like the following:

  "time": "2020-04-02T11:59:06.710Z",
  "severity": "debug",
  "message": "hello",
  "metadata": {
    "user_id": 13


Generates JSON that is compatible with the Google Cloud Logger LogEntry format:

    "function":"Elixir.LoggerJSONGoogleTest.test metadata can be configured/1",

Notice that GKE doesn't allow to set certain fields of the LogEntry, so support is limited. The results in Google Cloud Logger would looks something like this:



Adheres to the default standard attribute list.

  "domain": ["elixir"],
  "duration": 3863403,
  "http": {
    "url": "http://localhost/create-account",
    "status_code": 200,
    "method": "GET",
    "referer": "http://localhost:4000/login",
    "request_id": "http_FlDCOItxeudZJ20AAADD",
    "useragent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36",
    "url_details": {
      "host": "localhost",
      "port": 4000,
      "path": "/create-account",
      "queryString": "",
      "scheme": "http"
  "logger": {
    "thread_name": "#PID<0.1042.0>",
    "method_name": ""
  "message": "",
  "network": {
    "client": {
      "ip": ""
  "phoenix": {
    "controller": "Elixir.RecognizerWeb.Accounts.UserRegistrationController",
    "action": "new"
  "request_id": "http_FlDCOItxeudZJ20AAADD",
  "syslog": {
    "hostname": [10, 10, 100, 100, 100, 100, 100],
    "severity": "info",
    "timestamp": "2020-12-14T19:16:55.088Z"

Custom formatters

You can change this structure by implementing LoggerJSON.Formatter behaviour and passing module name to :formatter config option. Example module can be found in LoggerJSON.Formatters.GoogleCloudLogger.

config :logger_json, :backend,
  formatter: MyFormatterImplementation


It's available on Hex, the package can be installed as:

  1. Add :logger_json to your list of dependencies in mix.exs:
def deps do
  [{:logger_json, "~> 5.1"}]
  1. Set configuration in your config/config.exs:
config :logger_json, :backend,
  metadata: :all,
  json_encoder: Jason,
  formatter: LoggerJSON.Formatters.GoogleCloudLogger

Some integrations (for eg. Plug) use metadata to log request and response parameters. You can reduce log size by replacing :all (which means log all metadata) with a list of the ones that you actually need.

Beware that LoggerJSON always ignores some metadata keys, but formatters like GoogleCloudLogger and DatadogLogger still persist those metadata values into a structured output. This behavior is similar to the default Elixir logger backend.

  1. Replace default Logger :console back-end with LoggerJSON:
config :logger,
  backends: [LoggerJSON]
  1. Optionally. Log requests and responses by replacing a Plug.Logger in your endpoint with a:
plug LoggerJSON.Plug

LoggerJSON.Plug is configured by default to use LoggerJSON.Plug.MetadataFormatters.GoogleCloudLogger. You can replace it with the :metadata_formatter config option.

  1. Optionally. Use Ecto telemetry for additional metadata:

Attach telemetry handler for Ecto events in start/2 function in application.ex

:ok =
    [:my_app, :repo, :query],

Prevent duplicate logging of events, by setting log configuration option to false

config :my_app, MyApp.Repo,
  adapter: Ecto.Adapters.Postgres,
  log: false

Dynamic configuration

For dynamically configuring the endpoint, such as loading data from environment variables or configuration files, LoggerJSON provides an :on_init option that allows developers to set a module, function and list of arguments that is invoked when the endpoint starts.

config :logger_json, :backend,
  on_init: {YourApp.Logger, :load_from_system_env, []}

Encoders support

You can replace default Jason encoder with other module that supports encode_to_iodata!/1 function and encoding fragments.


The docs can be found at


Many source code has been taken from original Elixir Logger :console back-end source code, so I want to thank all it's authors and contributors.

Part of LoggerJSON.Plug module have origins from plug_logger_json by @bleacherreport, originally licensed under Apache License 2.0. Part of LoggerJSON.PlugTest are from Elixir's Plug licensed under Apache 2.

Copyright and License

Copyright (c) 2016 Nebo #15

Released under the MIT License, which can be found in