From 439df585e0eedde313f814aca75991cf78e92e88 Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Wed, 30 Apr 2025 16:22:59 +0300 Subject: [PATCH] TestData: Support a steps scenario (#104736) --- .../kinds/query.go | 1 + .../kinds/query.panel.schema.json | 3 +- .../kinds/query.request.schema.json | 3 +- .../kinds/query.types.json | 5 ++- .../grafana-testdata-datasource/scenarios.go | 12 ++++-- .../QueryEditor.tsx | 4 ++ .../grafana-testdata-datasource/dataquery.ts | 1 + .../grafana-testdata-datasource/datasource.ts | 37 +++++++++++++++++++ 8 files changed, 59 insertions(+), 7 deletions(-) diff --git a/pkg/tsdb/grafana-testdata-datasource/kinds/query.go b/pkg/tsdb/grafana-testdata-datasource/kinds/query.go index a2fc0bf6f05..1e325205c5b 100644 --- a/pkg/tsdb/grafana-testdata-datasource/kinds/query.go +++ b/pkg/tsdb/grafana-testdata-datasource/kinds/query.go @@ -77,6 +77,7 @@ const ( TestDataQueryTypeRandomWalkWithError TestDataQueryType = "random_walk_with_error" TestDataQueryTypeRawFrame TestDataQueryType = "raw_frame" TestDataQueryTypeServerError500 TestDataQueryType = "server_error_500" + TestDataQueryTypeSteps TestDataQueryType = "steps" TestDataQueryTypeSimulation TestDataQueryType = "simulation" TestDataQueryTypeSlowQuery TestDataQueryType = "slow_query" TestDataQueryTypeStreamingClient TestDataQueryType = "streaming_client" diff --git a/pkg/tsdb/grafana-testdata-datasource/kinds/query.panel.schema.json b/pkg/tsdb/grafana-testdata-datasource/kinds/query.panel.schema.json index 6fe899b2139..419e2afcc29 100644 --- a/pkg/tsdb/grafana-testdata-datasource/kinds/query.panel.schema.json +++ b/pkg/tsdb/grafana-testdata-datasource/kinds/query.panel.schema.json @@ -229,7 +229,7 @@ "additionalProperties": false }, "scenarioId": { - "description": "Possible enum values:\n - `\"annotations\"` \n - `\"arrow\"` \n - `\"csv_content\"` \n - `\"csv_file\"` \n - `\"csv_metric_values\"` \n - `\"datapoints_outside_range\"` \n - `\"error_with_source\"` \n - `\"exponential_heatmap_bucket_data\"` \n - `\"flame_graph\"` \n - `\"grafana_api\"` \n - `\"linear_heatmap_bucket_data\"` \n - `\"live\"` \n - `\"logs\"` \n - `\"manual_entry\"` \n - `\"no_data_points\"` \n - `\"node_graph\"` \n - `\"predictable_csv_wave\"` \n - `\"predictable_pulse\"` \n - `\"random_walk\"` \n - `\"random_walk_table\"` \n - `\"random_walk_with_error\"` \n - `\"raw_frame\"` \n - `\"server_error_500\"` \n - `\"simulation\"` \n - `\"slow_query\"` \n - `\"streaming_client\"` \n - `\"table_static\"` \n - `\"trace\"` \n - `\"usa\"` \n - `\"variables-query\"` ", + "description": "Possible enum values:\n - `\"annotations\"` \n - `\"arrow\"` \n - `\"csv_content\"` \n - `\"csv_file\"` \n - `\"csv_metric_values\"` \n - `\"datapoints_outside_range\"` \n - `\"error_with_source\"` \n - `\"exponential_heatmap_bucket_data\"` \n - `\"flame_graph\"` \n - `\"grafana_api\"` \n - `\"linear_heatmap_bucket_data\"` \n - `\"live\"` \n - `\"logs\"` \n - `\"manual_entry\"` \n - `\"no_data_points\"` \n - `\"node_graph\"` \n - `\"predictable_csv_wave\"` \n - `\"predictable_pulse\"` \n - `\"random_walk\"` \n - `\"random_walk_table\"` \n - `\"random_walk_with_error\"` \n - `\"raw_frame\"` \n - `\"server_error_500\"` \n - `\"steps\"` \n - `\"simulation\"` \n - `\"slow_query\"` \n - `\"streaming_client\"` \n - `\"table_static\"` \n - `\"trace\"` \n - `\"usa\"` \n - `\"variables-query\"` ", "type": "string", "enum": [ "annotations", @@ -255,6 +255,7 @@ "random_walk_with_error", "raw_frame", "server_error_500", + "steps", "simulation", "slow_query", "streaming_client", diff --git a/pkg/tsdb/grafana-testdata-datasource/kinds/query.request.schema.json b/pkg/tsdb/grafana-testdata-datasource/kinds/query.request.schema.json index 75795b52ee7..824bea0896b 100644 --- a/pkg/tsdb/grafana-testdata-datasource/kinds/query.request.schema.json +++ b/pkg/tsdb/grafana-testdata-datasource/kinds/query.request.schema.json @@ -239,7 +239,7 @@ "additionalProperties": false }, "scenarioId": { - "description": "Possible enum values:\n - `\"annotations\"` \n - `\"arrow\"` \n - `\"csv_content\"` \n - `\"csv_file\"` \n - `\"csv_metric_values\"` \n - `\"datapoints_outside_range\"` \n - `\"error_with_source\"` \n - `\"exponential_heatmap_bucket_data\"` \n - `\"flame_graph\"` \n - `\"grafana_api\"` \n - `\"linear_heatmap_bucket_data\"` \n - `\"live\"` \n - `\"logs\"` \n - `\"manual_entry\"` \n - `\"no_data_points\"` \n - `\"node_graph\"` \n - `\"predictable_csv_wave\"` \n - `\"predictable_pulse\"` \n - `\"random_walk\"` \n - `\"random_walk_table\"` \n - `\"random_walk_with_error\"` \n - `\"raw_frame\"` \n - `\"server_error_500\"` \n - `\"simulation\"` \n - `\"slow_query\"` \n - `\"streaming_client\"` \n - `\"table_static\"` \n - `\"trace\"` \n - `\"usa\"` \n - `\"variables-query\"` ", + "description": "Possible enum values:\n - `\"annotations\"` \n - `\"arrow\"` \n - `\"csv_content\"` \n - `\"csv_file\"` \n - `\"csv_metric_values\"` \n - `\"datapoints_outside_range\"` \n - `\"error_with_source\"` \n - `\"exponential_heatmap_bucket_data\"` \n - `\"flame_graph\"` \n - `\"grafana_api\"` \n - `\"linear_heatmap_bucket_data\"` \n - `\"live\"` \n - `\"logs\"` \n - `\"manual_entry\"` \n - `\"no_data_points\"` \n - `\"node_graph\"` \n - `\"predictable_csv_wave\"` \n - `\"predictable_pulse\"` \n - `\"random_walk\"` \n - `\"random_walk_table\"` \n - `\"random_walk_with_error\"` \n - `\"raw_frame\"` \n - `\"server_error_500\"` \n - `\"steps\"` \n - `\"simulation\"` \n - `\"slow_query\"` \n - `\"streaming_client\"` \n - `\"table_static\"` \n - `\"trace\"` \n - `\"usa\"` \n - `\"variables-query\"` ", "type": "string", "enum": [ "annotations", @@ -265,6 +265,7 @@ "random_walk_with_error", "raw_frame", "server_error_500", + "steps", "simulation", "slow_query", "streaming_client", diff --git a/pkg/tsdb/grafana-testdata-datasource/kinds/query.types.json b/pkg/tsdb/grafana-testdata-datasource/kinds/query.types.json index 2a6a17b811f..af7cb24a888 100644 --- a/pkg/tsdb/grafana-testdata-datasource/kinds/query.types.json +++ b/pkg/tsdb/grafana-testdata-datasource/kinds/query.types.json @@ -8,7 +8,7 @@ { "metadata": { "name": "default", - "resourceVersion": "1728405292506", + "resourceVersion": "1745998648052", "creationTimestamp": "2024-03-01T02:53:35Z" }, "spec": { @@ -151,7 +151,7 @@ "type": "string" }, "scenarioId": { - "description": "Possible enum values:\n - `\"annotations\"` \n - `\"arrow\"` \n - `\"csv_content\"` \n - `\"csv_file\"` \n - `\"csv_metric_values\"` \n - `\"datapoints_outside_range\"` \n - `\"error_with_source\"` \n - `\"exponential_heatmap_bucket_data\"` \n - `\"flame_graph\"` \n - `\"grafana_api\"` \n - `\"linear_heatmap_bucket_data\"` \n - `\"live\"` \n - `\"logs\"` \n - `\"manual_entry\"` \n - `\"no_data_points\"` \n - `\"node_graph\"` \n - `\"predictable_csv_wave\"` \n - `\"predictable_pulse\"` \n - `\"random_walk\"` \n - `\"random_walk_table\"` \n - `\"random_walk_with_error\"` \n - `\"raw_frame\"` \n - `\"server_error_500\"` \n - `\"simulation\"` \n - `\"slow_query\"` \n - `\"streaming_client\"` \n - `\"table_static\"` \n - `\"trace\"` \n - `\"usa\"` \n - `\"variables-query\"` ", + "description": "Possible enum values:\n - `\"annotations\"` \n - `\"arrow\"` \n - `\"csv_content\"` \n - `\"csv_file\"` \n - `\"csv_metric_values\"` \n - `\"datapoints_outside_range\"` \n - `\"error_with_source\"` \n - `\"exponential_heatmap_bucket_data\"` \n - `\"flame_graph\"` \n - `\"grafana_api\"` \n - `\"linear_heatmap_bucket_data\"` \n - `\"live\"` \n - `\"logs\"` \n - `\"manual_entry\"` \n - `\"no_data_points\"` \n - `\"node_graph\"` \n - `\"predictable_csv_wave\"` \n - `\"predictable_pulse\"` \n - `\"random_walk\"` \n - `\"random_walk_table\"` \n - `\"random_walk_with_error\"` \n - `\"raw_frame\"` \n - `\"server_error_500\"` \n - `\"steps\"` \n - `\"simulation\"` \n - `\"slow_query\"` \n - `\"streaming_client\"` \n - `\"table_static\"` \n - `\"trace\"` \n - `\"usa\"` \n - `\"variables-query\"` ", "enum": [ "annotations", "arrow", @@ -176,6 +176,7 @@ "random_walk_with_error", "raw_frame", "server_error_500", + "steps", "simulation", "slow_query", "streaming_client", diff --git a/pkg/tsdb/grafana-testdata-datasource/scenarios.go b/pkg/tsdb/grafana-testdata-datasource/scenarios.go index 7b5c4d66d30..6a0b20068cc 100644 --- a/pkg/tsdb/grafana-testdata-datasource/scenarios.go +++ b/pkg/tsdb/grafana-testdata-datasource/scenarios.go @@ -12,13 +12,13 @@ import ( "strings" "time" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" + "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/backend/log" "github.com/grafana/grafana-plugin-sdk-go/backend/tracing" "github.com/grafana/grafana-plugin-sdk-go/data" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" - "github.com/grafana/grafana/pkg/tsdb/grafana-testdata-datasource/kinds" ) @@ -110,6 +110,12 @@ Timestamps will line up evenly on timeStepSeconds (For example, 60 seconds means handler: s.handleClientSideScenario, }) + s.registerScenario(&Scenario{ + ID: kinds.TestDataQueryTypeSteps, + Name: "Steps", + handler: s.handleClientSideScenario, + }) + s.registerScenario(&Scenario{ ID: kinds.TestDataQueryTypeSimulation, Name: "Simulation", diff --git a/public/app/plugins/datasource/grafana-testdata-datasource/QueryEditor.tsx b/public/app/plugins/datasource/grafana-testdata-datasource/QueryEditor.tsx index 66eb259dbde..95b67bf1f0c 100644 --- a/public/app/plugins/datasource/grafana-testdata-datasource/QueryEditor.tsx +++ b/public/app/plugins/datasource/grafana-testdata-datasource/QueryEditor.tsx @@ -117,6 +117,9 @@ export const QueryEditor = ({ query, datasource, onChange, onRunQuery }: Props) case TestDataQueryType.Annotations: update.lines = 10; break; + case TestDataQueryType.Steps: + update.csvContent = 'a\nb\nc\n'; + break; case TestDataQueryType.USA: update.usa = { mode: usaQueryModes[0].value, @@ -293,6 +296,7 @@ export const QueryEditor = ({ query, datasource, onChange, onRunQuery }: Props) {scenarioId === TestDataQueryType.CSVContent && ( )} + {scenarioId === TestDataQueryType.Steps && } {scenarioId === TestDataQueryType.Logs && ( diff --git a/public/app/plugins/datasource/grafana-testdata-datasource/dataquery.ts b/public/app/plugins/datasource/grafana-testdata-datasource/dataquery.ts index 620f5233b0a..4d4a2084fc1 100644 --- a/public/app/plugins/datasource/grafana-testdata-datasource/dataquery.ts +++ b/public/app/plugins/datasource/grafana-testdata-datasource/dataquery.ts @@ -27,6 +27,7 @@ export enum TestDataQueryType { RawFrame = 'raw_frame', ServerError500 = 'server_error_500', Simulation = 'simulation', + Steps = 'steps', SlowQuery = 'slow_query', StreamingClient = 'streaming_client', TableStatic = 'table_static', diff --git a/public/app/plugins/datasource/grafana-testdata-datasource/datasource.ts b/public/app/plugins/datasource/grafana-testdata-datasource/datasource.ts index dbe61c56f79..3fd778a7659 100644 --- a/public/app/plugins/datasource/grafana-testdata-datasource/datasource.ts +++ b/public/app/plugins/datasource/grafana-testdata-datasource/datasource.ts @@ -17,6 +17,7 @@ import { MutableDataFrame, AnnotationQuery, getSearchFilterScopedVar, + FieldType, } from '@grafana/data'; import { DataSourceWithBackend, getBackendSrv, getGrafanaLiveSrv, getTemplateSrv, TemplateSrv } from '@grafana/runtime'; @@ -97,6 +98,9 @@ export class TestDataDataSource extends DataSourceWithBackend case 'flame_graph': streams.push(this.flameGraphQuery(target)); break; + case 'steps': + streams.push(this.stepsQuery(target)); + break; case 'trace': streams.push(this.trace(options)); break; @@ -348,6 +352,39 @@ export class TestDataDataSource extends DataSourceWithBackend } } + // Incremented with each refresh in a step query + step = 0; + + stepsQuery(target: TestDataDataQuery): Observable { + let steps = (target.csvContent ?? `a\n,b\nc\n`) + .split('\n') + .map((v) => v.trim()) + .filter((v) => Boolean(v.length)); + + this.step = this.step % steps.length; + const step = target.alias?.length ? target.alias : 'step'; + + const frame: DataFrame = { + refId: target.refId, + fields: [ + { name: 'time', type: FieldType.time, values: [Date.now()], config: {} }, + { name: 'index', type: FieldType.number, values: [this.step], config: {} }, + { name: step, type: FieldType.string, values: [steps[this.step]], config: {} }, + ], + length: 1, + }; + for (let i = 0; i < steps.length; i++) { + frame.fields.push({ + name: `${step}-${steps[i]}`, + type: FieldType.boolean, + values: [i <= this.step], + config: {}, + }); + } + this.step++; + return of({ data: [frame] }).pipe(delay(50)); + } + serverErrorQuery( target: TestDataDataQuery, options: DataQueryRequest