Documentation
¶
Overview ¶
Package analytics mounts the Hanzo Cloud /v1/analytics/* surface: a native-Go, per-org analytics read API over the `hanzo` datastore warehouse (the `datastore` cluster). It is the backend for the console Native Analytics module (unified-analytics.md §5) — two read lenses over one warehouse:
- LLM lens (REAL today): hanzo.cloud_usage, the live per-org usage ledger the cloud o11y path already writes (requests, tokens, spend, models, errors).
- Web/commerce lens (honest-empty until the collector emits): hanzo.events.
ONE datastore client. This package does NOT open a second connection: it rides the SAME datastore-go/v2 client the ai subsystem's o11y ledger opens in the shared Bootstrap (ai/object.InitDatastore → object.DatastoreQuery). DRY: one transport, one pool, one set of KMS-injected DATASTORE_* creds — never hard-coded, never a second design.
TENANT ISOLATION is the security bar and is enforced SERVER-SIDE on every request. The org is c.Org() — the value SanitizeIdentity minted from the VALIDATED bearer owner claim (HIP-0026), never a client header — AND every request must carry a validated principal (c.User() set, which SanitizeIdentity sets ONLY for a verified bearer). This closes the Phase-1 "no-bearer + forged X-Org-Id direct-to-pod" cross-tenant read exactly as clients/s3 does. Every datastore query binds the org POSITIONALLY (query.go llmWhere/eventsWhere), so a maxpower token can NEVER read another org's analytics.
Surface (all org-scoped; /v1 only; read-only):
GET /v1/analytics/overview per-org KPIs (llm real; web/commerce honest-empty) GET /v1/analytics/timeseries requests/tokens/spend over time (hour|day buckets) GET /v1/analytics/top top models (real) + top products (honest-empty) GET /v1/analytics/health subsystem health (datastore connectivity + lens tables)
Registered as id "analytics" with cloud.HealthOwner + order 132: it serves its OWN /v1/analytics/health (below), and cloud.HealthOwner makes serve.go skip the generic GET /v1/<name>/health so the always-ok route never shadows the real probe — the same flag the kms/paas/s3 subsystems use. Order 132 binds /v1/analytics/* before the ai subsystem's /v1/* catch-all (150).
Pure core of the analytics lens: SQL predicate builders, datastore value coercers, and the pure assemblers that turn raw datastore rows into the response structs. Everything here is I/O-free so the tests drive it with mock rows — no datastore needed — exactly as ai/object/cloud_usage.go proves out its Overview assembler. The handlers (analytics.go) are the thin orchestration that fetches the rows and calls these.
THE ONE TENANCY INVARIANT lives here: llmWhere / eventsWhere ALWAYS emit "… = ?" with the org bound POSITIONALLY (never interpolated), so no query this package builds can read a tenant other than the caller's, and a hostile org slug can never escape into SQL. The isolation test asserts this directly.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type CommerceOverview ¶
type CommerceOverview struct {
Available bool `json:"available"`
Reason string `json:"reason,omitempty"`
Orders int64 `json:"orders"`
Revenue float64 `json:"revenue"`
AOV float64 `json:"aov"` // revenue/orders
Source string `json:"source"`
}
CommerceOverview is the commerce lens over hanzo.events. Honest-empty until commerce emits order events.
type LLMOverview ¶
type LLMOverview struct {
Available bool `json:"available"`
Requests int64 `json:"requests"`
Tokens int64 `json:"tokens"`
PromptTokens int64 `json:"promptTokens"`
CompletionTokens int64 `json:"completionTokens"`
SpendCents int64 `json:"spendCents"`
Models int64 `json:"models"`
Providers int64 `json:"providers"`
Errors int64 `json:"errors"`
ErrorRate float64 `json:"errorRate"` // 0..1, errors/requests
Source string `json:"source"`
}
LLMOverview is the flagship lens: real per-org KPIs from hanzo.cloud_usage.
type Overview ¶
type Overview struct {
Range string `json:"range"`
Start string `json:"start"`
End string `json:"end"`
Interval string `json:"interval"`
Scope Scope `json:"scope"`
LLM LLMOverview `json:"llm"`
Web WebOverview `json:"web"`
Commerce CommerceOverview `json:"commerce"`
}
type ProductRow ¶
type SeriesPoint ¶
type Timeseries ¶
type TopProducts ¶
type TopProducts struct {
Available bool `json:"available"`
Reason string `json:"reason,omitempty"`
Items []ProductRow `json:"items"`
Source string `json:"source"`
}
type WebOverview ¶
type WebOverview struct {
Available bool `json:"available"`
Reason string `json:"reason,omitempty"`
Pageviews int64 `json:"pageviews"`
Visitors int64 `json:"visitors"`
Sessions int64 `json:"sessions"`
Source string `json:"source"`
}
WebOverview is the web lens over hanzo.events. Honest-empty (Available=false) until the collector emits web events.