forked from grafana/grafana
-
Notifications
You must be signed in to change notification settings - Fork 0
/
types.go
137 lines (111 loc) · 2.67 KB
/
types.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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package mqe
import (
"fmt"
"strings"
"regexp"
"github.com/grafana/grafana/pkg/log"
"github.com/grafana/grafana/pkg/tsdb"
)
type Metric struct {
Metric string
Alias string
}
type Function struct {
Func string
}
type Query struct {
Metrics []Metric
Hosts []string
Cluster []string
FunctionList []Function
AddClusterToAlias bool
AddHostToAlias bool
TimeRange *tsdb.TimeRange
UseRawQuery bool
RawQuery string
}
var (
containsWildcardPattern *regexp.Regexp = regexp.MustCompile(`\*`)
)
func (q *Query) Build(availableSeries []string) ([]QueryToSend, error) {
var queriesToSend []QueryToSend
where := q.buildWhereClause()
functions := q.buildFunctionList()
for _, metric := range q.Metrics {
alias := ""
if metric.Alias != "" {
alias = fmt.Sprintf(" {%s}", metric.Alias)
}
if !containsWildcardPattern.Match([]byte(metric.Metric)) {
rawQuery := q.renderQuerystring(metric.Metric, functions, alias, where, q.TimeRange)
queriesToSend = append(queriesToSend, QueryToSend{
RawQuery: rawQuery,
QueryRef: q,
Metric: metric,
})
} else {
m := strings.Replace(metric.Metric, "*", ".*", -1)
mp, err := regexp.Compile(m)
if err != nil {
log.Error2("failed to compile regex for ", "metric", m)
continue
}
//TODO: this lookup should be cached
for _, wildcardMatch := range availableSeries {
if mp.Match([]byte(wildcardMatch)) {
rawQuery := q.renderQuerystring(wildcardMatch, functions, alias, where, q.TimeRange)
queriesToSend = append(queriesToSend, QueryToSend{
RawQuery: rawQuery,
QueryRef: q,
Metric: metric,
})
}
}
}
}
return queriesToSend, nil
}
func (q *Query) renderQuerystring(path, functions, alias, where string, timerange *tsdb.TimeRange) string {
return fmt.Sprintf(
"`%s`%s%s %s from %v to %v",
path,
functions,
alias,
where,
q.TimeRange.GetFromAsMsEpoch(),
q.TimeRange.GetToAsMsEpoch())
}
func (q *Query) buildFunctionList() string {
functions := ""
for _, v := range q.FunctionList {
functions = fmt.Sprintf("%s|%s", functions, v.Func)
}
return functions
}
func (q *Query) buildWhereClause() string {
hasApps := len(q.Cluster) > 0
hasHosts := len(q.Hosts) > 0
where := ""
if hasHosts || hasApps {
where += "where "
}
if hasApps {
apps := strings.Join(q.Cluster, "', '")
where += fmt.Sprintf("cluster in ('%s')", apps)
}
if hasHosts && hasApps {
where += " and "
}
if hasHosts {
hosts := strings.Join(q.Hosts, "', '")
where += fmt.Sprintf("host in ('%s')", hosts)
}
return where
}
type TokenBody struct {
Metrics []string
}
type TokenResponse struct {
Success bool
Body TokenBody
}