Documentation
¶
Overview ¶
Package alert implements threshold-based monitoring rules for cloop plans. Rules are persisted in .cloop/alerts.yaml and evaluated after each task completes during PM mode execution.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AddRule ¶
AddRule appends a rule to .cloop/alerts.yaml, replacing any existing rule with the same name.
Holds alertsMu for the entire load → modify → save cycle so two concurrent AddRule calls cannot each overwrite the file with their own one-element snapshot, losing the other's rule.
func RemoveRule ¶
RemoveRule removes the rule with the given name from .cloop/alerts.yaml. Returns an error if the rule does not exist.
Holds alertsMu for the entire load → filter → save cycle so a concurrent AddRule cannot have its appended rule silently dropped by RemoveRule's stale snapshot.
func Save ¶
Save writes alert rules to .cloop/alerts.yaml in workDir.
The write is atomic — data is staged in a sibling .tmp file, fsynced, then renamed. A torn write would otherwise leave the YAML unparseable and disable every alert rule on the next run.
func SessionCostUSD ¶
SessionCostUSD returns the cumulative cost for the current session by summing the cost ledger. Returns 0 on any error (best-effort).
func ValidateRule ¶
ValidateRule returns a non-nil error if the rule has an invalid field.
Types ¶
type EvalContext ¶
type EvalContext struct {
// Plan is the current PM plan (may be nil — metrics that require it return 0).
Plan *pm.Plan
// LastTaskMinutes is the actual execution time of the most recently completed task.
// The caller should set this to task.ActualMinutes after each task.
LastTaskMinutes float64
// TotalCostUSD is the cumulative session cost read from the cost ledger.
TotalCostUSD float64
}
EvalContext holds the pre-computed metric values used for a single evaluation. Callers can pass nil for plan or set lastTaskMinutes to 0 when not applicable.
type Metric ¶
type Metric string
Metric identifies which plan value to compare against a threshold.
const ( // MetricFailureRate is the percentage of tasks in failed status (0-100). MetricFailureRate Metric = "failure_rate" // MetricTaskDurationMinutes is the actual execution time of the most recently // completed task in minutes. MetricTaskDurationMinutes Metric = "task_duration_minutes" // MetricPendingCount is the number of tasks with status "pending". MetricPendingCount Metric = "pending_count" // MetricCostUSD is the total estimated session cost in USD from the cost ledger. MetricCostUSD Metric = "cost_usd" )
type Rule ¶
type Rule struct {
// Name is a unique identifier for this rule (e.g. "high-failure-rate").
Name string `yaml:"name"`
// Metric is the value to monitor (failure_rate, task_duration_minutes, pending_count, cost_usd).
Metric Metric `yaml:"metric"`
// Op is the comparison operator: gt, lt, or eq.
Op Op `yaml:"op"`
// Threshold is the numeric value to compare against.
Threshold float64 `yaml:"threshold"`
// Notify is the notification channel: "desktop", "webhook:<url>", or "slack:<url>".
Notify string `yaml:"notify"`
}
Rule defines a single monitoring rule.
func Load ¶
Load reads alert rules from .cloop/alerts.yaml in workDir. Returns an empty slice (not an error) when the file does not exist.
On parse failure (zero-byte file, manual edit gone wrong, schema drift), the corrupt file is quarantined aside as alerts.yaml.corrupt-<unix> and an empty rule set is returned. Silently disabling alerts is the wrong choice — the warning to stderr ensures the user notices — but it's better than refusing to start the run because a single rules file is malformed.
type Violation ¶
type Violation struct {
Rule Rule
ObservedValue float64
// TriggeredAt is the wall-clock time when the violation was detected.
TriggeredAt time.Time
}
Violation records a triggered alert rule along with the observed value.
func Evaluate ¶
func Evaluate(workDir string, rules []Rule, ctx EvalContext) []Violation
Evaluate runs all rules loaded from .cloop/alerts.yaml against the current plan state and returns any triggered violations. It is safe to call with a nil plan; metrics that require plan data will be treated as 0.