Current section
Files
Jump to
Current section
Files
lib/reporter.ex
defmodule BencheeAsync.Reporter do
@moduledoc false
use GenServer
def start_link(opts \\ []) do
GenServer.start_link(__MODULE__, opts, name: __MODULE__)
end
@impl GenServer
def init(_opts \\ []) do
{:ok, init_state()}
end
def reset_timer() do
GenServer.cast(__MODULE__, :reset_timer)
end
def maybe_enable() do
GenServer.cast(__MODULE__, :maybe_enable)
end
def disable() do
GenServer.call(__MODULE__, :disable)
end
def ignore_ms(ms) when is_number(ms) do
GenServer.call(__MODULE__, {:ignore_ms, ms})
end
def set_scenario(scenario_name, input \\ :__no_input) when is_binary(scenario_name) do
GenServer.cast(__MODULE__, {:set_scenario, scenario_name, :erlang.phash2(input)})
end
def record() do
GenServer.cast(__MODULE__, :record)
end
def get_samples(scenario_name, input \\ :__no_input) when is_binary(scenario_name) do
GenServer.call(__MODULE__, {:samples, scenario_name, :erlang.phash2(input)})
end
def clear() do
GenServer.call(__MODULE__, :clear)
end
@impl GenServer
def handle_call({:set_pid, pid}, _caller, state) when is_pid(pid) do
{:reply, :ok, %{state | current_pid: pid}}
end
@impl GenServer
def handle_call({:samples, scenario_name, hash}, _caller, state) do
{:reply, Map.get(state.samples, {scenario_name, hash}, []), state}
end
@impl GenServer
def handle_call(:clear, _caller, _state) do
{:reply, :ok, init_state()}
end
@impl GenServer
def handle_call({:ignore_ms, ms}, _caller, state) do
Process.send_after(self(), :clear_ignore, round(ms))
{:reply, :ok, %{state | ignoring?: true, ignore_until: current_time() + round(ms * 1000)}}
end
@impl GenServer
def handle_call(:disable, _caller, state) do
{:reply, :ok, %{state | ignoring?: true}}
end
@impl GenServer
def handle_info(:clear_ignore, state) do
{:noreply, %{state | start_time: current_time(), ignoring?: false, ignore_until: nil}}
end
@impl GenServer
def handle_cast(:maybe_enable, %{ignoring?: true, ignore_until: nil} = state) do
{:noreply, %{state | ignoring?: false, start_time: current_time()}}
end
# keep ignoring
@impl GenServer
def handle_cast(:maybe_enable, state) do
{:noreply, state}
end
@impl GenServer
def handle_cast(:record, %{ignoring?: true} = state),
do: {:noreply, state}
@impl GenServer
def handle_cast(:record, state) do
now = current_time()
diff = now - state.start_time
samples =
Map.update(state.samples, state.current_key, [diff], fn prev ->
[diff | prev]
end)
{:noreply, %{state | samples: samples, start_time: now}}
end
@impl GenServer
def handle_cast(:reset_timer, state) do
{:noreply, %{state | start_time: current_time()}}
end
@impl GenServer
def handle_cast({:set_scenario, scenario_name, hash}, state) do
{:noreply, %{state | current_key: {scenario_name, hash}}}
end
defp current_time, do: :erlang.system_time(:nano_seconds)
defp init_state do
%{
start_time: current_time(),
samples: %{},
current_key: nil,
ignoring?: false,
ignore_until: nil
}
end
end