defmodule Absinthe.Phase.Telemetry do
@moduledoc """
Gather and report telemetry about an operation.
"""
@operation_start [:absinthe, :execute, :operation, :start]
@operation_stop [:absinthe, :execute, :operation, :stop]
@subscription_start [:absinthe, :subscription, :publish, :start]
@subscription_stop [:absinthe, :subscription, :publish, :stop]
use Absinthe.Phase
def run(blueprint, options) do
event = Keyword.fetch!(options, :event)
do_run(blueprint, event, options)
end
defp do_run(blueprint, [:execute, :operation, :start], options) do
id = :erlang.unique_integer()
system_time = System.system_time()
start_time_mono = System.monotonic_time()
:telemetry.execute(
@operation_start,
%{system_time: system_time},
%{id: id, telemetry_span_context: id, blueprint: blueprint, options: options}
)
{:ok,
%{
blueprint
| source: blueprint.input,
telemetry: %{id: id, start_time_mono: start_time_mono}
}}
end
defp do_run(blueprint, [:subscription, :publish, :start], options) do
id = :erlang.unique_integer()
system_time = System.system_time()
start_time_mono = System.monotonic_time()
:telemetry.execute(
@subscription_start,
%{system_time: system_time},
%{id: id, telemetry_span_context: id, blueprint: blueprint, options: options}
)
{:ok,
%{
blueprint
| telemetry: %{id: id, start_time_mono: start_time_mono}
}}
end
defp do_run(blueprint, [:subscription, :publish, :stop], options) do
end_time_mono = System.monotonic_time()
with %{id: id, start_time_mono: start_time_mono} <- blueprint.telemetry do
:telemetry.execute(
@subscription_stop,
%{duration: end_time_mono - start_time_mono, end_time_mono: end_time_mono},
%{id: id, telemetry_span_context: id, blueprint: blueprint, options: options}
)
end
{:ok, blueprint}
end
defp do_run(blueprint, [:execute, :operation, :stop], options) do
end_time_mono = System.monotonic_time()
with %{id: id, start_time_mono: start_time_mono} <- blueprint.telemetry do
:telemetry.execute(
@operation_stop,
%{duration: end_time_mono - start_time_mono, end_time_mono: end_time_mono},
%{id: id, telemetry_span_context: id, blueprint: blueprint, options: options}
)
end
{:ok, blueprint}
end
end