| Index: go/src/infra/monitoring/dispatcher/dispatcher.go
|
| diff --git a/go/src/infra/monitoring/dispatcher/dispatcher.go b/go/src/infra/monitoring/dispatcher/dispatcher.go
|
| index d81ccf058ca5f0bd006c7347a13f1d65e6a8ba5a..d4bc455c486d3aef0bb068a7d010fc327d3963ec 100644
|
| --- a/go/src/infra/monitoring/dispatcher/dispatcher.go
|
| +++ b/go/src/infra/monitoring/dispatcher/dispatcher.go
|
| @@ -16,6 +16,7 @@ import (
|
| "io/ioutil"
|
| "net/http"
|
| "os"
|
| + "sort"
|
| "strings"
|
| "time"
|
|
|
| @@ -55,10 +56,7 @@ var (
|
| duration, cycle time.Duration
|
|
|
| // gk is the gatekeeper config.
|
| - gk = &struct {
|
| - // Weird. Are there ever multiple configs per master key?
|
| - Masters map[string][]messages.MasterConfig `json:"masters"`
|
| - }{}
|
| + gk = &messages.GatekeeperConfig{}
|
| // gkt is the gatekeeper trees config.
|
| gkt = map[string]messages.TreeMasterConfig{}
|
| filteredFailures = uint64(0)
|
| @@ -128,6 +126,14 @@ func fetchBuildExtracts(c client.Reader, masterNames []string) map[string]*messa
|
| return bes
|
| }
|
|
|
| +type bySeverity []messages.Alert
|
| +
|
| +func (a bySeverity) Len() int { return len(a) }
|
| +func (a bySeverity) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
| +func (a bySeverity) Less(i, j int) bool {
|
| + return a[i].Severity < a[j].Severity
|
| +}
|
| +
|
| func mainLoop(ctx context.Context, a *analyzer.Analyzer, trees map[string]bool) error {
|
| done := make(chan interface{})
|
| errs := make(chan error)
|
| @@ -153,6 +159,8 @@ func mainLoop(ctx context.Context, a *analyzer.Analyzer, trees map[string]bool)
|
| alerts.Alerts = append(alerts.Alerts, analyzeBuildExtract(a, masterName, be)...)
|
| }
|
|
|
| + sort.Sort(bySeverity(alerts.Alerts))
|
| +
|
| // Make sure we have summaries for each revision implicated in a builder failure.
|
| for _, alert := range alerts.Alerts {
|
| if bf, ok := alert.Extension.(messages.BuildFailure); ok {
|
| @@ -267,7 +275,7 @@ func main() {
|
|
|
| err = readJSONFile(*gatekeeperTreesJSON, &gkt)
|
| if err != nil {
|
| - log.Errorf("Error reading gatekeeper json: %v", err)
|
| + log.Errorf("Error reading gatekeeper trees json: %v", err)
|
| os.Exit(1)
|
| }
|
|
|
| @@ -298,16 +306,29 @@ func main() {
|
| diff := time.Now().Sub(start)
|
| return t.Add(diff)
|
| }
|
| - }
|
| + } else if *replay != "" {
|
| + f, err := os.Open(*replay)
|
| + defer f.Close()
|
| + if err != nil {
|
| + log.Errorf("Couldn't open replay dir: %s", err)
|
| + os.Exit(1)
|
| + }
|
| + stat, err := f.Stat()
|
| + if err != nil {
|
| + log.Errorf("Couldn't stat replay dir: %s", err)
|
| + os.Exit(1)
|
| + }
|
| + start := time.Now()
|
| + t := stat.ModTime()
|
|
|
| - for masterURL, masterCfgs := range gk.Masters {
|
| - if len(masterCfgs) != 1 {
|
| - log.Errorf("Multiple configs for master: %s", masterURL)
|
| + a.Now = func() time.Time {
|
| + diff := time.Now().Sub(start)
|
| + return t.Add(diff)
|
| }
|
| - masterName := masterFromURL(masterURL)
|
| - a.MasterCfgs[masterName] = masterCfgs[0]
|
| }
|
|
|
| + a.Gatekeeper = analyzer.NewGatekeeperRules(*gk)
|
| +
|
| a.MasterOnly = *masterOnly
|
| a.BuilderOnly = *builderOnly
|
| a.BuildOnly = *buildOnly
|
|
|