Last active
November 11, 2021 06:10
-
-
Save slok/314d591df5539905689a5ed32548537e to your computer and use it in GitHub Desktop.
Alertmanager alarm tester. Fire a custom alert to your alertmanager: https://github.com/prometheus/alertmanager
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bytes" | |
"encoding/json" | |
"flag" | |
"fmt" | |
"log" | |
"net/http" | |
"net/url" | |
"regexp" | |
"strings" | |
"time" | |
) | |
const ( | |
// alertmanager alerts api path. | |
amAPIPath = "api/v1/alerts" | |
) | |
var ( | |
// label regular expression. | |
labelRgx = regexp.MustCompile("[^=]+=[^=]+") | |
) | |
// labelMap is the type to pass multiple labels as flags. | |
type labelMap map[string]string | |
// String implements flag.Value interface. | |
func (l *labelMap) String() string { | |
return fmt.Sprintf("%v", *l) | |
} | |
// Set implements flag.Value interface. | |
func (l *labelMap) Set(value string) error { | |
// Check label. | |
if !labelRgx.Match([]byte(value)) { | |
return fmt.Errorf("label %s is not in key value format of 'xxx=yyyy'", value) | |
} | |
// set the label. | |
spl := strings.Split(value, "=") | |
(*l)[spl[0]] = spl[1] // We tust our regexp | |
return nil | |
} | |
// Parses a url to check if it's correct and sets the alertmanagers alerts API path. | |
func parseURL(checkURL string) (*url.URL, error) { | |
// Check if is a valid url. | |
amURL, err := url.ParseRequestURI(checkURL) | |
if err != nil { | |
return nil, fmt.Errorf("wrong alertmanager url: %s", checkURL) | |
} | |
amURL.Path = amAPIPath | |
return amURL, nil | |
} | |
// amFirer fires alerts to alertmanager. | |
type amFirer struct { | |
amURL *url.URL // amURL is the alertmanager url. | |
} | |
// fire fires an alert. | |
func (a *amFirer) fire(alertName string, labels map[string]string) error { | |
// Add the alertname. | |
labels["alertname"] = alertName | |
// Create the alarm body. | |
value := []struct { | |
Status string `json:"status"` | |
Labels map[string]string `json:"labels"` | |
}{ | |
{ | |
Status: "firing", | |
Labels: labels, | |
}, | |
} | |
body, err := json.Marshal(&value) | |
if err != nil { | |
return fmt.Errorf("error generating alert body: %s", err) | |
} | |
// Send the alarm. | |
if _, err := http.Post(a.amURL.String(), "application/json", bytes.NewBuffer(body)); err != nil { | |
return fmt.Errorf("failed seding the alert: %v", err) | |
} | |
return nil | |
} | |
// main will trigger a new alarm on the desired alertmanager, this could be used with test purpouses | |
// or a quick & easy way of manualy triggering an alarm. (https://github.com/prometheus/alertmanager) | |
// build: | |
// go build -o amfirer amfirer.go | |
// Usage examples: | |
// amfirer -l severity="warning" | |
// amfirer -l email="true" -address="http://alerts.mycompany.io" | |
// amfirer -l label_team="team-marketplace" -l severity="pager" -alertname="ClusterIsOnFireOMG" | |
func main() { | |
// flags stuff. | |
var ( | |
amAddr string | |
labels = labelMap{} | |
alertName string | |
) | |
defAlertName := fmt.Sprintf("test_%d", time.Now().UTC().Unix()) | |
flag.StringVar(&amAddr, "address", "http://127.0.0.1:9093", "alertmanager address") | |
flag.Var(&labels, "l", "label for the alert in key value format: 'xxx=yyy'") | |
flag.StringVar(&alertName, "alertname", defAlertName, "the name of the alert") | |
flag.Parse() | |
// Set correct url. | |
amURL, error := parseURL(amAddr) | |
if error != nil { | |
log.Fatalf("[ERROR] error parsing alertmanager url: %v", error) | |
} | |
f := &amFirer{amURL: amURL} | |
// Fire the alert. | |
if err := f.fire(alertName, map[string]string(labels)); err != nil { | |
log.Fatalf("[ERROR] error firing the alert: %v", err) | |
} | |
log.Printf("[OK] Alert %s sent to %s", alertName, f.amURL.String()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Found this via google, so cheers for the code.
And then I also remembered that alertmanager has
amtool
. So assuming it is configured to talk to an alertmanager instance, you can go ahead and create an alert like so (and then wait for it to expire):