3
0
mirror of https://github.com/grafana/grafana.git synced 2025-02-25 18:55:37 -06:00

InfluxDB: Fix sending retention policy with the backend request ()

* Add retention policy to the request

* refactor

* refactor influxql query flow

* fix healthcheck

* organize imports

* handle queries separately

* fix tests

* update bench test
This commit is contained in:
ismail simsek 2023-08-30 13:42:02 +03:00 committed by GitHub
parent dc26cdf6c9
commit 29ea0886e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 317 additions and 408 deletions

View File

@ -11,6 +11,7 @@ import (
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/tsdb/influxdb/flux"
"github.com/grafana/grafana/pkg/tsdb/influxdb/fsql"
"github.com/grafana/grafana/pkg/tsdb/influxdb/influxql"
"github.com/grafana/grafana/pkg/tsdb/influxdb/models"
)
@ -34,7 +35,7 @@ func (s *Service) CheckHealth(ctx context.Context, req *backend.CheckHealthReque
case influxVersionFlux:
return CheckFluxHealth(ctx, dsInfo, req)
case influxVersionInfluxQL:
return CheckInfluxQLHealth(ctx, dsInfo, s)
return CheckInfluxQLHealth(ctx, dsInfo)
case influxVersionSQL:
return CheckSQLHealth(ctx, dsInfo, req)
default:
@ -77,30 +78,22 @@ func CheckFluxHealth(ctx context.Context, dsInfo *models.DatasourceInfo,
return getHealthCheckMessage(logger, "", errors.New("error getting flux query buckets"))
}
func CheckInfluxQLHealth(ctx context.Context, dsInfo *models.DatasourceInfo, s *Service) (*backend.CheckHealthResult, error) {
func CheckInfluxQLHealth(ctx context.Context, dsInfo *models.DatasourceInfo) (*backend.CheckHealthResult, error) {
logger := logger.FromContext(ctx)
queryString := "SHOW measurements"
hcRequest, err := s.createRequest(ctx, logger, dsInfo, queryString)
if err != nil {
return getHealthCheckMessage(logger, "error creating influxDB healthcheck request", err)
}
res, err := dsInfo.HTTPClient.Do(hcRequest)
resp, err := influxql.Query(ctx, dsInfo, &backend.QueryDataRequest{
Queries: []backend.DataQuery{
{
RefID: refID,
QueryType: "health",
JSON: []byte(`{"query": "SHOW measurements", "rawQuery": true}`),
},
},
})
if err != nil {
return getHealthCheckMessage(logger, "error performing influxQL query", err)
}
defer func() {
if err := res.Body.Close(); err != nil {
logger.Warn("failed to close response body", "err", err)
}
}()
resp := s.responseParser.Parse(res.Body, res.StatusCode, []Query{{
RefID: refID,
UseRawQuery: true,
RawQuery: queryString,
}})
if res, ok := resp.Responses[refID]; ok {
if res.Error != nil {
return getHealthCheckMessage(logger, "error reading influxDB", res.Error)

View File

@ -3,12 +3,7 @@ package influxdb
import (
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
"path"
"strings"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
@ -19,26 +14,19 @@ import (
"github.com/grafana/grafana/pkg/infra/httpclient"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/influxdb/influxql"
"github.com/grafana/grafana/pkg/tsdb/influxdb/models"
)
var logger log.Logger = log.New("tsdb.influxdb")
type Service struct {
queryParser *InfluxdbQueryParser
responseParser *ResponseParser
im instancemgmt.InstanceManager
}
var ErrInvalidHttpMode = errors.New("'httpMode' should be either 'GET' or 'POST'")
func ProvideService(httpClient httpclient.Provider) *Service {
return &Service{
queryParser: &InfluxdbQueryParser{},
responseParser: &ResponseParser{},
im: datasource.NewInstanceManager(newInstanceSettings(httpClient)),
im: datasource.NewInstanceManager(newInstanceSettings(httpClient)),
}
}
@ -106,102 +94,19 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest)
if err != nil {
return nil, err
}
version := dsInfo.Version
if version == influxVersionFlux {
logger.Debug(fmt.Sprintf("Making a %s type query", dsInfo.Version))
switch dsInfo.Version {
case influxVersionFlux:
return flux.Query(ctx, dsInfo, *req)
}
if version == influxVersionSQL {
case influxVersionInfluxQL:
return influxql.Query(ctx, dsInfo, req)
case influxVersionSQL:
return fsql.Query(ctx, dsInfo, *req)
}
logger.Debug("Making a non-Flux type query")
var allRawQueries string
queries := make([]Query, 0, len(req.Queries))
for _, reqQuery := range req.Queries {
query, err := s.queryParser.Parse(reqQuery)
if err != nil {
return &backend.QueryDataResponse{}, err
}
rawQuery, err := query.Build(req)
if err != nil {
return &backend.QueryDataResponse{}, err
}
allRawQueries = allRawQueries + rawQuery + ";"
query.RefID = reqQuery.RefID
query.RawQuery = rawQuery
queries = append(queries, *query)
}
if setting.Env == setting.Dev {
logger.Debug("Influxdb query", "raw query", allRawQueries)
}
request, err := s.createRequest(ctx, logger, dsInfo, allRawQueries)
if err != nil {
return &backend.QueryDataResponse{}, err
}
res, err := dsInfo.HTTPClient.Do(request)
if err != nil {
return &backend.QueryDataResponse{}, err
}
defer func() {
if err := res.Body.Close(); err != nil {
logger.Warn("Failed to close response body", "err", err)
}
}()
resp := s.responseParser.Parse(res.Body, res.StatusCode, queries)
return resp, nil
}
func (s *Service) createRequest(ctx context.Context, logger log.Logger, dsInfo *models.DatasourceInfo, query string) (*http.Request, error) {
u, err := url.Parse(dsInfo.URL)
if err != nil {
return nil, err
}
u.Path = path.Join(u.Path, "query")
httpMode := dsInfo.HTTPMode
var req *http.Request
switch httpMode {
case "GET":
req, err = http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
if err != nil {
return nil, err
}
case "POST":
bodyValues := url.Values{}
bodyValues.Add("q", query)
body := bodyValues.Encode()
req, err = http.NewRequestWithContext(ctx, http.MethodPost, u.String(), strings.NewReader(body))
if err != nil {
return nil, err
}
default:
return nil, ErrInvalidHttpMode
return nil, fmt.Errorf("unknown influxdb version")
}
params := req.URL.Query()
params.Set("db", dsInfo.DbName)
params.Set("epoch", "ms")
if httpMode == "GET" {
params.Set("q", query)
} else if httpMode == "POST" {
req.Header.Set("Content-type", "application/x-www-form-urlencoded")
}
req.URL.RawQuery = params.Encode()
logger.Debug("Influxdb request", "url", req.URL.String())
return req, nil
}
func (s *Service) getDSInfo(ctx context.Context, pluginCtx backend.PluginContext) (*models.DatasourceInfo, error) {

View File

@ -0,0 +1,125 @@
package influxql
import (
"context"
"errors"
"net/http"
"net/url"
"path"
"strings"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/influxdb/models"
)
const defaultRetentionPolicy = "default"
var (
ErrInvalidHttpMode = errors.New("'httpMode' should be either 'GET' or 'POST'")
glog = log.New("tsdb.influx_influxql")
)
func Query(ctx context.Context, dsInfo *models.DatasourceInfo, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
logger := glog.FromContext(ctx)
response := backend.NewQueryDataResponse()
for _, reqQuery := range req.Queries {
query, err := models.QueryParse(reqQuery)
if err != nil {
return &backend.QueryDataResponse{}, err
}
rawQuery, err := query.Build(req)
if err != nil {
return &backend.QueryDataResponse{}, err
}
query.RefID = reqQuery.RefID
query.RawQuery = rawQuery
if setting.Env == setting.Dev {
logger.Debug("Influxdb query", "raw query", rawQuery)
}
request, err := createRequest(ctx, logger, dsInfo, rawQuery, query.Policy)
if err != nil {
return &backend.QueryDataResponse{}, err
}
resp, err := execute(dsInfo, logger, query, request)
if err != nil {
response.Responses[query.RefID] = backend.DataResponse{Error: err}
} else {
response.Responses[query.RefID] = resp
}
}
return response, nil
}
func createRequest(ctx context.Context, logger log.Logger, dsInfo *models.DatasourceInfo, queryStr string, retentionPolicy string) (*http.Request, error) {
u, err := url.Parse(dsInfo.URL)
if err != nil {
return nil, err
}
u.Path = path.Join(u.Path, "query")
httpMode := dsInfo.HTTPMode
var req *http.Request
switch httpMode {
case "GET":
req, err = http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
if err != nil {
return nil, err
}
case "POST":
bodyValues := url.Values{}
bodyValues.Add("q", queryStr)
body := bodyValues.Encode()
req, err = http.NewRequestWithContext(ctx, http.MethodPost, u.String(), strings.NewReader(body))
if err != nil {
return nil, err
}
default:
return nil, ErrInvalidHttpMode
}
params := req.URL.Query()
params.Set("db", dsInfo.DbName)
params.Set("epoch", "ms")
// default is hardcoded default retention policy
// InfluxDB will use the default policy when it is not added to the request
if retentionPolicy != "" && retentionPolicy != "default" {
params.Set("rp", retentionPolicy)
}
if httpMode == "GET" {
params.Set("q", queryStr)
} else if httpMode == "POST" {
req.Header.Set("Content-type", "application/x-www-form-urlencoded")
}
req.URL.RawQuery = params.Encode()
logger.Debug("Influxdb request", "url", req.URL.String())
return req, nil
}
func execute(dsInfo *models.DatasourceInfo, logger log.Logger, query *models.Query, request *http.Request) (backend.DataResponse, error) {
res, err := dsInfo.HTTPClient.Do(request)
if err != nil {
return backend.DataResponse{}, err
}
defer func() {
if err := res.Body.Close(); err != nil {
logger.Warn("Failed to close response body", "err", err)
}
}()
resp := ResponseParse(res.Body, res.StatusCode, query)
return *resp, nil
}

View File

@ -1,4 +1,4 @@
package influxdb
package influxql
import (
"context"
@ -9,23 +9,21 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/tsdb/influxdb/models"
)
func TestExecutor_createRequest(t *testing.T) {
logger := log.New("tsdb.influx_influxql_test")
datasource := &models.DatasourceInfo{
URL: "http://awesome-influxdb:1337",
DbName: "awesome-db",
HTTPMode: "GET",
}
query := "SELECT awesomeness FROM somewhere"
s := &Service{
queryParser: &InfluxdbQueryParser{},
responseParser: &ResponseParser{},
}
t.Run("createRequest with GET httpMode", func(t *testing.T) {
req, err := s.createRequest(context.Background(), logger, datasource, query)
req, err := createRequest(context.Background(), logger, datasource, query, defaultRetentionPolicy)
require.NoError(t, err)
@ -39,7 +37,7 @@ func TestExecutor_createRequest(t *testing.T) {
t.Run("createRequest with POST httpMode", func(t *testing.T) {
datasource.HTTPMode = "POST"
req, err := s.createRequest(context.Background(), logger, datasource, query)
req, err := createRequest(context.Background(), logger, datasource, query, defaultRetentionPolicy)
require.NoError(t, err)
assert.Equal(t, "POST", req.Method)
@ -58,7 +56,7 @@ func TestExecutor_createRequest(t *testing.T) {
t.Run("createRequest with PUT httpMode", func(t *testing.T) {
datasource.HTTPMode = "PUT"
_, err := s.createRequest(context.Background(), logger, datasource, query)
_, err := createRequest(context.Background(), logger, datasource, query, defaultRetentionPolicy)
require.EqualError(t, err, ErrInvalidHttpMode.Error())
})
}

View File

@ -1,4 +1,4 @@
package influxdb
package influxql
import (
"encoding/json"
@ -11,51 +11,45 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/data"
)
type ResponseParser struct{}
"github.com/grafana/grafana/pkg/tsdb/influxdb/models"
)
var (
legendFormat = regexp.MustCompile(`\[\[([\@\/\w-]+)(\.[\@\/\w-]+)*\]\]*|\$([\@\w-]+?)*`)
)
func (rp *ResponseParser) Parse(buf io.ReadCloser, statusCode int, queries []Query) *backend.QueryDataResponse {
return rp.parse(buf, statusCode, queries)
func ResponseParse(buf io.ReadCloser, statusCode int, query *models.Query) *backend.DataResponse {
return parse(buf, statusCode, query)
}
// parse is the same as Parse, but without the io.ReadCloser (we don't need to
// close the buffer)
func (*ResponseParser) parse(buf io.Reader, statusCode int, queries []Query) *backend.QueryDataResponse {
resp := backend.NewQueryDataResponse()
func parse(buf io.Reader, statusCode int, query *models.Query) *backend.DataResponse {
response, jsonErr := parseJSON(buf)
if statusCode/100 != 2 {
resp.Responses["A"] = backend.DataResponse{Error: fmt.Errorf("InfluxDB returned error: %s", response.Error)}
return &backend.DataResponse{Error: fmt.Errorf("InfluxDB returned error: %s", response.Error)}
}
if jsonErr != nil {
resp.Responses["A"] = backend.DataResponse{Error: jsonErr}
return resp
return &backend.DataResponse{Error: jsonErr}
}
if response.Error != "" {
resp.Responses["A"] = backend.DataResponse{Error: fmt.Errorf(response.Error)}
return resp
return &backend.DataResponse{Error: fmt.Errorf(response.Error)}
}
for i, result := range response.Results {
if result.Error != "" {
resp.Responses[queries[i].RefID] = backend.DataResponse{Error: fmt.Errorf(result.Error)}
} else {
resp.Responses[queries[i].RefID] = backend.DataResponse{Frames: transformRows(result.Series, queries[i])}
}
result := response.Results[0]
if result.Error != "" {
return &backend.DataResponse{Error: fmt.Errorf(result.Error)}
} else {
return &backend.DataResponse{Frames: transformRows(result.Series, *query)}
}
return resp
}
func parseJSON(buf io.Reader) (Response, error) {
var response Response
func parseJSON(buf io.Reader) (models.Response, error) {
var response models.Response
dec := json.NewDecoder(buf)
dec.UseNumber()
@ -65,7 +59,7 @@ func parseJSON(buf io.Reader) (Response, error) {
return response, err
}
func transformRows(rows []Row, query Query) data.Frames {
func transformRows(rows []models.Row, query models.Query) data.Frames {
// pre-allocate frames - this can save many allocations
cols := 0
for _, row := range rows {
@ -106,7 +100,7 @@ func transformRows(rows []Row, query Query) data.Frames {
return frames
}
func newFrameWithTimeField(row Row, column string, colIndex int, query Query, frameName []byte) *data.Frame {
func newFrameWithTimeField(row models.Row, column string, colIndex int, query models.Query, frameName []byte) *data.Frame {
var timeArray []time.Time
var floatArray []*float64
var stringArray []*string
@ -164,7 +158,7 @@ func newFrameWithTimeField(row Row, column string, colIndex int, query Query, fr
return newDataFrame(name, query.RawQuery, timeField, valueField)
}
func newFrameWithoutTimeField(row Row, retentionPolicyQuery bool, tagValuesQuery bool) *data.Frame {
func newFrameWithoutTimeField(row models.Row, retentionPolicyQuery bool, tagValuesQuery bool) *data.Frame {
var values []string
if retentionPolicyQuery {
@ -213,7 +207,7 @@ func newDataFrame(name string, queryString string, timeField *data.Field, valueF
return frame
}
func formatFrameName(row Row, column string, query Query, frameName []byte) []byte {
func formatFrameName(row models.Row, column string, query models.Query, frameName []byte) []byte {
if query.Alias == "" {
return buildFrameNameFromQuery(row, column, frameName)
}
@ -253,7 +247,7 @@ func formatFrameName(row Row, column string, query Query, frameName []byte) []by
return result
}
func buildFrameNameFromQuery(row Row, column string, frameName []byte) []byte {
func buildFrameNameFromQuery(row models.Row, column string, frameName []byte) []byte {
frameName = append(frameName, row.Name...)
frameName = append(frameName, '.')
frameName = append(frameName, column...)
@ -329,10 +323,10 @@ func parseNumber(value interface{}) *float64 {
return &fvalue
}
func isTagValuesQuery(query Query) bool {
func isTagValuesQuery(query models.Query) bool {
return strings.Contains(strings.ToLower(query.RawQuery), strings.ToLower("SHOW TAG VALUES"))
}
func isRetentionPolicyQuery(query Query) bool {
func isRetentionPolicyQuery(query models.Query) bool {
return strings.Contains(strings.ToLower(query.RawQuery), strings.ToLower("SHOW RETENTION POLICIES"))
}

View File

@ -1,4 +1,4 @@
package influxdb
package influxql
import (
_ "embed"
@ -6,24 +6,24 @@ import (
"testing"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/tsdb/influxdb/models"
)
//go:embed testdata/response.json
var testResponse string
// go test -benchmem -run=^$ -memprofile memprofile.out -count=10 -bench ^BenchmarkParseJson$ github.com/grafana/grafana/pkg/tsdb/influxdb
// go test -benchmem -run=^$ -memprofile memprofile.out -count=10 -bench ^BenchmarkParseJson$ github.com/grafana/grafana/pkg/tsdb/influxdb/influxql
// go tool pprof -http=localhost:9999 memprofile.out
func BenchmarkParseJson(b *testing.B) {
parser := &ResponseParser{}
query := &Query{}
queries := addQueryToQueries(*query)
query := generateQuery(models.Query{})
b.ResetTimer()
for n := 0; n < b.N; n++ {
buf := strings.NewReader(testResponse)
result := parser.parse(buf, 200, queries)
require.NotNil(b, result.Responses["A"].Frames)
require.NoError(b, result.Responses["A"].Error)
result := parse(buf, 200, query)
require.NotNil(b, result.Frames)
require.NoError(b, result.Error)
}
}

View File

@ -1,4 +1,4 @@
package influxdb
package influxql
import (
"encoding/json"
@ -13,6 +13,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/tsdb/influxdb/models"
"github.com/grafana/grafana/pkg/util"
)
@ -20,31 +21,29 @@ func prepare(text string) io.ReadCloser {
return io.NopCloser(strings.NewReader(text))
}
func addQueryToQueries(query Query) []Query {
var queries []Query
query.RefID = "A"
query.RawQuery = "Test raw query"
queries = append(queries, query)
return queries
func generateQuery(query models.Query) *models.Query {
if query.RefID == "" {
query.RefID = "A"
}
if query.RawQuery == "" {
query.RawQuery = "Test raw query"
}
return &query
}
func TestInfluxdbResponseParser(t *testing.T) {
t.Run("Influxdb response parser should handle invalid JSON", func(t *testing.T) {
parser := &ResponseParser{}
response := `{ invalid }`
query := &Query{}
query := models.Query{}
result := parser.Parse(prepare(response), 200, addQueryToQueries(*query))
result := ResponseParse(prepare(response), 200, generateQuery(query))
require.Nil(t, result.Responses["A"].Frames)
require.Error(t, result.Responses["A"].Error)
require.Nil(t, result.Frames)
require.Error(t, result.Error)
})
t.Run("Influxdb response parser should parse everything normally including nil bools and nil strings", func(t *testing.T) {
parser := &ResponseParser{}
response := `
{
"results": [
@ -66,7 +65,7 @@ func TestInfluxdbResponseParser(t *testing.T) {
}
`
query := &Query{}
query := models.Query{}
labels, err := data.LabelsFromString("datacenter=America")
require.Nil(t, err)
@ -118,23 +117,20 @@ func TestInfluxdbResponseParser(t *testing.T) {
)
boolFrame.Meta = &data.FrameMeta{ExecutedQueryString: "Test raw query"}
result := parser.Parse(prepare(response), 200, addQueryToQueries(*query))
result := ResponseParse(prepare(response), 200, generateQuery(query))
frame := result.Responses["A"]
if diff := cmp.Diff(floatFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(floatFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
if diff := cmp.Diff(stringFrame, frame.Frames[1], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(stringFrame, result.Frames[1], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
if diff := cmp.Diff(boolFrame, frame.Frames[2], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(boolFrame, result.Frames[2], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
})
t.Run("Influxdb response parser should parse metricFindQueries normally", func(t *testing.T) {
parser := &ResponseParser{}
response := `
{
"results": [
@ -155,8 +151,7 @@ func TestInfluxdbResponseParser(t *testing.T) {
}
`
var queries []Query
queries = append(queries, Query{RefID: "metricFindQuery"})
query := models.Query{RefID: "metricFindQuery"}
newField := data.NewField("Value", nil, []string{
"cpu", "disk", "logs",
})
@ -164,17 +159,14 @@ func TestInfluxdbResponseParser(t *testing.T) {
newField,
)
result := parser.Parse(prepare(response), 200, queries)
result := ResponseParse(prepare(response), 200, generateQuery(query))
frame := result.Responses["metricFindQuery"]
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
})
t.Run("Influxdb response parser should parse metricFindQueries->SHOW TAG VALUES normally", func(t *testing.T) {
parser := &ResponseParser{}
response := `
{
"results": [
@ -194,8 +186,7 @@ func TestInfluxdbResponseParser(t *testing.T) {
}
`
var queries []Query
queries = append(queries, Query{RawQuery: "SHOW TAG VALUES", RefID: "metricFindQuery"})
query := models.Query{RawQuery: "SHOW TAG VALUES", RefID: "metricFindQuery"}
newField := data.NewField("Value", nil, []string{
"cpu-total", "cpu0", "cpu1",
})
@ -203,46 +194,14 @@ func TestInfluxdbResponseParser(t *testing.T) {
newField,
)
result := parser.Parse(prepare(response), 200, queries)
result := ResponseParse(prepare(response), 200, generateQuery(query))
frame := result.Responses["metricFindQuery"]
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
})
t.Run("Influxdb response parser should parse two responses with different refIDs", func(t *testing.T) {
parser := &ResponseParser{}
response := `
{
"results": [
{
"series": [{}]
},
{
"series": [{}]
}
]
}
`
query := &Query{}
var queries = addQueryToQueries(*query)
queryB := &Query{}
queryB.RefID = "B"
queries = append(queries, *queryB)
result := parser.Parse(prepare(response), 200, queries)
assert.Len(t, result.Responses, 2)
assert.Contains(t, result.Responses, "A")
assert.Contains(t, result.Responses, "B")
assert.NotContains(t, result.Responses, "C")
})
t.Run("Influxdb response parser populates the RawQuery in the response meta ExecutedQueryString", func(t *testing.T) {
parser := &ResponseParser{}
response := `
{
"results": [
@ -263,17 +222,14 @@ func TestInfluxdbResponseParser(t *testing.T) {
}
`
query := &Query{}
query := models.Query{}
query.RawQuery = "Test raw query"
result := parser.Parse(prepare(response), 200, addQueryToQueries(*query))
result := ResponseParse(prepare(response), 200, generateQuery(query))
frame := result.Responses["A"]
assert.Equal(t, frame.Frames[0].Meta.ExecutedQueryString, "Test raw query")
assert.Equal(t, result.Frames[0].Meta.ExecutedQueryString, "Test raw query")
})
t.Run("Influxdb response parser with invalid value-format", func(t *testing.T) {
parser := &ResponseParser{}
response := `
{
"results": [
@ -294,7 +250,7 @@ func TestInfluxdbResponseParser(t *testing.T) {
}
`
query := &Query{}
query := models.Query{}
newField := data.NewField("Value", nil, []*float64{
util.Pointer(50.0), nil, util.Pointer(52.0),
@ -311,17 +267,14 @@ func TestInfluxdbResponseParser(t *testing.T) {
)
testFrame.Meta = &data.FrameMeta{ExecutedQueryString: "Test raw query"}
result := parser.Parse(prepare(response), 200, addQueryToQueries(*query))
result := ResponseParse(prepare(response), 200, generateQuery(query))
frame := result.Responses["A"]
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
})
t.Run("Influxdb response parser with invalid timestamp-format", func(t *testing.T) {
parser := &ResponseParser{}
response := `
{
"results": [
@ -343,7 +296,7 @@ func TestInfluxdbResponseParser(t *testing.T) {
}
`
query := &Query{}
query := models.Query{}
newField := data.NewField("Value", nil, []*float64{
util.Pointer(50.0), util.Pointer(52.0),
@ -359,17 +312,14 @@ func TestInfluxdbResponseParser(t *testing.T) {
)
testFrame.Meta = &data.FrameMeta{ExecutedQueryString: "Test raw query"}
result := parser.Parse(prepare(response), 200, addQueryToQueries(*query))
result := ResponseParse(prepare(response), 200, generateQuery(query))
frame := result.Responses["A"]
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
})
t.Run("Influxdb response parser with alias", func(t *testing.T) {
parser := &ResponseParser{}
response := `
{
"results": [
@ -395,7 +345,7 @@ func TestInfluxdbResponseParser(t *testing.T) {
}
`
query := &Query{Alias: "series alias"}
query := models.Query{Alias: "series alias"}
labels, err := data.LabelsFromString("/cluster/name/=Cluster/, @cluster@name@=Cluster@, cluster-name=Cluster, datacenter=America, dc.region.name=Northeast")
require.Nil(t, err)
newField := data.NewField("Value", labels, []*float64{
@ -410,31 +360,28 @@ func TestInfluxdbResponseParser(t *testing.T) {
newField,
)
testFrame.Meta = &data.FrameMeta{ExecutedQueryString: "Test raw query"}
result := parser.Parse(prepare(response), 200, addQueryToQueries(*query))
result := ResponseParse(prepare(response), 200, generateQuery(query))
t.Run("should parse aliases", func(t *testing.T) {
frame := result.Responses["A"]
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
query = &Query{Alias: "alias $m $measurement", Measurement: "10m"}
result = parser.Parse(prepare(response), 200, addQueryToQueries(*query))
query = models.Query{Alias: "alias $m $measurement", Measurement: "10m"}
result = ResponseParse(prepare(response), 200, generateQuery(query))
frame = result.Responses["A"]
name := "alias 10m 10m"
testFrame.Name = name
testFrame.Fields[1].Config.DisplayNameFromDS = name
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
query = &Query{Alias: "alias $col", Measurement: "10m"}
result = parser.Parse(prepare(response), 200, addQueryToQueries(*query))
frame = result.Responses["A"]
query = models.Query{Alias: "alias $col", Measurement: "10m"}
result = ResponseParse(prepare(response), 200, generateQuery(query))
name = "alias mean"
testFrame.Name = name
testFrame.Fields[1].Config.DisplayNameFromDS = name
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
name = "alias sum"
@ -444,13 +391,12 @@ func TestInfluxdbResponseParser(t *testing.T) {
})
testFrame.Fields[1] = newField
testFrame.Fields[1].Config = &data.FieldConfig{DisplayNameFromDS: name}
if diff := cmp.Diff(testFrame, frame.Frames[1], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[1], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
query = &Query{Alias: "alias $tag_datacenter"}
result = parser.Parse(prepare(response), 200, addQueryToQueries(*query))
frame = result.Responses["A"]
query = models.Query{Alias: "alias $tag_datacenter"}
result = ResponseParse(prepare(response), 200, generateQuery(query))
name = "alias America"
testFrame.Name = name
newField = data.NewField("Value", labels, []*float64{
@ -458,13 +404,12 @@ func TestInfluxdbResponseParser(t *testing.T) {
})
testFrame.Fields[1] = newField
testFrame.Fields[1].Config = &data.FieldConfig{DisplayNameFromDS: name}
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
query = &Query{Alias: "alias $tag_datacenter/$tag_datacenter"}
result = parser.Parse(prepare(response), 200, addQueryToQueries(*query))
frame = result.Responses["A"]
query = models.Query{Alias: "alias $tag_datacenter/$tag_datacenter"}
result = ResponseParse(prepare(response), 200, generateQuery(query))
name = "alias America/America"
testFrame.Name = name
newField = data.NewField("Value", labels, []*float64{
@ -472,183 +417,152 @@ func TestInfluxdbResponseParser(t *testing.T) {
})
testFrame.Fields[1] = newField
testFrame.Fields[1].Config = &data.FieldConfig{DisplayNameFromDS: name}
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
query = &Query{Alias: "alias [[col]]", Measurement: "10m"}
result = parser.Parse(prepare(response), 200, addQueryToQueries(*query))
frame = result.Responses["A"]
query = models.Query{Alias: "alias [[col]]", Measurement: "10m"}
result = ResponseParse(prepare(response), 200, generateQuery(query))
name = "alias mean"
testFrame.Name = name
testFrame.Fields[1].Config.DisplayNameFromDS = name
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
query = &Query{Alias: "alias $0 $1 $2 $3 $4"}
result = parser.Parse(prepare(response), 200, addQueryToQueries(*query))
frame = result.Responses["A"]
query = models.Query{Alias: "alias $0 $1 $2 $3 $4"}
result = ResponseParse(prepare(response), 200, generateQuery(query))
name = "alias cpu upc $2 $3 $4"
testFrame.Name = name
testFrame.Fields[1].Config.DisplayNameFromDS = name
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
query = &Query{Alias: "alias $0, $1 - $2 - $3, $4: something"}
result = parser.Parse(prepare(response), 200, addQueryToQueries(*query))
frame = result.Responses["A"]
query = models.Query{Alias: "alias $0, $1 - $2 - $3, $4: something"}
result = ResponseParse(prepare(response), 200, generateQuery(query))
name = "alias cpu, upc - $2 - $3, $4: something"
testFrame.Name = name
testFrame.Fields[1].Config.DisplayNameFromDS = name
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
query = &Query{Alias: "alias $1"}
result = parser.Parse(prepare(response), 200, addQueryToQueries(*query))
frame = result.Responses["A"]
query = models.Query{Alias: "alias $1"}
result = ResponseParse(prepare(response), 200, generateQuery(query))
name = "alias upc"
testFrame.Name = name
testFrame.Fields[1].Config.DisplayNameFromDS = name
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
query = &Query{Alias: "alias $5"}
result = parser.Parse(prepare(response), 200, addQueryToQueries(*query))
frame = result.Responses["A"]
query = models.Query{Alias: "alias $5"}
result = ResponseParse(prepare(response), 200, generateQuery(query))
name = "alias $5"
testFrame.Name = name
testFrame.Fields[1].Config.DisplayNameFromDS = name
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
query = &Query{Alias: "series alias"}
result = parser.Parse(prepare(response), 200, addQueryToQueries(*query))
frame = result.Responses["A"]
query = models.Query{Alias: "series alias"}
result = ResponseParse(prepare(response), 200, generateQuery(query))
name = "series alias"
testFrame.Name = name
testFrame.Fields[1].Config.DisplayNameFromDS = name
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
query = &Query{Alias: "alias [[m]] [[measurement]]", Measurement: "10m"}
result = parser.Parse(prepare(response), 200, addQueryToQueries(*query))
frame = result.Responses["A"]
query = models.Query{Alias: "alias [[m]] [[measurement]]", Measurement: "10m"}
result = ResponseParse(prepare(response), 200, generateQuery(query))
name = "alias 10m 10m"
testFrame.Name = name
testFrame.Fields[1].Config.DisplayNameFromDS = name
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
query = &Query{Alias: "alias [[tag_datacenter]]"}
result = parser.Parse(prepare(response), 200, addQueryToQueries(*query))
frame = result.Responses["A"]
query = models.Query{Alias: "alias [[tag_datacenter]]"}
result = ResponseParse(prepare(response), 200, generateQuery(query))
name = "alias America"
testFrame.Name = name
testFrame.Fields[1].Config.DisplayNameFromDS = name
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
query = &Query{Alias: "alias [[tag_dc.region.name]]"}
result = parser.Parse(prepare(response), 200, addQueryToQueries(*query))
frame = result.Responses["A"]
query = models.Query{Alias: "alias [[tag_dc.region.name]]"}
result = ResponseParse(prepare(response), 200, generateQuery(query))
name = "alias Northeast"
testFrame.Name = name
testFrame.Fields[1].Config.DisplayNameFromDS = name
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
query = &Query{Alias: "alias [[tag_cluster-name]]"}
result = parser.Parse(prepare(response), 200, addQueryToQueries(*query))
frame = result.Responses["A"]
query = models.Query{Alias: "alias [[tag_cluster-name]]"}
result = ResponseParse(prepare(response), 200, generateQuery(query))
name = "alias Cluster"
testFrame.Name = name
testFrame.Fields[1].Config.DisplayNameFromDS = name
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
query = &Query{Alias: "alias [[tag_/cluster/name/]]"}
result = parser.Parse(prepare(response), 200, addQueryToQueries(*query))
frame = result.Responses["A"]
query = models.Query{Alias: "alias [[tag_/cluster/name/]]"}
result = ResponseParse(prepare(response), 200, generateQuery(query))
name = "alias Cluster/"
testFrame.Name = name
testFrame.Fields[1].Config.DisplayNameFromDS = name
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
query = &Query{Alias: "alias [[tag_@cluster@name@]]"}
result = parser.Parse(prepare(response), 200, addQueryToQueries(*query))
frame = result.Responses["A"]
query = models.Query{Alias: "alias [[tag_@cluster@name@]]"}
result = ResponseParse(prepare(response), 200, generateQuery(query))
name = "alias Cluster@"
testFrame.Name = name
testFrame.Fields[1].Config.DisplayNameFromDS = name
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
})
t.Run("shouldn't parse aliases", func(t *testing.T) {
query = &Query{Alias: "alias words with no brackets"}
result = parser.Parse(prepare(response), 200, addQueryToQueries(*query))
frame := result.Responses["A"]
query = models.Query{Alias: "alias words with no brackets"}
result = ResponseParse(prepare(response), 200, generateQuery(query))
name := "alias words with no brackets"
testFrame.Name = name
testFrame.Fields[1].Config.DisplayNameFromDS = name
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
query = &Query{Alias: "alias Test 1.5"}
result = parser.Parse(prepare(response), 200, addQueryToQueries(*query))
frame = result.Responses["A"]
query = models.Query{Alias: "alias Test 1.5"}
result = ResponseParse(prepare(response), 200, generateQuery(query))
name = "alias Test 1.5"
testFrame.Name = name
testFrame.Fields[1].Config.DisplayNameFromDS = name
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
query = &Query{Alias: "alias Test -1"}
result = parser.Parse(prepare(response), 200, addQueryToQueries(*query))
frame = result.Responses["A"]
query = models.Query{Alias: "alias Test -1"}
result = ResponseParse(prepare(response), 200, generateQuery(query))
name = "alias Test -1"
testFrame.Name = name
testFrame.Fields[1].Config.DisplayNameFromDS = name
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
})
})
t.Run("Influxdb response parser with errors", func(t *testing.T) {
parser := &ResponseParser{}
response := `
{
"results": [
{
"series": [
{
"name": "cpu",
"columns": ["time","mean","sum"],
"tags": {"datacenter": "America"},
"values": [
[111,222,333],
[111,222,333],
[111,null,333]
]
}
]
},
{
"error": "query-timeout limit exceeded"
}
@ -656,11 +570,7 @@ func TestInfluxdbResponseParser(t *testing.T) {
}
`
query := &Query{}
var queries = addQueryToQueries(*query)
queryB := &Query{}
queryB.RefID = "B"
queries = append(queries, *queryB)
query := models.Query{}
labels, err := data.LabelsFromString("datacenter=America")
require.Nil(t, err)
newField := data.NewField("Value", labels, []*float64{
@ -677,32 +587,25 @@ func TestInfluxdbResponseParser(t *testing.T) {
newField,
)
testFrame.Meta = &data.FrameMeta{ExecutedQueryString: "Test raw query"}
result := parser.Parse(prepare(response), 200, queries)
result := ResponseParse(prepare(response), 200, generateQuery(query))
frame := result.Responses["A"]
if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
require.EqualError(t, result.Responses["B"].Error, "query-timeout limit exceeded")
require.EqualError(t, result.Error, "query-timeout limit exceeded")
})
t.Run("Influxdb response parser with top-level error", func(t *testing.T) {
parser := &ResponseParser{}
response := `
{
"error": "error parsing query: found THING"
}
`
query := &Query{}
query := models.Query{}
result := parser.Parse(prepare(response), 200, addQueryToQueries(*query))
result := ResponseParse(prepare(response), 200, generateQuery(query))
require.Nil(t, result.Responses["A"].Frames)
require.Nil(t, result.Frames)
require.EqualError(t, result.Responses["A"].Error, "error parsing query: found THING")
require.EqualError(t, result.Error, "error parsing query: found THING")
})
t.Run("Influxdb response parser parseNumber nil", func(t *testing.T) {
@ -736,8 +639,6 @@ func TestInfluxdbResponseParser(t *testing.T) {
func TestResponseParser_Parse_RetentionPolicy(t *testing.T) {
t.Run("Influxdb response parser should parse metricFindQueries->SHOW RETENTION POLICIES normally", func(t *testing.T) {
parser := &ResponseParser{}
response := `
{
"results": [
@ -789,18 +690,16 @@ func TestResponseParser_Parse_RetentionPolicy(t *testing.T) {
}
`
var queries []Query
queries = append(queries, Query{RefID: "metricFindQuery", RawQuery: "SHOW RETENTION POLICIES"})
query := models.Query{RefID: "metricFindQuery", RawQuery: "SHOW RETENTION POLICIES"}
policyFrame := data.NewFrame("",
data.NewField("Value", nil, []string{
"bar", "autogen", "5m_avg", "1m_avg",
}),
)
result := parser.Parse(prepare(response), 200, queries)
result := ResponseParse(prepare(response), 200, generateQuery(query))
frame := result.Responses["metricFindQuery"]
if diff := cmp.Diff(policyFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
if diff := cmp.Diff(policyFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
})
@ -810,7 +709,7 @@ func TestResponseParser_Parse(t *testing.T) {
tests := []struct {
name string
input string
f func(t *testing.T, got *backend.QueryDataResponse)
f func(t *testing.T, got backend.DataResponse)
}{
{
name: "Influxdb response parser with valid value when null values returned",
@ -823,7 +722,7 @@ func TestResponseParser_Parse(t *testing.T) {
[102,52]
]
}]}]}`,
f: func(t *testing.T, got *backend.QueryDataResponse) {
f: func(t *testing.T, got backend.DataResponse) {
newField := data.NewField("Value", nil, []*float64{nil, nil, util.Pointer(52.0)})
newField.Config = &data.FieldConfig{DisplayNameFromDS: "cpu.mean"}
testFrame := data.NewFrame("cpu.mean",
@ -836,7 +735,7 @@ func TestResponseParser_Parse(t *testing.T) {
newField,
)
testFrame.Meta = &data.FrameMeta{ExecutedQueryString: "Test raw query"}
assert.Equal(t, testFrame, got.Responses["A"].Frames[0])
assert.Equal(t, testFrame, got.Frames[0])
},
},
{
@ -850,7 +749,7 @@ func TestResponseParser_Parse(t *testing.T) {
[102,null]
]
}]}]}`,
f: func(t *testing.T, got *backend.QueryDataResponse) {
f: func(t *testing.T, got backend.DataResponse) {
newField := data.NewField("Value", nil, []*float64{nil, nil, nil})
newField.Config = &data.FieldConfig{DisplayNameFromDS: "cpu.mean"}
testFrame := data.NewFrame("cpu.mean",
@ -863,17 +762,16 @@ func TestResponseParser_Parse(t *testing.T) {
newField,
)
testFrame.Meta = &data.FrameMeta{ExecutedQueryString: "Test raw query"}
assert.Equal(t, testFrame, got.Responses["A"].Frames[0])
assert.Equal(t, testFrame, got.Frames[0])
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
parser := &ResponseParser{}
got := parser.Parse(prepare(tt.input), 200, addQueryToQueries(Query{}))
got := ResponseParse(prepare(tt.input), 200, generateQuery(models.Query{}))
require.NotNil(t, got)
if tt.f != nil {
tt.f(t, got)
tt.f(t, *got)
}
})
}

View File

@ -113,8 +113,6 @@ func (rt *RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
func GetMockService(version string, rt RoundTripper) *Service {
return &Service{
queryParser: &InfluxdbQueryParser{},
responseParser: &ResponseParser{},
im: &fakeInstance{
version: version,
fakeRoundTripper: rt,

View File

@ -1,4 +1,4 @@
package influxdb
package models
import (
"fmt"
@ -12,7 +12,7 @@ import (
type InfluxdbQueryParser struct{}
func (qp *InfluxdbQueryParser) Parse(query backend.DataQuery) (*Query, error) {
func QueryParse(query backend.DataQuery) (*Query, error) {
model, err := simplejson.NewJson(query.JSON)
if err != nil {
return nil, fmt.Errorf("couldn't unmarshal query")
@ -29,17 +29,17 @@ func (qp *InfluxdbQueryParser) Parse(query backend.DataQuery) (*Query, error) {
measurement := model.Get("measurement").MustString("")
tags, err := qp.parseTags(model)
tags, err := parseTags(model)
if err != nil {
return nil, err
}
groupBys, err := qp.parseGroupBy(model)
groupBys, err := parseGroupBy(model)
if err != nil {
return nil, err
}
selects, err := qp.parseSelects(model)
selects, err := parseSelects(model)
if err != nil {
return nil, err
}
@ -70,7 +70,7 @@ func (qp *InfluxdbQueryParser) Parse(query backend.DataQuery) (*Query, error) {
}, nil
}
func (qp *InfluxdbQueryParser) parseSelects(model *simplejson.Json) ([]*Select, error) {
func parseSelects(model *simplejson.Json) ([]*Select, error) {
selectObjs := model.Get("select").MustArray()
result := make([]*Select, 0, len(selectObjs))
@ -80,7 +80,7 @@ func (qp *InfluxdbQueryParser) parseSelects(model *simplejson.Json) ([]*Select,
for _, partObj := range selectJson.MustArray() {
part := simplejson.NewFromAny(partObj)
queryPart, err := qp.parseQueryPart(part)
queryPart, err := parseQueryPart(part)
if err != nil {
return nil, err
}
@ -94,7 +94,7 @@ func (qp *InfluxdbQueryParser) parseSelects(model *simplejson.Json) ([]*Select,
return result, nil
}
func (*InfluxdbQueryParser) parseTags(model *simplejson.Json) ([]*Tag, error) {
func parseTags(model *simplejson.Json) ([]*Tag, error) {
tags := model.Get("tags").MustArray()
result := make([]*Tag, 0, len(tags))
for _, t := range tags {
@ -128,7 +128,7 @@ func (*InfluxdbQueryParser) parseTags(model *simplejson.Json) ([]*Tag, error) {
return result, nil
}
func (*InfluxdbQueryParser) parseQueryPart(model *simplejson.Json) (*QueryPart, error) {
func parseQueryPart(model *simplejson.Json) (*QueryPart, error) {
typ, err := model.Get("type").String()
if err != nil {
return nil, err
@ -161,12 +161,12 @@ func (*InfluxdbQueryParser) parseQueryPart(model *simplejson.Json) (*QueryPart,
return qp, nil
}
func (qp *InfluxdbQueryParser) parseGroupBy(model *simplejson.Json) ([]*QueryPart, error) {
func parseGroupBy(model *simplejson.Json) ([]*QueryPart, error) {
groupBy := model.Get("groupBy").MustArray()
result := make([]*QueryPart, 0, len(groupBy))
for _, groupObj := range groupBy {
groupJson := simplejson.NewFromAny(groupObj)
queryPart, err := qp.parseQueryPart(groupJson)
queryPart, err := parseQueryPart(groupJson)
if err != nil {
return nil, err
}

View File

@ -1,4 +1,4 @@
package influxdb
package models
import (
"testing"
@ -9,8 +9,6 @@ import (
)
func TestInfluxdbQueryParser_Parse(t *testing.T) {
parser := &InfluxdbQueryParser{}
t.Run("can parse influxdb json model", func(t *testing.T) {
json := `
{
@ -110,7 +108,7 @@ func TestInfluxdbQueryParser_Parse(t *testing.T) {
Interval: time.Second * 20,
}
res, err := parser.Parse(query)
res, err := QueryParse(query)
require.NoError(t, err)
require.Len(t, res.GroupBy, 3)
require.Len(t, res.Selects, 3)
@ -173,7 +171,7 @@ func TestInfluxdbQueryParser_Parse(t *testing.T) {
Interval: time.Second * 10,
}
res, err := parser.Parse(query)
res, err := QueryParse(query)
require.NoError(t, err)
require.Equal(t, "RawDummyQuery", res.RawQuery)
require.Len(t, res.GroupBy, 2)
@ -196,7 +194,7 @@ func TestInfluxdbQueryParser_Parse(t *testing.T) {
Interval: time.Millisecond * 0,
}
res, err := parser.Parse(query)
res, err := QueryParse(query)
require.NoError(t, err)
require.Equal(t, time.Millisecond*1, res.Interval)
})

View File

@ -1,4 +1,4 @@
package influxdb
package models
import "time"

View File

@ -1,4 +1,4 @@
package influxdb
package models
import (
"fmt"

View File

@ -1,4 +1,4 @@
package influxdb
package models
import (
"fmt"

View File

@ -1,4 +1,4 @@
package influxdb
package models
import (
"testing"

View File

@ -1,4 +1,4 @@
package influxdb
package models
import (
"strings"