An SLO turns the ad hoc availability view into a named, standing declaration: a selector, a target percent, and how the report should treat business hours and scheduled downtime. It has no window of its own: the range comes from the request each time a report is read, not from anything stored in the SLO's declaration.

1. What an SLO is here

An slo block is a named entry under slos:

slos: {
	web_tier: {
		selector:          "team=web"
		target:             99.9
		period:             "office"
		exclude_downtimes:  true
		down_statuses:      ["CRITICAL"]
	}
}
  • selector is the same label-selector grammar a view or a downtime uses; it names the objects the SLO measures by query, so an SLO can be declared before the hosts it will match exist.
  • target is the uptime percent the error budget is measured against.
  • period names a declared timeperiod; while it is set, only the period's open time counts toward the report at all, and time outside it is neither up, down nor undetermined. Leaving it out measures the whole requested range.
  • exclude_downtimes defaults to true and subtracts the part of down time that a scheduled, non-cancelled downtime window overlaps.
  • down_statuses lists which HARD statuses count as down; leaving it out uses every status the state model already treats as a problem.

An slo block requires ui.availability to be configured: an SLO with no datasource to measure against is refused at load, before it can ever answer a request. ui.availability's own datasource now has to share its host and database with a sink whose input is events; a config that declares ui.availability without such a sink is refused at load too, with a message naming the host and database it expected to find a sink writing to.

2. How the numbers are computed

Within the SLO's open time, every HARD status accrues its seconds, with one exception: time the engine recorded an object as unreachable always counts under its own bucket and wins over whatever HARD status overlaps it. Down time is the sum of the down set plus unreachable time. Determined time is every status except PENDING; undetermined time is what is left of the open time once determined time is subtracted. Uptime is a percent of determined time, with the excluded downtime seconds removed from down time first:

uptime_pct = 100 * (1 - (down_seconds - downtime_seconds) / determined_seconds)

An object with no determined time at all has no uptime percent to show. The budget is the down time the target still allows, and consumption is how much of it has actually been used:

budget_seconds   = determined_seconds * (1 - target / 100)
consumed_seconds = down_seconds - downtime_seconds

A member that matched the selector but has no HARD row at or before the range end appears in the report with no_data set and every count at zero, so a member with no history is visible instead of missing. Every report also carries the earliest timestamp its datasource holds, so a range that starts before that point shows a data boundary rather than a real 100% or a real gap.

3. Reading the report

The dashboard's availability view lists every declared SLO above the ad hoc object table: name, attained percent against target, a budget bar showing consumed against allowed, and the member count. Selecting one loads its per-object table and timeline into the same view the ad hoc report uses, with the period and the downtime policy shown as fixed text rather than the checkbox, since both are the SLO's own declaration rather than something a reader picks per request.

Two RPCs back this: ListSLOs returns every declared SLO with its current member count, the way ListViews reports on a view; QuerySLOReport takes an SLO name and a range and returns its declaration, one row per member with that member's budget alongside its availability, and the aggregate uptime and budget across the whole SLO.

4. What it does not do

Report export, scheduling and mail are not part of this: the RPC is the export, and a caller that wants a recurring report reads it on its own schedule. Alerting on budget consumption and multi-window burn rates are not implemented. An SLO has no rolling or calendar window of its own, and a caller may not override its period or its downtime policy per request; the range is the only thing a request supplies. Availability over a Prometheus datasource is not supported. Host reachability does not appear as its own row kind in the timeline; it only ever shows as time an object's status was unreachable.