Example #1
0
def migrate_subscriptions(apps, schema_editor):
    QuerySubscription = apps.get_model("sentry", "QuerySubscription")
    AppSnubaQueryEventType = apps.get_model("sentry", "SnubaQueryEventType")

    for subscription in RangeQuerySetWrapperWithProgressBar(
            QuerySubscription.objects.select_related("snuba_query").all()):
        if subscription.subscription_id is not None:
            # The migration apps don't build this property, so manually set it.
            raw_event_types = AppSnubaQueryEventType.objects.filter(
                snuba_query=subscription.snuba_query).all()
            event_types = [
                SnubaQueryEventType.EventType(ev.type)
                for ev in raw_event_types
            ]
            setattr(subscription.snuba_query, "event_types", event_types)

            subscription_id = None
            try:
                subscription_id = _create_in_snuba(subscription)
            except Exception as e:
                logging.exception(
                    f"failed to recreate {subscription.subscription_id}: {e}")
                continue

            try:
                _delete_from_snuba(
                    QueryDatasets(subscription.snuba_query.dataset),
                    subscription.subscription_id,
                )
            except Exception as e:
                try:
                    # Delete the subscription we just created to avoid orphans
                    _delete_from_snuba(
                        QueryDatasets(subscription.snuba_query.dataset),
                        subscription_id,
                    )
                except Exception as oe:
                    logging.exception(
                        f"failed to delete orphan {subscription_id}: {oe}")

                logging.exception(
                    f"failed to delete {subscription.subscription_id}: {e}")
                continue

            QuerySubscription.objects.filter(id=subscription.id).update(
                subscription_id=subscription_id)
Example #2
0
def update_snuba_query(snuba_query, dataset, query, aggregate, time_window,
                       resolution, environment, event_types):
    """
    Updates a SnubaQuery. Triggers updates to any related QuerySubscriptions.

    :param snuba_query: The `SnubaQuery` to update.
    :param dataset: The snuba dataset to query and aggregate over
    :param query: An event search query that we can parse and convert into a
    set of Snuba conditions
    :param aggregate: An aggregate to calculate over the time window
    :param time_window: The time window to aggregate over
    :param resolution: How often to receive updates/bucket size
    :param environment: An optional environment to filter by
    :param event_types: A (currently) optional list of event_types that apply to this
    query. If not passed, we'll use the existing event types on the query.
    :return: A list of QuerySubscriptions
    """
    current_event_types = set(snuba_query.event_types)
    if not event_types:
        event_types = current_event_types

    new_event_types = set(event_types) - current_event_types
    removed_event_types = current_event_types - set(event_types)
    old_dataset = QueryDatasets(snuba_query.dataset)
    with transaction.atomic():
        query_subscriptions = list(snuba_query.subscriptions.all())
        snuba_query.update(
            dataset=dataset.value,
            query=query,
            aggregate=aggregate,
            time_window=int(time_window.total_seconds()),
            resolution=int(resolution.total_seconds()),
            environment=environment,
        )
        if new_event_types:
            SnubaQueryEventType.objects.bulk_create([
                SnubaQueryEventType(snuba_query=snuba_query,
                                    type=event_type.value)
                for event_type in set(new_event_types)
            ])
        if removed_event_types:
            SnubaQueryEventType.objects.filter(
                snuba_query=snuba_query,
                type__in=[et.value for et in removed_event_types]).delete()

        bulk_update_snuba_subscriptions(query_subscriptions, old_dataset)
Example #3
0
    def get_attrs(self, item_list, user, **kwargs):
        result = super().get_attrs(item_list, user, **kwargs)
        alert_rules = {item.id: item for item in item_list}
        for alert_rule_id, project_slug in AlertRuleExcludedProjects.objects.filter(
            alert_rule__in=item_list
        ).values_list("alert_rule_id", "project__slug"):
            exclusions = result[alert_rules[alert_rule_id]].setdefault("excluded_projects", [])
            exclusions.append(project_slug)

        query_to_alert_rule = {ar.snuba_query_id: ar for ar in item_list}

        for event_type in SnubaQueryEventType.objects.filter(
            snuba_query_id__in=[item.snuba_query_id for item in item_list]
        ):
            event_types = result[query_to_alert_rule[event_type.snuba_query_id]].setdefault(
                "event_types", []
            )
            event_types.append(SnubaQueryEventType.EventType(event_type.type).name.lower())

        return result
Example #4
0
def create_snuba_query(dataset,
                       query,
                       aggregate,
                       time_window,
                       resolution,
                       environment,
                       event_types=None):
    """
    Creates a SnubaQuery.

    :param dataset: The snuba dataset to query and aggregate over
    :param query: An event search query that we can parse and convert into a
    set of Snuba conditions
    :param aggregate: An aggregate to calculate over the time window
    :param time_window: The time window to aggregate over
    :param resolution: How often to receive updates/bucket size
    :param environment: An optional environment to filter by
    :param event_types: A (currently) optional list of event_types that apply to this
    query. If not passed, we'll infer a default value based on the dataset.
    :return: A list of QuerySubscriptions
    """
    snuba_query = SnubaQuery.objects.create(
        dataset=dataset.value,
        query=query,
        aggregate=aggregate,
        time_window=int(time_window.total_seconds()),
        resolution=int(resolution.total_seconds()),
        environment=environment,
    )
    if not event_types:
        event_types = [
            SnubaQueryEventType.EventType.ERROR
            if dataset == QueryDatasets.EVENTS else
            SnubaQueryEventType.EventType.TRANSACTION
        ]
    sq_event_types = [
        SnubaQueryEventType(snuba_query=snuba_query, type=event_type.value)
        for event_type in set(event_types)
    ]
    SnubaQueryEventType.objects.bulk_create(sq_event_types)
    return snuba_query