// HTMLSnippet returns an HTML snippet representing this rule. func (rule RecordingRule) HTMLSnippet(pathPrefix string) template.HTML { ruleExpr := rule.vector.String() return template.HTML(fmt.Sprintf( `<a href="%s">%s</a>%s = <a href="%s">%s</a>`, pathPrefix+strutil.GraphLinkForExpression(rule.name), rule.name, template.HTMLEscapeString(rule.labels.String()), pathPrefix+strutil.GraphLinkForExpression(ruleExpr), template.HTMLEscapeString(ruleExpr))) }
// HTMLSnippet returns an HTML snippet representing this alerting rule. func (rule *AlertingRule) HTMLSnippet(pathPrefix string) template.HTML { alertMetric := clientmodel.Metric{ clientmodel.MetricNameLabel: alertMetricName, alertNameLabel: clientmodel.LabelValue(rule.name), } return template.HTML(fmt.Sprintf( `ALERT <a href="%s">%s</a> IF <a href="%s">%s</a> FOR %s WITH %s`, pathPrefix+strutil.GraphLinkForExpression(alertMetric.String()), rule.name, pathPrefix+strutil.GraphLinkForExpression(rule.vector.String()), rule.vector, strutil.DurationToString(rule.holdDuration), rule.labels)) }
// sendAlerts sends alert notifications for the given rule. func (g *Group) sendAlerts(rule *AlertingRule, timestamp model.Time) error { var alerts model.Alerts for _, alert := range rule.currentAlerts() { // Only send actually firing alerts. if alert.State == StatePending { continue } a := &model.Alert{ StartsAt: alert.ActiveAt.Add(rule.holdDuration).Time(), Labels: alert.Labels, Annotations: alert.Annotations, GeneratorURL: g.opts.ExternalURL.String() + strutil.GraphLinkForExpression(rule.vector.String()), } if alert.ResolvedAt != 0 { a.EndsAt = alert.ResolvedAt.Time() } alerts = append(alerts, a) } if len(alerts) > 0 { g.opts.Notifier.Send(alerts...) } return nil }
// HTMLSnippet returns an HTML snippet representing this alerting rule. The // resulting snippet is expected to be presented in a <pre> element, so that // line breaks and other returned whitespace is respected. func (rule *AlertingRule) HTMLSnippet(pathPrefix string) template.HTML { alertMetric := model.Metric{ model.MetricNameLabel: alertMetricName, alertNameLabel: model.LabelValue(rule.name), } s := fmt.Sprintf("ALERT <a href=%q>%s</a>", pathPrefix+strutil.GraphLinkForExpression(alertMetric.String()), rule.name) s += fmt.Sprintf("\n IF <a href=%q>%s</a>", pathPrefix+strutil.GraphLinkForExpression(rule.vector.String()), rule.vector) if rule.holdDuration > 0 { s += fmt.Sprintf("\n FOR %s", strutil.DurationToString(rule.holdDuration)) } if len(rule.labels) > 0 { s += fmt.Sprintf("\n WITH %s", rule.labels) } if len(rule.annotations) > 0 { s += fmt.Sprintf("\n ANNOTATIONS %s", rule.annotations) } return template.HTML(s) }
// HTMLSnippet returns an HTML snippet representing this alerting rule. The // resulting snippet is expected to be presented in a <pre> element, so that // line breaks and other returned whitespace is respected. func (r *AlertingRule) HTMLSnippet(pathPrefix string) html_template.HTML { alertMetric := model.Metric{ model.MetricNameLabel: alertMetricName, alertNameLabel: model.LabelValue(r.name), } s := fmt.Sprintf("ALERT <a href=%q>%s</a>", pathPrefix+strutil.GraphLinkForExpression(alertMetric.String()), r.name) s += fmt.Sprintf("\n IF <a href=%q>%s</a>", pathPrefix+strutil.GraphLinkForExpression(r.vector.String()), html_template.HTMLEscapeString(r.vector.String())) if r.holdDuration > 0 { s += fmt.Sprintf("\n FOR %s", model.Duration(r.holdDuration)) } if len(r.labels) > 0 { s += fmt.Sprintf("\n LABELS %s", html_template.HTMLEscapeString(r.labels.String())) } if len(r.annotations) > 0 { s += fmt.Sprintf("\n ANNOTATIONS %s", html_template.HTMLEscapeString(r.annotations.String())) } return html_template.HTML(s) }
// HTMLSnippet returns an HTML snippet representing this alerting rule. The // resulting snippet is expected to be presented in a <pre> element, so that // line breaks and other returned whitespace is respected. func (rule *AlertingRule) HTMLSnippet(pathPrefix string) template.HTML { alertMetric := model.Metric{ model.MetricNameLabel: alertMetricName, alertNameLabel: model.LabelValue(rule.name), } s := fmt.Sprintf("ALERT <a href=%q>%s</a>", pathPrefix+strutil.GraphLinkForExpression(alertMetric.String()), rule.name) s += fmt.Sprintf("\n IF <a href=%q>%s</a>", pathPrefix+strutil.GraphLinkForExpression(rule.vector.String()), rule.vector) if rule.holdDuration > 0 { s += fmt.Sprintf("\n FOR %s", strutil.DurationToString(rule.holdDuration)) } if len(rule.labels) > 0 { s += fmt.Sprintf("\n WITH %s", rule.labels) } s += fmt.Sprintf("\n SUMMARY %q", rule.summary) s += fmt.Sprintf("\n DESCRIPTION %q", rule.description) s += fmt.Sprintf("\n RUNBOOK %q", rule.runbook) return template.HTML(s) }
func (m *Manager) queueAlertNotifications(rule *AlertingRule, timestamp clientmodel.Timestamp) { activeAlerts := rule.ActiveAlerts() if len(activeAlerts) == 0 { return } notifications := make(notification.NotificationReqs, 0, len(activeAlerts)) for _, aa := range activeAlerts { if aa.State != StateFiring { // BUG: In the future, make AlertManager support pending alerts? continue } // Provide the alert information to the template. l := map[string]string{} for k, v := range aa.Labels { l[string(k)] = string(v) } tmplData := struct { Labels map[string]string Value clientmodel.SampleValue }{ Labels: l, Value: aa.Value, } // Inject some convenience variables that are easier to remember for users // who are not used to Go's templating system. defs := "{{$labels := .Labels}}{{$value := .Value}}" expand := func(text string) string { tmpl := template.NewTemplateExpander(defs+text, "__alert_"+rule.Name(), tmplData, timestamp, m.queryEngine, m.externalURL.Path) result, err := tmpl.Expand() if err != nil { result = err.Error() log.Warnf("Error expanding alert template %v with data '%v': %v", rule.Name(), tmplData, err) } return result } notifications = append(notifications, ¬ification.NotificationReq{ Summary: expand(rule.summary), Description: expand(rule.description), Runbook: rule.runbook, Labels: aa.Labels.Merge(clientmodel.LabelSet{ alertNameLabel: clientmodel.LabelValue(rule.Name()), }), Value: aa.Value, ActiveSince: aa.ActiveSince.Time(), RuleString: rule.String(), GeneratorURL: m.externalURL.String() + strutil.GraphLinkForExpression(rule.vector.String()), }) } m.notificationHandler.SubmitReqs(notifications) }
// sendAlerts sends alert notifications for the given rule. func (g *Group) sendAlerts(rule *AlertingRule, timestamp model.Time) error { var alerts model.Alerts for _, alert := range rule.currentAlerts() { // Only send actually firing alerts. if alert.State == StatePending { continue } // Provide the alert information to the template. l := make(map[string]string, len(alert.Labels)) for k, v := range alert.Labels { l[string(k)] = string(v) } tmplData := struct { Labels map[string]string Value float64 }{ Labels: l, Value: float64(alert.Value), } // Inject some convenience variables that are easier to remember for users // who are not used to Go's templating system. defs := "{{$labels := .Labels}}{{$value := .Value}}" expand := func(text model.LabelValue) model.LabelValue { tmpl := template.NewTemplateExpander( defs+string(text), "__alert_"+rule.Name(), tmplData, timestamp, g.opts.QueryEngine, g.opts.ExternalURL.Path, ) result, err := tmpl.Expand() if err != nil { result = fmt.Sprintf("<error expanding template: %s>", err) log.Warnf("Error expanding alert template %v with data '%v': %s", rule.Name(), tmplData, err) } return model.LabelValue(result) } labels := make(model.LabelSet, len(alert.Labels)+1) for ln, lv := range alert.Labels { labels[ln] = expand(lv) } labels[model.AlertNameLabel] = model.LabelValue(rule.Name()) annotations := make(model.LabelSet, len(rule.annotations)) for an, av := range rule.annotations { annotations[an] = expand(av) } a := &model.Alert{ StartsAt: alert.ActiveAt.Add(rule.holdDuration).Time(), Labels: labels, Annotations: annotations, GeneratorURL: g.opts.ExternalURL.String() + strutil.GraphLinkForExpression(rule.vector.String()), } if alert.ResolvedAt != 0 { a.EndsAt = alert.ResolvedAt.Time() } alerts = append(alerts, a) } if len(alerts) > 0 { g.opts.NotificationHandler.Send(alerts...) } return nil }