Consumed traffic over a given time window?

I need programmatic access to the following data over a given time window:

  • the base-rate traffic which my node consumed
  • the paid traffic which my node consumed

What are my options?


Canton Metrics?

For example, I see these two Canton Metrics:

Would I sum those metrics for the total traffic? However, I’m assuming that the metric does not differentiate between base-rate and paid traffic. Is that correct?

Scan API or Canton Console?

I see the traffic-status endpoint but that returns results for “at the time of the request.”

I see the traffic_state_of_members_at_timestamp function, but that would be challenging to use reliably due to traffic purchases and base rate credits during the time window.

Your first assumption is actually right: summing event-delivered-cost + event-rejected-cost gives you total charged traffic. Both meters are recorded from the consumedCost field of the actual traffic receipt the sequencer returns to the sender (see TrafficStateController in the Canton sources), so they reflect what was really debited — a sequenced-but-rejected event that was charged shows up in event-rejected-cost with its real cost, and a rejection where nothing was consumed records 0. The updates are also guarded against double counting during crash-recovery replay (metrics are only updated when the receipt actually advances the local traffic state).

Your second assumption is also correct - those metrics don’t differentiate base-rate vs. paid. The split happens in the accounting itself: each event’s cost is drawn from the base-rate bucket first, and only the overflow is charged against extra (paid) traffic (`TrafficConsumed.consume()` in the Canton sources).

The fact that unlocks windowed queries: extraTrafficConsumed and extraTrafficPurchased in the member’s traffic state are cumulative, monotonically increasing counters. Top-ups only bump extraTrafficPurchased, and base-rate credits only refill baseTrafficRemainder - neither disturbs extraTrafficConsumed. So purchases and base-rate credits during your window are a non-issue:

  • paid traffic over [t1, t2] = extraTrafficConsumed(t2) − extraTrafficConsumed(t1)
  • total traffic over [t1, t2] = increase(event-delivered-cost + event-rejected-cost) over the window
  • base-rate traffic over [t1, t2] = total − paid

You have several equivalent sources for the paid counter:

1. Prometheus gauges that live right next to the metrics you found - …traffic-control.extra-traffic-consumed, extra-traffic-purchased, and base-traffic-remainder. They are set from the absolute values in the sequencer’s traffic receipts, so after a node restart they resume at the true cumulative value on the first traffic update.

2. The Scan traffic-status endpoint - actual.total_consumed there is exactly this cumulative counter (“Total extra traffic consumed by the member on the given synchronizer” per the OpenAPI spec). The “at the time of the request” snapshot is fine precisely because the counter is cumulative: poll it on a schedule, store the samples, and diff.

3. The participant admin API (`TrafficControlService.TrafficControlState`) if you’d rather not depend on Scan.

4. traffic_state_of_members_at_timestamp at the two window boundaries also works, for the same reason - the concern about purchases and base-rate credits mid-window doesn’t apply to the consumed counter.

Caveats:

- The cost meters are in-process counters, so they reset on node restart - use increase() or persist samples

- The cumulative counters are scoped to a physical synchronizer instance - across synchronizer migrations the state can be re-initialized, so treat a negative delta as a migration boundary

If you need per-event attribution, the node logs the split at DEBUG level:

Consuming cost X: From base traffic: Y From extra traffic: Z