diff --git a/src/components/Explore/ByFrameRepeater.tsx b/src/components/Explore/ByFrameRepeater.tsx index 73b322c8..02fdd4b5 100644 --- a/src/components/Explore/ByFrameRepeater.tsx +++ b/src/components/Explore/ByFrameRepeater.tsx @@ -98,7 +98,7 @@ export class ByFrameRepeater extends SceneObjectBase { let frames = data.series; if (this.state.groupBy) { - frames = groupSeriesBy(data, this.getGroupByVariable().state.query); + frames = groupSeriesBy(data, this.getGroupByVariable().getValueText()); } for (let frameIndex = 0; frameIndex < frames.length; frameIndex++) { diff --git a/src/components/Explore/TracesByService/Tabs/AttributesBreakdown.tsx b/src/components/Explore/TracesByService/Tabs/AttributesBreakdown.tsx index 01a6b3c1..b1eeb17f 100644 --- a/src/components/Explore/TracesByService/Tabs/AttributesBreakdown.tsx +++ b/src/components/Explore/TracesByService/Tabs/AttributesBreakdown.tsx @@ -1,43 +1,34 @@ import { css } from '@emotion/css'; import React from 'react'; -import { DataFrame, GrafanaTheme2, PanelData } from '@grafana/data'; +import { DataFrame, GrafanaTheme2 } from '@grafana/data'; import { CustomVariable, - PanelBuilders, - PanelOptionsBuilders, SceneComponentProps, - SceneCSSGridItem, - SceneCSSGridLayout, - SceneDataNode, SceneFlexItem, - SceneFlexItemLike, - SceneFlexLayout, sceneGraph, SceneObject, SceneObjectBase, SceneObjectState, - SceneQueryRunner, SceneVariableSet, VariableDependencyConfig, } from '@grafana/scenes'; -import { Button, Field, TooltipDisplayMode, useStyles2 } from '@grafana/ui'; +import { Button, Field, useStyles2 } from '@grafana/ui'; import { BreakdownLabelSelector } from '../../BreakdownLabelSelector'; -import { explorationDS, VAR_ATTRIBUTE_GROUP_BY, VAR_FILTERS, VAR_FILTERS_EXPR } from '../../../../utils/shared'; +import { VAR_ATTRIBUTE_GROUP_BY, VAR_FILTERS } from '../../../../utils/shared'; -import { ByFrameRepeater } from '../../ByFrameRepeater'; import { LayoutSwitcher } from '../../LayoutSwitcher'; import { TracesByServiceScene } from '../TracesByServiceScene'; -import { getColorByIndex, getLabelValue } from '../../../../utils/utils'; import { AddToFiltersGraphAction } from '../../AddToFiltersGraphAction'; import { VARIABLE_ALL_VALUE } from '../../../../constants'; +import { buildAllLayout } from '../../layouts/allAttributes'; +import { buildNormalLayout } from '../../layouts/attributeBreakdown'; export interface AttributesBreakdownSceneState extends SceneObjectState { body?: SceneObject; } -const MAX_PANELS_IN_ALL_ATTRIBUTES_BREAKDOWN = 100; const ignoredAttributes = ['duration', 'traceDuration']; export class AttributesBreakdown extends SceneObjectBase { @@ -97,8 +88,11 @@ export class AttributesBreakdown extends SceneObjectBase new SelectAttributeAction({ attribute })) + : buildNormalLayout( + variable, + (frame: DataFrame) => new AddToFiltersGraphAction({ frame, variableName: VAR_FILTERS }) + ), }); } @@ -182,147 +176,6 @@ function getStyles(theme: GrafanaTheme2) { }; } -function getExpr(attr: string) { - return `{${VAR_FILTERS_EXPR}} | rate() by(${attr})`; -} - -function buildQuery(tagKey: string) { - return { - refId: 'A', - query: getExpr(tagKey), - queryType: 'traceql', - tableType: 'spans', - limit: 100, - spss: 10, - filters: [], - }; -} - -const GRID_TEMPLATE_COLUMNS = 'repeat(auto-fit, minmax(400px, 1fr))'; - -function buildNormalLayout(variable: CustomVariable) { - const query = buildQuery(variable.getValueText()); - - return new LayoutSwitcher({ - $data: new SceneQueryRunner({ - datasource: explorationDS, - maxDataPoints: 300, - queries: [query], - }), - options: [ - { value: 'single', label: 'Single' }, - { value: 'grid', label: 'Grid' }, - { value: 'rows', label: 'Rows' }, - ], - active: 'grid', - layouts: [ - new SceneFlexLayout({ - direction: 'column', - children: [ - new SceneFlexItem({ - minHeight: 300, - body: PanelBuilders.timeseries().build(), - }), - ], - }), - new ByFrameRepeater({ - body: new SceneCSSGridLayout({ - templateColumns: GRID_TEMPLATE_COLUMNS, - autoRows: '200px', - children: [], - }), - getLayoutChild: getLayoutChild(getLabelValue), - }), - new ByFrameRepeater({ - body: new SceneCSSGridLayout({ - templateColumns: '1fr', - autoRows: '200px', - children: [], - }), - getLayoutChild: getLayoutChild(getLabelValue), - }), - ], - }); -} - -function buildAllLayout(attributes?: string[]) { - const children: SceneFlexItemLike[] = []; - - if (!attributes) { - return new SceneFlexLayout({ children }); - } - - for (const attribute of attributes) { - if (children.length === MAX_PANELS_IN_ALL_ATTRIBUTES_BREAKDOWN) { - break; - } - - const vizPanel = PanelBuilders.timeseries() - .setTitle(attribute) - .setData( - new SceneQueryRunner({ - maxDataPoints: 250, - datasource: explorationDS, - queries: [buildQuery(attribute)], - }) - ) - .setHeaderActions(new SelectAttributeAction({ attribute: attribute })) - .build(); - - vizPanel.addActivationHandler(() => { - vizPanel.onOptionsChange( - PanelOptionsBuilders.timeseries() - .setOption('tooltip', { mode: TooltipDisplayMode.Multi }) - .setOption('legend', { showLegend: false }) - .build() - ); - }); - - children.push( - new SceneCSSGridItem({ - body: vizPanel, - }) - ); - } - return new LayoutSwitcher({ - active: 'grid', - options: [ - { value: 'grid', label: 'Grid' }, - { value: 'rows', label: 'Rows' }, - ], - layouts: [ - new SceneCSSGridLayout({ - templateColumns: GRID_TEMPLATE_COLUMNS, - autoRows: '200px', - children: children, - isLazy: true, - }), - new SceneCSSGridLayout({ - templateColumns: '1fr', - autoRows: '200px', - // Clone children since a scene object can only have one parent at a time - children: children.map((c) => c.clone()), - isLazy: true, - }), - ], - }); -} - -export function getLayoutChild(getTitle: (df: DataFrame) => string) { - return (data: PanelData, frame: DataFrame, frameIndex: number) => { - const panel = PanelBuilders.timeseries() // - .setOption('legend', { showLegend: true }) - .setCustomFieldConfig('fillOpacity', 9) - .setTitle(getTitle(frame)) - .setData(new SceneDataNode({ data: { ...data, series: [frame] } })) - .setColor({ mode: 'fixed', fixedColor: getColorByIndex(frameIndex) }) - .setHeaderActions(new AddToFiltersGraphAction({ frame, variableName: VAR_FILTERS })); - return new SceneCSSGridItem({ - body: panel.build(), - }); - }; -} - interface SelectAttributeActionState extends SceneObjectState { attribute: string; } diff --git a/src/components/Explore/layouts/allAttributes.ts b/src/components/Explore/layouts/allAttributes.ts new file mode 100644 index 00000000..2593e6d2 --- /dev/null +++ b/src/components/Explore/layouts/allAttributes.ts @@ -0,0 +1,83 @@ +import { + PanelBuilders, + SceneCSSGridItem, + SceneCSSGridLayout, + SceneFlexItemLike, + SceneQueryRunner, + VizPanelState, +} from '@grafana/scenes'; +import { explorationDS, VAR_FILTERS_EXPR } from '../../../utils/shared'; +import { TooltipDisplayMode } from '@grafana/ui'; +import { LayoutSwitcher } from '../LayoutSwitcher'; + +const MAX_PANELS_IN_ALL_ATTRIBUTES_BREAKDOWN = 100; +const GRID_TEMPLATE_COLUMNS = 'repeat(auto-fit, minmax(400px, 1fr))'; + +export function buildAllLayout(attributes: string[], actionsFn: (attribute: string) => VizPanelState['headerActions']) { + const children: SceneFlexItemLike[] = []; + + for (const attribute of attributes) { + if (children.length === MAX_PANELS_IN_ALL_ATTRIBUTES_BREAKDOWN) { + break; + } + + const vizPanel = PanelBuilders.timeseries() + .setTitle(attribute) + .setData( + new SceneQueryRunner({ + maxDataPoints: 250, + datasource: explorationDS, + queries: [buildQuery(attribute)], + }) + ) + .setCustomFieldConfig('axisLabel', 'Errors') + .setHeaderActions(actionsFn(attribute)) + .setOption('tooltip', { mode: TooltipDisplayMode.Multi }) + .setOption('legend', { showLegend: false }) + .build(); + + children.push( + new SceneCSSGridItem({ + body: vizPanel, + }) + ); + } + return new LayoutSwitcher({ + active: 'grid', + options: [ + { value: 'grid', label: 'Grid' }, + { value: 'rows', label: 'Rows' }, + ], + layouts: [ + new SceneCSSGridLayout({ + templateColumns: GRID_TEMPLATE_COLUMNS, + autoRows: '200px', + children: children, + isLazy: true, + }), + new SceneCSSGridLayout({ + templateColumns: '1fr', + autoRows: '200px', + // Clone children since a scene object can only have one parent at a time + children: children.map((c) => c.clone()), + isLazy: true, + }), + ], + }); +} + +function getExpr(attr: string) { + return `{${VAR_FILTERS_EXPR} && status = error} | rate() by(${attr})`; +} + +function buildQuery(tagKey: string) { + return { + refId: 'A', + query: getExpr(tagKey), + queryType: 'traceql', + tableType: 'spans', + limit: 100, + spss: 10, + filters: [], + }; +} diff --git a/src/components/Explore/layouts/attributeBreakdown.ts b/src/components/Explore/layouts/attributeBreakdown.ts new file mode 100644 index 00000000..31c35f90 --- /dev/null +++ b/src/components/Explore/layouts/attributeBreakdown.ts @@ -0,0 +1,158 @@ +import { + CustomVariable, + PanelBuilders, + SceneCSSGridItem, + SceneCSSGridLayout, + SceneDataNode, + SceneDataTransformer, + SceneFlexItem, + SceneFlexLayout, + SceneQueryRunner, + VizPanelState, +} from '@grafana/scenes'; +import { LayoutSwitcher } from '../LayoutSwitcher'; +import { explorationDS, VAR_FILTERS_EXPR } from '../../../utils/shared'; +import { ByFrameRepeater } from '../ByFrameRepeater'; +import { getLabelValue } from '../../../utils/utils'; +import { GRID_TEMPLATE_COLUMNS } from '../../../pages/Explore/SelectStartingPointScene'; +import { map, Observable } from 'rxjs'; +import { DataFrame, PanelData, reduceField, ReducerID } from '@grafana/data'; +import { AxisPlacement, DrawStyle, StackingMode } from '@grafana/ui'; + +export function buildNormalLayout( + variable: CustomVariable, + actionsFn: (df: DataFrame) => VizPanelState['headerActions'] +) { + const query = buildQuery(variable.getValueText()); + + return new LayoutSwitcher({ + $data: new SceneDataTransformer({ + $data: new SceneQueryRunner({ + datasource: explorationDS, + queries: [query], + }), + transformations: [ + () => (source: Observable) => { + return source.pipe( + map((data: DataFrame[]) => { + data.forEach((a) => reduceField({ field: a.fields[1], reducers: [ReducerID.max] })); + return data.sort((a, b) => { + return (b.fields[1].state?.calcs?.max || 0) - (a.fields[1].state?.calcs?.max || 0); + }); + }) + ); + }, + ], + }), + options: [ + { value: 'single', label: 'Single' }, + { value: 'grid', label: 'Grid' }, + { value: 'rows', label: 'Rows' }, + ], + active: 'grid', + layouts: [ + new SceneFlexLayout({ + direction: 'column', + children: [ + new SceneFlexItem({ + minHeight: 300, + body: PanelBuilders.timeseries().build(), + }), + ], + }), + new ByFrameRepeater({ + body: new SceneCSSGridLayout({ + templateColumns: GRID_TEMPLATE_COLUMNS, + autoRows: '200px', + children: [], + }), + groupBy: true, + getLayoutChild: getLayoutChild(getLabelValue, variable, actionsFn), + }), + new ByFrameRepeater({ + body: new SceneCSSGridLayout({ + templateColumns: '1fr', + autoRows: '200px', + children: [], + }), + groupBy: true, + getLayoutChild: getLayoutChild(getLabelValue, variable, actionsFn), + }), + ], + }); +} + +export function getLayoutChild( + getTitle: (df: DataFrame, labelName: string) => string, + variable: CustomVariable, + actionsFn: (df: DataFrame) => VizPanelState['headerActions'] +) { + return (data: PanelData, frame: DataFrame) => { + const panel = PanelBuilders.timeseries() + .setTitle(getTitle(frame, variable.getValueText())) + .setData( + new SceneDataNode({ + data: { + ...data, + series: [ + { + ...frame, + fields: frame.fields + .sort((a, b) => a.labels?.status?.localeCompare(b.labels?.status || '') || 0) + .reverse(), + }, + ], + }, + }) + ) + .setOption('legend', { showLegend: false }) + .setCustomFieldConfig('drawStyle', DrawStyle.Bars) + .setCustomFieldConfig('stacking', { mode: StackingMode.Normal }) + .setCustomFieldConfig('fillOpacity', 100) + .setCustomFieldConfig('lineWidth', 0) + .setCustomFieldConfig('pointSize', 0) + .setCustomFieldConfig('axisLabel', 'Rate') + .setOverrides((overrides) => { + overrides + .matchFieldsWithNameByRegex('.*status="error".*') + .overrideColor({ + mode: 'fixed', + fixedColor: 'semi-dark-red', + }) + .overrideCustomFieldConfig('axisPlacement', AxisPlacement.Right) + .overrideCustomFieldConfig('axisLabel', 'Errors'); + overrides.matchFieldsWithNameByRegex('.*status="unset".*').overrideColor({ + mode: 'fixed', + fixedColor: 'green', + }); + overrides.matchFieldsWithNameByRegex('.*status="ok".*').overrideColor({ + mode: 'fixed', + fixedColor: 'dark-green', + }); + }); + + const actions = actionsFn(frame); + if (actions) { + panel.setHeaderActions(actions); + } + return new SceneCSSGridItem({ + body: panel.build(), + }); + }; +} + +function getExpr(attr: string) { + return `{${VAR_FILTERS_EXPR}} | rate() by(${attr}, status)`; +} + +function buildQuery(tagKey: string) { + return { + refId: 'A', + query: getExpr(tagKey), + queryType: 'traceql', + tableType: 'spans', + limit: 100, + spss: 10, + filters: [], + }; +} diff --git a/src/pages/Explore/SelectAttributeWithValueAction.tsx b/src/pages/Explore/InvestigateAttributeWithValueAction.tsx similarity index 73% rename from src/pages/Explore/SelectAttributeWithValueAction.tsx rename to src/pages/Explore/InvestigateAttributeWithValueAction.tsx index 9447386a..43a62337 100644 --- a/src/pages/Explore/SelectAttributeWithValueAction.tsx +++ b/src/pages/Explore/InvestigateAttributeWithValueAction.tsx @@ -13,11 +13,11 @@ import { Button } from '@grafana/ui'; import { StartingPointSelectedEvent } from '../../utils/shared'; import { VAR_GROUPBY } from './SelectStartingPointScene'; -export interface SelectAttributeWithValueActionState extends SceneObjectState { +export interface InvestigateAttributeWithValueActionState extends SceneObjectState { value: string; } -export class SelectAttributeWithValueAction extends SceneObjectBase { +export class InvestigateAttributeWithValueAction extends SceneObjectBase { public onClick = () => { const variable = sceneGraph.lookupVariable('filters', this); if (!(variable instanceof AdHocFiltersVariable)) { @@ -44,9 +44,9 @@ export class SelectAttributeWithValueAction extends SceneObjectBase) => { + public static Component = ({ model }: SceneComponentProps) => { return ( - ); diff --git a/src/pages/Explore/SelectStartingPointScene.tsx b/src/pages/Explore/SelectStartingPointScene.tsx index 2e005f4e..e0f11bc4 100644 --- a/src/pages/Explore/SelectStartingPointScene.tsx +++ b/src/pages/Explore/SelectStartingPointScene.tsx @@ -1,34 +1,31 @@ import { css } from '@emotion/css'; import React from 'react'; -import { DataFrame, GrafanaTheme2, MetricFindValue, reduceField, ReducerID } from '@grafana/data'; +import { DataFrame, GrafanaTheme2, MetricFindValue } from '@grafana/data'; import { CustomVariable, - PanelBuilders, SceneComponentProps, - SceneCSSGridItem, - SceneCSSGridLayout, - SceneDataNode, - SceneDataTransformer, sceneGraph, SceneObjectBase, SceneObjectState, - SceneQueryRunner, SceneVariableSet, VariableDependencyConfig, } from '@grafana/scenes'; -import { DrawStyle, Select, StackingMode, Tab, TabsBar, useStyles2 } from '@grafana/ui'; +import { Button, Select, Tab, TabsBar, useStyles2 } from '@grafana/ui'; -import { SelectAttributeWithValueAction } from './SelectAttributeWithValueAction'; -import { explorationDS, VAR_DATASOURCE_EXPR, VAR_FILTERS, VAR_FILTERS_EXPR } from '../../utils/shared'; +import { VAR_DATASOURCE_EXPR, VAR_FILTERS } from '../../utils/shared'; import { getExplorationFor, getLabelValue } from '../../utils/utils'; -import { ByFrameRepeater } from '../../components/Explore/ByFrameRepeater'; -import { map, Observable } from 'rxjs'; import { getDataSourceSrv } from '@grafana/runtime'; import { primarySignalOptions } from './primary-signals'; +import { VARIABLE_ALL_VALUE } from '../../constants'; +import { buildNormalLayout } from '../../components/Explore/layouts/attributeBreakdown'; +import { buildAllLayout } from '../../components/Explore/layouts/allAttributes'; +import { LayoutSwitcher } from '../../components/Explore/LayoutSwitcher'; +import { AddToFiltersGraphAction } from '../../components/Explore/AddToFiltersGraphAction'; +import { InvestigateAttributeWithValueAction } from './InvestigateAttributeWithValueAction'; export interface TraceSelectSceneState extends SceneObjectState { - body: SceneCSSGridLayout; + body?: LayoutSwitcher; showHeading?: boolean; searchQuery?: string; showPreviews?: boolean; @@ -39,8 +36,6 @@ export interface TraceSelectSceneState extends SceneObjectState { export const GRID_TEMPLATE_COLUMNS = 'repeat(auto-fit, minmax(400px, 1fr))'; export const VAR_GROUPBY = 'groupBy'; -const VAR_GROUPBY_EXPR = '${groupBy}'; -const defaultGroupBy = 'resource.service.name'; export class SelectStartingPointScene extends SceneObjectBase { protected _variableDependency = new VariableDependencyConfig(this, { @@ -49,7 +44,6 @@ export class SelectStartingPointScene extends SceneObjectBase) { super({ - body: state.body ?? new SceneCSSGridLayout({ children: [] }), $variables: state.$variables ?? getVariableSet(), showPreviews: true, ...state, @@ -61,8 +55,18 @@ export class SelectStartingPointScene extends SceneObjectBase { + if (newState.attributes !== prevState.attributes) { + this.buildBody(); + } + }); + + groupByVariable.subscribeToState((newState, prevState) => { + if (newState.value !== prevState.value) { + this.buildBody(); + } }); } @@ -83,81 +87,18 @@ export class SelectStartingPointScene extends SceneObjectBase (source: Observable) => { - return source.pipe( - map((data: DataFrame[]) => { - data.forEach((a) => reduceField({ field: a.fields[1], reducers: [ReducerID.max] })); - return data.sort((a, b) => { - return (b.fields[1].state?.calcs?.max || 0) - (a.fields[1].state?.calcs?.max || 0); - }); - }) - ); - }, - ], - }), - body: new SceneCSSGridLayout({ - templateColumns: GRID_TEMPLATE_COLUMNS, - autoRows: '200px', - children: [], - }), - groupBy: true, - getLayoutChild: (data, frame, frameIndex) => { - return new SceneCSSGridItem({ - body: PanelBuilders.timeseries() - .setTitle(getLabelValue(frame, variable.state.query)) - .setData( - new SceneDataNode({ - data: { - ...data, - series: [ - { - ...frame, - fields: frame.fields - .sort((a, b) => a.labels?.status?.localeCompare(b.labels?.status || '') || 0) - .reverse(), - }, - ], - }, - }) - ) - .setOption('legend', { showLegend: false }) - .setCustomFieldConfig('drawStyle', DrawStyle.Bars) - .setCustomFieldConfig('stacking', { mode: StackingMode.Normal }) - .setCustomFieldConfig('fillOpacity', 100) - .setCustomFieldConfig('lineWidth', 0) - .setCustomFieldConfig('pointSize', 0) - .setOverrides((overrides) => { - overrides.matchFieldsWithNameByRegex('.*status="error".*').overrideColor({ - mode: 'fixed', - fixedColor: 'semi-dark-red', - }); - overrides.matchFieldsWithNameByRegex('.*status="unset".*').overrideColor({ - mode: 'fixed', - fixedColor: 'green', - }); - overrides.matchFieldsWithNameByRegex('.*status="ok".*').overrideColor({ - mode: 'fixed', - fixedColor: 'dark-green', - }); - }) - .setHeaderActions( - new SelectAttributeWithValueAction({ value: getLabelValue(frame, variable.state.query) }) - ) - .setDisplayMode('transparent') - .build(), - }); - }, - }), - ], + this.setState({ + body: + variable.hasAllValue() || variable.getValue() === VARIABLE_ALL_VALUE + ? buildAllLayout( + this.state.attributes ?? [], + (attribute) => new SelectAttributeAction({ attribute: attribute }) + ) + : buildNormalLayout( + variable, + (frame: DataFrame) => + new InvestigateAttributeWithValueAction({ value: getLabelValue(frame, variable.getValueText()) }) + ), }); } @@ -175,7 +116,6 @@ export class SelectStartingPointScene extends SceneObjectBase -
- -
+ {body && ( +
+ +
+ )} ); }; } function getAttributesAsOptions(attributes: string[]) { - return attributes.map((attribute) => ({ label: attribute.replace('resource.', ''), value: attribute })); + return [ + { label: 'All errors', value: VARIABLE_ALL_VALUE }, + ...attributes.map((attribute) => ({ label: attribute.replace('resource.', ''), value: attribute })), + ]; } function getVariableSet() { @@ -229,21 +174,14 @@ function getVariableSet() { variables: [ new CustomVariable({ name: VAR_GROUPBY, - query: defaultGroupBy, + defaultToAll: true, + includeAll: true, + value: VARIABLE_ALL_VALUE, }), ], }); } -function buildQuery() { - return { - refId: 'A', - query: `{${VAR_FILTERS_EXPR}} | rate() by (${VAR_GROUPBY_EXPR}, status)`, - queryType: 'traceql', - filters: [], - }; -} - function getStyles(theme: GrafanaTheme2) { return { container: css({ @@ -277,3 +215,21 @@ function getStyles(theme: GrafanaTheme2) { }), }; } + +interface SelectAttributeActionState extends SceneObjectState { + attribute: string; +} +export class SelectAttributeAction extends SceneObjectBase { + public onClick = () => { + const startingPointScene = sceneGraph.getAncestor(this, SelectStartingPointScene); + startingPointScene.onChangeGroupBy(this.state.attribute); + }; + + public static Component = ({ model }: SceneComponentProps) => { + return ( + + ); + }; +} diff --git a/src/pages/Explore/TraceExploration.tsx b/src/pages/Explore/TraceExploration.tsx index 912bfcbf..6d32f91f 100644 --- a/src/pages/Explore/TraceExploration.tsx +++ b/src/pages/Explore/TraceExploration.tsx @@ -27,11 +27,11 @@ import { ExplorationHistory, ExplorationHistoryStep } from './ExplorationHistory import { TracesByServiceScene } from '../../components/Explore/TracesByService/TracesByServiceScene'; import { SelectStartingPointScene } from './SelectStartingPointScene'; import { + DATASOURCE_LS_KEY, + DetailsSceneUpdated, StartingPointSelectedEvent, VAR_DATASOURCE, - DetailsSceneUpdated, VAR_FILTERS, - DATASOURCE_LS_KEY, } from '../../utils/shared'; import { getFilterSignature, getUrlForExploration } from '../../utils/utils'; import { DetailsScene } from '../../components/Explore/TracesByService/DetailsScene'; @@ -219,7 +219,7 @@ export class TraceExploration extends SceneObjectBase { export class TraceExplorationScene extends SceneObjectBase { static Component = ({ model }: SceneComponentProps) => { const traceExploration = sceneGraph.getAncestor(model, TraceExploration); - const { history, controls, topScene, showDetails, mode } = traceExploration.useState(); + const { controls, topScene, showDetails, mode } = traceExploration.useState(); const styles = useStyles2(getStyles); const dsVariable = sceneGraph.lookupVariable(VAR_DATASOURCE, traceExploration); @@ -232,10 +232,7 @@ export class TraceExplorationScene extends SceneObjectBase { return (
- - {dsVariable && } - - + {dsVariable && } {mode === 'traces' && (