123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- import moment from 'moment-timezone';
- import {getInterval} from 'sentry/components/charts/utils';
- import {getUtcDateString} from 'sentry/utils/dates';
- import {
- API_INTERVAL_POINTS_LIMIT,
- API_INTERVAL_POINTS_MIN,
- TIME_WINDOWS,
- type TimePeriodType,
- } from 'sentry/views/alerts/rules/metric/details/constants';
- import type {MetricRule} from 'sentry/views/alerts/rules/metric/types';
- import {Dataset, TimePeriod} from 'sentry/views/alerts/rules/metric/types';
- import {extractEventTypeFilterFromRule} from 'sentry/views/alerts/rules/metric/utils/getEventTypeFilter';
- import type {Incident} from 'sentry/views/alerts/types';
- import {isCrashFreeAlert} from '../utils/isCrashFreeAlert';
- /**
- * Retrieve start/end date of a metric alert incident for the events graph
- * Will show at least 150 and no more than 10,000 data points
- */
- export function buildMetricGraphDateRange(incident: Incident): {
- end: string;
- start: string;
- } {
- const timeWindowMillis = incident.alertRule.timeWindow * 60 * 1000;
- const minRange = timeWindowMillis * API_INTERVAL_POINTS_MIN;
- const maxRange = timeWindowMillis * API_INTERVAL_POINTS_LIMIT;
- const now = moment.utc();
- const startDate = moment.utc(incident.dateStarted);
- // make a copy of now since we will modify endDate and use now for comparing
- const endDate = incident.dateClosed ? moment.utc(incident.dateClosed) : moment(now);
- const incidentRange = Math.max(endDate.diff(startDate), 3 * timeWindowMillis);
- const range = Math.min(maxRange, Math.max(minRange, incidentRange));
- const halfRange = moment.duration(range / 2);
- return {
- start: getUtcDateString(startDate.subtract(halfRange)),
- end: getUtcDateString(moment.min(endDate.add(halfRange), now)),
- };
- }
- export function getPeriodInterval(timePeriod: TimePeriodType, rule: MetricRule) {
- const startDate = moment.utc(timePeriod.start);
- const endDate = moment.utc(timePeriod.end);
- const timeWindow = rule?.timeWindow;
- const startEndDifferenceMs = endDate.diff(startDate);
- if (
- timeWindow &&
- (startEndDifferenceMs < API_INTERVAL_POINTS_LIMIT * timeWindow * 60 * 1000 ||
- // Special case 7 days * 1m interval over the api limit
- startEndDifferenceMs === TIME_WINDOWS[TimePeriod.SEVEN_DAYS])
- ) {
- return `${timeWindow}m`;
- }
- return getInterval({start: timePeriod.start, end: timePeriod.end}, 'high');
- }
- export function getFilter(rule: MetricRule): string[] | null {
- const {dataset, query} = rule;
- if (isCrashFreeAlert(dataset) || dataset === Dataset.EVENTS_ANALYTICS_PLATFORM) {
- return query.trim().split(' ');
- }
- const eventType = extractEventTypeFilterFromRule(rule);
- return (query ? `(${eventType}) AND (${query.trim()})` : eventType).split(' ');
- }
- export function getViableDateRange({
- interval,
- rule: {timeWindow, dataset},
- timePeriod: rawTimePeriod,
- }: {
- interval: string;
- rule: MetricRule;
- timePeriod: TimePeriodType;
- }) {
- const timePeriod = {...rawTimePeriod};
- // Fix for 7 days * 1m interval being over the max number of results from events api
- // 10k events is the current max
- if (
- timePeriod.usingPeriod &&
- timePeriod.period === TimePeriod.SEVEN_DAYS &&
- interval === '1m'
- ) {
- timePeriod.start = getUtcDateString(
- // -5 minutes provides a small cushion for rounding up minutes. This might be able to be smaller
- moment(moment.utc(timePeriod.end).subtract(10000 - 5, 'minutes'))
- );
- }
- // If the chart duration isn't as long as the rollup duration the events-stats
- // endpoint will return an invalid timeseriesData dataset
- let viableStartDate = getUtcDateString(
- moment.min(
- moment.utc(timePeriod.start),
- moment.utc(timePeriod.end).subtract(timeWindow, 'minutes')
- )
- );
- // Events Analytics Platform Span queries only support up to 2016 buckets.
- // 14 day 10m and 7 day 5m interval queries actually exceed this limit because we always extend the end date by an extra bucket.
- // We push forward the start date by a bucket to counteract this and return to 2016 buckets.
- if (
- dataset === Dataset.EVENTS_ANALYTICS_PLATFORM &&
- timePeriod.usingPeriod &&
- ((timePeriod.period === TimePeriod.FOURTEEN_DAYS && interval === '10m') ||
- (timePeriod.period === TimePeriod.SEVEN_DAYS && interval === '5m'))
- ) {
- viableStartDate = getUtcDateString(
- moment.utc(viableStartDate).add(timeWindow, 'minutes')
- );
- }
- const viableEndDate = getUtcDateString(
- moment.utc(timePeriod.end).add(timeWindow, 'minutes')
- );
- return {
- start: viableStartDate,
- end: viableEndDate,
- };
- }
|