Example #1
0
    def test_logs_differences(self):
        logger = logging.getLogger("sentry.eventstore")

        with mock.patch.object(logger, "info") as mock_logger:
            # No differences to log
            filter = eventstore.Filter(project_ids=[self.project.id])
            eventstore.get_events(filter=filter)
            eventstore.get_event_by_id(self.project.id, "a" * 32)
            assert mock_logger.call_count == 0

            # Here we expect a difference since the original implementation handles type as a tag
            event = eventstore.get_event_by_id(self.project.id, "a" * 32)
            filter = eventstore.Filter(
                project_ids=[self.project.id],
                conditions=[["type", "=", "transaction"]])
            eventstore.get_next_event_id(event, filter)
            assert mock_logger.call_count == 1
            mock_logger.assert_called_with(
                "discover.result-mismatch",
                extra={
                    "snuba_result":
                    None,
                    "snuba_discover_result":
                    (six.text_type(self.project.id), "b" * 32),
                    "method":
                    "get_next_event_id",
                    "event_id":
                    event.event_id,
                    "filter_keys":
                    filter.filter_keys,
                    "conditions":
                    filter.conditions,
                },
            )
Example #2
0
def get_pagination_ids(event,
                       query,
                       params,
                       organization,
                       reference_event=None,
                       referrer=None):
    """
    High-level API for getting pagination data for an event + filter

    The provided event is used as a reference event to find events
    that are older and newer than the current one.

    event (Event) The event to find related events for.
    query (str) Filter query string to create conditions from.
    params (Dict[str, str]) Filtering parameters with start, end, project_id, environment,
    reference_event (ReferenceEvent) A reference event object. Used to generate additional
                                    conditions based on the provided reference.
    referrer (str|None) A referrer string to help locate the origin of this query.
    """
    snuba_filter = get_filter(query, params)

    if reference_event:
        ref_conditions = create_reference_event_conditions(reference_event)
        if ref_conditions:
            snuba_filter.conditions.extend(ref_conditions)

    result = {
        "next": eventstore.get_next_event_id(event, filter=snuba_filter),
        "previous": eventstore.get_prev_event_id(event, filter=snuba_filter),
        "latest": eventstore.get_latest_event_id(event, filter=snuba_filter),
        "oldest": eventstore.get_earliest_event_id(event, filter=snuba_filter),
    }

    # translate project ids to slugs

    project_ids = set([tuple[0] for tuple in result.values() if tuple])

    project_slugs = {}
    projects = Project.objects.filter(id__in=list(project_ids),
                                      organization=organization,
                                      status=ProjectStatus.VISIBLE).values(
                                          "id", "slug")

    for project in projects:
        project_slugs[project["id"]] = project["slug"]

    def into_pagination_record(project_slug_event_id):

        if not project_slug_event_id:
            return None

        project_id = int(project_slug_event_id[0])

        return "{}:{}".format(project_slugs[project_id],
                              project_slug_event_id[1])

    for key, value in result.items():
        result[key] = into_pagination_record(value)

    return PaginationResult(**result)
Example #3
0
def get_pagination_ids(event,
                       query,
                       params,
                       reference_event=None,
                       referrer=None):
    """
    High-level API for getting pagination data for an event + filter

    The provided event is used as a reference event to find events
    that are older and newer than the current one.

    event (Event) The event to find related events for.
    query (str) Filter query string to create conditions from.
    params (Dict[str, str]) Filtering parameters with start, end, project_id, environment,
    reference_event (ReferenceEvent) A reference event object. Used to generate additional
                                    conditions based on the provided reference.
    referrer (str|None) A referrer string to help locate the origin of this query.
    """
    snuba_filter = get_filter(query, params)

    if reference_event:
        ref_conditions = create_reference_event_conditions(reference_event)
        if ref_conditions:
            snuba_filter.conditions.extend(ref_conditions)

    return PaginationResult(
        next=get_id(eventstore.get_next_event_id(event, filter=snuba_filter)),
        previous=get_id(
            eventstore.get_prev_event_id(event, filter=snuba_filter)),
        latest=get_id(
            eventstore.get_latest_event_id(event, filter=snuba_filter)),
        oldest=get_id(
            eventstore.get_earliest_event_id(event, filter=snuba_filter)),
    )
    def get(self, request, project, event_id):
        """
        Retrieve an Event for a Project
        ```````````````````````````````

        Return details on an individual event.

        :pparam string organization_slug: the slug of the organization the
                                          event belongs to.
        :pparam string project_slug: the slug of the project the event
                                     belongs to.
        :pparam string event_id: the id of the event to retrieve (either the
                                 numeric primary-key or the hexadecimal id as
                                 reported by the raven client)
        :auth: required
        """

        event = eventstore.get_event_by_id(project.id, event_id)

        if event is None:
            return Response({"detail": "Event not found"}, status=404)

        data = serialize(event, request.user, DetailedEventSerializer())

        # Used for paginating through events of a single issue in group details
        # Skip next/prev for issueless events
        next_event_id = None
        prev_event_id = None

        if event.group_id:
            requested_environments = set(request.GET.getlist("environment"))
            conditions = [["event.type", "!=", "transaction"]]

            if requested_environments:
                conditions.append(
                    ["environment", "IN", requested_environments])

            _filter = eventstore.Filter(conditions=conditions,
                                        project_ids=[event.project_id],
                                        group_ids=[event.group_id])

            # Ignore any time params and search entire retention period
            next_event_filter = deepcopy(_filter)
            next_event_filter.end = datetime.utcnow()
            next_event = eventstore.get_next_event_id(event,
                                                      filter=next_event_filter)

            prev_event_filter = deepcopy(_filter)
            prev_event_filter.start = datetime.utcfromtimestamp(0)
            prev_event = eventstore.get_prev_event_id(event,
                                                      filter=prev_event_filter)

            next_event_id = next_event[1] if next_event else None
            prev_event_id = prev_event[1] if prev_event else None

        data["nextEventID"] = next_event_id
        data["previousEventID"] = prev_event_id

        return Response(data)
    def next_event_id(self, snuba_args, event):
        """
        Returns the next event ID if there is a subsequent event matching the
        conditions provided. Ignores the project_id.
        """
        next_event = eventstore.get_next_event_id(event, filter=self._get_filter(snuba_args))

        if next_event:
            return next_event[1]
    def get(self, request, project, event_id):
        """
        Retrieve an Event for a Project
        ```````````````````````````````

        Return details on an individual event.

        :pparam string organization_slug: the slug of the organization the
                                          event belongs to.
        :pparam string project_slug: the slug of the project the event
                                     belongs to.
        :pparam string event_id: the id of the event to retrieve (either the
                                 numeric primary-key or the hexadecimal id as
                                 reported by the raven client)
        :auth: required
        """

        event = eventstore.get_event_by_id(project.id, event_id)

        if event is None:
            return Response({"detail": "Event not found"}, status=404)

        data = serialize(event, request.user, DetailedEventSerializer())

        # Used for paginating through events of a single issue in group details
        # Skip next/prev for issueless events
        next_event_id = None
        prev_event_id = None

        if event.group_id:
            requested_environments = set(request.GET.getlist("environment"))
            conditions = []

            if requested_environments:
                conditions.append(
                    ["environment", "IN", requested_environments])

            filter_keys = {
                "project_id": [event.project_id],
                "issue": [event.group_id]
            }

            next_event = eventstore.get_next_event_id(event,
                                                      conditions=conditions,
                                                      filter_keys=filter_keys)

            prev_event = eventstore.get_prev_event_id(event,
                                                      conditions=conditions,
                                                      filter_keys=filter_keys)

            next_event_id = next_event[1] if next_event else None
            prev_event_id = prev_event[1] if prev_event else None

        data["nextEventID"] = next_event_id
        data["previousEventID"] = prev_event_id

        return Response(data)
Example #7
0
    def next_event_id(self, request, organization, snuba_args, event):
        """
        Returns the next event ID if there is a subsequent event matching the
        conditions provided. Ignores the project_id.
        """
        next_event = eventstore.get_next_event_id(
            event,
            conditions=snuba_args["conditions"],
            filter_keys=snuba_args["filter_keys"])

        if next_event:
            return next_event[1]
Example #8
0
    def next_event_id(self, snuba_args, event):
        """
        Returns the next event ID if there is a subsequent event matching the
        conditions provided. Ignores the project_id.
        """
        conditions = self._apply_start_and_end(snuba_args)
        next_event = eventstore.get_next_event_id(
            event,
            conditions=conditions,
            filter_keys=snuba_args["filter_keys"])

        if next_event:
            return next_event[1]
    def get(self, request, organization, project_slug, event_id):
        if not features.has(
                "organizations:events-v2", organization, actor=request.user):
            return Response(status=404)

        try:
            params = self.get_filter_params(request, organization)
            snuba_args = self.get_snuba_query_args(request, organization,
                                                   params)
        except OrganizationEventsError as exc:
            return Response({"detail": exc.message}, status=400)
        except NoProjects:
            return Response(status=404)

        try:
            project = Project.objects.get(slug=project_slug,
                                          organization_id=organization.id)
        except Project.DoesNotExist:
            return Response(status=404)

        # We return the requested event if we find a match regardless of whether
        # it occurred within the range specified
        event = eventstore.get_event_by_id(project.id, event_id,
                                           eventstore.full_columns)

        if event is None:
            return Response({"detail": "Event not found"}, status=404)

        # Scope the pagination related event ids to the current event
        # This ensure that if a field list/groupby conditions were provided
        # that we constrain related events to the query + current event values
        snuba_args["conditions"].extend(
            get_reference_event_conditions(snuba_args, event.snuba_data))
        next_event = eventstore.get_next_event_id(
            event,
            conditions=snuba_args["conditions"],
            filter_keys=snuba_args["filter_keys"])
        prev_event = eventstore.get_prev_event_id(
            event,
            conditions=snuba_args["conditions"],
            filter_keys=snuba_args["filter_keys"])

        data = serialize(event)
        data["nextEventID"] = next_event[1] if next_event else None
        data["previousEventID"] = prev_event[1] if prev_event else None
        data["oldestEventID"] = self.oldest_event_id(snuba_args, event)
        data["latestEventID"] = self.latest_event_id(snuba_args, event)
        data["projectSlug"] = project_slug

        return Response(data)
Example #10
0
    def next_event_id(self, snuba_args, event):
        """
        Returns the next event ID if there is a subsequent event matching the
        conditions provided. Ignores the project_id.
        """
        conditions = copy(snuba_args["conditions"])
        if "start" in snuba_args:
            conditions.append(["timestamp", ">=", snuba_args["start"]])
        if "end" in snuba_args:
            conditions.append(["timestamp", "<=", snuba_args["end"]])
        next_event = eventstore.get_next_event_id(
            event,
            conditions=conditions,
            filter_keys=snuba_args["filter_keys"])

        if next_event:
            return next_event[1]
Example #11
0
    def get(self, request, organization, project_slug, event_id):
        if not features.has(
                'organizations:events-v2', organization, actor=request.user):
            return Response(status=404)

        try:
            params = self.get_filter_params(request, organization)
            snuba_args = self.get_snuba_query_args(request, organization,
                                                   params)
        except OrganizationEventsError as exc:
            return Response({'detail': exc.message}, status=400)
        except NoProjects:
            return Response(status=404)

        try:
            project = Project.objects.get(slug=project_slug,
                                          organization_id=organization.id)
        except Project.DoesNotExist:
            return Response(status=404)

        # We return the requested event if we find a match regardless of whether
        # it occurred within the range specified
        event = eventstore.get_event_by_id(project.id, event_id)

        if event is None:
            return Response({'detail': 'Event not found'}, status=404)

        next_event = eventstore.get_next_event_id(
            event,
            conditions=snuba_args['conditions'],
            filter_keys=snuba_args['filter_keys'])
        prev_event = eventstore.get_prev_event_id(
            event,
            conditions=snuba_args['conditions'],
            filter_keys=snuba_args['filter_keys'])

        data = serialize(event)
        data['nextEventID'] = next_event[1] if next_event else None
        data['previousEventID'] = prev_event[1] if prev_event else None

        data['projectSlug'] = project_slug

        return Response(data)