Documentation
¶
Overview ¶
Package alerts implements CREATE ALERT DDL runtime: scheduler, sinks (webhook, alert_history table), and Prometheus metrics. Alerts run exclusively on the leader coordinator; see internal/coordinator for lifecycle wiring. The DDL grammar is parsed in internal/planner/sql.
Index ¶
- Constants
- func BuildHistoryInsertSQL(fire AlertFire, results []SinkResult, now time.Time) (string, error)
- func Collectors() []prometheus.Collector
- func EnsureHistoryTable(ctx context.Context, cat *catalog.Catalog) error
- type AlertFire
- type AlertSink
- type ColumnMeta
- type EvalContextFunc
- type SQLExecutor
- type Scheduler
- type SinkFactory
- type SinkResult
- type TableSink
- type WebhookSink
Constants ¶
const HistoryTableName = "alert_history"
HistoryTableName is the name of the system table holding alert fires.
const MaxRowsPerFire = 1000
MaxRowsPerFire is the hard cap on rows included in AlertFire.Rows.
Variables ¶
This section is empty.
Functions ¶
func BuildHistoryInsertSQL ¶
BuildHistoryInsertSQL constructs an INSERT INTO alert_history VALUES (...) statement. All string values are SQL-escaped (single-quote doubling) to handle embedded quotes in JSON payloads. Inputs are internal-only but escaping is defense-in-depth.
func Collectors ¶
func Collectors() []prometheus.Collector
Collectors returns all Prometheus collectors for the alerts package so the caller can register them with their custom registry (mirrors the project's metrics.New() pattern — no promauto / global registry usage).
Types ¶
type AlertFire ¶
type AlertFire struct {
AlertName string `json:"alert"`
EvaluatedAt time.Time `json:"evaluated_at"`
RowCount int64 `json:"row_count"` // true count, pre-truncation
Rows []map[string]any `json:"rows"` // capped at MaxRowsPerFire
Truncated bool `json:"truncated"`
Schema []ColumnMeta `json:"schema"`
}
AlertFire is the payload delivered to each sink on a matching evaluation.
type AlertSink ¶
AlertSink delivers an AlertFire to its destination. Implementations must be safe to call concurrently and should respect ctx cancellation.
type ColumnMeta ¶
ColumnMeta describes one result column.
type EvalContextFunc ¶
EvalContextFunc decorates the per-evaluation context for an alert before its query runs. Injected so the scheduler stays decoupled from the auth package: the owner (coordinator / embedded DB) supplies a func that stamps the alert creator's identity onto the context (definer's rights), so the scheduled query enforces the creator's ABAC row/column policies instead of running unfiltered. A nil func (or a nil return) leaves the context unchanged.
type SQLExecutor ¶
type SQLExecutor interface {
// Execute runs a mutation statement (INSERT INTO ...). Returns an error
// on failure; no result is surfaced.
Execute(ctx context.Context, sql string) error
// Query runs a SELECT and returns rows as []map[string]any plus a schema.
// Implementations should cap the number of rows returned to at most limit.
// If the underlying result has more rows, truncated is true and total is
// the true (pre-truncation) row count.
Query(ctx context.Context, sql string, limit int) (rows []map[string]any, schema []ColumnMeta, total int64, truncated bool, err error)
}
SQLExecutor is the narrow interface the TableSink and scheduler use to run SQL against the engine. Implemented by *coordinator.Coordinator so this package doesn't import coordinator (breaks a would-be import cycle).
type Scheduler ¶
type Scheduler struct {
// contains filtered or unexported fields
}
Scheduler runs alerts on their configured cadence. It owns one goroutine that ticks and dispatches per-alert evaluations as short-lived goroutines.
func NewScheduler ¶
func NewScheduler(cat *catalog.Catalog, exec SQLExecutor, sinks SinkFactory, evalCtx EvalContextFunc) *Scheduler
NewScheduler constructs a scheduler with a default 1s tick cadence. evalCtx may be nil (no per-alert context decoration); production callers pass a func that stamps the alert creator's identity for definer's-rights enforcement.
type SinkFactory ¶
SinkFactory returns the set of sinks for an alert. Injected so the scheduler doesn't know about WebhookSink/TableSink concretely and tests can stub.
type SinkResult ¶
type SinkResult struct {
Sink string `json:"sink"`
OK bool `json:"ok"`
Error string `json:"error,omitempty"`
}
SinkResult records per-sink delivery outcome.
type TableSink ¶
type TableSink struct {
Executor SQLExecutor
// Now is a clock injection seam for tests. Defaults to time.Now.
Now func() time.Time
// Results captured from sibling sinks, embedded in the history row.
// The scheduler sets this before calling Deliver.
Results []SinkResult
}
TableSink inserts one row into the alert_history table per fire by running INSERT INTO via an injected SQLExecutor.
type WebhookSink ¶
type WebhookSink struct {
AlertName string
URL string
Headers map[string]string
Client *http.Client
// contains filtered or unexported fields
}
WebhookSink POSTs an AlertFire JSON body to a URL with configurable headers and jittered exponential-backoff retries.
func NewWebhookSink ¶
func NewWebhookSink(alertName, url string, headers map[string]string, timeout time.Duration) *WebhookSink
NewWebhookSink constructs a WebhookSink with production defaults: 3 retries, 200ms base backoff (→ 200, 800, 3200 ms), and the supplied HTTP timeout.
func (*WebhookSink) Deliver ¶
func (s *WebhookSink) Deliver(ctx context.Context, fire AlertFire) error
Deliver POSTs the fire as JSON, retrying on network errors and non-2xx responses. Returns the last error after all retries are exhausted.
func (*WebhookSink) Name ¶
func (*WebhookSink) Name() string