defmodule Absinthe.Middleware.Telemetry do
@moduledoc """
Gather and report telemetry about an individual field resolution
"""
@field_start [:absinthe, :resolve, :field, :start]
@field_stop [:absinthe, :resolve, :field, :stop]
@behaviour Absinthe.Middleware
@impl Absinthe.Middleware
def call(resolution, _) do
id = :erlang.unique_integer()
system_time = System.system_time()
start_time_mono = System.monotonic_time()
:telemetry.execute(
@field_start,
%{system_time: system_time},
%{id: id, telemetry_span_context: id, resolution: resolution}
)
%{
resolution
| middleware:
resolution.middleware ++
[
{{__MODULE__, :on_complete},
%{
id: id,
start_time_mono: start_time_mono,
middleware: resolution.middleware
}}
]
}
end
def on_complete(
%{state: :resolved} = resolution,
%{
id: id,
start_time_mono: start_time_mono,
middleware: middleware
}
) do
end_time_mono = System.monotonic_time()
:telemetry.execute(
@field_stop,
%{duration: end_time_mono - start_time_mono, end_time_mono: end_time_mono},
%{
id: id,
telemetry_span_context: id,
middleware: middleware,
resolution: resolution
}
)
resolution
end
end