blob: 82d13c64502d07321faff1ad83e38ef932d468a4 [file] [log] [blame]
// Command-line application that parses a Promethues alerts file and produces a
// second alerts file that checks for missing data for each of the input
// alerts.
package main
import (
"flag"
"fmt"
"io/ioutil"
"strings"
"github.com/golang/glog"
"go.skia.org/infra/go/common"
)
// flags
var (
in = flag.String("in", "sys/alert.rules", "The Prometheus alerts to read as input.")
out = flag.String("out", "sys/absent.rules", "The Prometheus alerts to write as output.")
)
const (
RULE = `ALERT MissingData
IF absent(%s)
FOR 5m
LABELS { category = "infra", severity = "critical" }
ANNOTATIONS {
abbr = "%s",
description = "There is no data for the following alert: %s"
}
`
)
func main() {
common.Init()
// Open input file (alert.rules)
b, err := ioutil.ReadFile(*in)
if err != nil {
glog.Fatalf("Failed to open input file %q: %s", *in, err)
}
body := []string{
"# DO NOT EDIT: This file is generated by running the 'absent' tool.\n\n",
}
replacer := strings.NewReplacer("<", "", ">", "", "=", "", "!", "")
escaper := strings.NewReplacer("\"", "\\\"")
lines := strings.Split(string(b), "\n")
for _, line := range lines {
// The IF lines look like:
//
// IF prober{type="failure"} > 0
//
// Parse up each "IF" statement.
line = strings.TrimSpace(line)
if !strings.HasPrefix(line, "IF ") {
continue
}
parts := strings.Split(line, " ")
// Check that the second to last part is a valid comparison operator.
if len(parts) < 4 {
glog.Fatalf("Does not appear to be a valid IF statement: %q", line)
}
op := parts[len(parts)-2]
if len(op) == 0 {
glog.Fatalf("Missing a valid comparison operator in IF statement: %q", line)
}
empty := replacer.Replace(op)
if empty != "" {
glog.Fatalf("Not a valid comparison operator %q in IF statement %q:", op, line)
}
// We are interested in just the expression w/o the comparison, or the "IF".
expression := strings.Join(parts[1:len(parts)-2], "")
// Escape quotes in the expression.
escaped := escaper.Replace(expression)
// Create a new rule that checks if there is no data for the expression.
body = append(body, fmt.Sprintf(RULE, expression, escaped, escaped))
}
// Write the output file.
if err := ioutil.WriteFile(*out, []byte(strings.Join(body, "")), 0644); err != nil {
glog.Fatalf("Failed to write output file %q: %s", *out, err)
}
}