defmodule ExRay.Store do @moduledoc """ Store the span chains in an ETS table. The table must be created during the application initialization using the create call. The span chain acts like a call stack by pushing and popping spans as they come in and out of scope. """ @table_name :tracers require Logger @doc """ Initializes the spans ETS table. The span table can be shared across process boundary. """ @spec create :: any def create do :ets.new(@table_name, [ :set, :named_table, :public, read_concurrency: true, write_concurrency: true ] ) end @doc """ Pushes a new span to the span stack. The key must be unique. """ @spec push(String.t, any) :: any def push(key, val) when is_binary(key) do vals = get(key) if length(vals) > 0 do :ets.insert(@table_name, {key, [val] ++ vals}) else :ets.insert(@table_name, {key, [val]}) end val end @doc """ Pops the top span off the stack. """ @spec pop(String.t) :: any def pop(key) when is_binary(key) do [h | t] = get(key) :ets.insert(@table_name, {key, t}) h end @doc """ Fetch span stack for the given key """ @spec get(String.t) :: [any] def get(key) when is_binary(key) do @table_name |> :ets.lookup(key) |> case do [] -> [] [{_key, vals}] -> vals end end @doc """ Fetch the top level span for a given key """ @spec current(String.t) :: [any] def current(key) when is_binary(key) do key |> get |> case do [] -> nil [h | _t] -> h end end end