Packages

Guesswork is a logic programming library for Elixir. It is heavily inspired by Prolog, but attempts to use idiomatic Elixir when expressing problems and their solutions.

Current section

Files

Jump to
guesswork lib guesswork telemetry query_run.ex
Raw

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