Skip to content

Commit

Permalink
ServiceSelection: add support for aggregated metric (#713)
Browse files Browse the repository at this point in the history
* feat: add experimental support for `exploreLogsAggregatedMetrics` in service selection
---------

Co-authored-by: Sven Grossmann <[email protected]>
  • Loading branch information
gtk-grafana and svennergr committed Sep 19, 2024
1 parent b6ce250 commit 7fc099d
Show file tree
Hide file tree
Showing 12 changed files with 395 additions and 38 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
"@grafana/data": "^11.1.1",
"@grafana/lezer-logql": "^0.2.6",
"@grafana/runtime": "^11.1.1",
"@grafana/scenes": "5.7.2",
"@grafana/scenes": "5.9.0",
"@grafana/ui": "^11.1.1",
"@lezer/common": "^1.2.1",
"@lezer/lr": "^1.4.1",
Expand Down
27 changes: 20 additions & 7 deletions src/Components/IndexScene/IndexScene.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import { FilterOp } from 'services/filters';
import { getDrilldownSlug, PageSlugs } from '../../services/routing';
import { ServiceSelectionScene } from '../ServiceSelectionScene/ServiceSelectionScene';
import { LoadingPlaceholder } from '@grafana/ui';
import { locationService } from '@grafana/runtime';
import { config, locationService } from '@grafana/runtime';
import {
renderLogQLFieldFilters,
renderLogQLLabelFilters,
Expand All @@ -52,6 +52,7 @@ import {
} from 'services/query';
import { VariableHide } from '@grafana/schema';
import { CustomConstantVariable } from '../../services/CustomConstantVariable';
import { ToolbarScene } from './ToolbarScene';

export interface AppliedPattern {
pattern: string;
Expand All @@ -76,15 +77,27 @@ export class IndexScene extends SceneObjectBase<IndexSceneState> {
getLastUsedDataSourceFromStorage() ?? 'grafanacloud-logs',
state.initialFilters
);

const controls: SceneObject[] = [
new VariableValueSelectors({ layout: 'vertical' }),
new SceneControlsSpacer(),
new SceneTimePicker({}),
new SceneRefreshPicker({}),
];

//@ts-expect-error
if (getDrilldownSlug() === 'explore' && config.featureToggles.exploreLogsAggregatedMetrics) {
controls.push(
new ToolbarScene({
isOpen: false,
})
);
}

super({
$timeRange: state.$timeRange ?? new SceneTimeRange({}),
$variables: state.$variables ?? variablesScene,
controls: state.controls ?? [
new VariableValueSelectors({ layout: 'vertical' }),
new SceneControlsSpacer(),
new SceneTimePicker({}),
new SceneRefreshPicker({}),
],
controls: state.controls ?? controls,
// Need to clear patterns state when the class in constructed
patterns: [],
...state,
Expand Down
140 changes: 140 additions & 0 deletions src/Components/IndexScene/ToolbarScene.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import { SceneComponentProps, SceneObjectBase, SceneObjectState } from '@grafana/scenes';
import { Dropdown, Switch, ToolbarButton, useStyles2 } from '@grafana/ui';
import React from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { css } from '@emotion/css';
import { config } from '@grafana/runtime';
import { reportAppInteraction, USER_EVENTS_ACTIONS, USER_EVENTS_PAGES } from '../../services/analytics';
import { AGGREGATED_METRIC_START_DATE } from '../ServiceSelectionScene/ServiceSelectionScene';
import pluginJson from '../../plugin.json';
const AGGREGATED_METRICS_USER_OVERRIDE_LOCALSTORAGE_KEY = `${pluginJson.id}.serviceSelection.aggregatedMetrics`;

export interface ToolbarSceneState extends SceneObjectState {
isOpen: boolean;
options: {
aggregatedMetrics: {
active: boolean;
userOverride: boolean;
disabled: boolean;
};
};
}
export class ToolbarScene extends SceneObjectBase<ToolbarSceneState> {
constructor(state: Partial<ToolbarSceneState>) {
const userOverride = localStorage.getItem(AGGREGATED_METRICS_USER_OVERRIDE_LOCALSTORAGE_KEY);
// @ts-expect-error
const active = config.featureToggles.exploreLogsAggregatedMetrics && userOverride !== 'false';

super({
isOpen: false,
options: {
aggregatedMetrics: {
active,
userOverride: userOverride === 'true' ?? false,
disabled: false,
},
},
...state,
});
}

public toggleAggregatedMetricsOverride = () => {
const active = !this.state.options.aggregatedMetrics.active;

reportAppInteraction(
USER_EVENTS_PAGES.service_selection,
USER_EVENTS_ACTIONS.service_selection.aggregated_metrics_toggled,
{
enabled: active,
}
);

localStorage.setItem(AGGREGATED_METRICS_USER_OVERRIDE_LOCALSTORAGE_KEY, active.toString());

this.setState({
options: {
aggregatedMetrics: {
active,
disabled: this.state.options.aggregatedMetrics.disabled,
userOverride: active,
},
},
});
};

public onToggleOpen = (isOpen: boolean) => {
this.setState({ isOpen });
};

static Component = ({ model }: SceneComponentProps<ToolbarScene>) => {
const { isOpen, options } = model.useState();
const styles = useStyles2(getStyles);

const renderPopover = () => {
return (
<div className={styles.popover} onClick={(evt) => evt.stopPropagation()}>
<div className={styles.heading}>Query options</div>
<div className={styles.options}>
<div
title={
'Aggregated metrics will return service queries results much more quickly, but with lower resolution'
}
>
Aggregated metrics
</div>
<span
title={
options.aggregatedMetrics.disabled
? `Aggregated metrics can only be enabled for queries starting after ${AGGREGATED_METRIC_START_DATE.toLocaleString()}`
: ''
}
>
<Switch
value={options.aggregatedMetrics.active}
disabled={options.aggregatedMetrics.disabled}
onChange={model.toggleAggregatedMetricsOverride}
/>
</span>
</div>
</div>
);
};

if (options.aggregatedMetrics) {
return (
<Dropdown overlay={renderPopover} placement="bottom" onVisibleChange={model.onToggleOpen}>
<ToolbarButton icon="cog" variant="canvas" isOpen={isOpen} />
</Dropdown>
);
}

return <></>;
};
}

function getStyles(theme: GrafanaTheme2) {
return {
popover: css({
display: 'flex',
padding: theme.spacing(2),
flexDirection: 'column',
background: theme.colors.background.primary,
boxShadow: theme.shadows.z3,
borderRadius: theme.shape.radius.default,
border: `1px solid ${theme.colors.border.weak}`,
zIndex: 1,
marginRight: theme.spacing(2),
}),
heading: css({
fontWeight: theme.typography.fontWeightMedium,
paddingBottom: theme.spacing(2),
}),
options: css({
display: 'grid',
gridTemplateColumns: '1fr 50px',
rowGap: theme.spacing(1),
columnGap: theme.spacing(2),
alignItems: 'center',
}),
};
}
Loading

0 comments on commit 7fc099d

Please sign in to comment.