Statsig.ObservabilityClient behaviour (statsig_elixir v0.23.2)

Behaviour and helper APIs for forwarding Statsig SDK metrics to an observability backend (Datadog, Prometheus, etc.) from Elixir.

An implementation is a module that implements the callbacks in this behaviour. Use start_link/3 to launch the bridge process and pass the returned %Statsig.ObservabilityClient.Reference{} into Statsig.Options.

Callbacks are invoked fire-and-forget by the core: the SDK does not wait for a reply, and there is no backpressure. Callbacks should be non-blocking — a slow callback (e.g. a synchronous HTTP push inside handle_increment) lets the bridge process mailbox grow unbounded. Hand slow work off to another process instead.

The core's high-cardinality tags (lcut and prev_lcut) are dropped before the metric callbacks are invoked unless allowlisted. The synchronous should_enable_high_cardinality_for_this_tag callback cannot round-trip over the fire-and-forget bridge, so the allowlist is configured statically via the :high_cardinality_tags option to start_link/3:

{:ok, ref} =
  Statsig.ObservabilityClient.start_link(MyClient, nil,
    high_cardinality_tags: ["lcut"]
  )

Summary

Types

Opaque state returned from user callbacks.

Metric tags, or nil when the core supplies none.

Functions

Starts a bridge process for the provided implementation module.

Stops the bridge process for the given reference.

Types

state()

@type state() :: term()

Opaque state returned from user callbacks.

tags()

@type tags() :: %{optional(String.t()) => String.t()} | nil

Metric tags, or nil when the core supplies none.

Callbacks

handle_dist(t, number, tags, state)

(optional)
@callback handle_dist(String.t(), number(), tags(), state()) :: {:ok, state()} | :ok

handle_error(t, t, state)

(optional)
@callback handle_error(String.t(), String.t(), state()) :: {:ok, state()} | :ok

handle_gauge(t, number, tags, state)

(optional)
@callback handle_gauge(String.t(), number(), tags(), state()) :: {:ok, state()} | :ok

handle_increment(t, number, tags, state)

(optional)
@callback handle_increment(String.t(), number(), tags(), state()) :: {:ok, state()} | :ok

handle_init(state)

(optional)
@callback handle_init(state()) :: {:ok, state()} | :ok

handle_terminate(reason, state)

(optional)
@callback handle_terminate(reason :: term(), state()) :: term()

Invoked when the bridge process shuts down gracefully (e.g. via stop/3).

A last chance for implementations that buffer metrics in their state to flush them. Subject to the usual GenServer.terminate/2 caveats: not guaranteed to run on abnormal exits.

init(init_arg)

@callback init(init_arg :: term()) :: {:ok, state()} | {:error, term()}

Functions

start_link(module, init_arg \\ nil, opts \\ [])

@spec start_link(module(), term(), Keyword.t()) ::
  {:ok, Statsig.ObservabilityClient.Reference.t()} | :ignore | {:error, term()}

Starts a bridge process for the provided implementation module.

Returns {:ok, %Statsig.ObservabilityClient.Reference{}} which can be assigned to %Statsig.Options{observability_client: reference}.

Options

  • :high_cardinality_tags - which of the core's high-cardinality tags to keep on metrics. The core currently consults this only for "lcut" and "prev_lcut"; other values are a no-op, and tags outside that set are always kept regardless of this option. Defaults to nil (core default: lcut/prev_lcut are dropped).

Remaining options are passed to GenServer.start_link/3.

stop(reference, reason \\ :normal, timeout \\ 5000)

@spec stop(Statsig.ObservabilityClient.Reference.t(), term(), non_neg_integer()) ::
  :ok

Stops the bridge process for the given reference.