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)
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 prev_event_id(self, snuba_args, event): """ Returns the previous event ID if there is a previous event matching the conditions provided. Ignores the project_id. """ prev_event = eventstore.get_prev_event_id(event, filter=self._get_filter(snuba_args)) if prev_event: return prev_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)
def prev_event_id(self, request, organization, snuba_args, event): """ Returns the previous event ID if there is a previous event matching the conditions provided. Ignores the project_id. """ prev_event = eventstore.get_prev_event_id( event, conditions=snuba_args["conditions"], filter_keys=snuba_args["filter_keys"]) if prev_event: return prev_event[1]
def prev_event_id(self, snuba_args, event): """ Returns the previous event ID if there is a previous event matching the conditions provided. Ignores the project_id. """ conditions = self._apply_start_and_end(snuba_args) prev_event = eventstore.get_prev_event_id( event, conditions=conditions, filter_keys=snuba_args["filter_keys"]) if prev_event: return prev_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)
def prev_event_id(self, snuba_args, event): """ Returns the previous event ID if there is a previous 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"]]) prev_event = eventstore.get_prev_event_id( event, conditions=conditions, filter_keys=snuba_args["filter_keys"]) if prev_event: return prev_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) 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)