Explore Metrics: Remove overview tab in metric select view (#97118)
* introduce the exploreMetricsRemoveOverviewTab feature toggle * handle actionView equal to overview in url * set description in selected metric scene * fix import * ExploreMetrics: Disable the Overview tab by default (#98988) feat: disable overview tab by default * fix: remove unnecessary feature toggle * chore: remove overview * make i18n-extract --------- Co-authored-by: Nick Richmond <5732000+NWRichmond@users.noreply.github.com> Co-authored-by: Nick Richmond <nick.richmond@grafana.com>
This commit is contained in:
co-authored by
Nick Richmond
Nick Richmond
parent
6f12b8e3a4
commit
12ae2a520c
@@ -6153,9 +6153,6 @@ exports[`better eslint`] = {
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "10"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "11"]
|
||||
],
|
||||
"public/app/features/trails/ActionTabs/MetricOverviewScene.tsx:5381": [
|
||||
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
|
||||
],
|
||||
"public/app/features/trails/Breakdown/AddToFiltersGraphAction.tsx:5381": [
|
||||
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
|
||||
],
|
||||
|
||||
@@ -1,191 +0,0 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { isValidLegacyName, PromMetricsMetadataItem } from '@grafana/prometheus';
|
||||
import {
|
||||
QueryVariable,
|
||||
SceneComponentProps,
|
||||
sceneGraph,
|
||||
SceneObjectBase,
|
||||
SceneObjectState,
|
||||
VariableDependencyConfig,
|
||||
VariableValueOption,
|
||||
} from '@grafana/scenes';
|
||||
import { Stack, Text, TextLink } from '@grafana/ui';
|
||||
import { Trans } from 'app/core/internationalization';
|
||||
|
||||
import { MetricScene } from '../MetricScene';
|
||||
import { StatusWrapper } from '../StatusWrapper';
|
||||
import { getUnitFromMetric } from '../autoQuery/units';
|
||||
import { reportExploreMetrics } from '../interactions';
|
||||
import { updateOtelJoinWithGroupLeft } from '../otel/util';
|
||||
import { VAR_DATASOURCE_EXPR, VAR_GROUP_BY, VAR_OTEL_GROUP_LEFT } from '../shared';
|
||||
import { getMetricSceneFor, getTrailFor } from '../utils';
|
||||
|
||||
export interface MetricOverviewSceneState extends SceneObjectState {
|
||||
metadata?: PromMetricsMetadataItem;
|
||||
metadataLoading?: boolean;
|
||||
}
|
||||
|
||||
export class MetricOverviewScene extends SceneObjectBase<MetricOverviewSceneState> {
|
||||
protected _variableDependency = new VariableDependencyConfig(this, {
|
||||
variableNames: [VAR_DATASOURCE_EXPR],
|
||||
onReferencedVariableValueChanged: this.onReferencedVariableValueChanged.bind(this),
|
||||
});
|
||||
|
||||
constructor(state: Partial<MetricOverviewSceneState>) {
|
||||
super({
|
||||
...state,
|
||||
});
|
||||
|
||||
this.addActivationHandler(this._onActivate.bind(this));
|
||||
}
|
||||
|
||||
private getVariable(): QueryVariable {
|
||||
const variable = sceneGraph.lookupVariable(VAR_GROUP_BY, this)!;
|
||||
if (!(variable instanceof QueryVariable)) {
|
||||
throw new Error('Group by variable not found');
|
||||
}
|
||||
|
||||
return variable;
|
||||
}
|
||||
|
||||
private _onActivate() {
|
||||
this.updateMetadata();
|
||||
}
|
||||
|
||||
private onReferencedVariableValueChanged() {
|
||||
this.updateMetadata();
|
||||
this.updateOtelGroupLeft();
|
||||
}
|
||||
|
||||
private async updateMetadata() {
|
||||
this.setState({ metadataLoading: true, metadata: undefined });
|
||||
const metricScene = getMetricSceneFor(this);
|
||||
const metric = metricScene.state.metric;
|
||||
|
||||
const trail = getTrailFor(this);
|
||||
const metadata = await trail.getMetricMetadata(metric);
|
||||
this.setState({ metadata, metadataLoading: false });
|
||||
}
|
||||
|
||||
private async updateOtelGroupLeft() {
|
||||
const trail = getTrailFor(this);
|
||||
|
||||
if (trail.state.useOtelExperience) {
|
||||
await updateOtelJoinWithGroupLeft(trail, trail.state.metric ?? '');
|
||||
}
|
||||
}
|
||||
|
||||
public static Component = ({ model }: SceneComponentProps<MetricOverviewScene>) => {
|
||||
const { metadata, metadataLoading } = model.useState();
|
||||
const variable = model.getVariable();
|
||||
const { loading: labelsLoading, options: labelOptions } = variable.useState();
|
||||
|
||||
let allLabelOptions = labelOptions;
|
||||
|
||||
const trail = getTrailFor(model);
|
||||
const { useOtelExperience } = trail.useState();
|
||||
|
||||
if (useOtelExperience) {
|
||||
// when the group left variable is changed we should get all the resource attributes + labels
|
||||
const resourceAttributes = sceneGraph.lookupVariable(VAR_OTEL_GROUP_LEFT, trail)?.getValue();
|
||||
if (typeof resourceAttributes === 'string') {
|
||||
const attributeArray: VariableValueOption[] = resourceAttributes.split(',').map((el) => {
|
||||
let label = el;
|
||||
if (!isValidLegacyName(el)) {
|
||||
// remove '' from label
|
||||
label = el.slice(1, -1);
|
||||
}
|
||||
return { label, value: el };
|
||||
});
|
||||
allLabelOptions = attributeArray.concat(allLabelOptions);
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (useOtelExperience) {
|
||||
// this will update the group left variable
|
||||
model.updateOtelGroupLeft();
|
||||
}
|
||||
}, [model, useOtelExperience]);
|
||||
|
||||
// Get unit name from the metric name
|
||||
const metricScene = getMetricSceneFor(model);
|
||||
const metric = metricScene.state.metric;
|
||||
let unit = getUnitFromMetric(metric) ?? 'Unknown';
|
||||
return (
|
||||
<StatusWrapper isLoading={labelsLoading || metadataLoading}>
|
||||
<Stack gap={6}>
|
||||
<>
|
||||
<Stack direction="column" gap={0.5}>
|
||||
<Text weight={'medium'}>
|
||||
<Trans i18nKey="trails.metric-overview.description-label">Description</Trans>
|
||||
</Text>
|
||||
<div style={{ maxWidth: 360 }}>
|
||||
{metadata?.help ? (
|
||||
<div>{metadata?.help}</div>
|
||||
) : (
|
||||
<i>
|
||||
<Trans i18nKey="trails.metric-overview.no-description">No description available</Trans>
|
||||
</i>
|
||||
)}
|
||||
</div>
|
||||
</Stack>
|
||||
<Stack direction="column" gap={0.5}>
|
||||
<Text weight={'medium'}>
|
||||
<Trans i18nKey="trails.metric-overview.type-label">Type</Trans>
|
||||
</Text>
|
||||
{metadata?.type ? (
|
||||
<div>{metadata?.type}</div>
|
||||
) : (
|
||||
<i>
|
||||
<Trans i18nKey="trails.metric-overview.unknown-type">Unknown</Trans>
|
||||
</i>
|
||||
)}
|
||||
</Stack>
|
||||
<Stack direction="column" gap={0.5}>
|
||||
<Text weight={'medium'}>
|
||||
<Trans i18nKey="trails.metric-overview.unit-label">Unit</Trans>
|
||||
</Text>
|
||||
{metadata?.unit ? <div>{metadata?.unit}</div> : <i>{unit}</i>}
|
||||
</Stack>
|
||||
<Stack direction="column" gap={0.5}>
|
||||
<Text weight={'medium'}>
|
||||
{useOtelExperience ? (
|
||||
<Trans i18nKey="trails.metric-overview.metric-attributes">Attributes</Trans>
|
||||
) : (
|
||||
<Trans i18nKey="trails.metric-overview.labels">Labels</Trans>
|
||||
)}
|
||||
</Text>
|
||||
{allLabelOptions.length === 0 && 'Unable to fetch labels.'}
|
||||
{allLabelOptions.map((l) => (
|
||||
<TextLink
|
||||
key={l.label}
|
||||
href={`#View breakdown for ${l.label}`}
|
||||
title={`View breakdown for ${l.label}`}
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
sceneGraph.getAncestor(model, MetricScene).setActionView('breakdown');
|
||||
const groupByVar = sceneGraph.lookupVariable(VAR_GROUP_BY, model);
|
||||
if (groupByVar instanceof QueryVariable && l.label != null) {
|
||||
reportExploreMetrics('label_selected', { label: l.label, cause: 'overview_link' });
|
||||
groupByVar.setState({ value: l.value });
|
||||
}
|
||||
return false;
|
||||
}}
|
||||
>
|
||||
{l.label!}
|
||||
</TextLink>
|
||||
))}
|
||||
</Stack>
|
||||
</>
|
||||
</Stack>
|
||||
</StatusWrapper>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export function buildMetricOverviewScene() {
|
||||
return new MetricOverviewScene({});
|
||||
}
|
||||
@@ -16,7 +16,6 @@ import { Box, Icon, LinkButton, Stack, Tab, TabsBar, ToolbarButton, Tooltip, use
|
||||
|
||||
import { getExploreUrl } from '../../core/utils/explore';
|
||||
|
||||
import { buildMetricOverviewScene } from './ActionTabs/MetricOverviewScene';
|
||||
import { buildRelatedMetricsScene } from './ActionTabs/RelatedMetricsScene';
|
||||
import { buildLabelBreakdownActionScene } from './Breakdown/LabelBreakdownScene';
|
||||
import { MAIN_PANEL_MAX_HEIGHT, MAIN_PANEL_MIN_HEIGHT, MetricGraphScene } from './MetricGraphScene';
|
||||
@@ -39,7 +38,7 @@ import {
|
||||
} from './shared';
|
||||
import { getDataSource, getTrailFor, getUrlForTrail } from './utils';
|
||||
|
||||
const relatedLogsFeatureEnabled = config.featureToggles.exploreMetricsRelatedLogs;
|
||||
const { exploreMetricsRelatedLogs } = config.featureToggles;
|
||||
|
||||
export interface MetricSceneState extends SceneObjectState {
|
||||
body: MetricGraphScene;
|
||||
@@ -69,7 +68,7 @@ export class MetricScene extends SceneObjectBase<MetricSceneState> {
|
||||
|
||||
private _onActivate() {
|
||||
if (this.state.actionView === undefined) {
|
||||
this.setActionView('overview');
|
||||
this.setActionView('breakdown');
|
||||
}
|
||||
|
||||
if (config.featureToggles.enableScopesInMetricsExplore) {
|
||||
@@ -124,7 +123,6 @@ export class MetricScene extends SceneObjectBase<MetricSceneState> {
|
||||
}
|
||||
|
||||
const actionViewsDefinitions: ActionViewDefinition[] = [
|
||||
{ displayName: 'Overview', value: 'overview', getScene: buildMetricOverviewScene },
|
||||
{ displayName: 'Breakdown', value: 'breakdown', getScene: buildLabelBreakdownActionScene },
|
||||
{
|
||||
displayName: 'Related metrics',
|
||||
@@ -134,7 +132,7 @@ const actionViewsDefinitions: ActionViewDefinition[] = [
|
||||
},
|
||||
];
|
||||
|
||||
if (relatedLogsFeatureEnabled) {
|
||||
if (exploreMetricsRelatedLogs) {
|
||||
actionViewsDefinitions.push({
|
||||
displayName: 'Related logs',
|
||||
value: 'related_logs',
|
||||
@@ -197,7 +195,7 @@ export class MetricActionBar extends SceneObjectBase<MetricActionBarState> {
|
||||
icon="compass"
|
||||
tooltip="Open in explore"
|
||||
onClick={model.openExploreLink}
|
||||
></ToolbarButton>
|
||||
/>
|
||||
<ShareTrailButton trail={trail} />
|
||||
<ToolbarButton
|
||||
variant={'canvas'}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { SceneObjectState, SceneObjectBase, SceneComponentProps, VizPanel, SceneQueryRunner } from '@grafana/scenes';
|
||||
|
||||
import { AddToExplorationButton } from '../../MetricSelect/AddToExplorationsButton';
|
||||
import { getMetricDescription } from '../../helpers/MetricDatasourceHelper';
|
||||
import { MDP_METRIC_OVERVIEW, trailDS } from '../../shared';
|
||||
import { getMetricSceneFor } from '../../utils';
|
||||
import { getMetricSceneFor, getTrailFor } from '../../utils';
|
||||
import { AutoQueryDef } from '../types';
|
||||
|
||||
import { AutoVizPanelQuerySelector } from './AutoVizPanelQuerySelector';
|
||||
@@ -23,7 +24,12 @@ export class AutoVizPanel extends SceneObjectBase<AutoVizPanelState> {
|
||||
if (!this.state.panel) {
|
||||
const { autoQuery, metric } = getMetricSceneFor(this).state;
|
||||
|
||||
this.setState({ panel: this.getVizPanelFor(autoQuery.main, metric), metric });
|
||||
this.getVizPanelFor(autoQuery.main, metric).then((panel) =>
|
||||
this.setState({
|
||||
panel,
|
||||
metric,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,11 +38,15 @@ export class AutoVizPanel extends SceneObjectBase<AutoVizPanelState> {
|
||||
|
||||
const def = metricScene.state.autoQuery.variants.find((q) => q.variant === variant)!;
|
||||
|
||||
this.setState({ panel: this.getVizPanelFor(def) });
|
||||
this.getVizPanelFor(def).then((panel) => this.setState({ panel }));
|
||||
metricScene.setState({ queryDef: def });
|
||||
};
|
||||
|
||||
private getVizPanelFor(def: AutoQueryDef, metric?: string) {
|
||||
private async getVizPanelFor(def: AutoQueryDef, metric?: string) {
|
||||
const trail = getTrailFor(this);
|
||||
const metadata = await trail.getMetricMetadata(metric);
|
||||
const description = getMetricDescription(metadata);
|
||||
|
||||
return def
|
||||
.vizBuilder()
|
||||
.setData(
|
||||
@@ -46,6 +56,7 @@ export class AutoVizPanel extends SceneObjectBase<AutoVizPanelState> {
|
||||
queries: def.queries,
|
||||
})
|
||||
)
|
||||
.setDescription(description)
|
||||
.setHeaderActions([
|
||||
new AutoVizPanelQuerySelector({ queryDef: def, onChangeQuery: this.onChangeQuery }),
|
||||
new AddToExplorationButton({ labelName: metric ?? this.state.metric }),
|
||||
|
||||
@@ -13,8 +13,6 @@ type Interactions = {
|
||||
cause: (
|
||||
// By clicking the "select" button on that label's breakdown panel
|
||||
| 'breakdown_panel'
|
||||
// By clicking the label link on the overview
|
||||
| 'overview_link'
|
||||
// By clicking on the label selector at the top of the breakdown
|
||||
| 'selector'
|
||||
);
|
||||
|
||||
@@ -218,7 +218,7 @@ export function limitOtelMatchTerms(
|
||||
|
||||
/**
|
||||
* This updates the OTel join query variable that is interpolated into all queries.
|
||||
* When a user is in the breakdown or overview tab, they may want to breakdown a metric by a resource attribute.
|
||||
* When a user is in the breakdown tab, they may want to breakdown a metric by a resource attribute.
|
||||
* The only way to do this is by enriching the metric with the target_info resource.
|
||||
* This is done by joining on a unique identifier for the resource, job and instance.
|
||||
* The we can get the resource attributes for the metric, enrich the metric with the join query and
|
||||
|
||||
@@ -2,7 +2,7 @@ import { BusEventBase, BusEventWithPayload } from '@grafana/data';
|
||||
import { ConstantVariable, SceneObject } from '@grafana/scenes';
|
||||
import { VariableHide } from '@grafana/schema';
|
||||
|
||||
export type ActionViewType = 'overview' | 'breakdown' | 'related_logs' | 'related';
|
||||
export type ActionViewType = 'breakdown' | 'related_logs' | 'related';
|
||||
|
||||
export interface ActionViewDefinition {
|
||||
displayName: string;
|
||||
|
||||
@@ -3344,15 +3344,6 @@
|
||||
"start-your-metrics-exploration": "Start your metrics exploration!",
|
||||
"subtitle": "Explore your Prometheus-compatible metrics without writing a query."
|
||||
},
|
||||
"metric-overview": {
|
||||
"description-label": "Description",
|
||||
"labels": "Labels",
|
||||
"metric-attributes": "Attributes",
|
||||
"no-description": "No description available",
|
||||
"type-label": "Type",
|
||||
"unit-label": "Unit",
|
||||
"unknown-type": "Unknown"
|
||||
},
|
||||
"metric-select": {
|
||||
"filter-by": "Filter by",
|
||||
"native-histogram": "Native Histogram",
|
||||
|
||||
@@ -3344,15 +3344,6 @@
|
||||
"start-your-metrics-exploration": "Ŝŧäřŧ yőūř męŧřįčş ęχpľőřäŧįőʼn!",
|
||||
"subtitle": "Ēχpľőřę yőūř Přőmęŧĥęūş-čőmpäŧįþľę męŧřįčş ŵįŧĥőūŧ ŵřįŧįʼnģ ä qūęřy."
|
||||
},
|
||||
"metric-overview": {
|
||||
"description-label": "Đęşčřįpŧįőʼn",
|
||||
"labels": "Ŀäþęľş",
|
||||
"metric-attributes": "Åŧŧřįþūŧęş",
|
||||
"no-description": "Ńő đęşčřįpŧįőʼn äväįľäþľę",
|
||||
"type-label": "Ŧypę",
|
||||
"unit-label": "Ůʼnįŧ",
|
||||
"unknown-type": "Ůʼnĸʼnőŵʼn"
|
||||
},
|
||||
"metric-select": {
|
||||
"filter-by": "Fįľŧęř þy",
|
||||
"native-histogram": "Ńäŧįvę Ħįşŧőģřäm",
|
||||
|
||||
Reference in New Issue
Block a user