From c9dbf5a0d0f25a78917a58e92a2df4621b9df5d0 Mon Sep 17 00:00:00 2001 From: Kyle Brandt Date: Wed, 24 Feb 2021 13:16:26 -0500 Subject: [PATCH] Graphite/SSE: update graphite to work with server side expressions (#31455) Changes the time value of the response to be milliseconds, which I think is like the other data sources I have seen. Also if it sees the timerange values as numbers, assumes they are unixMS (and come from expressions, or our new backend.TimeRange type). When this timerange is used, the request is sent to graphite with from and until as epoch timestamps --- pkg/tsdb/graphite/graphite.go | 42 +++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/pkg/tsdb/graphite/graphite.go b/pkg/tsdb/graphite/graphite.go index 61946aad038..f8b0056620e 100644 --- a/pkg/tsdb/graphite/graphite.go +++ b/pkg/tsdb/graphite/graphite.go @@ -10,6 +10,7 @@ import ( "net/url" "path" "regexp" + "strconv" "strings" "golang.org/x/net/context/ctxhttp" @@ -38,8 +39,19 @@ func init() { func (e *GraphiteExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) (*tsdb.Response, error) { result := &tsdb.Response{} + // This logic is used when called from Dashboard Alerting. from := "-" + formatTimeRange(tsdbQuery.TimeRange.From) until := formatTimeRange(tsdbQuery.TimeRange.To) + + // This logic is used when called through server side expressions. + if isTimeRangeNumeric(tsdbQuery.TimeRange) { + var err error + from, until, err = epochMStoGraphiteTime(tsdbQuery.TimeRange) + if err != nil { + return nil, err + } + } + var target string formData := url.Values{ @@ -154,6 +166,12 @@ func (e *GraphiteExecutor) parseResponse(res *http.Response) ([]TargetResponseDT return nil, err } + for si := range data { + // Convert Response to timestamps MS + for pi, point := range data[si].DataPoints { + data[si].DataPoints[pi][1].Float64 = point[1].Float64 * 1000 + } + } return data, nil } @@ -196,3 +214,27 @@ func fixIntervalFormat(target string) string { }) return target } + +func isTimeRangeNumeric(tr *tsdb.TimeRange) bool { + if _, err := strconv.ParseInt(tr.From, 10, 64); err != nil { + return false + } + if _, err := strconv.ParseInt(tr.To, 10, 64); err != nil { + return false + } + return true +} + +func epochMStoGraphiteTime(tr *tsdb.TimeRange) (string, string, error) { + from, err := strconv.ParseInt(tr.From, 10, 64) + if err != nil { + return "", "", err + } + + to, err := strconv.ParseInt(tr.To, 10, 64) + if err != nil { + return "", "", err + } + + return fmt.Sprintf("%d", from/1000), fmt.Sprintf("%d", to/1000), nil +}