Telemetry events emitted by the bloccs runtime, and an optional default logger handler.
Attach your own handlers with :telemetry.attach/4 (or attach_many/4) to
feed metrics into Telemetry.Metrics, OpenTelemetry, StatsD, etc. A node's
[observability] block is passed through verbatim in every event's metadata
under :observability, so a handler can filter by the metrics/traces a node
declared.
Events
Per-message node execution is wrapped in :telemetry.span/3, which emits:
[:bloccs, :node, :start]- measurements:
%{system_time, monotonic_time} - metadata:
%{network, node, in_port, attempt, observability, telemetry_span_context}
- measurements:
[:bloccs, :node, :stop]- measurements:
%{duration, monotonic_time} metadata: above plus
:outcome(:ok | :failed) and, when failed,:reason
- measurements:
[:bloccs, :node, :exception]— only if execution raises (the runtime rescues node errors, so this fires only on a bug in the runtime itself)- measurements:
%{duration, monotonic_time} - metadata: above plus
:kind,:reason,:stacktrace
- measurements:
Routing emits a per-dispatch event (the signal Bloccs.Trace records for
coverage):
[:bloccs, :emit]— a node emitted on an out-port- measurements:
%{targets}(number of downstream edges) - metadata:
%{network, from_node, from_port, targets}wheretargetsis a list of{to_node, to_port}
- measurements:
Two additional point-in-time events:
[:bloccs, :node, :retry]— a backed-off retry was scheduled- measurements:
%{delay_ms, next_attempt} - metadata: base metadata plus
:reason
- measurements:
[:bloccs, :node, :skipped]— an idempotent duplicate was dropped- measurements:
%{} - metadata: base metadata
- measurements:
[:bloccs, :node, :dropped]— a node filtered a message: its effect shell returned:drop(or an empty emit list), so the message was consumed and acked without dispatching anything downstream. Distinct from:skipped(which is idempotency de-duplication), so filter and dedup metrics stay separable.- measurements:
%{} - metadata: base metadata
- measurements:
[:bloccs, :node, :dispatch_error]— a node emitted successfully but one or more downstream deliveries failed; the message is failed (not retried, since the effect already ran)- measurements:
%{count}(number of failed edges) - metadata: base metadata plus
:failures(a list of{endpoint, reason})
- measurements:
Routing reports each individual delivery failure too:
[:bloccs, :dispatch, :error]— a single downstream push failed- measurements:
%{} - metadata:
%{network, from_node, from_port, to_node, to_port, reason}wherereasonis:no_produceror{:error, :timeout}
- measurements:
:producer back-pressure is reported separately by Bloccs.Producer:
[:bloccs, :producer, :backpressure]— apush/3had to park because the buffer was full (the caller waits until a consumer drains space)- measurements:
%{size} - metadata:
%{name, buffer}
- measurements:
Summary
Functions
Attach a built-in handler that logs the interesting runtime events. Handy in development; in production you'll usually attach your own metrics handlers instead. Idempotent — re-attaching is a no-op.
Detach the default logger handler.
List the events the default logger handler subscribes to.
Functions
@spec attach_default_logger(Logger.level()) :: :ok | {:error, :already_exists}
Attach a built-in handler that logs the interesting runtime events. Handy in development; in production you'll usually attach your own metrics handlers instead. Idempotent — re-attaching is a no-op.
@spec detach_default_logger() :: :ok | {:error, :not_found}
Detach the default logger handler.
List the events the default logger handler subscribes to.