[v10.4.x] InfluxDB: Use json-iterator package for json operations (#88866)
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
(cherry picked from commit 808cf75ff8)
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
package buffered
|
package buffered
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -9,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
"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/influxql/util"
|
||||||
"github.com/grafana/grafana/pkg/tsdb/influxdb/models"
|
"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) {
|
func parseJSON(buf io.Reader) (models.Response, error) {
|
||||||
var response models.Response
|
var response models.Response
|
||||||
|
|
||||||
|
json := jsoniter.ConfigCompatibleWithStandardLibrary
|
||||||
|
|
||||||
dec := json.NewDecoder(buf)
|
dec := json.NewDecoder(buf)
|
||||||
dec.UseNumber()
|
|
||||||
|
|
||||||
err := dec.Decode(&response)
|
err := dec.Decode(&response)
|
||||||
|
|
||||||
@@ -154,6 +155,12 @@ func newValueFields(rows []models.Row, labels data.Labels, colIdxStart, colIdxEn
|
|||||||
case "json.Number":
|
case "json.Number":
|
||||||
value := util.ParseNumber(valuePair[colIdx])
|
value := util.ParseNumber(valuePair[colIdx])
|
||||||
floatArray = append(floatArray, value)
|
floatArray = append(floatArray, value)
|
||||||
|
case "float64":
|
||||||
|
if value, ok := valuePair[colIdx].(float64); ok {
|
||||||
|
floatArray = append(floatArray, &value)
|
||||||
|
} else {
|
||||||
|
floatArray = append(floatArray, nil)
|
||||||
|
}
|
||||||
case "bool":
|
case "bool":
|
||||||
value, ok := valuePair[colIdx].(bool)
|
value, ok := valuePair[colIdx].(bool)
|
||||||
if ok {
|
if ok {
|
||||||
@@ -196,6 +203,8 @@ func newValueFields(rows []models.Row, labels data.Labels, colIdxStart, colIdxEn
|
|||||||
valueField = data.NewField(row.Columns[colIdx], labels, stringArray)
|
valueField = data.NewField(row.Columns[colIdx], labels, stringArray)
|
||||||
case "json.Number":
|
case "json.Number":
|
||||||
valueField = data.NewField(row.Columns[colIdx], labels, floatArray)
|
valueField = data.NewField(row.Columns[colIdx], labels, floatArray)
|
||||||
|
case "float64":
|
||||||
|
valueField = data.NewField(row.Columns[colIdx], labels, floatArray)
|
||||||
case "bool":
|
case "bool":
|
||||||
valueField = data.NewField(row.Columns[colIdx], labels, boolArray)
|
valueField = data.NewField(row.Columns[colIdx], labels, boolArray)
|
||||||
case "null":
|
case "null":
|
||||||
@@ -241,12 +250,6 @@ func transformRowsForTimeSeries(rows []models.Row, query models.Query) data.Fram
|
|||||||
|
|
||||||
if !hasTimeCol {
|
if !hasTimeCol {
|
||||||
newFrame := newFrameWithoutTimeField(row, query)
|
newFrame := newFrameWithoutTimeField(row, query)
|
||||||
if len(frames) == 0 {
|
|
||||||
newFrame.Meta = &data.FrameMeta{
|
|
||||||
ExecutedQueryString: query.RawQuery,
|
|
||||||
PreferredVisualization: util.GetVisType(query.ResultFormat),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
frames = append(frames, newFrame)
|
frames = append(frames, newFrame)
|
||||||
} else {
|
} else {
|
||||||
for colIndex, column := range row.Columns {
|
for colIndex, column := range row.Columns {
|
||||||
@@ -254,17 +257,18 @@ func transformRowsForTimeSeries(rows []models.Row, query models.Query) data.Fram
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
newFrame := newFrameWithTimeField(row, column, colIndex, query, frameName)
|
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)
|
frames = append(frames, newFrame)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(frames) > 0 {
|
||||||
|
frames[0].Meta = &data.FrameMeta{
|
||||||
|
ExecutedQueryString: query.RawQuery,
|
||||||
|
PreferredVisualization: util.GetVisType(query.ResultFormat),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return frames
|
return frames
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,6 +298,12 @@ func newFrameWithTimeField(row models.Row, column string, colIndex int, query mo
|
|||||||
case "json.Number":
|
case "json.Number":
|
||||||
value := util.ParseNumber(valuePair[colIndex])
|
value := util.ParseNumber(valuePair[colIndex])
|
||||||
floatArray = append(floatArray, value)
|
floatArray = append(floatArray, value)
|
||||||
|
case "float64":
|
||||||
|
if value, ok := valuePair[colIndex].(float64); ok {
|
||||||
|
floatArray = append(floatArray, &value)
|
||||||
|
} else {
|
||||||
|
floatArray = append(floatArray, nil)
|
||||||
|
}
|
||||||
case "bool":
|
case "bool":
|
||||||
value, ok := valuePair[colIndex].(bool)
|
value, ok := valuePair[colIndex].(bool)
|
||||||
if ok {
|
if ok {
|
||||||
@@ -315,6 +325,8 @@ func newFrameWithTimeField(row models.Row, column string, colIndex int, query mo
|
|||||||
valueField = data.NewField("Value", row.Tags, stringArray)
|
valueField = data.NewField("Value", row.Tags, stringArray)
|
||||||
case "json.Number":
|
case "json.Number":
|
||||||
valueField = data.NewField("Value", row.Tags, floatArray)
|
valueField = data.NewField("Value", row.Tags, floatArray)
|
||||||
|
case "float64":
|
||||||
|
valueField = data.NewField("Value", row.Tags, floatArray)
|
||||||
case "bool":
|
case "bool":
|
||||||
valueField = data.NewField("Value", row.Tags, boolArray)
|
valueField = data.NewField("Value", row.Tags, boolArray)
|
||||||
case "null":
|
case "null":
|
||||||
|
|||||||
@@ -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.
|
// 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.
|
// 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.NoError(t, err)
|
||||||
require.Equal(t, timestamp.Format(time.RFC3339), "2021-01-02T03:04:05Z")
|
require.Equal(t, timestamp.Format(time.RFC3339), "2021-01-02T03:04:05Z")
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -89,18 +89,14 @@ func BuildFrameNameFromQuery(rowName, column string, tags map[string]string, fra
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ParseTimestamp(value any) (time.Time, error) {
|
func ParseTimestamp(value any) (time.Time, error) {
|
||||||
timestampNumber, ok := value.(json.Number)
|
timestampNumber, ok := value.(float64)
|
||||||
if !ok {
|
if !ok {
|
||||||
return time.Time{}, fmt.Errorf("timestamp-value has invalid type: %#v", value)
|
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
|
// currently in the code the influxdb-timestamps are requested with
|
||||||
// milliseconds-precision, meaning these values are milliseconds
|
// milliseconds-precision, meaning these values are milliseconds
|
||||||
t := time.UnixMilli(timestampInMilliseconds).UTC()
|
t := time.UnixMilli(int64(timestampNumber)).UTC()
|
||||||
|
|
||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user