# `RingLogger`
[🔗](https://github.com/nerves-project/ring_logger/blob/v0.11.7/lib/ring_logger.ex#L1)

This is an in-memory ring buffer backend for the Elixir Logger.

Install it by adding it to your `config.exs`:

```elixir
import Config

# Add the RingLogger backend. This removes the default :console backend.
config :logger, backends: [RingLogger]

# Periodically save logs to a file, and load logs on GenServer start from this file
config :logger, RingLogger, persist_path: "./myapp.log", persist_seconds: 300

# Save messages to one circular buffer that holds 1024 entries.
config :logger, RingLogger, max_size: 1024

# Separate out `:error` and `:warning` messages to their own circular buffer.
# All other log messages are stored in the default circular buffer.
config :logger, RingLogger, buffers: %{
  errors: %{
    levels: [:error, :warning],
    max_size: 1024
  }
}

# Specify circular buffers for all log levels. The default circular buffer won't
# be used in this example configuration.
config :logger, RingLogger, buffers: %{
  low_priority: %{
    levels: [:warning, :notice, :info, :debug],
    max_size: 1024
  },
  high_priority: %{
    levels: [:emergency, :alert, :critical, :error],
    max_size: 1024
  }
}
```

Or add manually:

```elixir
LoggerBackends.add(RingLogger)
LoggerBackends.configure(RingLogger, max_size: 1024)
```

Once added as a backend, you have two options depending on whether you're
accessing the `RingLogger` via the IEx prompt or via code.  If you're at the
IEx prompt, use the helper methods in here like `attach`, `detach`, `next`,
`tail`, `grep`, etc. They'll automate a few things behind the scenes. If
you're writing a program that needs to get log messages, use `get` or
`start_link` a `RingLogger.Client` and call its methods directly.

# `buffer`

```elixir
@type buffer() :: %{levels: [Logger.level()], max_size: pos_integer()}
```

Options to define a separate buffer based on log levels

# `client_option`

```elixir
@type client_option() ::
  {:io, term()}
  | {:pager, pager_fun()}
  | {:color, term()}
  | {:metadata, Logger.metadata()}
  | {:format, String.t() | custom_formatter()}
  | {:level, Logger.level()}
  | {:module_levels, map()}
  | {:application_levels, map()}
```

Option values used by client-side functions like `attach` and `tail`

# `client_options`

```elixir
@type client_options() :: [client_option()]
```

Option list for client-side functions

# `entry`

```elixir
@type entry() :: %{
  level: Logger.level(),
  module: module(),
  message: Logger.message(),
  timestamp: {{1970..10000, 1..12, 1..31}, {0..23, 0..59, 0..59, 0..999}},
  metadata: Logger.metadata()
}
```

A map holding a raw, unformatted log entry

# `pager_fun`

```elixir
@type pager_fun() :: (IO.device(), IO.chardata() -&gt; :ok | {:error, term()})
```

Callback function for printing/paging tail, grep, and next output

# `server_option`

```elixir
@type server_option() ::
  {:max_size, pos_integer()}
  | {:buffers, %{required(term()) =&gt; buffer()}}
  | {:persist_path, String.t()}
  | {:persist_seconds, pos_integer()}
```

Option values used by the ring logger

# `attach`

```elixir
@spec attach(client_options()) :: :ok | {:error, :no_client}
```

Attach the current IEx session to the logger. It will start printing log messages.

Options include:

* `:io` - output location when printing. Defaults to `:stdio`
* `:colors` - a keyword list of coloring options
* `:metadata` - a keyword list of additional metadata
* `:format` - the format message used to print logs
* `:level` - the minimum log level to report by this backend. Note that the `:logger`
  application's `:level` setting filters log messages prior to `RingLogger`.
* `:module_levels` - a map of log level overrides per module. For example,
  %{MyModule => :error, MyOtherModule => :none}
* `:application_levels` - a map of log level overrides per application. For example,
  %{:my_app => :error, :my_other_app => :none}. Note log levels set in `:module_levels`
  will take precedence.

# `config`

```elixir
@spec config() :: client_options() | {:error, :no_client}
```

Fetch the current configuration for the attached client

# `configure`

```elixir
@spec configure([server_option()]) :: :ok
```

Update the logger configuration.

Options include:
* `:max_size` - the max number of log messages to store at a time

# `count_next`

```elixir
@spec count_next(client_options()) :: non_neg_integer()
```

Count the next messages in the log

NOTE: This function may change in future releases.

Options include:

* Options from `attach/1`
* `:pager` - a function for printing log messages to the console. Defaults to `IO.write/2`.

# `detach`

```elixir
@spec detach() :: :ok
```

Detach the current IEx session from the logger

# `format`

```elixir
@spec format(entry()) :: :ok | {:error, :no_client}
```

Helper method for formatting log messages per the current client's
configuration.

# `get`

```elixir
@spec get(non_neg_integer(), non_neg_integer()) :: [entry()]
```

Get n log messages starting at the specified index.

Set n to 0 to get entries to the end

# `grep`

```elixir
@spec grep(Regex.t() | String.t(), client_options()) :: :ok | {:error, term()}
```

Run a regular expression on each entry in the log and print out the matchers.

For example:

iex> RingLogger.grep(~r/something/)
:ok

  Options include:

* Options from `attach/1`
* `:pager` - a function for printing log messages to the console. Defaults to `IO.write/2`.
* `:before` - Number of lines before the match to include
* `:after` - NUmber of lines after the match to include

# `grep_metadata`

```elixir
@spec grep_metadata(atom(), String.t() | Regex.t()) :: :ok | {:error, term()}
```

Return a list of formatted log entries that match the given metadata key-value pair.

For example:

iex> RingLogger.grep_metadata(:session_id, "abc")
:ok

iex> RingLogger.grep_metadata(:session_id, ~r/something/)
:ok

# `next`

```elixir
@spec next(client_options()) :: :ok | {:error, term()}
```

Print the next messages in the log

Options include:

* Options from `attach/1`
* `:pager` - a function for printing log messages to the console. Defaults to `IO.write/2`.

# `reset`

```elixir
@spec reset(client_options()) :: :ok | {:error, term()}
```

Reset the index into the log for `next/1` to the oldest entry.

# `save`

```elixir
@spec save(Path.t()) :: :ok | {:error, term()}
```

Save the contents of the log to the specified path

The file is overwritten if it already exists. Log message
formatting is done similarly to other RingLogger calls.

# `tail`

```elixir
@spec tail() :: :ok
```

Print the last 10 messages

# `tail`

```elixir
@spec tail(non_neg_integer() | client_options()) :: :ok
```

Print the last messages in the log

See `tail/2`.

# `tail`

```elixir
@spec tail(non_neg_integer(), client_options()) :: :ok
```

Print the last n messages in the log

Options include:

* Options from `attach/1`
* `:pager` - a function for printing log messages to the console. Defaults to `IO.write/2`.

# `viewer`

```elixir
@spec viewer() :: :ok
```

Starts the Ring Logger Viewer TUI app on the current prompt

# `viewer`

```elixir
@spec viewer(String.t()) :: :ok
```

Starts the Ring Logger Viewer TUI app on the current prompt with intial arguments

---

*Consult [api-reference.md](api-reference.md) for complete listing*
