Skip to main content

submilli_engine/runtime/
metrics.rs

1//! Embedder hook for runtime observability. The interpreter times host-side
2//! operations (currently HTTP transport), counts calls that needed an approval it
3//! could not ask for, and hands each to a [`MetricsSink`]
4//! the embedder installs on [`StoreData`](super::StoreData). The default sink
5//! discards everything, so the pure-interpreter path stays dependency-free —
6//! the binary crates (CLI, server) are the only place a real metrics backend
7//! (Sentry) is wired in.
8
9use super::approvals::{Approver, Unasked};
10
11/// One completed HTTP host operation, handed to [`MetricsSink::http_operation`]
12/// after the transport returns (success or failure).
13#[derive(Clone, Debug)]
14pub struct HttpMetric {
15    /// The gated capability that ran: `http.get`, `http.post`, `http.download`, …
16    pub capability: String,
17    /// Destination host from the request URL (e.g. `api.example.com`); empty when
18    /// the URL doesn't parse.
19    pub host: String,
20    /// Wall-clock of the network transport — `send` plus capped body read for a
21    /// request, or stream-plus-fsync for a download. Excludes arg marshalling.
22    pub duration_ms: u64,
23    /// HTTP status, or `0` if the request failed before any response arrived.
24    pub status: u16,
25    /// Bytes received: response-body length, or bytes written for a download.
26    pub bytes: u64,
27    /// Bounded outcome class: `ok`, `error`, `timeout`, or `too_large`.
28    pub outcome: &'static str,
29}
30
31/// Embedder sink for runtime metrics. Every method has a no-op default so an
32/// embedder only overrides what it reports on.
33pub trait MetricsSink: Send + Sync {
34    /// An HTTP host operation finished. Called once per `http_request` /
35    /// `http_download` host call, on both the success and failure paths.
36    fn http_operation(&self, _metric: HttpMetric) {}
37    /// A call that needs `approver`'s approval was denied without asking anyone,
38    /// for `why`.
39    fn approval_unasked(&self, _approver: Approver, _why: Unasked) {}
40}
41
42/// Discards every metric. The [`StoreData`](super::StoreData) default.
43pub struct NoopMetricsSink;
44
45impl MetricsSink for NoopMetricsSink {}