Reading a node’s :stats (Rust)¶
A monitor reads a node’s counters with one READ per seam:
READ <any vertex>:stats.graph.delivery answers one SETTINGS block of NAME/u64 pairs
(RFC-0010 Amendment 1). The example builds the request, then decodes the block a fresh node
answers.
What to notice¶
One READ is one seam is one block. The four counters arrive together, sampled in one call, so a monitor compares two whole blocks rather than counters read at different moments.
Look counters up by NAME. A reader ignores names it does not know.
settings_getreturnsNonefor one, which is how a newer node’s extra counters stay harmless.The answer here is built, not received. The crate has no transport, so the example constructs the 113-byte block a fresh node sends. The
settings/stats-seam-blockconformance vector pins those bytes.
Source¶
1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright 2026 avatarsd LLC
3
4/*!
5 * @brief One concept: reading a node's `:stats` counters. One READ names one seam and
6 * answers one SETTINGS block of `NAME`/u64 pairs (RFC-0010 Amendment 1).
7 *
8 * Run: `cargo run --example fwd_read_stats` (from `bindings/rust/`).
9 */
10
11use libtracer::fwd::{fwd_kind, fwd_op};
12use libtracer::structured::{settings_get, settings_typed, SettingValue};
13use libtracer::{decode_fwd, encode, encode_fwd_bytes, FieldSel, FwdRequest};
14
15fn main() {
16 // READ <any vertex>:stats.graph.delivery — the seam is node-scoped.
17 let mut req = FwdRequest::new(fwd_op::READ, &["sensor", "temp"], &["client"]);
18 req.field = Some(FieldSel::Str(":stats.graph.delivery"));
19 let frame = encode_fwd_bytes(&req).unwrap();
20 println!("READ :stats.graph.delivery ({} bytes)", frame.len());
21
22 // What a fresh node answers: four u64 LE counters, all zero. (Built here so the
23 // example runs without a peer; the `settings/stats-seam-block` vector pins it.)
24 let zero = 0u64.to_le_bytes();
25 let names = ["no_target", "denied", "out_of_memory", "fan_out_truncated"];
26 let pairs: Vec<_> = names
27 .iter()
28 .map(|n| (*n, SettingValue::Value(&zero)))
29 .collect();
30 let block = settings_typed(&pairs).unwrap();
31 assert_eq!(encode(&block).len(), 113);
32
33 let mut reply = FwdRequest::new(fwd_op::REPLY, &["client"], &["sensor", "temp"]);
34 reply.kind = Some(fwd_kind::RESULT);
35 reply.payload = Some(block);
36 let answer = decode_fwd(&encode_fwd_bytes(&reply).unwrap()).unwrap();
37
38 // A reader looks counters up by NAME and ignores any it does not know.
39 let settings = answer.payload.expect("a RESULT carries the block");
40 for name in names {
41 let raw = settings_get(&settings, name)
42 .unwrap()
43 .expect("counter present");
44 let count = u64::from_le_bytes(raw.try_into().expect("fixed-width u64"));
45 println!("{name:>18} = {count}");
46 assert_eq!(count, 0);
47 }
48 assert_eq!(settings_get(&settings, "not_a_counter").unwrap(), None);
49}
Run it from bindings/rust/:
$ cargo run --example fwd_read_stats
See also: protocol TLVs reference, the :stats record.