diff --git a/go.mod b/go.mod index 46d37191fb5..3d7c7a457f8 100644 --- a/go.mod +++ b/go.mod @@ -76,6 +76,7 @@ require ( github.com/mattn/go-sqlite3 v1.14.7 github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f + github.com/ohler55/ojg v1.12.9 github.com/opentracing/opentracing-go v1.2.0 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pkg/browser v0.0.0-20210904010418-6d279e18f982 // indirect @@ -88,7 +89,6 @@ require ( github.com/robfig/cron v0.0.0-20180505203441-b41be1df6967 github.com/robfig/cron/v3 v3.0.1 github.com/russellhaering/goxmldsig v1.1.1 - github.com/spyzhov/ajson v0.4.2 github.com/stretchr/testify v1.7.0 github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf github.com/timberio/go-datemath v0.1.1-0.20200323150745-74ddef604fff diff --git a/go.sum b/go.sum index 0bc56a152ac..02c84c72018 100644 --- a/go.sum +++ b/go.sum @@ -1812,6 +1812,8 @@ github.com/nsqio/go-nsq v1.0.7/go.mod h1:XP5zaUs3pqf+Q71EqUJs3HYfBIqfK6G83WQMdNN github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/ohler55/ojg v1.12.9 h1:HIHORjvA/i2IyDGgf9zzkFZc0yhEZIi3Tte+m+XBzTs= +github.com/ohler55/ojg v1.12.9/go.mod h1:LBbIVRAgoFbYBXQhRhuEpaJIqq+goSO63/FQ+nyJU88= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= @@ -2217,8 +2219,6 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= -github.com/spyzhov/ajson v0.4.2 h1:JMByd/jZApPKDvNsmO90X2WWGbmT2ahDFp73QhZbg3s= -github.com/spyzhov/ajson v0.4.2/go.mod h1:63V+CGM6f1Bu/p4nLIN8885ojBdt88TbLoSFzyqMuVA= github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/streadway/amqp v0.0.0-20180528204448-e5adc2ada8b8/go.mod h1:1WNBiOZtZQLpVAyu0iTduoJL9hEsMloAK5XWrtW0xdY= diff --git a/pkg/services/live/pipeline/converter_json_exact.go b/pkg/services/live/pipeline/converter_json_exact.go index 38e0e7981d7..0ccf8b21657 100644 --- a/pkg/services/live/pipeline/converter_json_exact.go +++ b/pkg/services/live/pipeline/converter_json_exact.go @@ -9,7 +9,8 @@ import ( "time" "github.com/grafana/grafana-plugin-sdk-go/data" - "github.com/spyzhov/ajson" + "github.com/ohler55/ojg/jp" + "github.com/ohler55/ojg/oj" ) type ExactJsonConverterConfig struct { @@ -34,10 +35,10 @@ func (c *ExactJsonConverter) Type() string { } func (c *ExactJsonConverter) Convert(_ context.Context, vars Vars, body []byte) ([]*ChannelFrame, error) { - //obj, err := oj.Parse(body) - //if err != nil { - // return nil, err - //} + obj, err := oj.Parse(body) + if err != nil { + return nil, err + } var fields []*data.Field @@ -51,17 +52,15 @@ func (c *ExactJsonConverter) Convert(_ context.Context, vars Vars, body []byte) if strings.HasPrefix(f.Value, "$") { // JSON path. - nodes, err := ajson.JSONPath(body, f.Value) + fragments, err := jp.ParseString(f.Value[1:]) if err != nil { return nil, err } - if len(nodes) == 0 { + values := fragments.Get(obj) + if len(values) == 0 { field.Set(0, nil) - } else if len(nodes) == 1 { - val, err := nodes[0].Value() - if err != nil { - return nil, err - } + } else if len(values) == 1 { + val := values[0] switch f.Type { case data.FieldTypeNullableFloat64: if val == nil { @@ -73,7 +72,7 @@ func (c *ExactJsonConverter) Convert(_ context.Context, vars Vars, body []byte) case int64: field.SetConcrete(0, float64(v)) default: - return nil, errors.New("malformed float64 type for: " + f.Name) + return nil, fmt.Errorf("malformed float64 type for %s: %T", f.Name, v) } } case data.FieldTypeNullableString: @@ -88,41 +87,6 @@ func (c *ExactJsonConverter) Convert(_ context.Context, vars Vars, body []byte) } else { return nil, errors.New("too many values") } - //x, err := jp.ParseString(f.Value[1:]) - //if err != nil { - // return nil, err - //} - //value := x.Get(obj) - //if len(value) == 0 { - // field.Set(0, nil) - //} else if len(value) == 1 { - // val := value[0] - // switch f.Type { - // case data.FieldTypeNullableFloat64: - // if val == nil { - // field.Set(0, nil) - // } else { - // switch v := val.(type) { - // case float64: - // field.SetConcrete(0, v) - // case int64: - // field.SetConcrete(0, float64(v)) - // default: - // return nil, errors.New("malformed float64 type for: " + f.Name) - // } - // } - // case data.FieldTypeNullableString: - // v, ok := val.(string) - // if !ok { - // return nil, errors.New("malformed string type") - // } - // field.SetConcrete(0, v) - // default: - // return nil, fmt.Errorf("unsupported field type: %s (%s)", f.Type, f.Name) - // } - //} else { - // return nil, errors.New("too many values") - //} } else if strings.HasPrefix(f.Value, "{") { // Goja script. script := strings.Trim(f.Value, "{}") @@ -162,33 +126,18 @@ func (c *ExactJsonConverter) Convert(_ context.Context, vars Vars, body []byte) labels := map[string]string{} for _, label := range f.Labels { if strings.HasPrefix(label.Value, "$") { - nodes, err := ajson.JSONPath(body, label.Value) + fragments, err := jp.ParseString(label.Value[1:]) if err != nil { return nil, err } - if len(nodes) == 0 { + values := fragments.Get(obj) + if len(values) == 0 { labels[label.Name] = "" - } else if len(nodes) == 1 { - value, err := nodes[0].Value() - if err != nil { - return nil, err - } - labels[label.Name] = fmt.Sprintf("%v", value) + } else if len(values) == 1 { + labels[label.Name] = fmt.Sprintf("%v", values[0]) } else { return nil, errors.New("too many values for a label") } - //x, err := jp.ParseString(label.Value[1:]) - //if err != nil { - // return nil, err - //} - //value := x.Get(obj) - //if len(value) == 0 { - // labels[label.Name] = "" - //} else if len(value) == 1 { - // labels[label.Name] = fmt.Sprintf("%v", value[0]) - //} else { - // return nil, errors.New("too many values for a label") - //} } else if strings.HasPrefix(label.Value, "{") { script := strings.Trim(label.Value, "{}") var err error diff --git a/pkg/services/live/pipeline/converter_json_exact_test.go b/pkg/services/live/pipeline/converter_json_exact_test.go index e1bfb90bbc1..f09b19543a2 100644 --- a/pkg/services/live/pipeline/converter_json_exact_test.go +++ b/pkg/services/live/pipeline/converter_json_exact_test.go @@ -36,6 +36,37 @@ func checkExactConversion(tb testing.TB, file string, fields []Field) *backend.D return dr } +func BenchmarkExactJsonConverter_Convert(b *testing.B) { + content := loadTestJson(b, "json_exact") + + converter := NewExactJsonConverter(ExactJsonConverterConfig{ + Fields: []Field{ + { + Name: "ax", + Value: "$.ax", + Type: data.FieldTypeNullableFloat64, + }, { + Name: "array_value", + Value: "$.string_array[0]", + Type: data.FieldTypeNullableString, + }, { + Name: "map_key", + Value: "$.map_with_floats['key1']", + Type: data.FieldTypeNullableFloat64, + }, + }, + }) + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := converter.Convert(context.Background(), Vars{}, content) + require.NoError(b, err) + //require.Len(b, cf, 1) + //require.Len(b, cf[0].Frame.Fields, 3) + } +} + func TestExactJsonConverter_Convert(t *testing.T) { checkExactConversion(t, "json_exact", []Field{ {