func procRule(t miniprofiler.Timer, c *conf.Conf, a *conf.Alert, now time.Time, summary bool, email string, template_group string) (*ruleResult, error) { s := &sched.Schedule{} s.DataAccess = schedule.DataAccess s.Search = schedule.Search if err := s.Init(c); err != nil { return nil, err } rh := s.NewRunHistory(now, cacheObj) if _, err := s.CheckExpr(t, rh, a, a.Warn, models.StWarning, nil); err != nil { return nil, err } if _, err := s.CheckExpr(t, rh, a, a.Crit, models.StCritical, nil); err != nil { return nil, err } keys := make(models.AlertKeys, len(rh.Events)) criticals, warnings, normals := make([]models.AlertKey, 0), make([]models.AlertKey, 0), make([]models.AlertKey, 0) i := 0 for k, v := range rh.Events { v.Time = now keys[i] = k i++ switch v.Status { case models.StNormal: normals = append(normals, k) case models.StWarning: warnings = append(warnings, k) case models.StCritical: criticals = append(criticals, k) default: return nil, fmt.Errorf("unknown state type %v", v.Status) } } sort.Sort(keys) var subject, body []byte var data interface{} warning := make([]string, 0) if !summary && len(keys) > 0 { var primaryIncident *models.IncidentState if template_group != "" { ts, err := opentsdb.ParseTags(template_group) if err != nil { return nil, err } for _, ak := range keys { if ak.Group().Subset(ts) { primaryIncident = sched.NewIncident(ak) primaryIncident.Events = []models.Event{*rh.Events[ak]} break } } } if primaryIncident == nil { primaryIncident = sched.NewIncident(keys[0]) primaryIncident.Events = []models.Event{*rh.Events[keys[0]]} if template_group != "" { warning = append(warning, fmt.Sprintf("template group %s was not a subset of any result", template_group)) } } if e := primaryIncident.Events[0]; e.Crit != nil { primaryIncident.Result = e.Crit } else if e.Warn != nil { primaryIncident.Result = e.Warn } var b_err, s_err error func() { defer func() { if err := recover(); err != nil { s := fmt.Sprint(err) warning = append(warning, s) b_err = fmt.Errorf(s) } }() if body, _, b_err = s.ExecuteBody(rh, a, primaryIncident, false); b_err != nil { warning = append(warning, b_err.Error()) } }() func() { defer func() { if err := recover(); err != nil { s := fmt.Sprint(err) warning = append(warning, s) s_err = fmt.Errorf(s) } }() subject, s_err = s.ExecuteSubject(rh, a, primaryIncident, false) if s_err != nil { warning = append(warning, s_err.Error()) } }() if s_err != nil || b_err != nil { var err error subject, body, err = s.ExecuteBadTemplate([]error{s_err, b_err}, rh, a, primaryIncident) if err != nil { subject = []byte(fmt.Sprintf("unable to create tempalate error notification: %v", err)) } } else if email != "" { m, err := mail.ParseAddress(email) if err != nil { return nil, err } n := conf.Notification{ Email: []*mail.Address{m}, } email, attachments, b_err := s.ExecuteBody(rh, a, primaryIncident, true) email_subject, s_err := s.ExecuteSubject(rh, a, primaryIncident, true) if b_err != nil { warning = append(warning, b_err.Error()) } else if s_err != nil { warning = append(warning, s_err.Error()) } else { n.DoEmail(email_subject, email, schedule.Conf, string(primaryIncident.AlertKey), attachments...) } } data = s.Data(rh, primaryIncident, a, false) } return &ruleResult{ criticals, warnings, normals, now, string(body), string(subject), data, rh.Events, warning, }, nil }