datatrails: fix: indicate __ignore_usage__ for preview queries (#82291)

* fix: indicate __ignore_usage__ for preview queries

* fix: further remove var that shouldn't be there

* refactor: move previewPanel code and add tests

* fix: use simpler `AdHocFiltersVariable` state

Co-authored-by: Andre Pereira <adrapereira@gmail.com>

---------

Co-authored-by: Andre Pereira <adrapereira@gmail.com>
This commit is contained in:
Darren Janeczek
2024-02-26 10:01:54 -05:00
committed by GitHub
parent da4fb8b3ed
commit fb324fc8ac
4 changed files with 98 additions and 31 deletions
@@ -0,0 +1,31 @@
import { SceneQueryRunner } from '@grafana/scenes';
import { getPreviewPanelFor } from './previewPanel';
describe('getPreviewPanelFor', () => {
describe('includes __ignore_usage__ indicator', () => {
function callAndGetExpr(filterCount: number) {
const result = getPreviewPanelFor('METRIC', 0, filterCount);
const runner = result.state.$data as SceneQueryRunner;
expect(runner).toBeInstanceOf(SceneQueryRunner);
const query = runner.state.queries[0];
const expr = query.expr as string;
return expr;
}
test('When there are no filters, replace the ${filters} variable', () => {
const expected = "avg(${metric}{__ignore_usage__=''})";
const expr = callAndGetExpr(0);
expect(expr).toStrictEqual(expected);
});
test('When there are 1 or more filters, append to the ${filters} variable', () => {
const expected = "avg(${metric}{${filters},__ignore_usage__=''})";
for (let i = 1; i < 10; ++i) {
const expr = callAndGetExpr(1);
expect(expr).toStrictEqual(expected);
}
});
});
});
@@ -0,0 +1,48 @@
import { SceneCSSGridItem, SceneQueryRunner, SceneVariableSet } from '@grafana/scenes';
import { PromQuery } from 'app/plugins/datasource/prometheus/types';
import { SelectMetricAction } from '../SelectMetricAction';
import { hideEmptyPreviews } from '../hideEmptyPreviews';
import { getVariablesWithMetricConstant, trailDS } from '../shared';
import { getColorByIndex } from '../utils';
import { getAutoQueriesForMetric } from './AutoQueryEngine';
export function getPreviewPanelFor(metric: string, index: number, currentFilterCount: number) {
const autoQuery = getAutoQueriesForMetric(metric);
const vizPanel = autoQuery.preview
.vizBuilder()
.setColor({ mode: 'fixed', fixedColor: getColorByIndex(index) })
.setHeaderActions(new SelectMetricAction({ metric, title: 'Select' }))
.build();
const queries = autoQuery.preview.queries.map((query) =>
convertPreviewQueriesToIgnoreUsage(query, currentFilterCount)
);
return new SceneCSSGridItem({
$variables: new SceneVariableSet({
variables: getVariablesWithMetricConstant(metric),
}),
$behaviors: [hideEmptyPreviews(metric)],
$data: new SceneQueryRunner({
datasource: trailDS,
maxDataPoints: 200,
queries,
}),
body: vizPanel,
});
}
function convertPreviewQueriesToIgnoreUsage(query: PromQuery, currentFilterCount: number) {
// If there are filters, we append to the list. Otherwise, we replace the empty list.
const replacement = currentFilterCount > 0 ? "${filters},__ignore_usage__=''" : "__ignore_usage__=''";
const expr = query.expr?.replace('${filters}', replacement);
return {
...query,
expr,
};
}
@@ -15,7 +15,6 @@ import {
SceneObjectBase,
SceneObjectRef,
SceneObjectState,
SceneQueryRunner,
SceneVariable,
SceneVariableSet,
VariableDependencyConfig,
@@ -23,14 +22,13 @@ import {
import { VariableHide } from '@grafana/schema';
import { Input, useStyles2, InlineSwitch, Field, Alert, Icon, LoadingPlaceholder } from '@grafana/ui';
import { getAutoQueriesForMetric } from './AutomaticMetricQueries/AutoQueryEngine';
import { getPreviewPanelFor } from './AutomaticMetricQueries/previewPanel';
import { MetricCategoryCascader } from './MetricCategory/MetricCategoryCascader';
import { MetricScene } from './MetricScene';
import { SelectMetricAction } from './SelectMetricAction';
import { hideEmptyPreviews } from './hideEmptyPreviews';
import { sortRelatedMetrics } from './relatedMetrics';
import { getVariablesWithMetricConstant, trailDS, VAR_DATASOURCE, VAR_FILTERS_EXPR, VAR_METRIC_NAMES } from './shared';
import { getColorByIndex, getTrailFor } from './utils';
import { getFilters, getTrailFor } from './utils';
interface MetricPanel {
name: string;
@@ -75,8 +73,6 @@ export class MetricSelectScene extends SceneObjectBase<MetricSelectSceneState> {
this.addActivationHandler(this._onActivate.bind(this));
}
// private justChangedTimeRange = false;
protected _variableDependency = new VariableDependencyConfig(this, {
variableNames: [VAR_METRIC_NAMES, VAR_DATASOURCE],
onReferencedVariableValueChanged: (variable: SceneVariable) => {
@@ -248,7 +244,13 @@ export class MetricSelectScene extends SceneObjectBase<MetricSelectSceneState> {
const children: SceneFlexItem[] = [];
const metricsList = this.sortedPreviewMetrics(); //!this.justChangedTimeRange ? this.sortedPreviewMetrics() : Object.values(this.previewCache);
const metricsList = this.sortedPreviewMetrics();
// Get the current filters to determine the count of them
// Which is required for `getPreviewPanelFor`
const filters = getFilters(this);
const currentFilterCount = filters?.length || 0;
for (let index = 0; index < metricsList.length; index++) {
const metric = metricsList[index];
@@ -257,7 +259,7 @@ export class MetricSelectScene extends SceneObjectBase<MetricSelectSceneState> {
children.push(metric.itemRef.resolve());
continue;
}
const panel = getPreviewPanelFor(metric.name, index);
const panel = getPreviewPanelFor(metric.name, index, currentFilterCount);
metric.itemRef = panel.getRef();
metric.isPanel = true;
children.push(panel);
@@ -400,29 +402,6 @@ function getMetricNamesVariableSet() {
});
}
function getPreviewPanelFor(metric: string, index: number) {
const autoQuery = getAutoQueriesForMetric(metric);
const vizPanel = autoQuery.preview
.vizBuilder()
.setColor({ mode: 'fixed', fixedColor: getColorByIndex(index) })
.setHeaderActions(new SelectMetricAction({ metric, title: 'Select' }))
.build();
return new SceneCSSGridItem({
$variables: new SceneVariableSet({
variables: getVariablesWithMetricConstant(metric),
}),
$behaviors: [hideEmptyPreviews(metric)],
$data: new SceneQueryRunner({
datasource: trailDS,
maxDataPoints: 200,
queries: autoQuery.preview.queries,
}),
body: vizPanel,
});
}
function getCardPanelFor(metric: string) {
return PanelBuilders.text()
.setTitle(metric)
+9
View File
@@ -1,6 +1,7 @@
import { urlUtil } from '@grafana/data';
import { config, getDataSourceSrv } from '@grafana/runtime';
import {
AdHocFiltersVariable,
getUrlSyncManager,
sceneGraph,
SceneObject,
@@ -105,3 +106,11 @@ export function isSceneTimeRangeState(state: SceneObjectState): state is SceneTi
const keys = Object.keys(state);
return keys.includes('from') && keys.includes('to');
}
export function getFilters(scene: SceneObject) {
const filters = sceneGraph.lookupVariable('filters', scene);
if (filters instanceof AdHocFiltersVariable) {
return filters.state.filters;
}
return null;
}