Current section
Files
Jump to
Current section
Files
lib/guesswork/telemetry/query_run.ex
defmodule Guesswork.Telemetry.QueryRun do
@moduledoc """
Represents a single 'run', or unification, of a query.
"""
defstruct [:query_id, :run_id, :start_time, :end_time, :duration_ms, :error]
@type t() :: %__MODULE__{
query_id: String.t(),
run_id: String.t(),
start_time: DateTime.t(),
end_time: DateTime.t() | nil,
duration_ms: integer() | nil,
error: nil | term()
}
@doc """
Attempts to build a new query run entry using the needed ids and the start time
provided by telemetry (assumes a `:native` unix time).
"""
@spec new(String.t(), String.t(), integer()) :: {:ok, t()} | {:error, atom()}
def new(query_id, run_id, start_time) do
case DateTime.from_unix(start_time, :native) do
{:ok, start_time} ->
{:ok,
%__MODULE__{
query_id: query_id,
run_id: run_id,
start_time: start_time,
end_time: nil,
duration_ms: nil,
error: nil
}}
{:error, e} ->
{:error, e}
end
end
@doc """
Returns a key used for storage in ets.
"""
@spec ets_key(t()) :: {String.t(), String.t()}
def ets_key(%__MODULE__{query_id: query_id, run_id: run_id}) do
{query_id, run_id}
end
@doc """
Takes a query run and the `duration` of the run then completes the record by
calculating and inserting the `end_time` and `duration`.
`duration` is assumed to be `:native` unix times.
"""
@spec finish(t(), integer()) :: {:ok, t()} | {:error, atom()}
def finish(
%__MODULE__{start_time: start_time, end_time: nil, duration_ms: nil, error: nil} = run,
duration
) do
duration_ms = System.convert_time_unit(duration, :native, :millisecond)
{:ok,
%__MODULE__{
run
| end_time: DateTime.add(start_time, duration_ms, :millisecond),
duration_ms: duration_ms
}}
end
def finish(%__MODULE__{}, _duration), do: {:error, :already_finished}
@doc """
Takes a query run the `duration` and the error that failed the query, and then
completes the record by calculating and inserting the `end_time` and `duration`.
`duration` is assumed to be `:native` unix times.
"""
@spec finish(t(), integer(), term()) :: {:ok, t()} | {:error, atom()}
def finish(
%__MODULE__{start_time: start_time, end_time: nil, duration_ms: nil, error: nil} = run,
duration,
error
) do
duration_ms = System.convert_time_unit(duration, :native, :millisecond)
{:ok,
%__MODULE__{
run
| end_time: DateTime.add(start_time, duration_ms, :millisecond),
duration_ms: duration_ms,
error: error
}}
end
def finish(%__MODULE__{}, _duration, _error), do: {:error, :already_finished}
end