Skip to content

Commit 5d0f79a

Browse files
author
Vladimir Smirnov
authored
Merge pull request #472 from rodio/graphite-promql
Enhance convertGraphiteTargetToPromQL()
2 parents 5013ad7 + 1339372 commit 5d0f79a

File tree

2 files changed

+48
-23
lines changed

2 files changed

+48
-23
lines changed

zipper/protocols/prometheus/prometheus_group.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ func (c *PrometheusGroup) Fetch(ctx context.Context, request *protov3.MultiFetch
217217
stepLocalStr, target = c.seriesByTagToPromQL(stepLocalStr, target)
218218
} else {
219219
reQuery := convertGraphiteTargetToPromQL(target)
220-
target = "{__name__=~\"" + reQuery + "\"}"
220+
target = fmt.Sprintf("{__name__=~%q}", reQuery)
221221
}
222222
if stepLocalStr[len(stepLocalStr)-1] >= '0' && stepLocalStr[len(stepLocalStr)-1] <= '9' {
223223
stepLocalStr += "s"
@@ -334,8 +334,12 @@ func (c *PrometheusGroup) Find(ctx context.Context, request *protov3.MultiGlobRe
334334
uniqueMetrics := make(map[string]bool)
335335
for _, query := range request.Metrics {
336336
// Convert query to Prometheus-compatible regex
337+
if !strings.HasSuffix(query, "*") {
338+
query = query + "*"
339+
}
340+
337341
reQuery := convertGraphiteTargetToPromQL(query)
338-
matchQuery := "{__name__=~\"" + reQuery + "\"}"
342+
matchQuery := fmt.Sprintf("{__name__=~%q}", reQuery)
339343
v := url.Values{
340344
"match[]": []string{matchQuery},
341345
}

zipper/protocols/prometheus/prometheus_helper.go

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"encoding/json"
55
"fmt"
66
"math"
7+
"regexp"
78
"sort"
89
"strconv"
910
"strings"
@@ -191,32 +192,52 @@ func (c *PrometheusGroup) seriesByTagToPromQL(step, target string) (string, stri
191192
}
192193

193194
func convertGraphiteTargetToPromQL(query string) string {
194-
// Special case for query for "*", which is used to get top level metric parts
195-
if query == "*" {
196-
return ".*"
197-
}
198-
reQuery := strings.Builder{}
195+
var sb strings.Builder
196+
197+
for {
198+
n := strings.IndexAny(query, "*[{")
199+
if n < 0 {
200+
sb.WriteString(regexp.QuoteMeta(query))
201+
return sb.String()
202+
}
199203

200-
inGroup := 0
201-
for _, c := range query {
202-
switch c {
203-
case '.':
204-
reQuery.WriteString("\\\\.")
204+
sb.WriteString(regexp.QuoteMeta(query[:n]))
205+
ch := query[n]
206+
query = query[n+1:]
207+
208+
switch ch {
205209
case '*':
206-
reQuery.WriteString("[^.][^.]*")
210+
if query == "" {
211+
// needed to support find requests when asterisk is the last character and dots should be included
212+
sb.WriteString(".*")
213+
break
214+
}
215+
216+
sb.WriteString("[^.]*?")
217+
218+
case '[':
219+
n = strings.Index(query, "]")
220+
if n < 0 {
221+
sb.WriteString(regexp.QuoteMeta("[" + query))
222+
return sb.String()
223+
}
224+
sb.WriteString("[" + query[:n+1])
225+
query = query[n+1:]
226+
207227
case '{':
208-
reQuery.WriteString("(")
209-
inGroup++
210-
case ',':
211-
reQuery.WriteString("|")
212-
case '}':
213-
reQuery.WriteString(")")
214-
default:
215-
reQuery.WriteRune(c)
228+
n = strings.Index(query, "}")
229+
if n < 0 {
230+
sb.WriteString(regexp.QuoteMeta("{" + query))
231+
return sb.String()
232+
}
233+
alts := strings.Split(query[:n], ",")
234+
query = query[n+1:]
235+
for i := range alts {
236+
alts[i] = regexp.QuoteMeta(alts[i])
237+
}
238+
sb.WriteString("(" + strings.Join(alts, "|") + ")")
216239
}
217240
}
218-
219-
return reQuery.String()
220241
}
221242

222243
// inserts math.NaN() in place of gaps in data from Prometheus

0 commit comments

Comments
 (0)