skip to content

In a gNMI STREAM subscription, why sample interface counters but put oper-status on ON_CHANGE, and what do heartbeat_interval and suppress_redundant add?

level: middleimportance: must knowfreq 30%

answer

  1. how often each value moves
  2. a counter changes with every packet
  3. silence is ambiguous
  4. nanoseconds, not seconds
  5. re-send once per heartbeat

basics

~20 s

Counters change with every packet, so a gNMI SAMPLE subscription sends them on a fixed sample_interval; status changes rarely, so ON_CHANGE sends it only when it moves. heartbeat_interval forces periodic re-sends so silence is distinguishable from a dead stream.

solid answer

~40 s

In gNMI (an OpenConfig specification) each path in a `STREAM` subscription has its own mode. `SAMPLE` sends the value once per `sample_interval`, given in **nanoseconds**; a target that cannot meet it must reject the subscription, and `0` means the fastest interval it can do. That fits counters, which move with every packet. `ON_CHANGE` first sends every matching path, then sends a value only when it changes, which fits `oper-status`: a flap arrives in near real time and a stable link costs nothing. Two knobs fix the edge cases. `heartbeat_interval` makes the target re-send the value once per interval even if unchanged, so a quiet stream proves it is alive. `suppress_redundant` on a `SAMPLE` path skips leaves that have not changed since the last update, and a heartbeat still forces one update per interval.

go deeper

for a junior

Remember the two main per-path modes: SAMPLE sends on a fixed interval, ON_CHANGE sends only when a value changes, and counters suit the first while status suits the second.

for a middle

Explain the parameters: sample_interval in nanoseconds with 0 meaning fastest possible, the initial dump before on-change updates, and how heartbeat_interval and suppress_redundant interact.

for a senior

Show you have run it: alarm on missing heartbeats, watch the duplicates count for a lagging collector, and pick intervals that 2,000 devices and the collector can both sustain.

for a principal

Weigh resolution against cost per data type, decide where TARGET_DEFINED is acceptable, and set an estate-wide policy for intervals and heartbeats rather than per-team choices.

## The setting A team is replacing five-minute SNMP polls of 2,000 devices with **gNMI** streaming telemetry. gNMI is an **OpenConfig specification** (version 0.10.0), not an IETF RFC. A collector opens a `Subscribe` RPC and sends a `SubscriptionList` whose `mode` is `STREAM`: a long-lived subscription that keeps sending. Inside that list, **each `Subscription` (one path) carries its own mode**: `SAMPLE`, `ON_CHANGE` or `TARGET_DEFINED`. Choosing per path is the skill being tested. ## SAMPLE: a value on a fixed interval - A `SAMPLE` subscription **must** carry a `sample_interval`, an unsigned 64-bit integer in **nanoseconds** between samples. Ten seconds is `10000000000`. - The value **must** be sent once per interval. - If the target cannot support the requested interval, it **must reject** the subscription by closing the RPC with an `InvalidArgument` error rather than silently sending slower. - `sample_interval` of `0` does not disable anything: the target creates the subscription and sends at the **lowest interval it can**. Interface counters (`in-octets`, `out-octets`, error counts) change with every packet. Sampling gives the collector evenly spaced readings, stamped with the collection time, from which it computes rates. ## ON_CHANGE: a value only when it moves - The target **first sends updates for all paths** that match, so the collector starts with a full picture. - After that, values **should** be sent only when they change. - When a node disappears (an interface is removed), the target must send an explicit **delete** in the `Notification`; in `SAMPLE` mode an explicit delete is optional. `oper-status` changes rarely and matters immediately. On-change delivers a flap within moments and sends nothing while the link is stable. Putting a counter on `ON_CHANGE` would mean an update for almost every packet; the IETF's YANG-Push text (RFC 8641, section 3.10) gives `in-octets` as an example of a node a publisher may not support on-change for at all. ## heartbeat_interval and suppress_redundant Pure on-change has a blind spot: **silence is ambiguous**. A link that stays up and a stream that silently stalled look the same to the collector. 1. On an `ON_CHANGE` path, a `heartbeat_interval` makes the target **re-send the value once per heartbeat interval**, changed or not. The collector can refresh its cache and alarm when an expected heartbeat is missing. 2. On a `SAMPLE` path, `suppress_redundant` set to true means the target **should not** send a leaf that has not changed since its last update. It works per leaf: under `/a/b` with leaves `c` and `d`, if only `c` changed, only `c` is sent. 3. A `heartbeat_interval` on a suppressed `SAMPLE` path forces **one update per heartbeat interval** regardless, restoring the liveness signal. Like `sample_interval`, it is in nanoseconds. ## TARGET_DEFINED and a comparison With `TARGET_DEFINED` the target chooses per leaf: on-change for event-driven leaves, sampling for counters, at an interval it picks and may change. If the request carries a `sample_interval`, the target should reject it. | Mode | Sends | Good for | Watch out for | |---|---|---|---| | `SAMPLE` | value every `sample_interval` | counters, gauges | interval cost on 2,000 devices | | `SAMPLE` + `suppress_redundant` | only changed leaves, per sample | slow-moving values | add a heartbeat for liveness | | `ON_CHANGE` | initial values, then changes | status, configuration | quiet stream looks like a dead one | | `ON_CHANGE` + heartbeat | changes plus periodic re-send | status you alarm on | heartbeat traffic | | `TARGET_DEFINED` | target's choice per leaf | mixed subtrees | you give up control of the interval | ## When the collector falls behind An `Update` carries a `duplicates` count. If the collector cannot keep up, the target may coalesce values for a path, keep only the latest and increment `duplicates`, so the collector can see that transitions happened even though it missed them. A rising duplicates count on on-change status is a sign the collector, not the network, is the bottleneck.

  • In gNMI, what does a SAMPLE subscription with sample_interval set to 0 do?
    It does not turn sampling off or switch to on-change. The specification says the target must create the subscription and send the data at the lowest interval possible for that target. It is a way of saying "as fast as you can", which on a large estate is usually a bad default.
  • Why might you choose TARGET_DEFINED instead of picking SAMPLE or ON_CHANGE per path?
    For a broad subtree that mixes counters and state, `TARGET_DEFINED` lets the device pick on-change for event-driven leaves and sampling for counters. The cost is control: the target chooses the interval and may change it dynamically, and a request that also sets `sample_interval` should be rejected.
  • How does a gNMI ON_CHANGE collector learn that an interface was removed?
    The target must put the removed node's path in the `delete` field of a `Notification`; explicit deletion is required in on-change mode and optional in sample mode. Deletes may name a container, covering all its leaves at once.

On-change with a heartbeat works like a smoke alarm that chirps on a schedule: it stays quiet while nothing happens, sounds at once when something does, and the scheduled chirp proves it is still alive, because silence alone cannot tell you that.

saying these in an interview costs you the question

  • ON_CHANGE on byte counters gives the most accurate traffic graphs.
  • A quiet ON_CHANGE stream proves the device and link are healthy.
  • gNMI sample_interval is given in seconds.
  • Setting sample_interval to 0 turns sampling off.
  • A target that cannot meet the sample interval silently sends more slowly.