Bloccs.Telemetry (bloccs v0.2.0)

Copy Markdown View Source

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}
  • [:bloccs, :node, :stop]
    • measurements: %{duration, monotonic_time}
    • metadata: above plus :outcome (:ok | :failed) and, when failed, :reason

  • [: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

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} where targets is a list of {to_node, to_port}

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
  • [:bloccs, :node, :skipped] — an idempotent duplicate was dropped
    • measurements: %{}
    • metadata: base metadata
  • [: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
  • [: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})

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} where reason is :no_producer or {:error, :timeout}

:producer back-pressure is reported separately by Bloccs.Producer:

  • [:bloccs, :producer, :backpressure] — a push/3 had to park because the buffer was full (the caller waits until a consumer drains space)
    • measurements: %{size}
    • metadata: %{name, buffer}

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

attach_default_logger(level \\ :debug)

@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.

detach_default_logger()

@spec detach_default_logger() :: :ok | {:error, :not_found}

Detach the default logger handler.

events()

List the events the default logger handler subscribes to.