codetether_agent/telemetry/mod.rs
1//! # Telemetry
2//!
3//! Observability for the CodeTether agent. Tracks token usage, tool executions,
4//! per-provider latency/throughput, file changes, swarm progress, cost
5//! estimates, and persistent audit-style records.
6//!
7//! ## Architecture
8//!
9//! Every telemetry concern lives in its own submodule so that individual files
10//! stay small (≤ 50 lines of code, per the project's [coding standards]) and
11//! each file holds a **single responsibility**. This module re-exports the
12//! public surface so callers continue to write `use crate::telemetry::Foo;`
13//! without knowing the internal layout.
14//!
15//! | Submodule | Responsibility |
16//! |---|---|
17//! | [`tokens`] | Token totals, snapshots, and the global [`AtomicTokenCounter`] |
18//! | [`tools`] | Tool-execution records, the [`AtomicToolCounter`], and [`FileChange`] |
19//! | [`provider`] | Per-provider request records, snapshots, and aggregated stats |
20//! | [`context`] | Context-window usage ratios ([`ContextLimit`]) |
21//! | [`cost`] | USD cost estimation ([`CostEstimate`]) |
22//! | [`a2a`] | A2A message records |
23//! | [`swarm`] | Swarm (multi-agent) telemetry collector |
24//! | [`metrics`] | Per-instance rolling metrics ([`Telemetry`]) |
25//! | [`persistent`] | On-disk / long-lived stats façade |
26//! | [`globals`] | Process-wide `Lazy` singletons |
27//!
28//! ## Coding Standards for This Module
29//!
30//! New code must follow these rules (enforced in review):
31//!
32//! 1. **Single Responsibility.** One struct or one tight function group per file.
33//! 2. **50-line limit.** Hard cap per file (excluding comments/blanks). Split
34//! before you reach 45.
35//! 3. **Rustdoc everywhere.** Every public item gets `///` docs with a
36//! `# Examples` section. Prefer runnable (` ```rust `) examples;
37//! fall back to `no_run` only when a runtime is required; avoid `ignore`.
38//! 4. **No `any`-style typing.** Every public field and return type is
39//! explicitly typed.
40//! 5. **Tracing over println.** Use structured fields, e.g.
41//! `tracing::info!(tool = %name, "...")`.
42//! 6. **Never hand-roll atomics when an existing counter fits.** Reuse
43//! [`AtomicTokenCounter`] / [`AtomicToolCounter`] rather than adding new
44//! `AtomicU64` fields elsewhere.
45//!
46//! [coding standards]: ../../AGENTS.md
47//!
48//! ## Quick Start
49//!
50//! ```rust
51//! use codetether_agent::telemetry::{TokenTotals, CostEstimate, TokenCounts};
52//!
53//! let totals = TokenTotals::new(1_000, 500);
54//! assert_eq!(totals.total(), 1_500);
55//!
56//! let cost = CostEstimate::from_tokens(
57//! &TokenCounts::new(1_000_000, 500_000),
58//! 3.00, // $ per 1M input tokens
59//! 15.00, // $ per 1M output tokens
60//! );
61//! assert_eq!(cost.currency, "USD");
62//! ```
63
64pub mod a2a;
65pub mod context;
66pub mod cost;
67pub mod globals;
68pub mod memory;
69pub mod metrics;
70pub mod persistent;
71pub mod provider;
72pub mod rss_watchdog;
73pub mod swarm;
74pub mod tokens;
75pub mod tools;
76
77pub use a2a::A2AMessageRecord;
78pub use context::ContextLimit;
79pub use cost::CostEstimate;
80pub use globals::{PROVIDER_METRICS, TOKEN_USAGE, TOOL_EXECUTIONS};
81pub use metrics::{Telemetry, TelemetryMetrics};
82pub use persistent::{
83 PersistentStats, PersistentStatsInner, get_persistent_stats, record_persistent,
84};
85pub use provider::{ProviderMetrics, ProviderRequestRecord, ProviderSnapshot};
86pub use swarm::SwarmTelemetryCollector;
87pub use tokens::{
88 AtomicTokenCounter, GlobalTokenSnapshot, TokenCounts, TokenTotals, TokenUsageSnapshot,
89};
90pub use tools::{AtomicToolCounter, FileChange, ToolExecution};