def check_project_alerts(project_id, **kwargs): """ Given 'when' and 'count', which should signify recent times we compare it to historical data for this project and if over a given threshold, create an alert. """ from sentry.app import tsdb from sentry.constants import DEFAULT_ALERT_PROJECT_THRESHOLD from sentry.models import ProjectOption, Alert threshold, min_events = ProjectOption.objects.get_value( project_id, 'alert:threshold', DEFAULT_ALERT_PROJECT_THRESHOLD) if not threshold and min_events: return end = datetime.now().replace(tzinfo=utc) - timedelta(seconds=10) start = end - timedelta(minutes=5) results = [v for _, v in tsdb.get_range( tsdb.models.project, [project_id], start=start, end=end, rollup=10, )[project_id]] half_intervals = int(len(results) / 2) previous_data, current_data = results[:half_intervals], results[half_intervals:] if not current_data: return current_avg = sum(current_data) / len(current_data) # if there first few points within previous data are empty, assume that the # project hasn't been active long enough for rates to be valid if not any(previous_data[:3]): return if min_events > current_avg: return mean = math.mean(previous_data) dev = math.mad(previous_data) previous_avg = (mean + dev * 2) pct_increase = (current_avg / previous_avg * 100) - 100 logger.info('Rate of events for project %d changed from %.2f to %2.f', project_id, previous_avg, current_avg) if pct_increase > threshold and current_avg > previous_avg: Alert.maybe_alert( project_id=project_id, message='Rate of events increased from %.2f to %.2f' % (previous_avg, current_avg), )
def check_project_alerts(project_id, **kwargs): """ Given 'when' and 'count', which should signify recent times we compare it to historical data for this project and if over a given threshold, create an alert. """ from sentry.app import tsdb from sentry.constants import DEFAULT_ALERT_PROJECT_THRESHOLD from sentry.models import ProjectOption, Alert threshold, min_events = ProjectOption.objects.get_value( project_id, 'alert:threshold', DEFAULT_ALERT_PROJECT_THRESHOLD) if not threshold and min_events: return end = datetime.now().replace(tzinfo=utc) - timedelta(seconds=10) start = end - timedelta(minutes=5) results = [ v for _, v in tsdb.get_range( tsdb.models.project, [project_id], start=start, end=end, rollup=10, )[project_id] ] half_intervals = int(len(results) / 2) previous_data, current_data = results[:half_intervals], results[ half_intervals:] current_avg = sum(current_data) / len(current_data) # if there first few points within previous data are empty, assume that the # project hasn't been active long enough for rates to be valid if not any(previous_data[:3]): return if min_events > current_avg: return mean = math.mean(previous_data) dev = math.mad(previous_data) previous_avg = (mean + dev * 2) pct_increase = (current_avg / previous_avg * 100) - 100 logger.info('Rate of events for project %d changed from %.2f to %2.f', project_id, previous_avg, current_avg) if pct_increase > threshold and current_avg > previous_avg: Alert.maybe_alert( project_id=project_id, message='Rate of events increased from %.2f to %.2f' % (previous_avg, current_avg), )
def check_project_alerts(project_id, when, count, **kwargs): """ Given 'when' and 'count', which should signify recent times we compare it to historical data for this project and if over a given threshold, create an alert. """ from sentry.conf import settings from sentry.models import ProjectCountByMinute, ProjectOption, Alert # TODO: make this use the cache try: threshold, min_events = ProjectOption.objects.get( project=project_id, key='alert:threshold', ).value except ProjectOption.DoesNotExist: threshold, min_events = settings.DEFAULT_ALERT_PROJECT_THRESHOLD if not threshold and min_events: return if min_events > count: return # number of 15 minute intervals to capture intervals = 8 max_date = when - timedelta(minutes=MINUTE_NORMALIZATION) min_date = max_date - timedelta(minutes=(intervals * MINUTE_NORMALIZATION)) # get historical data data = list( ProjectCountByMinute.objects.filter( project=project_id, date__lte=max_date, date__gt=min_date, ).values_list('times_seen', flat=True)) # Bail if we don't have enough data points if len(data) != intervals: return mean = math.mean(data) dev = math.mad(data) previous = (mean + dev * 2) / MINUTE_NORMALIZATION pct_increase = count / previous * 100 if pct_increase > threshold: Alert.maybe_alert( project_id=project_id, message='Rate of events per minute increased from %d to %d (+%d%%)' % (previous, count, pct_increase), )
def check_project_alerts(project_id, when, count, **kwargs): """ Given 'when' and 'count', which should signify recent times we compare it to historical data for this project and if over a given threshold, create an alert. """ from sentry.conf import settings from sentry.models import ProjectCountByMinute, ProjectOption, Alert # TODO: make this use the cache try: threshold, min_events = ProjectOption.objects.get( project=project_id, key='alert:threshold', ).value except ProjectOption.DoesNotExist: threshold, min_events = settings.DEFAULT_ALERT_PROJECT_THRESHOLD if not threshold and min_events: return if min_events > count: return # number of 15 minute intervals to capture intervals = 8 max_date = when - timedelta(minutes=MINUTE_NORMALIZATION) min_date = max_date - timedelta(minutes=(intervals * MINUTE_NORMALIZATION)) # get historical data data = list(ProjectCountByMinute.objects.filter( project=project_id, date__lte=max_date, date__gt=min_date, ).values_list('times_seen', flat=True)) # Bail if we don't have enough data points if len(data) != intervals: return mean = math.mean(data) dev = math.mad(data) previous = (mean + dev * 2) / MINUTE_NORMALIZATION pct_increase = count / previous * 100 if pct_increase > threshold: Alert.maybe_alert( project_id=project_id, message='Rate of events per minute increased from %d to %d (+%d%%)' % (previous, count, pct_increase), )
def test_does_add_trending_events(self, get_accelerated): get_accelerated.return_value = [self.group] alert = Alert.maybe_alert(**self.params) assert alert is not None get_accelerated.assert_called_once_with([self.project.id], minutes=MINUTE_NORMALIZATION) assert list(alert.related_groups.all()) == [self.group]
def test_does_add_trending_events(self, get_accelerated): get_accelerated.return_value = [self.group] alert = Alert.maybe_alert(**self.params) get_accelerated.assert_called_once_with([self.project.id], minutes=MINUTE_NORMALIZATION) assert list(alert.related_groups.all()) == [self.group]