diff --git a/pkg/plugin/response.go b/pkg/plugin/response.go index ec9d22d..670b72e 100644 --- a/pkg/plugin/response.go +++ b/pkg/plugin/response.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "io" + "time" "github.com/VictoriaMetrics/metricsql" "github.com/grafana/grafana-plugin-sdk-go/backend" @@ -84,6 +85,16 @@ func parseStreamResponse(reader io.Reader) backend.DataResponse { return newResponseError(err, backend.StatusInternal) } labelsField.Append(d) + + if timeFd.Len() == 0 { + lineField.Append(string(d)) + } + } + + if timeFd.Len() == 0 { + for i := 0; i < lineField.Len(); i++ { + timeFd.Append(time.Now()) + } } frame := data.NewFrame("", timeFd, lineField, labelsField) diff --git a/pkg/plugin/response_test.go b/pkg/plugin/response_test.go index cee4e96..ea28470 100644 --- a/pkg/plugin/response_test.go +++ b/pkg/plugin/response_test.go @@ -127,6 +127,77 @@ func Test_parseStreamResponse(t *testing.T) { frame.Meta = &data.FrameMeta{} rsp.Frames = append(rsp.Frames, frame) + return rsp + }, + }, + { + name: "response with different labels and without standard fields", + response: `{"stream":"stderr","count(*)":"394"} +{"stream":"stdout","count(*)":"21"}`, + want: func() backend.DataResponse { + labelsField := data.NewFieldFromFieldType(data.FieldTypeJSON, 0) + labelsField.Name = gLabelsField + + timeFd := data.NewFieldFromFieldType(data.FieldTypeTime, 0) + timeFd.Name = gTimeField + + lineField := data.NewFieldFromFieldType(data.FieldTypeString, 0) + lineField.Name = gLineField + + lineField.Append(`{"count(*)":"394","stream":"stderr"}`) + lineField.Append(`{"count(*)":"21","stream":"stdout"}`) + + labels := data.Labels{ + "count(*)": "394", + "stream": "stderr", + } + + b, _ := labelsToJSON(labels) + labelsField.Append(b) + + labels = data.Labels{ + "count(*)": "21", + "stream": "stdout", + } + b, _ = labelsToJSON(labels) + labelsField.Append(b) + frame := data.NewFrame("", timeFd, lineField, labelsField) + + rsp := backend.DataResponse{} + frame.Meta = &data.FrameMeta{} + rsp.Frames = append(rsp.Frames, frame) + + return rsp + }, + }, + { + name: "response with different labels only one label", + response: `{"level":""}`, + want: func() backend.DataResponse { + labelsField := data.NewFieldFromFieldType(data.FieldTypeJSON, 0) + labelsField.Name = gLabelsField + + timeFd := data.NewFieldFromFieldType(data.FieldTypeTime, 0) + timeFd.Name = gTimeField + + lineField := data.NewFieldFromFieldType(data.FieldTypeString, 0) + lineField.Name = gLineField + + lineField.Append(`{"level":""}`) + + labels := data.Labels{ + "level": "", + } + + b, _ := labelsToJSON(labels) + labelsField.Append(b) + + frame := data.NewFrame("", timeFd, lineField, labelsField) + + rsp := backend.DataResponse{} + frame.Meta = &data.FrameMeta{} + rsp.Frames = append(rsp.Frames, frame) + return rsp }, }, @@ -135,7 +206,24 @@ func Test_parseStreamResponse(t *testing.T) { t.Run(tt.name, func(t *testing.T) { r := io.NopCloser(bytes.NewBuffer([]byte(tt.response))) w := tt.want() - if got := parseStreamResponse(r); !reflect.DeepEqual(got, w) { + got := parseStreamResponse(r) + // if time field is empty, fill it with the value from the response + // because time field in the parseStreamResponse generated as time.Now() + for i, frame := range w.Frames { + for j, field := range frame.Fields { + if field.Name == gTimeField && field.Len() == 0 { + for _, f := range got.Frames { + for _, f2 := range f.Fields { + if f2.Name == gTimeField { + w.Frames[i].Fields[j] = f2 + } + } + } + } + } + } + + if !reflect.DeepEqual(got, w) { t.Errorf("parseStreamResponse() = %#v, want %#v", got, w) } })