InfluxDB: Use json-iterator package for json operations (#88562)

* return error early

* enable gzip between grafana and influxdb

* use json-iterator package for json operations

* revert gzip changes

* update test

* go mod tidy
go work sync
This commit is contained in:
ismail simsek
2024-06-06 20:14:53 +03:00
committed by GitHub
parent e21d357d67
commit 808cf75ff8
5 changed files with 39 additions and 27 deletions
@@ -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"
@@ -46,8 +46,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)
@@ -150,6 +151,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 {
@@ -192,6 +199,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":
@@ -237,12 +246,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 {
@@ -250,17 +253,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
}
@@ -290,6 +294,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 {
@@ -311,6 +321,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":
@@ -380,10 +380,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")
})
+2 -6
View File
@@ -98,18 +98,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
}