func getAndFilterAnnotations(e *State, start, end time.Time, filter string) (annotate.Annotations, error) { annotations, err := e.AnnotateContext.GetAnnotations(&start, &end, "", "", "", "", "", "", "") if err != nil { return nil, err } var t *boolq.Tree if filter != "" { var err error t, err = boolq.Parse(filter) if err != nil { return nil, fmt.Errorf("failed to parse annotation filter: %v", err) } } filteredAnnotations := annotate.Annotations{} for _, a := range annotations { if filter == "" { filteredAnnotations = append(filteredAnnotations, a) continue } match, err := boolq.AskParsedExpr(t, a) if err != nil { return nil, err } if match { filteredAnnotations = append(filteredAnnotations, a) } } sort.Sort(sort.Reverse(annotate.AnnotationsByStartID(filteredAnnotations))) return filteredAnnotations, nil }
func ListOpenIncidents(t miniprofiler.Timer, w http.ResponseWriter, r *http.Request) (interface{}, error) { // TODO: Retune this when we no longer store email bodies with incidents list, err := schedule.DataAccess.State().GetAllOpenIncidents() if err != nil { return nil, err } suppressor := schedule.Silenced() if suppressor == nil { return nil, fmt.Errorf("failed to get silences") } summaries := []*sched.IncidentSummaryView{} filterText := r.FormValue("filter") var parsedExpr *boolq.Tree parsedExpr, err = boolq.Parse(filterText) if err != nil { return nil, fmt.Errorf("bad filter: %v", err) } for _, iState := range list { is, err := sched.MakeIncidentSummary(schedule.RuleConf, suppressor, iState) if err != nil { return nil, err } match, err := boolq.AskParsedExpr(parsedExpr, is) if err != nil { return nil, err } if match { summaries = append(summaries, is) } } return summaries, nil }
func (s *Schedule) MarshalGroups(T miniprofiler.Timer, filter string) (*StateGroups, error) { var silenced SilenceTester T.Step("Silenced", func(miniprofiler.Timer) { silenced = s.Silenced() }) var groups map[StateTuple]States var err error status := make(States) t := StateGroups{ TimeAndDate: s.SystemConf.GetTimeAndDate(), } t.FailingAlerts, t.UnclosedErrors = s.getErrorCounts() T.Step("Setup", func(miniprofiler.Timer) { status2, err2 := s.GetOpenStates() if err2 != nil { err = err2 return } var parsedExpr *boolq.Tree parsedExpr, err2 = boolq.Parse(filter) if err2 != nil { err = err2 return } for k, v := range status2 { a := s.RuleConf.GetAlert(k.Name()) if a == nil { slog.Errorf("unknown alert %s. Force closing.", k.Name()) if err2 = s.ActionByAlertKey("bosun", "closing because alert doesn't exist.", models.ActionForceClose, k); err2 != nil { slog.Error(err2) } continue } is, err2 := MakeIncidentSummary(s.RuleConf, silenced, v) if err2 != nil { err = err2 return } match := false match, err2 = boolq.AskParsedExpr(parsedExpr, is) if err2 != nil { err = err2 return } if match { status[k] = v } } }) if err != nil { return nil, err } T.Step("GroupStates", func(T miniprofiler.Timer) { groups = status.GroupStates(silenced) }) T.Step("groups", func(T miniprofiler.Timer) { for tuple, states := range groups { var grouped []*StateGroup switch tuple.Status { case models.StWarning, models.StCritical, models.StUnknown: var sets map[string]models.AlertKeys T.Step(fmt.Sprintf("GroupSets (%d): %v", len(states), tuple), func(T miniprofiler.Timer) { sets = states.GroupSets(s.SystemConf.GetMinGroupSize()) }) for name, group := range sets { g := StateGroup{ Active: tuple.Active, Status: tuple.Status, CurrentStatus: tuple.CurrentStatus, Silenced: tuple.Silenced, Subject: fmt.Sprintf("%s - %s", tuple.Status, name), } for _, ak := range group { st := status[ak] st.Body = "" st.EmailBody = nil st.Attachments = nil g.Children = append(g.Children, &StateGroup{ Active: tuple.Active, Status: tuple.Status, Silenced: tuple.Silenced, AlertKey: ak, Alert: ak.Name(), Subject: string(st.Subject), Ago: marshalTime(st.Last().Time), State: st, IsError: !s.AlertSuccessful(ak.Name()), }) } if len(g.Children) == 1 && g.Children[0].Subject != "" { g.Subject = g.Children[0].Subject } grouped = append(grouped, &g) } default: continue } if tuple.NeedAck { t.Groups.NeedAck = append(t.Groups.NeedAck, grouped...) } else { t.Groups.Acknowledged = append(t.Groups.Acknowledged, grouped...) } } }) T.Step("sort", func(T miniprofiler.Timer) { gsort := func(grp []*StateGroup) func(i, j int) bool { return func(i, j int) bool { a := grp[i] b := grp[j] if a.Active && !b.Active { return true } else if !a.Active && b.Active { return false } if a.Status != b.Status { return a.Status > b.Status } if a.AlertKey != b.AlertKey { return a.AlertKey < b.AlertKey } return a.Subject < b.Subject } } slice.Sort(t.Groups.NeedAck, gsort(t.Groups.NeedAck)) slice.Sort(t.Groups.Acknowledged, gsort(t.Groups.Acknowledged)) }) return &t, nil }