diff --git a/frontend/src/container/MetricsExplorer/Inspect/ExpandedView.tsx b/frontend/src/container/MetricsExplorer/Inspect/ExpandedView.tsx index 9a01fcc7b111..986613ca2133 100644 --- a/frontend/src/container/MetricsExplorer/Inspect/ExpandedView.tsx +++ b/frontend/src/container/MetricsExplorer/Inspect/ExpandedView.tsx @@ -33,7 +33,7 @@ function ExpandedView({ options, spaceAggregationSeriesMap, step, - metricInspectionOptions, + appliedMetricInspectionOptions, timeAggregatedSeriesMap, }: ExpandedViewProps): JSX.Element { const [ @@ -44,17 +44,17 @@ function ExpandedView({ useEffect(() => { logEvent(MetricsExplorerEvents.InspectPointClicked, { [MetricsExplorerEventKeys.Modal]: 'inspect', - [MetricsExplorerEventKeys.Filters]: metricInspectionOptions.filters, + [MetricsExplorerEventKeys.Filters]: appliedMetricInspectionOptions.filters, [MetricsExplorerEventKeys.TimeAggregationInterval]: - metricInspectionOptions.timeAggregationInterval, + appliedMetricInspectionOptions.timeAggregationInterval, [MetricsExplorerEventKeys.TimeAggregationOption]: - metricInspectionOptions.timeAggregationOption, + appliedMetricInspectionOptions.timeAggregationOption, [MetricsExplorerEventKeys.SpaceAggregationOption]: - metricInspectionOptions.spaceAggregationOption, + appliedMetricInspectionOptions.spaceAggregationOption, [MetricsExplorerEventKeys.SpaceAggregationLabels]: - metricInspectionOptions.spaceAggregationLabels, + appliedMetricInspectionOptions.spaceAggregationLabels, }); - }, [metricInspectionOptions]); + }, [appliedMetricInspectionOptions]); useEffect(() => { if (step !== InspectionStep.COMPLETED) { @@ -167,7 +167,7 @@ function ExpandedView({ {`${absoluteValue} is the ${ SPACE_AGGREGATION_OPTIONS_FOR_EXPANDED_VIEW[ - metricInspectionOptions.spaceAggregationOption ?? + appliedMetricInspectionOptions.spaceAggregationOption ?? SpaceAggregationOptions.SUM_BY ] } of`} @@ -240,7 +240,7 @@ function ExpandedView({ )?.value ?? options?.value } is the ${ TIME_AGGREGATION_OPTIONS[ - metricInspectionOptions.timeAggregationOption ?? + appliedMetricInspectionOptions.timeAggregationOption ?? TimeAggregationOptions.SUM ] } of` @@ -299,7 +299,7 @@ function ExpandedView({ {`${absoluteValue} is the ${ TIME_AGGREGATION_OPTIONS[ - metricInspectionOptions.timeAggregationOption ?? + appliedMetricInspectionOptions.timeAggregationOption ?? TimeAggregationOptions.SUM ] } of`} diff --git a/frontend/src/container/MetricsExplorer/Inspect/GraphView.tsx b/frontend/src/container/MetricsExplorer/Inspect/GraphView.tsx index 947672ac6472..63cdd4dd6442 100644 --- a/frontend/src/container/MetricsExplorer/Inspect/GraphView.tsx +++ b/frontend/src/container/MetricsExplorer/Inspect/GraphView.tsx @@ -29,7 +29,7 @@ function GraphView({ popoverOptions, setShowExpandedView, setExpandedViewOptions, - metricInspectionOptions, + appliedMetricInspectionOptions, isInspectMetricsRefetching, }: GraphViewProps): JSX.Element { const isDarkMode = useIsDarkMode(); @@ -233,7 +233,7 @@ function GraphView({ inspectMetricsTimeSeries={inspectMetricsTimeSeries} setShowExpandedView={setShowExpandedView} setExpandedViewOptions={setExpandedViewOptions} - metricInspectionOptions={metricInspectionOptions} + appliedMetricInspectionOptions={appliedMetricInspectionOptions} isInspectMetricsRefetching={isInspectMetricsRefetching} /> )} @@ -255,7 +255,7 @@ function GraphView({ )} diff --git a/frontend/src/container/MetricsExplorer/Inspect/Inspect.styles.scss b/frontend/src/container/MetricsExplorer/Inspect/Inspect.styles.scss index 721049f6d643..24db96a62937 100644 --- a/frontend/src/container/MetricsExplorer/Inspect/Inspect.styles.scss +++ b/frontend/src/container/MetricsExplorer/Inspect/Inspect.styles.scss @@ -122,6 +122,10 @@ gap: 4px; .inspect-metrics-query-builder-header { + display: flex; + align-items: center; + justify-content: space-between; + .query-builder-button-label { display: flex; align-items: center; diff --git a/frontend/src/container/MetricsExplorer/Inspect/Inspect.tsx b/frontend/src/container/MetricsExplorer/Inspect/Inspect.tsx index 97ac5845a49a..6b138b674f9c 100644 --- a/frontend/src/container/MetricsExplorer/Inspect/Inspect.tsx +++ b/frontend/src/container/MetricsExplorer/Inspect/Inspect.tsx @@ -24,6 +24,7 @@ import { MetricInspectionAction, } from './types'; import { useInspectMetrics } from './useInspectMetrics'; +import { useMetricName } from './utils'; function Inspect({ metricName: defaultMetricName, @@ -31,7 +32,12 @@ function Inspect({ onClose, }: InspectProps): JSX.Element { const isDarkMode = useIsDarkMode(); - const [metricName, setMetricName] = useState(defaultMetricName); + const { + currentMetricName, + setCurrentMetricName, + appliedMetricName, + setAppliedMetricName, + } = useMetricName(defaultMetricName); const [ popoverOptions, setPopoverOptions, @@ -42,9 +48,12 @@ function Inspect({ ] = useState(null); const [showExpandedView, setShowExpandedView] = useState(false); - const { data: metricDetailsData } = useGetMetricDetails(metricName ?? '', { - enabled: !!metricName, - }); + const { data: metricDetailsData } = useGetMetricDetails( + appliedMetricName ?? '', + { + enabled: !!appliedMetricName, + }, + ); const { currentQuery } = useQueryBuilder(); const { handleChangeQueryData } = useQueryOperations({ @@ -97,25 +106,16 @@ function Inspect({ aggregatedTimeSeries, timeAggregatedSeriesMap, reset, - } = useInspectMetrics(metricName); + } = useInspectMetrics(appliedMetricName); const handleDispatchMetricInspectionOptions = useCallback( (action: MetricInspectionAction): void => { dispatchMetricInspectionOptions(action); logEvent(MetricsExplorerEvents.InspectQueryChanged, { [MetricsExplorerEventKeys.Modal]: 'inspect', - [MetricsExplorerEventKeys.Filters]: metricInspectionOptions.filters, - [MetricsExplorerEventKeys.TimeAggregationInterval]: - metricInspectionOptions.timeAggregationInterval, - [MetricsExplorerEventKeys.TimeAggregationOption]: - metricInspectionOptions.timeAggregationOption, - [MetricsExplorerEventKeys.SpaceAggregationOption]: - metricInspectionOptions.spaceAggregationOption, - [MetricsExplorerEventKeys.SpaceAggregationLabels]: - metricInspectionOptions.spaceAggregationLabels, }); }, - [dispatchMetricInspectionOptions, metricInspectionOptions], + [dispatchMetricInspectionOptions], ); const selectedMetricType = useMemo( @@ -135,12 +135,6 @@ function Inspect({ reset(); }, [reset]); - // Reset inspection when the selected metric changes - useEffect(() => { - resetInspection(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [metricName]); - // Hide expanded view whenever inspection step changes useEffect(() => { setShowExpandedView(false); @@ -193,7 +187,7 @@ function Inspect({ inspectMetricsTimeSeries={aggregatedTimeSeries} formattedInspectMetricsTimeSeries={formattedInspectMetricsTimeSeries} resetInspection={resetInspection} - metricName={metricName} + metricName={appliedMetricName} metricUnit={selectedMetricUnit} metricType={selectedMetricType} spaceAggregationSeriesMap={spaceAggregationSeriesMap} @@ -203,15 +197,16 @@ function Inspect({ showExpandedView={showExpandedView} setExpandedViewOptions={setExpandedViewOptions} popoverOptions={popoverOptions} - metricInspectionOptions={metricInspectionOptions} + appliedMetricInspectionOptions={metricInspectionOptions.appliedOptions} isInspectMetricsRefetching={isInspectMetricsRefetching} /> )} @@ -244,7 +239,10 @@ function Inspect({ aggregatedTimeSeries, formattedInspectMetricsTimeSeries, resetInspection, - metricName, + appliedMetricName, + currentMetricName, + setCurrentMetricName, + setAppliedMetricName, selectedMetricUnit, selectedMetricType, spaceAggregationSeriesMap, diff --git a/frontend/src/container/MetricsExplorer/Inspect/QueryBuilder.tsx b/frontend/src/container/MetricsExplorer/Inspect/QueryBuilder.tsx index 6f00d8c3a3f5..2132f3bb07fe 100644 --- a/frontend/src/container/MetricsExplorer/Inspect/QueryBuilder.tsx +++ b/frontend/src/container/MetricsExplorer/Inspect/QueryBuilder.tsx @@ -1,5 +1,6 @@ import { Button, Card } from 'antd'; -import { Atom } from 'lucide-react'; +import { Atom, Play } from 'lucide-react'; +import { useCallback } from 'react'; import { QueryBuilderProps } from './types'; import { @@ -10,16 +11,24 @@ import { } from './utils'; function QueryBuilder({ - metricName, - setMetricName, + currentMetricName, + setCurrentMetricName, + setAppliedMetricName, spaceAggregationLabels, - metricInspectionOptions, + currentMetricInspectionOptions, dispatchMetricInspectionOptions, inspectionStep, inspectMetricsTimeSeries, searchQuery, metricType, }: QueryBuilderProps): JSX.Element { + const applyInspectionOptions = useCallback(() => { + setAppliedMetricName(currentMetricName ?? ''); + dispatchMetricInspectionOptions({ + type: 'APPLY_INSPECTION_OPTIONS', + }); + }, [currentMetricName, setAppliedMetricName, dispatchMetricInspectionOptions]); + return (
@@ -31,25 +40,36 @@ function QueryBuilder({ > Query Builder +
- + diff --git a/frontend/src/container/MetricsExplorer/Inspect/TableView.tsx b/frontend/src/container/MetricsExplorer/Inspect/TableView.tsx index ad2f02968b97..740686ba8039 100644 --- a/frontend/src/container/MetricsExplorer/Inspect/TableView.tsx +++ b/frontend/src/container/MetricsExplorer/Inspect/TableView.tsx @@ -11,13 +11,13 @@ function TableView({ setShowExpandedView, setExpandedViewOptions, isInspectMetricsRefetching, - metricInspectionOptions, + appliedMetricInspectionOptions, }: TableViewProps): JSX.Element { const isSpaceAggregatedWithoutLabel = useMemo( () => - !!metricInspectionOptions.spaceAggregationOption && - metricInspectionOptions.spaceAggregationLabels.length === 0, - [metricInspectionOptions], + !!appliedMetricInspectionOptions.spaceAggregationOption && + appliedMetricInspectionOptions.spaceAggregationLabels.length === 0, + [appliedMetricInspectionOptions], ); const labelKeys = useMemo(() => { if (isSpaceAggregatedWithoutLabel) { diff --git a/frontend/src/container/MetricsExplorer/Inspect/constants.ts b/frontend/src/container/MetricsExplorer/Inspect/constants.ts index 1bb71fce21da..854607108bda 100644 --- a/frontend/src/container/MetricsExplorer/Inspect/constants.ts +++ b/frontend/src/container/MetricsExplorer/Inspect/constants.ts @@ -72,13 +72,25 @@ export const SPACE_AGGREGATION_OPTIONS_FOR_EXPANDED_VIEW: Record< }; export const INITIAL_INSPECT_METRICS_OPTIONS: MetricInspectionOptions = { - timeAggregationOption: undefined, - timeAggregationInterval: undefined, - spaceAggregationOption: undefined, - spaceAggregationLabels: [], - filters: { - items: [], - op: 'AND', + currentOptions: { + timeAggregationOption: undefined, + timeAggregationInterval: undefined, + spaceAggregationOption: undefined, + spaceAggregationLabels: [], + filters: { + items: [], + op: 'AND', + }, + }, + appliedOptions: { + timeAggregationOption: undefined, + timeAggregationInterval: undefined, + spaceAggregationOption: undefined, + spaceAggregationLabels: [], + filters: { + items: [], + op: 'AND', + }, }, }; diff --git a/frontend/src/container/MetricsExplorer/Inspect/types.ts b/frontend/src/container/MetricsExplorer/Inspect/types.ts index eda878574dcf..fdd85093019f 100644 --- a/frontend/src/container/MetricsExplorer/Inspect/types.ts +++ b/frontend/src/container/MetricsExplorer/Inspect/types.ts @@ -43,16 +43,17 @@ export interface GraphViewProps { showExpandedView: boolean; setShowExpandedView: (showExpandedView: boolean) => void; setExpandedViewOptions: (options: GraphPopoverOptions | null) => void; - metricInspectionOptions: MetricInspectionOptions; + appliedMetricInspectionOptions: InspectOptions; isInspectMetricsRefetching: boolean; } export interface QueryBuilderProps { - metricName: string | null; - setMetricName: (metricName: string) => void; + currentMetricName: string | null; + setCurrentMetricName: (metricName: string) => void; + setAppliedMetricName: (metricName: string) => void; metricType: MetricType | undefined; spaceAggregationLabels: string[]; - metricInspectionOptions: MetricInspectionOptions; + currentMetricInspectionOptions: InspectOptions; dispatchMetricInspectionOptions: (action: MetricInspectionAction) => void; inspectionStep: InspectionStep; inspectMetricsTimeSeries: InspectMetricsSeries[]; @@ -60,19 +61,19 @@ export interface QueryBuilderProps { } export interface MetricNameSearchProps { - metricName: string | null; - setMetricName: (metricName: string) => void; + currentMetricName: string | null; + setCurrentMetricName: (metricName: string) => void; } export interface MetricFiltersProps { searchQuery: IBuilderQuery; dispatchMetricInspectionOptions: (action: MetricInspectionAction) => void; - metricName: string | null; + currentMetricName: string | null; metricType: MetricType | null; } export interface MetricTimeAggregationProps { - metricInspectionOptions: MetricInspectionOptions; + currentMetricInspectionOptions: InspectOptions; dispatchMetricInspectionOptions: (action: MetricInspectionAction) => void; inspectionStep: InspectionStep; inspectMetricsTimeSeries: InspectMetricsSeries[]; @@ -80,7 +81,7 @@ export interface MetricTimeAggregationProps { export interface MetricSpaceAggregationProps { spaceAggregationLabels: string[]; - metricInspectionOptions: MetricInspectionOptions; + currentMetricInspectionOptions: InspectOptions; dispatchMetricInspectionOptions: (action: MetricInspectionAction) => void; inspectionStep: InspectionStep; } @@ -101,7 +102,7 @@ export enum SpaceAggregationOptions { AVG_BY = 'avg_by', } -export interface MetricInspectionOptions { +export interface InspectOptions { timeAggregationOption: TimeAggregationOptions | undefined; timeAggregationInterval: number | undefined; spaceAggregationOption: SpaceAggregationOptions | undefined; @@ -109,13 +110,19 @@ export interface MetricInspectionOptions { filters: TagFilter; } +export interface MetricInspectionOptions { + currentOptions: InspectOptions; + appliedOptions: InspectOptions; +} + export type MetricInspectionAction = | { type: 'SET_TIME_AGGREGATION_OPTION'; payload: TimeAggregationOptions } | { type: 'SET_TIME_AGGREGATION_INTERVAL'; payload: number } | { type: 'SET_SPACE_AGGREGATION_OPTION'; payload: SpaceAggregationOptions } | { type: 'SET_SPACE_AGGREGATION_LABELS'; payload: string[] } | { type: 'SET_FILTERS'; payload: TagFilter } - | { type: 'RESET_INSPECTION' }; + | { type: 'RESET_INSPECTION' } + | { type: 'APPLY_INSPECTION_OPTIONS' }; export enum InspectionStep { TIME_AGGREGATION = 1, @@ -156,7 +163,7 @@ export interface ExpandedViewProps { options: GraphPopoverOptions | null; spaceAggregationSeriesMap: Map; step: InspectionStep; - metricInspectionOptions: MetricInspectionOptions; + appliedMetricInspectionOptions: InspectOptions; timeAggregatedSeriesMap: Map; } @@ -165,7 +172,7 @@ export interface TableViewProps { inspectMetricsTimeSeries: InspectMetricsSeries[]; setShowExpandedView: (showExpandedView: boolean) => void; setExpandedViewOptions: (options: GraphPopoverOptions | null) => void; - metricInspectionOptions: MetricInspectionOptions; + appliedMetricInspectionOptions: InspectOptions; isInspectMetricsRefetching: boolean; } diff --git a/frontend/src/container/MetricsExplorer/Inspect/useInspectMetrics.ts b/frontend/src/container/MetricsExplorer/Inspect/useInspectMetrics.ts index 20914d164a7f..a86bfa78ab04 100644 --- a/frontend/src/container/MetricsExplorer/Inspect/useInspectMetrics.ts +++ b/frontend/src/container/MetricsExplorer/Inspect/useInspectMetrics.ts @@ -27,30 +27,55 @@ const metricInspectionReducer = ( case 'SET_TIME_AGGREGATION_OPTION': return { ...state, - timeAggregationOption: action.payload, + currentOptions: { + ...state.currentOptions, + timeAggregationOption: action.payload, + }, }; case 'SET_TIME_AGGREGATION_INTERVAL': return { ...state, - timeAggregationInterval: action.payload, + currentOptions: { + ...state.currentOptions, + timeAggregationInterval: action.payload, + }, }; case 'SET_SPACE_AGGREGATION_OPTION': return { ...state, - spaceAggregationOption: action.payload, + currentOptions: { + ...state.currentOptions, + spaceAggregationOption: action.payload, + }, }; case 'SET_SPACE_AGGREGATION_LABELS': return { ...state, - spaceAggregationLabels: action.payload, + currentOptions: { + ...state.currentOptions, + spaceAggregationLabels: action.payload, + }, }; case 'SET_FILTERS': return { ...state, - filters: action.payload, + currentOptions: { + ...state.currentOptions, + filters: action.payload, + }, + }; + case 'APPLY_INSPECTION_OPTIONS': + return { + ...state, + appliedOptions: { + ...state.appliedOptions, + ...state.currentOptions, + }, }; case 'RESET_INSPECTION': - return { ...INITIAL_INSPECT_METRICS_OPTIONS }; + return { + ...INITIAL_INSPECT_METRICS_OPTIONS, + }; default: return state; } @@ -84,7 +109,7 @@ export function useInspectMetrics( metricName: metricName ?? '', start, end, - filters: metricInspectionOptions.filters, + filters: metricInspectionOptions.appliedOptions.filters, }, { enabled: !!metricName, @@ -117,13 +142,26 @@ export function useInspectMetrics( ); // Evaluate inspection step - const inspectionStep = useMemo(() => { - if (metricInspectionOptions.spaceAggregationOption) { + const currentInspectionStep = useMemo(() => { + if (metricInspectionOptions.currentOptions.spaceAggregationOption) { return InspectionStep.COMPLETED; } if ( - metricInspectionOptions.timeAggregationOption && - metricInspectionOptions.timeAggregationInterval + metricInspectionOptions.currentOptions.timeAggregationOption && + metricInspectionOptions.currentOptions.timeAggregationInterval + ) { + return InspectionStep.SPACE_AGGREGATION; + } + return InspectionStep.TIME_AGGREGATION; + }, [metricInspectionOptions]); + + const appliedInspectionStep = useMemo(() => { + if (metricInspectionOptions.appliedOptions.spaceAggregationOption) { + return InspectionStep.COMPLETED; + } + if ( + metricInspectionOptions.appliedOptions.timeAggregationOption && + metricInspectionOptions.appliedOptions.timeAggregationInterval ) { return InspectionStep.SPACE_AGGREGATION; } @@ -149,23 +187,26 @@ export function useInspectMetrics( // Apply time aggregation once required options are set if ( - inspectionStep >= InspectionStep.SPACE_AGGREGATION && - metricInspectionOptions.timeAggregationOption && - metricInspectionOptions.timeAggregationInterval + appliedInspectionStep >= InspectionStep.SPACE_AGGREGATION && + metricInspectionOptions.appliedOptions.timeAggregationOption && + metricInspectionOptions.appliedOptions.timeAggregationInterval ) { const { timeAggregatedSeries, timeAggregatedSeriesMap, - } = applyTimeAggregation(inspectMetricsTimeSeries, metricInspectionOptions); + } = applyTimeAggregation( + inspectMetricsTimeSeries, + metricInspectionOptions.appliedOptions, + ); timeSeries = timeAggregatedSeries; setTimeAggregatedSeriesMap(timeAggregatedSeriesMap); setAggregatedTimeSeries(timeSeries); } // Apply space aggregation - if (inspectionStep === InspectionStep.COMPLETED) { + if (appliedInspectionStep === InspectionStep.COMPLETED) { const { aggregatedSeries, spaceAggregatedSeriesMap } = applySpaceAggregation( timeSeries, - metricInspectionOptions, + metricInspectionOptions.appliedOptions, ); timeSeries = aggregatedSeries; setSpaceAggregatedSeriesMap(spaceAggregatedSeriesMap); @@ -186,7 +227,7 @@ export function useInspectMetrics( const rawData = [timestamps, ...timeseriesArray]; return rawData.map((series) => new Float64Array(series)); - }, [inspectMetricsTimeSeries, inspectionStep, metricInspectionOptions]); + }, [inspectMetricsTimeSeries, appliedInspectionStep, metricInspectionOptions]); const spaceAggregationLabels = useMemo(() => { const labels = new Set(); @@ -216,7 +257,7 @@ export function useInspectMetrics( spaceAggregationLabels, metricInspectionOptions, dispatchMetricInspectionOptions, - inspectionStep, + inspectionStep: currentInspectionStep, isInspectMetricsRefetching, spaceAggregatedSeriesMap, aggregatedTimeSeries, diff --git a/frontend/src/container/MetricsExplorer/Inspect/utils.tsx b/frontend/src/container/MetricsExplorer/Inspect/utils.tsx index cb29d464d36a..8441a3f7ca18 100644 --- a/frontend/src/container/MetricsExplorer/Inspect/utils.tsx +++ b/frontend/src/container/MetricsExplorer/Inspect/utils.tsx @@ -29,8 +29,8 @@ import { GraphPopoverData, GraphPopoverOptions, InspectionStep, + InspectOptions, MetricFiltersProps, - MetricInspectionOptions, MetricNameSearchProps, MetricSpaceAggregationProps, MetricTimeAggregationProps, @@ -74,13 +74,13 @@ export function getDefaultTimeAggregationInterval( } export function MetricNameSearch({ - metricName, - setMetricName, + currentMetricName, + setCurrentMetricName, }: MetricNameSearchProps): JSX.Element { - const [searchText, setSearchText] = useState(metricName); + const [searchText, setSearchText] = useState(currentMetricName); const handleSetMetricName = (value: BaseAutocompleteData): void => { - setMetricName(value.key); + setCurrentMetricName(value.key); }; const handleChange = (value: BaseAutocompleteData): void => { @@ -106,19 +106,19 @@ export function MetricNameSearch({ export function MetricFilters({ dispatchMetricInspectionOptions, searchQuery, - metricName, + currentMetricName, metricType, }: MetricFiltersProps): JSX.Element { const aggregateAttribute = useMemo( () => ({ - key: metricName ?? '', + key: currentMetricName ?? '', dataType: DataTypes.String, type: metricType, isColumn: true, isJSON: false, - id: `${metricName}--${DataTypes.String}--${metricType}--true`, + id: `${currentMetricName}--${DataTypes.String}--${metricType}--true`, }), - [metricName, metricType], + [currentMetricName, metricType], ); const [currentQuery, setCurrentQuery] = useState({ @@ -169,7 +169,7 @@ export function MetricFilters({ } export function MetricTimeAggregation({ - metricInspectionOptions, + currentMetricInspectionOptions, dispatchMetricInspectionOptions, inspectionStep, inspectMetricsTimeSeries, @@ -190,14 +190,14 @@ export function MetricTimeAggregation({
Align with { @@ -240,7 +240,7 @@ export function MetricTimeAggregation({ export function MetricSpaceAggregation({ spaceAggregationLabels, - metricInspectionOptions, + currentMetricInspectionOptions, dispatchMetricInspectionOptions, inspectionStep, }: MetricSpaceAggregationProps): JSX.Element { @@ -259,7 +259,7 @@ export function MetricSpaceAggregation({