mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Evaluate data templating in alert rule name and message (#29908)
* evaluate Go style template * inlince func * add test case * PR feedback and add tests for templte data map func * Add test case Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * do regex check * ensure ecape * small cleanup * dont exit on template execution errors * add info tooltip * add docs * switch from go tmpl to regex * update docs/comments * update tooltip wording * update docs wording * add simple test * avoid .MustCompile * point to labels in docs * update docs * fix docs links * remove line * fix lint * add note about multiple labels * propagate labels for CM * update docs * remove whitespace * update task title * update docs * pr feedback Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com>
This commit is contained in:
@@ -3,6 +3,7 @@ package alerting
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
@@ -178,3 +179,66 @@ func getNewStateInternal(c *EvalContext) models.AlertStateType {
|
||||
|
||||
return models.AlertStateOK
|
||||
}
|
||||
|
||||
// evaluateNotificationTemplateFields will treat the alert evaluation rule's name and message fields as
|
||||
// templates, and evaluate the templates using data from the alert evaluation's tags
|
||||
func (c *EvalContext) evaluateNotificationTemplateFields() error {
|
||||
if len(c.EvalMatches) < 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
templateDataMap, err := buildTemplateDataMap(c.EvalMatches)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ruleMsg, err := evaluateTemplate(c.Rule.Message, templateDataMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.Rule.Message = ruleMsg
|
||||
|
||||
ruleName, err := evaluateTemplate(c.Rule.Name, templateDataMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.Rule.Name = ruleName
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func evaluateTemplate(s string, m map[string]string) (string, error) {
|
||||
for k, v := range m {
|
||||
re, err := regexp.Compile(fmt.Sprintf(`\${%s}`, regexp.QuoteMeta(k)))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
s = re.ReplaceAllString(s, v)
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// buildTemplateDataMap builds a map of alert evaluation tag names to a set of associated values (comma separated)
|
||||
func buildTemplateDataMap(evalMatches []*EvalMatch) (map[string]string, error) {
|
||||
var result = map[string]string{}
|
||||
for _, match := range evalMatches {
|
||||
for tagName, tagValue := range match.Tags {
|
||||
// skip duplicate values
|
||||
rVal, err := regexp.Compile(fmt.Sprintf(`\b%s\b`, regexp.QuoteMeta(tagValue)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rMatch := rVal.FindString(result[tagName])
|
||||
if len(rMatch) > 0 {
|
||||
continue
|
||||
}
|
||||
if _, exists := result[tagName]; exists {
|
||||
result[tagName] = fmt.Sprintf("%s, %s", result[tagName], tagValue)
|
||||
} else {
|
||||
result[tagName] = tagValue
|
||||
}
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user