diff --git a/pkg/tsdb/influxdb/response_parser.go b/pkg/tsdb/influxdb/response_parser.go index f38e69fbe25..52bf876fd38 100644 --- a/pkg/tsdb/influxdb/response_parser.go +++ b/pkg/tsdb/influxdb/response_parser.go @@ -56,32 +56,59 @@ func parseJSON(buf io.ReadCloser) (Response, error) { func transformRows(rows []Row, query Query) data.Frames { frames := data.Frames{} for _, row := range rows { - for columnIndex, column := range row.Columns { + var hasTimeCol = false + + for _, column := range row.Columns { if column == "time" { - continue + hasTimeCol = true } + } - var timeArray []time.Time - var valueArray []*float64 + if !hasTimeCol { + var values []string for _, valuePair := range row.Values { - timestamp, timestampErr := parseTimestamp(valuePair[0]) - // we only add this row if the timestamp is valid - if timestampErr == nil { - value := parseValue(valuePair[columnIndex]) - timeArray = append(timeArray, timestamp) - valueArray = append(valueArray, value) + if strings.Contains(strings.ToLower(query.RawQuery), strings.ToLower("SHOW TAG VALUES")) { + if len(valuePair) >= 2 { + values = append(values, valuePair[1].(string)) + } + } else { + if len(valuePair) >= 1 { + values = append(values, valuePair[0].(string)) + } } } - name := formatFrameName(row, column, query) - timeField := data.NewField("time", nil, timeArray) - valueField := data.NewField("value", row.Tags, valueArray) + field := data.NewField("value", nil, values) + frames = append(frames, data.NewFrame(row.Name, field)) + } else { + for columnIndex, column := range row.Columns { + if column == "time" { + continue + } + + var timeArray []time.Time + var valueArray []*float64 + + for _, valuePair := range row.Values { + timestamp, timestampErr := parseTimestamp(valuePair[0]) + // we only add this row if the timestamp is valid + if timestampErr == nil { + value := parseValue(valuePair[columnIndex]) + timeArray = append(timeArray, timestamp) + valueArray = append(valueArray, value) + } + } + name := formatFrameName(row, column, query) + + timeField := data.NewField("time", nil, timeArray) + valueField := data.NewField("value", row.Tags, valueArray) - // set a nice name on the value-field - valueField.SetConfig(&data.FieldConfig{DisplayNameFromDS: name}) + // set a nice name on the value-field + valueField.SetConfig(&data.FieldConfig{DisplayNameFromDS: name}) - frames = append(frames, newDataFrame(name, query.RawQuery, timeField, valueField)) + frames = append(frames, newDataFrame(name, query.RawQuery, timeField, valueField)) + } } } diff --git a/pkg/tsdb/influxdb/response_parser_test.go b/pkg/tsdb/influxdb/response_parser_test.go index e47c6b4cae7..56599b2bfd6 100644 --- a/pkg/tsdb/influxdb/response_parser_test.go +++ b/pkg/tsdb/influxdb/response_parser_test.go @@ -91,6 +91,85 @@ func TestInfluxdbResponseParser(t *testing.T) { } }) + t.Run("Influxdb response parser should parse metricFindQueries normally", func(t *testing.T) { + parser := &ResponseParser{} + + response := ` + { + "results": [ + { + "series": [ + { + "refId": "metricFindQuery", + "name": "cpu", + "values": [ + ["cpu"], + ["disk"], + ["logs"] + ] + } + ] + } + ] + } + ` + + var queries []Query + queries = append(queries, Query{RefID: "metricFindQuery"}) + newField := data.NewField("value", nil, []string{ + "cpu", "disk", "logs", + }) + testFrame := data.NewFrame("cpu", + newField, + ) + + result := parser.Parse(prepare(response), queries) + + frame := result.Responses["metricFindQuery"] + if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + t.Errorf("Result mismatch (-want +got):\n%s", diff) + } + }) + + t.Run("Influxdb response parser should parse metricFindQueries->SHOW TAG VALUES normally", func(t *testing.T) { + parser := &ResponseParser{} + + response := ` + { + "results": [ + { + "series": [ + { + "name": "cpu", + "values": [ + ["values", "cpu-total"], + ["values", "cpu0"], + ["values", "cpu1"] + ] + } + ] + } + ] + } + ` + + var queries []Query + queries = append(queries, Query{RawQuery: "SHOW TAG VALUES", RefID: "metricFindQuery"}) + newField := data.NewField("value", nil, []string{ + "cpu-total", "cpu0", "cpu1", + }) + testFrame := data.NewFrame("cpu", + newField, + ) + + result := parser.Parse(prepare(response), queries) + + frame := result.Responses["metricFindQuery"] + if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + t.Errorf("Result mismatch (-want +got):\n%s", diff) + } + }) + t.Run("Influxdb response parser should parse two responses with different refIDs", func(t *testing.T) { parser := &ResponseParser{} @@ -130,7 +209,12 @@ func TestInfluxdbResponseParser(t *testing.T) { "series": [ { "name": "cpu", - "columns": ["time","mean"] + "columns": ["time","cpu"], + "values": [ + ["values", "cpu-total"], + ["values", "cpu0"], + ["values", "cpu1"] + ] } ] } diff --git a/public/app/plugins/datasource/influxdb/datasource.ts b/public/app/plugins/datasource/influxdb/datasource.ts index dba531a1e88..e9cff1ca03a 100644 --- a/public/app/plugins/datasource/influxdb/datasource.ts +++ b/public/app/plugins/datasource/influxdb/datasource.ts @@ -445,10 +445,11 @@ export default class InfluxDatasource extends DataSourceWithBackend { - if (this.isFlux) { + if (this.isFlux || (config.featureToggles.influxdbBackendMigration && this.access === 'proxy')) { const target: InfluxQuery = { refId: 'metricFindQuery', query, + rawQuery: true, }; return lastValueFrom( super.query({