Beispiel #1
0
    def _get_events_snuba(self, request, project):
        from sentry.api.paginator import GenericOffsetPaginator
        from sentry.models import SnubaEvent
        from sentry.utils.snuba import raw_query

        query = request.GET.get('query')
        conditions = []
        if query:
            conditions.append(
                [['positionCaseInsensitive', ['message',
                                              "'%s'" % (query, )]], '!=', 0])

        now = timezone.now()
        data_fn = partial(
            # extract 'data' from raw_query result
            lambda *args, **kwargs: raw_query(*args, **kwargs)['data'],
            start=now - timedelta(days=90),
            end=now,
            conditions=conditions,
            filter_keys={'project_id': [project.id]},
            selected_columns=SnubaEvent.minimal_columns,
            orderby='-timestamp',
            referrer='api.project-events',
        )

        return self.paginate(request=request,
                             on_results=lambda results: serialize(
                                 [SnubaEvent(row)
                                  for row in results], request.user),
                             paginator=GenericOffsetPaginator(data_fn=data_fn))
Beispiel #2
0
    def get_events(
        self,
        filter,
        additional_columns=None,
        orderby=None,
        limit=DEFAULT_LIMIT,
        offset=DEFAULT_OFFSET,
        referrer="eventstore.get_events",
    ):
        """
        Get events from Snuba.
        """
        assert filter, "You must provide a filter"
        cols = self.__get_columns(additional_columns)
        orderby = orderby or DESC_ORDERING

        result = snuba.dataset_query(
            selected_columns=cols,
            start=filter.start,
            end=filter.end,
            conditions=filter.conditions,
            filter_keys=filter.filter_keys,
            orderby=orderby,
            limit=limit,
            offset=offset,
            referrer=referrer,
        )

        if "error" not in result:
            return [SnubaEvent(evt) for evt in result["data"]]

        return []
Beispiel #3
0
def get_oldest_or_latest_event_for_environments(ordering,
                                                environments=[],
                                                issue_id=None,
                                                project_id=None):
    from sentry.utils import snuba
    from sentry.models import SnubaEvent

    conditions = []

    if len(environments) > 0:
        conditions.append(['environment', 'IN', environments])

    result = snuba.raw_query(
        start=datetime.utcfromtimestamp(0),
        end=datetime.utcnow(),
        selected_columns=SnubaEvent.selected_columns,
        conditions=conditions,
        filter_keys={
            'issue': [issue_id],
            'project_id': [project_id],
        },
        orderby=ordering.value,
        limit=1,
    )

    if 'error' not in result and len(result['data']) == 1:
        return SnubaEvent(result['data'][0])

    return None
Beispiel #4
0
def get_oldest_or_latest_event_for_environments(ordering,
                                                environments=(),
                                                issue_id=None,
                                                project_id=None):
    from sentry.utils import snuba
    from sentry.models import SnubaEvent

    conditions = []

    if len(environments) > 0:
        conditions.append(["environment", "IN", environments])

    result = snuba.raw_query(
        selected_columns=SnubaEvent.selected_columns,
        conditions=conditions,
        filter_keys={
            "issue": [issue_id],
            "project_id": [project_id]
        },
        orderby=ordering.value,
        limit=1,
        referrer="Group.get_latest",
    )

    if "error" not in result and len(result["data"]) == 1:
        return SnubaEvent(result["data"][0])

    return None
Beispiel #5
0
    def get_events(
        self,
        start=None,
        end=None,
        additional_columns=None,
        conditions=None,
        filter_keys=None,
        orderby=DEFAULT_ORDERBY,
        limit=DEFAULT_LIMIT,
        offset=DEFAULT_OFFSET,
    ):
        """
        Get events from Snuba.
        """
        cols = self.__get_columns(additional_columns)

        result = snuba.raw_query(
            start=start,
            end=end,
            selected_columns=cols,
            conditions=conditions,
            filter_keys=filter_keys,
            orderby=orderby,
            limit=limit,
            offset=offset,
            referrer='eventstore.get_events',
        )

        if 'error' not in result:
            return [SnubaEvent(evt) for evt in result['data']]

        return []
Beispiel #6
0
    def get(self, request, organization):
        # Check for a direct hit on event ID
        query = request.GET.get('query', '').strip()
        if is_event_id(query):
            try:
                snuba_args = get_snuba_query_args(
                    query=u'id:{}'.format(query),
                    params=self.get_filter_params(request, organization))

                results = raw_query(
                    selected_columns=SnubaEvent.selected_columns,
                    referrer='api.organization-events',
                    **snuba_args)['data']

                if len(results) == 1:
                    response = Response(
                        serialize([SnubaEvent(row) for row in results],
                                  request.user))
                    response['X-Sentry-Direct-Hit'] = '1'
                    return response
            except (OrganizationEventsError, NoProjects):
                pass

        try:
            snuba_args = self.get_snuba_query_args(request, organization)
        except OrganizationEventsError as exc:
            return Response({'detail': exc.message}, status=400)
        except NoProjects:
            # return empty result if org doesn't have projects
            # or user doesn't have access to projects in org
            data_fn = lambda *args, **kwargs: []
        else:
            data_fn = partial(
                # extract 'data' from raw_query result
                lambda *args, **kwargs: raw_query(*args, **kwargs)['data'],
                selected_columns=SnubaEvent.selected_columns,
                orderby='-timestamp',
                referrer='api.organization-events',
                **snuba_args)

        serializer = SimpleEventSerializer()
        return self.paginate(
            request=request,
            on_results=lambda results: serialize(
                [SnubaEvent(row)
                 for row in results], request.user, serializer),
            paginator=GenericOffsetPaginator(data_fn=data_fn))
Beispiel #7
0
    def get_event_by_id(self, project_id, event_id, additional_columns=None):
        """
        Get an event given a project ID and event ID
        Returns None if an event cannot be found
        """
        cols = self.__get_columns(additional_columns)

        return SnubaEvent.get_event(project_id, event_id, snuba_cols=cols)
    def get(self, latest_or_oldest, request, organization):
        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)

        if latest_or_oldest == EventOrdering.LATEST:
            orderby = ["-timestamp", "-event_id"]
        else:
            orderby = ["timestamp", "event_id"]

        result = raw_query(
            start=snuba_args["start"],
            end=snuba_args["end"],
            selected_columns=SnubaEvent.selected_columns,
            conditions=snuba_args["conditions"],
            filter_keys=snuba_args["filter_keys"],
            orderby=orderby,
            limit=2,
            referrer="api.organization-event-details-latest-or-oldest",
        )

        if "error" in result or len(result["data"]) == 0:
            return Response({"detail": "Event not found"}, status=404)

        try:
            project_id = result["data"][0]["project_id"]
            project_slug = Project.objects.get(organization=organization,
                                               id=project_id).slug
        except Project.DoesNotExist:
            project_slug = None

        data = serialize(SnubaEvent(result["data"][0]))
        data["previousEventID"] = None
        data["nextEventID"] = None
        data["projectSlug"] = project_slug

        if latest_or_oldest == EventOrdering.LATEST and len(
                result["data"]) == 2:
            data["previousEventID"] = six.text_type(
                result["data"][1]["event_id"])

        if latest_or_oldest == EventOrdering.OLDEST and len(
                result["data"]) == 2:
            data["nextEventID"] = six.text_type(result["data"][1]["event_id"])

        return Response(data)
Beispiel #9
0
    def get(self, latest_or_oldest, request, organization):
        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)

        if latest_or_oldest == EventOrdering.LATEST:
            orderby = ['-timestamp', '-event_id']
        else:
            orderby = ['timestamp', 'event_id']

        result = raw_query(
            start=snuba_args['start'],
            end=snuba_args['end'],
            selected_columns=SnubaEvent.selected_columns,
            conditions=snuba_args['conditions'],
            filter_keys=snuba_args['filter_keys'],
            orderby=orderby,
            limit=2,
            referrer='api.organization-event-details-latest-or-oldest',
        )

        if 'error' in result or len(result['data']) == 0:
            return Response({'detail': 'Event not found'}, status=404)

        try:
            project_id = result['data'][0]['project_id']
            project_slug = Project.objects.get(organization=organization,
                                               id=project_id).slug
        except Project.DoesNotExist:
            project_slug = None

        data = serialize(SnubaEvent(result['data'][0]))
        data['previousEventID'] = None
        data['nextEventID'] = None
        data['projectSlug'] = project_slug

        if latest_or_oldest == EventOrdering.LATEST and len(
                result['data']) == 2:
            data['previousEventID'] = six.text_type(
                result['data'][1]['event_id'])

        if latest_or_oldest == EventOrdering.OLDEST and len(
                result['data']) == 2:
            data['nextEventID'] = six.text_type(result['data'][1]['event_id'])

        return Response(data)
Beispiel #10
0
    def __handle_result(self, user, project_id, group_id, result):
        event = {
            'timestamp': result['latest_event_timestamp'],
            'event_id': result['event_id'],
            'group_id': group_id,
            'project_id': project_id
        }

        return {
            'id': result['primary_hash'],
            'latestEvent': serialize(SnubaEvent(event), user, EventSerializer())
        }
Beispiel #11
0
    def __handle_result(self, user, project_id, group_id, result):
        event = {
            "timestamp": result["latest_event_timestamp"],
            "event_id": result["event_id"],
            "group_id": group_id,
            "project_id": project_id,
        }

        return {
            "id": result["primary_hash"],
            "latestEvent": serialize(SnubaEvent(event), user,
                                     EventSerializer()),
        }
Beispiel #12
0
    def _get_events_snuba(self, request, group, environments, query, tags,
                          start, end):
        default_end = timezone.now()
        default_start = default_end - timedelta(days=90)
        params = {
            'issue.id': [group.id],
            'project_id': [group.project_id],
            'start': start if start else default_start,
            'end': end if end else default_end
        }
        direct_hit_resp = get_direct_hit_response(request, query, params,
                                                  'api.group-events')
        if direct_hit_resp:
            return direct_hit_resp

        if environments:
            params['environment'] = [env.name for env in environments]

        full = request.GET.get('full', False)
        snuba_args = get_snuba_query_args(request.GET.get('query', None),
                                          params)

        # TODO(lb): remove once boolean search is fully functional
        if snuba_args:
            has_boolean_op_flag = features.has('organizations:boolean-search',
                                               group.project.organization,
                                               actor=request.user)
            if snuba_args.pop('has_boolean_terms',
                              False) and not has_boolean_op_flag:
                raise GroupEventsError(
                    'Boolean search operator OR and AND not allowed in this search.'
                )

        snuba_cols = SnubaEvent.minimal_columns if full else SnubaEvent.selected_columns

        data_fn = partial(
            # extract 'data' from raw_query result
            lambda *args, **kwargs: raw_query(*args, **kwargs)['data'],
            selected_columns=snuba_cols,
            orderby='-timestamp',
            referrer='api.group-events',
            **snuba_args)

        serializer = EventSerializer() if full else SimpleEventSerializer()
        return self.paginate(
            request=request,
            on_results=lambda results: serialize(
                [SnubaEvent(row)
                 for row in results], request.user, serializer),
            paginator=GenericOffsetPaginator(data_fn=data_fn))
Beispiel #13
0
    def get(self, request, organization):
        if features.has('organizations:events-v2', organization, actor=request.user):
            return self.get_v2(request, organization)

        # Check for a direct hit on event ID
        query = request.GET.get('query', '').strip()

        try:
            direct_hit_resp = get_direct_hit_response(
                request,
                query,
                self.get_filter_params(request, organization),
                'api.organization-events'
            )
        except (OrganizationEventsError, NoProjects):
            pass
        else:
            if direct_hit_resp:
                return direct_hit_resp

        full = request.GET.get('full', False)
        try:
            snuba_args = self.get_snuba_query_args(request, organization)
        except OrganizationEventsError as exc:
            return Response({'detail': exc.message}, status=400)
        except NoProjects:
            # return empty result if org doesn't have projects
            # or user doesn't have access to projects in org
            data_fn = lambda *args, **kwargs: []
        else:
            snuba_cols = SnubaEvent.minimal_columns if full else SnubaEvent.selected_columns
            data_fn = partial(
                # extract 'data' from raw_query result
                lambda *args, **kwargs: raw_query(*args, **kwargs)['data'],
                selected_columns=snuba_cols,
                orderby='-timestamp',
                referrer='api.organization-events',
                **snuba_args
            )

        serializer = EventSerializer() if full else SimpleEventSerializer()
        return self.paginate(
            request=request,
            on_results=lambda results: serialize(
                [SnubaEvent(row) for row in results], request.user, serializer),
            paginator=GenericOffsetPaginator(data_fn=data_fn)
        )
Beispiel #14
0
    def get(self, request, project):
        """
        List a Project's Events
        ```````````````````````

        Return a list of events bound to a project.

        Note: This endpoint is experimental and may be removed without notice.

        :pparam string organization_slug: the slug of the organization the
                                          groups belong to.
        :pparam string project_slug: the slug of the project the groups
                                     belong to.
        """
        from sentry.api.paginator import GenericOffsetPaginator
        from sentry.models import SnubaEvent
        from sentry.utils.snuba import raw_query

        query = request.GET.get('query')
        conditions = []
        if query:
            conditions.append(
                [['positionCaseInsensitive', ['message',
                                              "'%s'" % (query, )]], '!=', 0])

        full = request.GET.get('full', False)
        snuba_cols = SnubaEvent.minimal_columns if full else SnubaEvent.selected_columns
        now = timezone.now()
        data_fn = partial(
            # extract 'data' from raw_query result
            lambda *args, **kwargs: raw_query(*args, **kwargs)['data'],
            start=now - timedelta(days=90),
            end=now,
            conditions=conditions,
            filter_keys={'project_id': [project.id]},
            selected_columns=snuba_cols,
            orderby='-timestamp',
            referrer='api.project-events',
        )

        serializer = EventSerializer() if full else SimpleEventSerializer()
        return self.paginate(
            request=request,
            on_results=lambda results: serialize(
                [SnubaEvent(row)
                 for row in results], request.user, serializer),
            paginator=GenericOffsetPaginator(data_fn=data_fn))
Beispiel #15
0
    def _get_events_snuba(self, request, group, environments, query, tags,
                          start, end):
        conditions = []
        if query:
            msg_substr = [
                'positionCaseInsensitive', ['message',
                                            "'%s'" % (query, )]
            ]
            message_condition = [msg_substr, '!=', 0]
            if is_event_id(query):
                or_condition = [message_condition, ['event_id', '=', query]]
                conditions.append(or_condition)
            else:
                conditions.append(message_condition)

        if tags:
            for tag_name, tag_val in tags.items():
                operator = 'IN' if isinstance(tag_val, list) else '='
                conditions.append(
                    [u'tags[{}]'.format(tag_name), operator, tag_val])

        default_end = timezone.now()
        default_start = default_end - timedelta(days=90)

        data_fn = partial(
            # extract 'data' from raw_query result
            lambda *args, **kwargs: raw_query(*args, **kwargs)['data'],
            start=max(start, default_start) if start else default_start,
            end=min(end, default_end) if end else default_end,
            conditions=conditions,
            filter_keys={
                'project_id': [group.project_id],
                'issue': [group.id]
            },
            selected_columns=SnubaEvent.selected_columns,
            orderby='-timestamp',
            referrer='api.group-events',
        )

        serializer = SimpleEventSerializer()
        return self.paginate(
            request=request,
            on_results=lambda results: serialize(
                [SnubaEvent(row)
                 for row in results], request.user, serializer),
            paginator=GenericOffsetPaginator(data_fn=data_fn))
Beispiel #16
0
    def get(self, request):
        org = Organization(id=1, slug="organization", name="My Company")
        project = Project(id=1,
                          organization=org,
                          slug="project",
                          name="My Project")

        group = next(make_group_generator(get_random(request), project))

        data = dict(load_data("python"))
        data["message"] = group.message
        data.pop("logentry", None)

        event_manager = EventManager(data)
        event_manager.normalize()
        data = event_manager.get_data()
        event_type = event_manager.get_event_type()

        group.message = event_manager.get_search_message()
        group.data = {
            "type": event_type.key,
            "metadata": event_type.get_metadata(data)
        }

        event = SnubaEvent({
            "event_id": "a" * 32,
            "project_id": project.id,
            "group_id": group.id,
            "message": event_manager.get_search_message(),
            "data": data.data,
            "timestamp": data["timestamp"],
        })

        activity = Activity(group=group,
                            project=event.project,
                            **self.get_activity(request, event))

        return render_to_response(
            "sentry/debug/mail/preview.html",
            context={
                "preview": ActivityMailPreview(request, activity),
                "format": request.GET.get("format"),
            },
        )
Beispiel #17
0
def get_direct_hit_response(request, query, snuba_params, referrer):
    """
    Checks whether a query is a direct hit for an event, and if so returns
    a response. Otherwise returns None
    """
    event_id = normalize_event_id(query)
    if event_id:
        snuba_args = get_snuba_query_args(query=u'id:{}'.format(event_id),
                                          params=snuba_params)

        results = raw_query(selected_columns=SnubaEvent.selected_columns,
                            referrer=referrer,
                            **snuba_args)['data']

        if len(results) == 1:
            response = Response(
                serialize([SnubaEvent(row) for row in results], request.user))
            response['X-Sentry-Direct-Hit'] = '1'
            return response
Beispiel #18
0
    def get_event_by_id(self, project_id, event_id, additional_columns=None):
        """
        Get an event given a project ID and event ID
        Returns None if an event cannot be found
        """
        cols = self.__get_columns(additional_columns)

        event_id = normalize_event_id(event_id)

        if not event_id:
            return None

        result = snuba.raw_query(
            selected_columns=cols,
            filter_keys={"event_id": [event_id], "project_id": [project_id]},
            referrer="eventstore.get_event_by_id",
            limit=1,
        )
        if "error" not in result and len(result["data"]) == 1:
            return SnubaEvent(result["data"][0])
        return None
Beispiel #19
0
    def _get_events_snuba(self, request, group, environments, query, tags,
                          start, end):
        default_end = timezone.now()
        default_start = default_end - timedelta(days=90)
        params = {
            'issue.id': [group.id],
            'project_id': [group.project_id],
            'start': start if start else default_start,
            'end': end if end else default_end
        }
        direct_hit_resp = get_direct_hit_response(request, query, params,
                                                  'api.group-events')
        if direct_hit_resp:
            return direct_hit_resp

        if environments:
            params['environment'] = [env.name for env in environments]

        full = request.GET.get('full', False)
        snuba_args = get_snuba_query_args(request.GET.get('query', None),
                                          params)
        snuba_cols = SnubaEvent.minimal_columns if full else SnubaEvent.selected_columns

        data_fn = partial(
            # extract 'data' from raw_query result
            lambda *args, **kwargs: raw_query(*args, **kwargs)['data'],
            selected_columns=snuba_cols,
            orderby='-timestamp',
            referrer='api.group-events',
            **snuba_args)

        serializer = EventSerializer() if full else SimpleEventSerializer()
        return self.paginate(
            request=request,
            on_results=lambda results: serialize(
                [SnubaEvent(row)
                 for row in results], request.user, serializer),
            paginator=GenericOffsetPaginator(data_fn=data_fn))
Beispiel #20
0
    def from_event_id(self, id_or_event_id, project_id):
        """
        Get a SnubaEvent by either its id primary key or its hex event_id.

        Returns None if the event cannot be found under either scheme.

        Log any attempt to fetch a SnubaEvent by primary key and eventually remove.
        """
        from sentry.models import SnubaEvent, Event

        if not is_event_id(id_or_event_id):
            logger.warning('Attempt to fetch SnubaEvent by primary key', exc_info=True, extra={
                'stack': True
            })

            event = Event.objects.from_event_id(id_or_event_id, project_id)

            if not event:
                return None

            id_or_event_id = event.event_id

        return SnubaEvent.get_event(project_id, id_or_event_id)
Beispiel #21
0
    def from_event_id(self, id_or_event_id, project_id):
        """
        Get a SnubaEvent by either its id primary key or its hex event_id.

        Returns None if the event cannot be found under either scheme.

        Log any attempt to fetch a SnubaEvent by primary key and eventually remove.
        """
        from sentry.models import SnubaEvent, Event

        if not is_event_id(id_or_event_id):
            logger.warning('Attempt to fetch SnubaEvent by primary key',
                           exc_info=True,
                           extra={'stack': True})

            event = Event.objects.from_event_id(id_or_event_id, project_id)

            if not event:
                return None

            id_or_event_id = event.event_id

        return SnubaEvent.get_event(project_id, id_or_event_id)
Beispiel #22
0
def digest(request):
    random = get_random(request)

    # TODO: Refactor all of these into something more manageable.
    org = Organization(id=1, slug="example", name="Example Organization")

    project = Project(id=1,
                      slug="example",
                      name="Example Project",
                      organization=org)

    rules = {
        i: Rule(id=i, project=project, label="Rule #%s" % (i, ))
        for i in range(1, random.randint(2, 4))
    }

    state = {
        "project": project,
        "groups": {},
        "rules": rules,
        "event_counts": {},
        "user_counts": {},
    }

    records = []

    group_generator = make_group_generator(random, project)

    for i in range(random.randint(1, 30)):
        group = next(group_generator)
        state["groups"][group.id] = group

        offset = timedelta(seconds=0)
        for i in range(random.randint(1, 10)):
            offset += timedelta(seconds=random.random() * 120)

            data = dict(load_data("python"))
            data["message"] = group.message
            data.pop("logentry", None)

            event_manager = EventManager(data)
            event_manager.normalize()
            data = event_manager.get_data()

            timestamp = to_datetime(
                random.randint(to_timestamp(group.first_seen),
                               to_timestamp(group.last_seen)))

            event = SnubaEvent({
                "event_id":
                uuid.uuid4().hex,
                "project_id":
                project.id,
                "group_id":
                group.id,
                "message":
                group.message,
                "data":
                data.data,
                "timestamp":
                timestamp.strftime("%Y-%m-%dT%H:%M:%S"),
            })
            event.group = group

            records.append(
                Record(
                    event.event_id,
                    Notification(
                        event,
                        random.sample(state["rules"],
                                      random.randint(1, len(state["rules"])))),
                    to_timestamp(event.datetime),
                ))

            state["event_counts"][group.id] = random.randint(10, 1e4)
            state["user_counts"][group.id] = random.randint(10, 1e4)

    digest = build_digest(project, records, state)
    start, end, counts = get_digest_metadata(digest)

    context = {
        "project": project,
        "counts": counts,
        "digest": digest,
        "start": start,
        "end": end,
        "referrer": "digest_email",
    }
    add_unsubscribe_link(context)

    return MailPreview(
        html_template="sentry/emails/digests/body.html",
        text_template="sentry/emails/digests/body.txt",
        context=context,
    ).render(request)