Skip to content
This repository has been archived by the owner on Jan 7, 2020. It is now read-only.

Commit

Permalink
Refactoring of the findStatus method
Browse files Browse the repository at this point in the history
  • Loading branch information
Simon Plourde committed Jun 8, 2015
1 parent 0b991f5 commit bccb61b
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 71 deletions.
70 changes: 65 additions & 5 deletions uchiwa/daemon/clients.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,76 @@
package daemon

import (
"fmt"

"github.com/mitchellh/mapstructure"
"github.com/palourde/logger"
"github.com/sensu/uchiwa/uchiwa/structs"
)

// buildClients constructs clients objects for frontend consumption
func (d *Daemon) buildClients() {
for _, c := range d.Data.Clients {
m := c.(map[string]interface{})
client := c.(map[string]interface{})

if m["version"] == nil {
m["version"] = "0.12.x"
if client["version"] == nil {
client["version"] = "0.12.x"
}

d.findStatus(m)
client = findClientEvents(client, &d.Data.Events)

m["acknowledged"] = IsAcknowledged(m["name"].(string), "", m["dc"].(string), d.Data.Stashes)
client["acknowledged"] = IsAcknowledged(client["name"].(string), "", client["dc"].(string), d.Data.Stashes)
}
}

// 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 {

var event structs.GenericEvent
err := mapstructure.Decode(e, &event)
if err != nil {
logger.Warningf("Could not convert the event to a generic event structure: %s", err)
continue
}

// skip this event if not the right client
if event.Client.Name != client["name"] || event.Dc != client["dc"] {
continue
}

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

results = append(results, event.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
}
83 changes: 83 additions & 0 deletions uchiwa/daemon/clients_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package daemon

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestFindClientEvents(t *testing.T) {

// no events
client := map[string]interface{}{"dc": "us-east-1", "name": "foo"}
events := []interface{}{nil}
expectedClient := map[string]interface{}{"dc": "us-east-1", "name": "foo", "status": 0}
result := findClientEvents(client, &events)
assert.Equal(t, expectedClient, result)

var statusFloat = 1.0
events = []interface{}{
map[string]interface{}{
"check": map[string]interface{}{"output": "http_critical", "status": 2},
"client": map[string]interface{}{"name": "foo"},
"dc": "us-east-1",
},
map[string]interface{}{
"check": map[string]interface{}{"output": "http_warning", "status": statusFloat},
"client": map[string]interface{}{"name": "bar"},
"dc": "us-west-1",
},
}

// event where status is a float64
client = map[string]interface{}{"dc": "us-west-1", "name": "bar"}
expectedClient = map[string]interface{}{"dc": "us-west-1", "name": "bar", "output": "http_warning", "status": 1}
result = findClientEvents(client, &events)
assert.Equal(t, expectedClient, result)

// event where status is an int
client = map[string]interface{}{"dc": "us-east-1", "name": "foo"}
expectedClient = map[string]interface{}{"dc": "us-east-1", "name": "foo", "output": "http_critical", "status": 2}
result = findClientEvents(client, &events)
assert.Equal(t, expectedClient, result)

// client has no events
client = map[string]interface{}{"dc": "us-east-1", "name": "qux"}
expectedClient = map[string]interface{}{"dc": "us-east-1", "name": "qux", "status": 0}
result = findClientEvents(client, &events)
assert.Equal(t, expectedClient, result)

// client has multiple events
newEvents := []interface{}{
map[string]interface{}{
"check": map[string]interface{}{"output": "http_critical", "status": 2},
"client": map[string]interface{}{"name": "qux"},
"dc": "us-east-1",
},
map[string]interface{}{
"check": map[string]interface{}{"output": "http_warning", "status": 1},
"client": map[string]interface{}{"name": "qux"},
"dc": "us-east-1",
},
}
events = append(events, newEvents[0])
events = append(events, newEvents[1])

client = map[string]interface{}{"dc": "us-east-1", "name": "qux"}
expectedClient = map[string]interface{}{"dc": "us-east-1", "name": "qux", "output": "http_critical and 1 more...", "status": 2}
result = findClientEvents(client, &events)
assert.Equal(t, expectedClient, result)

// event with unknown status
newEvent := map[string]interface{}{
"check": map[string]interface{}{"output": "http_unknown", "status": 3},
"client": map[string]interface{}{"name": "baz"},
"dc": "us-west-1",
}
events = append(events, newEvent)

client = map[string]interface{}{"dc": "us-west-1", "name": "baz"}
expectedClient = map[string]interface{}{"dc": "us-west-1", "name": "baz", "output": "http_unknown", "status": 3}
result = findClientEvents(client, &events)
assert.Equal(t, expectedClient, result)
}
64 changes: 0 additions & 64 deletions uchiwa/daemon/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,70 +32,6 @@ func FindDcFromInterface(data interface{}, datacenters *[]sensu.Sensu) (*sensu.S
return nil, nil, fmt.Errorf("Could not find the datacenter %s", id)
}

func (d *Daemon) findStatus(client map[string]interface{}) {
if len(d.Data.Events) == 0 {
client["status"] = 0
} else {
var criticals, warnings int
var results []string
for _, event := range d.Data.Events {
m, ok := event.(map[string]interface{})
if !ok {
logger.Warningf("Could not assert the event %+v", event)
continue
}

// skip this event if another dc
if m["dc"] != client["dc"] {
continue
}

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

// skip this event if another client
if c["name"] != client["name"] || m["dc"] != client["dc"] {
continue
}

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

results = append(results, check["output"].(string))

status := int(check["status"].(float64))
if status == 2 {
criticals++
} else if status == 1 {
warnings++
}
}

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
}
}
}

// IsAcknowledged ...
func IsAcknowledged(client string, check string, dc string, stashes []interface{}) bool {
if len(stashes) == 0 {
Expand Down
8 changes: 6 additions & 2 deletions uchiwa/structs/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,23 @@ type Generic struct {
// GenericCheck is a structure for holding a generic check
type GenericCheck struct {
Dc string `json:"dc"`
Output string `json:"output"`
Status int `json:"status"`
Subscribers []string `json:"subscribers"`
}

// GenericClient is a structure for holding a generic client
type GenericClient struct {
Dc string `json:"dc"`
Name string `json:"name"`
Subscriptions []string `json:"subscriptions"`
}

// GenericEvent is a structure for holding a generic event
type GenericEvent struct {
Dc string `json:"dc"`
Check GenericCheck `json:"check"`
Check GenericCheck `json:"check"`
Client GenericClient `json:"client"`
Dc string `json:"dc"`
}

// Health is a structure for holding health informaton about Sensu & Uchiwa
Expand Down

0 comments on commit bccb61b

Please sign in to comment.