Struct CostTracker
pub struct CostTracker { /* private fields */ }Implementations§
Source§impl CostTracker
impl CostTracker
Sourcepub fn new(config: CostConfig, workspace_dir: &Path) -> Result<Self>
pub fn new(config: CostConfig, workspace_dir: &Path) -> Result<Self>
Create a new cost tracker.
pub fn config(&self) -> CostConfig
Sourcepub fn is_enabled(&self) -> bool
pub fn is_enabled(&self) -> bool
Whether this tracker enforces and records spend. The process-global tracker reads the live config, so a reload applies at its next check; a derived tracker reports the mode frozen at derivation time, matching what its checks and records actually honor for the delegation’s whole lifetime.
Sourcepub fn enforcement_flags(&self) -> (bool, bool)
pub fn enforcement_flags(&self) -> (bool, bool)
The effective (enabled, track_per_agent) pair for this tracker,
as the runtime reads it when deciding how a delegated sub-loop is
scoped: the process-global tracker reports the live pair, and a
derived tracker the pair frozen at derivation (for a nested hop,
inherited from its delegating parent). Exposed as a plain pair
rather than the mode itself so the public surface stays two
booleans.
Sourcepub fn update_config(&self, config: CostConfig)
pub fn update_config(&self, config: CostConfig)
Hot-swap config so reloaded budget limits apply without a restart.
Derive an ephemeral tracker whose budget checks read only the
shared process-wide daily and monthly totals against the global
limits (read live each check), with no per-agent ceiling and no
subtree chain: the frozen-mode equivalent of the global tracker.
An independent nested delegation with no per-hop ceiling (0 =
inherit the global limit) uses this so the target runs under the
shared global limits instead of its delegating parent’s
agent-scoped tracker, while the enforcement mode stays frozen
from the base exactly as for every other derived tracker.
Derive an ephemeral tracker whose shared daily check uses the base
tracker’s global daily limit tightened by daily_ceiling_usd
(config.daily_limit_usd.min(daily_ceiling_usd), read live each
check). Delegated sub-loops use this when
[cost].track_per_agent is false: per-alias daily totals cannot
exist, so the per-hop ceiling can only tighten the shared check, and
their recorded spend lands on the same durable ledger as every other
path. The captured track_per_agent = false is frozen for the
derived tracker’s lifetime, so a mid-run reload enabling per-agent
attribution does not start attributing this delegation’s rows
halfway through a run. The derived tracker is never registered as
the process-global one; it lives only as long as the delegation
that created it.
Sourcepub fn derived_for_agent(
&self,
agent_alias: &str,
daily_ceiling_usd: f64,
) -> Self
pub fn derived_for_agent( &self, agent_alias: &str, daily_ceiling_usd: f64, ) -> Self
Derive an ephemeral tracker whose daily_ceiling_usd is compared
against agent_alias’s OWN daily spend on the shared ledger, so a
per-profile cost ceiling means that agent’s usage for the day. The
tracker’s own shared daily and monthly limits still apply to the
shared totals on top, so the derived tracker can only ever be
stricter than the base tracker, never looser. The scope kind and
the enforcement mode (enabled, track_per_agent, captured at
derivation) are fixed for the derived tracker’s lifetime; the
limits themselves are read live from the base tracker’s shared
config handle, so config reloads apply at the next check_budget.
Sourcepub fn derived_for_agent_in_chain(
&self,
agent_alias: &str,
daily_ceiling_usd: f64,
inherited: Vec<Arc<SubtreeSpend>>,
) -> Self
pub fn derived_for_agent_in_chain( &self, agent_alias: &str, daily_ceiling_usd: f64, inherited: Vec<Arc<SubtreeSpend>>, ) -> Self
derived_for_agent with an inherited delegation chain: inherited
carries the ancestor subtree entries (nearest first) collected with
Self::subtree_chain_for_children on the delegating parent’s
tracker. Budget checks through the derived tracker then also count
this agent’s spend against every ancestor’s per-hop ceiling, and
usage recorded through it accumulates into each ancestor entry’s
descendant total. Chains only apply to per-agent scopes.
The scope kind and the enforcement mode (enabled,
track_per_agent, captured at derivation) are fixed for the
derived tracker’s lifetime; the limits themselves are read live
from the base tracker’s shared config handle, so config reloads
apply at the next check_budget.
Sourcepub fn subtree_chain_for_children(&self) -> Vec<Arc<SubtreeSpend>>
pub fn subtree_chain_for_children(&self) -> Vec<Arc<SubtreeSpend>>
The subtree entries a delegation FROM this tracker’s agent passes to the child’s budget scope: this agent’s own entry first, then the inherited ancestor chain (nearest first). Empty when this tracker is not agent-scoped, so unscoped and shared-cap delegations carry no chain. Delegation plumbing calls this on the tracker of the loop a delegated sub-agent runs under when building that sub-agent’s own delegate tool.
Sourcepub fn session_id(&self) -> &str
pub fn session_id(&self) -> &str
Get the session ID.
Sourcepub fn check_budget(&self, estimated_cost_usd: f64) -> Result<BudgetCheck>
pub fn check_budget(&self, estimated_cost_usd: f64) -> Result<BudgetCheck>
Check if a request is within budget.
Sourcepub fn record_usage(&self, usage: TokenUsage) -> Result<()>
pub fn record_usage(&self, usage: TokenUsage) -> Result<()>
Record a usage event without per-agent attribution.
Sourcepub fn record_usage_with_agent(
&self,
usage: TokenUsage,
agent_alias: Option<&str>,
) -> Result<()>
pub fn record_usage_with_agent( &self, usage: TokenUsage, agent_alias: Option<&str>, ) -> Result<()>
Record a usage event attributed to a specific agent alias. When
[cost].track_per_agent is false the alias is dropped before
persistence.
Sourcepub fn record_usage_with_task_attribution(
&self,
usage: TokenUsage,
agent_alias: Option<&str>,
task_id: Option<&str>,
) -> Result<()>
pub fn record_usage_with_task_attribution( &self, usage: TokenUsage, agent_alias: Option<&str>, task_id: Option<&str>, ) -> Result<()>
Record a usage event attributed to a specific agent alias and/or task.
Agent attribution still follows [cost].track_per_agent; task
attribution is independent because it keys feature-level usage back to
the durable control-plane task that spent it.
Sourcepub fn record_usage_with_owned_task_attribution(
&self,
usage: TokenUsage,
agent_alias: Option<&str>,
task_id: Option<String>,
) -> Result<()>
pub fn record_usage_with_owned_task_attribution( &self, usage: TokenUsage, agent_alias: Option<&str>, task_id: Option<String>, ) -> Result<()>
Record a usage event with an already-owned task id. Runtime attribution resolves the id from durable task state, so this avoids cloning that id again before persistence.
Sourcepub fn record_usage_attributed(
&self,
usage: TokenUsage,
agent_alias: Option<&str>,
task_id: Option<String>,
conversation_id: Option<String>,
) -> Result<()>
pub fn record_usage_attributed( &self, usage: TokenUsage, agent_alias: Option<&str>, task_id: Option<String>, conversation_id: Option<String>, ) -> Result<()>
Record a usage event attributed to an agent, a durable task, and the
chat session that incurred it. conversation_id is the runtime
session key scoped around the turn; None keeps the record
attributable only to the daemon-lifetime tracker id.
pub fn record_scoped_usage_with_owned_task_attribution( &self, usage: TokenUsage, agent_alias: Option<&str>, task_id: Option<String>, ) -> Result<()>
Sourcepub fn get_summary(&self) -> Result<CostSummary>
pub fn get_summary(&self) -> Result<CostSummary>
Get the current cost summary. When [cost].track_per_agent is
enabled, the response includes a by_agent rollup over the current
month’s records.
Sourcepub fn get_current_month_model_stats(
&self,
) -> Result<HashMap<String, ModelStats>>
pub fn get_current_month_model_stats( &self, ) -> Result<HashMap<String, ModelStats>>
Per-model rollup over every record in the current UTC month.
CostSummary::by_model stays daily-scoped for dashboard and RPC
consumers. Operator surfaces that qualify the monthly total, such as
the zeroclaw status pricing-unavailable warning, need the whole
month’s recorded provenance so unpriced usage from an earlier day
does not disappear at UTC day rollover while the monthly spend still
omits its cost. Derived from the persisted ledger on demand; nothing
is cached or duplicated.
pub fn get_summary_in_bounds( &self, from: Option<DateTime<Utc>>, to: Option<DateTime<Utc>>, ) -> Result<CostSummary>
Sourcepub fn get_summary_for_agent(&self, agent_alias: &str) -> Result<CostSummary>
pub fn get_summary_for_agent(&self, agent_alias: &str) -> Result<CostSummary>
Get the current cost summary scoped to a single agent alias. The
session/day/month figures and by_model are filtered to records
attributed to that alias; by_agent is left empty since the
caller already chose the dimension.
Sourcepub fn get_summary_for_task(&self, task_id: &str) -> Result<CostSummary>
pub fn get_summary_for_task(&self, task_id: &str) -> Result<CostSummary>
Get usage summary for a durable attributed task. Totals are derived from persisted ledger rows carrying the task-attribution key; no consumed counters are stored on feature-specific extension records.
Sourcepub fn get_usage_totals_for_task(&self, task_id: &str) -> Result<(u64, f64)>
pub fn get_usage_totals_for_task(&self, task_id: &str) -> Result<(u64, f64)>
Get usage totals for a durable attributed task without building model/agent rollups. Totals are still derived from the canonical persisted ledger.
pub fn get_usage_totals_for_task_with_pricing( &self, task_id: &str, ) -> Result<(u64, f64, bool)>
Sourcepub fn get_daily_cost(&self, date: NaiveDate) -> Result<f64>
pub fn get_daily_cost(&self, date: NaiveDate) -> Result<f64>
Get the daily cost for a specific date.
Source§impl CostTracker
impl CostTracker
Sourcepub fn get_or_init_global(
config: CostConfig,
workspace_dir: &Path,
) -> Option<Arc<Self>>
pub fn get_or_init_global( config: CostConfig, workspace_dir: &Path, ) -> Option<Arc<Self>>
Return the process-global CostTracker for the ledger under
workspace_dir, applying config to the existing tracker on later
calls and reusing the same Arc. Returns None while cost tracking is
disabled and no tracker exists for that ledger yet; a later reload
flipping enabled to true constructs it on demand.
Auto Trait Implementations§
impl !RefUnwindSafe for CostTracker
impl !UnwindSafe for CostTracker
impl Freeze for CostTracker
impl Send for CostTracker
impl Sync for CostTracker
impl Unpin for CostTracker
impl UnsafeUnpin for CostTracker
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more