diff --git a/pkg/tsdb/influxdb/influxql/buffered/response_parser.go b/pkg/tsdb/influxdb/influxql/buffered/response_parser.go index bcc89ea3960..ab5f2114d58 100644 --- a/pkg/tsdb/influxdb/influxql/buffered/response_parser.go +++ b/pkg/tsdb/influxdb/influxql/buffered/response_parser.go @@ -1,7 +1,6 @@ package buffered import ( - "encoding/json" "fmt" "io" "strings" @@ -9,6 +8,7 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/data" + jsoniter "github.com/json-iterator/go" "github.com/grafana/grafana/pkg/tsdb/influxdb/influxql/util" "github.com/grafana/grafana/pkg/tsdb/influxdb/models" @@ -50,8 +50,9 @@ func parse(buf io.Reader, statusCode int, query *models.Query) *backend.DataResp func parseJSON(buf io.Reader) (models.Response, error) { var response models.Response + json := jsoniter.ConfigCompatibleWithStandardLibrary + dec := json.NewDecoder(buf) - dec.UseNumber() err := dec.Decode(&response) @@ -154,6 +155,12 @@ func newValueFields(rows []models.Row, labels data.Labels, colIdxStart, colIdxEn case "json.Number": value := util.ParseNumber(valuePair[colIdx]) floatArray = append(floatArray, value) + case "float64": + if value, ok := valuePair[colIdx].(float64); ok { + floatArray = append(floatArray, &value) + } else { + floatArray = append(floatArray, nil) + } case "bool": value, ok := valuePair[colIdx].(bool) if ok { @@ -196,6 +203,8 @@ func newValueFields(rows []models.Row, labels data.Labels, colIdxStart, colIdxEn valueField = data.NewField(row.Columns[colIdx], labels, stringArray) case "json.Number": valueField = data.NewField(row.Columns[colIdx], labels, floatArray) + case "float64": + valueField = data.NewField(row.Columns[colIdx], labels, floatArray) case "bool": valueField = data.NewField(row.Columns[colIdx], labels, boolArray) case "null": @@ -241,12 +250,6 @@ func transformRowsForTimeSeries(rows []models.Row, query models.Query) data.Fram if !hasTimeCol { newFrame := newFrameWithoutTimeField(row, query) - if len(frames) == 0 { - newFrame.Meta = &data.FrameMeta{ - ExecutedQueryString: query.RawQuery, - PreferredVisualization: util.GetVisType(query.ResultFormat), - } - } frames = append(frames, newFrame) } else { for colIndex, column := range row.Columns { @@ -254,17 +257,18 @@ func transformRowsForTimeSeries(rows []models.Row, query models.Query) data.Fram continue } newFrame := newFrameWithTimeField(row, column, colIndex, query, frameName) - if len(frames) == 0 { - newFrame.Meta = &data.FrameMeta{ - ExecutedQueryString: query.RawQuery, - PreferredVisualization: util.GetVisType(query.ResultFormat), - } - } frames = append(frames, newFrame) } } } + if len(frames) > 0 { + frames[0].Meta = &data.FrameMeta{ + ExecutedQueryString: query.RawQuery, + PreferredVisualization: util.GetVisType(query.ResultFormat), + } + } + return frames } @@ -294,6 +298,12 @@ func newFrameWithTimeField(row models.Row, column string, colIndex int, query mo case "json.Number": value := util.ParseNumber(valuePair[colIndex]) floatArray = append(floatArray, value) + case "float64": + if value, ok := valuePair[colIndex].(float64); ok { + floatArray = append(floatArray, &value) + } else { + floatArray = append(floatArray, nil) + } case "bool": value, ok := valuePair[colIndex].(bool) if ok { @@ -315,6 +325,8 @@ func newFrameWithTimeField(row models.Row, column string, colIndex int, query mo valueField = data.NewField("Value", row.Tags, stringArray) case "json.Number": valueField = data.NewField("Value", row.Tags, floatArray) + case "float64": + valueField = data.NewField("Value", row.Tags, floatArray) case "bool": valueField = data.NewField("Value", row.Tags, boolArray) case "null": diff --git a/pkg/tsdb/influxdb/influxql/buffered/response_parser_test.go b/pkg/tsdb/influxdb/influxql/buffered/response_parser_test.go index c6f4028a32f..e3415d5270e 100644 --- a/pkg/tsdb/influxdb/influxql/buffered/response_parser_test.go +++ b/pkg/tsdb/influxdb/influxql/buffered/response_parser_test.go @@ -363,10 +363,11 @@ func TestInfluxdbResponseParser(t *testing.T) { } }) - t.Run("Influxdb response parser parseTimestamp valid JSON.number", func(t *testing.T) { + t.Run("Influxdb response parser parseTimestamp valid number", func(t *testing.T) { // currently we use milliseconds-precision with influxdb, so the test works with that. // if we change this to for example nanoseconds-precision, the tests will have to change. - timestamp, err := util.ParseTimestamp(json.Number("1609556645000")) + ts := float64(1609556645000) + timestamp, err := util.ParseTimestamp(ts) require.NoError(t, err) require.Equal(t, timestamp.Format(time.RFC3339), "2021-01-02T03:04:05Z") }) diff --git a/pkg/tsdb/influxdb/influxql/util/util.go b/pkg/tsdb/influxdb/influxql/util/util.go index b4ecc095b6b..707e52099d7 100644 --- a/pkg/tsdb/influxdb/influxql/util/util.go +++ b/pkg/tsdb/influxdb/influxql/util/util.go @@ -89,18 +89,14 @@ func BuildFrameNameFromQuery(rowName, column string, tags map[string]string, fra } func ParseTimestamp(value any) (time.Time, error) { - timestampNumber, ok := value.(json.Number) + timestampNumber, ok := value.(float64) if !ok { return time.Time{}, fmt.Errorf("timestamp-value has invalid type: %#v", value) } - timestampInMilliseconds, err := timestampNumber.Int64() - if err != nil { - return time.Time{}, err - } // currently in the code the influxdb-timestamps are requested with // milliseconds-precision, meaning these values are milliseconds - t := time.UnixMilli(timestampInMilliseconds).UTC() + t := time.UnixMilli(int64(timestampNumber)).UTC() return t, nil }