ring_logger
This is an in-memory ring buffer backend for the Elixir Logger with convenience methods for accessing the logs from the IEx prompt.
Use cases:
- Get log messages in real-time over remote IEx sessions
- Grep and tail through log messages without setting up anything else
- Keep logs in limited resource environments
- Capture recent log events for error reports
As a bonus, ring_logger
is nice to your IEx prompt. If you attach to the log
and are receiving messages as they’re sent, they won’t stomp what you’re typing.
Configuration
Add ring_logger
to your projects dependencies in your mix.exs
:
def deps do
[{:ring_logger, "~> 0.4"}]
end
Then configure the logger in your config/config.exs
:
use Mix.Config
# Add the RingLogger backend. This removes the
# default :console backend.
config :logger, backends: [RingLogger]
# Set the number of messages to hold in the circular buffer
config :logger, RingLogger, max_size: 100
Or you can start the backend manually by running the following:
Logger.add_backend(RingLogger)
Logger.configure(RingLogger, max_size: 100)
IEx session usage
See the example project for a hands-on walkthrough of using the logger. Read on for the highlights.
Log messages aren’t printed to the console by default. If you’re seeing them,
they may be coming from Elixir’s default :console
logger.
To see log messages as they come in, call RingLogger.attach()
and
then to make the log messages stop, call RingLogger.detach()
. The
attach
method takes options if you want to limit the log level, change the
formatting, etc.
Here’s an example:
iex> Logger.add_backend(RingLogger)
{:ok, #PID<0.199.0>}
iex> Logger.remove_backend(:console)
:ok
iex> RingLogger.attach
:ok
iex> require Logger
iex> Logger.info("hello")
:ok
14:04:52.516 [info] hello
This probably isn’t too exciting until you see that it works on remote shells as
well (the :console
logger doesn’t do this).
Say you prefer polling for log messages rather than having them print over your
console at random times. If you’re still attached, then detach
and tail
:
iex> RingLogger.detach
:ok
iex> Logger.info("Hello logger, how are you?")
:ok
iex> Logger.info("It's a nice day. Wouldn't you say?")
:ok
iex> RingLogger.tail
14:04:52.516 [info] hello
14:11:54.397 [info] Hello logger, how are you?
14:12:09.180 [info] It's a nice day. Wouldn't you say?
:ok
You can also grep
:
iex> RingLogger.grep(~r/[Nn]eedle/)
16:55:41.614 [info] Needle in a haystack
Programmatic usage
It can be useful to get a snapshot of the log when an unexpected event occurs.
The commandline functions demonstrated above are available, but you can also get
the raw log entries by calling RingLogger.get/0
:
iex> RingLogger.get
[
debug: {Logger, "8", {{2018, 2, 5}, {17, 44, 7, 675}},
[
pid: #PID<0.139.0>,
application: :example,
module: Example,
function: "log/1",
file: "ring_logger/example/lib/example.ex",
line: 11
]},
debug: {Logger, "9", {{2018, 2, 5}, {17, 44, 8, 676}},
[
pid: #PID<0.139.0>,
application: :example,
module: Example,
function: "log/1",
file: "ring_logger/example/lib/example.ex",
line: 11
]},
debug: {Logger, "10", {{2018, 2, 5}, {17, 44, 9, 677}},
[
pid: #PID<0.139.0>,
application: :example,
module: Example,
function: "log/1",
file: "ring_logger/example/lib/example.ex",
line: 11
]}
]