hive-agent: export a per-file line count for subagent role files
A role file is read into every subagent dispatch that names it, and nothing measured its size. A new watch on the same 15-minute tick as claude_md_watch records `hyperhive.agent.subagent_role.lines`, one series per `<role>.md` under the state dir's `subagent_roles/`, labelled `role` with the file stem. Metric only: no todo, no threshold. Fixes #4558
This commit is contained in:
parent
74b63dd031
commit
f19a9f546e
4 changed files with 123 additions and 6 deletions
|
|
@ -18,12 +18,12 @@
|
|||
//! from `handle_turn`. The `PeriodicReader` still batches + exports on its
|
||||
//! own interval; only the recording is event-driven, not the export.
|
||||
//!
|
||||
//! [`record_claude_md_lines`] is the one exception, sharing this module's
|
||||
//! exporter setup rather than [`record`]'s per-turn call site — `CLAUDE.md`
|
||||
//! size *is* continuously live (like hive-c0re's cgroup values), so
|
||||
//! [`crate::claude_md_watch`] records it from its own periodic tick instead.
|
||||
//! [`record_claude_usage`] is the same kind of exception, fed from
|
||||
//! [`crate::claude_usage_watch`]'s poll of the subscription usage endpoint.
|
||||
//! Three exceptions share this module's exporter but not [`record`]'s
|
||||
//! per-turn call site: their values are continuously live (like hive-c0re's
|
||||
//! cgroup values), so each is recorded from its own watch's periodic tick —
|
||||
//! [`record_claude_md_lines`] from [`crate::claude_md_watch`],
|
||||
//! [`record_subagent_role_lines`] from [`crate::subagent_role_watch`], and
|
||||
//! [`record_claude_usage`] from [`crate::claude_usage_watch`].
|
||||
//!
|
||||
//! Resource attributes (`service.name`, `agent`, `hive`, `swarm`) are picked
|
||||
//! up automatically by the SDK from the container-wide `OTEL_RESOURCE_ATTRIBUTES`
|
||||
|
|
@ -58,6 +58,9 @@ struct Instruments {
|
|||
/// hive-c0re's container gauges), not a once-per-turn one, so it has
|
||||
/// its own entry point rather than riding `record`'s per-turn call.
|
||||
claude_md_lines: Gauge<u64>,
|
||||
/// Recorded from [`crate::subagent_role_watch`]'s own tick, keyed by
|
||||
/// `role`.
|
||||
subagent_role_lines: Gauge<u64>,
|
||||
/// Recorded from [`crate::claude_usage_watch`]'s own tick, keyed by
|
||||
/// `window`.
|
||||
claude_usage_percent: Gauge<f64>,
|
||||
|
|
@ -120,6 +123,17 @@ pub fn record_claude_md_lines(lines: u64) {
|
|||
inst.claude_md_lines.record(lines, &[]);
|
||||
}
|
||||
|
||||
/// Record one subagent role file's line count, keyed by `role` (the file
|
||||
/// stem). Called from [`crate::subagent_role_watch`]'s periodic tick.
|
||||
/// No-op when OTEL isn't configured, same as [`record`].
|
||||
pub fn record_subagent_role_lines(role: String, lines: u64) {
|
||||
let Some(inst) = INSTRUMENTS.get_or_init(build).as_ref() else {
|
||||
return;
|
||||
};
|
||||
inst.subagent_role_lines
|
||||
.record(lines, &[KeyValue::new("role", role)]);
|
||||
}
|
||||
|
||||
/// Record one subscription usage window (`five_hour`, `seven_day`, …):
|
||||
/// `percent` is 0-100, `resets_at` unix seconds. No-op when OTEL isn't
|
||||
/// configured, same as [`record`].
|
||||
|
|
@ -182,6 +196,9 @@ fn build() -> Option<Instruments> {
|
|||
.u64_gauge("hyperhive.agent.loose_ends.reminders")
|
||||
.build(),
|
||||
claude_md_lines: meter.u64_gauge("hyperhive.agent.claude_md.lines").build(),
|
||||
subagent_role_lines: meter
|
||||
.u64_gauge("hyperhive.agent.subagent_role.lines")
|
||||
.build(),
|
||||
claude_usage_percent: meter
|
||||
.f64_gauge("hyperhive.agent.claude_usage.percent")
|
||||
.with_unit("%")
|
||||
|
|
|
|||
Loading…
Reference in a new issue