Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 33 additions & 8 deletions crates/busbar-kernel/src/metrics/door_cells.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,14 @@
//! when the egress is sealed; this module renders those strings as they were stated and never builds
//! one.
//!
//! THE MONEY GAUGE'S `model` LABEL IS STATED THE SAME WAY. A door plane's money rows are ledgered
//! under its internal lane keys (`"<plane>\u{1f}<entry>"`, and its fee lane `"<plane>\u{1f}"`); the
//! egress carries, beside its breaker labels, the `model` label each of those keys is scraped under
//! ([`DoorBreaker::models`]). Those are kept across generations ([`DoorCells::model_labels`]): the
//! ledger keeps a key's history after an apply retires the entry, so its label stays known.
//!
//! A door plane whose breaker is the kernel's own lane store (the plane serving the `pools` map)
//! publishes no unit: its cells are scraped from the store.
//! publishes no unit: its cells are scraped from the store, and its money rows are keyed bare.
//!
//! The set is carried across config applies with the `Arc` the `App` holds, and a plane's newer
//! generation replaces its older one, so a retired generation's cells are never scraped.
Expand All @@ -42,12 +48,17 @@ pub struct DoorBreaker {
pub pools: HashMap<String, String>,
/// Member → the stated `lane` label.
pub lanes: HashMap<DestinationId, String>,
/// Money ledger lane key → the stated `model` label its `busbar_bucket_tokens` series carry.
pub models: HashMap<String, String>,
}

/// Every served door plane's breaker cells, by plane.
/// Every served door plane's breaker cells, by plane, and the `model` label every door plane has
/// stated for a money ledger lane key.
#[derive(Default)]
pub struct DoorCells {
planes: RwLock<BTreeMap<String, DoorBreaker>>,
/// Sticky: a newer generation adds or restates labels and never withdraws one.
models: RwLock<HashMap<String, String>>,
}

impl DoorCells {
Expand All @@ -60,27 +71,41 @@ impl DoorCells {
/// Publish `plane`'s current generation: the breaker its egress walk trips, with its stated
/// labels. Replaces the generation published before it. An egress whose breaker is the kernel's
/// own lane store (no unit of its own) withdraws the plane.
/// The `model` labels the generation states are kept past it ([`Self::model_labels`]).
pub fn publish(&self, plane: &str, egress: &Egress) {
let mut planes = self.planes.write().unwrap_or_else(|e| e.into_inner());
match &egress.cells {
Some(breaker) => {
planes.insert(plane.to_string(), breaker.clone());
}
Some(breaker) => self.publish_breaker(plane, breaker.clone()),
None => {
planes.remove(plane);
self.planes
.write()
.unwrap_or_else(|e| e.into_inner())
.remove(plane);
}
}
}

/// Publish `plane`'s breaker directly: what [`Self::publish`] reads off an egress.
#[cfg(test)]
pub(crate) fn publish_breaker(&self, plane: &str, breaker: DoorBreaker) {
self.models
.write()
.unwrap_or_else(|e| e.into_inner())
.extend(breaker.models.iter().map(|(k, v)| (k.clone(), v.clone())));
self.planes
.write()
.unwrap_or_else(|e| e.into_inner())
.insert(plane.to_string(), breaker);
}

/// READ-ONLY: the `model` label every door plane has stated for a money ledger lane key, as
/// stated, including a retired generation's (its ledger history is still scraped).
#[must_use]
pub fn model_labels(&self) -> HashMap<String, String> {
self.models
.read()
.unwrap_or_else(|e| e.into_inner())
.clone()
}

/// READ-ONLY: every cell the published units have materialized, with its own state and
/// remaining cooldown, under its stated labels: `(pool, lane, state, cooldown)`. A destination
/// whose lifetime budget is spent reads Open with a never-elapsing cooldown, as a dead lane does.
Expand Down
44 changes: 40 additions & 4 deletions crates/busbar-kernel/src/metrics/money.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@
//! derived from the ledger x the CURRENT rate card (reprice-on-read).
//! * `busbar_bucket_tokens` — per (bucket, model, tier), the counts every spend figure is priced from.
//!
//! # THE `model` LABEL IS STATED, NEVER AN INTERNAL KEY
//!
//! A money row is ledgered under its lane key. The plane serving the `pools` map keys its rows by
//! the bare model name, which is the label 1.5.5 served. A door plane keys them
//! `"<plane>\u{1f}<entry>"` (and its fee lane `"<plane>\u{1f}"`), an internal key no scrape may
//! carry: the plane states the label each of its keys is scraped under, and this file renders that
//! string as stated ([`model_label`]). A key nobody stated that is not a plain name (a control byte,
//! or the plane separator) emits no series at all.
//!
//! # INTEGERS UP TO ONE NAMED BOUNDARY
//!
//! Every figure here is an integer — cents are `i64`, token counts `u64` — from the ledger read to
Expand All @@ -33,6 +42,7 @@ use crate::diagnostics::{
METRICS_SCRAPE_GROUP_LEDGER_READ_FAILED, METRICS_SCRAPE_KEY_USAGE_READ_FAILED,
METRICS_SCRAPE_LIST_KEYS_FAILED,
};
use crate::governance::PLANE_LANE_SEP;
use crate::state::App;

/// THE MONEY EGRESS BOUNDARY — the one function in this file that may name a float.
Expand All @@ -45,11 +55,27 @@ pub(super) fn set_gauge(gauge: metrics::Gauge, value: impl Into<i128>) {
gauge.set(exact as f64);
}

/// THE `model` LABEL a money row's ledger lane `key` is scraped under: the label a door plane stated
/// for it (`stated`, [`crate::metrics::door_cells::DoorCells::model_labels`]), else the key itself
/// when it is a plain name (1.5.5's bare model name). `None` — no series — for an unstated key that
/// carries a control byte or the plane separator, and for a stated label that carries one: an
/// internal key never reaches the exposition.
pub(super) fn model_label<'k>(
stated: &'k std::collections::HashMap<String, String>,
key: &'k str,
) -> Option<&'k str> {
let label = stated.get(key).map_or(key, String::as_str);
let internal = label.bytes().any(|b| b < 0x20) || label.contains(PLANE_LANE_SEP);
(!internal).then_some(label)
}

/// Refresh every money gauge for this scrape. No-op when governance is disabled. `now` is the
/// scrape's single clock read, shared with the lane gauges.
pub(super) fn refresh_money_gauges(app: &App, now: u64) {
// ── Governance: per-key spend, budget-remaining, tokens ────────────────────────────────────
if let Some(gov) = &app.governance {
// The `model` label every door plane stated for its ledger lane keys, read once.
let stated = app.door_cells.model_labels();
// `all_keys()` lists every VirtualKey from the SQLite store; this is a low-frequency scrape
// path. On error we skip only the PER-KEY gauge refresh below (by treating the key list as
// empty) rather than returning a stale/wrong per-key value. This must NOT `return` out of
Expand Down Expand Up @@ -142,9 +168,12 @@ pub(super) fn refresh_money_gauges(app: &App, now: u64) {
// Per-(bucket, model, tier) token gauges from the key bucket's ledger (the raw
// material any external per-model cost dashboard multiplies by its own catalog). The
// key's attribution bucket accrues in the all-time window.
for (model, tokens) in
for (lane, tokens) in
gov.bucket_model_tokens(&app.cost, &key.id, crate::governance::WINDOW_TOTAL, now)
{
let Some(model) = model_label(&stated, &lane) else {
continue;
};
let tier_v = |u: &str| tokens.get(u).copied().unwrap_or(0);
for (tier, v) in [
("input", tier_v(busbar_contract::records::UNIT_INPUT)),
Expand All @@ -163,7 +192,7 @@ pub(super) fn refresh_money_gauges(app: &App, now: u64) {
for (k, val) in &key.labels {
labels.push(metrics::Label::new(k.clone(), val.clone()));
}
labels.push(metrics::Label::new("model", model.clone()));
labels.push(metrics::Label::new("model", model.to_string()));
labels.push(metrics::Label::new("tier", tier));
set_gauge(metrics::gauge!(BUCKET_TOKENS, labels), v);
}
Expand Down Expand Up @@ -215,9 +244,12 @@ pub(super) fn refresh_money_gauges(app: &App, now: u64) {
remaining,
);
}
for (model, tokens) in
for (lane, tokens) in
gov.bucket_model_tokens(&app.cost, &bucket.bucket_id, bucket.window, now)
{
let Some(model) = model_label(&stated, &lane) else {
continue;
};
let tier_v = |u: &str| tokens.get(u).copied().unwrap_or(0);
for (tier, v) in [
("input", tier_v(busbar_contract::records::UNIT_INPUT)),
Expand All @@ -234,7 +266,7 @@ pub(super) fn refresh_money_gauges(app: &App, now: u64) {
set_gauge(
metrics::gauge!(
BUCKET_TOKENS,
dims(&[("model", model.clone()), ("tier", tier.to_string())])
dims(&[("model", model.to_string()), ("tier", tier.to_string())])
),
v,
);
Expand All @@ -244,3 +276,7 @@ pub(super) fn refresh_money_gauges(app: &App, now: u64) {
}
}
}

#[cfg(test)]
#[path = "../tests/money_label_tests.rs"]
mod tests;
4 changes: 4 additions & 0 deletions crates/busbar-kernel/src/tests/door_cells_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ fn tripped(pool: &str, stated: &str) -> DoorBreaker {
unit,
pools: HashMap::from([(pool.to_string(), stated.to_string())]),
lanes: HashMap::from([(d(7), "a".to_string()), (d(9), "b".to_string())]),
models: HashMap::new(),
}
}

Expand Down Expand Up @@ -59,6 +60,7 @@ fn a_spent_destination_reads_open_for_good() {
unit,
pools: HashMap::from([("solo".to_string(), "sec/solo".to_string())]),
lanes: HashMap::from([(d(3), "solo".to_string())]),
models: HashMap::new(),
},
);
assert_eq!(
Expand All @@ -84,6 +86,7 @@ fn a_newer_generation_replaces_the_older() {
unit: fresh,
pools: HashMap::from([("key-c".to_string(), "sec/c".to_string())]),
lanes: HashMap::from([(d(7), "a".to_string())]),
models: HashMap::new(),
},
);
assert_eq!(
Expand All @@ -110,6 +113,7 @@ fn a_door_planes_tripped_cell_is_on_the_scrape() {
unit,
pools: HashMap::from([("k\u{1f}scrape".to_string(), "sec-d/scrape".to_string())]),
lanes: HashMap::from([(d(7), "ok-m".to_string()), (d(9), "down-m".to_string())]),
models: HashMap::new(),
},
);
crate::metrics::refresh_scrape_gauges(&app);
Expand Down
159 changes: 159 additions & 0 deletions crates/busbar-kernel/src/tests/money_label_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2026 Busbar Inc and contributors

//! Tests for `crates/busbar-kernel/src/metrics/money.rs`: the `model` label a money row's ledger
//! lane key is scraped under.

use std::collections::{BTreeMap, HashMap};
use std::sync::Arc;

use super::*;
use crate::governance::{GovState, MemoryStore, RecordStore, VirtualKey};
use crate::metrics::door_cells::DoorBreaker;

/// THE RULE: a stated label is rendered as stated; an unstated plain name (1.5.5's bare model) is
/// its own label, byte for byte; an unstated key carrying the plane separator or any control byte,
/// and a stated label carrying one, emit no series.
#[test]
fn the_model_label_is_stated_or_plain_and_never_an_internal_key() {
let sep = PLANE_LANE_SEP;
let stated = HashMap::from([
(format!("door{sep}e"), "sec/e".to_string()),
(format!("door{sep}"), "sec".to_string()),
(format!("bad{sep}e"), "bad\u{7}label".to_string()),
]);
assert_eq!(model_label(&stated, &format!("door{sep}e")), Some("sec/e"));
assert_eq!(
model_label(&stated, &format!("door{sep}")),
Some("sec"),
"the plane's fee lane: its scope alone"
);
assert_eq!(
model_label(&stated, "gpt-5"),
Some("gpt-5"),
"the llm plane's bare model keeps its 1.5.5 bytes"
);
assert_eq!(
model_label(&stated, "claude-3.5/sonnet:v2"),
Some("claude-3.5/sonnet:v2")
);
assert_eq!(
model_label(&stated, &format!("other{sep}e")),
None,
"an unstated separator-bearing key is suppressed"
);
assert_eq!(
model_label(&stated, &format!("other{sep}")),
None,
"an unstated fee lane is suppressed"
);
assert_eq!(model_label(&stated, "tab\there"), None, "a control byte");
assert_eq!(
model_label(&stated, &format!("bad{sep}e")),
None,
"a stated label carrying a control byte is suppressed too"
);
}

fn key(id: &str) -> VirtualKey {
VirtualKey {
id: id.to_string(),
generation_hash: format!("hash-{id}"),
name: format!("key-{id}"),
enabled: true,
created_at: 1_700_000_000,
revision: 1,
..Default::default()
}
}

/// ON THE SCRAPE: a door plane's rows are `busbar_bucket_tokens` series under the labels it stated,
/// kept after a newer generation stops stating them (the ledger keeps the history); an unstated
/// internal key is no series; the llm plane's bare model is its own label; no money series carries
/// the separator. RED: the ledger key rendered verbatim (`model="door\u{1f}e"`).
#[test]
fn a_door_planes_money_rows_are_scraped_under_its_stated_labels() {
crate::metrics::init();
let sep = PLANE_LANE_SEP;
let vk = key("vk_money_label_scrape");
let store = Arc::new(MemoryStore::new());
store.put_key(&vk).expect("the key");
let gov = Arc::new(GovState::new(store, None).expect("governance"));
let cost = crate::cost::CostModel::flat(1);
let input = |n: u64| BTreeMap::from([(busbar_contract::records::UNIT_INPUT.to_string(), n)]);
for (lane, n) in [
("gpt-5-money-label".to_string(), 11),
(format!("door{sep}e"), 12),
(format!("door{sep}"), 13),
(format!("unstated{sep}x"), 14),
] {
gov.record_usage(&cost, &vk, "", &lane, &input(n), 1_700_000_000);
}
let app = crate::test_support::TestApp::new()
.governance(gov)
.cost(cost)
.build();
let models = |pairs: &[(String, &str)]| -> HashMap<String, String> {
pairs
.iter()
.map(|(k, v)| (k.clone(), (*v).to_string()))
.collect()
};
let breaker = |stated: HashMap<String, String>| DoorBreaker {
unit: Arc::new(busbar_kernel_breaker::BreakerUnit::new()),
pools: HashMap::new(),
lanes: HashMap::new(),
models: stated,
};
app.door_cells.publish_breaker(
"door",
breaker(models(&[
(format!("door{sep}e"), "sec/e"),
(format!("door{sep}"), "sec"),
])),
);
// A newer generation states only the fee lane: the entry's label is still known.
app.door_cells
.publish_breaker("door", breaker(models(&[(format!("door{sep}"), "sec")])));
crate::metrics::refresh_scrape_gauges(&app);
let out = crate::metrics::render();
let ours: Vec<&str> = out
.lines()
.filter(|l| {
l.starts_with("busbar_bucket_tokens{")
&& l.contains("bucket=\"vk_money_label_scrape\"")
&& l.contains("tier=\"input\"")
})
.collect();
let value = |model: &str| {
ours.iter()
.find(|l| l.contains(&format!("model=\"{model}\"")))
.and_then(|l| l.rsplit(' ').next())
.map(str::to_string)
};
assert_eq!(
value("gpt-5-money-label").as_deref(),
Some("11"),
"the bare model: {ours:?}"
);
assert_eq!(value("sec/e").as_deref(), Some("12"), "the entry: {ours:?}");
assert_eq!(
value("sec").as_deref(),
Some("13"),
"the fee lane: {ours:?}"
);
assert_eq!(
ours.len(),
3,
"the unstated internal key is no series: {ours:?}"
);
for line in out
.lines()
.filter(|l| l.starts_with("busbar_bucket_tokens{"))
{
assert!(
!line.contains(sep),
"no money series carries the separator: {line}"
);
}
}
Loading