Просмотр исходного кода

ref(metrics): renames operation to aggregation (#73489)

Ogi 8 месяцев назад
Родитель
Сommit
6f43d7d041

+ 2 - 2
static/app/components/metrics/chart/types.tsx

@@ -1,12 +1,12 @@
 import type {MarkLineComponentOption, SeriesOption} from 'echarts';
 
 import type {BaseChartProps} from 'sentry/components/charts/baseChart';
-import type {MetricsAggregate} from 'sentry/types';
 import type {DateString} from 'sentry/types/core';
+import type {MetricAggregation} from 'sentry/types/metrics';
 import type {MetricDisplayType} from 'sentry/utils/metrics/types';
 
 export type Series = {
-  aggregate: MetricsAggregate;
+  aggregate: MetricAggregation;
   color: string;
   data: {name: number; value: number}[];
   id: string;

+ 10 - 9
static/app/components/metrics/chart/useMetricChartSamples.tsx

@@ -14,12 +14,13 @@ import {fitToValueRect} from 'sentry/components/metrics/chart/utils';
 import type {Field} from 'sentry/components/metrics/metricSamplesTable';
 import {t} from 'sentry/locale';
 import type {EChartClickHandler, ReactEchartsRef} from 'sentry/types/echarts';
+import type {MetricAggregation} from 'sentry/types/metrics';
 import {defined} from 'sentry/utils';
 import mergeRefs from 'sentry/utils/mergeRefs';
-import {isCumulativeOp} from 'sentry/utils/metrics';
+import {isCumulativeAggregation} from 'sentry/utils/metrics';
 import {formatMetricUsingUnit} from 'sentry/utils/metrics/formatters';
 import {
-  getSummaryValueForOp,
+  getSummaryValueForAggregation,
   type MetricsSamplesResults,
 } from 'sentry/utils/metrics/useMetricsSamples';
 
@@ -60,9 +61,9 @@ type EChartMouseEventParam = Parameters<EChartClickHandler>[0];
 
 interface UseMetricChartSamplesOptions {
   timeseries: Series[];
+  aggregation?: MetricAggregation;
   highlightedSampleId?: string;
   onSampleClick?: (sample: MetricsSamplesResults<Field>['data'][number]) => void;
-  operation?: string;
   samples?: MetricsSamplesResults<Field>['data'];
   unit?: string;
 }
@@ -71,7 +72,7 @@ export function useMetricChartSamples({
   timeseries,
   highlightedSampleId,
   onSampleClick,
-  operation,
+  aggregation,
   samples,
   unit = '',
 }: UseMetricChartSamplesOptions) {
@@ -132,11 +133,11 @@ export function useMetricChartSamples({
       valueFormatter: (_, label?: string) => {
         // We need to access the sample as the charts datapoints are fit to the charts viewport
         const sample = samplesById[label ?? ''];
-        const yValue = getSummaryValueForOp(sample.summary, operation);
+        const yValue = getSummaryValueForAggregation(sample.summary, aggregation);
         return formatMetricUsingUnit(yValue, unit);
       },
     };
-  }, [operation, samplesById, unit]);
+  }, [aggregation, samplesById, unit]);
 
   const handleClick = useCallback<EChartClickHandler>(
     (event: EChartMouseEventParam) => {
@@ -155,12 +156,12 @@ export function useMetricChartSamples({
       const newYAxisIndex = Array.isArray(baseProps.yAxes) ? baseProps.yAxes.length : 1;
       const newXAxisIndex = Array.isArray(baseProps.xAxes) ? baseProps.xAxes.length : 1;
 
-      if (!isCumulativeOp(operation)) {
+      if (aggregation && !isCumulativeAggregation(aggregation)) {
         series = (samples ?? []).map((sample, index) => {
           const isHighlighted = highlightedSampleId === sample.id;
 
           const xValue = moment(sample.timestamp).valueOf();
-          const value = getSummaryValueForOp(sample.summary, operation);
+          const value = getSummaryValueForAggregation(sample.summary, aggregation);
           const yValue = value;
 
           const [xPosition, yPosition] = fitToValueRect(xValue, yValue, valueRect);
@@ -250,7 +251,7 @@ export function useMetricChartSamples({
       formatterOptions,
       handleClick,
       highlightedSampleId,
-      operation,
+      aggregation,
       samples,
       theme.purple400,
       theme.white,

+ 3 - 3
static/app/components/metrics/customMetricsEventData.tsx

@@ -22,7 +22,7 @@ import type {
   MRI,
 } from 'sentry/types/metrics';
 import {defined} from 'sentry/utils';
-import {getDefaultAggregate, getMetricsUrl} from 'sentry/utils/metrics';
+import {getDefaultAggregation, getMetricsUrl} from 'sentry/utils/metrics';
 import {hasCustomMetrics} from 'sentry/utils/metrics/features';
 import {formatMetricUsingUnit} from 'sentry/utils/metrics/formatters';
 import {formatMRI, parseMRI} from 'sentry/utils/metrics/mri';
@@ -93,7 +93,7 @@ export function CustomMetricsEventData({
       metricsSummaryEntries.map((entry, index) => ({
         mri: entry.mri,
         name: index.toString(),
-        op: getDefaultAggregate(entry.mri),
+        aggregation: getDefaultAggregation(entry.mri),
         query: Object.entries(entry.item.tags ?? {})
           .map(([tagKey, tagValue]) => tagToQuery(tagKey, tagValue))
           .join(' '),
@@ -210,7 +210,7 @@ export function CustomMetricsEventData({
               {
                 mri: mri,
                 displayType: MetricDisplayType.LINE,
-                op: getDefaultAggregate(mri),
+                aggregation: getDefaultAggregation(mri),
                 query: Object.entries(summaryItem.tags ?? {})
                   .map(([tagKey, tagValue]) => tagToQuery(tagKey, tagValue))
                   .join(' '),

+ 19 - 13
static/app/components/metrics/metricSamplesTable.tsx

@@ -23,7 +23,7 @@ import {IconProfiling} from 'sentry/icons';
 import {t} from 'sentry/locale';
 import {space} from 'sentry/styles/space';
 import type {DateString, PageFilters} from 'sentry/types/core';
-import type {MRI, ParsedMRI} from 'sentry/types/metrics';
+import type {MetricAggregation, MRI, ParsedMRI} from 'sentry/types/metrics';
 import {defined} from 'sentry/utils';
 import {trackAnalytics} from 'sentry/utils/analytics';
 import {Container, FieldDateTime, NumberContainer} from 'sentry/utils/discover/styles';
@@ -33,7 +33,7 @@ import {formatMetricUsingUnit} from 'sentry/utils/metrics/formatters';
 import {parseMRI} from 'sentry/utils/metrics/mri';
 import {
   type Field as SelectedField,
-  getSummaryValueForOp,
+  getSummaryValueForAggregation,
   type MetricsSamplesResults,
   type ResultField,
   type Summary,
@@ -68,11 +68,11 @@ const fields: SelectedField[] = [
 export type Field = (typeof fields)[number];
 
 interface MetricsSamplesTableProps {
+  aggregation?: MetricAggregation;
   focusArea?: SelectionRange;
   hasPerformance?: boolean;
   mri?: MRI;
   onRowHover?: (sampleId?: string) => void;
-  op?: string;
   query?: string;
   setMetricsSamples?: React.Dispatch<
     React.SetStateAction<MetricsSamplesResults<Field>['data'] | undefined>
@@ -148,7 +148,7 @@ export function MetricSamplesTable({
   focusArea,
   mri,
   onRowHover,
-  op,
+  aggregation,
   query,
   setMetricsSamples,
   sortKey = 'sort',
@@ -212,7 +212,7 @@ export function MetricSamplesTable({
     max: focusArea?.max,
     min: focusArea?.min,
     mri,
-    op,
+    aggregation,
     query,
     referrer: 'api.organization.metrics-samples',
     enabled,
@@ -288,8 +288,8 @@ export function MetricSamplesTable({
   }, [currentSort, location]);
 
   const _renderBodyCell = useMemo(
-    () => renderBodyCell(op, parsedMRI?.unit),
-    [op, parsedMRI?.unit]
+    () => renderBodyCell(aggregation, parsedMRI?.unit),
+    [aggregation, parsedMRI?.unit]
   );
 
   const wrapperRef = useRef<HTMLDivElement>(null);
@@ -409,7 +409,7 @@ function renderHeadCell(
   };
 }
 
-function renderBodyCell(op?: string, unit?: string) {
+function renderBodyCell(aggregation?: MetricAggregation, unit?: string) {
   return function (
     col: GridColumnOrder<ResultField>,
     dataRow: MetricsSamplesResults<SelectedField>['data'][number]
@@ -443,7 +443,13 @@ function renderBodyCell(op?: string, unit?: string) {
     }
 
     if (col.key === 'summary') {
-      return <SummaryRenderer summary={dataRow.summary} op={op} unit={unit} />;
+      return (
+        <SummaryRenderer
+          summary={dataRow.summary}
+          aggregation={aggregation}
+          unit={unit}
+        />
+      );
     }
 
     if (col.key === 'timestamp') {
@@ -638,17 +644,17 @@ function DurationRenderer({duration}: {duration: number}) {
 
 function SummaryRenderer({
   summary,
-  op,
+  aggregation,
   unit,
 }: {
   summary: Summary;
-  op?: string;
+  aggregation?: MetricAggregation;
   unit?: string;
 }) {
-  const value = getSummaryValueForOp(summary, op);
+  const value = getSummaryValueForAggregation(summary, aggregation);
 
   // if the op is `count`, then the unit does not apply
-  unit = op === 'count' ? '' : unit;
+  unit = aggregation === 'count' ? '' : unit;
 
   return (
     <NumberContainer>{formatMetricUsingUnit(value ?? null, unit ?? '')}</NumberContainer>

+ 14 - 12
static/app/components/metrics/queryBuilder.tsx

@@ -13,7 +13,7 @@ import {t} from 'sentry/locale';
 import {space} from 'sentry/styles/space';
 import type {MRI} from 'sentry/types/metrics';
 import {trackAnalytics} from 'sentry/utils/analytics';
-import {getDefaultAggregate, isAllowedOp} from 'sentry/utils/metrics';
+import {getDefaultAggregation, isAllowedAggregation} from 'sentry/utils/metrics';
 import {parseMRI} from 'sentry/utils/metrics/mri';
 import type {MetricsQuery} from 'sentry/utils/metrics/types';
 import {useIncrementQueryMetric} from 'sentry/utils/metrics/useIncrementQueryMetric';
@@ -90,7 +90,7 @@ export const QueryBuilder = memo(function QueryBuilder({
       } else {
         queryChanges = {
           mri: mriValue,
-          op: getDefaultAggregate(mriValue),
+          aggregation: getDefaultAggregation(mriValue),
           groupBy: undefined,
         };
       }
@@ -105,9 +105,9 @@ export const QueryBuilder = memo(function QueryBuilder({
   const handleOpChange = useCallback(
     ({value}) => {
       trackAnalytics('ddm.widget.operation', {organization});
-      incrementQueryMetric('ddm.widget.operation', {op: value});
+      incrementQueryMetric('ddm.widget.operation', {aggregation: value});
       onChange({
-        op: value,
+        aggregation: value,
       });
     },
     [incrementQueryMetric, onChange, organization]
@@ -176,18 +176,20 @@ export const QueryBuilder = memo(function QueryBuilder({
             position="bottom"
             disabled={index !== 0}
           >
-            <OpSelect
+            <AggregationSelect
               size="md"
               triggerProps={{prefix: t('Agg')}}
               options={
-                selectedMeta?.operations.filter(isAllowedOp).map(op => ({
-                  label: op,
-                  value: op,
-                })) ?? []
+                selectedMeta?.operations
+                  .filter(isAllowedAggregation)
+                  .map(aggregation => ({
+                    label: aggregation,
+                    value: aggregation,
+                  })) ?? []
               }
-              triggerLabel={metricsQuery.op}
+              triggerLabel={metricsQuery.aggregation}
               disabled={!selectedMeta}
-              value={metricsQuery.op}
+              value={metricsQuery.aggregation}
               onChange={handleOpChange}
             />
           </GuideAnchor>
@@ -250,7 +252,7 @@ const FlexBlock = styled('div')`
   flex-wrap: wrap;
 `;
 
-const OpSelect = styled(CompactSelect)`
+const AggregationSelect = styled(CompactSelect)`
   /* makes selects from different have the same width which is enough to fit all agg options except "count_unique" */
   min-width: 128px;
   & > button {

+ 4 - 4
static/app/types/metrics.tsx

@@ -1,10 +1,11 @@
 import type {DateString} from 'sentry/types/core';
 
-export type MetricsAggregate =
+export type MetricAggregation =
   | 'sum'
   | 'count_unique'
   | 'avg'
   | 'count'
+  | 'min'
   | 'max'
   | 'p50'
   | 'p75'
@@ -100,9 +101,8 @@ export type MetricsTagValue = {
 export type MetricMeta = {
   blockingStatus: BlockingStatus[];
   mri: MRI;
-  // name is returned by the API but should not be used, use parseMRI(mri).name instead
-  // name: string;
-  operations: MetricsAggregate[];
+  // name: string; // returned by the API but should not be used, use parseMRI(mri).name instead
+  operations: MetricAggregation[];
   projectIds: number[];
   type: MetricType;
   unit: string;

+ 1 - 1
static/app/utils/metrics/constants.tsx

@@ -41,7 +41,7 @@ export const emptyMetricsQueryWidget: MetricsQueryWidget = {
   type: MetricExpressionType.QUERY,
   id: NO_QUERY_ID,
   mri: 'd:transactions/duration@millisecond' satisfies MRI,
-  op: 'avg',
+  aggregation: 'avg',
   query: '',
   groupBy: [],
   sort: DEFAULT_SORT_STATE,

+ 5 - 6
static/app/utils/metrics/dashboard.spec.tsx

@@ -1,4 +1,4 @@
-import type {MRI} from 'sentry/types/metrics';
+import type {MetricAggregation, MRI} from 'sentry/types/metrics';
 import {
   convertToDashboardWidget,
   getWidgetQuery,
@@ -16,7 +16,7 @@ describe('convertToDashboardWidget', () => {
             groupBy: ['project'],
             query: 'event.type:transaction',
             mri: 'c:custom/login@second',
-            op: 'p95',
+            aggregation: 'p95',
             id: 1,
           },
         ],
@@ -48,7 +48,7 @@ describe('convertToDashboardWidget', () => {
             groupBy: [],
             query: '',
             mri: 'd:transactions/measurements.duration@second',
-            op: 'p95',
+            aggregation: 'p95',
           },
         ],
         MetricDisplayType.BAR
@@ -80,7 +80,7 @@ describe('convertToDashboardWidget', () => {
             groupBy: [],
             query: '',
             mri: 'd:transactions/measurements.duration@second',
-            op: 'p95',
+            aggregation: 'p95',
             isHidden: true,
           },
           {
@@ -129,11 +129,10 @@ describe('getWidgetQuery', () => {
   };
 
   it('should return the correct widget query object', () => {
-    // Arrange
     const metricsQuery = {
       ...metricsQueryBase,
       mri: 'd:custom/sentry.events.symbolicator.query_task@second' as MRI,
-      op: 'sum',
+      aggregation: 'sum' as MetricAggregation,
       query: 'status = "success"',
       title: 'Example Widget',
     };

+ 1 - 1
static/app/utils/metrics/dashboard.tsx

@@ -43,7 +43,7 @@ export function toDisplayType(displayType: unknown): DisplayType {
 }
 
 export function getWidgetQuery(metricsQuery: QueryParams): WidgetQuery {
-  const field = MRIToField(metricsQuery.mri, metricsQuery.op);
+  const field = MRIToField(metricsQuery.mri, metricsQuery.aggregation);
   return {
     name: defined(metricsQuery.id) ? `${metricsQuery.id}` : '',
     aggregates: [field],

+ 15 - 13
static/app/utils/metrics/dashboardImport.tsx

@@ -94,7 +94,7 @@ export async function parseDashboard(
 const SUPPORTED_COLUMNS = new Set(['avg', 'max', 'min', 'sum', 'value']);
 const SUPPORTED_WIDGET_TYPES = new Set(['timeseries']);
 
-const METRIC_SUFFIX_TO_OP = {
+const METRIC_SUFFIX_TO_AGGREGATION = {
   avg: 'avg',
   max: 'max',
   min: 'min',
@@ -289,8 +289,8 @@ export class WidgetParser {
   }
 
   private parseQueryString(str: string) {
-    const operationMatch = str.match(/^(sum|avg|max|min):/);
-    let op = operationMatch ? operationMatch[1] : undefined;
+    const aggregationMatch = str.match(/^(sum|avg|max|min):/);
+    let aggregation = aggregationMatch ? aggregationMatch[1] : undefined;
 
     const metricNameMatch = str.match(/:(\S*){/);
     let metric = metricNameMatch ? metricNameMatch[1] : undefined;
@@ -298,10 +298,10 @@ export class WidgetParser {
     if (metric?.includes('.')) {
       const lastIndex = metric.lastIndexOf('.');
       const metricName = metric.slice(0, lastIndex);
-      const operationSuffix = metric.slice(lastIndex + 1);
+      const aggregationSuffix = metric.slice(lastIndex + 1);
 
-      if (METRIC_SUFFIX_TO_OP[operationSuffix]) {
-        op = METRIC_SUFFIX_TO_OP[operationSuffix];
+      if (METRIC_SUFFIX_TO_AGGREGATION[aggregationSuffix]) {
+        aggregation = METRIC_SUFFIX_TO_AGGREGATION[aggregationSuffix];
         metric = metricName;
       }
     }
@@ -315,9 +315,11 @@ export class WidgetParser {
     const appliedFunctionMatch = str.match(/\.(\w+)\(\)/);
     const appliedFunction = appliedFunctionMatch ? appliedFunctionMatch[1] : undefined;
 
-    if (!op) {
-      this.errors.push(`widget.request.query - could not parse op: ${str}, assuming sum`);
-      op = 'sum';
+    if (!aggregation) {
+      this.errors.push(
+        `widget.request.query - could not parse aggregation: ${str}, assuming sum`
+      );
+      aggregation = 'sum';
     }
 
     if (!metric) {
@@ -330,7 +332,7 @@ export class WidgetParser {
     // TODO: check which other functions are supported
     if (appliedFunction) {
       if (appliedFunction === 'as_count') {
-        op = 'sum';
+        aggregation = 'sum';
         this.errors.push(
           `widget.request.query - unsupported function ${appliedFunction}, assuming sum`
         );
@@ -342,7 +344,7 @@ export class WidgetParser {
     }
 
     return {
-      op,
+      aggregation,
       metric,
       filters,
       groupBy,
@@ -383,7 +385,7 @@ export class WidgetParser {
 
   // Mapping functions
   private async mapToMetricsQuery(widget): Promise<MetricsQuery | null> {
-    const {metric, op, filters} = widget;
+    const {metric, aggregation, filters} = widget;
 
     // @ts-expect-error name is actually defined on MetricMeta
     const metricMeta = this.availableMetrics.find(m => m.name === metric);
@@ -400,7 +402,7 @@ export class WidgetParser {
 
     return {
       mri: metricMeta.mri,
-      op,
+      aggregation,
       query,
       groupBy,
     };

Некоторые файлы не были показаны из-за большого количества измененных файлов