Set one up
Say every tenant underacme/prod/* has a template group abuse_by_day, keyed by a day bucket you write and keeping the last 7 days, and by_plan, keyed by plan. Choose the groups each tenant publishes, a band for each aggregate you want to judge by, and the key values you want published one by one:
POST /v1/namespaces/acme%2Fprod%2F*/tenant_summary
bands names one of their aggregates as <group>.<aggregate>, as a group’s rows key them. A value takes the label of how many cut points are at or below it, so each band has one more label than cut points. keys is optional: each group it names must be one of groups, with the key values you want broken out. Templates need the Team plan or above.
The tenant document
Once an hour a run reads each tenant’s group rows and writes its document into the template’s namespace, hereacme/prod:
idis the tenant’s namespace name, andattributes.kindistenant.state.groupsholds labels only. Each group’sallbands its aggregates over all its key values together: here, the abuse count over the 7 daysabuse_by_daykeeps. A group you listed inkeysalso haskeys, the labels of each listed key value the tenant has; this tenant has nofreerow, sofreeis absent. An aggregate without a band does not appear, and neither does a key value you did not list.state.sourcesays where the labels came from, without any of the tenant’s data: the position in the tenant’s history they are exact at (as_of).
Judge your tenants
A tenant document is an ordinary document, so a judgment reads it like any other:POST /v1/namespaces/acme%2Fprod/judgments
state.source, the position in the tenant’s history they are exact at.
How current it is
GET lists each tenant by name with its status:
GET /v1/namespaces/acme%2Fprod%2F*/tenant_summary
A group’s rows are at most about an hour behind its tenant’s writes, and the run reads it once an hour and pages through your tenants. So a tenant document lags its tenant by up to a run plus the paging, not one hour: read
published_at and source_as_of rather than assuming.
Changing it
- Groups, bands and keys change with
PATCH, each replacing the setting whole. The next run rewrites every tenant document whose labels move, which re-judges each of them, so aPATCHwithout"confirm": truechanges nothing and returns what that costs: one line per judgment on the template’s namespace that reads tenant documents. Send it again with"confirm": trueand it applies from the next run, unattended. - Delete with
DELETE. Runs stop; the tenant documents stay, as ordinary documents.
Tenants that come and go
- A tenant created under the template gets its document at the first run after its groups first have rows.
- A tenant deleted and created again under the same name has its document deleted and written anew, so the history of anything judging it splits at the new incarnation, as it does for the tenant itself.
- A tenant document is deleted only once a strong read says the tenant’s namespace is deleted, never because a listing missed it.
Billing and failures
Tenant documents are written like any write to the template’s namespace: they bill your organization as writes and stored bytes, and judgments over them bill as any judgment does. An idle tenant writes nothing. If the template’s namespace refuses the writes, for example because it is over its budget withon_exceeded: reject, the tenant summary shows the warning tenant_summary_failed and the events feed carries one namespace.tenant_summary_failed for the run, with the reason. Nothing is lost: the next run that can write catches every tenant up and clears the warning.