Telemetry

View Source

reckon-gater — the gateway API layer that fronts a ReckonDB cluster — is instrumented with telemetry, the standard BEAM instrumentation library. Every request, retry, worker-registry change, cluster membership change, and channel broadcast emits a telemetry event. You attach handlers to turn those events into logs, metrics, or traces.

Telemetry is in-process pub/sub: emitting an event with no attached handler costs a single ETS lookup, so instrumentation is effectively free until you opt in.

How it works

An event is a stable list of atoms, e.g. [reckon_gater, request, stop]. When the operation happens, gater calls:

telemetry:execute(Event, Measurements, Metadata).
  • Measurements — a map of numbers (durations, counts). Feed counters and histograms.
  • Metadata — a map of context (store_id, request_type, reason). Become labels you filter and group by.

A handler is a 4-arity function attached to one or more events. It runs synchronously in the emitting process, so keep it cheap — forward to a separate process or a metrics exporter rather than doing heavy work inline.

Quick start

%% Attach the built-in logger handler:
ok = reckon_gater_telemetry:attach_default_handler().

%% Or a custom handler across all gater events:
reckon_gater_telemetry:attach(my_metrics, fun my_app:handle/4, #{}).

A minimal handler that records request latency:

handle([reckon_gater, request, stop], #{duration := Us}, #{request_type := T}, _Cfg) ->
    my_histogram:observe({gater_request, T}, Us),
    ok;
handle(_Event, _Measurements, _Metadata, _Cfg) ->
    ok.

Detach with reckon_gater_telemetry:detach(my_metrics).

The facade

reckon_gater_telemetry is the public entry point:

FunctionPurpose
attach_default_handler/0Attach the built-in logger handler.
detach_default_handler/0Remove it.
attach/3Attach a custom HandlerId, Fun, Config across gater events.
detach/1Remove a handler by id.
emit/3Emit an event (wrapper over telemetry:execute/3).
all_events/0The list of gater event names — handy for telemetry:attach_many.

Metrics exporters

For production, bridge to your metrics backend instead of (or alongside) the logger:

Because event names are stable, exporter configuration is a straight mapping from event → metric.

Event catalogue

Durations are in microseconds. The definitive list with inline measurement/metadata docs lives in include/reckon_gater_telemetry.hrl.

Worker registry

Gater tracks store workers in a pg-backed registry.

EventMeasurementsMetadata
[reckon_gater, worker, registered]system_timestore_id, node, pid
[reckon_gater, worker, unregistered]system_timestore_id, pid (adds reason => down on a monitored exit)
[reckon_gater, worker, lookup]durationstore_id

Request

The gater request path — one pair (or start+error) per API call.

EventMeasurementsMetadata
[reckon_gater, request, start]system_timestore_id, request_type
[reckon_gater, request, stop]durationstore_id, request_type, result (success)
[reckon_gater, request, error]durationstore_id, request_type, reason

Retry

Gater retries transient errors with back-off.

EventMeasurementsMetadata
[reckon_gater, retry, attempt]delay_ms, attempt (1-based, upcoming attempt)store_id, reason
[reckon_gater, retry, exhausted]total_attemptsstore_id, reason

Cluster

EventMeasurementsMetadata
[reckon_gater, cluster, node_up]system_timenode, member_count
[reckon_gater, cluster, node_down]system_timenode, member_count

Channel

EventMeasurementsMetadata
[reckon_gater, channel, broadcast]recipient_countchannel, topic

What to watch

  • Request throughput / latency — count + duration histogram of request.stop, grouped by request_type.
  • Error raterequest.error rate, and retry.exhausted (operations that gave up after retries).
  • Retry pressureretry.attempt volume signals a struggling backend.
  • Fan-outchannel.broadcast recipient_count distribution.
  • Cluster churncluster.node_up / node_down.