Current section
Files
Jump to
Current section
Files
lib/tower/ephemeral_reporter.ex
defmodule Tower.EphemeralReporter do
@max_events 50
@moduledoc """
A very slim and naive built-in reporter, that just stores Tower events as process state.
It keeps only the last #{@max_events} events.
Possibly useful for development or testing.
## Example
iex> Tower.EphemeralReporter.events()
[]
iex> Application.put_env(:tower, :reporters, [Tower.EphemeralReporter])
iex> spawn(fn -> 1 / 0 end)
iex> Process.sleep(200)
:ok
iex> [event] = Tower.EphemeralReporter.events()
iex> event.kind
:error
iex> event.reason
%ArithmeticError{message: "bad argument in arithmetic expression"}
iex> Tower.EphemeralReporter.reset()
"""
@behaviour Tower.Reporter
@default_level :info
@empty_events {:queue.new(), 0}
use Agent
require Logger
alias Tower.Event
def start_link(_opts) do
Agent.start_link(fn -> @empty_events end, name: __MODULE__)
|> case do
{:error, {:already_started, existing_pid}} ->
Logger.warning("""
An attempt to start Tower.EphemeralReporter when it is already started was ignored.
If you are manually starting Tower.EphemeralReporter, you can safely stop doing it given
it is automatically started by Tower.
""")
{:ok, existing_pid}
on_start ->
on_start
end
end
def stop(pid) do
Agent.stop(pid)
end
@impl true
def report_event(%Event{level: level} = event) do
if Tower.equal_or_greater_level?(level, @default_level) do
Agent.update(
__MODULE__,
fn
{q, count} when count >= @max_events ->
{:queue.in(event, :queue.drop(q)), count}
{q, count} ->
{:queue.in(event, q), count + 1}
end
)
end
end
@doc """
Returns the list of all stored events.
"""
@spec events() :: [Tower.Event.t()]
def events do
Agent.get(
__MODULE__,
fn {q, _} ->
q
|> :queue.reverse()
|> :queue.to_list()
end
)
end
@spec reset() :: :ok
def reset do
Agent.update(__MODULE__, fn _events -> @empty_events end)
end
end