Skip to main content

CostTracker

Struct CostTracker 

pub struct CostTracker { /* private fields */ }

Implementations§

Source§

impl CostTracker

Source

pub fn new(config: CostConfig, workspace_dir: &Path) -> Result<Self>

Create a new cost tracker.

Source

pub fn config(&self) -> CostConfig

Source

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.

Source

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.

Source

pub fn update_config(&self, config: CostConfig)

Hot-swap config so reloaded budget limits apply without a restart.

Source

pub fn derived_shared(&self) -> Self

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.

Source

pub fn derived_shared_capped(&self, daily_ceiling_usd: f64) -> Self

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.

Source

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.

Source

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.

Source

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.

Source

pub fn session_id(&self) -> &str

Get the session ID.

Source

pub fn check_budget(&self, estimated_cost_usd: f64) -> Result<BudgetCheck>

Check if a request is within budget.

Source

pub fn record_usage(&self, usage: TokenUsage) -> Result<()>

Record a usage event without per-agent attribution.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn record_scoped_usage_with_owned_task_attribution( &self, usage: TokenUsage, agent_alias: Option<&str>, task_id: Option<String>, ) -> Result<()>

Source

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.

Source

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.

Source

pub fn get_summary_in_bounds( &self, from: Option<DateTime<Utc>>, to: Option<DateTime<Utc>>, ) -> Result<CostSummary>

Source

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.

Source

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.

Source

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.

Source

pub fn get_usage_totals_for_task_with_pricing( &self, task_id: &str, ) -> Result<(u64, f64, bool)>

Source

pub fn get_daily_cost(&self, date: NaiveDate) -> Result<f64>

Get the daily cost for a specific date.

Source

pub fn get_monthly_cost(&self, year: i32, month: u32) -> Result<f64>

Get the monthly cost for a specific month.

Source§

impl CostTracker

Source

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§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts 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
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more