mirror of https://github.com/grafana/grafana
Scenes: Remove old scenes stuff (#79760)
* Scenes: Remove old scenes stuff * Fixes * Fixes * updatepull/80023/head
parent
692e8958a3
commit
f0c38611a2
@ -1,57 +0,0 @@ |
|||||||
// Libraries
|
|
||||||
import React from 'react'; |
|
||||||
import { useAsync } from 'react-use'; |
|
||||||
|
|
||||||
import { Card, Stack } from '@grafana/ui'; |
|
||||||
import { Page } from 'app/core/components/Page/Page'; |
|
||||||
|
|
||||||
// Types
|
|
||||||
import { getGrafanaSearcher } from '../search/service'; |
|
||||||
|
|
||||||
import { getScenes } from './scenes'; |
|
||||||
|
|
||||||
export interface Props {} |
|
||||||
|
|
||||||
export const SceneListPage = ({}: Props) => { |
|
||||||
const scenes = getScenes(); |
|
||||||
const results = useAsync(() => { |
|
||||||
return getGrafanaSearcher().starred({ starred: true }); |
|
||||||
}, []); |
|
||||||
|
|
||||||
return ( |
|
||||||
<Page navId="scenes" subTitle="Experimental new runtime and state model for dashboards"> |
|
||||||
<Page.Contents> |
|
||||||
<Stack direction="column" gap={1}> |
|
||||||
<h5>Apps</h5> |
|
||||||
<Stack direction="column" gap={0}> |
|
||||||
<Card href={`/scenes/grafana-monitoring`}> |
|
||||||
<Card.Heading>Grafana monitoring</Card.Heading> |
|
||||||
</Card> |
|
||||||
</Stack> |
|
||||||
<h5>Test scenes</h5> |
|
||||||
<Stack direction="column" gap={0}> |
|
||||||
{scenes.map((scene) => ( |
|
||||||
<Card key={scene.title} href={`/scenes/${scene.title}`}> |
|
||||||
<Card.Heading>{scene.title}</Card.Heading> |
|
||||||
</Card> |
|
||||||
))} |
|
||||||
</Stack> |
|
||||||
{results.value && ( |
|
||||||
<> |
|
||||||
<h5>Starred dashboards</h5> |
|
||||||
<Stack direction="column" gap={0}> |
|
||||||
{results.value!.view.map((dash) => ( |
|
||||||
<Card href={`/scenes/dashboard/${dash.uid}`} key={dash.uid}> |
|
||||||
<Card.Heading>{dash.name}</Card.Heading> |
|
||||||
</Card> |
|
||||||
))} |
|
||||||
</Stack> |
|
||||||
</> |
|
||||||
)} |
|
||||||
</Stack> |
|
||||||
</Page.Contents> |
|
||||||
</Page> |
|
||||||
); |
|
||||||
}; |
|
||||||
|
|
||||||
export default SceneListPage; |
|
@ -1,33 +0,0 @@ |
|||||||
// Libraries
|
|
||||||
import React, { useEffect, useState } from 'react'; |
|
||||||
|
|
||||||
import { getUrlSyncManager } from '@grafana/scenes'; |
|
||||||
import { GrafanaRouteComponentProps } from 'app/core/navigation/types'; |
|
||||||
|
|
||||||
import { getSceneByTitle } from './scenes'; |
|
||||||
|
|
||||||
export interface Props extends GrafanaRouteComponentProps<{ name: string }> {} |
|
||||||
|
|
||||||
export const ScenePage = (props: Props) => { |
|
||||||
const scene = getSceneByTitle(props.match.params.name); |
|
||||||
const [isInitialized, setInitialized] = useState(false); |
|
||||||
|
|
||||||
useEffect(() => { |
|
||||||
if (scene && !isInitialized) { |
|
||||||
getUrlSyncManager().initSync(scene); |
|
||||||
setInitialized(true); |
|
||||||
} |
|
||||||
}, [isInitialized, scene]); |
|
||||||
|
|
||||||
if (!scene) { |
|
||||||
return <h2>Scene not found</h2>; |
|
||||||
} |
|
||||||
|
|
||||||
if (!isInitialized) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
return <scene.Component model={scene} />; |
|
||||||
}; |
|
||||||
|
|
||||||
export default ScenePage; |
|
@ -1,110 +0,0 @@ |
|||||||
// Libraries
|
|
||||||
import React, { useMemo, useState } from 'react'; |
|
||||||
|
|
||||||
import { SceneApp, SceneAppPage, SceneRouteMatch, SceneAppPageLike } from '@grafana/scenes'; |
|
||||||
import { usePageNav } from 'app/core/components/Page/usePageNav'; |
|
||||||
import { PluginPageContext, PluginPageContextType } from 'app/features/plugins/components/PluginPageContext'; |
|
||||||
|
|
||||||
import { |
|
||||||
getOverviewScene, |
|
||||||
getHttpHandlerListScene, |
|
||||||
getOverviewLogsScene, |
|
||||||
getHandlerDetailsScene, |
|
||||||
getHandlerLogsScene, |
|
||||||
} from './scenes'; |
|
||||||
import { getTrafficScene } from './traffic'; |
|
||||||
|
|
||||||
export function GrafanaMonitoringApp() { |
|
||||||
const appScene = useMemo( |
|
||||||
() => |
|
||||||
new SceneApp({ |
|
||||||
pages: [getMainPageScene()], |
|
||||||
}), |
|
||||||
[] |
|
||||||
); |
|
||||||
|
|
||||||
const sectionNav = usePageNav('scenes')!; |
|
||||||
const [pluginContext] = useState<PluginPageContextType>({ sectionNav }); |
|
||||||
|
|
||||||
return ( |
|
||||||
<PluginPageContext.Provider value={pluginContext}> |
|
||||||
<appScene.Component model={appScene} /> |
|
||||||
</PluginPageContext.Provider> |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
export function getMainPageScene() { |
|
||||||
return new SceneAppPage({ |
|
||||||
title: 'Grafana Monitoring', |
|
||||||
subTitle: 'A custom app with embedded scenes to monitor your Grafana server', |
|
||||||
url: '/scenes/grafana-monitoring', |
|
||||||
hideFromBreadcrumbs: false, |
|
||||||
getScene: getOverviewScene, |
|
||||||
tabs: [ |
|
||||||
new SceneAppPage({ |
|
||||||
title: 'Overview', |
|
||||||
url: '/scenes/grafana-monitoring', |
|
||||||
getScene: getOverviewScene, |
|
||||||
preserveUrlKeys: ['from', 'to', 'var-instance'], |
|
||||||
}), |
|
||||||
new SceneAppPage({ |
|
||||||
title: 'HTTP handlers', |
|
||||||
url: '/scenes/grafana-monitoring/handlers', |
|
||||||
getScene: getHttpHandlerListScene, |
|
||||||
preserveUrlKeys: ['from', 'to', 'var-instance'], |
|
||||||
drilldowns: [ |
|
||||||
{ |
|
||||||
routePath: '/scenes/grafana-monitoring/handlers/:handler', |
|
||||||
getPage: getHandlerDrilldownPage, |
|
||||||
}, |
|
||||||
], |
|
||||||
}), |
|
||||||
new SceneAppPage({ |
|
||||||
title: 'Traffic', |
|
||||||
url: '/scenes/grafana-monitoring/traffic', |
|
||||||
getScene: getTrafficScene, |
|
||||||
preserveUrlKeys: ['from', 'to', 'var-instance'], |
|
||||||
}), |
|
||||||
new SceneAppPage({ |
|
||||||
title: 'Logs', |
|
||||||
url: '/scenes/grafana-monitoring/logs', |
|
||||||
getScene: getOverviewLogsScene, |
|
||||||
preserveUrlKeys: ['from', 'to', 'var-instance'], |
|
||||||
}), |
|
||||||
], |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
export function getHandlerDrilldownPage( |
|
||||||
match: SceneRouteMatch<{ handler: string; tab?: string }>, |
|
||||||
parent: SceneAppPageLike |
|
||||||
) { |
|
||||||
const handler = decodeURIComponent(match.params.handler); |
|
||||||
const baseUrl = `/scenes/grafana-monitoring/handlers/${encodeURIComponent(handler)}`; |
|
||||||
|
|
||||||
return new SceneAppPage({ |
|
||||||
title: handler, |
|
||||||
subTitle: 'A grafana http handler is responsible for service a specific API request', |
|
||||||
url: baseUrl, |
|
||||||
getParentPage: () => parent, |
|
||||||
getScene: () => getHandlerDetailsScene(handler), |
|
||||||
tabs: [ |
|
||||||
new SceneAppPage({ |
|
||||||
title: 'Metrics', |
|
||||||
url: baseUrl, |
|
||||||
routePath: '/scenes/grafana-monitoring/handlers/:handler', |
|
||||||
getScene: () => getHandlerDetailsScene(handler), |
|
||||||
preserveUrlKeys: ['from', 'to', 'var-instance'], |
|
||||||
}), |
|
||||||
new SceneAppPage({ |
|
||||||
title: 'Logs', |
|
||||||
url: baseUrl + '/logs', |
|
||||||
routePath: '/scenes/grafana-monitoring/handlers/:handler/logs', |
|
||||||
getScene: () => getHandlerLogsScene(handler), |
|
||||||
preserveUrlKeys: ['from', 'to', 'var-instance'], |
|
||||||
}), |
|
||||||
], |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
export default GrafanaMonitoringApp; |
|
@ -1,24 +0,0 @@ |
|||||||
import React from 'react'; |
|
||||||
|
|
||||||
import { SelectableValue } from '@grafana/data'; |
|
||||||
import { SceneComponentProps, SceneObjectBase, SceneObjectState } from '@grafana/scenes'; |
|
||||||
import { RadioButtonGroup } from '@grafana/ui'; |
|
||||||
|
|
||||||
export interface SceneRadioToggleState extends SceneObjectState { |
|
||||||
options: Array<SelectableValue<string>>; |
|
||||||
value: string; |
|
||||||
onChange: (value: string) => void; |
|
||||||
} |
|
||||||
|
|
||||||
export class SceneRadioToggle extends SceneObjectBase<SceneRadioToggleState> { |
|
||||||
onChange = (value: string) => { |
|
||||||
this.setState({ value }); |
|
||||||
this.state.onChange(value); |
|
||||||
}; |
|
||||||
|
|
||||||
static Component = ({ model }: SceneComponentProps<SceneRadioToggle>) => { |
|
||||||
const { options, value } = model.useState(); |
|
||||||
|
|
||||||
return <RadioButtonGroup options={options} value={value} onChange={model.onChange} />; |
|
||||||
}; |
|
||||||
} |
|
@ -1,20 +0,0 @@ |
|||||||
import React from 'react'; |
|
||||||
|
|
||||||
import { SceneComponentProps, SceneObjectState, SceneObjectBase } from '@grafana/scenes'; |
|
||||||
import { Input } from '@grafana/ui'; |
|
||||||
|
|
||||||
export interface SceneSearchBoxState extends SceneObjectState { |
|
||||||
value: string; |
|
||||||
} |
|
||||||
|
|
||||||
export class SceneSearchBox extends SceneObjectBase<SceneSearchBoxState> { |
|
||||||
onChange = (evt: React.FormEvent<HTMLInputElement>) => { |
|
||||||
this.setState({ value: evt.currentTarget.value }); |
|
||||||
}; |
|
||||||
|
|
||||||
static Component = ({ model }: SceneComponentProps<SceneSearchBox>) => { |
|
||||||
const { value } = model.useState(); |
|
||||||
|
|
||||||
return <Input width={25} placeholder="Search..." value={value} onChange={model.onChange} />; |
|
||||||
}; |
|
||||||
} |
|
@ -1,428 +0,0 @@ |
|||||||
import React from 'react'; |
|
||||||
|
|
||||||
import { FieldColorModeId, getFrameDisplayName } from '@grafana/data'; |
|
||||||
import { locationService } from '@grafana/runtime'; |
|
||||||
import { |
|
||||||
SceneFlexLayout, |
|
||||||
SceneByFrameRepeater, |
|
||||||
SceneTimePicker, |
|
||||||
EmbeddedScene, |
|
||||||
SceneDataNode, |
|
||||||
SceneTimeRange, |
|
||||||
VariableValueSelectors, |
|
||||||
SceneQueryRunner, |
|
||||||
SceneControlsSpacer, |
|
||||||
SceneDataTransformer, |
|
||||||
SceneRefreshPicker, |
|
||||||
SceneFlexItem, |
|
||||||
PanelBuilders, |
|
||||||
} from '@grafana/scenes'; |
|
||||||
import { BigValueGraphMode, BigValueTextMode, LogsDedupStrategy, LogsSortOrder } from '@grafana/schema'; |
|
||||||
import { LinkButton } from '@grafana/ui'; |
|
||||||
|
|
||||||
import { SceneRadioToggle } from './SceneRadioToggle'; |
|
||||||
import { SceneSearchBox } from './SceneSearchBox'; |
|
||||||
import { getTableFilterTransform, getTimeSeriesFilterTransform } from './transforms'; |
|
||||||
import { getInstantQuery, getLinkUrlWithAppUrlState, getTimeSeriesQuery, getVariablesDefinitions } from './utils'; |
|
||||||
|
|
||||||
export function getHttpHandlerListScene(): EmbeddedScene { |
|
||||||
const searchBox = new SceneSearchBox({ value: '' }); |
|
||||||
|
|
||||||
const httpHandlerQueries = getInstantQuery({ |
|
||||||
expr: 'sort_desc(avg without(job, instance) (rate(grafana_http_request_duration_seconds_sum[$__rate_interval]) * 1e3)) ', |
|
||||||
}); |
|
||||||
|
|
||||||
const httpHandlerQueriesFiltered = new SceneDataTransformer({ |
|
||||||
$data: httpHandlerQueries, |
|
||||||
transformations: [getTableFilterTransform('')], |
|
||||||
}); |
|
||||||
|
|
||||||
httpHandlerQueriesFiltered.addActivationHandler(() => { |
|
||||||
const sub = searchBox.subscribeToState((state) => { |
|
||||||
// Update transform and re-process them
|
|
||||||
httpHandlerQueriesFiltered.setState({ transformations: [getTableFilterTransform(state.value)] }); |
|
||||||
httpHandlerQueriesFiltered.reprocessTransformations(); |
|
||||||
}); |
|
||||||
|
|
||||||
return () => sub.unsubscribe(); |
|
||||||
}); |
|
||||||
|
|
||||||
const httpHandlersTable = PanelBuilders.table() |
|
||||||
.setTitle('Handlers') |
|
||||||
.setData(httpHandlerQueriesFiltered) |
|
||||||
.setOption('footer', { |
|
||||||
enablePagination: true, |
|
||||||
}) |
|
||||||
.setOverrides((b) => |
|
||||||
b |
|
||||||
.matchFieldsWithNameByRegex('.*') |
|
||||||
.overrideFilterable(false) |
|
||||||
.matchFieldsWithName('Time') |
|
||||||
.overrideCustomFieldConfig('hidden', true) |
|
||||||
.matchFieldsWithName('Value') |
|
||||||
.overrideDisplayName('Duration (Avg)') |
|
||||||
.matchFieldsWithName('handler') |
|
||||||
.overrideLinks([ |
|
||||||
{ |
|
||||||
title: 'Go to handler drilldown view', |
|
||||||
url: '', |
|
||||||
onBuildUrl: () => { |
|
||||||
const params = locationService.getSearchObject(); |
|
||||||
return getLinkUrlWithAppUrlState( |
|
||||||
'/scenes/grafana-monitoring/handlers/${__value.text:percentencode}', |
|
||||||
params |
|
||||||
); |
|
||||||
}, |
|
||||||
}, |
|
||||||
]) |
|
||||||
) |
|
||||||
.build(); |
|
||||||
|
|
||||||
const reqDurationTimeSeries = new SceneQueryRunner({ |
|
||||||
datasource: { uid: 'gdev-prometheus' }, |
|
||||||
queries: [ |
|
||||||
{ |
|
||||||
refId: 'A', |
|
||||||
//expr: ``,
|
|
||||||
expr: 'topk(20, avg without(job, instance) (rate(grafana_http_request_duration_seconds_sum[$__rate_interval])) * 1e3)', |
|
||||||
range: true, |
|
||||||
format: 'time_series', |
|
||||||
legendFormat: '{{method}} {{handler}} (status = {{status_code}})', |
|
||||||
maxDataPoints: 500, |
|
||||||
}, |
|
||||||
], |
|
||||||
}); |
|
||||||
|
|
||||||
const reqDurationTimeSeriesFiltered = new SceneDataTransformer({ |
|
||||||
$data: reqDurationTimeSeries, |
|
||||||
transformations: [getTimeSeriesFilterTransform('')], |
|
||||||
}); |
|
||||||
|
|
||||||
reqDurationTimeSeriesFiltered.addActivationHandler(() => { |
|
||||||
const sub = searchBox.subscribeToState((state) => { |
|
||||||
// Update transform and re-process them
|
|
||||||
reqDurationTimeSeriesFiltered.setState({ transformations: [getTimeSeriesFilterTransform(state.value)] }); |
|
||||||
reqDurationTimeSeriesFiltered.reprocessTransformations(); |
|
||||||
}); |
|
||||||
|
|
||||||
return () => sub.unsubscribe(); |
|
||||||
}); |
|
||||||
|
|
||||||
const graphsScene = new SceneByFrameRepeater({ |
|
||||||
$data: reqDurationTimeSeriesFiltered, |
|
||||||
body: new SceneFlexLayout({ |
|
||||||
direction: 'column', |
|
||||||
children: [], |
|
||||||
}), |
|
||||||
getLayoutChild: (data, frame, frameIndex) => { |
|
||||||
return new SceneFlexItem({ |
|
||||||
key: `panel-${frameIndex}`, |
|
||||||
minHeight: 200, |
|
||||||
$data: new SceneDataNode({ |
|
||||||
data: { |
|
||||||
...data, |
|
||||||
series: [frame], |
|
||||||
}, |
|
||||||
}), |
|
||||||
body: new SceneFlexLayout({ |
|
||||||
direction: 'row', |
|
||||||
key: `row-${frameIndex}`, |
|
||||||
children: [ |
|
||||||
new SceneFlexItem({ |
|
||||||
key: `flex1-${frameIndex}`, |
|
||||||
body: PanelBuilders.timeseries() |
|
||||||
.setTitle(getFrameDisplayName(frame)) |
|
||||||
.setOption('legend', { showLegend: false }) |
|
||||||
.setHeaderActions( |
|
||||||
<LinkButton |
|
||||||
fill="text" |
|
||||||
size="sm" |
|
||||||
icon="arrow-right" |
|
||||||
href={getHandlerDrilldownUrl(frame.fields[1]!.labels!.handler)} |
|
||||||
> |
|
||||||
Details |
|
||||||
</LinkButton> |
|
||||||
) |
|
||||||
.build(), |
|
||||||
}), |
|
||||||
|
|
||||||
new SceneFlexItem({ |
|
||||||
key: `flex2-${frameIndex}`, |
|
||||||
width: 200, |
|
||||||
body: PanelBuilders.stat() |
|
||||||
.setTitle('Last') |
|
||||||
.setOption('graphMode', BigValueGraphMode.None) |
|
||||||
.setOption('textMode', BigValueTextMode.Value) |
|
||||||
.setDisplayName('Last') |
|
||||||
.build(), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
}); |
|
||||||
}, |
|
||||||
}); |
|
||||||
|
|
||||||
const layout = new SceneFlexLayout({ |
|
||||||
children: [new SceneFlexItem({ body: httpHandlersTable })], |
|
||||||
}); |
|
||||||
|
|
||||||
const sceneToggle = new SceneRadioToggle({ |
|
||||||
options: [ |
|
||||||
{ value: 'table', label: 'Table' }, |
|
||||||
{ value: 'graphs', label: 'Graphs' }, |
|
||||||
], |
|
||||||
value: 'table', |
|
||||||
onChange: (value) => { |
|
||||||
if (value === 'table') { |
|
||||||
layout.setState({ children: [new SceneFlexItem({ body: httpHandlersTable })] }); |
|
||||||
} else { |
|
||||||
layout.setState({ children: [graphsScene] }); |
|
||||||
} |
|
||||||
}, |
|
||||||
}); |
|
||||||
|
|
||||||
const scene = new EmbeddedScene({ |
|
||||||
$variables: getVariablesDefinitions(), |
|
||||||
$data: httpHandlerQueries, |
|
||||||
$timeRange: new SceneTimeRange({ from: 'now-1h', to: 'now' }), |
|
||||||
controls: [ |
|
||||||
new VariableValueSelectors({}), |
|
||||||
searchBox, |
|
||||||
new SceneControlsSpacer(), |
|
||||||
sceneToggle, |
|
||||||
new SceneTimePicker({ isOnCanvas: true }), |
|
||||||
new SceneRefreshPicker({ isOnCanvas: true }), |
|
||||||
], |
|
||||||
body: layout, |
|
||||||
}); |
|
||||||
|
|
||||||
return scene; |
|
||||||
} |
|
||||||
|
|
||||||
function getHandlerDrilldownUrl(handler: string) { |
|
||||||
const params = locationService.getSearchObject(); |
|
||||||
return getLinkUrlWithAppUrlState(`/scenes/grafana-monitoring/handlers/${encodeURIComponent(handler)}`, params); |
|
||||||
} |
|
||||||
|
|
||||||
export function getHandlerDetailsScene(handler: string): EmbeddedScene { |
|
||||||
const reqDurationTimeSeries = getTimeSeriesQuery({ |
|
||||||
expr: `avg without(job, instance) (rate(grafana_http_request_duration_seconds_sum{handler="${handler}"}[$__rate_interval])) * 1e3`, |
|
||||||
legendFormat: '{{method}} {{handler}} (status = {{status_code}})', |
|
||||||
}); |
|
||||||
|
|
||||||
const reqCountTimeSeries = getTimeSeriesQuery({ |
|
||||||
expr: `sum without(job, instance) (rate(grafana_http_request_duration_seconds_count{handler="${handler}"}[$__rate_interval])) `, |
|
||||||
legendFormat: '{{method}} {{handler}} (status = {{status_code}})', |
|
||||||
}); |
|
||||||
|
|
||||||
const scene = new EmbeddedScene({ |
|
||||||
$variables: getVariablesDefinitions(), |
|
||||||
$timeRange: new SceneTimeRange({ from: 'now-1h', to: 'now' }), |
|
||||||
controls: [ |
|
||||||
new VariableValueSelectors({}), |
|
||||||
new SceneControlsSpacer(), |
|
||||||
new SceneTimePicker({ isOnCanvas: true }), |
|
||||||
new SceneRefreshPicker({ isOnCanvas: true }), |
|
||||||
], |
|
||||||
body: new SceneFlexLayout({ |
|
||||||
direction: 'column', |
|
||||||
children: [ |
|
||||||
new SceneFlexItem({ |
|
||||||
body: PanelBuilders.timeseries().setData(reqDurationTimeSeries).setTitle('Request duration avg (ms)').build(), |
|
||||||
}), |
|
||||||
new SceneFlexItem({ |
|
||||||
body: PanelBuilders.timeseries().setData(reqCountTimeSeries).setTitle('Request count/s').build(), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
}); |
|
||||||
|
|
||||||
return scene; |
|
||||||
} |
|
||||||
|
|
||||||
export function getOverviewScene(): EmbeddedScene { |
|
||||||
const scene = new EmbeddedScene({ |
|
||||||
$variables: getVariablesDefinitions(), |
|
||||||
$timeRange: new SceneTimeRange({ from: 'now-1h', to: 'now' }), |
|
||||||
controls: [ |
|
||||||
new VariableValueSelectors({}), |
|
||||||
new SceneControlsSpacer(), |
|
||||||
new SceneTimePicker({ isOnCanvas: true }), |
|
||||||
new SceneRefreshPicker({ isOnCanvas: true }), |
|
||||||
], |
|
||||||
body: new SceneFlexLayout({ |
|
||||||
direction: 'column', |
|
||||||
children: [ |
|
||||||
new SceneFlexItem({ |
|
||||||
height: 150, |
|
||||||
body: new SceneFlexLayout({ |
|
||||||
children: [ |
|
||||||
new SceneFlexItem({ |
|
||||||
body: getInstantStatPanel('grafana_stat_totals_dashboard', 'Dashboards'), |
|
||||||
}), |
|
||||||
new SceneFlexItem({ |
|
||||||
body: getInstantStatPanel('grafana_stat_total_users', 'Users'), |
|
||||||
}), |
|
||||||
new SceneFlexItem({ |
|
||||||
body: getInstantStatPanel('sum(grafana_stat_totals_datasource)', 'Data sources'), |
|
||||||
}), |
|
||||||
new SceneFlexItem({ |
|
||||||
body: getInstantStatPanel('grafana_stat_total_service_account_tokens', 'Service account tokens'), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
}), |
|
||||||
|
|
||||||
new SceneFlexItem({ |
|
||||||
body: PanelBuilders.timeseries() |
|
||||||
.setData( |
|
||||||
new SceneQueryRunner({ |
|
||||||
datasource: { uid: 'gdev-prometheus' }, |
|
||||||
queries: [ |
|
||||||
{ |
|
||||||
refId: 'A', |
|
||||||
expr: `sum(process_resident_memory_bytes{job="grafana", instance=~"$instance"})`, |
|
||||||
range: true, |
|
||||||
format: 'time_series', |
|
||||||
maxDataPoints: 500, |
|
||||||
}, |
|
||||||
], |
|
||||||
}) |
|
||||||
) |
|
||||||
.setTitle('Memory usage') |
|
||||||
.setOption('legend', { showLegend: false }) |
|
||||||
.setUnit('bytes') |
|
||||||
.setMin(0) |
|
||||||
.setCustomFieldConfig('lineWidth', 2) |
|
||||||
.setCustomFieldConfig('fillOpacity', 6) |
|
||||||
.build(), |
|
||||||
}), |
|
||||||
new SceneFlexItem({ |
|
||||||
body: PanelBuilders.timeseries() |
|
||||||
.setData( |
|
||||||
new SceneQueryRunner({ |
|
||||||
datasource: { uid: 'gdev-prometheus' }, |
|
||||||
queries: [ |
|
||||||
{ |
|
||||||
refId: 'A', |
|
||||||
expr: `sum(go_goroutines{job="grafana", instance=~"$instance"})`, |
|
||||||
range: true, |
|
||||||
format: 'time_series', |
|
||||||
maxDataPoints: 500, |
|
||||||
}, |
|
||||||
], |
|
||||||
}) |
|
||||||
) |
|
||||||
.setOption('legend', { showLegend: false }) |
|
||||||
.setMin(0) |
|
||||||
.setCustomFieldConfig('lineWidth', 2) |
|
||||||
.setCustomFieldConfig('fillOpacity', 6) |
|
||||||
.setTitle('Go routines') |
|
||||||
.build(), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
}); |
|
||||||
|
|
||||||
return scene; |
|
||||||
} |
|
||||||
|
|
||||||
function getInstantStatPanel(query: string, title: string) { |
|
||||||
return PanelBuilders.stat() |
|
||||||
.setData(getInstantQuery({ expr: query })) |
|
||||||
.setTitle(title) |
|
||||||
.setColor({ fixedColor: 'text', mode: FieldColorModeId.Fixed }) |
|
||||||
.build(); |
|
||||||
} |
|
||||||
|
|
||||||
export function getHandlerLogsScene(handler: string): EmbeddedScene { |
|
||||||
const logsQuery = new SceneQueryRunner({ |
|
||||||
datasource: { uid: 'gdev-loki' }, |
|
||||||
queries: [ |
|
||||||
{ |
|
||||||
refId: 'A', |
|
||||||
expr: `{job="grafana"} | logfmt | handler=\`${handler}\` | __error__=\`\``, |
|
||||||
queryType: 'range', |
|
||||||
maxDataPoints: 5000, |
|
||||||
}, |
|
||||||
], |
|
||||||
}); |
|
||||||
|
|
||||||
const scene = new EmbeddedScene({ |
|
||||||
$variables: getVariablesDefinitions(), |
|
||||||
$timeRange: new SceneTimeRange({ from: 'now-1h', to: 'now' }), |
|
||||||
controls: [ |
|
||||||
new VariableValueSelectors({}), |
|
||||||
new SceneControlsSpacer(), |
|
||||||
new SceneTimePicker({ isOnCanvas: true }), |
|
||||||
new SceneRefreshPicker({ isOnCanvas: true }), |
|
||||||
], |
|
||||||
body: new SceneFlexLayout({ |
|
||||||
direction: 'column', |
|
||||||
children: [ |
|
||||||
new SceneFlexItem({ |
|
||||||
body: PanelBuilders.logs() |
|
||||||
.setData(logsQuery) |
|
||||||
.setTitle('') |
|
||||||
.setOption('showTime', true) |
|
||||||
.setOption('showLabels', false) |
|
||||||
.setOption('showCommonLabels', false) |
|
||||||
.setOption('wrapLogMessage', true) |
|
||||||
.setOption('prettifyLogMessage', false) |
|
||||||
.setOption('enableLogDetails', true) |
|
||||||
.setOption('dedupStrategy', LogsDedupStrategy.none) |
|
||||||
.setOption('sortOrder', LogsSortOrder.Descending) |
|
||||||
.build(), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
}); |
|
||||||
|
|
||||||
return scene; |
|
||||||
} |
|
||||||
|
|
||||||
export function getOverviewLogsScene(): EmbeddedScene { |
|
||||||
const logsQuery = new SceneQueryRunner({ |
|
||||||
datasource: { uid: 'gdev-loki' }, |
|
||||||
queries: [ |
|
||||||
{ |
|
||||||
refId: 'A', |
|
||||||
expr: `{job="grafana"} | logfmt | __error__=\`\``, |
|
||||||
queryType: 'range', |
|
||||||
maxDataPoints: 5000, |
|
||||||
}, |
|
||||||
], |
|
||||||
}); |
|
||||||
|
|
||||||
const scene = new EmbeddedScene({ |
|
||||||
$variables: getVariablesDefinitions(), |
|
||||||
$timeRange: new SceneTimeRange({ from: 'now-1h', to: 'now' }), |
|
||||||
controls: [ |
|
||||||
new VariableValueSelectors({}), |
|
||||||
new SceneControlsSpacer(), |
|
||||||
new SceneTimePicker({ isOnCanvas: true }), |
|
||||||
new SceneRefreshPicker({ isOnCanvas: true }), |
|
||||||
], |
|
||||||
body: new SceneFlexLayout({ |
|
||||||
direction: 'column', |
|
||||||
children: [ |
|
||||||
new SceneFlexItem({ |
|
||||||
body: PanelBuilders.logs() |
|
||||||
.setTitle('') |
|
||||||
.setData(logsQuery) |
|
||||||
.setOption('showTime', true) |
|
||||||
.setOption('showLabels', false) |
|
||||||
.setOption('showCommonLabels', false) |
|
||||||
.setOption('wrapLogMessage', true) |
|
||||||
.setOption('prettifyLogMessage', false) |
|
||||||
.setOption('enableLogDetails', true) |
|
||||||
.setOption('dedupStrategy', LogsDedupStrategy.none) |
|
||||||
.setOption('sortOrder', LogsSortOrder.Descending) |
|
||||||
.build(), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
}); |
|
||||||
|
|
||||||
return scene; |
|
||||||
} |
|
@ -1,127 +0,0 @@ |
|||||||
import React from 'react'; |
|
||||||
|
|
||||||
import { |
|
||||||
SceneFlexLayout, |
|
||||||
SceneTimePicker, |
|
||||||
EmbeddedScene, |
|
||||||
SceneTimeRange, |
|
||||||
VariableValueSelectors, |
|
||||||
SceneControlsSpacer, |
|
||||||
SceneRefreshPicker, |
|
||||||
SceneFlexItem, |
|
||||||
SceneObjectState, |
|
||||||
SceneObjectBase, |
|
||||||
SceneObjectUrlSyncConfig, |
|
||||||
SceneObjectUrlValues, |
|
||||||
PanelBuilders, |
|
||||||
} from '@grafana/scenes'; |
|
||||||
import { Button } from '@grafana/ui'; |
|
||||||
|
|
||||||
import { getInstantQuery, getTimeSeriesQuery, getVariablesDefinitions } from './utils'; |
|
||||||
|
|
||||||
export function getTrafficScene(): EmbeddedScene { |
|
||||||
const httpHandlersTable = PanelBuilders.table() |
|
||||||
.setData( |
|
||||||
getInstantQuery({ |
|
||||||
expr: 'sort_desc(avg without(job, instance) (rate(grafana_http_request_duration_seconds_sum[$__rate_interval]) * 1e3)) ', |
|
||||||
}) |
|
||||||
) |
|
||||||
.setTitle('Handlers') |
|
||||||
.setOption('footer', { enablePagination: true }) |
|
||||||
.setOverrides((b) => |
|
||||||
b |
|
||||||
.matchFieldsWithNameByRegex('.*') |
|
||||||
.overrideFilterable(false) |
|
||||||
.matchFieldsWithName('Time') |
|
||||||
.overrideCustomFieldConfig('hidden', true) |
|
||||||
.matchFieldsWithName('Value') |
|
||||||
.overrideDisplayName('Duration (Avg)') |
|
||||||
.matchFieldsWithName('handler') |
|
||||||
.overrideLinks([ |
|
||||||
{ |
|
||||||
title: 'Go to handler drilldown view', |
|
||||||
url: '/scenes/grafana-monitoring/traffic?handler=${__value.text:percentencode}', |
|
||||||
}, |
|
||||||
]) |
|
||||||
) |
|
||||||
.build(); |
|
||||||
|
|
||||||
const scene = new EmbeddedScene({ |
|
||||||
$variables: getVariablesDefinitions(), |
|
||||||
$timeRange: new SceneTimeRange({ from: 'now-1h', to: 'now' }), |
|
||||||
controls: [ |
|
||||||
new VariableValueSelectors({}), |
|
||||||
new SceneControlsSpacer(), |
|
||||||
new SceneTimePicker({ isOnCanvas: true }), |
|
||||||
new SceneRefreshPicker({ isOnCanvas: true }), |
|
||||||
], |
|
||||||
body: new SceneFlexLayout({ |
|
||||||
$behaviors: [new HandlerDrilldownViewBehavior()], |
|
||||||
children: [new SceneFlexItem({ body: httpHandlersTable })], |
|
||||||
}), |
|
||||||
}); |
|
||||||
|
|
||||||
return scene; |
|
||||||
} |
|
||||||
|
|
||||||
export interface HandlerDrilldownViewBehaviorState extends SceneObjectState { |
|
||||||
handler?: string; |
|
||||||
} |
|
||||||
|
|
||||||
export class HandlerDrilldownViewBehavior extends SceneObjectBase<HandlerDrilldownViewBehaviorState> { |
|
||||||
protected _urlSync = new SceneObjectUrlSyncConfig(this, { keys: ['handler'] }); |
|
||||||
|
|
||||||
constructor() { |
|
||||||
super({}); |
|
||||||
|
|
||||||
this.addActivationHandler(() => { |
|
||||||
this._subs.add(this.subscribeToState((state) => this.onHandlerChanged(state.handler))); |
|
||||||
this.onHandlerChanged(this.state.handler); |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
private onHandlerChanged(handler: string | undefined) { |
|
||||||
const layout = this.getLayout(); |
|
||||||
|
|
||||||
if (handler == null) { |
|
||||||
layout.setState({ children: layout.state.children.slice(0, 1) }); |
|
||||||
} else { |
|
||||||
layout.setState({ children: [layout.state.children[0], this.getDrilldownView(handler)] }); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private getDrilldownView(handler: string): SceneFlexItem { |
|
||||||
return new SceneFlexItem({ |
|
||||||
key: 'drilldown-flex', |
|
||||||
body: PanelBuilders.timeseries() |
|
||||||
.setData( |
|
||||||
getTimeSeriesQuery({ |
|
||||||
expr: `rate(grafana_http_request_duration_seconds_sum{handler="${handler}"}[$__rate_interval]) * 1e3`, |
|
||||||
}) |
|
||||||
) |
|
||||||
.setTitle(`Handler: ${handler} details`) |
|
||||||
.setHeaderActions( |
|
||||||
<Button size="sm" variant="secondary" icon="times" onClick={() => this.setState({ handler: undefined })} /> |
|
||||||
) |
|
||||||
.build(), |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
getUrlState() { |
|
||||||
return { handler: this.state.handler }; |
|
||||||
} |
|
||||||
|
|
||||||
updateFromUrl(values: SceneObjectUrlValues) { |
|
||||||
if (typeof values.handler === 'string' || values.handler === undefined) { |
|
||||||
this.setState({ handler: values.handler }); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private getLayout() { |
|
||||||
if (this.parent instanceof SceneFlexLayout) { |
|
||||||
return this.parent; |
|
||||||
} |
|
||||||
|
|
||||||
throw new Error('Invalid parent'); |
|
||||||
} |
|
||||||
} |
|
@ -1,42 +0,0 @@ |
|||||||
import { map } from 'rxjs'; |
|
||||||
|
|
||||||
import { |
|
||||||
BasicValueMatcherOptions, |
|
||||||
CustomTransformOperator, |
|
||||||
DataTransformerID, |
|
||||||
getFrameDisplayName, |
|
||||||
ValueMatcherID, |
|
||||||
} from '@grafana/data'; |
|
||||||
import { FilterByValueMatch, FilterByValueType } from '@grafana/data/src/transformations/transformers/filterByValue'; |
|
||||||
import { DataTransformerConfig, MatcherConfig } from '@grafana/schema'; |
|
||||||
|
|
||||||
export function getTableFilterTransform(query: string): DataTransformerConfig { |
|
||||||
const regex: MatcherConfig<BasicValueMatcherOptions<string>> = { |
|
||||||
id: ValueMatcherID.regex, |
|
||||||
options: { value: query }, |
|
||||||
}; |
|
||||||
|
|
||||||
return { |
|
||||||
id: DataTransformerID.filterByValue, |
|
||||||
options: { |
|
||||||
type: FilterByValueType.include, |
|
||||||
match: FilterByValueMatch.all, |
|
||||||
filters: [ |
|
||||||
{ |
|
||||||
fieldName: 'handler', |
|
||||||
config: regex, |
|
||||||
}, |
|
||||||
], |
|
||||||
}, |
|
||||||
}; |
|
||||||
} |
|
||||||
|
|
||||||
export function getTimeSeriesFilterTransform(query: string): CustomTransformOperator { |
|
||||||
return () => (source) => { |
|
||||||
return source.pipe( |
|
||||||
map((data) => { |
|
||||||
return data.filter((frame) => getFrameDisplayName(frame).toLowerCase().includes(query.toLowerCase())); |
|
||||||
}) |
|
||||||
); |
|
||||||
}; |
|
||||||
} |
|
@ -1,57 +0,0 @@ |
|||||||
import { useLocation } from 'react-router-dom'; |
|
||||||
|
|
||||||
import { UrlQueryMap, urlUtil } from '@grafana/data'; |
|
||||||
import { locationSearchToObject } from '@grafana/runtime'; |
|
||||||
import { QueryVariable, SceneQueryRunner, SceneVariableSet } from '@grafana/scenes'; |
|
||||||
import { PromQuery } from 'app/plugins/datasource/prometheus/types'; |
|
||||||
|
|
||||||
export function useAppQueryParams() { |
|
||||||
const location = useLocation(); |
|
||||||
return locationSearchToObject(location.search || ''); |
|
||||||
} |
|
||||||
|
|
||||||
export function getLinkUrlWithAppUrlState(path: string, params: UrlQueryMap): string { |
|
||||||
return urlUtil.renderUrl(path, params); |
|
||||||
} |
|
||||||
|
|
||||||
export function getInstantQuery(query: Partial<PromQuery>): SceneQueryRunner { |
|
||||||
return new SceneQueryRunner({ |
|
||||||
datasource: { uid: 'gdev-prometheus' }, |
|
||||||
queries: [ |
|
||||||
{ |
|
||||||
refId: 'A', |
|
||||||
instant: true, |
|
||||||
format: 'table', |
|
||||||
maxDataPoints: 500, |
|
||||||
...query, |
|
||||||
}, |
|
||||||
], |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
export function getTimeSeriesQuery(query: Partial<PromQuery>): SceneQueryRunner { |
|
||||||
return new SceneQueryRunner({ |
|
||||||
datasource: { uid: 'gdev-prometheus' }, |
|
||||||
queries: [ |
|
||||||
{ |
|
||||||
refId: 'A', |
|
||||||
range: true, |
|
||||||
format: 'time_series', |
|
||||||
maxDataPoints: 500, |
|
||||||
...query, |
|
||||||
}, |
|
||||||
], |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
export function getVariablesDefinitions() { |
|
||||||
return new SceneVariableSet({ |
|
||||||
variables: [ |
|
||||||
new QueryVariable({ |
|
||||||
name: 'instance', |
|
||||||
datasource: { uid: 'gdev-prometheus' }, |
|
||||||
query: { query: 'label_values(grafana_http_request_duration_seconds_sum, instance)', refId: 'A' }, |
|
||||||
}), |
|
||||||
], |
|
||||||
}); |
|
||||||
} |
|
@ -1,73 +0,0 @@ |
|||||||
import { |
|
||||||
SceneGridRow, |
|
||||||
SceneTimePicker, |
|
||||||
SceneGridLayout, |
|
||||||
SceneTimeRange, |
|
||||||
SceneRefreshPicker, |
|
||||||
SceneGridItem, |
|
||||||
PanelBuilders, |
|
||||||
} from '@grafana/scenes'; |
|
||||||
import { TestDataQueryType } from '@grafana-plugins/grafana-testdata-datasource/dataquery.gen'; |
|
||||||
|
|
||||||
import { DashboardScene } from '../../dashboard-scene/scene/DashboardScene'; |
|
||||||
|
|
||||||
import { getQueryRunnerWithRandomWalkQuery } from './queries'; |
|
||||||
|
|
||||||
export function getGridWithMultipleTimeRanges(): DashboardScene { |
|
||||||
const globalTimeRange = new SceneTimeRange(); |
|
||||||
const row1TimeRange = new SceneTimeRange({ |
|
||||||
from: 'now-1y', |
|
||||||
to: 'now', |
|
||||||
}); |
|
||||||
|
|
||||||
return new DashboardScene({ |
|
||||||
title: 'Grid with rows and different queries and time ranges', |
|
||||||
body: new SceneGridLayout({ |
|
||||||
children: [ |
|
||||||
new SceneGridRow({ |
|
||||||
$timeRange: row1TimeRange, |
|
||||||
$data: getQueryRunnerWithRandomWalkQuery({ scenarioId: TestDataQueryType.RandomWalkTable }), |
|
||||||
title: 'Row A - has its own query, last year time range', |
|
||||||
key: 'Row A', |
|
||||||
isCollapsed: true, |
|
||||||
y: 0, |
|
||||||
children: [ |
|
||||||
new SceneGridItem({ |
|
||||||
x: 0, |
|
||||||
y: 1, |
|
||||||
width: 12, |
|
||||||
height: 5, |
|
||||||
isResizable: true, |
|
||||||
isDraggable: true, |
|
||||||
body: PanelBuilders.timeseries().setTitle('Row A Child1').build(), |
|
||||||
}), |
|
||||||
new SceneGridItem({ |
|
||||||
x: 0, |
|
||||||
y: 5, |
|
||||||
width: 6, |
|
||||||
height: 5, |
|
||||||
isResizable: true, |
|
||||||
isDraggable: true, |
|
||||||
body: PanelBuilders.timeseries().setTitle('Row A Child2').build(), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
new SceneGridItem({ |
|
||||||
x: 0, |
|
||||||
y: 12, |
|
||||||
width: 6, |
|
||||||
height: 10, |
|
||||||
isResizable: true, |
|
||||||
isDraggable: true, |
|
||||||
body: PanelBuilders.timeseries() |
|
||||||
.setTitle('Outsider, has its own query') |
|
||||||
.setData(getQueryRunnerWithRandomWalkQuery()) |
|
||||||
.build(), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
$timeRange: globalTimeRange, |
|
||||||
$data: getQueryRunnerWithRandomWalkQuery(), |
|
||||||
actions: [new SceneTimePicker({}), new SceneRefreshPicker({})], |
|
||||||
}); |
|
||||||
} |
|
@ -1,117 +0,0 @@ |
|||||||
import { |
|
||||||
SceneTimePicker, |
|
||||||
SceneFlexLayout, |
|
||||||
SceneGridLayout, |
|
||||||
SceneTimeRange, |
|
||||||
SceneRefreshPicker, |
|
||||||
SceneGridItem, |
|
||||||
SceneFlexItem, |
|
||||||
PanelBuilders, |
|
||||||
} from '@grafana/scenes'; |
|
||||||
|
|
||||||
import { DashboardScene } from '../../dashboard-scene/scene/DashboardScene'; |
|
||||||
|
|
||||||
import { getQueryRunnerWithRandomWalkQuery } from './queries'; |
|
||||||
|
|
||||||
export function getMultipleGridLayoutTest(): DashboardScene { |
|
||||||
return new DashboardScene({ |
|
||||||
title: 'Multiple grid layouts test', |
|
||||||
body: new SceneFlexLayout({ |
|
||||||
children: [ |
|
||||||
new SceneFlexItem({ |
|
||||||
body: new SceneGridLayout({ |
|
||||||
children: [ |
|
||||||
new SceneGridItem({ |
|
||||||
x: 0, |
|
||||||
y: 0, |
|
||||||
width: 12, |
|
||||||
height: 10, |
|
||||||
isDraggable: true, |
|
||||||
isResizable: true, |
|
||||||
body: PanelBuilders.timeseries().setTitle('Dragabble and resizable').build(), |
|
||||||
}), |
|
||||||
new SceneGridItem({ |
|
||||||
x: 12, |
|
||||||
y: 0, |
|
||||||
width: 12, |
|
||||||
height: 10, |
|
||||||
isResizable: false, |
|
||||||
isDraggable: true, |
|
||||||
body: PanelBuilders.timeseries().setTitle('Draggable only').build(), |
|
||||||
}), |
|
||||||
new SceneGridItem({ |
|
||||||
x: 6, |
|
||||||
y: 11, |
|
||||||
width: 12, |
|
||||||
height: 10, |
|
||||||
isResizable: false, |
|
||||||
isDraggable: true, |
|
||||||
body: new SceneFlexLayout({ |
|
||||||
direction: 'column', |
|
||||||
children: [ |
|
||||||
new SceneFlexItem({ |
|
||||||
ySizing: 'fill', |
|
||||||
body: PanelBuilders.timeseries().setTitle('Fill height').build(), |
|
||||||
}), |
|
||||||
new SceneFlexItem({ |
|
||||||
ySizing: 'fill', |
|
||||||
body: PanelBuilders.timeseries().setTitle('Fill height').build(), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
}), |
|
||||||
new SceneFlexItem({ |
|
||||||
body: new SceneGridLayout({ |
|
||||||
children: [ |
|
||||||
new SceneGridItem({ |
|
||||||
x: 0, |
|
||||||
y: 0, |
|
||||||
width: 12, |
|
||||||
height: 10, |
|
||||||
isDraggable: true, |
|
||||||
isResizable: true, |
|
||||||
body: PanelBuilders.timeseries().setTitle('Dragabble and resizable').build(), |
|
||||||
}), |
|
||||||
new SceneGridItem({ |
|
||||||
x: 12, |
|
||||||
y: 0, |
|
||||||
width: 12, |
|
||||||
height: 10, |
|
||||||
isResizable: false, |
|
||||||
isDraggable: true, |
|
||||||
body: PanelBuilders.timeseries().setTitle('Draggable only').build(), |
|
||||||
}), |
|
||||||
new SceneGridItem({ |
|
||||||
x: 6, |
|
||||||
y: 11, |
|
||||||
width: 12, |
|
||||||
height: 10, |
|
||||||
isResizable: false, |
|
||||||
isDraggable: true, |
|
||||||
body: new SceneFlexLayout({ |
|
||||||
direction: 'column', |
|
||||||
children: [ |
|
||||||
new SceneFlexItem({ |
|
||||||
ySizing: 'fill', |
|
||||||
body: PanelBuilders.timeseries().setTitle('Fill height').build(), |
|
||||||
}), |
|
||||||
new SceneFlexItem({ |
|
||||||
ySizing: 'fill', |
|
||||||
body: PanelBuilders.timeseries().setTitle('Fill height').build(), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
$timeRange: new SceneTimeRange(), |
|
||||||
$data: getQueryRunnerWithRandomWalkQuery(), |
|
||||||
actions: [new SceneTimePicker({}), new SceneRefreshPicker({})], |
|
||||||
}); |
|
||||||
} |
|
@ -1,105 +0,0 @@ |
|||||||
import { |
|
||||||
SceneGridRow, |
|
||||||
SceneTimePicker, |
|
||||||
SceneGridLayout, |
|
||||||
SceneTimeRange, |
|
||||||
SceneRefreshPicker, |
|
||||||
SceneGridItem, |
|
||||||
PanelBuilders, |
|
||||||
} from '@grafana/scenes'; |
|
||||||
import { TestDataQueryType } from '@grafana-plugins/grafana-testdata-datasource/dataquery.gen'; |
|
||||||
|
|
||||||
import { DashboardScene } from '../../dashboard-scene/scene/DashboardScene'; |
|
||||||
|
|
||||||
import { getQueryRunnerWithRandomWalkQuery } from './queries'; |
|
||||||
|
|
||||||
export function getGridWithMultipleData(): DashboardScene { |
|
||||||
return new DashboardScene({ |
|
||||||
title: 'Grid with rows and different queries', |
|
||||||
body: new SceneGridLayout({ |
|
||||||
children: [ |
|
||||||
new SceneGridRow({ |
|
||||||
$timeRange: new SceneTimeRange(), |
|
||||||
$data: getQueryRunnerWithRandomWalkQuery({ scenarioId: TestDataQueryType.RandomWalkTable }), |
|
||||||
title: 'Row A - has its own query', |
|
||||||
key: 'Row A', |
|
||||||
isCollapsed: true, |
|
||||||
y: 0, |
|
||||||
children: [ |
|
||||||
new SceneGridItem({ |
|
||||||
x: 0, |
|
||||||
y: 1, |
|
||||||
width: 12, |
|
||||||
height: 5, |
|
||||||
isResizable: true, |
|
||||||
isDraggable: true, |
|
||||||
body: PanelBuilders.timeseries().setTitle('Row A Child1').build(), |
|
||||||
}), |
|
||||||
new SceneGridItem({ |
|
||||||
x: 0, |
|
||||||
y: 5, |
|
||||||
width: 6, |
|
||||||
height: 5, |
|
||||||
isResizable: true, |
|
||||||
isDraggable: true, |
|
||||||
body: PanelBuilders.timeseries().setTitle('Row A Child2').build(), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
new SceneGridRow({ |
|
||||||
title: 'Row B - uses global query', |
|
||||||
key: 'Row B', |
|
||||||
isCollapsed: true, |
|
||||||
y: 1, |
|
||||||
children: [ |
|
||||||
new SceneGridItem({ |
|
||||||
x: 0, |
|
||||||
y: 2, |
|
||||||
width: 12, |
|
||||||
height: 5, |
|
||||||
isResizable: false, |
|
||||||
isDraggable: true, |
|
||||||
body: PanelBuilders.timeseries().setTitle('Row B Child1').build(), |
|
||||||
}), |
|
||||||
new SceneGridItem({ |
|
||||||
x: 0, |
|
||||||
y: 7, |
|
||||||
width: 6, |
|
||||||
height: 5, |
|
||||||
isResizable: false, |
|
||||||
isDraggable: true, |
|
||||||
body: PanelBuilders.timeseries() |
|
||||||
.setTitle('Row B Child2 with data') |
|
||||||
.setData(getQueryRunnerWithRandomWalkQuery({ seriesCount: 10 })) |
|
||||||
.build(), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
new SceneGridItem({ |
|
||||||
x: 0, |
|
||||||
y: 12, |
|
||||||
width: 6, |
|
||||||
height: 10, |
|
||||||
isResizable: true, |
|
||||||
isDraggable: true, |
|
||||||
body: PanelBuilders.timeseries() |
|
||||||
.setTitle('Outsider, has its own query') |
|
||||||
.setData(getQueryRunnerWithRandomWalkQuery({ seriesCount: 10 })) |
|
||||||
.build(), |
|
||||||
}), |
|
||||||
new SceneGridItem({ |
|
||||||
x: 6, |
|
||||||
y: 12, |
|
||||||
width: 12, |
|
||||||
height: 10, |
|
||||||
isResizable: true, |
|
||||||
isDraggable: true, |
|
||||||
body: PanelBuilders.timeseries().setTitle('Outsider, uses global query').build(), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
$timeRange: new SceneTimeRange(), |
|
||||||
$data: getQueryRunnerWithRandomWalkQuery(), |
|
||||||
actions: [new SceneTimePicker({}), new SceneRefreshPicker({})], |
|
||||||
}); |
|
||||||
} |
|
@ -1,45 +0,0 @@ |
|||||||
import { DashboardScene } from '../../dashboard-scene/scene/DashboardScene'; |
|
||||||
|
|
||||||
import { getGridWithMultipleTimeRanges } from './gridMultiTimeRange'; |
|
||||||
import { getMultipleGridLayoutTest } from './gridMultiple'; |
|
||||||
import { getGridWithMultipleData } from './gridWithMultipleData'; |
|
||||||
import { getQueryVariableDemo } from './queryVariableDemo'; |
|
||||||
import { getRepeatingPanelsDemo, getRepeatingRowsDemo } from './repeatingPanels'; |
|
||||||
import { getSceneWithRows } from './sceneWithRows'; |
|
||||||
import { getTransformationsDemo } from './transformations'; |
|
||||||
import { getVariablesDemo, getVariablesDemoWithAll } from './variablesDemo'; |
|
||||||
|
|
||||||
interface SceneDef { |
|
||||||
title: string; |
|
||||||
getScene: () => DashboardScene; |
|
||||||
} |
|
||||||
export function getScenes(): SceneDef[] { |
|
||||||
return [ |
|
||||||
{ title: 'Scene with rows', getScene: getSceneWithRows }, |
|
||||||
{ title: 'Grid with rows and different queries', getScene: getGridWithMultipleData }, |
|
||||||
{ title: 'Grid with rows and different queries and time ranges', getScene: getGridWithMultipleTimeRanges }, |
|
||||||
{ title: 'Multiple grid layouts test', getScene: getMultipleGridLayoutTest }, |
|
||||||
{ title: 'Variables', getScene: getVariablesDemo }, |
|
||||||
{ title: 'Variables with All values', getScene: getVariablesDemoWithAll }, |
|
||||||
{ title: 'Variables - Repeating panels', getScene: getRepeatingPanelsDemo }, |
|
||||||
{ title: 'Variables - Repeating rows', getScene: getRepeatingRowsDemo }, |
|
||||||
{ title: 'Query variable', getScene: getQueryVariableDemo }, |
|
||||||
{ title: 'Transformations demo', getScene: getTransformationsDemo }, |
|
||||||
]; |
|
||||||
} |
|
||||||
|
|
||||||
const cache: Record<string, DashboardScene> = {}; |
|
||||||
|
|
||||||
export function getSceneByTitle(title: string) { |
|
||||||
if (cache[title]) { |
|
||||||
return cache[title]; |
|
||||||
} |
|
||||||
|
|
||||||
const scene = getScenes().find((x) => x.title === title); |
|
||||||
|
|
||||||
if (scene) { |
|
||||||
cache[title] = scene.getScene(); |
|
||||||
} |
|
||||||
|
|
||||||
return cache[title]; |
|
||||||
} |
|
@ -1,22 +0,0 @@ |
|||||||
import { QueryRunnerState, SceneQueryRunner } from '@grafana/scenes'; |
|
||||||
import { TestData } from '@grafana-plugins/grafana-testdata-datasource/dataquery.gen'; |
|
||||||
|
|
||||||
export function getQueryRunnerWithRandomWalkQuery( |
|
||||||
overrides?: Partial<TestData>, |
|
||||||
queryRunnerOverrides?: Partial<QueryRunnerState> |
|
||||||
) { |
|
||||||
return new SceneQueryRunner({ |
|
||||||
queries: [ |
|
||||||
{ |
|
||||||
refId: 'A', |
|
||||||
datasource: { |
|
||||||
uid: 'gdev-testdata', |
|
||||||
type: 'testdata', |
|
||||||
}, |
|
||||||
scenarioId: 'random_walk', |
|
||||||
...overrides, |
|
||||||
}, |
|
||||||
], |
|
||||||
...queryRunnerOverrides, |
|
||||||
}); |
|
||||||
} |
|
@ -1,68 +0,0 @@ |
|||||||
import { VariableRefresh } from '@grafana/data'; |
|
||||||
import { |
|
||||||
SceneCanvasText, |
|
||||||
SceneTimePicker, |
|
||||||
SceneFlexLayout, |
|
||||||
SceneTimeRange, |
|
||||||
VariableValueSelectors, |
|
||||||
SceneVariableSet, |
|
||||||
CustomVariable, |
|
||||||
DataSourceVariable, |
|
||||||
QueryVariable, |
|
||||||
SceneRefreshPicker, |
|
||||||
SceneFlexItem, |
|
||||||
} from '@grafana/scenes'; |
|
||||||
|
|
||||||
import { DashboardScene } from '../../dashboard-scene/scene/DashboardScene'; |
|
||||||
|
|
||||||
export function getQueryVariableDemo(): DashboardScene { |
|
||||||
return new DashboardScene({ |
|
||||||
title: 'Query variable', |
|
||||||
$variables: new SceneVariableSet({ |
|
||||||
variables: [ |
|
||||||
new CustomVariable({ |
|
||||||
name: 'metric', |
|
||||||
query: 'job : job, instance : instance', |
|
||||||
}), |
|
||||||
new DataSourceVariable({ |
|
||||||
name: 'datasource', |
|
||||||
pluginId: 'prometheus', |
|
||||||
}), |
|
||||||
new QueryVariable({ |
|
||||||
name: 'instance (using datasource variable)', |
|
||||||
refresh: VariableRefresh.onTimeRangeChanged, |
|
||||||
query: { query: 'label_values(go_gc_duration_seconds, ${metric})', refId: 'A' }, |
|
||||||
datasource: { uid: '${datasource}' }, |
|
||||||
}), |
|
||||||
new QueryVariable({ |
|
||||||
name: 'label values (on time range refresh)', |
|
||||||
refresh: VariableRefresh.onTimeRangeChanged, |
|
||||||
query: { query: 'label_values(go_gc_duration_seconds, ${metric})', refId: 'B' }, |
|
||||||
datasource: { uid: 'gdev-prometheus', type: 'prometheus' }, |
|
||||||
}), |
|
||||||
new QueryVariable({ |
|
||||||
name: 'legacy (graphite)', |
|
||||||
refresh: VariableRefresh.onTimeRangeChanged, |
|
||||||
query: { queryType: 'Default', target: 'stats.response.*', refId: 'C' }, |
|
||||||
datasource: { uid: 'gdev-graphite', type: 'graphite' }, |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
body: new SceneFlexLayout({ |
|
||||||
direction: 'row', |
|
||||||
children: [ |
|
||||||
new SceneFlexItem({ |
|
||||||
width: '40%', |
|
||||||
body: new SceneCanvasText({ |
|
||||||
text: 'metric: ${metric}', |
|
||||||
fontSize: 20, |
|
||||||
align: 'center', |
|
||||||
}), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
$timeRange: new SceneTimeRange(), |
|
||||||
actions: [new SceneTimePicker({}), new SceneRefreshPicker({})], |
|
||||||
controls: [new VariableValueSelectors({})], |
|
||||||
}); |
|
||||||
} |
|
@ -1,189 +0,0 @@ |
|||||||
import { |
|
||||||
SceneTimePicker, |
|
||||||
SceneTimeRange, |
|
||||||
VariableValueSelectors, |
|
||||||
SceneVariableSet, |
|
||||||
TestVariable, |
|
||||||
SceneRefreshPicker, |
|
||||||
PanelBuilders, |
|
||||||
SceneGridLayout, |
|
||||||
SceneControlsSpacer, |
|
||||||
SceneGridRow, |
|
||||||
} from '@grafana/scenes'; |
|
||||||
import { VariableRefresh } from '@grafana/schema'; |
|
||||||
import { PanelRepeaterGridItem } from 'app/features/dashboard-scene/scene/PanelRepeaterGridItem'; |
|
||||||
import { RowRepeaterBehavior } from 'app/features/dashboard-scene/scene/RowRepeaterBehavior'; |
|
||||||
|
|
||||||
import { DashboardScene } from '../../dashboard-scene/scene/DashboardScene'; |
|
||||||
|
|
||||||
import { getQueryRunnerWithRandomWalkQuery } from './queries'; |
|
||||||
|
|
||||||
/** |
|
||||||
* Repeat panels by variable that changes with time refresh. This tries to setup a very specific scenario |
|
||||||
* where a variable that is slow (2s) and constantly changing it's result is used to repeat panels. This |
|
||||||
* can be used to verify that when the time range change the repeated panels with locally scoped variable value |
|
||||||
* still wait for the top level variable to finish loading and the repeat process to complete. |
|
||||||
*/ |
|
||||||
export function getRepeatingPanelsDemo(): DashboardScene { |
|
||||||
return new DashboardScene({ |
|
||||||
title: 'Variables - Repeating panels', |
|
||||||
$variables: new SceneVariableSet({ |
|
||||||
variables: [ |
|
||||||
new TestVariable({ |
|
||||||
name: 'server', |
|
||||||
query: 'AB', |
|
||||||
value: 'server', |
|
||||||
text: '', |
|
||||||
delayMs: 2000, |
|
||||||
isMulti: true, |
|
||||||
includeAll: true, |
|
||||||
refresh: VariableRefresh.onTimeRangeChanged, |
|
||||||
optionsToReturn: [ |
|
||||||
{ label: 'A', value: 'A' }, |
|
||||||
{ label: 'B', value: 'B' }, |
|
||||||
], |
|
||||||
options: [], |
|
||||||
$behaviors: [changeVariable], |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
body: new SceneGridLayout({ |
|
||||||
isDraggable: true, |
|
||||||
isResizable: true, |
|
||||||
children: [ |
|
||||||
new PanelRepeaterGridItem({ |
|
||||||
variableName: 'server', |
|
||||||
x: 0, |
|
||||||
y: 0, |
|
||||||
width: 24, |
|
||||||
height: 8, |
|
||||||
itemHeight: 8, |
|
||||||
source: PanelBuilders.timeseries() |
|
||||||
.setTitle('server = $server') |
|
||||||
.setData(getQueryRunnerWithRandomWalkQuery({ alias: 'server = $server' })) |
|
||||||
.build(), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
$timeRange: new SceneTimeRange(), |
|
||||||
actions: [], |
|
||||||
controls: [ |
|
||||||
new VariableValueSelectors({}), |
|
||||||
new SceneControlsSpacer(), |
|
||||||
new SceneTimePicker({}), |
|
||||||
new SceneRefreshPicker({}), |
|
||||||
], |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
function changeVariable(variable: TestVariable) { |
|
||||||
const sub = variable.subscribeToState((state, old) => { |
|
||||||
if (!state.loading && old.loading) { |
|
||||||
if (variable.state.optionsToReturn?.length === 2) { |
|
||||||
variable.setState({ |
|
||||||
query: 'ABC', |
|
||||||
optionsToReturn: [ |
|
||||||
{ label: 'A', value: 'A' }, |
|
||||||
{ label: 'B', value: 'B' }, |
|
||||||
{ label: 'C', value: 'C' }, |
|
||||||
], |
|
||||||
}); |
|
||||||
} else { |
|
||||||
variable.setState({ |
|
||||||
query: 'AB', |
|
||||||
optionsToReturn: [ |
|
||||||
{ label: 'A', value: 'A' }, |
|
||||||
{ label: 'B', value: 'B' }, |
|
||||||
], |
|
||||||
}); |
|
||||||
} |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
return () => { |
|
||||||
sub.unsubscribe(); |
|
||||||
}; |
|
||||||
} |
|
||||||
|
|
||||||
export function getRepeatingRowsDemo(): DashboardScene { |
|
||||||
return new DashboardScene({ |
|
||||||
title: 'Variables - Repeating rows', |
|
||||||
$variables: new SceneVariableSet({ |
|
||||||
variables: [ |
|
||||||
new TestVariable({ |
|
||||||
name: 'server', |
|
||||||
query: 'AB', |
|
||||||
value: ['A', 'B', 'C'], |
|
||||||
text: ['A', 'B', 'C'], |
|
||||||
delayMs: 2000, |
|
||||||
isMulti: true, |
|
||||||
includeAll: true, |
|
||||||
refresh: VariableRefresh.onTimeRangeChanged, |
|
||||||
optionsToReturn: [ |
|
||||||
{ label: 'A', value: 'A' }, |
|
||||||
{ label: 'B', value: 'B' }, |
|
||||||
{ label: 'C', value: 'C' }, |
|
||||||
], |
|
||||||
options: [], |
|
||||||
//$behaviors: [changeVariable],
|
|
||||||
}), |
|
||||||
new TestVariable({ |
|
||||||
name: 'pod', |
|
||||||
query: 'AB', |
|
||||||
value: ['Mu', 'Ma', 'Mi'], |
|
||||||
text: ['Mu', 'Ma', 'Mi'], |
|
||||||
delayMs: 2000, |
|
||||||
isMulti: true, |
|
||||||
includeAll: true, |
|
||||||
refresh: VariableRefresh.onTimeRangeChanged, |
|
||||||
optionsToReturn: [ |
|
||||||
{ label: 'Mu', value: 'Mu' }, |
|
||||||
{ label: 'Ma', value: 'Ma' }, |
|
||||||
{ label: 'Mi', value: 'Mi' }, |
|
||||||
], |
|
||||||
options: [], |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
body: new SceneGridLayout({ |
|
||||||
isDraggable: true, |
|
||||||
isResizable: true, |
|
||||||
children: [ |
|
||||||
new SceneGridRow({ |
|
||||||
title: 'Row $server', |
|
||||||
key: 'Row A', |
|
||||||
isCollapsed: false, |
|
||||||
y: 0, |
|
||||||
x: 0, |
|
||||||
$behaviors: [ |
|
||||||
new RowRepeaterBehavior({ |
|
||||||
variableName: 'server', |
|
||||||
sources: [ |
|
||||||
new PanelRepeaterGridItem({ |
|
||||||
variableName: 'pod', |
|
||||||
x: 0, |
|
||||||
y: 0, |
|
||||||
width: 24, |
|
||||||
height: 5, |
|
||||||
itemHeight: 5, |
|
||||||
source: PanelBuilders.timeseries() |
|
||||||
.setTitle('server = $server, pod = $pod') |
|
||||||
.setData(getQueryRunnerWithRandomWalkQuery({ alias: 'server = $server, pod = $pod' })) |
|
||||||
.build(), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
$timeRange: new SceneTimeRange(), |
|
||||||
actions: [], |
|
||||||
controls: [ |
|
||||||
new VariableValueSelectors({}), |
|
||||||
new SceneControlsSpacer(), |
|
||||||
new SceneTimePicker({}), |
|
||||||
new SceneRefreshPicker({}), |
|
||||||
], |
|
||||||
}); |
|
||||||
} |
|
@ -1,58 +0,0 @@ |
|||||||
import { |
|
||||||
NestedScene, |
|
||||||
SceneTimePicker, |
|
||||||
SceneFlexLayout, |
|
||||||
SceneTimeRange, |
|
||||||
SceneRefreshPicker, |
|
||||||
SceneFlexItem, |
|
||||||
PanelBuilders, |
|
||||||
} from '@grafana/scenes'; |
|
||||||
|
|
||||||
import { DashboardScene } from '../../dashboard-scene/scene/DashboardScene'; |
|
||||||
|
|
||||||
import { getQueryRunnerWithRandomWalkQuery } from './queries'; |
|
||||||
|
|
||||||
export function getSceneWithRows(): DashboardScene { |
|
||||||
return new DashboardScene({ |
|
||||||
title: 'Scene with rows', |
|
||||||
body: new SceneFlexLayout({ |
|
||||||
direction: 'column', |
|
||||||
children: [ |
|
||||||
new NestedScene({ |
|
||||||
title: 'Overview', |
|
||||||
canCollapse: true, |
|
||||||
body: new SceneFlexLayout({ |
|
||||||
direction: 'row', |
|
||||||
children: [ |
|
||||||
new SceneFlexItem({ |
|
||||||
body: PanelBuilders.timeseries().setTitle('Fill height').build(), |
|
||||||
}), |
|
||||||
|
|
||||||
new SceneFlexItem({ |
|
||||||
body: PanelBuilders.timeseries().setTitle('Fill height').build(), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
}), |
|
||||||
new NestedScene({ |
|
||||||
title: 'More server details', |
|
||||||
canCollapse: true, |
|
||||||
body: new SceneFlexLayout({ |
|
||||||
direction: 'row', |
|
||||||
children: [ |
|
||||||
new SceneFlexItem({ |
|
||||||
body: PanelBuilders.timeseries().setTitle('Fill height').build(), |
|
||||||
}), |
|
||||||
new SceneFlexItem({ |
|
||||||
body: PanelBuilders.timeseries().setTitle('Fill height').build(), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
$timeRange: new SceneTimeRange(), |
|
||||||
$data: getQueryRunnerWithRandomWalkQuery(), |
|
||||||
actions: [new SceneTimePicker({}), new SceneRefreshPicker({})], |
|
||||||
}); |
|
||||||
} |
|
@ -1,79 +0,0 @@ |
|||||||
import { |
|
||||||
SceneTimePicker, |
|
||||||
SceneFlexLayout, |
|
||||||
SceneDataTransformer, |
|
||||||
SceneTimeRange, |
|
||||||
SceneRefreshPicker, |
|
||||||
SceneFlexItem, |
|
||||||
PanelBuilders, |
|
||||||
} from '@grafana/scenes'; |
|
||||||
|
|
||||||
import { DashboardScene } from '../../dashboard-scene/scene/DashboardScene'; |
|
||||||
|
|
||||||
import { getQueryRunnerWithRandomWalkQuery } from './queries'; |
|
||||||
|
|
||||||
export function getTransformationsDemo(): DashboardScene { |
|
||||||
return new DashboardScene({ |
|
||||||
title: 'Transformations demo', |
|
||||||
body: new SceneFlexLayout({ |
|
||||||
direction: 'row', |
|
||||||
children: [ |
|
||||||
new SceneFlexItem({ |
|
||||||
body: new SceneFlexLayout({ |
|
||||||
direction: 'column', |
|
||||||
children: [ |
|
||||||
new SceneFlexItem({ |
|
||||||
body: new SceneFlexLayout({ |
|
||||||
direction: 'row', |
|
||||||
children: [ |
|
||||||
new SceneFlexItem({ |
|
||||||
body: PanelBuilders.timeseries().setTitle('Source data (global query)').build(), |
|
||||||
}), |
|
||||||
new SceneFlexItem({ |
|
||||||
body: PanelBuilders.stat() |
|
||||||
.setTitle('Transformed data') |
|
||||||
.setData( |
|
||||||
new SceneDataTransformer({ |
|
||||||
transformations: [ |
|
||||||
{ |
|
||||||
id: 'reduce', |
|
||||||
options: { |
|
||||||
reducers: ['last', 'mean'], |
|
||||||
}, |
|
||||||
}, |
|
||||||
], |
|
||||||
}) |
|
||||||
) |
|
||||||
.build(), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
}), |
|
||||||
new SceneFlexItem({ |
|
||||||
body: PanelBuilders.stat() |
|
||||||
.setTitle('Query with predefined transformations') |
|
||||||
.setData( |
|
||||||
new SceneDataTransformer({ |
|
||||||
$data: getQueryRunnerWithRandomWalkQuery(), |
|
||||||
transformations: [ |
|
||||||
{ |
|
||||||
id: 'reduce', |
|
||||||
options: { |
|
||||||
reducers: ['mean'], |
|
||||||
}, |
|
||||||
}, |
|
||||||
], |
|
||||||
}) |
|
||||||
) |
|
||||||
.build(), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
$timeRange: new SceneTimeRange(), |
|
||||||
$data: getQueryRunnerWithRandomWalkQuery(), |
|
||||||
actions: [new SceneTimePicker({}), new SceneRefreshPicker({})], |
|
||||||
}); |
|
||||||
} |
|
@ -1,203 +0,0 @@ |
|||||||
import { |
|
||||||
SceneCanvasText, |
|
||||||
SceneTimePicker, |
|
||||||
SceneFlexLayout, |
|
||||||
SceneTimeRange, |
|
||||||
VariableValueSelectors, |
|
||||||
SceneVariableSet, |
|
||||||
CustomVariable, |
|
||||||
DataSourceVariable, |
|
||||||
TestVariable, |
|
||||||
NestedScene, |
|
||||||
SceneRefreshPicker, |
|
||||||
TextBoxVariable, |
|
||||||
SceneFlexItem, |
|
||||||
PanelBuilders, |
|
||||||
} from '@grafana/scenes'; |
|
||||||
|
|
||||||
import { DashboardScene } from '../../dashboard-scene/scene/DashboardScene'; |
|
||||||
|
|
||||||
import { getQueryRunnerWithRandomWalkQuery } from './queries'; |
|
||||||
|
|
||||||
export function getVariablesDemo(): DashboardScene { |
|
||||||
return new DashboardScene({ |
|
||||||
title: 'Variables', |
|
||||||
$variables: new SceneVariableSet({ |
|
||||||
variables: [ |
|
||||||
new TestVariable({ |
|
||||||
name: 'server', |
|
||||||
query: 'A.*', |
|
||||||
value: 'server', |
|
||||||
text: '', |
|
||||||
delayMs: 1000, |
|
||||||
options: [], |
|
||||||
}), |
|
||||||
new TestVariable({ |
|
||||||
name: 'pod', |
|
||||||
query: 'A.$server.*', |
|
||||||
value: 'pod', |
|
||||||
delayMs: 1000, |
|
||||||
isMulti: true, |
|
||||||
text: '', |
|
||||||
options: [], |
|
||||||
}), |
|
||||||
new TestVariable({ |
|
||||||
name: 'handler', |
|
||||||
query: 'A.$server.$pod.*', |
|
||||||
value: 'handler', |
|
||||||
delayMs: 1000, |
|
||||||
//isMulti: true,
|
|
||||||
text: '', |
|
||||||
options: [], |
|
||||||
}), |
|
||||||
new CustomVariable({ |
|
||||||
name: 'custom', |
|
||||||
query: 'A : 10,B : 20', |
|
||||||
}), |
|
||||||
new DataSourceVariable({ |
|
||||||
name: 'ds', |
|
||||||
pluginId: 'testdata', |
|
||||||
}), |
|
||||||
new TextBoxVariable({ |
|
||||||
name: 'textbox', |
|
||||||
value: 'default value', |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
body: new SceneFlexLayout({ |
|
||||||
direction: 'row', |
|
||||||
children: [ |
|
||||||
new SceneFlexItem({ |
|
||||||
body: new SceneFlexLayout({ |
|
||||||
direction: 'column', |
|
||||||
children: [ |
|
||||||
new SceneFlexItem({ |
|
||||||
body: new SceneFlexLayout({ |
|
||||||
children: [ |
|
||||||
new SceneFlexItem({ |
|
||||||
body: PanelBuilders.timeseries() |
|
||||||
.setTitle('handler: $handler') |
|
||||||
.setData( |
|
||||||
getQueryRunnerWithRandomWalkQuery({ |
|
||||||
alias: 'handler: $handler', |
|
||||||
}) |
|
||||||
) |
|
||||||
.build(), |
|
||||||
}), |
|
||||||
new SceneFlexItem({ |
|
||||||
body: new SceneCanvasText({ |
|
||||||
text: 'Text: ${textbox}', |
|
||||||
fontSize: 20, |
|
||||||
align: 'center', |
|
||||||
}), |
|
||||||
}), |
|
||||||
new SceneFlexItem({ |
|
||||||
width: '40%', |
|
||||||
body: new SceneCanvasText({ |
|
||||||
text: 'server: ${server} pod:${pod}', |
|
||||||
fontSize: 20, |
|
||||||
align: 'center', |
|
||||||
}), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
}), |
|
||||||
new SceneFlexItem({ |
|
||||||
body: new NestedScene({ |
|
||||||
title: 'Collapsable inner scene', |
|
||||||
canCollapse: true, |
|
||||||
body: new SceneFlexLayout({ |
|
||||||
direction: 'row', |
|
||||||
children: [ |
|
||||||
new SceneFlexItem({ |
|
||||||
body: PanelBuilders.timeseries() |
|
||||||
.setTitle('handler: $handler') |
|
||||||
.setData( |
|
||||||
getQueryRunnerWithRandomWalkQuery({ |
|
||||||
alias: 'handler: $handler', |
|
||||||
}) |
|
||||||
) |
|
||||||
.build(), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
}), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
$timeRange: new SceneTimeRange(), |
|
||||||
actions: [new SceneTimePicker({}), new SceneRefreshPicker({})], |
|
||||||
controls: [new VariableValueSelectors({})], |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
export function getVariablesDemoWithAll(): DashboardScene { |
|
||||||
return new DashboardScene({ |
|
||||||
title: 'Variables with All values', |
|
||||||
$variables: new SceneVariableSet({ |
|
||||||
variables: [ |
|
||||||
new TestVariable({ |
|
||||||
name: 'server', |
|
||||||
query: 'A.*', |
|
||||||
value: 'AA', |
|
||||||
text: 'AA', |
|
||||||
includeAll: true, |
|
||||||
defaultToAll: true, |
|
||||||
delayMs: 1000, |
|
||||||
options: [], |
|
||||||
}), |
|
||||||
new TestVariable({ |
|
||||||
name: 'pod', |
|
||||||
query: 'A.$server.*', |
|
||||||
value: [], |
|
||||||
delayMs: 1000, |
|
||||||
isMulti: true, |
|
||||||
includeAll: true, |
|
||||||
defaultToAll: true, |
|
||||||
text: '', |
|
||||||
options: [], |
|
||||||
}), |
|
||||||
new TestVariable({ |
|
||||||
name: 'handler', |
|
||||||
query: 'A.$server.$pod.*', |
|
||||||
value: [], |
|
||||||
delayMs: 1000, |
|
||||||
includeAll: true, |
|
||||||
defaultToAll: false, |
|
||||||
isMulti: true, |
|
||||||
text: '', |
|
||||||
options: [], |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
body: new SceneFlexLayout({ |
|
||||||
direction: 'row', |
|
||||||
children: [ |
|
||||||
new SceneFlexItem({ |
|
||||||
body: PanelBuilders.timeseries() |
|
||||||
.setTitle('handler: $handler') |
|
||||||
.setData( |
|
||||||
getQueryRunnerWithRandomWalkQuery({ |
|
||||||
alias: 'handler: $handler', |
|
||||||
}) |
|
||||||
) |
|
||||||
.build(), |
|
||||||
}), |
|
||||||
new SceneFlexItem({ |
|
||||||
width: '40%', |
|
||||||
body: new SceneCanvasText({ |
|
||||||
text: 'server: ${server} pod:${pod}', |
|
||||||
fontSize: 20, |
|
||||||
align: 'center', |
|
||||||
}), |
|
||||||
}), |
|
||||||
], |
|
||||||
}), |
|
||||||
$timeRange: new SceneTimeRange(), |
|
||||||
actions: [new SceneTimePicker({}), new SceneRefreshPicker({})], |
|
||||||
controls: [new VariableValueSelectors({})], |
|
||||||
}); |
|
||||||
} |
|
Loading…
Reference in new issue