diff --git a/static/app/views/explore/metrics/hooks/useMetricAggregatesTable.tsx b/static/app/views/explore/metrics/hooks/useMetricAggregatesTable.tsx index 075b823f7c2171..dfca5476f39df7 100644 --- a/static/app/views/explore/metrics/hooks/useMetricAggregatesTable.tsx +++ b/static/app/views/explore/metrics/hooks/useMetricAggregatesTable.tsx @@ -11,7 +11,10 @@ import { type RPCQueryExtras, } from 'sentry/views/explore/hooks/useProgressiveQuery'; import type {TraceMetric} from 'sentry/views/explore/metrics/metricQuery'; -import {useMetricVisualizes} from 'sentry/views/explore/metrics/metricsQueryParams'; +import { + useMetricVisualize, + useMetricVisualizes, +} from 'sentry/views/explore/metrics/metricsQueryParams'; import {TraceMetricKnownFieldKey} from 'sentry/views/explore/metrics/types'; import {makeMetricsAggregate} from 'sentry/views/explore/metrics/utils'; import { @@ -19,6 +22,7 @@ import { useQueryParamsGroupBys, useQueryParamsQuery, } from 'sentry/views/explore/queryParams/context'; +import {isVisualizeEquation} from 'sentry/views/explore/queryParams/visualize'; import {useSpansQuery} from 'sentry/views/insights/common/queries/useSpansQuery'; interface UseMetricAggregatesTableOptions { @@ -48,8 +52,12 @@ export function useMetricAggregatesTable({ traceMetric, queryExtras, }: UseMetricAggregatesTableOptions) { + const visualize = useMetricVisualize(); const canTriggerHighAccuracy = useCallback( (result: ReturnType['result']) => { + if (isVisualizeEquation(visualize)) { + return false; + } const countAggregate = makeCountAggregate(traceMetric); const canGoToHigherAccuracyTier = result.meta?.dataScanned === 'partial'; const hasData = @@ -58,7 +66,7 @@ export function useMetricAggregatesTable({ (result.data.length === 1 && Boolean(result.data[0][countAggregate]))); return !hasData && canGoToHigherAccuracyTier; }, - [traceMetric] + [traceMetric, visualize] ); return useProgressiveQuery({ queryHookImplementation: useMetricAggregatesTableImp, @@ -87,6 +95,8 @@ function useMetricAggregatesTableImp({ const query = useQueryParamsQuery(); const sortBys = useQueryParamsAggregateSortBys(); + const isEquation = visualizes.every(isVisualizeEquation); + const fields = useMemo(() => { const allFields: string[] = []; @@ -111,7 +121,7 @@ function useMetricAggregatesTableImp({ const discoverQuery: NewQuery = { id: undefined, name: 'Explore - Metric Aggregates', - fields: [...fields, makeCountAggregate(traceMetric)], + fields: [...fields, ...(isEquation ? [] : [makeCountAggregate(traceMetric)])], orderby: sortBys.map(formatSort), query, version: 2, @@ -119,10 +129,17 @@ function useMetricAggregatesTableImp({ }; return EventView.fromNewQueryWithPageFilters(discoverQuery, selection); - }, [fields, query, selection, sortBys, traceMetric]); + }, [fields, query, selection, sortBys, traceMetric, isEquation]); const result = useSpansQuery({ - enabled: enabled && Boolean(traceMetric.name) && fields.length > 0, + enabled: + enabled && + fields.length > 0 && + (isEquation + ? visualizes.every( + visualize => isVisualizeEquation(visualize) && visualize.expression.text + ) + : Boolean(traceMetric.name)), eventView, initialData: [], limit, diff --git a/static/app/views/explore/metrics/metricInfoTabs/aggregatesTab.tsx b/static/app/views/explore/metrics/metricInfoTabs/aggregatesTab.tsx index 9037f91fecdc99..f8266328b641c7 100644 --- a/static/app/views/explore/metrics/metricInfoTabs/aggregatesTab.tsx +++ b/static/app/views/explore/metrics/metricInfoTabs/aggregatesTab.tsx @@ -10,7 +10,7 @@ import {COL_WIDTH_UNDEFINED} from 'sentry/components/tables/gridEditable'; import {SimpleTable} from 'sentry/components/tables/simpleTable'; import {IconWarning} from 'sentry/icons/iconWarning'; import {t} from 'sentry/locale'; -import {parseFunction} from 'sentry/utils/discover/fields'; +import {isEquation, parseFunction} from 'sentry/utils/discover/fields'; import {prettifyTagKey} from 'sentry/utils/fields'; import {useOrganization} from 'sentry/utils/useOrganization'; import type {TableColumn} from 'sentry/views/discover/table/types'; @@ -29,6 +29,7 @@ import { } from 'sentry/views/explore/metrics/metricInfoTabs/metricInfoTabStyles'; import type {TraceMetric} from 'sentry/views/explore/metrics/metricQuery'; import {canUseMetricsUIRefresh} from 'sentry/views/explore/metrics/metricsFlags'; +import {useMetricVisualize} from 'sentry/views/explore/metrics/metricsQueryParams'; import {TraceMetricKnownFieldKey} from 'sentry/views/explore/metrics/types'; import { createTraceMetricFilter, @@ -39,6 +40,10 @@ import { useQueryParamsGroupBys, useSetQueryParamsAggregateSortBys, } from 'sentry/views/explore/queryParams/context'; +import { + isVisualizeEquation, + isVisualizeFunction, +} from 'sentry/views/explore/queryParams/visualize'; import {FieldRenderer} from 'sentry/views/explore/tables/fieldRenderer'; import {TraceItemDataset} from 'sentry/views/explore/types'; import {GenericWidgetEmptyStateWarning} from 'sentry/views/performance/landing/widgets/components/selectableList'; @@ -67,9 +72,12 @@ export function AggregatesTab({traceMetric, isMetricOptionsEmpty}: AggregatesTab const hasMetricsUIRefresh = canUseMetricsUIRefresh(organization); const topEvents = useTopEvents(); const tableRef = useRef(null); + const visualize = useMetricVisualize(); const {result, eventView, fields} = useMetricAggregatesTable({ - enabled: Boolean(traceMetric.name) && !isMetricOptionsEmpty, + enabled: isVisualizeFunction(visualize) + ? Boolean(traceMetric.name) && !isMetricOptionsEmpty + : isVisualizeEquation(visualize) && Boolean(visualize.expression.text), limit: RESULT_LIMIT, traceMetric, }); @@ -107,21 +115,22 @@ export function AggregatesTab({traceMetric, isMetricOptionsEmpty}: AggregatesTab // When no group bys are selected, prepend the metric name as a virtual group-by column const displayFields = useMemo(() => { - if (groupBys.length === 0) { + if (groupBys.length === 0 && isVisualizeFunction(visualize)) { return [TraceMetricKnownFieldKey.METRIC_NAME, ...fields]; } return fields; - }, [groupBys.length, fields]); + }, [groupBys.length, fields, visualize]); const displayColumns = useMemo(() => { - if (groupBys.length === 0) { + if (groupBys.length === 0 && isVisualizeFunction(visualize)) { return [METRIC_NAME_COLUMN, ...columns]; } return columns; - }, [groupBys.length, columns]); + }, [groupBys.length, columns, visualize]); // Include the virtual metric name column in the group-by count so grid/divider logic works - const groupByFieldCount = groupBys.length === 0 ? 1 : groupBys.length; + const groupByFieldCount = + groupBys.length === 0 && isVisualizeFunction(visualize) ? 1 : groupBys.length; const aggregateFieldCount = displayFields.length - groupByFieldCount; const tableStyle = useMemo(() => { @@ -233,12 +242,16 @@ export function AggregatesTab({traceMetric, isMetricOptionsEmpty}: AggregatesTab label = `${func.name}(…)`; } else if (tag) { label = tag.name; + } else if (isEquation(field)) { + // TODO: This should say the reference format of equations + label = t('Result'); } else { label = prettifyTagKey(field); } const direction = sorts.find(s => s.field === field)?.kind; - const canSort = displayColumns[i]?.isSortable !== false; + const canSort = + displayColumns.find(column => column.key === field)?.isSortable !== false; function updateSort() { const kind = direction === 'desc' ? 'asc' : 'desc'; @@ -250,7 +263,9 @@ export function AggregatesTab({traceMetric, isMetricOptionsEmpty}: AggregatesTab key={i} divider={shouldShowDivider(i)} data-sticky-column={isLastColumn(i) ? 'true' : 'false'} - isAggregate={Boolean(func)} + isAggregate={ + Boolean(func) || (isVisualizeEquation(visualize) && isEquation(field)) + } isSticky={isLastColumn(i)} sort={direction} handleSortClick={canSort ? updateSort : undefined} @@ -289,7 +304,7 @@ export function AggregatesTab({traceMetric, isMetricOptionsEmpty}: AggregatesTab offset={j === 0 ? firstColumnOffset : undefined} > column.key === field)} data={displayRow} unit={getMetricsUnit(meta, field)} meta={meta} diff --git a/static/app/views/explore/metrics/metricPanel/index.tsx b/static/app/views/explore/metrics/metricPanel/index.tsx index 61a03da9a1d686..5d0b914a3104b1 100644 --- a/static/app/views/explore/metrics/metricPanel/index.tsx +++ b/static/app/views/explore/metrics/metricPanel/index.tsx @@ -32,7 +32,10 @@ import { useQueryParamsMode, useQueryParamsSortBys, } from 'sentry/views/explore/queryParams/context'; -import {isVisualizeEquation} from 'sentry/views/explore/queryParams/visualize'; +import { + isVisualizeEquation, + isVisualizeFunction, +} from 'sentry/views/explore/queryParams/visualize'; const RESULT_LIMIT = 50; const TWO_MINUTE_DELAY = 120; @@ -72,8 +75,19 @@ export function MetricPanel({ const hasMetricsUIRefresh = canUseMetricsUIRefresh(organization); const fields = getTraceSamplesTableFields(TraceSamplesTableColumns); + const mode = useQueryParamsMode(); + const sortBys = useQueryParamsSortBys(); + const aggregateSortBys = useQueryParamsAggregateSortBys(); + const [interval] = useChartInterval(); + const topEvents = useTopEvents(); + const visualize = useMetricVisualize(); + + const areQueriesEnabled = isVisualizeFunction(visualize) + ? Boolean(traceMetric.name) && !isMetricOptionsEmpty + : isVisualizeEquation(visualize) && Boolean(visualize.expression.text); + const metricSamplesTableResult = useMetricSamplesTable({ - disabled: !traceMetric?.name || isMetricOptionsEmpty, + disabled: !areQueriesEnabled, limit: RESULT_LIMIT, traceMetric, fields, @@ -81,18 +95,11 @@ export function MetricPanel({ }); const metricAggregatesTableResult = useMetricAggregatesTable({ - enabled: Boolean(traceMetric.name) && !isMetricOptionsEmpty, + enabled: areQueriesEnabled, limit: RESULT_LIMIT, traceMetric, }); - const mode = useQueryParamsMode(); - const sortBys = useQueryParamsSortBys(); - const aggregateSortBys = useQueryParamsAggregateSortBys(); - const [interval] = useChartInterval(); - const topEvents = useTopEvents(); - const visualize = useMetricVisualize(); - const {result: timeseriesResult} = useMetricTimeseries({ traceMetric, enabled: