Documentation
¶
Overview ¶
Pure core of the usage summary: the response shape, the ledger→category mapper, the spend roll-up + gap-filled series assembler, and the ClickHouse value coercers. Everything here is I/O-free so the tests drive it with plain structs and mock rows — no commerce, no ClickHouse. The handler (usage.go) is the thin orchestration that fetches and calls these.
Package usage mounts the Hanzo Cloud UNIFIED USAGE surface (GET /v1/usage/summary): one org-scoped roll-up answering "what am I running and what does it cost" — the flagship footprint view. It is a native-Go composition over the two canonical shared cost sources, and exists because NO single endpoint aggregates this today:
- Spend (the genuinely-missing categorized cost roll-up): the commerce ledger — usage-rollup (authoritative month-to-date consumed + prepaid wallet) plus the raw transaction ledger, rolled up server-side into spend-by-category over time. Every metered resource (GPU, machine-hours, LLM tokens, datastore footprint) debits this ONE ledger with a category tag, so it is already the unified cost source — this endpoint is the categorizing lens over it.
- LLM usage totals: hanzo.cloud_usage, the per-org warehouse ledger (the same table /v1/analytics/* and the o11y board read). Totals only here — the per-model / timeseries detail stays at /v1/analytics/*.
The console Usage view composes THIS (cost roll-up + LLM totals) with the existing org-scoped inventory endpoints (/v1/machines, /v1/gpus, /v1/agents, provisioning lists) for the per-kind counts — one screen, this one authoritative money source.
TENANT ISOLATION (the bar). The org is the VALIDATED IAM owner claim (principal.Tenant — the trusted X-Org-Id the identity middleware minted from the caller's verified bearer, HIP-0026; NEVER a client header) AND a validated principal is required (c.User() set only for a verified bearer). The commerce subject is pinned server-side to that org; the warehouse query binds it POSITIONALLY. A caller can only ever read its OWN org. Fail-closed: no principal → 401. Every source degrades independently to honest zeros (source markers say which answered) — a partial deploy never fabricates spend or usage.
Registered as "usagesvc" (NOT "usage") + order 131: the name diverges from the /v1/usage route so serve.go's generic GET /v1/<name>/health parks at /v1/usagesvc/health and never shadows the summary. Order 131 binds /v1/usage/* before the ai subsystem's /v1/* catch-all (150).
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type CategorySpend ¶
type CategorySpend struct {
Category string `json:"category"`
Cents int64 `json:"cents"`
Count int64 `json:"count"`
}
CategorySpend is one row of the spend-by-category breakdown: a friendly category bucket, the total cents spent in the window, and how many ledger lines rolled up into it. Categories are DERIVED from the commerce ledger's own tags — never fabricated — so an unknown tag surfaces as its own honest bucket.
type LLM ¶
type LLM struct {
Available bool `json:"available"`
Requests int64 `json:"requests"`
Tokens int64 `json:"tokens"`
PromptTokens int64 `json:"promptTokens"`
CompletionTokens int64 `json:"completionTokens"`
CostCents int64 `json:"costCents"`
Models int64 `json:"models"`
Source string `json:"source"`
}
LLM is the org's LLM usage totals from the warehouse ledger. Available=false when the datastore is not connected (honest zeros). The detailed per-model / timeseries breakdown lives at /v1/analytics/*; this is the KPI-band total.
type Sources ¶
Sources reports which upstreams actually answered, so the console can badge a board as "connected" vs "no data yet" honestly instead of showing a fabricated zero as if it were real.
type Spend ¶
type Spend struct {
Available bool `json:"available"`
TotalCents int64 `json:"totalCents"`
MTDCents int64 `json:"mtdCents"`
OverageCents int64 `json:"overageCents"`
BalanceCents int64 `json:"balanceCents"`
AvailableCents int64 `json:"availableCents"`
ByCategory []CategorySpend `json:"byCategory"`
Series []SpendPoint `json:"series"`
Source string `json:"source"`
}
Spend is the cost roll-up: the genuinely-missing aggregation. TotalCents is the windowed consumption (self-consistent with ByCategory + Series); MTDCents is commerce's authoritative month-to-date figure; Balance/Available are the prepaid wallet the gateway debits. Available=false means commerce was unconfigured or unreachable — honest zeros, never fabricated spend.
type SpendPoint ¶
type SpendPoint struct {
T string `json:"t"` // RFC3339 bucket start (UTC)
Cents int64 `json:"cents"`
}
SpendPoint is one time bucket of consumption (usage/withdrawal cents).
type Summary ¶
type Summary struct {
Range string `json:"range"`
Start string `json:"start"`
End string `json:"end"`
Interval string `json:"interval"`
Scope Scope `json:"scope"`
Spend Spend `json:"spend"`
LLM LLM `json:"llm"`
Sources Sources `json:"sources"`
}
Summary is the whole org-scoped usage footprint roll-up: the cost roll-up (spend) + the LLM usage totals, over one window, for one org.