diff --git a/pkg/tsdb/influxdb/influxql/buffered/response_parser.go b/pkg/tsdb/influxdb/influxql/buffered/response_parser.go index bcc89ea3960..0d456329879 100644 --- a/pkg/tsdb/influxdb/influxql/buffered/response_parser.go +++ b/pkg/tsdb/influxdb/influxql/buffered/response_parser.go @@ -330,18 +330,22 @@ func newFrameWithoutTimeField(row models.Row, query models.Query) *data.Frame { var values []*string for _, valuePair := range row.Values { - if strings.Contains(strings.ToLower(query.RawQuery), strings.ToLower("SHOW TAG VALUES")) { - if len(valuePair) >= 2 { - values = append(values, util.ParseString(valuePair[1])) - } - } else if strings.Contains(strings.ToLower(query.RawQuery), strings.ToLower("SHOW DIAGNOSTICS")) { - // https://docs.influxdata.com/platform/monitoring/influxdata-platform/tools/show-diagnostics/ - for _, vp := range valuePair { - values = append(values, util.ParseString(vp)) - } + if strings.Contains(strings.ToLower(query.RawQuery), strings.ToLower("CARDINALITY")) { + values = append(values, util.ParseString(valuePair[0])) } else { - if len(valuePair) >= 1 { - values = append(values, util.ParseString(valuePair[0])) + if strings.Contains(strings.ToLower(query.RawQuery), strings.ToLower("SHOW TAG VALUES")) { + if len(valuePair) >= 2 { + values = append(values, util.ParseString(valuePair[1])) + } + } else if strings.Contains(strings.ToLower(query.RawQuery), strings.ToLower("SHOW DIAGNOSTICS")) { + // https://docs.influxdata.com/platform/monitoring/influxdata-platform/tools/show-diagnostics/ + for _, vp := range valuePair { + values = append(values, util.ParseString(vp)) + } + } else { + if len(valuePair) >= 1 { + values = append(values, util.ParseString(valuePair[0])) + } } } } diff --git a/pkg/tsdb/influxdb/influxql/buffered/response_parser_test.go b/pkg/tsdb/influxdb/influxql/buffered/response_parser_test.go index c6f4028a32f..890d25a4125 100644 --- a/pkg/tsdb/influxdb/influxql/buffered/response_parser_test.go +++ b/pkg/tsdb/influxdb/influxql/buffered/response_parser_test.go @@ -5,7 +5,6 @@ import ( "fmt" "io" "os" - "path" "path/filepath" "strings" "testing" @@ -34,9 +33,9 @@ func readJsonFile(filePath string) io.ReadCloser { return io.NopCloser(strings.NewReader(string(bytes))) } -func generateQuery(resFormat string, alias string) *models.Query { +func generateQuery(query, resFormat, alias string) *models.Query { return &models.Query{ - RawQuery: "Test raw query", + RawQuery: query, UseRawQuery: true, Alias: alias, ResultFormat: resFormat, @@ -83,25 +82,43 @@ func TestReadInfluxAsTable(t *testing.T) { func runScenario(tf string, resultFormat string) func(t *testing.T) { return func(t *testing.T) { - f, err := os.Open(path.Join(testPath, filepath.Clean(tf+".json"))) - require.NoError(t, err) + f := readJsonFile(tf) - query := generateQuery(resultFormat, "") + query := generateQuery("Test raw query", resultFormat, "") - rsp := ResponseParse(io.NopCloser(f), 200, query) - require.NoError(t, rsp.Error) - - fname := tf + "." + resultFormat + ".golden" - experimental.CheckGoldenJSONResponse(t, testPath, fname, rsp, shouldUpdate) + runQuery(t, f, tf, resultFormat, query) } } +func runQuery(t *testing.T, f io.ReadCloser, tf string, rf string, query *models.Query) { + rsp := ResponseParse(f, 200, query) + + if strings.Contains(tf, "error") { + require.Error(t, rsp.Error) + return + } + require.NoError(t, rsp.Error) + + fname := tf + "." + rf + ".golden" + experimental.CheckGoldenJSONResponse(t, testPath, fname, rsp, shouldUpdate) +} + +func TestParsingAsTimeSeriesWithoutTimeColumn(t *testing.T) { + t.Run("cardinality", func(t *testing.T) { + f := readJsonFile("cardinality") + + query := generateQuery(`SHOW TAG VALUES CARDINALITY with key = "host"`, "time_series", "") + + runQuery(t, f, "cardinality", "time_series", query) + }) +} + func TestInfluxdbResponseParser(t *testing.T) { t.Run("Influxdb response parser should handle invalid JSON", func(t *testing.T) { result := ResponseParse( io.NopCloser(strings.NewReader(`{ invalid }`)), 200, - generateQuery("time_series", ""), + generateQuery("Test raw query", "time_series", ""), ) require.Nil(t, result.Frames) @@ -132,7 +149,7 @@ func TestInfluxdbResponseParser(t *testing.T) { ) t.Run("should parse aliases", func(t *testing.T) { - result := ResponseParse(readJsonFile("response"), 200, generateQuery("time_sereies", "alias $m $measurement")) + result := ResponseParse(readJsonFile("response"), 200, generateQuery("Test raw query", "time_sereies", "alias $m $measurement")) name := "alias cpu.upc cpu.upc" testFrame.Name = name @@ -141,7 +158,7 @@ func TestInfluxdbResponseParser(t *testing.T) { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - query := generateQuery("time_series", "alias $col") + query := generateQuery("Test raw query", "time_series", "alias $col") query.Measurement = "10m" result = ResponseParse(readJsonFile("response"), 200, query) name = "alias mean" @@ -162,7 +179,7 @@ func TestInfluxdbResponseParser(t *testing.T) { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - result = ResponseParse(readJsonFile("response"), 200, generateQuery("time_series", "alias $tag_datacenter")) + result = ResponseParse(readJsonFile("response"), 200, generateQuery("Test raw query", "time_series", "alias $tag_datacenter")) name = "alias America" testFrame.Name = name newField = data.NewField("Value", labels, []*float64{ @@ -174,7 +191,7 @@ func TestInfluxdbResponseParser(t *testing.T) { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - result = ResponseParse(readJsonFile("response"), 200, generateQuery("time_series", "alias $tag_datacenter/$tag_datacenter")) + result = ResponseParse(readJsonFile("response"), 200, generateQuery("Test raw query", "time_series", "alias $tag_datacenter/$tag_datacenter")) name = "alias America/America" testFrame.Name = name newField = data.NewField("Value", labels, []*float64{ @@ -186,7 +203,7 @@ func TestInfluxdbResponseParser(t *testing.T) { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - query = generateQuery("time_series", "alias [[col]]") + query = generateQuery("Test raw query", "time_series", "alias [[col]]") query.Measurement = "10m" result = ResponseParse(readJsonFile("response"), 200, query) name = "alias mean" @@ -196,7 +213,7 @@ func TestInfluxdbResponseParser(t *testing.T) { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - result = ResponseParse(readJsonFile("response"), 200, generateQuery("time_series", "alias $0 $1 $2 $3 $4")) + result = ResponseParse(readJsonFile("response"), 200, generateQuery("Test raw query", "time_series", "alias $0 $1 $2 $3 $4")) name = "alias cpu upc $2 $3 $4" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name @@ -204,7 +221,7 @@ func TestInfluxdbResponseParser(t *testing.T) { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - result = ResponseParse(readJsonFile("response"), 200, generateQuery("time_series", "alias $0, $1 - $2 - $3, $4: something")) + result = ResponseParse(readJsonFile("response"), 200, generateQuery("Test raw query", "time_series", "alias $0, $1 - $2 - $3, $4: something")) name = "alias cpu, upc - $2 - $3, $4: something" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name @@ -212,7 +229,7 @@ func TestInfluxdbResponseParser(t *testing.T) { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - result = ResponseParse(readJsonFile("response"), 200, generateQuery("time_series", "alias $1")) + result = ResponseParse(readJsonFile("response"), 200, generateQuery("Test raw query", "time_series", "alias $1")) name = "alias upc" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name @@ -220,7 +237,7 @@ func TestInfluxdbResponseParser(t *testing.T) { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - result = ResponseParse(readJsonFile("response"), 200, generateQuery("time_series", "alias $5")) + result = ResponseParse(readJsonFile("response"), 200, generateQuery("Test raw query", "time_series", "alias $5")) name = "alias $5" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name @@ -228,7 +245,7 @@ func TestInfluxdbResponseParser(t *testing.T) { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - result = ResponseParse(readJsonFile("response"), 200, generateQuery("time_series", "series alias")) + result = ResponseParse(readJsonFile("response"), 200, generateQuery("Test raw query", "time_series", "series alias")) name = "series alias" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name @@ -236,7 +253,7 @@ func TestInfluxdbResponseParser(t *testing.T) { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - query = generateQuery("time_series", "alias [[m]] [[measurement]]") + query = generateQuery("Test raw query", "time_series", "alias [[m]] [[measurement]]") query.Measurement = "10m" result = ResponseParse(readJsonFile("response"), 200, query) name = "alias cpu.upc cpu.upc" @@ -246,7 +263,7 @@ func TestInfluxdbResponseParser(t *testing.T) { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - result = ResponseParse(readJsonFile("response"), 200, generateQuery("time_series", "alias [[tag_datacenter]]")) + result = ResponseParse(readJsonFile("response"), 200, generateQuery("Test raw query", "time_series", "alias [[tag_datacenter]]")) name = "alias America" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name @@ -254,7 +271,7 @@ func TestInfluxdbResponseParser(t *testing.T) { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - result = ResponseParse(readJsonFile("response"), 200, generateQuery("time_series", "alias [[tag_dc.region.name]]")) + result = ResponseParse(readJsonFile("response"), 200, generateQuery("Test raw query", "time_series", "alias [[tag_dc.region.name]]")) name = "alias Northeast" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name @@ -262,7 +279,7 @@ func TestInfluxdbResponseParser(t *testing.T) { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - result = ResponseParse(readJsonFile("response"), 200, generateQuery("time_series", "alias [[tag_cluster-name]]")) + result = ResponseParse(readJsonFile("response"), 200, generateQuery("Test raw query", "time_series", "alias [[tag_cluster-name]]")) name = "alias Cluster" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name @@ -270,7 +287,7 @@ func TestInfluxdbResponseParser(t *testing.T) { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - result = ResponseParse(readJsonFile("response"), 200, generateQuery("time_series", "alias [[tag_/cluster/name/]]")) + result = ResponseParse(readJsonFile("response"), 200, generateQuery("Test raw query", "time_series", "alias [[tag_/cluster/name/]]")) name = "alias Cluster/" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name @@ -278,7 +295,7 @@ func TestInfluxdbResponseParser(t *testing.T) { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - result = ResponseParse(readJsonFile("response"), 200, generateQuery("time_series", "alias [[tag_@cluster@name@]]")) + result = ResponseParse(readJsonFile("response"), 200, generateQuery("Test raw query", "time_series", "alias [[tag_@cluster@name@]]")) name = "alias Cluster@" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name @@ -288,7 +305,7 @@ func TestInfluxdbResponseParser(t *testing.T) { }) t.Run("shouldn't parse aliases", func(t *testing.T) { - result := ResponseParse(readJsonFile("response"), 200, generateQuery("time_series", "alias words with no brackets")) + result := ResponseParse(readJsonFile("response"), 200, generateQuery("Test raw query", "time_series", "alias words with no brackets")) name := "alias words with no brackets" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name @@ -296,7 +313,7 @@ func TestInfluxdbResponseParser(t *testing.T) { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - result = ResponseParse(readJsonFile("response"), 200, generateQuery("time_series", "alias Test 1.5")) + result = ResponseParse(readJsonFile("response"), 200, generateQuery("Test raw query", "time_series", "alias Test 1.5")) name = "alias Test 1.5" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name @@ -304,7 +321,7 @@ func TestInfluxdbResponseParser(t *testing.T) { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - result = ResponseParse(readJsonFile("response"), 200, generateQuery("time_series", "alias Test -1")) + result = ResponseParse(readJsonFile("response"), 200, generateQuery("Test raw query", "time_series", "alias Test -1")) name = "alias Test -1" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name @@ -315,13 +332,13 @@ func TestInfluxdbResponseParser(t *testing.T) { }) t.Run("Influxdb response parser with errors", func(t *testing.T) { - result := ResponseParse(readJsonFile("error_response"), 200, generateQuery("time_series", "")) + result := ResponseParse(readJsonFile("error_response"), 200, generateQuery("Test raw query", "time_series", "")) require.EqualError(t, result.Error, "query-timeout limit exceeded") }) t.Run("Influxdb response parser with top-level error", func(t *testing.T) { - result := ResponseParse(readJsonFile("error_on_top_level_response"), 200, generateQuery("time_series", "")) + result := ResponseParse(readJsonFile("error_on_top_level_response"), 200, generateQuery("Test raw query", "time_series", "")) require.Nil(t, result.Frames) require.EqualError(t, result.Error, "error parsing query: found THING") }) @@ -356,7 +373,7 @@ func TestInfluxdbResponseParser(t *testing.T) { ) testFrame.Meta = &data.FrameMeta{PreferredVisualization: util.GraphVisType, ExecutedQueryString: "Test raw query"} - result := ResponseParse(readJsonFile("invalid_timestamp_format"), 200, generateQuery("time_series", "")) + result := ResponseParse(readJsonFile("invalid_timestamp_format"), 200, generateQuery("Test raw query", "time_series", "")) if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) diff --git a/pkg/tsdb/influxdb/influxql/converter/converter.go b/pkg/tsdb/influxdb/influxql/converter/converter.go index 63cfadb878a..0cdbc010b73 100644 --- a/pkg/tsdb/influxdb/influxql/converter/converter.go +++ b/pkg/tsdb/influxdb/influxql/converter/converter.go @@ -2,6 +2,7 @@ package converter import ( "fmt" + "strconv" "strings" "time" @@ -359,6 +360,18 @@ func handleTimeSeriesFormatWithTimeColumn(valueFields data.Fields, tags map[stri func handleTimeSeriesFormatWithoutTimeColumn(valueFields data.Fields, columns []string, measurement string, query *models.Query) *data.Frame { // Frame without time column + if strings.Contains(strings.ToLower(query.RawQuery), strings.ToLower("CARDINALITY")) { + var stringArray []*string + for _, v := range valueFields { + if f, ok := v.At(0).(*float64); ok { + str := strconv.FormatFloat(*f, 'f', -1, 64) + stringArray = append(stringArray, util.ParseString(str)) + } else { + stringArray = append(stringArray, util.ParseString(v.At(0))) + } + } + return data.NewFrame(measurement, data.NewField("Value", nil, stringArray)) + } if len(columns) >= 2 && strings.Contains(strings.ToLower(query.RawQuery), strings.ToLower("SHOW TAG VALUES")) { return data.NewFrame(measurement, valueFields[1]) } diff --git a/pkg/tsdb/influxdb/influxql/querydata/stream_parser_test.go b/pkg/tsdb/influxdb/influxql/querydata/stream_parser_test.go index dfd739453d3..7e2f8951bbe 100644 --- a/pkg/tsdb/influxdb/influxql/querydata/stream_parser_test.go +++ b/pkg/tsdb/influxdb/influxql/querydata/stream_parser_test.go @@ -1,13 +1,14 @@ package querydata import ( + "fmt" + "io" "os" "path" "path/filepath" "strings" "testing" - "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/experimental" "github.com/stretchr/testify/require" @@ -19,6 +20,24 @@ const ( testPath = "../testdata" ) +func readJsonFile(filePath string) io.ReadCloser { + bytes, err := os.ReadFile(filepath.Join(testPath, filepath.Clean(filePath)+".json")) + if err != nil { + panic(fmt.Sprintf("cannot read the file: %s", filePath)) + } + + return io.NopCloser(strings.NewReader(string(bytes))) +} + +func generateQuery(query, resFormat, alias string) *models.Query { + return &models.Query{ + RawQuery: query, + UseRawQuery: true, + Alias: alias, + ResultFormat: resFormat, + } +} + var testFiles = []string{ "all_values_are_null", "influx_select_all_from_cpu", @@ -55,26 +74,34 @@ func TestReadInfluxAsTable(t *testing.T) { func runScenario(tf string, resultFormat string) func(t *testing.T) { return func(t *testing.T) { - f, err := os.Open(path.Join(testPath, filepath.Clean(tf+".json"))) - require.NoError(t, err) + f := readJsonFile(tf) - var rsp *backend.DataResponse + query := generateQuery("Test raw query", resultFormat, "") - query := &models.Query{ - RawQuery: "Test raw query", - UseRawQuery: true, - ResultFormat: resultFormat, - } - - rsp = ResponseParse(f, 200, query) - - if strings.Contains(tf, "error") { - require.Error(t, rsp.Error) - return - } - require.NoError(t, rsp.Error) - - fname := tf + "." + resultFormat + ".golden" - experimental.CheckGoldenJSONResponse(t, testPath, fname, rsp, shouldUpdate) + runQuery(t, f, tf, resultFormat, query) } } + +func runQuery(t *testing.T, f io.ReadCloser, tf string, rf string, query *models.Query) { + rsp := ResponseParse(f, 200, query) + + if strings.Contains(tf, "error") { + require.Error(t, rsp.Error) + return + } + require.NoError(t, rsp.Error) + + fname := tf + "." + rf + ".golden" + experimental.CheckGoldenJSONResponse(t, testPath, fname, rsp, shouldUpdate) +} + +func TestParsingAsTimeSeriesWithoutTimeColumn(t *testing.T) { + t.Run("cardinality", func(t *testing.T) { + f, err := os.Open(path.Join(testPath, filepath.Clean("cardinality.json"))) + require.NoError(t, err) + + query := generateQuery(`SHOW TAG VALUES CARDINALITY with key = "host"`, "time_series", "") + + runQuery(t, f, "cardinality", "time_series", query) + }) +} diff --git a/pkg/tsdb/influxdb/influxql/testdata/cardinality.json b/pkg/tsdb/influxdb/influxql/testdata/cardinality.json new file mode 100644 index 00000000000..142f3cdec85 --- /dev/null +++ b/pkg/tsdb/influxdb/influxql/testdata/cardinality.json @@ -0,0 +1 @@ +{"results":[{"statement_id":0,"series":[{"name":"cpu","columns":["count"],"values":[[1]]},{"name":"disk","columns":["count"],"values":[[1]]},{"name":"diskio","columns":["count"],"values":[[1]]},{"name":"kernel","columns":["count"],"values":[[1]]},{"name":"logs","columns":["count"],"values":[[1]]},{"name":"mem","columns":["count"],"values":[[1]]},{"name":"processes","columns":["count"],"values":[[1]]},{"name":"swap","columns":["count"],"values":[[1]]},{"name":"system","columns":["count"],"values":[[1]]}]}]} diff --git a/pkg/tsdb/influxdb/influxql/testdata/cardinality.table.golden.jsonc b/pkg/tsdb/influxdb/influxql/testdata/cardinality.table.golden.jsonc new file mode 100644 index 00000000000..fa5e42a0a94 --- /dev/null +++ b/pkg/tsdb/influxdb/influxql/testdata/cardinality.table.golden.jsonc @@ -0,0 +1,76 @@ +// 🌟 This was machine generated. Do not edit. 🌟 +// +// Frame[0] { +// "typeVersion": [ +// 0, +// 0 +// ], +// "preferredVisualisationType": "table", +// "executedQueryString": "Test raw query" +// } +// Name: cpu +// Dimensions: 1 Fields by 9 Rows +// +------------------+ +// | Name: count | +// | Labels: | +// | Type: []*float64 | +// +------------------+ +// | 1 | +// | 1 | +// | 1 | +// | 1 | +// | 1 | +// | 1 | +// | 1 | +// | 1 | +// | 1 | +// +------------------+ +// +// +// 🌟 This was machine generated. Do not edit. 🌟 +{ + "status": 200, + "frames": [ + { + "schema": { + "name": "cpu", + "meta": { + "typeVersion": [ + 0, + 0 + ], + "preferredVisualisationType": "table", + "executedQueryString": "Test raw query" + }, + "fields": [ + { + "name": "count", + "type": "number", + "typeInfo": { + "frame": "float64", + "nullable": true + }, + "config": { + "displayNameFromDS": "count" + } + } + ] + }, + "data": { + "values": [ + [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ] + ] + } + } + ] +} \ No newline at end of file diff --git a/pkg/tsdb/influxdb/influxql/testdata/cardinality.time_series.golden.jsonc b/pkg/tsdb/influxdb/influxql/testdata/cardinality.time_series.golden.jsonc new file mode 100644 index 00000000000..5719d64a6fc --- /dev/null +++ b/pkg/tsdb/influxdb/influxql/testdata/cardinality.time_series.golden.jsonc @@ -0,0 +1,337 @@ +// 🌟 This was machine generated. Do not edit. 🌟 +// +// Frame[0] { +// "typeVersion": [ +// 0, +// 0 +// ], +// "preferredVisualisationType": "graph", +// "executedQueryString": "SHOW TAG VALUES CARDINALITY with key = \"host\"" +// } +// Name: cpu +// Dimensions: 1 Fields by 1 Rows +// +-----------------+ +// | Name: Value | +// | Labels: | +// | Type: []*string | +// +-----------------+ +// | 1 | +// +-----------------+ +// +// +// +// Frame[1] +// Name: disk +// Dimensions: 1 Fields by 1 Rows +// +-----------------+ +// | Name: Value | +// | Labels: | +// | Type: []*string | +// +-----------------+ +// | 1 | +// +-----------------+ +// +// +// +// Frame[2] +// Name: diskio +// Dimensions: 1 Fields by 1 Rows +// +-----------------+ +// | Name: Value | +// | Labels: | +// | Type: []*string | +// +-----------------+ +// | 1 | +// +-----------------+ +// +// +// +// Frame[3] +// Name: kernel +// Dimensions: 1 Fields by 1 Rows +// +-----------------+ +// | Name: Value | +// | Labels: | +// | Type: []*string | +// +-----------------+ +// | 1 | +// +-----------------+ +// +// +// +// Frame[4] +// Name: logs +// Dimensions: 1 Fields by 1 Rows +// +-----------------+ +// | Name: Value | +// | Labels: | +// | Type: []*string | +// +-----------------+ +// | 1 | +// +-----------------+ +// +// +// +// Frame[5] +// Name: mem +// Dimensions: 1 Fields by 1 Rows +// +-----------------+ +// | Name: Value | +// | Labels: | +// | Type: []*string | +// +-----------------+ +// | 1 | +// +-----------------+ +// +// +// +// Frame[6] +// Name: processes +// Dimensions: 1 Fields by 1 Rows +// +-----------------+ +// | Name: Value | +// | Labels: | +// | Type: []*string | +// +-----------------+ +// | 1 | +// +-----------------+ +// +// +// +// Frame[7] +// Name: swap +// Dimensions: 1 Fields by 1 Rows +// +-----------------+ +// | Name: Value | +// | Labels: | +// | Type: []*string | +// +-----------------+ +// | 1 | +// +-----------------+ +// +// +// +// Frame[8] +// Name: system +// Dimensions: 1 Fields by 1 Rows +// +-----------------+ +// | Name: Value | +// | Labels: | +// | Type: []*string | +// +-----------------+ +// | 1 | +// +-----------------+ +// +// +// 🌟 This was machine generated. Do not edit. 🌟 +{ + "status": 200, + "frames": [ + { + "schema": { + "name": "cpu", + "meta": { + "typeVersion": [ + 0, + 0 + ], + "preferredVisualisationType": "graph", + "executedQueryString": "SHOW TAG VALUES CARDINALITY with key = \"host\"" + }, + "fields": [ + { + "name": "Value", + "type": "string", + "typeInfo": { + "frame": "string", + "nullable": true + } + } + ] + }, + "data": { + "values": [ + [ + "1" + ] + ] + } + }, + { + "schema": { + "name": "disk", + "fields": [ + { + "name": "Value", + "type": "string", + "typeInfo": { + "frame": "string", + "nullable": true + } + } + ] + }, + "data": { + "values": [ + [ + "1" + ] + ] + } + }, + { + "schema": { + "name": "diskio", + "fields": [ + { + "name": "Value", + "type": "string", + "typeInfo": { + "frame": "string", + "nullable": true + } + } + ] + }, + "data": { + "values": [ + [ + "1" + ] + ] + } + }, + { + "schema": { + "name": "kernel", + "fields": [ + { + "name": "Value", + "type": "string", + "typeInfo": { + "frame": "string", + "nullable": true + } + } + ] + }, + "data": { + "values": [ + [ + "1" + ] + ] + } + }, + { + "schema": { + "name": "logs", + "fields": [ + { + "name": "Value", + "type": "string", + "typeInfo": { + "frame": "string", + "nullable": true + } + } + ] + }, + "data": { + "values": [ + [ + "1" + ] + ] + } + }, + { + "schema": { + "name": "mem", + "fields": [ + { + "name": "Value", + "type": "string", + "typeInfo": { + "frame": "string", + "nullable": true + } + } + ] + }, + "data": { + "values": [ + [ + "1" + ] + ] + } + }, + { + "schema": { + "name": "processes", + "fields": [ + { + "name": "Value", + "type": "string", + "typeInfo": { + "frame": "string", + "nullable": true + } + } + ] + }, + "data": { + "values": [ + [ + "1" + ] + ] + } + }, + { + "schema": { + "name": "swap", + "fields": [ + { + "name": "Value", + "type": "string", + "typeInfo": { + "frame": "string", + "nullable": true + } + } + ] + }, + "data": { + "values": [ + [ + "1" + ] + ] + } + }, + { + "schema": { + "name": "system", + "fields": [ + { + "name": "Value", + "type": "string", + "typeInfo": { + "frame": "string", + "nullable": true + } + } + ] + }, + "data": { + "values": [ + [ + "1" + ] + ] + } + } + ] +} \ No newline at end of file