mirror of
https://github.com/grafana/grafana.git
synced 2026-08-26 21:37:31 -05:00
datatrails: interpolate adhoc variables and datasource variables when opening "explore metrics" from dashboard panels (#86252)
* fix: interpolate "explore metrics" from panels --------- Co-authored-by: Darren Janeczek <darren.janeczek@grafana.com> * fix: remove support for legacy dashboard - simplify code - take advantage of scenes dashboard async and datasource api object --------- Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
This commit is contained in:
co-authored by
Torkel Ödegaard
parent
8028d1c3e1
commit
53ead9904d
@@ -168,7 +168,7 @@ export function panelMenuBehavior(menu: VizPanelMenu, isRepeat = false) {
|
||||
}
|
||||
|
||||
if (config.featureToggles.exploreMetrics) {
|
||||
addDataTrailPanelAction(dashboard, panel, items);
|
||||
await addDataTrailPanelAction(dashboard, panel, items);
|
||||
}
|
||||
|
||||
if (exploreMenuItem) {
|
||||
|
||||
@@ -25,7 +25,6 @@ import { DashboardInteractions } from 'app/features/dashboard-scene/utils/intera
|
||||
import { InspectTab } from 'app/features/inspector/types';
|
||||
import { isPanelModelLibraryPanel } from 'app/features/library-panels/guard';
|
||||
import { createExtensionSubMenu } from 'app/features/plugins/extensions/utils';
|
||||
import { addDataTrailPanelAction } from 'app/features/trails/Integrations/dashboardIntegration';
|
||||
import { SHARED_DASHBOARD_QUERY } from 'app/plugins/datasource/dashboard';
|
||||
import { dispatch, store } from 'app/store/store';
|
||||
|
||||
@@ -164,10 +163,6 @@ export function getPanelMenu(
|
||||
});
|
||||
}
|
||||
|
||||
if (config.featureToggles.exploreMetrics) {
|
||||
addDataTrailPanelAction(dashboard, panel, menu);
|
||||
}
|
||||
|
||||
const inspectMenu: PanelMenuItem[] = [];
|
||||
|
||||
// Only show these inspect actions for data plugins
|
||||
|
||||
@@ -1,55 +1,55 @@
|
||||
import { isString } from 'lodash';
|
||||
|
||||
import { PanelMenuItem, PanelModel } from '@grafana/data';
|
||||
import { PanelMenuItem } from '@grafana/data';
|
||||
import { PromQuery } from '@grafana/prometheus';
|
||||
import { getDataSourceSrv } from '@grafana/runtime';
|
||||
import { SceneTimeRangeLike, VizPanel } from '@grafana/scenes';
|
||||
import { DataSourceRef } from '@grafana/schema';
|
||||
import { DataQuery, DataSourceRef } from '@grafana/schema';
|
||||
import { getQueryRunnerFor } from 'app/features/dashboard-scene/utils/utils';
|
||||
|
||||
import { DashboardModel } from '../../dashboard/state';
|
||||
import { DashboardScene } from '../../dashboard-scene/scene/DashboardScene';
|
||||
import { MetricScene } from '../MetricScene';
|
||||
import { reportExploreMetrics } from '../interactions';
|
||||
|
||||
import { DataTrailEmbedded, DataTrailEmbeddedState } from './DataTrailEmbedded';
|
||||
import { SceneDrawerAsScene, launchSceneDrawerInGlobalModal } from './SceneDrawer';
|
||||
import { SceneDrawerAsScene } from './SceneDrawer';
|
||||
import { QueryMetric, getQueryMetrics } from './getQueryMetrics';
|
||||
import {
|
||||
createAdHocFilters,
|
||||
getPanelType,
|
||||
getQueryMetricLabel,
|
||||
getQueryRunner,
|
||||
getTimeRangeFromDashboard,
|
||||
} from './utils';
|
||||
import { createAdHocFilters, getQueryMetricLabel, getTimeRangeFromDashboard } from './utils';
|
||||
|
||||
export function addDataTrailPanelAction(
|
||||
dashboard: DashboardScene | DashboardModel,
|
||||
panel: VizPanel | PanelModel,
|
||||
items: PanelMenuItem[]
|
||||
) {
|
||||
const panelType = getPanelType(panel);
|
||||
if (panelType !== 'timeseries') {
|
||||
export async function addDataTrailPanelAction(dashboard: DashboardScene, panel: VizPanel, items: PanelMenuItem[]) {
|
||||
if (panel.state.pluginId !== 'timeseries') {
|
||||
return;
|
||||
}
|
||||
|
||||
const queryRunner = getQueryRunner(panel);
|
||||
if (!queryRunner) {
|
||||
const queryRunner = getQueryRunnerFor(panel);
|
||||
if (queryRunner == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ds = getDataSourceSrv().getInstanceSettings(queryRunner.state.datasource);
|
||||
const { queries, datasource, data } = queryRunner.state;
|
||||
|
||||
if (ds?.meta.id !== 'prometheus') {
|
||||
if (datasource == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const queries = queryRunner.state.queries.map((q) => q.expr).filter(isString);
|
||||
if (datasource.type !== 'prometheus') {
|
||||
return;
|
||||
}
|
||||
|
||||
const queryMetrics = getQueryMetrics(queries);
|
||||
const dataSourceApi = await getDataSourceSrv().get(datasource);
|
||||
|
||||
if (dataSourceApi.interpolateVariablesInQueries == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const interpolated = dataSourceApi
|
||||
.interpolateVariablesInQueries(queries, { __sceneObject: { value: panel } }, data?.request?.filters)
|
||||
.filter(isPromQuery);
|
||||
|
||||
const queryMetrics = getQueryMetrics(interpolated.map((q) => q.expr));
|
||||
|
||||
const subMenu: PanelMenuItem[] = queryMetrics.map((item) => {
|
||||
return {
|
||||
text: getQueryMetricLabel(item),
|
||||
onClick: createClickHandler(item, dashboard, ds),
|
||||
onClick: createClickHandler(item, dashboard, dataSourceApi),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -88,11 +88,7 @@ function getEmbeddedTrailsState(
|
||||
return state;
|
||||
}
|
||||
|
||||
function createCommonEmbeddedTrailStateProps(
|
||||
item: QueryMetric,
|
||||
dashboard: DashboardScene | DashboardModel,
|
||||
ds: DataSourceRef
|
||||
) {
|
||||
function createCommonEmbeddedTrailStateProps(item: QueryMetric, dashboard: DashboardScene, ds: DataSourceRef) {
|
||||
const timeRange = getTimeRangeFromDashboard(dashboard);
|
||||
const trailState = getEmbeddedTrailsState(item, timeRange, ds.uid);
|
||||
const embeddedTrail: DataTrailEmbedded = new DataTrailEmbedded(trailState);
|
||||
@@ -111,21 +107,18 @@ function createCommonEmbeddedTrailStateProps(
|
||||
return commonProps;
|
||||
}
|
||||
|
||||
function createClickHandler(item: QueryMetric, dashboard: DashboardScene | DashboardModel, ds: DataSourceRef) {
|
||||
if (dashboard instanceof DashboardScene) {
|
||||
return () => {
|
||||
const commonProps = createCommonEmbeddedTrailStateProps(item, dashboard, ds);
|
||||
const drawerScene = new SceneDrawerAsScene({
|
||||
...commonProps,
|
||||
onDismiss: () => dashboard.closeModal(),
|
||||
});
|
||||
reportExploreMetrics('exploration_started', { cause: 'dashboard_panel' });
|
||||
dashboard.showModal(drawerScene);
|
||||
};
|
||||
} else {
|
||||
return () => {
|
||||
reportExploreMetrics('exploration_started', { cause: 'dashboard_panel' });
|
||||
launchSceneDrawerInGlobalModal(createCommonEmbeddedTrailStateProps(item, dashboard, ds));
|
||||
};
|
||||
}
|
||||
function createClickHandler(item: QueryMetric, dashboard: DashboardScene, ds: DataSourceRef) {
|
||||
return () => {
|
||||
const commonProps = createCommonEmbeddedTrailStateProps(item, dashboard, ds);
|
||||
const drawerScene = new SceneDrawerAsScene({
|
||||
...commonProps,
|
||||
onDismiss: () => dashboard.closeModal(),
|
||||
});
|
||||
reportExploreMetrics('exploration_started', { cause: 'dashboard_panel' });
|
||||
dashboard.showModal(drawerScene);
|
||||
};
|
||||
}
|
||||
|
||||
export function isPromQuery(model: DataQuery): model is PromQuery {
|
||||
return 'expr' in model;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import { PanelModel } from '@grafana/data';
|
||||
import { QueryBuilderLabelFilter } from '@grafana/prometheus/src/querybuilder/shared/types';
|
||||
import { SceneQueryRunner, SceneTimeRange, VizPanel } from '@grafana/scenes';
|
||||
import { DashboardModel } from 'app/features/dashboard/state';
|
||||
import { DashboardScene } from 'app/features/dashboard-scene/scene/DashboardScene';
|
||||
import { getQueryRunnerFor } from 'app/features/dashboard-scene/utils/utils';
|
||||
|
||||
import { QueryMetric } from './getQueryMetrics';
|
||||
|
||||
@@ -12,22 +8,8 @@ export function isEquals(labelFilter: QueryBuilderLabelFilter) {
|
||||
return labelFilter.op === '=';
|
||||
}
|
||||
|
||||
export function getQueryRunner(panel: VizPanel | PanelModel) {
|
||||
if (panel instanceof VizPanel) {
|
||||
return getQueryRunnerFor(panel);
|
||||
}
|
||||
|
||||
return new SceneQueryRunner({ datasource: panel.datasource || undefined, queries: panel.targets || [] });
|
||||
}
|
||||
|
||||
export function getTimeRangeFromDashboard(dashboard: DashboardScene | DashboardModel) {
|
||||
if (dashboard instanceof DashboardScene) {
|
||||
return dashboard.state.$timeRange!.clone();
|
||||
}
|
||||
if (dashboard instanceof DashboardModel) {
|
||||
return new SceneTimeRange({ ...dashboard.time });
|
||||
}
|
||||
return new SceneTimeRange();
|
||||
export function getTimeRangeFromDashboard(dashboard: DashboardScene) {
|
||||
return dashboard.state.$timeRange!.clone();
|
||||
}
|
||||
|
||||
export function getQueryMetricLabel({ metric, labelFilters }: QueryMetric) {
|
||||
@@ -43,10 +25,3 @@ export function getQueryMetricLabel({ metric, labelFilters }: QueryMetric) {
|
||||
export function createAdHocFilters(labels: QueryBuilderLabelFilter[]) {
|
||||
return labels?.map((label) => ({ key: label.label, value: label.value, operator: label.op }));
|
||||
}
|
||||
|
||||
export function getPanelType(panel: VizPanel | PanelModel) {
|
||||
if (panel instanceof VizPanel) {
|
||||
return panel.state.pluginId;
|
||||
}
|
||||
return panel.type;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user