This repository has been archived by the owner on Oct 3, 2020. It is now read-only.
/
grafana.go
100 lines (90 loc) · 2.96 KB
/
grafana.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package api
import (
"encoding/json"
"net/http"
"os"
"github.com/ant0ine/go-json-rest/rest"
log "github.com/sirupsen/logrus"
"github.com/underarmour/libra/config"
"github.com/underarmour/libra/nomad"
)
type GrafanaRequest struct {
Title string `json:"title"`
State string `json:"state"`
Count int `json:"count"`
Message string `json:"message"`
EvalMatches []GrafanaEvalMatches `json:"evalMatches"`
}
type GrafanaEvalMatches struct {
Metric string `json:"metric"`
Value float64 `json:"value"`
}
type GrafanaMessageBody struct {
Job string `json:"job"`
Group string `json:"group"`
MinCount int `json:"min_count"`
MaxCount int `json:"max_count"`
MaxThreshold float64 `json:"max_threshold"`
MinThreshold float64 `json:"min_threshold"`
MaxAction string `json:"max_action"`
MinAction string `json:"min_action"`
MaxActionCount int `json:"max_action_count"`
MinActionCount int `json:"min_action_count"`
}
func GrafanaHandler(w rest.ResponseWriter, r *rest.Request) {
var t GrafanaRequest
err := r.DecodeJsonPayload(&t)
if err != nil {
log.Errorln(err)
rest.Error(w, err.Error(), http.StatusBadRequest)
return
}
defer r.Body.Close()
var mb GrafanaMessageBody
if err := json.Unmarshal([]byte(t.Message), &mb); err != nil {
log.Errorf("Problem parsing Grafana webhook json %s: %s", t.Message, err)
rest.Error(w, err.Error(), http.StatusBadRequest)
return
}
log.Infof("Received Grafana webhook: %v", t.Message)
config, err := config.NewConfig(os.Getenv("LIBRA_CONFIG_DIR"))
if err != nil {
log.Errorf("Failed to read or parse config file: %s", err)
rest.Error(w, err.Error(), http.StatusInternalServerError)
}
log.Info("Loaded and parsed configuration file")
n, err := nomad.NewClient(config.Nomad)
if err != nil {
log.Errorf("Failed to create Nomad Client: %s", err)
rest.Error(w, err.Error(), http.StatusInternalServerError)
}
log.Info("Successfully created Nomad Client")
var amount int
// TODO: Right now this only grabs the first match. Really, we should take all of them and average them together
if len(t.EvalMatches) == 0 {
log.Infof("Alert %s has been cleared. Doing nothing...", t.Title)
return
}
if t.EvalMatches[0].Value < mb.MinThreshold {
amount = -mb.MinActionCount
} else if t.EvalMatches[0].Value > mb.MaxThreshold {
amount = mb.MaxActionCount
} else {
w.WriteHeader(http.StatusOK)
return
}
evalID, newCount, err := nomad.Scale(n, mb.Job, mb.Group, amount, mb.MinCount, mb.MaxCount)
if err != nil {
log.Error("Problem scaling the task group " + err.Error())
rest.Error(w, err.Error(), http.StatusInternalServerError)
} else {
log.Infoln("Scaled it! Evaluation " + evalID)
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
respBody := &ScaleResponse{
Eval: evalID,
NewCount: newCount,
}
w.WriteJson(respBody)
}
}