def GetAlertsForKeys(keys): """Get alerts for |keys|. Query for anomalies with overlapping revision. The |keys| parameter for group_report is a comma-separated list of urlsafe strings for Keys for Anomaly entities. (Each key corresponds to an alert) Args: keys: Comma-separated list of urlsafe strings for Anomaly keys. Returns: tuple (alerts, extra_columns) """ urlsafe_keys = keys try: keys = [ndb.Key(urlsafe=k) for k in urlsafe_keys] # Errors that can be thrown here include ProtocolBufferDecodeError # in google.net.proto.ProtocolBuffer. We want to catch any errors here # because they're almost certainly urlsafe key decoding errors. except Exception: raise request_handler.InvalidInputError('Invalid Anomaly key given.') requested_anomalies = utils.GetMulti(keys) extra_columns = None for i, anomaly_entity in enumerate(requested_anomalies): if isinstance(anomaly_entity, anomaly.Anomaly): extra_columns = 'anomalies' elif (isinstance(anomaly_entity, stoppage_alert.StoppageAlert) and extra_columns is None): extra_columns = 'stoppage_alerts' if anomaly_entity is None: raise request_handler.InvalidInputError( 'No Anomaly found for key %s.' % urlsafe_keys[i]) if not requested_anomalies: raise request_handler.InvalidInputError('No anomalies found.') sheriff_key = requested_anomalies[0].sheriff min_range = utils.MinimumAlertRange(requested_anomalies) if min_range: query = anomaly.Anomaly.query(anomaly.Anomaly.sheriff == sheriff_key) query = query.order(-anomaly.Anomaly.timestamp) anomalies = query.fetch(limit=_QUERY_LIMIT) # Filter out anomalies that have been marked as invalid or ignore. # Include all anomalies with an overlapping revision range that have # been associated with a bug, or are not yet triaged. anomalies = [a for a in anomalies if a.bug_id is None or a.bug_id > 0] anomalies = _GetOverlaps(anomalies, min_range[0], min_range[1]) # Make sure alerts in specified param "keys" are included. key_set = {a.key for a in anomalies} for anomaly_entity in requested_anomalies: if anomaly_entity.key not in key_set: anomalies.append(anomaly_entity) else: anomalies = requested_anomalies return anomalies, extra_columns
def GetAlertsForKeys(keys): """Get alerts for |keys|. Query for anomalies with overlapping revision. The |keys| parameter for group_report is a comma-separated list of urlsafe strings for Keys for Anomaly entities. (Each key corresponds to an alert) Args: keys: Comma-separated list of urlsafe strings for Anomaly keys. Returns: list of anomaly.Anomaly """ urlsafe_keys = keys try: keys = [ndb.Key(urlsafe=k) for k in urlsafe_keys] # Errors that can be thrown here include ProtocolBufferDecodeError # in google.net.proto.ProtocolBuffer. We want to catch any errors here # because they're almost certainly urlsafe key decoding errors. except Exception: raise request_handler.InvalidInputError('Invalid Anomaly key given.') requested_anomalies = utils.GetMulti(keys) for i, anomaly_entity in enumerate(requested_anomalies): if anomaly_entity is None: raise request_handler.InvalidInputError( 'No Anomaly found for key %s.' % urlsafe_keys[i]) if not requested_anomalies: raise request_handler.InvalidInputError('No anomalies found.') # Just an optimization because we can't fetch anomalies directly based # on revisions. Apply some filters to reduce unrelated anomalies. subscriptions = [] for anomaly_entity in requested_anomalies: subscriptions.extend(anomaly_entity.subscription_names) subscriptions = list(set(subscriptions)) min_range = utils.MinimumAlertRange(requested_anomalies) if min_range: anomalies, _, _ = anomaly.Anomaly.QueryAsync( subscriptions=subscriptions, limit=_QUERY_LIMIT).get_result() # Filter out anomalies that have been marked as invalid or ignore. # Include all anomalies with an overlapping revision range that have # been associated with a bug, or are not yet triaged. requested_anomalies_set = set([a.key for a in requested_anomalies]) def _IsValidAlert(a): if a.key in requested_anomalies_set: return False return a.bug_id is None or a.bug_id > 0 anomalies = [a for a in anomalies if _IsValidAlert(a)] anomalies = _GetOverlaps(anomalies, min_range[0], min_range[1]) anomalies = requested_anomalies + anomalies else: anomalies = requested_anomalies return anomalies
def GetAlertsForKeys(keys): """Get alerts for |keys|. Query for anomalies with overlapping revision. The |keys| parameter for group_report is a comma-separated list of urlsafe strings for Keys for Anomaly entities. (Each key corresponds to an alert) Args: keys: Comma-separated list of urlsafe strings for Anomaly keys. Returns: list of anomaly.Anomaly """ urlsafe_keys = keys try: keys = [ndb.Key(urlsafe=k) for k in urlsafe_keys] # Errors that can be thrown here include ProtocolBufferDecodeError # in google.net.proto.ProtocolBuffer. We want to catch any errors here # because they're almost certainly urlsafe key decoding errors. except Exception: raise request_handler.InvalidInputError('Invalid Anomaly key given.') requested_anomalies = utils.GetMulti(keys) for i, anomaly_entity in enumerate(requested_anomalies): if anomaly_entity is None: raise request_handler.InvalidInputError( 'No Anomaly found for key %s.' % urlsafe_keys[i]) if not requested_anomalies: raise request_handler.InvalidInputError('No anomalies found.') sheriff_key = requested_anomalies[0].sheriff min_range = utils.MinimumAlertRange(requested_anomalies) if min_range: query = anomaly.Anomaly.query(anomaly.Anomaly.sheriff == sheriff_key) query = query.order(-anomaly.Anomaly.timestamp) anomalies = query.fetch(limit=_QUERY_LIMIT) # Filter out anomalies that have been marked as invalid or ignore. # Include all anomalies with an overlapping revision range that have # been associated with a bug, or are not yet triaged. requested_anomalies_set = set([a.key for a in requested_anomalies]) def _IsValidAlert(a): if a.key in requested_anomalies_set: return False return a.bug_id is None or a.bug_id > 0 anomalies = [a for a in anomalies if _IsValidAlert(a)] anomalies = _GetOverlaps(anomalies, min_range[0], min_range[1]) # Make sure alerts in specified param "keys" are included. # We actually only send the first _DISPLAY_LIMIT alerts to the UI, so we # need to include those keys at the start of the list. anomalies = requested_anomalies + anomalies else: anomalies = requested_anomalies return anomalies
def testGetMulti_AllExternalEntities_ReturnsAllEntities(self): keys = self._PutEntitiesAllExternal() self.SetCurrentUser('*****@*****.**') self.assertEqual(len(keys), len(utils.GetMulti(keys)))
def testGetMulti_ExternalUser_ReturnsSomeEntities(self): keys = self._PutEntitiesHalfInternal() self.SetCurrentUser('*****@*****.**') self.assertEqual(len(keys) / 2, len(utils.GetMulti(keys)))
def _GetKeyToTestDict(anomalies): """Returns a map of TestMetadata keys to entities for the given anomalies.""" test_keys = {a.GetTestMetadataKey() for a in anomalies} tests = utils.GetMulti(test_keys) return {t.key: t for t in tests}