Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions static/app/views/alerts/create.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type {Member, Organization} from 'sentry/types/organization';
import type {Project} from 'sentry/types/project';
import EventView from 'sentry/utils/discover/eventView';
import {uniqueId} from 'sentry/utils/guid';
import {decodeScalar} from 'sentry/utils/queryString';
import useRouteAnalyticsEventNames from 'sentry/utils/routeAnalytics/useRouteAnalyticsEventNames';
import useRouteAnalyticsParams from 'sentry/utils/routeAnalytics/useRouteAnalyticsParams';
import normalizeUrl from 'sentry/utils/url/normalizeUrl';
Expand All @@ -19,6 +20,7 @@ import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import IssueRuleEditor from 'sentry/views/alerts/rules/issue';
import MetricRulesCreate from 'sentry/views/alerts/rules/metric/create';
import MetricRuleDuplicate from 'sentry/views/alerts/rules/metric/duplicate';
import type {EventTypes} from 'sentry/views/alerts/rules/metric/types';
import {UptimeAlertForm} from 'sentry/views/alerts/rules/uptime/uptimeAlertForm';
import {AlertRuleType} from 'sentry/views/alerts/types';
import type {
Expand Down Expand Up @@ -51,13 +53,16 @@ function Create(props: Props) {
const {
aggregate,
dataset,
eventTypes,
createFromDuplicate,
duplicateRuleId,
createFromDiscover,
query,
createFromWizard,
} = location?.query ?? {};
const eventTypes = location?.query?.eventTypes
? (decodeScalar(location.query.eventTypes) as EventTypes)
: undefined;

const alertType = params.alertType || AlertRuleType.METRIC;

const sessionId = useRef(uniqueId());
Expand Down Expand Up @@ -122,7 +127,11 @@ function Create(props: Props) {
let wizardAlertType: undefined | WizardAlertType;
if (createFromWizard && alertType === AlertRuleType.METRIC) {
wizardAlertType = wizardTemplate
? getAlertTypeFromAggregateDataset({...wizardTemplate, organization})
? getAlertTypeFromAggregateDataset({
...wizardTemplate,
eventTypes: [wizardTemplate.eventTypes],
organization,
})
: 'issues';
}

Expand Down
1 change: 1 addition & 0 deletions static/app/views/alerts/rules/metric/details/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ function DetailsHeader({
getAlertTypeFromAggregateDataset({
aggregate: rule.aggregate,
dataset: rule.dataset,
eventTypes: rule.eventTypes,
});

return (
Expand Down
30 changes: 26 additions & 4 deletions static/app/views/alerts/rules/metric/details/metricChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,10 @@ import {
} from 'sentry/views/alerts/utils';
import {getChangeStatus} from 'sentry/views/alerts/utils/getChangeStatus';
import {AlertWizardAlertNames} from 'sentry/views/alerts/wizard/options';
import {getAlertTypeFromAggregateDataset} from 'sentry/views/alerts/wizard/utils';
import {
getAlertTypeFromAggregateDataset,
getTraceItemTypeForDatasetAndEventType,
} from 'sentry/views/alerts/wizard/utils';
import {hasDatasetSelector} from 'sentry/views/dashboards/utils';
import {SAMPLING_MODE} from 'sentry/views/explore/hooks/useProgressiveQuery';
import {useMetricEventStats} from 'sentry/views/issueDetails/metricIssues/useMetricEventStats';
Expand Down Expand Up @@ -158,6 +161,11 @@ export default function MetricChart({
const organization = useOrganization();
const shouldUseSessionsStats = isCrashFreeAlert(rule.dataset);

const traceItemType = getTraceItemTypeForDatasetAndEventType(
rule.dataset,
rule.eventTypes
);

const handleZoom = useCallback(
(start: DateString, end: DateString) => {
navigate({
Expand Down Expand Up @@ -233,6 +241,7 @@ export default function MetricChart({
query,
dataset,
openInDiscoverDataset,
traceItemType,
});

const resolvedPercent =
Expand Down Expand Up @@ -287,7 +296,13 @@ export default function MetricChart({
</Fragment>
</StyledInlineContainer>
{!isSessionAggregate(rule.aggregate) &&
(isEapAlertType(getAlertTypeFromAggregateDataset(rule)) ? (
(isEapAlertType(
getAlertTypeFromAggregateDataset({
...rule,
eventTypes: rule.eventTypes,
organization,
})
) ? (
<Feature features="visibility-explore-view">
<LinkButton size="sm" {...props}>
{buttonText}
Expand All @@ -303,7 +318,7 @@ export default function MetricChart({
</StyledChartControls>
);
},
[rule, organization, project, timePeriod, query]
[query, rule, organization, project, timePeriod, traceItemType]
);

const renderChart = useCallback(
Expand Down Expand Up @@ -377,7 +392,14 @@ export default function MetricChart({
<StyledPanelBody withPadding>
<ChartHeader>
<HeaderTitleLegend>
{AlertWizardAlertNames[getAlertTypeFromAggregateDataset(rule)]}
{
AlertWizardAlertNames[
getAlertTypeFromAggregateDataset({
...rule,
organization,
})
]
}
</HeaderTitleLegend>
</ChartHeader>
<ChartFilters>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ function MetricAlertActivity({organization, incident}: MetricAlertActivityProps)
);
const timeWindow = getDuration(incident.alertRule.timeWindow * 60);
const alertName = capitalize(
AlertWizardAlertNames[getAlertTypeFromAggregateDataset(incident.alertRule)]
AlertWizardAlertNames[
getAlertTypeFromAggregateDataset({...incident.alertRule, organization})
]
);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
import {makeDefaultCta} from 'sentry/views/alerts/rules/metric/metricRulePresets';
import type {MetricRule} from 'sentry/views/alerts/rules/metric/types';
import {isSessionAggregate} from 'sentry/views/alerts/utils';
import {getTraceItemTypeForDatasetAndEventType} from 'sentry/views/alerts/wizard/utils';

import type {TimePeriodType} from './constants';

Expand Down Expand Up @@ -65,6 +66,10 @@ function RelatedIssues({
rule,
query,
timePeriod,
traceItemType: getTraceItemTypeForDatasetAndEventType(
rule.dataset,
rule.eventTypes
),
});
return <RelatedIssuesNotAvailable buttonTo={to} buttonText={buttonText} />;
}
Expand Down
4 changes: 3 additions & 1 deletion static/app/views/alerts/rules/metric/details/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {getSearchFilters, isOnDemandSearchKey} from 'sentry/utils/onDemandMetric
import {capitalize} from 'sentry/utils/string/capitalize';
import {isChonkTheme} from 'sentry/utils/theme/withChonk';
import {useFeedbackForm} from 'sentry/utils/useFeedbackForm';
import useOrganization from 'sentry/utils/useOrganization';
import {COMPARISON_DELTA_OPTIONS} from 'sentry/views/alerts/rules/metric/constants';
import type {Action, MetricRule} from 'sentry/views/alerts/rules/metric/types';
import {
Expand Down Expand Up @@ -47,6 +48,7 @@ function TriggerDescription({
rule: MetricRule;
threshold: number;
}) {
const organization = useOrganization();
const status =
label === AlertRuleTriggerType.CRITICAL
? t('Critical')
Expand All @@ -70,7 +72,7 @@ function TriggerDescription({
: t('below');
const timeWindow = <Duration seconds={rule.timeWindow * 60} />;
const metricName = capitalize(
AlertWizardAlertNames[getAlertTypeFromAggregateDataset(rule)]
AlertWizardAlertNames[getAlertTypeFromAggregateDataset({...rule, organization})]
);

const thresholdText = rule.comparisonDelta
Expand Down
84 changes: 68 additions & 16 deletions static/app/views/alerts/rules/metric/eapField.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {OrganizationFixture} from 'sentry-fixture/organization';
import {render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary';

import EAPField from 'sentry/views/alerts/rules/metric/eapField';
import {EventTypes} from 'sentry/views/alerts/rules/metric/types';
import {TraceItemAttributeProvider} from 'sentry/views/explore/contexts/traceItemAttributeContext';
import {TraceItemDataset} from 'sentry/views/explore/types';

Expand All @@ -21,7 +22,11 @@ describe('EAPField', () => {
it('renders', () => {
render(
<TraceItemAttributeProvider traceItemType={TraceItemDataset.SPANS} enabled>
<EAPField aggregate={'count(span.duration)'} onChange={() => {}} />
<EAPField
aggregate={'count(span.duration)'}
onChange={() => {}}
eventTypes={[EventTypes.TRACE_ITEM_SPAN]}
/>
</TraceItemAttributeProvider>
);
expect(fieldsMock).toHaveBeenCalledWith(
Expand Down Expand Up @@ -50,19 +55,17 @@ describe('EAPField', () => {
it('renders epm with argument disabled', () => {
render(
<TraceItemAttributeProvider traceItemType={TraceItemDataset.SPANS} enabled>
<EAPField aggregate={'epm()'} onChange={() => {}} />
<EAPField
aggregate={'epm()'}
onChange={() => {}}
eventTypes={[EventTypes.TRACE_ITEM_SPAN]}
/>
</TraceItemAttributeProvider>
);
expect(fieldsMock).toHaveBeenCalledWith(
`/organizations/${organization.slug}/trace-items/attributes/`,
expect.objectContaining({
query: expect.objectContaining({attributeType: 'number'}),
})
);
expect(fieldsMock).toHaveBeenCalledWith(
`/organizations/${organization.slug}/trace-items/attributes/`,
expect.objectContaining({
query: expect.objectContaining({attributeType: 'string'}),
query: expect.objectContaining({attributeType: 'number', itemType: 'spans'}),
})
);
expect(screen.getByText('epm')).toBeInTheDocument();
Expand All @@ -79,19 +82,23 @@ describe('EAPField', () => {
it('renders failure_rate with argument disabled', () => {
render(
<TraceItemAttributeProvider traceItemType={TraceItemDataset.SPANS} enabled>
<EAPField aggregate={'failure_rate()'} onChange={() => {}} />
<EAPField
aggregate={'failure_rate()'}
onChange={() => {}}
eventTypes={[EventTypes.TRACE_ITEM_SPAN]}
/>
</TraceItemAttributeProvider>
);
expect(fieldsMock).toHaveBeenCalledWith(
`/organizations/${organization.slug}/trace-items/attributes/`,
expect.objectContaining({
query: expect.objectContaining({attributeType: 'number'}),
query: expect.objectContaining({attributeType: 'number', itemType: 'spans'}),
})
);
expect(fieldsMock).toHaveBeenCalledWith(
`/organizations/${organization.slug}/trace-items/attributes/`,
expect.objectContaining({
query: expect.objectContaining({attributeType: 'string'}),
query: expect.objectContaining({attributeType: 'string', itemType: 'spans'}),
})
);
expect(screen.getByText('failure_rate')).toBeInTheDocument();
Expand All @@ -109,7 +116,11 @@ describe('EAPField', () => {
const onChange = jest.fn();
render(
<TraceItemAttributeProvider traceItemType={TraceItemDataset.SPANS} enabled>
<EAPField aggregate={'count(span.duration)'} onChange={onChange} />
<EAPField
aggregate={'count(span.duration)'}
onChange={onChange}
eventTypes={[EventTypes.TRACE_ITEM_SPAN]}
/>
</TraceItemAttributeProvider>
);
expect(fieldsMock).toHaveBeenCalledWith(
Expand All @@ -121,7 +132,7 @@ describe('EAPField', () => {
expect(fieldsMock).toHaveBeenCalledWith(
`/organizations/${organization.slug}/trace-items/attributes/`,
expect.objectContaining({
query: expect.objectContaining({attributeType: 'string'}),
query: expect.objectContaining({attributeType: 'string', itemType: 'spans'}),
})
);
await userEvent.click(screen.getByText('count'));
Expand All @@ -134,7 +145,11 @@ describe('EAPField', () => {
const [aggregate, setAggregate] = useState('count(span.duration)');
return (
<TraceItemAttributeProvider traceItemType={TraceItemDataset.SPANS} enabled>
<EAPField aggregate={aggregate} onChange={setAggregate} />
<EAPField
aggregate={aggregate}
onChange={setAggregate}
eventTypes={[EventTypes.TRACE_ITEM_SPAN]}
/>
</TraceItemAttributeProvider>
);
}
Expand Down Expand Up @@ -163,7 +178,11 @@ describe('EAPField', () => {
const [aggregate, setAggregate] = useState('count(span.duration)');
return (
<TraceItemAttributeProvider traceItemType={TraceItemDataset.SPANS} enabled>
<EAPField aggregate={aggregate} onChange={setAggregate} />
<EAPField
aggregate={aggregate}
onChange={setAggregate}
eventTypes={[EventTypes.TRACE_ITEM_SPAN]}
/>
</TraceItemAttributeProvider>
);
}
Expand All @@ -190,4 +209,37 @@ describe('EAPField', () => {
expect(screen.getByText('count_unique')).toBeInTheDocument();
expect(screen.getByText('span.op')).toBeInTheDocument();
});

it('renders count with argument disabled for logs', () => {
render(
<TraceItemAttributeProvider traceItemType={TraceItemDataset.LOGS} enabled>
<EAPField
aggregate={'count(message)'}
onChange={() => {}}
eventTypes={[EventTypes.TRACE_ITEM_LOG]}
/>
</TraceItemAttributeProvider>
);
expect(fieldsMock).toHaveBeenCalledWith(
`/organizations/${organization.slug}/trace-items/attributes/`,
expect.objectContaining({
query: expect.objectContaining({attributeType: 'number', itemType: 'logs'}),
})
);
expect(fieldsMock).toHaveBeenCalledWith(
`/organizations/${organization.slug}/trace-items/attributes/`,
expect.objectContaining({
query: expect.objectContaining({attributeType: 'string', itemType: 'logs'}),
})
);
expect(screen.getByText('count')).toBeInTheDocument();
expect(screen.getByText('logs')).toBeInTheDocument();

const inputs = screen.getAllByRole('textbox');
expect(inputs).toHaveLength(2);
// this corresponds to the `count` input
expect(inputs[0]).toBeEnabled();
// this corresponds to the `spans` input
expect(inputs[1]).toBeDisabled();
});
});
Loading
Loading