Node and Flow Metrics

September 10, 2026 ยท View on GitHub

This guide explains the two metric layers available for tracing signal volume through an OTel Arrow Dataflow Engine pipeline:

receiver --> processor A --> processor B --> exporter
   |            |                |           |
   +------------+----------------+-----------+-- node metrics (all nodes)
                +----------------+
                `-- flow metrics (processors only)

Use node metrics to see the messages, signal items, and logical payload size a specific receiver, processor, or exporter consumes and produces. Use flow metrics to measure a selected, contiguous processor range as one operation: how many items entered and left, how long processing took, and which decision nodes removed items.

Both metric layers are emitted through the engine's internal observability pipeline. Configure an engine.observability.pipeline to export them, or use the admin metrics endpoint while developing. See Configuration for observability-pipeline configuration.

Choose the Right Metric Layer

QuestionUse
Which node changed the count of logs, metrics, or traces?Node item metrics
What is the aggregate compute time for selected processor stages?Flow metrics
Which decision processor dropped items within a processor range?Flow metrics
How many items did a receiver admit or exporter emit?Node item metrics

Node Metrics

A message is the PData batch that moves between nodes. An item is an individual log record, metric data point, or span in that batch. One message can contain multiple items. Logical size is the byte size of the current in-memory payload representation. Payload size is the encoded application payload observed at a receiver or exporter boundary.

Completion duration measures from a node boundary until the terminal ACK or NACK: from input for processors and exporters, and from output for receivers. Local duration uses the boundary defined by each node instrument, which may include encoding or backend latency. Use flow.compute.duration instead for compute time across a processor range.

none and basic enable no node metrics by default. normal adds message measurements, and detailed adds every optional measurement. A per-node policy enables its measurement at any runtime metric level.

MeasurementEngine-managed metricsNode-implemented metricsDefault levelPer-node policy
Messagesnode.input.messages, node.output.messagesreceiver.received.messages, exporter.attempted.messagesnormalmessages: true
Itemsnode.input.items, node.output.itemsexporter.attempted.itemsdetaileditem_counts: true
Logical sizenode.input.size, node.output.size-detailedsize: true
Payload size-receiver.received.payload.size, exporter.attempted.payload.sizedetailedsize: true
Completion durationnode.completion.duration-detailedcompletion_duration: true
Local duration-receiver.processing.duration, processor.compute.duration, exporter.attempted.durationdetailedduration: true

The node.input.* metrics apply to processors and exporters. node.output.* metrics apply to receivers and processors. Node-implemented metrics require the implementation to use the corresponding shared instrumentation.

Message, item, and size counters have bounded signal and outcome data-point attributes. signal is one of logs, metrics, or traces; outcome is success, failure, or refused, recorded during terminal ACK/NACK unwinding. The metric-set entity attributes identify the pipeline and node, so group by those attributes when comparing nodes.

Enable Optional Measurements

Warning

Item counting and sizing may inspect the payload; completion and local duration add timing and bookkeeping. Measure the impact on a representative workload before enabling these measurements broadly. Prefer per-node opt-in when only a specific stage needs them.

To enable it for every node in a pipeline, use detailed:

policies:
  telemetry:
    runtime_metrics: detailed

To enable it only for selected nodes, opt in the relevant nodes:

nodes:
  sampler:
    type: processor:log_sampling
    policies:
      telemetry:
        item_counts: true
        size: true
    config: {}

This narrower configuration is appropriate when only a small part of a pipeline needs payload measurements. detailed enables item counts and size for every node without node-level settings.

Interpret Node Counts

For a linear topology, a node's output.items normally matches the next node's input.items for the same signal. A filtering or sampling processor can emit fewer items than it receives; a fan-out processor can emit an item on more than one output. Compare counts only along the particular edge or topology behavior being investigated.

Node metrics are the right choice when operators need to locate where a signal count changes, including receiver admission, processors, and exporter output. Use the runnable trafficgen-node-metrics.yaml example to inspect the metrics on every node, compare local duration with flow duration, or observe an individually opted-in processor.

Flow Metrics

Flow metrics are an explicit telemetry policy for a contiguous range of processor nodes. They are not enabled by runtime_metrics; declare each flow under the pipeline's policies.telemetry.flow_metrics list.

policies:
  telemetry:
    flow_metrics:
      - id: ingest_processing
        bounds:
          start_node: enrich
          end_node: filter
        duration_distribution: normal
        purpose: transform
        metrics:
          - input_messages
          - input_items
          - input_size
          - output_messages
          - output_items
          - output_size
          - compute_duration
          - dropped_items

The start_node and end_node fields name processors; the range includes both boundary processors. The engine validates that the end processor is reachable from the start processor and rejects interleaved flow ranges. Omit metrics to enable every supported flow metric. When present, it must not be empty and must not repeat a metric.

duration_distribution controls the aggregation used by compute_duration:

ValueOTLP representationRetained data
basicBucketless HistogramCount, sum, min, and max
normalExponentialHistogramNormal-resolution buckets and summary statistics
detailedExponentialHistogramHigher-resolution buckets and summary statistics

The setting defaults to normal. Use basic for lower aggregation cost or compatibility with consumers that do not support exponential histograms. Basic distributions do not retain buckets, so percentiles cannot be reconstructed. The setting is ignored when compute_duration is not enabled. Its distribution tier is independent of runtime_metrics, which controls whether broader metric families are enabled.

Each flow's attributes are part of its OTLP instrumentation scope, so flows using different tiers have distinct metric stream identities. Some backends flatten instrumentation scopes and require one data type per metric name. Use the same wire type across flows and deployments when exporting to such a backend: basic produces Histogram, while normal and detailed produce ExponentialHistogram.

Flow Metrics and Attributes

Flow metrics use the flow.input, flow.output, flow.compute, and flow.dropped instrumentation scopes and include these scope attributes:

AttributeMeaning
flow.idThe configured id.
flow.node.startThe configured start processor.
flow.node.endThe configured end processor.
flow.purposeThe configured purpose, or an empty value when omitted.
flow.node.decisionThe decision processor that emitted dropped.items, or an empty value for other flow metrics.

flow.purpose lets OpenTelemetry Views select a specific kind of flow when multiple flows use the shared directional scopes. For example, a view can select scope_name: flow.compute with scope_attributes: { flow.purpose: transform } to rename or route only transformation-flow metrics.

The metrics have a bounded signal data-point attribute with values logs, metrics, and traces. They intentionally do not have an outcome attribute. Flow metrics are recorded while a PData batch moves forward through the processor range, before its terminal ACK/NACK outcome is known. They describe range traversal and decision-node drops, independently of the eventual node outcome.

An end processor that ACKs without sending, such as a filter that removes every item, does not increment any flow.output metric. It still records flow.compute.duration and may record flow.dropped.items.

Configuration valueEmitted metricMeaning
input_messagesflow.input.messagesPData messages entering the start processor.
input_itemsflow.input.itemsSignal items entering the start processor.
input_sizeflow.input.sizeLogical payload bytes entering the start processor.
output_messagesflow.output.messagesPData sends leaving the end processor.
output_itemsflow.output.itemsSignal items leaving the end processor.
output_sizeflow.output.sizeLogical payload bytes leaving the end processor.
compute_durationflow.compute.durationHistogram of aggregate processor compute duration in the range, in seconds.
dropped_itemsflow.dropped.itemsSignal items a decision processor in the range chose to drop.

For a linear flow, the sum of flow.dropped.items across flow.node.decision equals flow.input.items - flow.output.items. There is no per-decision-node kept metric: counts that survive one decision can reach a later decision, so per-node kept counts are not additive. Use the flow's flow.output.items as the flow-wide surviving count.

See trafficgen-node-metrics.yaml for a runnable comparison of node and flow metrics around a sampling processor.