Skip to content
LogoLogo

Self-metrics

Headrace exports its own telemetry over OTLP - the same protocol it processes - so you can watch a pipeline with the tools you already point at everything else. It is off by default.

Enabling

headrace --metrics otlp run pipeline.yaml          # export over OTLP/gRPC
headrace --metrics otlp --otlp-endpoint http://collector:4317 run pipeline.yaml
headrace --metrics stdout run pipeline.yaml        # print to stderr, for debugging
  • otlp exports to --otlp-endpoint, or OTEL_EXPORTER_OTLP_ENDPOINT, or the default.
  • stdout periodically prints metrics to stderr. Convenience only: the dump interleaves with a stdout sink's data, so prefer otlp for clean output.

Instruments

Every metric is attributed by node (the node id) and kind (source, filter, window, map, join, sink); records.dropped adds a reason. The two window instruments carry node only.

MetricTypeAttributesMeaning
headrace.records.outcounternode, kindRecords a node emitted or forwarded.
headrace.records.droppedcounternode, kind, reasonRecords dropped, split by reason (below).
headrace.window.flushescounternodeWindow flush events.
headrace.window.groupshistogramnodeAggregate groups emitted per flush.
headrace.node.errorscounternode, kindNode tasks that terminated with an error.
headrace.wasm.memory.byteshistogramnode, kindA wasm module's linear-memory size, recorded when it changes.

reason on headrace.records.dropped:

reasonMeaning
filteredA filter predicate rejected the record.
invalidA missing/non-numeric field or an inevaluable expression, under a skip policy.
lateThe record arrived after its window had already fired.
incompleteA join bucket was evicted before every input supplied a value.
cappedThe node was at its max_groups cap.

Reading them

  • A rising records.dropped{reason=late} means allowed_lateness is too small for the source's out-of-orderness - see Troubleshooting.
  • records.dropped{reason=invalid} on a window or map node points at a missing or non-numeric field with an on_missing / on_invalid policy of skip.
  • headrace.window.groups shows the cardinality of each flush - useful for spotting a group_by that fans out more than you expected.
  • records.dropped{reason=capped} is nonzero only when a node hit its max_groups cap: the group_by cardinality outran the limit (a misconfigured key or an attack). Raise the cap or narrow the group_by.
  • wasm.memory.bytes is the linear memory a wasm module settled on; size its max_memory above the peak you see here, with headroom.