forked from moira-alert/moira
-
Notifications
You must be signed in to change notification settings - Fork 0
/
trigger_render.go
101 lines (94 loc) · 3.47 KB
/
trigger_render.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
101
package handler
import (
"fmt"
"net/http"
"strconv"
"time"
"github.com/go-chi/render"
"github.com/go-graphite/carbonapi/date"
"github.com/go-graphite/carbonapi/expr/types"
"github.com/wcharczuk/go-chart"
"github.com/moira-alert/moira"
"github.com/moira-alert/moira/api"
"github.com/moira-alert/moira/api/controller"
"github.com/moira-alert/moira/api/middleware"
"github.com/moira-alert/moira/plotting"
"github.com/moira-alert/moira/remote"
)
func renderTrigger(writer http.ResponseWriter, request *http.Request) {
remoteCfg, from, to, triggerID, fetchRealtimeData, err := getEvaluationParameters(request)
if err != nil {
render.Render(writer, request, api.ErrorInvalidRequest(err))
return
}
metricsData, trigger, err := evaluateTriggerMetrics(remoteCfg, from, to, triggerID, fetchRealtimeData)
if err != nil {
render.Render(writer, request, api.ErrorInternalServer(err))
return
}
renderable, err := buildRenderable(request, trigger, metricsData)
if err != nil {
render.Render(writer, request, api.ErrorInternalServer(err))
return
}
writer.Header().Set("Content-Type", "image/png")
err = renderable.Render(chart.PNG, writer)
if err != nil {
render.Render(writer, request, api.ErrorInternalServer(fmt.Errorf("can not render plot %s", err.Error())))
}
}
func getEvaluationParameters(request *http.Request) (remoteCfg *remote.Config, from int64, to int64, triggerID string, fetchRealtimeData bool, err error) {
remoteCfg = middleware.GetRemoteConfig(request)
triggerID = middleware.GetTriggerID(request)
fromStr := middleware.GetFromStr(request)
toStr := middleware.GetToStr(request)
from = date.DateParamToEpoch(fromStr, "UTC", 0, time.UTC)
if from == 0 {
return remoteCfg, 0, 0, "", false, fmt.Errorf("can not parse from: %s", fromStr)
}
to = date.DateParamToEpoch(toStr, "UTC", 0, time.UTC)
if to == 0 {
return remoteCfg, 0, 0, "", false, fmt.Errorf("can not parse to: %s", fromStr)
}
realtime := request.URL.Query().Get("realtime")
if realtime == "" {
return
}
fetchRealtimeData, err = strconv.ParseBool(realtime)
if err != nil {
return remoteCfg, 0, 0, "", false, fmt.Errorf("invalid realtime param: %s", err.Error())
}
return
}
func evaluateTriggerMetrics(remoteCfg *remote.Config, from, to int64, triggerID string, fetchRealtimeData bool) ([]*types.MetricData, *moira.Trigger, error) {
tts, trigger, err := controller.GetTriggerEvaluationResult(database, remoteCfg, from, to, triggerID, fetchRealtimeData)
if err != nil {
return nil, trigger, err
}
var metricsData = make([]*types.MetricData, 0, len(tts.Main)+len(tts.Additional))
for _, ts := range tts.Main {
metricsData = append(metricsData, &ts.MetricData)
}
for _, ts := range tts.Additional {
metricsData = append(metricsData, &ts.MetricData)
}
return metricsData, trigger, err
}
func buildRenderable(request *http.Request, trigger *moira.Trigger, metricsData []*types.MetricData) (*chart.Chart, error) {
timezone := request.URL.Query().Get("timezone")
location, err := time.LoadLocation(timezone)
if err != nil {
return nil, fmt.Errorf("failed to load %s timezone: %s", timezone, err.Error())
}
plotTheme := request.URL.Query().Get("theme")
plotTemplate, err := plotting.GetPlotTemplate(plotTheme, location)
if err != nil {
return nil, fmt.Errorf("can not initialize plot theme %s", err.Error())
}
var metricsWhiteList = make([]string, 0)
renderable, err := plotTemplate.GetRenderable(trigger, metricsData, metricsWhiteList)
if err != nil {
return nil, err
}
return &renderable, err
}