Skip to main content

ProviderUsage

Struct ProviderUsage 

Source
pub struct ProviderUsage {
    pub provider: String,
    pub api_provider: Option<String>,
    pub account: Option<String>,
    pub source: Option<String>,
    pub account_info: Option<AccountInfo>,
    pub fetched_at: Option<String>,
    pub saved_resets: Option<SavedResets>,
    pub usage: Option<Usage>,
    pub spend: Option<Vec<Pool>>,
    pub error: Option<String>,
    pub error_class: Option<String>,
    pub stale: Option<Stale>,
}
Expand description

One provider/account’s usage entry. The /usage response is an array of these. A fetch failure becomes an entry carrying error (silent-degrade), never a failure of the whole array.

Fields§

§provider: String

CodexBar provider name (e.g. “codex”), which consumers map to their own id.

§api_provider: Option<String>

Canonical API provider identifier — the models.dev slug for the same provider (e.g. “openai” when provider == "codex", “anthropic” for “claude”, “google” for “gemini”, “xai” for “grok”). Present when the producer knows the canonical name; absent for providers with no models.dev counterpart, where consumers fall back to provider. Lets every consumer key on one canonical name instead of each maintaining its own CodexBar-name → canonical map.

§account: Option<String>

The account this entry describes, as the credential store identifies it.

Absent means the producer could not resolve an identity for this credential, not that the provider has one account. Some credentials carry no account identity at all (a bare API key), and an entry is also emitted unlabelled while an identity is still being confirmed — so an unlabelled entry is not evidence that a labelled one does not exist.

§source: Option<String>

Which retrieval path produced this (e.g. “oauth”) — observability only.

Per lane, not per account, and it moves. One account can be reached through more than one credential path, and which one answers is decided per fetch by whichever is healthy. So the same account can report one value on a poll and another on the next with nothing having changed about the account, the credential, or anything the consumer did. Do not key on it, branch on it, or treat a change in it as an event.

§account_info: Option<AccountInfo>

Display labels for the account. Absent when the upstream supplies none of them; carries no operational meaning.

§fetched_at: Option<String>

When this entry’s figures were last successfully fetched — producer time, per entry, never a common instant across the array.

Absent means this credential has never had a successful fetch. It keeps its old value while a failure is being retried, so it ages honestly rather than pausing; never restamp it with your own poll time.

§saved_resets: Option<SavedResets>

Banked quota-reset credits held by this account.

Absent means there is no credit inventory to report — which includes the inventory lookup having failed on this fetch, since it is separate from the usage fetch and may fail without degrading the entry. Absent is therefore not “zero credits held”.

§usage: Option<Usage>

The windows. Absent on a degraded entry, and on an entry whose credential works but whose account reports no quota at all — read error and error_class to tell those apart, rather than inferring from this field.

§spend: Option<Vec<Pool>>

Prepaid balances and credit pools on this account, when the provider reports any.

Deliberately apart from Self::usage, because a pool and a rate window are different facts that fail in opposite directions: over-consuming a window gets you throttled and recovers by waiting, while over-consuming a balance gets you billed and recovers by paying. Nothing in a routing loop can undo the second, so a balance is never expressed as a window, never carries a reset, and never appears as a percentage — a consumer that found one where it expects headroom would pace into a bill.

Absent means the producer has nothing to say, which is not the same as an account having no credit. Empty means it looked and the provider reports no pools.

§error: Option<String>

Present only on a degraded entry. The consumer skips any entry with a truthy error.

§error_class: Option<String>

A stable, machine-readable name for why a degraded entry failed, published beside the human-readable error.

error is prose with no stability promise, so consumers are told not to branch on it — which leaves them no way to separate failures that mean something from failures that are a permanent, correct state. A host that never configured a provider and a host whose credential broke this morning both produce a degraded entry, and only the second is worth anyone’s attention.

Classes currently produced:

ValueMeaning
credential_absentNo credential was found. Permanent and correct on a host that never configured this provider; nothing to fix.
credential_unusableA credential was found but cannot be used as it stands (empty, incomplete, or refused by the credential store). Someone configured this and it needs fixing.
credential_rejectedThe upstream rejected the credential (401/403). Usually means logging in again.
no_quota_reportedThe credential works and the account genuinely has no quota to report. Not a failure.
upstream_failedThe upstream could not be reached or returned an error status. Usually transient.
decode_failedThe response arrived but was not the expected shape.

This list will grow. A consumer must render an unrecognised class as a degraded entry with an unknown reason — never drop the entry, and never fold it into an existing bucket. It is a String rather than an enum for exactly that reason: on an observability surface, meeting an unknown value must not turn into a parse failure that makes a provider disappear at the moment its state changed.

Absent on healthy entries, and absent from any producer that predates this field.

§stale: Option<Stale>

Present when this entry is a last-known-good reading served through an ongoing failure, absent when it is a fresh success.

Without it a preserved reading is byte-identical to a fresh one apart from fetched_at, so a consumer cannot separate “this figure is old because the producer has been unable to reach the provider” from “this figure is old because nothing polled recently”. Those have opposite remedies — the first is a reason to stop acting on the number, the second is not — and a consumer with only a timestamp has to guess with a wall-clock threshold, which denies fresh-enough data to catch stale data.

A producer serving preserved readings is behaving correctly: a brief upstream failure should not blank a window. This field discloses that it is happening rather than reporting a fault.

Implementations§

Source§

impl ProviderUsage

Source

pub fn healthy( provider: &str, account: Option<String>, source: &str, usage: Usage, ) -> Self

A healthy entry with resolved windows.

Source

pub fn degraded(provider: &str, error: impl Display) -> Self

A degraded entry: the provider is named so the consumer can correlate, but it carries only an error string and no windows.

Source

pub fn degraded_with_class( provider: &str, error: impl Display, error_class: impl Into<String>, ) -> Self

A degraded entry that also names why it failed.

Prefer this over Self::degraded wherever the producer knows the class: without it a consumer can only tell an unconfigured provider from a broken one by reading prose it has been told not to parse. See ProviderUsage::error_class for the classes and for the rule that an unrecognised one must still render.

Trait Implementations§

Source§

impl Clone for ProviderUsage

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ProviderUsage

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for ProviderUsage

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl PartialEq for ProviderUsage

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for ProviderUsage

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for ProviderUsage

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

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

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

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

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.