Metrics from Rust
metra-ic-client records metrics in your canister and sends them to your Agent
in small batches. Recording never makes a network call; sending happens when
you flush.
Before you start
Section titled “Before you start”- Add your canister as a sender of the Agent’s Metrics connection. Send telemetry from your code.
- The crate ships with icLens’s source and isn’t on crates.io yet. Vendor it into your workspace.
Create the client
Section titled “Create the client”Create one ClientState and keep it across messages and upgrades:
use metra_ic_client::{ClientError, ClientState, CollectionPolicy};
fn new_metrics_client() -> Result<ClientState, ClientError> { ClientState::new(CollectionPolicy::default())}Define a metric
Section titled “Define a metric”Register each metric once. This one is a gauge of queue depth:
use metra_ic_client::{ ClientError, ClientState, Descriptor, DescriptorIdentity, InstrumentationScope, PointKind, Resource,};
fn register_queue_depth(client: &mut ClientState) -> Result<u64, ClientError> { client.register_instrument(Descriptor { description: "Items waiting for processing".into(), identity: DescriptorIdentity { name: "app.queue.depth".into(), unit: "1".into(), point_kind: PointKind::Gauge, monotonic: None, temporality: None, }, metadata: vec![], resource: Resource { schema_url: None, attributes: vec![], }, scope: InstrumentationScope { name: "worker.metrics".into(), version: Some("1".into()), schema_url: None, attributes: vec![], }, })}Record a value
Section titled “Record a value”use metra_ic_client::{ClientError, ClientState, Number, PointValue};
fn record_queue_depth( client: &mut ClientState, instrument_id: u64, depth: u128, now_nanos: u64,) -> Result<(), ClientError> { client.record_gauge( instrument_id, vec![], PointValue::Number(Number::Nat128(depth)), None, now_nanos, now_nanos, )}Use add_sum for counters and observe_histogram for durations. If the
buffer is full, recording returns an error rather than dropping the value.
Send to the Agent
Section titled “Send to the Agent”-
Open a lane to the Agent and register your metrics with it.
-
Flush on a timer. Read
flush_status; when a flush is due, callprepare_appendfor one batch. -
Save, send, settle. Save the attempt with
begin_attempt, release any borrow of your state, awaitexecute, then settle the reply.
If a send times out
Section titled “If a send times out”A timeout becomes TransportError::UnknownOutcome. Call mark_unknown, then
reconcile_remote and reconcile: the client asks the Agent what it received
before sending anything else. New values keep collecting in the meantime.
After an upgrade, restore the client state and start your timer again. Never rebuild a pending batch from newer values.