def _IsAlertRecovered(self, alert_entity): test = alert_entity.GetTestMetadataKey().get() if not test: logging.error( 'TestMetadata %s not found for Anomaly %s, deleting test.', utils.TestPath(alert_entity.GetTestMetadataKey()), alert_entity) return False config = anomaly_config.GetAnomalyConfigDict(test) max_num_rows = config.get('max_window_size', find_anomalies.DEFAULT_NUM_POINTS) rows = [ r for r in find_anomalies.GetRowsToAnalyze(test, max_num_rows) if r.revision > alert_entity.end_revision ] change_points = find_anomalies.FindChangePointsForTest(rows, config) delta_anomaly = (alert_entity.median_after_anomaly - alert_entity.median_before_anomaly) for change in change_points: delta_change = change.median_after - change.median_before if (self._IsOppositeDirection(delta_anomaly, delta_change) and self._IsApproximatelyEqual(delta_anomaly, -delta_change)): logging.debug( 'Anomaly %s recovered; recovery change point %s.', alert_entity.key, change.AsDict()) return True return False
def _IsAnomalyRecovered(anomaly_entity): """Checks whether an Anomaly has recovered. An Anomaly will be considered "recovered" if there's a change point in the series after the Anomaly with roughly equal magnitude and opposite direction. Args: anomaly_entity: The original regression Anomaly. Returns: True if the Anomaly should be marked as recovered, False otherwise. """ test = anomaly_entity.test.get() config = anomaly_config.GetAnomalyConfigDict(test) max_num_rows = config.get('max_window_size', find_anomalies.DEFAULT_NUM_POINTS) rows = [ r for r in find_anomalies.GetRowsToAnalyze(test, max_num_rows) if r.revision > anomaly_entity.end_revision ] change_points = find_anomalies.FindChangePointsForTest(rows, config) delta_anomaly = (anomaly_entity.median_after_anomaly - anomaly_entity.median_before_anomaly) for change in change_points: delta_change = change.median_after - change.median_before if (_IsOppositeDirection(delta_anomaly, delta_change) and _IsApproximatelyEqual(delta_anomaly, -delta_change)): logging.debug('Anomaly %s recovered; recovery change point %s.', anomaly_entity.key, change.AsDict()) return True return False