示例#1
0
文件: helpers.go 项目: cgeers/uchiwa
// BuildEventsMetrics builds the metrics for the events
func BuildEventsMetrics(events *[]interface{}) *structs.StatusMetrics {
	metrics := structs.StatusMetrics{}

	metrics.Total = len(*events)

	for _, e := range *events {
		event := e.(map[string]interface{})

		check, ok := event["check"].(map[string]interface{})
		if !ok {
			logger.Warningf("Could not assert this check to an interface: %+v", event["check"])
			continue
		}

		status, ok := check["status"].(float64)
		if !ok {
			logger.Warningf("Could not assert this status to a flot64: %+v", check["status"])
			continue
		}

		if status == 2.0 {
			metrics.Critical++
			continue
		} else if status == 1.0 {
			metrics.Warning++
			continue
		}
		metrics.Unknown++
	}

	return &metrics
}
示例#2
0
func initSensu(apis []SensuConfig) []SensuConfig {
	for i, api := range apis {
		// Set a datacenter name if missing
		if api.Name == "" {
			logger.Warningf("Sensu API %s has no name property, make sure to set it in your configuration. Generating a temporary one...", api.URL)
			apis[i].Name = fmt.Sprintf("sensu-%v", rand.Intn(100))
		}

		// Escape special characters in DC name
		r := strings.NewReplacer(":", "", "/", "", ";", "", "?", "")
		apis[i].Name = r.Replace(apis[i].Name)

		// Make sure the host is not empty
		if api.Host == "" {
			logger.Fatalf("Sensu API %q Host is missing", api.Name)
		}

		// Determine the protocol to use
		prot := "http"
		if api.Ssl {
			prot += "s"
		}

		// Set the API URL
		apis[i].URL = fmt.Sprintf("%s://%s:%d%s", prot, api.Host, api.Port, api.Path)
	}
	return apis
}
示例#3
0
文件: helpers.go 项目: cgeers/uchiwa
// BuildClientsMetrics builds the metrics for the events
func BuildClientsMetrics(clients *[]interface{}) *structs.StatusMetrics {
	metrics := structs.StatusMetrics{}

	metrics.Total = len(*clients)

	for _, c := range *clients {
		client := c.(map[string]interface{})

		status, ok := client["status"].(int)
		if !ok {
			logger.Warningf("Could not assert this status to an int: %+v", client["status"])
			continue
		}

		if status == 2.0 {
			metrics.Critical++
			continue
		} else if status == 1.0 {
			metrics.Warning++
			continue
		} else if status == 0.0 {
			continue
		}
		metrics.Unknown++
	}

	return &metrics
}
示例#4
0
文件: config.go 项目: jsoriano/uchiwa
func (c *Config) initSensu() {
	for i, api := range c.Sensu {
		prot := "http"
		if api.Name == "" {
			logger.Warningf("Sensu API %s has no name property. Generating random one...", api.URL)
			c.Sensu[i].Name = fmt.Sprintf("sensu-%v", rand.Intn(100))
		}
		// escape special characters in DC name
		r := strings.NewReplacer(":", "", "/", "", ";", "", "?", "")
		c.Sensu[i].Name = r.Replace(api.Name)

		if api.Host == "" {
			logger.Fatalf("Sensu API %q Host is missing", api.Name)
		}
		if api.Timeout == 0 {
			c.Sensu[i].Timeout = 10
		} else if api.Timeout >= 1000 { // backward compatibility with < 0.3.0 version
			c.Sensu[i].Timeout = api.Timeout / 1000
		}
		if api.Port == 0 {
			c.Sensu[i].Port = 4567
		}
		if api.Ssl {
			prot += "s"
		}
		c.Sensu[i].URL = fmt.Sprintf("%s://%s:%d%s", prot, api.Host, c.Sensu[i].Port, api.Path)
	}
}
示例#5
0
// WebServer starts the web server and serves GET & POST requests
func (u *Uchiwa) WebServer(publicPath *string, auth auth.Config) {
	// Private endpoints
	http.Handle("/aggregates", auth.Authenticate(http.HandlerFunc(u.aggregatesHandler)))
	http.Handle("/aggregates/", auth.Authenticate(http.HandlerFunc(u.aggregatesHandler)))
	http.Handle("/checks", auth.Authenticate(http.HandlerFunc(u.checksHandler)))
	http.Handle("/clients", auth.Authenticate(http.HandlerFunc(u.clientsHandler)))
	http.Handle("/clients/", auth.Authenticate(http.HandlerFunc(u.clientsHandler)))
	http.Handle("/config", auth.Authenticate(http.HandlerFunc(u.configHandler)))
	http.Handle("/datacenters", auth.Authenticate(http.HandlerFunc(u.datacentersHandler)))
	http.Handle("/events", auth.Authenticate(http.HandlerFunc(u.eventsHandler)))
	http.Handle("/events/", auth.Authenticate(http.HandlerFunc(u.eventsHandler)))
	http.Handle("/request", auth.Authenticate(http.HandlerFunc(u.requestHandler)))
	http.Handle("/results/", auth.Authenticate(http.HandlerFunc(u.resultsHandler)))
	http.Handle("/stashes", auth.Authenticate(http.HandlerFunc(u.stashesHandler)))
	http.Handle("/stashes/", auth.Authenticate(http.HandlerFunc(u.stashesHandler)))
	http.Handle("/subscriptions", auth.Authenticate(http.HandlerFunc(u.subscriptionsHandler)))
	if u.Config.Uchiwa.Enterprise == false {
		http.Handle("/metrics", auth.Authenticate(http.HandlerFunc(u.metricsHandler)))
	}

	// Static files
	http.Handle("/", http.FileServer(http.Dir(*publicPath)))

	// Public endpoints
	http.Handle("/config/", http.HandlerFunc(u.configHandler))
	http.Handle("/health", http.HandlerFunc(u.healthHandler))
	http.Handle("/health/", http.HandlerFunc(u.healthHandler))
	http.Handle("/login", auth.GetIdentification())

	listen := fmt.Sprintf("%s:%d", u.Config.Uchiwa.Host, u.Config.Uchiwa.Port)
	logger.Warningf("Uchiwa is now listening on %s", listen)
	logger.Fatal(http.ListenAndServe(listen, nil))
}
示例#6
0
func setDc(v interface{}, dc string) {
	m, ok := v.(map[string]interface{})
	if !ok {
		logger.Warningf("Could not assert interface: %+v", v)
	} else {
		m["dc"] = dc
	}
}
示例#7
0
func (u *Uchiwa) buildClientHistory(client, dc string, history []interface{}) []interface{} {
	for _, h := range history {
		m, ok := h.(map[string]interface{})
		if !ok {
			logger.Warningf("Could not assert this client history to an interface: %+v", h)
			continue
		}

		// Set some attributes for easier frontend consumption
		check, ok := m["check"].(string)
		if !ok {
			continue
		}
		m["client"] = client
		m["dc"] = dc
		m["acknowledged"] = helpers.IsAcknowledged(check, client, dc, u.Data.Stashes)

		// Add missing attributes to last_result object
		if m["last_result"] != nil {
			if m["last_status"] == 0.0 {
				continue
			}

			event, err := helpers.GetEvent(check, client, dc, &u.Data.Events)
			if err != nil {
				continue
			}

			lastResult, ok := m["last_result"].(map[string]interface{})
			if !ok {
				continue
			}

			if event["action"] != nil {
				lastResult["action"] = event["action"]
			}
			if event["occurrences"] != nil {
				lastResult["occurrences"] = event["occurrences"]
			}
		}

		// Maintain backward compatiblity with Sensu <= 0.17
		// by constructing the last_result object
		if m["last_status"] != nil && m["last_status"] != 0.0 {
			event, err := helpers.GetEvent(check, client, dc, &u.Data.Events)
			if err != nil {
				continue
			}
			m["last_result"] = event
		} else {
			m["last_result"] = map[string]interface{}{"last_execution": m["last_execution"], "status": m["last_status"]}
		}
	}

	return history
}
示例#8
0
func (u *Uchiwa) findOutput(id *string, h map[string]interface{}, dc *string) string {
	if h["last_status"] == 0 {
		return ""
	}

	for _, e := range u.Data.Events {
		// does the dc match?
		m, ok := e.(map[string]interface{})
		if !ok {
			logger.Warningf("Could not assert this event to an interface %+v", e)
			continue
		}
		if m["dc"] != *dc {
			continue
		}

		// does the client match?
		c, ok := m["client"].(map[string]interface{})
		if !ok {
			logger.Warningf("Could not assert this client to an interface: %+v", c)
			continue
		}

		if c["name"] != *id {
			continue
		}

		// does the check match?
		k := m["check"].(map[string]interface{})
		if !ok {
			logger.Warningf("Could not assert this check to an interface: %+v", k)
			continue
		}
		if k["name"] != h["check"] {
			continue
		}
		return k["output"].(string)
	}

	return ""
}
示例#9
0
// FindDcFromInterface ...
func FindDcFromInterface(data interface{}, datacenters *[]sensu.Sensu) (*sensu.Sensu, map[string]interface{}, error) {
	m, ok := data.(map[string]interface{})
	if !ok {
		logger.Warningf("Type assertion failed. Could not assert the given interface into a map: %+v", data)
		return nil, nil, errors.New("Could not determine the datacenter.")
	}

	id := m["dc"].(string)
	if id == "" {
		logger.Warningf("The received interface does not contain any datacenter information: ", data)
		return nil, nil, errors.New("Could not determine the datacenter.")
	}

	for _, dc := range *datacenters {
		if dc.Name == id {
			return &dc, m, nil
		}
	}

	logger.Warningf("Could not find the datacenter %s into %+v: ", id, data)
	return nil, nil, fmt.Errorf("Could not find the datacenter %s", id)
}
示例#10
0
func findModel(id string, dc string, checks []interface{}) map[string]interface{} {
	for _, k := range checks {
		m, ok := k.(map[string]interface{})
		if !ok {
			logger.Warningf("Could not assert check interface %+v", k)
			continue
		}
		if m["name"] == id && m["dc"] == dc {
			return m
		}
	}
	return nil
}
示例#11
0
func (u *Uchiwa) findClientInClients(id *string, dc *string) (map[string]interface{}, error) {
	for _, c := range u.Data.Clients {
		m, ok := c.(map[string]interface{})
		if !ok {
			logger.Warningf("Could not assert this client to an interface %+v", c)
			continue
		}
		if m["name"] == *id && m["dc"] == *dc {
			return m, nil
		}
	}
	return nil, fmt.Errorf("Could not find client %s", *id)
}
示例#12
0
func (s *Sensu) getSlice(endpoint string, limit int) ([]interface{}, error) {
	apis := shuffle(s.APIs)

	for i := 0; i < len(apis); i++ {
		logger.Debugf("GET %s/%s", s.APIs[i].URL, endpoint)
		slice, err := apis[i].getSlice(endpoint, limit)
		if err == nil {
			return slice, err
		}
		logger.Warningf("GET %s/%s returned: %v", s.APIs[i].URL, endpoint, err)
	}

	return nil, errors.New("")
}
示例#13
0
func (s *Sensu) postPayload(endpoint string, payload string) (map[string]interface{}, error) {
	apis := shuffle(s.APIs)

	for i := 0; i < len(apis); i++ {
		logger.Debugf("POST %s/%s", s.APIs[i].URL, endpoint)
		m, err := apis[i].postPayload(endpoint, payload)
		if err == nil {
			return m, err
		}
		logger.Warningf("POST %s/%s returned: %v", s.APIs[i].URL, endpoint, err)
	}

	return nil, errors.New("")
}
示例#14
0
func (s *Sensu) getBytes(endpoint string) ([]byte, *http.Response, error) {
	apis := shuffle(s.APIs)

	for i := 0; i < len(apis); i++ {
		logger.Debugf("GET %s/%s", s.APIs[i].URL, endpoint)
		bytes, res, err := apis[i].getBytes(endpoint)
		if err == nil {
			return bytes, res, err
		}
		logger.Warningf("GET %s/%s returned: %v", s.APIs[i].URL, endpoint, err)
	}

	return nil, nil, errors.New("")
}
示例#15
0
func (s *Sensu) delete(endpoint string) error {
	apis := shuffle(s.APIs)

	var err error
	for i := 0; i < len(apis); i++ {
		logger.Infof("DELETE %s/%s", s.APIs[i].URL, endpoint)
		err = apis[i].delete(endpoint)
		if err == nil {
			return err
		}
		logger.Warningf("DELETE %s/%s returned: %v", s.APIs[i].URL, endpoint, err)
	}

	return err
}
示例#16
0
// loadFile loads a Config struct from a configuration file
func loadFile(path string) (*Config, error) {
	logger.Warningf("Loading the configuration file %s", path)

	c := new(Config)
	file, err := os.Open(path)
	if err != nil {
		if len(path) > 1 {
			return nil, fmt.Errorf("Error: could not read config file %s.", path)
		}
	}

	decoder := json.NewDecoder(file)
	err = decoder.Decode(c)
	if err != nil {
		return nil, fmt.Errorf("Error decoding file %s: %s", path, err)
	}

	return c, nil
}
示例#17
0
// Stashes
func (u *Uchiwa) stashesHandler(w http.ResponseWriter, r *http.Request) {
	token := auth.GetTokenFromContext(r)
	resources := strings.Split(r.URL.Path, "/")

	// DELETE on /stashes/{dc}/{path}
	if r.Method == "DELETE" && len(resources) >= 3 {
		dc := resources[2]
		path := strings.Join(resources[3:], "/")

		if dc == "" || path == "" {
			http.Error(w, "", http.StatusBadRequest)
			return
		}

		unauthorized := FilterGetRequest(dc, token)
		if unauthorized {
			http.Error(w, fmt.Sprint(""), http.StatusNotFound)
			return
		}

		err := u.DeleteStash(dc, path)
		if err != nil {
			logger.Warningf("Could not delete the stash '%s': %s", path, err)
			http.Error(w, "Could not create the stash", http.StatusNotFound)
			return
		}
	} else if r.Method == "GET" {
		// GET on /stashes
		stashes := FilterStashes(&u.Data.Stashes, token)

		// Create header
		w.Header().Add("Accept-Charset", "utf-8")
		w.Header().Add("Content-Type", "application/json")
		w.Header().Set("Content-Encoding", "gzip")

		gz := gzip.NewWriter(w)
		defer gz.Close()
		if err := json.NewEncoder(gz).Encode(stashes); err != nil {
			http.Error(w, fmt.Sprintf("Cannot encode response data: %v", err), http.StatusInternalServerError)
			return
		}
		return
	} else if r.Method == "POST" {
		// POST on /stashes
		decoder := json.NewDecoder(r.Body)
		var data stash
		err := decoder.Decode(&data)
		if err != nil {
			http.Error(w, "Could not decode body", http.StatusInternalServerError)
			return
		}

		// verify that the authenticated user is authorized to access this resource
		unauthorized := FilterGetRequest(data.Dc, token)
		if unauthorized {
			http.Error(w, fmt.Sprint(""), http.StatusNotFound)
			return
		}

		if token != nil && token.Claims["Username"] != nil {
			data.Content["username"] = token.Claims["Username"]
		}

		err = u.PostStash(data)
		if err != nil {
			http.Error(w, "Could not create the stash", http.StatusNotFound)
			return
		}
	} else {
		http.Error(w, "", http.StatusBadRequest)
		return
	}
}
示例#18
0
// GetIdentification retrieves the user & pass from a POST and authenticates the user against the Identification driver
func (a *Config) GetIdentification() http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method != "POST" {
			http.Redirect(w, r, "/#/login", http.StatusFound)
			return
		}

		decoder := json.NewDecoder(r.Body)
		var data interface{}
		err := decoder.Decode(&data)
		if err != nil {
			logger.Warningf("Could not decode the body: %s", err)
			http.Error(w, "", http.StatusInternalServerError)
			return
		}

		m, ok := data.(map[string]interface{})
		if !ok {
			logger.Warningf("Could not assert the body: %s", err)
			http.Error(w, "", http.StatusInternalServerError)
			return
		}

		u := m["user"].(string)
		p := m["pass"].(string)
		if u == "" || p == "" {
			logger.Info("Authentication failed: user and password must not be empty")
			http.Error(w, "", http.StatusUnauthorized)
			return
		}

		// validate the user with the Login authentication driver
		user, err := a.Driver(u, p)
		if err != nil {
			message := fmt.Sprintf("Authentication failed: %s", err)

			// Output to stdout
			logger.Info(message)

			// Output to audit log
			log := structs.AuditLog{Action: "loginfailure", Level: "default", Output: message}
			log.RemoteAddr = helpers.GetIP(r)
			audit.Log(log)

			http.Error(w, "", http.StatusUnauthorized)
			return
		}

		// obfuscate the user's salt & hash
		user.PasswordHash = ""
		user.PasswordSalt = ""

		token, err := GetToken(&user.Role, u)
		if err != nil {
			logger.Warningf("Authentication failed, could not create the token: %s", err)
			http.Error(w, "", http.StatusInternalServerError)
			return
		}

		// Add token to the user struct
		user.Token = token

		j, err := json.Marshal(user)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		w.Header().Set("Content-Type", "application/json")
		w.Write(j)
		return
	})
}
示例#19
0
文件: events.go 项目: jsoriano/uchiwa
// BuildEvents constructs events objects for frontend consumption
func (d *Daemon) buildEvents() {
	for _, e := range d.Data.Events {
		m := e.(map[string]interface{})

		// build backward compatible event object for Sensu < 0.13.0
		if m["id"] == nil {

			// build client object
			c := m["client"]
			delete(m, "client")
			m["client"] = map[string]interface{}{"name": c}

			// build check object
			c = m["check"]
			delete(m, "check")
			m["check"] = map[string]interface{}{"name": c, "issued": m["issued"], "output": m["output"], "status": m["status"]}

			// is flapping?
			if m["action"] == false {
				m["action"] = "create"
			} else {
				m["action"] = "flapping"
			}

			// remove old entries
			delete(m, "issued")
			delete(m, "output")
			delete(m, "status")
		}

		// we assume the event isn't acknowledged in case we can't assert the following values
		m["acknowledged"] = false

		// get client name
		c, ok := m["client"].(map[string]interface{})
		if !ok {
			logger.Warningf("Could not assert event's client interface from %+v", c)
			continue
		}

		clientName, ok := c["name"].(string)
		if !ok {
			logger.Warningf("Could not assert event's client name from %+v", c)
			continue
		}

		// get check name
		k, ok := m["check"].(map[string]interface{})
		if !ok {
			logger.Warningf("Could not assert event's check interface from %+v", k)
			continue
		}

		checkName, ok := k["name"].(string)
		if !ok {
			logger.Warningf("Could not assert event's check name from %+v", k)
			continue
		}

		// get dc name
		dcName, ok := m["dc"].(string)
		if !ok {
			logger.Warningf("Could not assert event's datacenter name from %+v", m)
			continue
		}

		// determine if the event is acknowledged
		m["acknowledged"] = IsAcknowledged(clientName, checkName, dcName, d.Data.Stashes)

		// detertermine if the client is acknowledged
		m["client"].(map[string]interface{})["acknowledged"] = IsAcknowledged(clientName, "", dcName, d.Data.Stashes)
	}
}
示例#20
0
文件: daemon.go 项目: nhooey/uchiwa
// getData retrieves all endpoints for every datacenter
func (d *Daemon) fetchData() {
	d.Data.Health.Sensu = make(map[string]structs.SensuHealth, len(*d.Datacenters))

	for _, datacenter := range *d.Datacenters {
		logger.Infof("Updating the datacenter %s", datacenter.Name)

		// set default health status
		d.Data.Health.Sensu[datacenter.Name] = structs.SensuHealth{Output: datacenterErrorString, Status: 2}
		d.Data.Health.Uchiwa = "ok"

		// fetch sensu data from the datacenter
		stashes, err := datacenter.GetStashes()
		if err != nil {
			logger.Warningf("Connection failed to the datacenter %s", datacenter.Name)
			continue
		}
		checks, err := datacenter.GetChecks()
		if err != nil {
			logger.Warningf("Connection failed to the datacenter %s", datacenter.Name)
			continue
		}
		clients, err := datacenter.GetClients()
		if err != nil {
			logger.Warningf("Connection failed to the datacenter %s", datacenter.Name)
			continue
		}
		events, err := datacenter.GetEvents()
		if err != nil {
			logger.Warningf("Connection failed to the datacenter %s", datacenter.Name)
			continue
		}
		info, err := datacenter.GetInfo()
		if err != nil {
			logger.Warningf("Connection failed to the datacenter %s", datacenter.Name)
			continue
		}
		aggregates, err := datacenter.GetAggregates()
		if err != nil {
			logger.Warningf("Connection failed to the datacenter %s", datacenter.Name)
			continue
		}

		if d.Enterprise {
			d.Data.SERawMetrics = *getEnterpriseMetrics(&datacenter, &d.Data.SERawMetrics)
		}

		// Determine the status of the datacenter
		if !info.Redis.Connected {
			d.Data.Health.Sensu[datacenter.Name] = structs.SensuHealth{Output: "Not connected to Redis", Status: 1}
		} else if !info.Transport.Connected {
			d.Data.Health.Sensu[datacenter.Name] = structs.SensuHealth{Output: "Not connected to the transport", Status: 1}
		} else {
			d.Data.Health.Sensu[datacenter.Name] = structs.SensuHealth{Output: "ok", Status: 0}
		}

		// add fetched data into d.Data interface
		for _, v := range stashes {
			setDc(v, datacenter.Name)
			d.Data.Stashes = append(d.Data.Stashes, v)
		}
		for _, v := range checks {
			setDc(v, datacenter.Name)
			d.Data.Checks = append(d.Data.Checks, v)
		}
		for _, v := range clients {
			setDc(v, datacenter.Name)
			d.Data.Clients = append(d.Data.Clients, v)
		}
		for _, v := range events {
			setDc(v, datacenter.Name)
			d.Data.Events = append(d.Data.Events, v)
		}
		for _, v := range aggregates {
			setDc(v, datacenter.Name)
			d.Data.Aggregates = append(d.Data.Aggregates, v)
		}

		// build datacenter
		dc := d.buildDatacenter(&datacenter.Name, info)
		dc.Stats["aggregates"] = len(aggregates)
		dc.Stats["checks"] = len(checks)
		dc.Stats["clients"] = len(clients)
		dc.Stats["events"] = len(events)
		dc.Stats["stashes"] = len(stashes)
		d.Data.Dc = append(d.Data.Dc, dc)
	}
}
示例#21
0
// getData retrieves all endpoints for every datacenter
func (d *Daemon) fetchData() {
	d.Data.Health.Sensu = make(map[string]structs.SensuHealth, len(*d.Datacenters))

	for _, datacenter := range *d.Datacenters {
		logger.Infof("Updating the datacenter %s", datacenter.Name)

		// set default health status
		d.Data.Health.Sensu[datacenter.Name] = structs.SensuHealth{Output: datacenterErrorString, Status: 2}
		d.Data.Health.Uchiwa = "ok"

		// fetch sensu data from the datacenter
		stashes, err := datacenter.GetStashes()
		if err != nil {
			logger.Warningf("Connection failed to the datacenter %s", datacenter.Name)
			continue
		}
		checks, err := datacenter.GetChecks()
		if err != nil {
			logger.Warningf("Connection failed to the datacenter %s", datacenter.Name)
			continue
		}
		clients, err := datacenter.GetClients()
		if err != nil {
			logger.Warningf("Connection failed to the datacenter %s", datacenter.Name)
			continue
		}
		events, err := datacenter.GetEvents()
		if err != nil {
			logger.Warningf("Connection failed to the datacenter %s", datacenter.Name)
			continue
		}
		info, err := datacenter.GetInfo()
		if err != nil {
			logger.Warningf("Connection failed to the datacenter %s", datacenter.Name)
			continue
		}
		aggregates, err := datacenter.GetAggregates()
		if err != nil {
			logger.Warningf("Connection failed to the datacenter %s", datacenter.Name)
			continue
		}

		if d.Enterprise {
			hasMetrics := true
			metrics := make(map[string]*structs.SERawMetric)
			metricsEndpoints := []string{"clients", "events", "keepalives_avg_60", "check_requests", "results"}

			for _, metric := range metricsEndpoints {
				metrics[metric], err = datacenter.Metric(metric)
				if err != nil {
					logger.Warningf("Could not retrieve the %s metrics. Discarding all metrics for the datacenter %s", metric, datacenter.Name)
					hasMetrics = false
					break
				}
			}

			if hasMetrics {
				metrics["events"].Name = datacenter.Name
				d.Data.SERawMetrics.Clients = append(d.Data.SERawMetrics.Clients, metrics["clients"])
				d.Data.SERawMetrics.Events = append(d.Data.SERawMetrics.Events, metrics["events"])
				d.Data.SERawMetrics.KeepalivesAVG60 = append(d.Data.SERawMetrics.KeepalivesAVG60, metrics["keepalives_avg_60"])
				d.Data.SERawMetrics.Requests = append(d.Data.SERawMetrics.Requests, metrics["check_requests"])
				d.Data.SERawMetrics.Results = append(d.Data.SERawMetrics.Results, metrics["results"])
			}
		}

		// Determine the status of the datacenter
		if !info.Redis.Connected {
			d.Data.Health.Sensu[datacenter.Name] = structs.SensuHealth{Output: "Not connected to Redis", Status: 1}
		} else if !info.Transport.Connected {
			d.Data.Health.Sensu[datacenter.Name] = structs.SensuHealth{Output: "Not connected to the transport", Status: 1}
		} else {
			d.Data.Health.Sensu[datacenter.Name] = structs.SensuHealth{Output: "ok", Status: 0}
		}

		// add fetched data into d.Data interface
		for _, v := range stashes {
			setDc(v, datacenter.Name)
			d.Data.Stashes = append(d.Data.Stashes, v)
		}
		for _, v := range checks {
			setDc(v, datacenter.Name)
			d.Data.Checks = append(d.Data.Checks, v)
		}
		for _, v := range clients {
			setDc(v, datacenter.Name)
			d.Data.Clients = append(d.Data.Clients, v)
		}
		for _, v := range events {
			setDc(v, datacenter.Name)
			d.Data.Events = append(d.Data.Events, v)
		}
		for _, v := range aggregates {
			setDc(v, datacenter.Name)
			d.Data.Aggregates = append(d.Data.Aggregates, v)
		}

		// build datacenter
		dc := d.buildDatacenter(&datacenter.Name, info)
		dc.Stats["aggregates"] = len(aggregates)
		dc.Stats["checks"] = len(checks)
		dc.Stats["clients"] = len(clients)
		dc.Stats["events"] = len(events)
		dc.Stats["stashes"] = len(stashes)
		d.Data.Dc = append(d.Data.Dc, dc)
	}
}
示例#22
0
// findClientEvents searches for all events related to a particular client
// and set the status and output attributes of this client based on the events found
func findClientEvents(client map[string]interface{}, events *[]interface{}) map[string]interface{} {
	if len(*events) == 0 {
		client["status"] = 0
	} else {
		var criticals, warnings int
		var results []string
		for _, e := range *events {

			eventMap, ok := e.(map[string]interface{})
			if !ok {
				logger.Warningf("Could not convert the event to a map: %+v", eventMap)
				continue
			}

			// skip this event if the check attribute does not exist
			if eventMap["check"] == nil {
				continue
			}

			// skip this event if the datacenter isn't the right one
			if eventMap["dc"] == nil || eventMap["dc"] != client["dc"] {
				continue
			}

			clientMap, ok := eventMap["client"].(map[string]interface{})
			if !ok {
				logger.Warningf("Could not convert the event's client to a map: %+v", eventMap)
				continue
			}

			// skip this event if the client isn't the right one
			if clientMap["name"] == nil || clientMap["name"] != client["name"] {
				continue
			}

			// convert the check to a structure for easier handling
			var check structs.GenericCheck
			err := mapstructure.Decode(eventMap["check"], &check)
			if err != nil {
				logger.Warningf("Could not convert the event's check to a generic check structure: %s", err)
				continue
			}

			if check.Status == 2 {
				criticals++
			} else if check.Status == 1 {
				warnings++
			}

			results = append(results, check.Output)
		}

		if len(results) == 0 {
			client["status"] = 0
		} else if criticals > 0 {
			client["status"] = 2
		} else if warnings > 0 {
			client["status"] = 1
		} else {
			client["status"] = 3
		}

		if len(results) == 1 {
			client["output"] = results[0]
		} else if len(results) > 1 {
			output := fmt.Sprintf("%s and %d more...", results[0], (len(results) - 1))
			client["output"] = output
		}
	}

	return client
}