def _build_query_params_from_request(self, request, project): query_kwargs = { 'project': project, 'sort_by': request.GET.get('sort', DEFAULT_SORT_OPTION), } limit = request.GET.get('limit') if limit: try: query_kwargs['limit'] = int(limit) except ValueError: raise ValidationError('invalid limit') # TODO: proper pagination support cursor = request.GET.get('cursor') if cursor: query_kwargs['cursor'] = Cursor.from_string(cursor) query = request.GET.get('query', 'is:unresolved').strip() if query: try: query_kwargs.update(parse_query(project, query, request.user)) except InvalidQuery as e: raise ValidationError( u'Your search query could not be parsed: {}'.format( e.message) ) return query_kwargs
def _get_search_query_and_tags(self, request, group, environments=None): raw_query = request.GET.get("query") if raw_query: query_kwargs = parse_query([group.project], raw_query, request.user, environments) query = query_kwargs.pop("query", None) tags = query_kwargs.pop("tags", {}) else: query = None tags = {} if environments: env_names = set(env.name for env in environments) if "environment" in tags: # If a single environment was passed as part of the query, then # we'll just search for that individual environment in this # query, even if more are selected. if tags["environment"] not in env_names: # An event can only be associated with a single # environment, so if the environments associated with # the request don't contain the environment provided as a # tag lookup, the query cannot contain any valid results. raise NoResults else: # XXX: Handle legacy backends here. Just store environment as a # single tag if we only have one so that we don't break existing # usage. tags["environment"] = list( env_names) if len(env_names) > 1 else env_names.pop() return query, tags
def get(self, request, group): """ List an Issue's Events `````````````````````` This endpoint lists an issue's events. :pparam string issue_id: the ID of the issue to retrieve. :auth: required """ events = Event.objects.filter(group_id=group.id, ) query = request.GET.get('query') if query: query_kwargs = parse_query(group.project, query, request.user) if query_kwargs['query']: events = events.filter( message__icontains=query_kwargs['query'], ) if query_kwargs['tags']: events = events.filter(id__in=self._tags_to_filter( group, query_kwargs['tags']), ) return self.paginate( request=request, queryset=events, order_by='-datetime', on_results=lambda x: serialize(x, request.user), paginator_cls=DateTimePaginator, )
def _build_query_params_from_request(self, request, project): query_kwargs = { 'project': project, 'sort_by': request.GET.get('sort', DEFAULT_SORT_OPTION), } limit = request.GET.get('limit') if limit: try: query_kwargs['limit'] = int(limit) except ValueError: raise ValidationError('invalid limit') # TODO: proper pagination support cursor = request.GET.get('cursor') if cursor: query_kwargs['cursor'] = Cursor.from_string(cursor) query = request.GET.get('query', 'is:unresolved').strip() if query: try: query_kwargs.update(parse_query(project, query, request.user)) except InvalidQuery as e: raise ValidationError( u'Your search query could not be parsed: {}'.format( e.message)) return query_kwargs
def test_is_resolved(self): result = parse_query('is:resolved', self.user) assert result == { 'status': GroupStatus.RESOLVED, 'tags': {}, 'query': '' }
def _get_search_query_and_tags(self, request, group, environments=None): raw_query = request.GET.get('query') if raw_query: query_kwargs = parse_query([group.project], raw_query, request.user, environments) query = query_kwargs.pop('query', None) tags = query_kwargs.pop('tags', {}) else: query = None tags = {} if environments: env_names = set(env.name for env in environments) if 'environment' in tags: # If a single environment was passed as part of the query, then # we'll just search for that individual environment in this # query, even if more are selected. if tags['environment'] not in env_names: # An event can only be associated with a single # environment, so if the environments associated with # the request don't contain the environment provided as a # tag lookup, the query cannot contain any valid results. raise NoResults else: # XXX: Handle legacy backends here. Just store environment as a # single tag if we only have one so that we don't break existing # usage. tags['environment'] = list(env_names) if len(env_names) > 1 else env_names.pop() return query, tags
def _get_search_query_and_tags(self, request, group, environment=None): raw_query = request.GET.get('query') if raw_query: query_kwargs = parse_query([group.project], raw_query, request.user) query = query_kwargs.pop('query', None) tags = query_kwargs.pop('tags', {}) else: query = None tags = {} if environment is not None: if 'environment' in tags and tags[ 'environment'] != environment.name: # An event can only be associated with a single # environment, so if the environment associated with # the request is different than the environment # provided as a tag lookup, the query cannot contain # any valid results. raise NoResults else: tags['environment'] = environment.name return query, tags
def get(self, request, group): """ List an Issue's Events `````````````````````` This endpoint lists an issue's events. :pparam string issue_id: the ID of the issue to retrieve. :auth: required """ events = Event.objects.filter(group_id=group.id) query = request.GET.get("query") if query: query_kwargs = parse_query(group.project, query, request.user) if query_kwargs["query"]: events = events.filter(message__icontains=query_kwargs["query"]) if query_kwargs["tags"]: events = events.filter(id__in=self._tags_to_filter(group, query_kwargs["tags"])) return self.paginate( request=request, queryset=events, order_by="-datetime", on_results=lambda x: serialize(x, request.user), paginator_cls=DateTimePaginator, )
def _get_search_query_and_tags(self, request): raw_query = request.GET.get('query') if raw_query: query_kwargs = parse_query(raw_query, request.user) query = query_kwargs.pop('query', None) tags = query_kwargs.pop('tags', {}) else: query = None tags = {} return query, tags
def _build_query_params_from_request(self, request, project): query_kwargs = { 'project': project, } if request.GET.get('status'): try: query_kwargs['status'] = STATUS_CHOICES[request.GET['status']] except KeyError: raise ValidationError('invalid status') if request.user.is_authenticated() and request.GET.get('bookmarks'): query_kwargs['bookmarked_by'] = request.user if request.user.is_authenticated() and request.GET.get('assigned'): query_kwargs['assigned_to'] = request.user sort_by = request.GET.get('sort') if sort_by is None: sort_by = DEFAULT_SORT_OPTION query_kwargs['sort_by'] = sort_by tags = {} for tag_key in TagKey.objects.all_keys(project): if request.GET.get(tag_key): tags[tag_key] = request.GET[tag_key] if tags: query_kwargs['tags'] = tags limit = request.GET.get('limit') if limit: try: query_kwargs['limit'] = int(limit) except ValueError: raise ValidationError('invalid limit') # TODO: proper pagination support cursor = request.GET.get('cursor') if cursor: query_kwargs['cursor'] = Cursor.from_string(cursor) query = request.GET.get('query', 'is:unresolved').strip() if query: try: query_kwargs.update(parse_query(project, query, request.user)) except InvalidQuery as e: raise ValidationError( u'Your search query could not be parsed: {}'.format( e.message) ) return query_kwargs
def get(self, request, group): """ List an Issue's Events `````````````````````` This endpoint lists an issue's events. :pparam string issue_id: the ID of the issue to retrieve. :auth: required """ events = Event.objects.filter(group_id=group.id, ) query = request.GET.get('query') if query: try: query_kwargs = parse_query(group.project, query, request.user) except InvalidQuery as exc: return Response({'detail': six.text_type(exc)}, status=400) if query_kwargs['query']: q = Q(message__icontains=query_kwargs['query']) if len(query) == 32: q |= Q(event_id__exact=query_kwargs['query']) events = events.filter(q) if query_kwargs['tags']: try: environment_id = self._get_environment_id_from_request( request, group.project.organization_id) except Environment.DoesNotExist: event_ids = [] else: event_ids = tagstore.get_group_event_ids( group.project_id, group.id, environment_id, query_kwargs['tags']) if event_ids: events = events.filter(id__in=event_ids, ) else: events = events.none() return self.paginate( request=request, queryset=events, order_by='-datetime', on_results=lambda x: serialize(x, request.user), paginator_cls=DateTimePaginator, )
def build_query_params_from_request(request, organization, projects, environments): query_kwargs = { 'projects': projects, 'sort_by': request.GET.get('sort', DEFAULT_SORT_OPTION), } limit = request.GET.get('limit') if limit: try: query_kwargs['limit'] = int(limit) except ValueError: raise ValidationError('invalid limit') # TODO: proper pagination support cursor = request.GET.get('cursor') if cursor: query_kwargs['cursor'] = Cursor.from_string(cursor) query = request.GET.get('query', 'is:unresolved').strip() use_new_filters = request.GET.get('use_new_filters', '1') == '1' if query: try: query_kwargs.update( parse_query(projects, query, request.user, environments)) except InvalidQuery as e: raise ValidationError( u'Your search query could not be parsed: {}'.format(e.message)) try: search_filters = convert_query_values( parse_search_query(query), projects, request.user, environments, ) except Exception: # TODO: Catch less broad exceptions when we're confident in these # new filters logging.exception( 'Error occurred while parsing new style search query') search_filters = [] # If something goes wrong here we just want to use the working # filters use_new_filters = False if use_new_filters: validate_search_filter_permissions(organization, search_filters) query_kwargs['search_filters'] = search_filters query_kwargs['use_new_filters'] = use_new_filters return query_kwargs
def _build_query_params_from_request(self, request, project): query_kwargs = { 'project': project, } if request.GET.get('status'): try: query_kwargs['status'] = STATUS_CHOICES[request.GET['status']] except KeyError: raise ValidationError('invalid status') if request.user.is_authenticated() and request.GET.get('bookmarks'): query_kwargs['bookmarked_by'] = request.user if request.user.is_authenticated() and request.GET.get('assigned'): query_kwargs['assigned_to'] = request.user sort_by = request.GET.get('sort') if sort_by is None: sort_by = DEFAULT_SORT_OPTION query_kwargs['sort_by'] = sort_by tags = {} for tag_key in TagKey.objects.all_keys(project): if request.GET.get(tag_key): tags[tag_key] = request.GET[tag_key] if tags: query_kwargs['tags'] = tags limit = request.GET.get('limit') if limit: try: query_kwargs['limit'] = int(limit) except ValueError: raise ValidationError('invalid limit') # TODO: proper pagination support cursor = request.GET.get('cursor') if cursor: query_kwargs['cursor'] = Cursor.from_string(cursor) query = request.GET.get('query', 'is:unresolved').strip() if query: try: query_kwargs.update(parse_query(project, query, request.user)) except InvalidQuery as e: raise ValidationError(u'Your search query could not be parsed: {}'.format(e.message)) return query_kwargs
def get(self, request, group): """ List an Issue's Events `````````````````````` This endpoint lists an issue's events. :pparam string issue_id: the ID of the issue to retrieve. :auth: required """ events = Event.objects.filter( group_id=group.id, ) query = request.GET.get('query') if query: try: query_kwargs = parse_query(group.project, query, request.user) except InvalidQuery as exc: return Response({'detail': six.text_type(exc)}, status=400) if query_kwargs['query']: events = events.filter( message__icontains=query_kwargs['query'], ) if query_kwargs['tags']: event_ids = tagstore.get_group_event_ids( group.project_id, group.id, query_kwargs['tags']) if event_ids: events = events.filter( id__in=event_ids, ) else: events = events.none() return self.paginate( request=request, queryset=events, order_by='-datetime', on_results=lambda x: serialize(x, request.user), paginator_cls=DateTimePaginator, )
def build_query_params_from_request(request, organization, projects, environments): query_kwargs = { 'projects': projects, 'sort_by': request.GET.get('sort', DEFAULT_SORT_OPTION), } limit = request.GET.get('limit') if limit: try: query_kwargs['limit'] = int(limit) except ValueError: raise ValidationError('invalid limit') # TODO: proper pagination support cursor = request.GET.get('cursor') if cursor: query_kwargs['cursor'] = Cursor.from_string(cursor) query = request.GET.get('query', 'is:unresolved').strip() if query: try: query_kwargs.update( parse_query(projects, query, request.user, environments)) except InvalidQuery as e: raise ValidationError( u'Your search query could not be parsed: {}'.format(e.message)) try: search_filters = convert_query_values( parse_search_query(query), projects, request.user, environments, ) except InvalidSearchQuery as e: raise ValidationError( u'Your search query could not be parsed: {}'.format(e.message)) validate_search_filter_permissions(organization, search_filters) query_kwargs['search_filters'] = search_filters return query_kwargs
def get(self, request, group): """ List an Issue's Events `````````````````````` This endpoint lists an issue's events. :pparam string issue_id: the ID of the issue to retrieve. :auth: required """ events = Event.objects.filter(group_id=group.id, ) query = request.GET.get('query') if query: try: query_kwargs = parse_query(group.project, query, request.user) except InvalidQuery as exc: return Response({'detail': six.text_type(exc)}, status=400) if query_kwargs['query']: events = events.filter( message__icontains=query_kwargs['query'], ) if query_kwargs['tags']: matches = self._tags_to_filter(group, query_kwargs['tags']) if matches: events = events.filter(id__in=matches, ) else: events = events.none() return self.paginate( request=request, queryset=events, order_by='-datetime', on_results=lambda x: serialize(x, request.user), paginator_cls=DateTimePaginator, )
def test_single_tag_with_quotes(self): result = parse_query('foo:"bar"', self.user) assert result == {'tags': {'foo': 'bar'}, 'query': ''}
def test_multiple_tags(self): result = parse_query('foo:bar key:value', self.user) assert result == {'tags': {'key': 'value', 'foo': 'bar'}, 'query': ''}
def test_tag_with_colon_in_value(self): result = parse_query('url:http://example.com', self.user) assert result == {'tags': {'url': 'http://example.com'}, 'query': ''}
def test_single_tag(self): result = parse_query('key:value', self.user) assert result == {'tags': {'key': 'value'}, 'query': ''}
def test_mix_tag_and_query(self): result = parse_query('foo bar key:value', self.user) assert result == {'tags': {'key': 'value'}, 'query': 'foo bar'}
def test_useless_prefix(self): result = parse_query('foo: bar', self.user) assert result == {'tags': {}, 'query': 'foo: bar'}
def get(self, request, group): """ List an Issue's Events `````````````````````` This endpoint lists an issue's events. :pparam string issue_id: the ID of the issue to retrieve. :auth: required """ def respond(queryset): return self.paginate( request=request, queryset=queryset, order_by='-datetime', on_results=lambda x: serialize(x, request.user), paginator_cls=DateTimePaginator, ) events = Event.objects.filter(group_id=group.id) try: environment = self._get_environment_from_request( request, group.project.organization_id, ) except Environment.DoesNotExist: return respond(events.none()) raw_query = request.GET.get('query') if raw_query: try: query_kwargs = parse_query(group.project, raw_query, request.user) except InvalidQuery as exc: return Response({'detail': six.text_type(exc)}, status=400) else: query = query_kwargs.pop('query', None) tags = query_kwargs.pop('tags', {}) else: query = None tags = {} if environment is not None: if 'environment' in tags and tags['environment'] != environment.name: # An event can only be associated with a single # environment, so if the environment associated with # the request is different than the environment # provided as a tag lookup, the query cannot contain # any valid results. return respond(events.none()) else: tags['environment'] = environment.name if query: q = Q(message__icontains=query) if len(query) == 32: q |= Q(event_id__exact=query) events = events.filter(q) if tags: event_ids = tagstore.get_group_event_ids( group.project_id, group.id, environment.id if environment is not None else None, tags, ) if not event_ids: return respond(events.none()) events = events.filter(id__in=event_ids) # filter out events which are beyond the retention period retention = quotas.get_event_retention(organization=group.project.organization) if retention: events = events.filter( datetime__gte=timezone.now() - timedelta(days=retention) ) return respond(events)
def parse_query(self, query): return parse_query(self.project, query, self.user)
def parse_query(self, query): return parse_query([self.project], query, self.user, None)
def test_assigned_me(self): result = parse_query('assigned:me', self.user) assert result == {'assigned_to': self.user, 'tags': {}, 'query': ''}
def test_simple(self): result = parse_query('foo bar', self.user) assert result == {'tags': {}, 'query': 'foo bar'}
def test_release(self): result = parse_query('release:bar', self.user) assert result == {'tags': {'sentry:release': 'bar'}, 'query': ''}
def test_assigned_unknown_user(self): result = parse_query('assigned:[email protected]', self.user) assert result['assigned_to'].id == 0
def test_tag_with_quotes_and_query(self): result = parse_query('key:"a value" hello', self.user) assert result == {'tags': {'key': 'a value'}, 'query': 'hello'}
def _build_query_params_from_request(self, request, project): query_kwargs = { 'project': project, } if request.GET.get('status'): try: query_kwargs['status'] = STATUS_CHOICES[request.GET['status']] except KeyError: raise ValidationError('invalid status') if request.user.is_authenticated() and request.GET.get('bookmarks'): query_kwargs['bookmarked_by'] = request.user if request.user.is_authenticated() and request.GET.get('assigned'): query_kwargs['assigned_to'] = request.user sort_by = request.GET.get('sort') if sort_by is None: sort_by = DEFAULT_SORT_OPTION query_kwargs['sort_by'] = sort_by tags = {} for tag_key in TagKey.objects.all_keys(project): if request.GET.get(tag_key): tags[tag_key] = request.GET[tag_key] if tags: query_kwargs['tags'] = tags # TODO: dates should include timestamps date_from = request.GET.get('since') date_to = request.GET.get('until') date_filter = request.GET.get('date_filter') limit = request.GET.get('limit') if limit: try: query_kwargs['limit'] = int(limit) except ValueError: raise ValidationError('invalid limit') if date_from: date_from = self._parse_date(date_from) if date_to: date_to = self._parse_date(date_to) query_kwargs['date_from'] = date_from query_kwargs['date_to'] = date_to if date_filter: query_kwargs['date_filter'] = date_filter # TODO: proper pagination support cursor = request.GET.get('cursor') if cursor: query_kwargs['cursor'] = Cursor.from_string(cursor) query = request.GET.get('query', 'is:unresolved').strip() if query: query_kwargs.update(parse_query(project, query, request.user)) return query_kwargs
def test_is_resolved(self): result = parse_query('is:resolved', self.user) assert result == {'status': GroupStatus.RESOLVED, 'tags': {}, 'query': ''}
def get(self, request, project): """ List a project's aggregates Return a list of aggregates bound to a project. {method} {path} A default query of 'is:resolved' is applied. To return results with other statuses send an new query value (i.e. ?query= for all results). Any standard Sentry structured search query can be passed via the ``query`` parameter. The ``statsPeriod`` parameter can be used to select the timeline stats which should be present. Possible values are: '' (disable), '24h', '14d' """ query_kwargs = { 'project': project, } stats_period = request.GET.get('statsPeriod') if stats_period not in (None, '', '24h', '14d'): return Response({"detail": ERR_INVALID_STATS_PERIOD}, status=400) elif stats_period is None: # default stats_period = '24h' elif stats_period == '': # disable stats stats_period = None if request.GET.get('status'): try: query_kwargs['status'] = STATUS_CHOICES[request.GET['status']] except KeyError: return Response('{"detail": "invalid status"}', status=400) if request.user.is_authenticated() and request.GET.get('bookmarks'): query_kwargs['bookmarked_by'] = request.user if request.user.is_authenticated() and request.GET.get('assigned'): query_kwargs['assigned_to'] = request.user sort_by = request.GET.get('sort') if sort_by is None: sort_by = DEFAULT_SORT_OPTION query_kwargs['sort_by'] = sort_by tags = {} for tag_key in TagKey.objects.all_keys(project): if request.GET.get(tag_key): tags[tag_key] = request.GET[tag_key] if tags: query_kwargs['tags'] = tags # TODO: dates should include timestamps date_from = request.GET.get('since') date_to = request.GET.get('until') date_filter = request.GET.get('date_filter') limit = request.GET.get('limit') if limit: try: query_kwargs['limit'] = int(limit) except ValueError: return Response('{"detail": "invalid limit"}', status=400) if date_from: date_from = self._parse_date(date_from) if date_to: date_to = self._parse_date(date_to) query_kwargs['date_from'] = date_from query_kwargs['date_to'] = date_to if date_filter: query_kwargs['date_filter'] = date_filter # TODO: proper pagination support cursor = request.GET.get('cursor') if cursor: query_kwargs['cursor'] = Cursor.from_string(cursor) query = request.GET.get('query', 'is:unresolved').strip() if len(query) == 32: # check to see if we've got an event ID try: matching_event = EventMapping.objects.filter( project=project, event_id=query, ).select_related('group')[0] except IndexError: pass else: return Response(serialize( [matching_event.group], request.user, StreamGroupSerializer( stats_period=stats_period ) )) if query is not None: query_kwargs.update(parse_query(query, request.user)) cursor_result = search.query(**query_kwargs) results = list(cursor_result) # HACK: remove auto resolved entries if query_kwargs.get('status') == STATUS_UNRESOLVED: results = [ r for r in results if not r.is_resolved() ] response = Response(serialize( results, request.user, StreamGroupSerializer( stats_period=stats_period ) )) response['Link'] = ', '.join([ self.build_cursor_link(request, 'previous', cursor_result.prev), self.build_cursor_link(request, 'next', cursor_result.next), ]) return response
def test_assigned_email(self): result = parse_query('assigned:%s' % (self.user.email,), self.user) assert result == {'assigned_to': self.user, 'tags': {}, 'query': ''}
def test_first_release(self): result = parse_query('first-release:bar', self.user) assert result == {'first_release': 'bar', 'tags': {}, 'query': ''}
def test_padded_spacing(self): result = parse_query('release:bar foo bar', self.user) assert result == {'tags': {'sentry:release': 'bar'}, 'query': 'foo bar'}
def _get_group_list(request, project): query_kwargs = {"project": project} status = request.GET.get("status", "0") if status: query_kwargs["status"] = int(status) if request.user.is_authenticated() and request.GET.get("bookmarks"): query_kwargs["bookmarked_by"] = request.user if request.user.is_authenticated() and request.GET.get("assigned"): query_kwargs["assigned_to"] = request.user sort_by = request.GET.get("sort") or request.session.get("streamsort") if sort_by is None: sort_by = DEFAULT_SORT_OPTION # Save last sort in session if sort_by != request.session.get("streamsort"): request.session["streamsort"] = sort_by query_kwargs["sort_by"] = sort_by tags = {} for tag_key in TagKey.objects.all_keys(project): if request.GET.get(tag_key): tags[tag_key] = request.GET[tag_key] if tags: query_kwargs["tags"] = tags else: query_kwargs["tags"] = {} date_from = request.GET.get("df") time_from = request.GET.get("tf") date_to = request.GET.get("dt") time_to = request.GET.get("tt") date_filter = request.GET.get("date_type") today = timezone.now() # date format is Y-m-d if any(x is not None for x in [date_from, time_from, date_to, time_to]): date_from, date_to = parse_date(date_from, time_from), parse_date(date_to, time_to) else: date_from = today - datetime.timedelta(days=5) date_to = None query_kwargs["date_from"] = date_from query_kwargs["date_to"] = date_to if date_filter: query_kwargs["date_filter"] = date_filter cursor = request.GET.get("cursor") if cursor: try: query_kwargs["cursor"] = Cursor.from_string(cursor) except ValueError: # XXX(dcramer): ideally we'd error, but this is an internal API so # we'd rather just throw it away logging.info("Throwing away invalid cursor: %s", cursor) query_kwargs["limit"] = EVENTS_PER_PAGE query = request.GET.get("query", "") if query is not None: query_result = parse_query(query, request.user) # Disclaimer: the following code is disgusting if query_result.get("query"): query_kwargs["query"] = query_result["query"] if query_result.get("tags"): query_kwargs["tags"].update(query_result["tags"]) results = app.search.query(**query_kwargs) return { "event_list": results[:EVENTS_PER_PAGE], "date_from": date_from, "date_to": date_to, "today": today, "sort": sort_by, "date_type": date_filter, "next_cursor": results.next, "prev_cursor": results.prev, }
def get(self, request, project_id): """ List a project's aggregates Return a list of aggregates bound to a project. {method} {path}?id=1&id=2&id=3 A default query of 'is:resolved' is applied. To return results with other statuses send an new query value (i.e. ?query= for all results). Any standard Sentry structured search query can be passed via the ``query`` parameter. """ project = Project.objects.get_from_cache( id=project_id, ) assert_perm(project, request.user, request.auth) query_kwargs = { 'project': project, } if request.GET.get('status'): try: query_kwargs['status'] = STATUS_CHOICES[request.GET['status']] except KeyError: return Response('{"error": "invalid status"}', status=400) if request.user.is_authenticated() and request.GET.get('bookmarks'): query_kwargs['bookmarked_by'] = request.user if request.user.is_authenticated() and request.GET.get('assigned'): query_kwargs['assigned_to'] = request.user sort_by = request.GET.get('sort') if sort_by is None: sort_by = DEFAULT_SORT_OPTION query_kwargs['sort_by'] = sort_by tags = {} for tag_key in TagKey.objects.all_keys(project): if request.GET.get(tag_key): tags[tag_key] = request.GET[tag_key] if tags: query_kwargs['tags'] = tags # TODO: dates should include timestamps date_from = request.GET.get('since') time_from = request.GET.get('until') date_filter = request.GET.get('date_filter') date_to = request.GET.get('dt') time_to = request.GET.get('tt') limit = request.GET.get('limit') if limit: try: query_kwargs['limit'] = int(limit) except ValueError: return Response('{"error": "invalid limit"}', status=400) today = timezone.now() # date format is Y-m-d if any(x is not None for x in [date_from, time_from, date_to, time_to]): date_from, date_to = parse_date(date_from, time_from), parse_date(date_to, time_to) else: date_from = today - timedelta(days=5) date_to = None query_kwargs['date_from'] = date_from query_kwargs['date_to'] = date_to if date_filter: query_kwargs['date_filter'] = date_filter # TODO: proper pagination support cursor = request.GET.get('cursor') if cursor: query_kwargs['cursor'] = Cursor.from_string(cursor) query = request.GET.get('query', 'is:unresolved') if query is not None: query_kwargs.update(parse_query(query, request.user)) cursor_result = search.query(**query_kwargs) context = list(cursor_result) GroupMeta.objects.populate_cache(context) response = Response(serialize(context, request.user)) response['Link'] = ', '.join([ self.build_cursor_link(request, 'previous', cursor_result.prev), self.build_cursor_link(request, 'next', cursor_result.next), ]) return response
def _get_group_list(request, project): query_kwargs = { 'project': project, } status = request.GET.get('status', '0') if status: query_kwargs['status'] = int(status) if request.user.is_authenticated() and request.GET.get('bookmarks'): query_kwargs['bookmarked_by'] = request.user if request.user.is_authenticated() and request.GET.get('assigned'): query_kwargs['assigned_to'] = request.user sort_by = request.GET.get('sort') or request.session.get('streamsort') if sort_by is None: sort_by = DEFAULT_SORT_OPTION # Save last sort in session if sort_by != request.session.get('streamsort'): request.session['streamsort'] = sort_by query_kwargs['sort_by'] = sort_by tags = {} for tag_key in TagKey.objects.all_keys(project): if request.GET.get(tag_key): tags[tag_key] = request.GET[tag_key] if tags: query_kwargs['tags'] = tags else: query_kwargs['tags'] = {} date_from = request.GET.get('df') time_from = request.GET.get('tf') date_to = request.GET.get('dt') time_to = request.GET.get('tt') date_filter = request.GET.get('date_type') today = timezone.now() # date format is Y-m-d if any(x is not None for x in [date_from, time_from, date_to, time_to]): date_from, date_to = parse_date(date_from, time_from), parse_date(date_to, time_to) else: date_from = today - datetime.timedelta(days=5) date_to = None query_kwargs['date_from'] = date_from query_kwargs['date_to'] = date_to if date_filter: query_kwargs['date_filter'] = date_filter cursor = request.GET.get('cursor') if cursor: try: query_kwargs['cursor'] = Cursor.from_string(cursor) except ValueError: # XXX(dcramer): ideally we'd error, but this is an internal API so # we'd rather just throw it away logging.info('Throwing away invalid cursor: %s', cursor) query_kwargs['limit'] = EVENTS_PER_PAGE query = request.GET.get('query', '') if query is not None: query_result = parse_query(query, request.user) # Disclaimer: the following code is disgusting if query_result.get('query'): query_kwargs['query'] = query_result['query'] if query_result.get('tags'): query_kwargs['tags'].update(query_result['tags']) results = app.search.query(**query_kwargs) return { 'event_list': results[:EVENTS_PER_PAGE], 'date_from': date_from, 'date_to': date_to, 'today': today, 'sort': sort_by, 'date_type': date_filter, 'next_cursor': results.next, 'prev_cursor': results.prev, }
def get(self, request, project): """ List a Project's Aggregates ``````````````````````````` Return a list of aggregates bound to a project. All parameters are supplied as query string parameters. A default query of ``is:resolved`` is applied. To return results with other statuses send an new query value (i.e. ``?query=`` for all results). The ``statsPeriod`` parameter can be used to select the timeline stats which should be present. Possible values are: '' (disable), '24h', '14d' :qparam string statsPeriod: an optional stat period (can be one of ``"24h"``, ``"14d"``, and ``""``). :qparam querystring query: an optional Sentry structured search query. If not provided an implied ``"is:resolved"`` is assumed.) :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. :auth: required """ query_kwargs = { 'project': project, } stats_period = request.GET.get('statsPeriod') if stats_period not in (None, '', '24h', '14d'): return Response({"detail": ERR_INVALID_STATS_PERIOD}, status=400) elif stats_period is None: # default stats_period = '24h' elif stats_period == '': # disable stats stats_period = None if request.GET.get('status'): try: query_kwargs['status'] = STATUS_CHOICES[request.GET['status']] except KeyError: return Response('{"detail": "invalid status"}', status=400) if request.user.is_authenticated() and request.GET.get('bookmarks'): query_kwargs['bookmarked_by'] = request.user if request.user.is_authenticated() and request.GET.get('assigned'): query_kwargs['assigned_to'] = request.user sort_by = request.GET.get('sort') if sort_by is None: sort_by = DEFAULT_SORT_OPTION query_kwargs['sort_by'] = sort_by tags = {} for tag_key in TagKey.objects.all_keys(project): if request.GET.get(tag_key): tags[tag_key] = request.GET[tag_key] if tags: query_kwargs['tags'] = tags # TODO: dates should include timestamps date_from = request.GET.get('since') date_to = request.GET.get('until') date_filter = request.GET.get('date_filter') limit = request.GET.get('limit') if limit: try: query_kwargs['limit'] = int(limit) except ValueError: return Response('{"detail": "invalid limit"}', status=400) if date_from: date_from = self._parse_date(date_from) if date_to: date_to = self._parse_date(date_to) query_kwargs['date_from'] = date_from query_kwargs['date_to'] = date_to if date_filter: query_kwargs['date_filter'] = date_filter # TODO: proper pagination support cursor = request.GET.get('cursor') if cursor: query_kwargs['cursor'] = Cursor.from_string(cursor) query = request.GET.get('query', 'is:unresolved').strip() if len(query) == 32: # check to see if we've got an event ID try: matching_event = EventMapping.objects.filter( project=project, event_id=query, ).select_related('group')[0] except IndexError: pass else: return Response( serialize( [matching_event.group], request.user, StreamGroupSerializer(stats_period=stats_period))) if query is not None: query_kwargs.update(parse_query(project, query, request.user)) cursor_result = search.query(**query_kwargs) results = list(cursor_result) context = serialize(results, request.user, StreamGroupSerializer(stats_period=stats_period)) # HACK: remove auto resolved entries if query_kwargs.get('status') == GroupStatus.UNRESOLVED: context = [r for r in context if r['status'] == 'unresolved'] response = Response(context) response['Link'] = ', '.join([ self.build_cursor_link(request, 'previous', cursor_result.prev), self.build_cursor_link(request, 'next', cursor_result.next), ]) return response