예제 #1
0
파일: views.go 프로젝트: nicollet/bosun
func MakeIncidentSummary(c conf.RuleConfProvider, s SilenceTester, is *models.IncidentState) (*IncidentSummaryView, error) {
	alert := c.GetAlert(is.AlertKey.Name())
	if alert == nil {
		return nil, fmt.Errorf("alert %v does not exist in the configuration", is.AlertKey.Name())
	}
	warnNotifications := alert.WarnNotification.Get(c, is.AlertKey.Group())
	critNotifications := alert.CritNotification.Get(c, is.AlertKey.Group())
	eventSummaries := []EventSummary{}
	nonNormalNonUnknownCount := 0
	for _, event := range is.Events {
		if event.Status > models.StNormal && event.Status < models.StUnknown {
			nonNormalNonUnknownCount++
		}
		if eventSummary, unevaluated := MakeEventSummary(event); !unevaluated {
			eventSummaries = append(eventSummaries, eventSummary)
		}
	}
	actions := make([]EpochAction, len(is.Actions))
	for i, action := range is.Actions {
		actions[i] = MakeEpochAction(action)
	}
	subject := is.Subject
	// There is no rendered subject when the state is unknown and
	// there is no other non-normal status in the history.
	if subject == "" && nonNormalNonUnknownCount == 0 {
		subject = fmt.Sprintf("%s: %v", is.CurrentStatus, is.AlertKey)
	}
	return &IncidentSummaryView{
		Id:                     is.Id,
		Subject:                subject,
		Start:                  is.Start.Unix(),
		AlertName:              is.AlertKey.Name(),
		Tags:                   is.AlertKey.Group(),
		TagsString:             is.AlertKey.Group().String(),
		CurrentStatus:          is.CurrentStatus,
		WorstStatus:            is.WorstStatus,
		LastAbnormalStatus:     is.LastAbnormalStatus,
		LastAbnormalTime:       is.LastAbnormalTime,
		Unevaluated:            is.Unevaluated,
		NeedAck:                is.NeedAck,
		Silenced:               s(is.AlertKey) != nil,
		Actions:                actions,
		Events:                 eventSummaries,
		WarnNotificationChains: conf.GetNotificationChains(c, warnNotifications),
		CritNotificationChains: conf.GetNotificationChains(c, critNotifications),
	}, nil
}
예제 #2
0
파일: main.go 프로젝트: nicollet/bosun
func main() {
	flag.Parse()
	if *flagVersion {
		fmt.Println(version.GetVersionInfo("bosun"))
		os.Exit(0)
	}
	for _, m := range mains {
		m()
	}
	systemConf, err := conf.LoadSystemConfigFile(*flagConf)
	if err != nil {
		slog.Fatalf("couldn't read system configuration: %v", err)
	}
	sysProvider, err := systemConf.GetSystemConfProvider()
	if err != nil {
		slog.Fatal(err)
	}
	ruleConf, err := rule.ParseFile(sysProvider.GetRuleFilePath(), systemConf.EnabledBackends())
	if err != nil {
		slog.Fatalf("couldn't read rules: %v", err)
	}
	if *flagTest {
		os.Exit(0)
	}
	var ruleProvider conf.RuleConfProvider = ruleConf
	httpListen := &url.URL{
		Scheme: "http",
		Host:   sysProvider.GetHTTPListen(),
	}
	if strings.HasPrefix(httpListen.Host, ":") {
		httpListen.Host = "localhost" + httpListen.Host
	}
	if err := metadata.Init(httpListen, false); err != nil {
		slog.Fatal(err)
	}
	if err := sched.Load(sysProvider, ruleProvider, *flagSkipLast, *flagQuiet); err != nil {
		slog.Fatal(err)
	}
	if sysProvider.GetRelayListen() != "" {
		go func() {
			mux := http.NewServeMux()
			mux.Handle("/api/", util.NewSingleHostProxy(httpListen))
			s := &http.Server{
				Addr:    sysProvider.GetRelayListen(),
				Handler: mux,
			}
			slog.Fatal(s.ListenAndServe())
		}()
	}
	if sysProvider.GetTSDBHost() != "" {
		if err := collect.Init(httpListen, "bosun"); err != nil {
			slog.Fatal(err)
		}
		tsdbHost := &url.URL{
			Scheme: "http",
			Host:   sysProvider.GetTSDBHost(),
		}
		if *flagReadonly {
			rp := util.NewSingleHostProxy(tsdbHost)
			ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				if r.URL.Path == "/api/put" {
					w.WriteHeader(204)
					return
				}
				rp.ServeHTTP(w, r)
			}))
			slog.Infoln("readonly relay at", ts.URL, "to", tsdbHost)
			tsdbHost, _ = url.Parse(ts.URL)
			sysProvider.SetTSDBHost(tsdbHost.Host)
		}
	}
	if systemConf.GetPing() {
		go ping.PingHosts(sched.DefaultSched.Search, systemConf.GetPingDuration())
	}
	if sysProvider.GetInternetProxy() != "" {
		web.InternetProxy, err = url.Parse(sysProvider.GetInternetProxy())
		if err != nil {
			slog.Fatalf("InternetProxy error: %s", err)
		}
	}
	var cmdHook conf.SaveHook
	if hookPath := sysProvider.GetCommandHookPath(); hookPath != "" {
		cmdHook, err = conf.MakeSaveCommandHook(hookPath)
		if err != nil {
			slog.Fatal(err)
		}
		ruleProvider.SetSaveHook(cmdHook)
	}
	var reload func() error
	reloading := make(chan bool, 1) // a lock that we can give up acquiring
	reload = func() error {
		select {
		case reloading <- true:
			// Got lock
		default:
			return fmt.Errorf("not reloading, reload in progress")
		}
		defer func() {
			<-reloading
		}()
		newConf, err := rule.ParseFile(sysProvider.GetRuleFilePath(), sysProvider.EnabledBackends())
		if err != nil {
			return err
		}
		newConf.SetSaveHook(cmdHook)
		newConf.SetReload(reload)
		oldSched := sched.DefaultSched
		oldDA := oldSched.DataAccess
		oldSearch := oldSched.Search
		sched.Close(true)
		sched.Reset()
		newSched := sched.DefaultSched
		newSched.Search = oldSearch
		newSched.DataAccess = oldDA
		slog.Infoln("schedule shutdown, loading new schedule")

		// Load does not set the DataAccess or Search if it is already set
		if err := sched.Load(sysProvider, newConf, *flagSkipLast, *flagQuiet); err != nil {
			slog.Fatal(err)
		}
		web.ResetSchedule() // Signal web to point to the new DefaultSchedule
		go func() {
			slog.Infoln("running new schedule")
			if !*flagNoChecks {
				sched.Run()
			}
		}()
		slog.Infoln("config reload complete")
		return nil
	}

	ruleProvider.SetReload(reload)

	go func() {
		slog.Fatal(web.Listen(sysProvider.GetHTTPListen(), *flagDev, sysProvider.GetTSDBHost(), reload))
	}()
	go func() {
		if !*flagNoChecks {
			sched.Run()
		}
	}()

	go func() {
		sc := make(chan os.Signal, 1)
		signal.Notify(sc, os.Interrupt, syscall.SIGTERM)
		killing := false
		for range sc {
			if killing {
				slog.Infoln("Second interrupt: exiting")
				os.Exit(1)
			}
			killing = true
			go func() {
				slog.Infoln("Interrupt: closing down...")
				sched.Close(false)
				slog.Infoln("done")
				os.Exit(1)
			}()
		}
	}()

	if *flagWatch {
		watch(".", "*.go", quit)
		watch(filepath.Join("web", "static", "templates"), "*.html", web.RunEsc)
		base := filepath.Join("web", "static", "js")
		watch(base, "*.ts", web.RunTsc)
	}
	select {}
}