Files
o11y/rulesalerts.go
zeekayandHanzo Dev cae99adb44 The relay reads the operation zip served
An op learns its address from zip.OpOf and zip.AddressOf, so the claim table,
the five declaring verbs and the address bookkeeping are gone. A host that
declares one of these addresses itself now gets a Build conflict from zip.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-17 15:02:30 -07:00

735 lines
32 KiB
Go

package o11y
// The RULES & ALERTING face — alert rules, their test-fire, planned
// maintenance (downtime) schedules, rule state history, notification channels,
// route policies and the alerts read — as TYPED ops.
//
// These thirty-six routes reached traffic only through the delegation
// wildcard, and a route behind a wildcard is in no document: no SDK method, no
// CLI command, no agent tool, no reference page. A customer could not create,
// test, list or silence an alert rule, wire a notification channel, or read a
// rule's firing history from anything but a hand-written HTTP call. Typing the
// face is what puts the operations in the document and therefore in every
// projection built from it.
//
// THE WIRE DOES NOT MOVE, the same way telemetry.go, infra.go, logs.go and
// identity.go do not move it: no op here re-implements a read or a write. Each
// hands the call to the SAME runtime handler the wildcard delegates to (see
// rulesAlertsRelay), so identity resolution, the org gate, the ROLE CHECK the
// mux registration declared — ViewAccess, EditAccess or AdminAccess — the
// audit record, the timeout and the success envelope are all still the
// runtime's, executed in the order they always were. The gate is NOT re-stated
// here because it is not enforced here; each op's comment names the gate its
// route has always had, and the runtime keeps enforcing it one layer in.
//
// The request and response payloads are the RUNTIME'S OWN types
// (pkg/types/ruletypes, pkg/types/alertmanagertypes,
// pkg/types/rulestatehistorytypes, pkg/types/telemetrytypes and, for the four
// legacy v1 history writes, pkg/query-service/model), not mirrors of them: the
// field list that decodes a request here is the field list the handler decodes
// one layer in, so the two cannot drift. Only the {status, data} envelopes and
// the GET query-parameter shapes are NAMED here, because the runtime spells
// those on the wire rather than in a type.
//
// TWO history faces sit at the same four paths on purpose. The v2 reads answer
// GET with URL query parameters (rulestatehistory.go, o11yapiserver); the v1
// reads answer POST with a JSON body (routes_rules.go, query-service). They are
// distinct method+path operations and each keeps its own contract — the flatten
// left both live, so both are typed rather than one silently chosen.
//
// Registered ahead of the wildcard, and specific-beats-wildcard is what the
// router does regardless of registration order, so these paths dispatch here
// and every other path under the prefix still reaches the runtime untouched.
import (
"context"
"net/http"
"net/url"
"strconv"
"github.com/hanzoai/o11y/pkg/query-service/model"
"github.com/hanzoai/o11y/pkg/types/alertmanagertypes"
"github.com/hanzoai/o11y/pkg/types/rulestatehistorytypes"
"github.com/hanzoai/o11y/pkg/types/ruletypes"
"github.com/hanzoai/o11y/pkg/types/telemetrytypes"
"github.com/zap-proto/zip"
)
// mountRulesAlerts registers the rules & alerting face's typed ops on the
// native router. Collection routes sit beside their parameterised siblings
// safely: the router matches the most specific pattern, so /rules/test is never
// swallowed by /rules/:id, the same disambiguation the runtime's own tree makes.
func mountRulesAlerts(app *zip.App) {
g := app.Group(o11yRoot)
// alert rules (runtime gate per op: see each op's comment)
g.Get("/rules", listRules, zip.WithOperationID("ListRules"))
g.Get("/rules/:id", getRuleByID, zip.WithOperationID("GetRuleByID"))
g.Post("/rules", createRule, zip.WithStatus(http.StatusCreated), zip.WithOperationID("CreateRule"))
g.Put("/rules/:id", updateRuleByID, zip.WithStatus(http.StatusNoContent), zip.WithOperationID("UpdateRuleByID"))
g.Delete("/rules/:id", deleteRuleByID, zip.WithStatus(http.StatusNoContent), zip.WithOperationID("DeleteRuleByID"))
g.Patch("/rules/:id", patchRuleByID, zip.WithOperationID("PatchRuleByID"))
g.Post("/rules/test", testRule, zip.WithOperationID("TestRule"))
// planned maintenance / downtime schedules
g.Get("/downtime_schedules", listDowntimeSchedules, zip.WithOperationID("ListDowntimeSchedules"))
g.Get("/downtime_schedules/:id", getDowntimeScheduleByID, zip.WithOperationID("GetDowntimeScheduleByID"))
g.Post("/downtime_schedules", createDowntimeSchedule, zip.WithStatus(http.StatusCreated), zip.WithOperationID("CreateDowntimeSchedule"))
g.Put("/downtime_schedules/:id", updateDowntimeScheduleByID, zip.WithStatus(http.StatusNoContent), zip.WithOperationID("UpdateDowntimeScheduleByID"))
g.Delete("/downtime_schedules/:id", deleteDowntimeScheduleByID, zip.WithStatus(http.StatusNoContent), zip.WithOperationID("DeleteDowntimeScheduleByID"))
// rule state history — v2 reads (GET, URL query parameters)
g.Get("/rules/:id/history/stats", getRuleHistoryStats, zip.WithOperationID("GetRuleHistoryStats"))
g.Get("/rules/:id/history/timeline", getRuleHistoryTimeline, zip.WithOperationID("GetRuleHistoryTimeline"))
g.Get("/rules/:id/history/top_contributors", getRuleHistoryTopContributors, zip.WithOperationID("GetRuleHistoryTopContributors"))
g.Get("/rules/:id/history/filter_keys", getRuleHistoryFilterKeys, zip.WithOperationID("GetRuleHistoryFilterKeys"))
g.Get("/rules/:id/history/filter_values", getRuleHistoryFilterValues, zip.WithOperationID("GetRuleHistoryFilterValues"))
g.Get("/rules/:id/history/overall_status", getRuleHistoryOverallStatus, zip.WithOperationID("GetRuleHistoryOverallStatus"))
// rule state history — v1 reads (POST, JSON body) and the legacy test-fire
g.Post("/testRule", testRuleNotification, zip.WithOperationID("TestRuleNotification"))
g.Post("/rules/:id/history/stats", getRuleStats, zip.WithOperationID("GetRuleStats"))
g.Post("/rules/:id/history/timeline", getRuleStateHistory, zip.WithOperationID("GetRuleStateHistory"))
g.Post("/rules/:id/history/top_contributors", getRuleStateHistoryTopContributors, zip.WithOperationID("GetRuleStateHistoryTopContributors"))
g.Post("/rules/:id/history/overall_status", getOverallStateTransitions, zip.WithOperationID("GetOverallStateTransitions"))
// notification channels
g.Get("/channels", listChannels, zip.WithOperationID("ListChannels"))
g.Get("/channels/:id", getChannelByID, zip.WithOperationID("GetChannelByID"))
g.Post("/channels", createChannel, zip.WithStatus(http.StatusCreated), zip.WithOperationID("CreateChannel"))
g.Put("/channels/:id", updateChannelByID, zip.WithStatus(http.StatusNoContent), zip.WithOperationID("UpdateChannelByID"))
g.Delete("/channels/:id", deleteChannelByID, zip.WithStatus(http.StatusNoContent), zip.WithOperationID("DeleteChannelByID"))
g.Post("/channels/test", testChannel, zip.WithStatus(http.StatusNoContent), zip.WithOperationID("TestChannel"))
g.Post("/testChannel", testChannelDeprecated, zip.WithStatus(http.StatusNoContent), zip.WithOperationID("TestChannelDeprecated"))
// route policies
g.Get("/route_policies", getAllRoutePolicies, zip.WithOperationID("GetAllRoutePolicies"))
g.Get("/route_policies/:id", getRoutePolicyByID, zip.WithOperationID("GetRoutePolicyByID"))
g.Post("/route_policies", createRoutePolicy, zip.WithStatus(http.StatusCreated), zip.WithOperationID("CreateRoutePolicy"))
g.Put("/route_policies/:id", updateRoutePolicy, zip.WithOperationID("UpdateRoutePolicy"))
g.Delete("/route_policies/:id", deleteRoutePolicyByID, zip.WithStatus(http.StatusNoContent), zip.WithOperationID("DeleteRoutePolicyByID"))
// alerts
g.Get("/alerts", getAlerts, zip.WithOperationID("GetAlerts"))
}
// ── alert rules ─────────────────────────────────────────────────────────────
// listRules lists all alert rules with their current evaluation state. Viewer gate.
func listRules(ctx context.Context, _ *struct{}) (*O11yRulesOut, error) {
out := new(O11yRulesOut)
return out, relay(ctx, nil, nil, out)
}
// getRuleByID returns one alert rule with its evaluation state, by id. Viewer gate.
func getRuleByID(ctx context.Context, in *O11yRuleRef) (*O11yRuleOut, error) {
out := new(O11yRuleOut)
return out, relay(ctx, nil, nil, out)
}
// createRule creates a new alert rule and answers with the stored rule. Editor gate.
func createRule(ctx context.Context, in *ruletypes.PostableRule) (*O11yRuleOut, error) {
out := new(O11yRuleOut)
return out, relay(ctx, nil, in, out)
}
// updateRuleByID replaces an alert rule's definition, by id. Editor gate.
func updateRuleByID(ctx context.Context, in *O11yRuleUpdateIn) (*struct{}, error) {
return nil, relay(ctx, nil, &in.PostableRule, nil)
}
// deleteRuleByID removes an alert rule, by id. Editor gate.
func deleteRuleByID(ctx context.Context, in *O11yRuleRef) (*struct{}, error) {
return nil, relay(ctx, nil, nil, nil)
}
// patchRuleByID applies a partial update to an alert rule, by id, answering
// with the stored rule — the common toggle for enabling or muting a rule.
// Editor gate.
func patchRuleByID(ctx context.Context, in *O11yRuleUpdateIn) (*O11yRuleOut, error) {
out := new(O11yRuleOut)
return out, relay(ctx, nil, &in.PostableRule, out)
}
// testRule fires a test notification for a rule definition without saving it,
// answering with how many series would alert. Editor gate.
func testRule(ctx context.Context, in *ruletypes.PostableRule) (*O11yTestRuleOut, error) {
out := new(O11yTestRuleOut)
return out, relay(ctx, nil, in, out)
}
// ── planned maintenance / downtime schedules ────────────────────────────────
// listDowntimeSchedules lists all planned maintenance windows, optionally
// narrowed to the active ones or the recurring ones. Viewer gate.
func listDowntimeSchedules(ctx context.Context, in *O11yListDowntimeSchedulesIn) (*O11yDowntimeSchedulesOut, error) {
out := new(O11yDowntimeSchedulesOut)
return out, relay(ctx, query(
"active", in.Active,
"recurring", in.Recurring,
), nil, out)
}
// getDowntimeScheduleByID returns one planned maintenance window, by id. Viewer gate.
func getDowntimeScheduleByID(ctx context.Context, in *O11yDowntimeRef) (*O11yDowntimeScheduleOut, error) {
out := new(O11yDowntimeScheduleOut)
return out, relay(ctx, nil, nil, out)
}
// createDowntimeSchedule creates a planned maintenance window, answering with
// the stored schedule. Editor gate.
func createDowntimeSchedule(ctx context.Context, in *alertmanagertypes.PostablePlannedMaintenance) (*O11yDowntimeScheduleOut, error) {
out := new(O11yDowntimeScheduleOut)
return out, relay(ctx, nil, in, out)
}
// updateDowntimeScheduleByID replaces a planned maintenance window, by id. Editor gate.
func updateDowntimeScheduleByID(ctx context.Context, in *O11yDowntimeUpdateIn) (*struct{}, error) {
return nil, relay(ctx, nil, &in.PostablePlannedMaintenance, nil)
}
// deleteDowntimeScheduleByID removes a planned maintenance window, by id. Editor gate.
func deleteDowntimeScheduleByID(ctx context.Context, in *O11yDowntimeRef) (*struct{}, error) {
return nil, relay(ctx, nil, nil, nil)
}
// ── rule state history — v2 (GET, query parameters) ─────────────────────────
// getRuleHistoryStats returns trigger and resolution statistics for a rule over
// the selected time range, current window against the prior one. Viewer gate.
func getRuleHistoryStats(ctx context.Context, in *O11yRuleHistoryBaseIn) (*O11yRuleHistoryStatsOut, error) {
out := new(O11yRuleHistoryStatsOut)
return out, relay(ctx, ruleHistoryBaseParams(in), nil, out)
}
// getRuleHistoryTimeline returns paginated timeline entries for a rule's state
// transitions, filterable by state and a label expression, cursor-paginated. Viewer gate.
func getRuleHistoryTimeline(ctx context.Context, in *O11yRuleHistoryTimelineIn) (*O11yRuleHistoryTimelineOut, error) {
out := new(O11yRuleHistoryTimelineOut)
params := ruleHistoryBaseParams(&O11yRuleHistoryBaseIn{Start: in.Start, End: in.End})
if in.State != "" {
params.Set("state", in.State)
}
if in.FilterExpression != "" {
params.Set("filterExpression", in.FilterExpression)
}
if in.Limit != 0 {
params.Set("limit", strconv.FormatInt(in.Limit, 10))
}
if in.Order != "" {
params.Set("order", in.Order)
}
if in.Cursor != "" {
params.Set("cursor", in.Cursor)
}
return out, relay(ctx, params, nil, out)
}
// getRuleHistoryTopContributors returns the label combinations that contributed
// most to a rule firing over the selected range. Viewer gate.
func getRuleHistoryTopContributors(ctx context.Context, in *O11yRuleHistoryBaseIn) (*O11yRuleHistoryContributorsOut, error) {
out := new(O11yRuleHistoryContributorsOut)
return out, relay(ctx, ruleHistoryBaseParams(in), nil, out)
}
// getRuleHistoryFilterKeys returns the distinct label keys present in a rule's
// history entries over the selected range, for building history filters. Viewer gate.
func getRuleHistoryFilterKeys(ctx context.Context, in *O11yRuleHistoryFilterKeysIn) (*O11yRuleHistoryFilterKeysOut, error) {
out := new(O11yRuleHistoryFilterKeysOut)
return out, relay(ctx, filterKeysParams(in), nil, out)
}
// getRuleHistoryFilterValues returns the distinct values a given label key has
// taken across a rule's history entries. Viewer gate.
func getRuleHistoryFilterValues(ctx context.Context, in *O11yRuleHistoryFilterValuesIn) (*O11yRuleHistoryFilterValuesOut, error) {
out := new(O11yRuleHistoryFilterValuesOut)
params := filterKeysParams(&in.O11yRuleHistoryFilterKeysIn)
params.Set("name", in.Name)
if in.ExistingQuery != "" {
params.Set("existingQuery", in.ExistingQuery)
}
return out, relay(ctx, params, nil, out)
}
// getRuleHistoryOverallStatus returns the overall firing/inactive intervals for
// a rule over the selected range. Viewer gate.
func getRuleHistoryOverallStatus(ctx context.Context, in *O11yRuleHistoryBaseIn) (*O11yRuleHistoryOverallStatusOut, error) {
out := new(O11yRuleHistoryOverallStatusOut)
return out, relay(ctx, ruleHistoryBaseParams(in), nil, out)
}
// ── rule state history — v1 (POST, JSON body) + legacy test-fire ────────────
// testRuleNotification fires a test notification for the posted rule definition
// and answers with how many series alerted and a status message. The legacy
// path; prefer /rules/test. Editor gate.
func testRuleNotification(ctx context.Context, in *ruletypes.PostableRule) (*O11yTestNotificationOut, error) {
out := new(O11yTestNotificationOut)
return out, relay(ctx, nil, in, out)
}
// getRuleStats returns trigger and resolution statistics for a rule, current
// window against the prior one, for the posted query range. Viewer gate.
func getRuleStats(ctx context.Context, in *O11yRuleHistoryQueryIn) (*O11yRuleStatsOut, error) {
out := new(O11yRuleStatsOut)
return out, relay(ctx, nil, &in.QueryRuleStateHistory, out)
}
// getRuleStateHistory returns a rule's state-transition timeline for the posted
// query range, each entry carrying its related-logs or related-traces link. Viewer gate.
func getRuleStateHistory(ctx context.Context, in *O11yRuleHistoryQueryIn) (*O11yRuleStateTimelineOut, error) {
out := new(O11yRuleStateTimelineOut)
return out, relay(ctx, nil, &in.QueryRuleStateHistory, out)
}
// getRuleStateHistoryTopContributors returns the label combinations that
// contributed most to a rule firing, for the posted query range. Viewer gate.
func getRuleStateHistoryTopContributors(ctx context.Context, in *O11yRuleHistoryQueryIn) (*O11yRuleStateContributorsOut, error) {
out := new(O11yRuleStateContributorsOut)
return out, relay(ctx, nil, &in.QueryRuleStateHistory, out)
}
// getOverallStateTransitions returns the overall firing/inactive windows for a
// rule, for the posted query range. Viewer gate.
func getOverallStateTransitions(ctx context.Context, in *O11yRuleHistoryQueryIn) (*O11yOverallStateTransitionsOut, error) {
out := new(O11yOverallStateTransitionsOut)
return out, relay(ctx, nil, &in.QueryRuleStateHistory, out)
}
// ── notification channels ───────────────────────────────────────────────────
// listChannels lists the org's notification channels. Viewer gate.
func listChannels(ctx context.Context, _ *struct{}) (*O11yChannelsOut, error) {
out := new(O11yChannelsOut)
return out, relay(ctx, nil, nil, out)
}
// getChannelByID returns one notification channel, by id. Viewer gate.
func getChannelByID(ctx context.Context, in *O11yChannelRef) (*O11yChannelOut, error) {
out := new(O11yChannelOut)
return out, relay(ctx, nil, nil, out)
}
// createChannel creates a notification channel, answering with the stored
// channel. Admin gate.
func createChannel(ctx context.Context, in *alertmanagertypes.PostableChannel) (*O11yChannelOut, error) {
out := new(O11yChannelOut)
return out, relay(ctx, nil, in, out)
}
// updateChannelByID replaces a notification channel's receiver, by id. Admin gate.
func updateChannelByID(ctx context.Context, in *O11yChannelUpdateIn) (*struct{}, error) {
return nil, relay(ctx, nil, &in.Receiver, nil)
}
// deleteChannelByID removes a notification channel, by id. Admin gate.
func deleteChannelByID(ctx context.Context, in *O11yChannelRef) (*struct{}, error) {
return nil, relay(ctx, nil, nil, nil)
}
// testChannel sends a test notification to the posted receiver. Editor gate.
func testChannel(ctx context.Context, in *alertmanagertypes.Receiver) (*struct{}, error) {
return nil, relay(ctx, nil, in, nil)
}
// testChannelDeprecated sends a test notification to the posted receiver. The
// legacy path; prefer /channels/test. Editor gate.
func testChannelDeprecated(ctx context.Context, in *alertmanagertypes.Receiver) (*struct{}, error) {
return nil, relay(ctx, nil, in, nil)
}
// ── route policies ──────────────────────────────────────────────────────────
// getAllRoutePolicies lists the org's route policies. Viewer gate.
func getAllRoutePolicies(ctx context.Context, _ *struct{}) (*O11yRoutePoliciesOut, error) {
out := new(O11yRoutePoliciesOut)
return out, relay(ctx, nil, nil, out)
}
// getRoutePolicyByID returns one route policy, by id. Viewer gate.
func getRoutePolicyByID(ctx context.Context, in *O11yRoutePolicyRef) (*O11yRoutePolicyOut, error) {
out := new(O11yRoutePolicyOut)
return out, relay(ctx, nil, nil, out)
}
// createRoutePolicy creates a route policy, answering with the stored policy. Admin gate.
func createRoutePolicy(ctx context.Context, in *alertmanagertypes.PostableRoutePolicy) (*O11yRoutePolicyOut, error) {
out := new(O11yRoutePolicyOut)
return out, relay(ctx, nil, in, out)
}
// updateRoutePolicy replaces a route policy, by id, answering with the stored
// policy. Admin gate.
func updateRoutePolicy(ctx context.Context, in *O11yRoutePolicyUpdateIn) (*O11yRoutePolicyOut, error) {
out := new(O11yRoutePolicyOut)
return out, relay(ctx, nil, &in.PostableRoutePolicy, out)
}
// deleteRoutePolicyByID removes a route policy, by id. Admin gate.
func deleteRoutePolicyByID(ctx context.Context, in *O11yRoutePolicyRef) (*struct{}, error) {
return nil, relay(ctx, nil, nil, nil)
}
// ── alerts ──────────────────────────────────────────────────────────────────
// getAlerts returns the org's current alerts. Viewer gate.
func getAlerts(ctx context.Context, _ *struct{}) (*O11yAlertsOut, error) {
out := new(O11yAlertsOut)
return out, relay(ctx, nil, nil, out)
}
// ── query-parameter builders ────────────────────────────────────────────────
// ruleHistoryBaseParams renders the {start, end} window every v2 history read
// shares. The runtime spells these as millisecond query parameters; a zero is
// "unsent", which the runtime then refuses, exactly as it always has.
func ruleHistoryBaseParams(in *O11yRuleHistoryBaseIn) url.Values {
p := url.Values{}
if in.Start != 0 {
p.Set("start", strconv.FormatInt(in.Start, 10))
}
if in.End != 0 {
p.Set("end", strconv.FormatInt(in.End, 10))
}
return p
}
// filterKeysParams renders the window, search text and limit the history filter
// reads share. startUnixMilli/endUnixMilli are the runtime's own parameter
// names for this pair of reads.
func filterKeysParams(in *O11yRuleHistoryFilterKeysIn) url.Values {
p := url.Values{}
if in.StartUnixMilli != 0 {
p.Set("startUnixMilli", strconv.FormatInt(in.StartUnixMilli, 10))
}
if in.EndUnixMilli != 0 {
p.Set("endUnixMilli", strconv.FormatInt(in.EndUnixMilli, 10))
}
if in.SearchText != "" {
p.Set("searchText", in.SearchText)
}
if in.Limit != 0 {
p.Set("limit", strconv.Itoa(in.Limit))
}
return p
}
// ── inputs ──────────────────────────────────────────────────────────────────
//
// The path-borne id names itself for the URL with `url:` and stays out of the
// body with `json:"-"`. The GET query inputs are named here because the runtime
// spells them as query parameters rather than as a type; no field carries
// validate: the runtime is the one place these are judged, so a bad or missing
// value answers with the status it has always answered with. The write bodies
// are the runtime's own request types, embedded so their fields decode and
// re-encode as the runtime spells them, never mirrored.
// O11yRuleRef addresses one alert rule by id.
type O11yRuleRef struct {
// ID is the alert rule id.
ID string `json:"-" url:"id" validate:"required"`
}
// O11yRuleUpdateIn is a rule id plus the rule definition to store at it.
type O11yRuleUpdateIn struct {
// ID is the alert rule id.
ID string `json:"-" url:"id" validate:"required"`
ruletypes.PostableRule
}
// O11yDowntimeRef addresses one planned maintenance window by id.
type O11yDowntimeRef struct {
// ID is the downtime schedule id.
ID string `json:"-" url:"id" validate:"required"`
}
// O11yDowntimeUpdateIn is a schedule id plus the window to store at it.
type O11yDowntimeUpdateIn struct {
// ID is the downtime schedule id.
ID string `json:"-" url:"id" validate:"required"`
alertmanagertypes.PostablePlannedMaintenance
}
// O11yListDowntimeSchedulesIn narrows the downtime list.
type O11yListDowntimeSchedulesIn struct {
// Active, when "true" or "false", keeps only the active or inactive windows.
// Absent lists all.
Active string `json:"active"`
// Recurring, when "true" or "false", keeps only the recurring or one-off
// windows. Absent lists all.
Recurring string `json:"recurring"`
}
// O11yRuleHistoryBaseIn is the id and time window shared by the stats,
// top-contributors and overall-status v2 reads.
type O11yRuleHistoryBaseIn struct {
// ID is the alert rule id.
ID string `json:"-" url:"id" validate:"required"`
// Start is the window start, unix milliseconds. Required by the runtime.
Start int64 `json:"start"`
// End is the window end, unix milliseconds. Required by the runtime.
End int64 `json:"end"`
}
// O11yRuleHistoryTimelineIn is the timeline read's id, window and paging.
type O11yRuleHistoryTimelineIn struct {
// ID is the alert rule id.
ID string `json:"-" url:"id" validate:"required"`
// Start is the window start, unix milliseconds. Required by the runtime.
Start int64 `json:"start"`
// End is the window end, unix milliseconds. Required by the runtime.
End int64 `json:"end"`
// State keeps only entries in one alert state, e.g. firing or normal.
State string `json:"state"`
// FilterExpression narrows entries to those whose labels match it.
FilterExpression string `json:"filterExpression"`
// Limit caps how many entries come back. Absent means 50.
Limit int64 `json:"limit"`
// Order sorts by time, asc or desc.
Order string `json:"order"`
// Cursor resumes a previous page; opaque, returned as nextCursor.
Cursor string `json:"cursor"`
}
// O11yRuleHistoryFilterKeysIn is the id, window, search and limit the history
// filter-keys read takes.
type O11yRuleHistoryFilterKeysIn struct {
// ID is the alert rule id.
ID string `json:"-" url:"id" validate:"required"`
// StartUnixMilli is the window start, unix milliseconds.
StartUnixMilli int64 `json:"startUnixMilli"`
// EndUnixMilli is the window end, unix milliseconds.
EndUnixMilli int64 `json:"endUnixMilli"`
// SearchText narrows the keys to those containing it.
SearchText string `json:"searchText"`
// Limit caps how many keys come back. Absent means 50, capped at 200.
Limit int `json:"limit"`
}
// O11yRuleHistoryFilterValuesIn adds the key to read values for, and an
// optional existing filter to scope them.
type O11yRuleHistoryFilterValuesIn struct {
O11yRuleHistoryFilterKeysIn
// Name is the label key whose values to list. Required.
Name string `json:"name" validate:"required"`
// ExistingQuery is a filter expression scoping which values appear.
ExistingQuery string `json:"existingQuery"`
}
// O11yRuleHistoryQueryIn is the rule id plus the posted query range the four v1
// history reads share.
type O11yRuleHistoryQueryIn struct {
// ID is the alert rule id.
ID string `json:"-" url:"id" validate:"required"`
model.QueryRuleStateHistory
}
// O11yChannelRef addresses one notification channel by id.
type O11yChannelRef struct {
// ID is the notification channel id.
ID string `json:"-" url:"id" validate:"required"`
}
// O11yChannelUpdateIn is a channel id plus the receiver to store at it.
type O11yChannelUpdateIn struct {
// ID is the notification channel id.
ID string `json:"-" url:"id" validate:"required"`
alertmanagertypes.Receiver
}
// O11yRoutePolicyRef addresses one route policy by id.
type O11yRoutePolicyRef struct {
// ID is the route policy id.
ID string `json:"-" url:"id" validate:"required"`
}
// O11yRoutePolicyUpdateIn is a policy id plus the policy to store at it.
type O11yRoutePolicyUpdateIn struct {
// ID is the route policy id.
ID string `json:"-" url:"id" validate:"required"`
alertmanagertypes.PostableRoutePolicy
}
// ── outputs ─────────────────────────────────────────────────────────────────
//
// Each Out names the runtime's answer: the {status, data} envelope every read
// and write on this face has always answered with, around the runtime's own
// response type. Status is declared first because the runtime writes it first,
// and a typed op that changes the bytes is a break, not a migration.
// O11yRulesOut is a list of alert rules.
type O11yRulesOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds the rules.
Data []*ruletypes.Rule `json:"data,omitempty"`
}
// O11yRuleOut is one alert rule.
type O11yRuleOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds the rule.
Data ruletypes.Rule `json:"data,omitempty"`
}
// O11yTestRuleOut is the result of a saved-rule test fire.
type O11yTestRuleOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds how many series would alert.
Data ruletypes.GettableTestRule `json:"data,omitempty"`
}
// O11yDowntimeSchedulesOut is a list of planned maintenance windows.
type O11yDowntimeSchedulesOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds the schedules.
Data []*alertmanagertypes.PlannedMaintenance `json:"data,omitempty"`
}
// O11yDowntimeScheduleOut is one planned maintenance window.
type O11yDowntimeScheduleOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds the schedule.
Data alertmanagertypes.PlannedMaintenance `json:"data,omitempty"`
}
// O11yRuleHistoryStatsOut is a rule's trigger/resolution statistics.
type O11yRuleHistoryStatsOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds the statistics.
Data rulestatehistorytypes.GettableRuleStateHistoryStats `json:"data,omitempty"`
}
// O11yRuleHistoryTimelineOut is a page of a rule's state transitions.
type O11yRuleHistoryTimelineOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds the timeline and its paging cursor.
Data rulestatehistorytypes.GettableRuleStateTimeline `json:"data,omitempty"`
}
// O11yRuleHistoryContributorsOut is a rule's top firing contributors.
type O11yRuleHistoryContributorsOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds the contributors.
Data []rulestatehistorytypes.GettableRuleStateHistoryContributor `json:"data,omitempty"`
}
// O11yRuleHistoryFilterKeysOut is the label keys present in a rule's history.
type O11yRuleHistoryFilterKeysOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds the keys.
Data telemetrytypes.GettableFieldKeys `json:"data,omitempty"`
}
// O11yRuleHistoryFilterValuesOut is the values one history label key has taken.
type O11yRuleHistoryFilterValuesOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds the values.
Data telemetrytypes.GettableFieldValues `json:"data,omitempty"`
}
// O11yRuleHistoryOverallStatusOut is a rule's firing/inactive windows.
type O11yRuleHistoryOverallStatusOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds the windows.
Data []rulestatehistorytypes.GettableRuleStateWindow `json:"data,omitempty"`
}
// O11yTestNotificationOut is the result of a legacy rule test fire.
type O11yTestNotificationOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds the fired-series count and a status message.
Data O11yTestNotificationResult `json:"data,omitempty"`
}
// O11yTestNotificationResult is how many series alerted, and a message.
type O11yTestNotificationResult struct {
// AlertCount is how many series would alert for the tested rule.
AlertCount int `json:"alertCount"`
// Message is a human-readable status, e.g. "notification sent".
Message string `json:"message"`
}
// O11yRuleStatsOut is a rule's v1 trigger/resolution statistics.
type O11yRuleStatsOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds the statistics.
Data model.Stats `json:"data,omitempty"`
}
// O11yRuleStateTimelineOut is a rule's v1 state-transition timeline.
type O11yRuleStateTimelineOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds the timeline.
Data model.RuleStateTimeline `json:"data,omitempty"`
}
// O11yRuleStateContributorsOut is a rule's v1 top firing contributors.
type O11yRuleStateContributorsOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds the contributors.
Data []model.RuleStateHistoryContributor `json:"data,omitempty"`
}
// O11yOverallStateTransitionsOut is a rule's v1 firing/inactive windows.
type O11yOverallStateTransitionsOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds the windows.
Data []model.ReleStateItem `json:"data,omitempty"`
}
// O11yChannelsOut is a list of notification channels.
type O11yChannelsOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds the channels.
Data []*alertmanagertypes.Channel `json:"data,omitempty"`
}
// O11yChannelOut is one notification channel.
type O11yChannelOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds the channel.
Data alertmanagertypes.Channel `json:"data,omitempty"`
}
// O11yRoutePoliciesOut is a list of route policies.
type O11yRoutePoliciesOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds the policies.
Data []*alertmanagertypes.GettableRoutePolicy `json:"data,omitempty"`
}
// O11yRoutePolicyOut is one route policy.
type O11yRoutePolicyOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds the policy.
Data alertmanagertypes.GettableRoutePolicy `json:"data,omitempty"`
}
// O11yAlertsOut is the org's current alerts.
type O11yAlertsOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds the alerts.
Data alertmanagertypes.DeprecatedGettableAlerts `json:"data,omitempty"`
}