diff --git a/src/page/HomePage.tsx b/src/page/HomePage.tsx index 1158c72eb..635df4308 100644 --- a/src/page/HomePage.tsx +++ b/src/page/HomePage.tsx @@ -136,6 +136,7 @@ export const HomePage = () => { const usage = useUsageCalc(checks); const { isEnabled: scenesEnabled } = useFeatureFlag(FeatureName.Scenes); const { isEnabled: multiHttpEnabled } = useFeatureFlag(FeatureName.MultiHttp); + const { isEnabled: scriptedEnabled } = useFeatureFlag(FeatureName.ScriptedChecks); useEffect(() => { // Sort to make sure the summary dashboard is at the top of the list @@ -174,9 +175,13 @@ export const HomePage = () => { dashboardList.splice(3, 0, { title: 'MULTIHTTP dashboard', uid: 'multihttp' }); } + if (scriptedEnabled) { + dashboardList.push({ title: 'Scripted dashboard', uid: 'k6' }); + } + setDashboards(dashboardList); } - }, [instance.api, scenesEnabled, multiHttpEnabled]); + }, [instance.api, scenesEnabled, multiHttpEnabled, scriptedEnabled]); return ( diff --git a/src/scenes/MULTIHTTP/distinctTargets.ts b/src/scenes/MULTIHTTP/distinctTargets.ts index 5fa4cf1e3..343afc63c 100644 --- a/src/scenes/MULTIHTTP/distinctTargets.ts +++ b/src/scenes/MULTIHTTP/distinctTargets.ts @@ -28,7 +28,7 @@ export function getDistinctTargets(metrics: DataSourceRef) { body: new ExplorablePanel({ $data: getQueryRunner(metrics), pluginId: 'stat', - title: 'Number of distinct targets', + title: 'Distinct targets', }), }); } diff --git a/src/scenes/SCRIPTED/dataTransferred.ts b/src/scenes/SCRIPTED/dataTransferred.ts new file mode 100644 index 000000000..5e08425a3 --- /dev/null +++ b/src/scenes/SCRIPTED/dataTransferred.ts @@ -0,0 +1,70 @@ +import { SceneFlexItem, SceneFlexLayout, SceneQueryRunner } from '@grafana/scenes'; +import { DataSourceRef } from '@grafana/schema'; + +import { ExplorablePanel } from 'scenes/ExplorablePanel'; + +function getSentQueryRunner(metrics: DataSourceRef) { + return new SceneQueryRunner({ + datasource: metrics, + queries: [ + { + expr: `probe_data_sent_bytes{job="$job", instance="$instance"}`, + instant: false, + legendFormat: '{{ probe }}', + range: true, + refId: 'B', + }, + ], + }); +} + +function getReceivedQueryRunner(metrics: DataSourceRef) { + return new SceneQueryRunner({ + datasource: metrics, + queries: [ + { + expr: `probe_data_received_bytes{job="$job", instance="$instance"}`, + instant: false, + legendFormat: '{{ probe }}', + range: true, + refId: 'A', + }, + ], + }); +} + +export function getDataTransferred(metrics: DataSourceRef) { + return new SceneFlexLayout({ + height: 200, + children: [ + new SceneFlexItem({ + width: '50%', + body: new ExplorablePanel({ + $data: getSentQueryRunner(metrics), + pluginId: 'timeseries', + title: 'Data sent', + fieldConfig: { + defaults: { + unit: 'decbytes', + }, + overrides: [], + }, + }), + }), + new SceneFlexItem({ + width: '50%', + body: new ExplorablePanel({ + $data: getReceivedQueryRunner(metrics), + pluginId: 'timeseries', + title: 'Data received', + fieldConfig: { + defaults: { + unit: 'decbytes', + }, + overrides: [], + }, + }), + }), + ], + }); +} diff --git a/src/scenes/SCRIPTED/expectedResponse.ts b/src/scenes/SCRIPTED/expectedResponse.ts new file mode 100644 index 000000000..dce80850a --- /dev/null +++ b/src/scenes/SCRIPTED/expectedResponse.ts @@ -0,0 +1,64 @@ +import { SceneFlexItem, SceneQueryRunner } from '@grafana/scenes'; +import { DataSourceRef } from '@grafana/schema'; + +import { ExplorablePanel } from 'scenes/ExplorablePanel'; + +function getQueryRunner(metrics: DataSourceRef) { + return new SceneQueryRunner({ + datasource: metrics, + queries: [ + { + expr: ` + sum by (name) (probe_http_got_expected_response{job="$job", instance="$instance"}) + / + count by (name) (probe_http_got_expected_response{job="$job", instance="$instance"})`, + format: 'table', + instant: true, + legendFormat: '{{ name }}', + range: false, + refId: 'B', + }, + ], + }); +} + +export function getExpectedResponse(metrics: DataSourceRef) { + return new SceneFlexItem({ + body: new ExplorablePanel({ + $data: getQueryRunner(metrics), + pluginId: 'table', + title: 'Expected response by target', + fieldConfig: { + defaults: { + unit: 'percentunit', + }, + overrides: [ + { + matcher: { + id: 'byName', + options: 'Time', + }, + properties: [ + { + id: 'custom.hidden', + value: true, + }, + ], + }, + { + matcher: { + id: 'byName', + options: 'Value', + }, + properties: [ + { + id: 'displayName', + value: 'Expected status received', + }, + ], + }, + ], + }, + }), + }); +} diff --git a/src/scenes/SCRIPTED/scriptedScene.ts b/src/scenes/SCRIPTED/scriptedScene.ts index 38b94a43a..19296e2af 100644 --- a/src/scenes/SCRIPTED/scriptedScene.ts +++ b/src/scenes/SCRIPTED/scriptedScene.ts @@ -20,6 +20,11 @@ import { getAssertionTable } from 'scenes/MULTIHTTP/assertionTable'; import { getDistinctTargets } from 'scenes/MULTIHTTP/distinctTargets'; import { getProbeDuration } from 'scenes/MULTIHTTP/probeDuration'; +import { getDataTransferred } from './dataTransferred'; +import { getExpectedResponse } from './expectedResponse'; +import { getSuccessRateByUrl } from './successRateByUrl'; +import { getTimingByTarget } from './timingByTarget'; + export function getScriptedScene({ metrics, logs }: DashboardSceneAppConfig, checks: Check[] = []) { return () => { if (checks.length === 0) { @@ -67,6 +72,22 @@ export function getScriptedScene({ metrics, logs }: DashboardSceneAppConfig, che height: 200, children: [probeDuration], }), + getDataTransferred(metrics), + new SceneFlexLayout({ + direction: 'row', + height: 200, + children: [getTimingByTarget(metrics)], + }), + new SceneFlexLayout({ + direction: 'row', + height: 400, + children: [getExpectedResponse(metrics)], + }), + new SceneFlexLayout({ + direction: 'row', + height: 200, + children: [getSuccessRateByUrl(metrics)], + }), new SceneFlexLayout({ direction: 'row', minHeight: 300, diff --git a/src/scenes/SCRIPTED/successRateByUrl.ts b/src/scenes/SCRIPTED/successRateByUrl.ts new file mode 100644 index 000000000..56634dc5b --- /dev/null +++ b/src/scenes/SCRIPTED/successRateByUrl.ts @@ -0,0 +1,40 @@ +import { SceneFlexItem, SceneQueryRunner } from '@grafana/scenes'; +import { DataSourceRef } from '@grafana/schema'; + +import { ExplorablePanel } from 'scenes/ExplorablePanel'; + +function getQueryRunner(metrics: DataSourceRef) { + return new SceneQueryRunner({ + datasource: metrics, + queries: [ + { + refId: 'A', + expr: ` + sum by (name) (probe_http_requests_total{job="$job", instance="$instance"}) + / + count by (name) (probe_http_requests_total{job="$job", instance="$instance"})`, + range: true, + instant: false, + legendFormat: '{{ name }}', + format: 'time_series', + }, + ], + }); +} + +export function getSuccessRateByUrl(metrics: DataSourceRef) { + return new SceneFlexItem({ + body: new ExplorablePanel({ + $data: getQueryRunner(metrics), + pluginId: 'timeseries', + title: 'Success rate by target', + fieldConfig: { + defaults: { + unit: 'percentunit', + max: 1, + }, + overrides: [], + }, + }), + }); +} diff --git a/src/scenes/SCRIPTED/timingByTarget.ts b/src/scenes/SCRIPTED/timingByTarget.ts new file mode 100644 index 000000000..77a575151 --- /dev/null +++ b/src/scenes/SCRIPTED/timingByTarget.ts @@ -0,0 +1,34 @@ +import { SceneFlexItem, SceneQueryRunner } from '@grafana/scenes'; +import { DataSourceRef } from '@grafana/schema'; + +import { ExplorablePanel } from 'scenes/ExplorablePanel'; + +function getQueryRunner(metrics: DataSourceRef) { + return new SceneQueryRunner({ + datasource: metrics, + queries: [ + { + refId: 'A', + expr: 'sum by(name)(rate(probe_http_duration_seconds{job="$job", instance="$instance"}[5m]))', + range: true, + legendFormat: '{{ name }}', + format: 'time_series', + }, + ], + }); +} +export function getTimingByTarget(metrics: DataSourceRef) { + return new SceneFlexItem({ + body: new ExplorablePanel({ + $data: getQueryRunner(metrics), + pluginId: 'timeseries', + title: 'Timing by target', + fieldConfig: { + defaults: { + unit: 's', + }, + overrides: [], + }, + }), + }); +}