|
|
@ -8,15 +8,15 @@ 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" |
|
|
|
|
|
|
|
sdkjsoniter "github.com/grafana/grafana-plugin-sdk-go/data/utils/jsoniter" |
|
|
|
jsoniter "github.com/json-iterator/go" |
|
|
|
jsoniter "github.com/json-iterator/go" |
|
|
|
"golang.org/x/exp/slices" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/grafana/grafana/pkg/util/converter/jsonitere" |
|
|
|
"golang.org/x/exp/slices" |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
// helpful while debugging all the options that may appear
|
|
|
|
// helpful while debugging all the options that may appear
|
|
|
|
func logf(format string, a ...any) { |
|
|
|
func logf(format string, a ...any) { |
|
|
|
//fmt.Printf(format, a...)
|
|
|
|
// fmt.Printf(format, a...)
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
type Options struct { |
|
|
|
type Options struct { |
|
|
@ -29,7 +29,7 @@ func rspErr(e error) backend.DataResponse { |
|
|
|
|
|
|
|
|
|
|
|
// ReadPrometheusStyleResult will read results from a prometheus or loki server and return data frames
|
|
|
|
// ReadPrometheusStyleResult will read results from a prometheus or loki server and return data frames
|
|
|
|
func ReadPrometheusStyleResult(jIter *jsoniter.Iterator, opt Options) backend.DataResponse { |
|
|
|
func ReadPrometheusStyleResult(jIter *jsoniter.Iterator, opt Options) backend.DataResponse { |
|
|
|
iter := jsonitere.NewIterator(jIter) |
|
|
|
iter := sdkjsoniter.NewIterator(jIter) |
|
|
|
var rsp backend.DataResponse |
|
|
|
var rsp backend.DataResponse |
|
|
|
status := "unknown" |
|
|
|
status := "unknown" |
|
|
|
errorType := "" |
|
|
|
errorType := "" |
|
|
@ -102,14 +102,14 @@ l1Fields: |
|
|
|
return rsp |
|
|
|
return rsp |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func readWarnings(iter *jsonitere.Iterator) ([]data.Notice, error) { |
|
|
|
func readWarnings(iter *sdkjsoniter.Iterator) ([]data.Notice, error) { |
|
|
|
warnings := []data.Notice{} |
|
|
|
warnings := []data.Notice{} |
|
|
|
next, err := iter.WhatIsNext() |
|
|
|
next, err := iter.WhatIsNext() |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return nil, err |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if next != jsoniter.ArrayValue { |
|
|
|
if next != sdkjsoniter.ArrayValue { |
|
|
|
return warnings, nil |
|
|
|
return warnings, nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -121,7 +121,7 @@ func readWarnings(iter *jsonitere.Iterator) ([]data.Notice, error) { |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return nil, err |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
} |
|
|
|
if next == jsoniter.StringValue { |
|
|
|
if next == sdkjsoniter.StringValue { |
|
|
|
s, err := iter.ReadString() |
|
|
|
s, err := iter.ReadString() |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return nil, err |
|
|
|
return nil, err |
|
|
@ -137,18 +137,18 @@ func readWarnings(iter *jsonitere.Iterator) ([]data.Notice, error) { |
|
|
|
return warnings, nil |
|
|
|
return warnings, nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func readPrometheusData(iter *jsonitere.Iterator, opt Options) backend.DataResponse { |
|
|
|
func readPrometheusData(iter *sdkjsoniter.Iterator, opt Options) backend.DataResponse { |
|
|
|
var rsp backend.DataResponse |
|
|
|
var rsp backend.DataResponse |
|
|
|
t, err := iter.WhatIsNext() |
|
|
|
t, err := iter.WhatIsNext() |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return rspErr(err) |
|
|
|
return rspErr(err) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if t == jsoniter.ArrayValue { |
|
|
|
if t == sdkjsoniter.ArrayValue { |
|
|
|
return readArrayData(iter) |
|
|
|
return readArrayData(iter) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if t != jsoniter.ObjectValue { |
|
|
|
if t != sdkjsoniter.ObjectValue { |
|
|
|
return backend.DataResponse{ |
|
|
|
return backend.DataResponse{ |
|
|
|
Error: fmt.Errorf("expected object type"), |
|
|
|
Error: fmt.Errorf("expected object type"), |
|
|
|
} |
|
|
|
} |
|
|
@ -190,7 +190,7 @@ l1Fields: |
|
|
|
// if we have saved resultBytes we will parse them here
|
|
|
|
// if we have saved resultBytes we will parse them here
|
|
|
|
// we saved them because when we had them we don't know the resultType
|
|
|
|
// we saved them because when we had them we don't know the resultType
|
|
|
|
if len(resultBytes) > 0 { |
|
|
|
if len(resultBytes) > 0 { |
|
|
|
ji := jsonitere.NewIterator(jsoniter.ParseBytes(jsoniter.ConfigDefault, resultBytes)) |
|
|
|
ji := sdkjsoniter.NewIterator(jsoniter.ParseBytes(sdkjsoniter.ConfigDefault, resultBytes)) |
|
|
|
rsp = readResult(resultType, rsp, ji, opt, encodingFlags) |
|
|
|
rsp = readResult(resultType, rsp, ji, opt, encodingFlags) |
|
|
|
} |
|
|
|
} |
|
|
|
case "result": |
|
|
|
case "result": |
|
|
@ -200,7 +200,7 @@ l1Fields: |
|
|
|
if resultTypeFound { |
|
|
|
if resultTypeFound { |
|
|
|
rsp = readResult(resultType, rsp, iter, opt, encodingFlags) |
|
|
|
rsp = readResult(resultType, rsp, iter, opt, encodingFlags) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
resultBytes = iter.SkipAndReturnBytes() |
|
|
|
resultBytes, _ = iter.SkipAndReturnBytes() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
case "stats": |
|
|
|
case "stats": |
|
|
@ -241,7 +241,7 @@ l1Fields: |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// will read the result object based on the resultType and return a DataResponse
|
|
|
|
// will read the result object based on the resultType and return a DataResponse
|
|
|
|
func readResult(resultType string, rsp backend.DataResponse, iter *jsonitere.Iterator, opt Options, encodingFlags []string) backend.DataResponse { |
|
|
|
func readResult(resultType string, rsp backend.DataResponse, iter *sdkjsoniter.Iterator, opt Options, encodingFlags []string) backend.DataResponse { |
|
|
|
switch resultType { |
|
|
|
switch resultType { |
|
|
|
case "matrix", "vector": |
|
|
|
case "matrix", "vector": |
|
|
|
rsp = readMatrixOrVectorMulti(iter, resultType, opt) |
|
|
|
rsp = readMatrixOrVectorMulti(iter, resultType, opt) |
|
|
@ -279,7 +279,7 @@ func readResult(resultType string, rsp backend.DataResponse, iter *jsonitere.Ite |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// will return strings or exemplars
|
|
|
|
// will return strings or exemplars
|
|
|
|
func readArrayData(iter *jsonitere.Iterator) backend.DataResponse { |
|
|
|
func readArrayData(iter *sdkjsoniter.Iterator) backend.DataResponse { |
|
|
|
lookup := make(map[string]*data.Field) |
|
|
|
lookup := make(map[string]*data.Field) |
|
|
|
|
|
|
|
|
|
|
|
var labelFrame *data.Frame |
|
|
|
var labelFrame *data.Frame |
|
|
@ -298,7 +298,7 @@ func readArrayData(iter *jsonitere.Iterator) backend.DataResponse { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
switch next { |
|
|
|
switch next { |
|
|
|
case jsoniter.StringValue: |
|
|
|
case sdkjsoniter.StringValue: |
|
|
|
s, err := iter.ReadString() |
|
|
|
s, err := iter.ReadString() |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return rspErr(err) |
|
|
|
return rspErr(err) |
|
|
@ -306,7 +306,7 @@ func readArrayData(iter *jsonitere.Iterator) backend.DataResponse { |
|
|
|
stringField.Append(s) |
|
|
|
stringField.Append(s) |
|
|
|
|
|
|
|
|
|
|
|
// Either label or exemplars
|
|
|
|
// Either label or exemplars
|
|
|
|
case jsoniter.ObjectValue: |
|
|
|
case sdkjsoniter.ObjectValue: |
|
|
|
exemplar, labelPairs, err := readLabelsOrExemplars(iter) |
|
|
|
exemplar, labelPairs, err := readLabelsOrExemplars(iter) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
rspErr(err) |
|
|
|
rspErr(err) |
|
|
@ -365,7 +365,7 @@ func readArrayData(iter *jsonitere.Iterator) backend.DataResponse { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// For consistent ordering read values to an array not a map
|
|
|
|
// For consistent ordering read values to an array not a map
|
|
|
|
func readLabelsAsPairs(iter *jsonitere.Iterator) ([][2]string, error) { |
|
|
|
func readLabelsAsPairs(iter *sdkjsoniter.Iterator) ([][2]string, error) { |
|
|
|
pairs := make([][2]string, 0, 10) |
|
|
|
pairs := make([][2]string, 0, 10) |
|
|
|
for k, err := iter.ReadObject(); k != ""; k, err = iter.ReadObject() { |
|
|
|
for k, err := iter.ReadObject(); k != ""; k, err = iter.ReadObject() { |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
@ -380,7 +380,7 @@ func readLabelsAsPairs(iter *jsonitere.Iterator) ([][2]string, error) { |
|
|
|
return pairs, nil |
|
|
|
return pairs, nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func readLabelsOrExemplars(iter *jsonitere.Iterator) (*data.Frame, [][2]string, error) { |
|
|
|
func readLabelsOrExemplars(iter *sdkjsoniter.Iterator) (*data.Frame, [][2]string, error) { |
|
|
|
pairs := make([][2]string, 0, 10) |
|
|
|
pairs := make([][2]string, 0, 10) |
|
|
|
labels := data.Labels{} |
|
|
|
labels := data.Labels{} |
|
|
|
var frame *data.Frame |
|
|
|
var frame *data.Frame |
|
|
@ -496,7 +496,7 @@ l1Fields: |
|
|
|
return frame, pairs, nil |
|
|
|
return frame, pairs, nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func readString(iter *jsonitere.Iterator) backend.DataResponse { |
|
|
|
func readString(iter *sdkjsoniter.Iterator) backend.DataResponse { |
|
|
|
timeField := data.NewFieldFromFieldType(data.FieldTypeTime, 0) |
|
|
|
timeField := data.NewFieldFromFieldType(data.FieldTypeTime, 0) |
|
|
|
timeField.Name = data.TimeSeriesTimeFieldName |
|
|
|
timeField.Name = data.TimeSeriesTimeFieldName |
|
|
|
valueField := data.NewFieldFromFieldType(data.FieldTypeString, 0) |
|
|
|
valueField := data.NewFieldFromFieldType(data.FieldTypeString, 0) |
|
|
@ -541,7 +541,7 @@ func readString(iter *jsonitere.Iterator) backend.DataResponse { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func readScalar(iter *jsonitere.Iterator, dataPlane bool) backend.DataResponse { |
|
|
|
func readScalar(iter *sdkjsoniter.Iterator, dataPlane bool) backend.DataResponse { |
|
|
|
rsp := backend.DataResponse{} |
|
|
|
rsp := backend.DataResponse{} |
|
|
|
|
|
|
|
|
|
|
|
timeField := data.NewFieldFromFieldType(data.FieldTypeTime, 0) |
|
|
|
timeField := data.NewFieldFromFieldType(data.FieldTypeTime, 0) |
|
|
@ -573,7 +573,7 @@ func readScalar(iter *jsonitere.Iterator, dataPlane bool) backend.DataResponse { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func readMatrixOrVectorMulti(iter *jsonitere.Iterator, resultType string, opt Options) backend.DataResponse { |
|
|
|
func readMatrixOrVectorMulti(iter *sdkjsoniter.Iterator, resultType string, opt Options) backend.DataResponse { |
|
|
|
rsp := backend.DataResponse{} |
|
|
|
rsp := backend.DataResponse{} |
|
|
|
|
|
|
|
|
|
|
|
for more, err := iter.ReadArray(); more; more, err = iter.ReadArray() { |
|
|
|
for more, err := iter.ReadArray(); more; more, err = iter.ReadArray() { |
|
|
@ -679,7 +679,7 @@ func readMatrixOrVectorMulti(iter *jsonitere.Iterator, resultType string, opt Op |
|
|
|
return rsp |
|
|
|
return rsp |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func readTimeValuePair(iter *jsonitere.Iterator) (time.Time, float64, error) { |
|
|
|
func readTimeValuePair(iter *sdkjsoniter.Iterator) (time.Time, float64, error) { |
|
|
|
if _, err := iter.ReadArray(); err != nil { |
|
|
|
if _, err := iter.ReadArray(); err != nil { |
|
|
|
return time.Time{}, 0, err |
|
|
|
return time.Time{}, 0, err |
|
|
|
} |
|
|
|
} |
|
|
@ -708,7 +708,7 @@ func readTimeValuePair(iter *jsonitere.Iterator) (time.Time, float64, error) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
type histogramInfo struct { |
|
|
|
type histogramInfo struct { |
|
|
|
//XMax (time) YMin Ymax Count YLayout
|
|
|
|
// XMax (time) YMin Ymax Count YLayout
|
|
|
|
time *data.Field |
|
|
|
time *data.Field |
|
|
|
yMin *data.Field // will have labels?
|
|
|
|
yMin *data.Field // will have labels?
|
|
|
|
yMax *data.Field |
|
|
|
yMax *data.Field |
|
|
@ -734,7 +734,7 @@ func newHistogramInfo() *histogramInfo { |
|
|
|
|
|
|
|
|
|
|
|
// This will read a single sparse histogram
|
|
|
|
// This will read a single sparse histogram
|
|
|
|
// [ time, { count, sum, buckets: [...] }]
|
|
|
|
// [ time, { count, sum, buckets: [...] }]
|
|
|
|
func readHistogram(iter *jsonitere.Iterator, hist *histogramInfo) error { |
|
|
|
func readHistogram(iter *sdkjsoniter.Iterator, hist *histogramInfo) error { |
|
|
|
// first element
|
|
|
|
// first element
|
|
|
|
if _, err := iter.ReadArray(); err != nil { |
|
|
|
if _, err := iter.ReadArray(); err != nil { |
|
|
|
return err |
|
|
|
return err |
|
|
@ -834,7 +834,7 @@ func readHistogram(iter *jsonitere.Iterator, hist *histogramInfo) error { |
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func appendValueFromString(iter *jsonitere.Iterator, field *data.Field) error { |
|
|
|
func appendValueFromString(iter *sdkjsoniter.Iterator, field *data.Field) error { |
|
|
|
var err error |
|
|
|
var err error |
|
|
|
var s string |
|
|
|
var s string |
|
|
|
if s, err = iter.ReadString(); err != nil { |
|
|
|
if s, err = iter.ReadString(); err != nil { |
|
|
@ -850,7 +850,7 @@ func appendValueFromString(iter *jsonitere.Iterator, field *data.Field) error { |
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func readStream(iter *jsonitere.Iterator) backend.DataResponse { |
|
|
|
func readStream(iter *sdkjsoniter.Iterator) backend.DataResponse { |
|
|
|
rsp := backend.DataResponse{} |
|
|
|
rsp := backend.DataResponse{} |
|
|
|
|
|
|
|
|
|
|
|
labelsField := data.NewFieldFromFieldType(data.FieldTypeJSON, 0) |
|
|
|
labelsField := data.NewFieldFromFieldType(data.FieldTypeJSON, 0) |
|
|
@ -950,7 +950,7 @@ func readStream(iter *jsonitere.Iterator) backend.DataResponse { |
|
|
|
return rsp |
|
|
|
return rsp |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func readCategorizedStream(iter *jsonitere.Iterator) backend.DataResponse { |
|
|
|
func readCategorizedStream(iter *sdkjsoniter.Iterator) backend.DataResponse { |
|
|
|
rsp := backend.DataResponse{} |
|
|
|
rsp := backend.DataResponse{} |
|
|
|
|
|
|
|
|
|
|
|
labelsField := data.NewFieldFromFieldType(data.FieldTypeJSON, 0) |
|
|
|
labelsField := data.NewFieldFromFieldType(data.FieldTypeJSON, 0) |
|
|
@ -1084,7 +1084,7 @@ func readCategorizedStream(iter *jsonitere.Iterator) backend.DataResponse { |
|
|
|
return rsp |
|
|
|
return rsp |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func readCategorizedStreamField(iter *jsonitere.Iterator) (map[string]interface{}, map[string]interface{}, error) { |
|
|
|
func readCategorizedStreamField(iter *sdkjsoniter.Iterator) (map[string]interface{}, map[string]interface{}, error) { |
|
|
|
parsedLabels := data.Labels{} |
|
|
|
parsedLabels := data.Labels{} |
|
|
|
structuredMetadata := data.Labels{} |
|
|
|
structuredMetadata := data.Labels{} |
|
|
|
var parsedLabelsMap map[string]interface{} |
|
|
|
var parsedLabelsMap map[string]interface{} |
|
|
|