|
@@ -11,7 +11,7 @@ import ExternalLink from 'sentry/components/links/externalLink';
|
|
|
import {IconAdd, IconClose} from 'sentry/icons';
|
|
|
import {t, tct} from 'sentry/locale';
|
|
|
import {space} from 'sentry/styles/space';
|
|
|
-import type {MetricsAggregate} from 'sentry/types/metrics';
|
|
|
+import type {MetricsAggregate, MetricsExtractionCondition} from 'sentry/types/metrics';
|
|
|
import type {Project} from 'sentry/types/project';
|
|
|
import {DiscoverDatasets} from 'sentry/utils/discover/types';
|
|
|
import useOrganization from 'sentry/utils/useOrganization';
|
|
@@ -20,7 +20,7 @@ import {useSpanFieldSupportedTags} from 'sentry/views/performance/utils/useSpanF
|
|
|
export type AggregateGroup = 'count' | 'count_unique' | 'min_max' | 'percentiles';
|
|
|
export interface FormData {
|
|
|
aggregates: AggregateGroup[];
|
|
|
- conditions: string[];
|
|
|
+ conditions: MetricsExtractionCondition[];
|
|
|
spanAttribute: string | null;
|
|
|
tags: string[];
|
|
|
}
|
|
@@ -92,6 +92,22 @@ export function aggregatesToGroups(aggregates: MetricsAggregate[]): AggregateGro
|
|
|
}
|
|
|
return groups;
|
|
|
}
|
|
|
+
|
|
|
+let currentTempId = 0;
|
|
|
+function createTempId(): number {
|
|
|
+ currentTempId -= 1;
|
|
|
+ return currentTempId;
|
|
|
+}
|
|
|
+
|
|
|
+export function createCondition(): MetricsExtractionCondition {
|
|
|
+ return {
|
|
|
+ query: '',
|
|
|
+ // id and mris will be set by the backend after creation
|
|
|
+ id: createTempId(),
|
|
|
+ mris: [],
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
const EMPTY_SET = new Set<never>();
|
|
|
const SPAN_SEARCH_CONFIG = {
|
|
|
booleanKeys: EMPTY_SET,
|
|
@@ -218,20 +234,33 @@ export function MetricsExtractionRuleForm({isEdit, project, onSubmit, ...props}:
|
|
|
flexibleControlStateSize
|
|
|
>
|
|
|
{({onChange, initialData, value}) => {
|
|
|
- const conditions = (value || initialData) as string[];
|
|
|
+ const conditions = (value ||
|
|
|
+ initialData ||
|
|
|
+ []) as MetricsExtractionCondition[];
|
|
|
+
|
|
|
+ const handleChange = (queryString: string, index: number) => {
|
|
|
+ onChange(
|
|
|
+ conditions.toSpliced(index, 1, {
|
|
|
+ ...conditions[index],
|
|
|
+ query: queryString,
|
|
|
+ }),
|
|
|
+ {}
|
|
|
+ );
|
|
|
+ };
|
|
|
+
|
|
|
return (
|
|
|
<Fragment>
|
|
|
<ConditionsWrapper hasDelete={value.length > 1}>
|
|
|
- {conditions.map((query, index) => (
|
|
|
- <Fragment key={index}>
|
|
|
+ {conditions.map((condition, index) => (
|
|
|
+ <Fragment key={condition.id}>
|
|
|
<SearchWrapper hasPrefix={index !== 0}>
|
|
|
{index !== 0 && <ConditionLetter>{t('or')}</ConditionLetter>}
|
|
|
<SearchBar
|
|
|
{...SPAN_SEARCH_CONFIG}
|
|
|
searchSource="metrics-extraction"
|
|
|
- query={query}
|
|
|
+ query={condition.query}
|
|
|
onSearch={(queryString: string) =>
|
|
|
- onChange(conditions.toSpliced(index, 1, queryString), {})
|
|
|
+ handleChange(queryString, index)
|
|
|
}
|
|
|
placeholder={t('Search for span attributes')}
|
|
|
organization={organization}
|
|
@@ -241,8 +270,10 @@ export function MetricsExtractionRuleForm({isEdit, project, onSubmit, ...props}:
|
|
|
projectIds={[parseInt(project.id, 10)]}
|
|
|
hasRecentSearches={false}
|
|
|
onBlur={(queryString: string) =>
|
|
|
- onChange(conditions.toSpliced(index, 1, queryString), {})
|
|
|
+ handleChange(queryString, index)
|
|
|
}
|
|
|
+ savedSearchType={undefined}
|
|
|
+ useFormWrapper={false}
|
|
|
/>
|
|
|
</SearchWrapper>
|
|
|
{value.length > 1 && (
|
|
@@ -257,8 +288,7 @@ export function MetricsExtractionRuleForm({isEdit, project, onSubmit, ...props}:
|
|
|
</ConditionsWrapper>
|
|
|
<ConditionsButtonBar>
|
|
|
<Button
|
|
|
- disabled={conditions.some(query => !query)}
|
|
|
- onClick={() => onChange([...conditions, ''], {})}
|
|
|
+ onClick={() => onChange([...conditions, createCondition()], {})}
|
|
|
icon={<IconAdd />}
|
|
|
>
|
|
|
{t('Add Query')}
|