mirror of
https://github.com/prometheus/alertmanager
synced 2024-12-26 16:12:20 +00:00
add hipchat room notifier
This commit is contained in:
parent
0c668ea4e5
commit
23db37dc98
@ -26,7 +26,7 @@ import (
|
|||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var patAuthLine = regexp.MustCompile(`((?:api_token|api_key|service_key|api_url):\s+)(".+"|'.+'|[^\s]+)`)
|
var patAuthLine = regexp.MustCompile(`((?:api_token|api_key|service_key|api_url|auth_token):\s+)(".+"|'.+'|[^\s]+)`)
|
||||||
|
|
||||||
// Secret is a string that must not be revealed on marshaling.
|
// Secret is a string that must not be revealed on marshaling.
|
||||||
type Secret string
|
type Secret string
|
||||||
@ -169,6 +169,23 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|||||||
sc.APIURL = c.Global.SlackAPIURL
|
sc.APIURL = c.Global.SlackAPIURL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, hc := range rcv.HipchatConfigs {
|
||||||
|
if hc.APIURL == "" {
|
||||||
|
if c.Global.HipchatURL == "" {
|
||||||
|
return fmt.Errorf("no global Hipchat API URL set")
|
||||||
|
}
|
||||||
|
hc.APIURL = c.Global.HipchatURL
|
||||||
|
}
|
||||||
|
if !strings.HasSuffix(hc.APIURL, "/") {
|
||||||
|
hc.APIURL += "/"
|
||||||
|
}
|
||||||
|
if hc.AuthToken == "" {
|
||||||
|
if c.Global.HipchatAuthToken == "" {
|
||||||
|
return fmt.Errorf("no global Hipchat Auth Token set")
|
||||||
|
}
|
||||||
|
hc.AuthToken = c.Global.HipchatAuthToken
|
||||||
|
}
|
||||||
|
}
|
||||||
for _, pdc := range rcv.PagerdutyConfigs {
|
for _, pdc := range rcv.PagerdutyConfigs {
|
||||||
if pdc.URL == "" {
|
if pdc.URL == "" {
|
||||||
if c.Global.PagerdutyURL == "" {
|
if c.Global.PagerdutyURL == "" {
|
||||||
@ -198,6 +215,7 @@ var DefaultGlobalConfig = GlobalConfig{
|
|||||||
ResolveTimeout: model.Duration(5 * time.Minute),
|
ResolveTimeout: model.Duration(5 * time.Minute),
|
||||||
|
|
||||||
PagerdutyURL: "https://events.pagerduty.com/generic/2010-04-15/create_event.json",
|
PagerdutyURL: "https://events.pagerduty.com/generic/2010-04-15/create_event.json",
|
||||||
|
HipchatURL: "https://api.hipchat.com/",
|
||||||
OpsGenieAPIHost: "https://api.opsgenie.com/",
|
OpsGenieAPIHost: "https://api.opsgenie.com/",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,11 +226,13 @@ type GlobalConfig struct {
|
|||||||
// if it has not been updated.
|
// if it has not been updated.
|
||||||
ResolveTimeout model.Duration `yaml:"resolve_timeout"`
|
ResolveTimeout model.Duration `yaml:"resolve_timeout"`
|
||||||
|
|
||||||
SMTPFrom string `yaml:"smtp_from"`
|
SMTPFrom string `yaml:"smtp_from"`
|
||||||
SMTPSmarthost string `yaml:"smtp_smarthost"`
|
SMTPSmarthost string `yaml:"smtp_smarthost"`
|
||||||
SlackAPIURL Secret `yaml:"slack_api_url"`
|
SlackAPIURL Secret `yaml:"slack_api_url"`
|
||||||
PagerdutyURL string `yaml:"pagerduty_url"`
|
PagerdutyURL string `yaml:"pagerduty_url"`
|
||||||
OpsGenieAPIHost string `yaml:"opsgenie_api_host"`
|
HipchatURL string `yaml:"hipchat_url"`
|
||||||
|
HipchatAuthToken Secret `yaml:"hipchat_auth_token"`
|
||||||
|
OpsGenieAPIHost string `yaml:"opsgenie_api_host"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
||||||
@ -336,6 +356,7 @@ type Receiver struct {
|
|||||||
|
|
||||||
EmailConfigs []*EmailConfig `yaml:"email_configs,omitempty"`
|
EmailConfigs []*EmailConfig `yaml:"email_configs,omitempty"`
|
||||||
PagerdutyConfigs []*PagerdutyConfig `yaml:"pagerduty_configs,omitempty"`
|
PagerdutyConfigs []*PagerdutyConfig `yaml:"pagerduty_configs,omitempty"`
|
||||||
|
HipchatConfigs []*HipchatConfig `yaml:"hipchat_configs,omitempty"`
|
||||||
SlackConfigs []*SlackConfig `yaml:"slack_configs,omitempty"`
|
SlackConfigs []*SlackConfig `yaml:"slack_configs,omitempty"`
|
||||||
WebhookConfigs []*WebhookConfig `yaml:"webhook_configs,omitempty"`
|
WebhookConfigs []*WebhookConfig `yaml:"webhook_configs,omitempty"`
|
||||||
OpsGenieConfigs []*OpsGenieConfig `yaml:"opsgenie_configs,omitempty"`
|
OpsGenieConfigs []*OpsGenieConfig `yaml:"opsgenie_configs,omitempty"`
|
||||||
|
@ -67,6 +67,18 @@ var (
|
|||||||
Fallback: `{{ template "slack.default.fallback" . }}`,
|
Fallback: `{{ template "slack.default.fallback" . }}`,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DefaultHipchatConfig defines default values for Hipchat configurations.
|
||||||
|
DefaultHipchatConfig = HipchatConfig{
|
||||||
|
NotifierConfig: NotifierConfig{
|
||||||
|
VSendResolved: false,
|
||||||
|
},
|
||||||
|
Color: `{{ if eq .Status "firing" }}red{{ else }}green{{ end }}`,
|
||||||
|
From: `{{ template "hipchat.default.from" . }}`,
|
||||||
|
Notify: false,
|
||||||
|
Message: `{{ template "hipchat.default.message" . }}`,
|
||||||
|
MessageFormat: `text`,
|
||||||
|
}
|
||||||
|
|
||||||
// DefaultOpsGenieConfig defines default values for OpsGenie configurations.
|
// DefaultOpsGenieConfig defines default values for OpsGenie configurations.
|
||||||
DefaultOpsGenieConfig = OpsGenieConfig{
|
DefaultOpsGenieConfig = OpsGenieConfig{
|
||||||
NotifierConfig: NotifierConfig{
|
NotifierConfig: NotifierConfig{
|
||||||
@ -188,6 +200,41 @@ func (c *SlackConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|||||||
return checkOverflow(c.XXX, "slack config")
|
return checkOverflow(c.XXX, "slack config")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HipchatConfig configures notifications via Hipchat.
|
||||||
|
type HipchatConfig struct {
|
||||||
|
NotifierConfig `yaml:",inline"`
|
||||||
|
|
||||||
|
APIURL string `yaml:"api_url"`
|
||||||
|
AuthToken Secret `yaml:"auth_token"`
|
||||||
|
RoomID string `yaml:"room_id"`
|
||||||
|
From string `yaml:"from"`
|
||||||
|
Notify bool `yaml:"notify"`
|
||||||
|
Message string `yaml:"message"`
|
||||||
|
MessageFormat string `yaml:"message_format"`
|
||||||
|
Color string `yaml:"color"`
|
||||||
|
|
||||||
|
// Catches all undefined fields and must be empty after parsing.
|
||||||
|
XXX map[string]interface{} `yaml:",inline"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
||||||
|
func (c *HipchatConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
|
*c = DefaultHipchatConfig
|
||||||
|
type plain HipchatConfig
|
||||||
|
if err := unmarshal((*plain)(c)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if c.RoomID == "" {
|
||||||
|
return fmt.Errorf("missing room id in Hipchat config")
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.AuthToken == "" {
|
||||||
|
return fmt.Errorf("missing auth token in Hipchat config")
|
||||||
|
}
|
||||||
|
|
||||||
|
return checkOverflow(c.XXX, "hipchat config")
|
||||||
|
}
|
||||||
|
|
||||||
// WebhookConfig configures notifications via a generic webhook.
|
// WebhookConfig configures notifications via a generic webhook.
|
||||||
type WebhookConfig struct {
|
type WebhookConfig struct {
|
||||||
NotifierConfig `yaml:",inline"`
|
NotifierConfig `yaml:",inline"`
|
||||||
|
@ -98,6 +98,10 @@ func Build(confs []*config.Receiver, tmpl *template.Template) map[string]Fanout
|
|||||||
n := NewSlack(c, tmpl)
|
n := NewSlack(c, tmpl)
|
||||||
add(i, n, filter(n, c))
|
add(i, n, filter(n, c))
|
||||||
}
|
}
|
||||||
|
for i, c := range nc.HipchatConfigs {
|
||||||
|
n := NewHipchat(c, tmpl)
|
||||||
|
add(i, n, filter(n, c))
|
||||||
|
}
|
||||||
|
|
||||||
res[nc.Name] = fo
|
res[nc.Name] = fo
|
||||||
}
|
}
|
||||||
@ -477,6 +481,75 @@ func (n *Slack) Notify(ctx context.Context, as ...*types.Alert) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hipchat implements a Notifier for Hipchat notifications.
|
||||||
|
type Hipchat struct {
|
||||||
|
conf *config.HipchatConfig
|
||||||
|
tmpl *template.Template
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewHipchat returns a new Hipchat notification handler.
|
||||||
|
func NewHipchat(conf *config.HipchatConfig, tmpl *template.Template) *Hipchat {
|
||||||
|
return &Hipchat{
|
||||||
|
conf: conf,
|
||||||
|
tmpl: tmpl,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type hipchatReq struct {
|
||||||
|
From string `json:"from"`
|
||||||
|
Notify bool `json:"notify"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
MessageFormat string `json:"message_format"`
|
||||||
|
Color string `json:"color"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify implements the Notifier interface.
|
||||||
|
func (n *Hipchat) Notify(ctx context.Context, as ...*types.Alert) error {
|
||||||
|
var err error
|
||||||
|
var msg string
|
||||||
|
var (
|
||||||
|
data = n.tmpl.Data(receiver(ctx), groupLabels(ctx), as...)
|
||||||
|
tmplText = tmplText(n.tmpl, data, &err)
|
||||||
|
tmplHTML = tmplHTML(n.tmpl, data, &err)
|
||||||
|
url = fmt.Sprintf("%sv2/room/%s/notification?auth_token=%s", n.conf.APIURL, n.conf.RoomID, n.conf.AuthToken)
|
||||||
|
)
|
||||||
|
|
||||||
|
if n.conf.MessageFormat == "html" {
|
||||||
|
msg = tmplHTML(n.conf.Message)
|
||||||
|
} else {
|
||||||
|
msg = tmplText(n.conf.Message)
|
||||||
|
}
|
||||||
|
|
||||||
|
req := &hipchatReq{
|
||||||
|
From: tmplText(n.conf.From),
|
||||||
|
Notify: n.conf.Notify,
|
||||||
|
Message: msg,
|
||||||
|
MessageFormat: n.conf.MessageFormat,
|
||||||
|
Color: tmplText(n.conf.Color),
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if err := json.NewEncoder(&buf).Encode(req); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := ctxhttp.Post(ctx, http.DefaultClient, url, contentTypeJSON, &buf)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode/100 != 2 {
|
||||||
|
return fmt.Errorf("unexpected status code %v", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// OpsGenie implements a Notifier for OpsGenie notifications.
|
// OpsGenie implements a Notifier for OpsGenie notifications.
|
||||||
type OpsGenie struct {
|
type OpsGenie struct {
|
||||||
conf *config.OpsGenieConfig
|
conf *config.OpsGenieConfig
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
{{ define "__subject" }}[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .GroupLabels.SortedPairs.Values | join " " }} {{ if gt (len .CommonLabels) (len .GroupLabels) }}({{ with .CommonLabels.Remove .GroupLabels.Names }}{{ .Values | join " " }}{{ end }}){{ end }}{{ end }}
|
{{ define "__subject" }}[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .GroupLabels.SortedPairs.Values | join " " }} {{ if gt (len .CommonLabels) (len .GroupLabels) }}({{ with .CommonLabels.Remove .GroupLabels.Names }}{{ .Values | join " " }}{{ end }}){{ end }}{{ end }}
|
||||||
{{ define "__description" }}{{ end }}
|
{{ define "__description" }}{{ end }}
|
||||||
|
|
||||||
{{ define "__text_alert_list" }}{{ range . }}Labels:
|
{{ define "__text_alert_list" }}{{ range . }}Labels:
|
||||||
{{ range .Labels.SortedPairs }} - {{ .Name }} = {{ .Value }}
|
{{ range .Labels.SortedPairs }} - {{ .Name }} = {{ .Value }}
|
||||||
{{ end }}Annotations:
|
{{ end }}Annotations:
|
||||||
{{ range .Annotations.SortedPairs }} - {{ .Name }} = {{ .Value }}
|
{{ range .Annotations.SortedPairs }} - {{ .Name }} = {{ .Value }}
|
||||||
{{ end}}
|
{{ end}}
|
||||||
{{ end }}{{ end }}
|
{{ end }}{{ end }}
|
||||||
@ -20,6 +20,10 @@
|
|||||||
{{ define "slack.default.text" }}{{ end }}
|
{{ define "slack.default.text" }}{{ end }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ define "hipchat.default.from" }}{{ template "__alertmanager" . }}{{ end }}
|
||||||
|
{{ define "hipchat.default.message" }}{{ template "__subject" . }}{{ end }}
|
||||||
|
|
||||||
|
|
||||||
{{ define "pagerduty.default.description" }}{{ template "__subject" . }}{{ end }}
|
{{ define "pagerduty.default.description" }}{{ template "__subject" . }}{{ end }}
|
||||||
{{ define "pagerduty.default.client" }}{{ template "__alertmanager" . }}{{ end }}
|
{{ define "pagerduty.default.client" }}{{ template "__alertmanager" . }}{{ end }}
|
||||||
{{ define "pagerduty.default.clientURL" }}{{ template "__alertmanagerURL" . }}{{ end }}
|
{{ define "pagerduty.default.clientURL" }}{{ template "__alertmanagerURL" . }}{{ end }}
|
||||||
@ -52,7 +56,7 @@
|
|||||||
<tr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
<tr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
||||||
<td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; vertical-align: top; color: #fff; font-weight: 500; text-align: center; border-radius: 3px 3px 0 0; background-color: #E6522C; margin: 0; padding: 20px;" align="center" bgcolor="#E6522C" valign="top">
|
<td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; vertical-align: top; color: #fff; font-weight: 500; text-align: center; border-radius: 3px 3px 0 0; background-color: #E6522C; margin: 0; padding: 20px;" align="center" bgcolor="#E6522C" valign="top">
|
||||||
{{ .Alerts | len }} alert{{ if gt (len .Alerts) 1 }}s{{ end }} for {{ range .GroupLabels.SortedPairs }}
|
{{ .Alerts | len }} alert{{ if gt (len .Alerts) 1 }}s{{ end }} for {{ range .GroupLabels.SortedPairs }}
|
||||||
{{ .Name }}={{ .Value }}
|
{{ .Name }}={{ .Value }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user