def test_valid_ignore_case(): helper = ClientApiHelper() request = mock.Mock() request.META = {'HTTP_X_SENTRY_AUTH': 'SeNtRy sentry_key=value, biz=baz'} request.GET = {} result = helper.auth_from_request(request) assert result.public_key == 'value'
def process_event_from_kafka(message): project = Project.objects.get_from_cache(pk=message['project_id']) remote_addr = message['remote_addr'] helper = ClientApiHelper( agent=message['agent'], project_id=project.id, ip_address=remote_addr, ) helper.context.bind_project(project) auth = Auth(message['auth'], message['auth'].pop('is_public')) helper.context.bind_auth(auth) key = helper.project_key_from_auth(auth) data = message['data'] version = data['version'] event_manager = EventManager( data, project=project, key=key, auth=auth, client_ip=remote_addr, user_agent=helper.context.agent, version=version, ) event_manager._normalized = True del data return process_event(event_manager, project, key, remote_addr, helper, attachments=None)
def reprocess_events(project_id, **kwargs): from sentry.models import ProcessingIssue from sentry.coreapi import ClientApiHelper from sentry import app lock_key = 'events:reprocess_events:%s' % project_id have_more = False lock = app.locks.get(lock_key, duration=60) try: with lock.acquire(): raw_events, have_more = ProcessingIssue.objects \ .find_resolved(project_id) if raw_events: helper = ClientApiHelper() for raw_event in raw_events: helper.insert_data_to_database(raw_event.data.data, from_reprocessing=True) create_reprocessing_report(project_id=project_id, event_id=raw_event.event_id) raw_event.delete() except UnableToAcquireLock as error: logger.warning('reprocess_events.fail', extra={'error': error}) # There are more, kick us off again if have_more: reprocess_events.delay(project_id=project_id)
def test_save_path(self, mock_produce, mock_preprocess_event, mock_process_event, mock_save_event): with self.feature('projects:kafka-ingest'): project = self.create_project() data = self._create_event_with_platform(project, 'doesnt_need_process') helper = ClientApiHelper(project_id=self.project.id) helper.context.bind_project(project) helper.insert_data_to_database(data) # preprocess self._call_consumer(mock_produce) # save self._call_consumer(mock_produce) assert mock_preprocess_event.delay.call_count == 0 assert mock_process_event.delay.call_count == 0 assert mock_save_event.delay.call_count == 0 event = Event.objects.get(project_id=project.id, event_id=data['event_id']) saved_data = event.get_raw_data() assert 'foo' not in saved_data assert saved_data['platform'] == 'doesnt_need_process'
def reprocess_events(project_id, **kwargs): from sentry.models import ProcessingIssue from sentry.coreapi import ClientApiHelper from sentry import app lock_key = "events:reprocess_events:%s" % project_id have_more = False lock = app.locks.get(lock_key, duration=60) try: with lock.acquire(): raw_events, have_more = ProcessingIssue.objects.find_resolved( project_id) if raw_events: helper = ClientApiHelper() for raw_event in raw_events: helper.insert_data_to_database(raw_event.data.data, from_reprocessing=True) create_reprocessing_report(project_id=project_id, event_id=raw_event.event_id) # Here we only delete the raw event but leave the # reprocessing report alive. When the queue # eventually kicks in this should clean up. raw_event.delete() except UnableToAcquireLock as error: logger.warning("reprocess_events.fail", extra={"error": error}) # There are more, kick us off again if have_more: reprocess_events.delay(project_id=project_id)
def test_multiple_auth_suspicious(): helper = ClientApiHelper() request = mock.Mock() request.GET = {'sentry_version': '1', 'foo': 'bar'} request.META = {'HTTP_X_SENTRY_AUTH': 'Sentry sentry_key=value, biz=baz'} with pytest.raises(SuspiciousOperation): helper.auth_from_request(request)
def test_invalid_malformed_value(): helper = ClientApiHelper() request = mock.Mock() request.META = {'HTTP_X_SENTRY_AUTH': 'Sentry sentry_key=value,,biz=baz'} request.GET = {} with pytest.raises(APIUnauthorized): helper.auth_from_request(request)
def test_invalid_header_missing_pair(): helper = ClientApiHelper() request = mock.Mock() request.META = {'HTTP_X_SENTRY_AUTH': 'Sentry foo'} request.GET = {} with pytest.raises(APIUnauthorized): helper.auth_from_request(request)
def test_invalid_legacy_header_defers_to_GET(): helper = ClientApiHelper() request = mock.Mock() request.META = {'HTTP_AUTHORIZATION': 'foobar'} request.GET = {'sentry_version': '1', 'foo': 'bar'} result = helper.auth_from_request(request) assert result.version == '1'
def send(self, **kwargs): # TODO(dcramer): this should respect rate limits/etc and use the normal # pipeline from sentry.app import tsdb from sentry.coreapi import ClientApiHelper from sentry.event_manager import EventManager from sentry.models import Project helper = ClientApiHelper( agent='raven-python/%s (sentry %s)' % (raven.VERSION, sentry.VERSION), project_id=settings.SENTRY_PROJECT, version=self.protocol_version, ) try: project = Project.objects.get_from_cache( id=settings.SENTRY_PROJECT) except DatabaseError: self.error_logger.error('Unable to fetch internal project', exc_info=True) return except Project.DoesNotExist: self.error_logger.error('Internal project (id=%s) does not exist', settings.SENTRY_PROJECT) return except Exception: self.error_logger.error( 'Unable to fetch internal project for some unknown reason', exec_info=True) return helper.context.bind_project(project) metrics.incr('events.total') kwargs['project'] = project.id try: manager = EventManager(kwargs) data = manager.normalize() tsdb.incr_multi([ (tsdb.models.project_total_received, project.id), (tsdb.models.organization_total_received, project.organization_id), ]) helper.insert_data_to_database(data) except Exception as e: if self.raise_send_errors: raise self.error_logger.error( 'Unable to record event: %s\nEvent was: %r', e, kwargs['message'], exc_info=True)
def dispatch(self, request, project_id=None, *args, **kwargs): helper = ClientApiHelper( agent=request.META.get('HTTP_USER_AGENT'), project_id=project_id, ip_address=request.META['REMOTE_ADDR'], ) origin = None try: origin = helper.origin_from_request(request) response = self._dispatch(request, helper, project_id=project_id, origin=origin, *args, **kwargs) except APIError as e: context = { 'error': unicode(e.msg).encode('utf-8'), } if e.name: context['error_name'] = e.name response = HttpResponse(json.dumps(context), content_type='application/json', status=e.http_status) # Set X-Sentry-Error as in many cases it is easier to inspect the headers response['X-Sentry-Error'] = context['error'] if isinstance(e, APIRateLimited) and e.retry_after is not None: response['Retry-After'] = str(e.retry_after) except Exception: if settings.DEBUG or True: content = traceback.format_exc() else: content = '' traceback.print_exc() response = HttpResponse(content, content_type='text/plain', status=500) if response.status_code != 200 and origin: # We allow all origins on errors response['Access-Control-Allow-Origin'] = '*' if origin: response['Access-Control-Allow-Headers'] = \ 'X-Sentry-Auth, X-Requested-With, Origin, Accept, ' \ 'Content-Type, Authentication' response['Access-Control-Allow-Methods'] = \ ', '.join(self._allowed_methods()) return response
def test_should_filter_message(self, mock_is_valid_error_message): TestItem = namedtuple('TestItem', 'value formatted result') helper = ClientApiHelper() items = [ TestItem( {'type': 'UnfilteredException'}, 'UnfilteredException', True, ), TestItem( {'value': 'This is an unfiltered exception.'}, 'This is an unfiltered exception.', True, ), TestItem( { 'type': 'UnfilteredException', 'value': 'This is an unfiltered exception.' }, 'UnfilteredException: This is an unfiltered exception.', True, ), TestItem( { 'type': 'FilteredException', 'value': 'This is a filtered exception.' }, 'FilteredException: This is a filtered exception.', False, ), ] data = { 'sentry.interfaces.Exception': { 'values': [item.value for item in items] }, } mock_is_valid_error_message.side_effect = [ item.result for item in items ] assert helper.should_filter(self.project, data) == (True, FilterStatKeys.ERROR_MESSAGE) assert mock_is_valid_error_message.call_args_list == [ mock.call(self.project, item.formatted) for item in items ]
def send(self, **kwargs): # TODO(dcramer): this should respect rate limits/etc and use the normal # pipeline from sentry.app import tsdb from sentry.coreapi import ClientApiHelper from sentry.event_manager import EventManager from sentry.models import Project helper = ClientApiHelper( agent='raven-python/%s (sentry %s)' % (raven.VERSION, sentry.VERSION), project_id=settings.SENTRY_PROJECT, version=self.protocol_version, ) try: project = Project.objects.get_from_cache(id=settings.SENTRY_PROJECT) except DatabaseError: self.error_logger.error('Unable to fetch internal project', exc_info=True) return except Project.DoesNotExist: self.error_logger.error('Internal project (id=%s) does not exist', settings.SENTRY_PROJECT) return except Exception: self.error_logger.error( 'Unable to fetch internal project for some unknown reason', exc_info=True) return helper.context.bind_project(project) metrics.incr('events.total') kwargs['project'] = project.id try: manager = EventManager(kwargs) data = manager.normalize() tsdb.incr_multi([ (tsdb.models.project_total_received, project.id), (tsdb.models.organization_total_received, project.organization_id), ]) helper.insert_data_to_database(data) except Exception as e: if self.raise_send_errors: raise self.error_logger.error( 'Unable to record event: %s\nEvent was: %r', e, kwargs['message'], exc_info=True)
def setUp(self): self.user = self.create_user('*****@*****.**') self.team = self.create_team(name='Foo') self.project = self.create_project(teams=[self.team]) self.pk = self.project.key_set.get_or_create()[0] self.helper = ClientApiHelper(agent='Awesome Browser', ip_address='198.51.100.0')
def setUp(self): self.user = self.create_user("*****@*****.**") self.team = self.create_team(name="Foo") self.project = self.create_project(teams=[self.team]) self.pk = self.project.key_set.get_or_create()[0] self.helper = ClientApiHelper(agent="Awesome Browser", ip_address="198.51.100.0")
def setUp(self): self.user = self.create_user('*****@*****.**') self.team = self.create_team(name='Foo') self.project = self.create_project(team=self.team) self.pm = self.project.team.member_set.get_or_create(user=self.user)[0] self.pk = self.project.key_set.get_or_create()[0] self.helper = ClientApiHelper()
def mark_failed(self, last_checkin=None): from sentry.coreapi import ClientApiHelper from sentry.event_manager import EventManager from sentry.models import Project from sentry.signals import monitor_failed if last_checkin is None: next_checkin_base = timezone.now() last_checkin = self.last_checkin or timezone.now() else: next_checkin_base = last_checkin affected = (type(self).objects.filter( Q(last_checkin__lte=last_checkin) | Q(last_checkin__isnull=True), id=self.id).update( next_checkin=self.get_next_scheduled_checkin( next_checkin_base), status=MonitorStatus.ERROR, last_checkin=last_checkin, )) if not affected: return False event_manager = EventManager( { "logentry": { "message": "Monitor failure: %s" % (self.name, ) }, "contexts": { "monitor": { "id": six.text_type(self.guid) } }, }, project=Project(id=self.project_id), ) event_manager.normalize() data = event_manager.get_data() helper = ClientApiHelper(project_id=self.project_id) helper.insert_data_to_database(data) monitor_failed.send(monitor=self, sender=type(self)) return True
def mark_failed(self, last_checkin=None): from sentry.coreapi import ClientApiHelper from sentry.event_manager import EventManager from sentry.models import Project from sentry.signals import monitor_failed if last_checkin is None: next_checkin_base = timezone.now() last_checkin = self.last_checkin or timezone.now() else: next_checkin_base = last_checkin affected = type(self).objects.filter( Q(last_checkin__lte=last_checkin) | Q(last_checkin__isnull=True), id=self.id, ).update( next_checkin=self.get_next_scheduled_checkin(next_checkin_base), status=MonitorStatus.ERROR, last_checkin=last_checkin, ) if not affected: return False event_manager = EventManager( { 'logentry': { 'message': 'Monitor failure: %s' % (self.name,), }, 'contexts': { 'monitor': { 'id': six.text_type(self.guid), }, }, }, project=Project(id=self.project_id), ) event_manager.normalize() data = event_manager.get_data() helper = ClientApiHelper(project_id=self.project_id) helper.insert_data_to_database(data) monitor_failed.send(monitor=self, sender=type(self)) return True
def mark_failed(self, last_checkin=None): from sentry.coreapi import ClientApiHelper from sentry.event_manager import EventManager from sentry.models import Project from sentry.signals import monitor_failed if last_checkin is None: next_checkin_base = timezone.now() last_checkin = self.last_checkin else: next_checkin_base = last_checkin affected = type(self).objects.filter( id=self.id, last_checkin=self.last_checkin, ).update( next_checkin=self.get_next_scheduled_checkin(next_checkin_base), status=MonitorStatus.ERROR, last_checkin=last_checkin, ) if not affected: return False event_manager = EventManager( { 'logentry': { 'message': 'Monitor failure: %s' % (self.name, ), }, 'contexts': { 'monitor': { 'id': six.text_type(self.guid), }, }, }, project=Project(id=self.project_id), ) event_manager.normalize() data = event_manager.get_data() helper = ClientApiHelper(project_id=self.project_id) helper.insert_data_to_database(data) monitor_failed.send(monitor=self, sender=type(self)) return True
def create_sample_event(project, platform=None, default=None, raw=True, sample_name=None, **kwargs): if not platform and not default: return timestamp = kwargs.get('timestamp') data = load_data(platform, default, timestamp, sample_name) if not data: return data.update(kwargs) data = ClientApiHelper().validate_data(data) manager = EventManager(data) manager.normalize() return manager.save(project.id, raw=raw)
def send(self, **kwargs): # TODO(dcramer): this should respect rate limits/etc and use the normal # pipeline # Report the issue to an upstream Sentry if active # NOTE: we don't want to check self.is_enabled() like normal, since # is_enabled behavior is overridden in this class. We explicitly # want to check if the remote is active. if self.remote.is_active(): from sentry import options # Append some extra tags that are useful for remote reporting super_kwargs = copy.deepcopy(kwargs) super_kwargs['tags']['install-id'] = options.get( 'sentry:install-id') super(SentryInternalClient, self).send(**super_kwargs) if not is_current_event_safe(): return from sentry import tsdb from sentry.coreapi import ClientApiHelper from sentry.event_manager import EventManager from sentry.models import Project helper = ClientApiHelper( agent='raven-python/%s (sentry %s)' % (raven.VERSION, sentry.VERSION), project_id=settings.SENTRY_PROJECT, version=self.protocol_version, ) try: project = Project.objects.get_from_cache( id=settings.SENTRY_PROJECT) except DatabaseError: self.error_logger.error('Unable to fetch internal project', exc_info=True) return except Project.DoesNotExist: self.error_logger.error('Internal project (id=%s) does not exist', settings.SENTRY_PROJECT) return except Exception: self.error_logger.error( 'Unable to fetch internal project for some unknown reason', exc_info=True) return helper.context.bind_project(project) metrics.incr('events.total') kwargs['project'] = project.id try: # This in theory is the right way to do it because validate # also normalizes currently, but we just send in data already # normalised in the raven client now. # data = helper.validate_data(kwargs) data = kwargs manager = EventManager(data) data = manager.normalize() tsdb.incr_multi([ (tsdb.models.project_total_received, project.id), (tsdb.models.organization_total_received, project.organization_id), ]) helper.insert_data_to_database(data) except Exception as e: if self.raise_send_errors: raise message = kwargs.get('message') if not message: msg_interface = kwargs.get('sentry.interface.Message', {}) message = msg_interface.get( 'formatted', msg_interface.get('message', 'unknown error')) self.error_logger.error( 'Unable to record event: %s\nEvent was: %r', e, message, exc_info=True)
def dispatch(self, request, project_id=None, *args, **kwargs): helper = ClientApiHelper( agent=request.META.get('HTTP_USER_AGENT'), project_id=project_id, ip_address=request.META['REMOTE_ADDR'], ) origin = None if kafka_publisher is not None: self._publish_to_kafka(request) try: origin = self.auth_helper_cls.origin_from_request(request) response = self._dispatch(request, helper, project_id=project_id, origin=origin, *args, **kwargs) except APIError as e: context = { 'error': force_bytes(e.msg, errors='replace'), } if e.name: context['error_name'] = e.name response = HttpResponse(json.dumps(context), content_type='application/json', status=e.http_status) # Set X-Sentry-Error as in many cases it is easier to inspect the headers response['X-Sentry-Error'] = context['error'] if isinstance(e, APIRateLimited) and e.retry_after is not None: response['Retry-After'] = six.text_type( int(math.ceil(e.retry_after))) except Exception as e: # TODO(dcramer): test failures are not outputting the log message # here if settings.DEBUG: content = traceback.format_exc() else: content = '' logger.exception(e) response = HttpResponse(content, content_type='text/plain', status=500) # TODO(dcramer): it'd be nice if we had an incr_multi method so # tsdb could optimize this metrics.incr('client-api.all-versions.requests', skip_internal=False) metrics.incr('client-api.all-versions.responses.%s' % (response.status_code, ), skip_internal=False) metrics.incr( 'client-api.all-versions.responses.%sxx' % (six.text_type(response.status_code)[0], ), skip_internal=False, ) if helper.context.version: metrics.incr( 'client-api.v%s.requests' % (helper.context.version, ), skip_internal=False, ) metrics.incr( 'client-api.v%s.responses.%s' % (helper.context.version, response.status_code), skip_internal=False, ) metrics.incr( 'client-api.v%s.responses.%sxx' % (helper.context.version, six.text_type( response.status_code)[0]), skip_internal=False, ) if response.status_code != 200 and origin: # We allow all origins on errors response['Access-Control-Allow-Origin'] = '*' if origin: response['Access-Control-Allow-Headers'] = \ 'X-Sentry-Auth, X-Requested-With, Origin, Accept, ' \ 'Content-Type, Authentication' response['Access-Control-Allow-Methods'] = \ ', '.join(self._allowed_methods()) response['Access-Control-Expose-Headers'] = \ 'X-Sentry-Error, Retry-After' return response
def send(self, **kwargs): # TODO(dcramer): this should respect rate limits/etc and use the normal # pipeline # Report the issue to an upstream Sentry if active # NOTE: we don't want to check self.is_enabled() like normal, since # is_enabled behavior is overridden in this class. We explicitly # want to check if the remote is active. if self.remote.is_active(): from sentry import options # Append some extra tags that are useful for remote reporting super_kwargs = copy.deepcopy(kwargs) super_kwargs['tags']['install-id'] = options.get('sentry:install-id') super(SentryInternalClient, self).send(**super_kwargs) if not is_current_event_safe(): return from sentry.app import tsdb from sentry.coreapi import ClientApiHelper from sentry.event_manager import EventManager from sentry.models import Project helper = ClientApiHelper( agent='raven-python/%s (sentry %s)' % (raven.VERSION, sentry.VERSION), project_id=settings.SENTRY_PROJECT, version=self.protocol_version, ) try: project = Project.objects.get_from_cache(id=settings.SENTRY_PROJECT) except DatabaseError: self.error_logger.error('Unable to fetch internal project', exc_info=True) return except Project.DoesNotExist: self.error_logger.error('Internal project (id=%s) does not exist', settings.SENTRY_PROJECT) return except Exception: self.error_logger.error( 'Unable to fetch internal project for some unknown reason', exc_info=True) return helper.context.bind_project(project) metrics.incr('events.total') kwargs['project'] = project.id try: # This in theory is the right way to do it because validate # also normalizes currently, but we just send in data already # normalised in the raven client now. # data = helper.validate_data(project, kwargs) data = kwargs manager = EventManager(data) data = manager.normalize() tsdb.incr_multi([ (tsdb.models.project_total_received, project.id), (tsdb.models.organization_total_received, project.organization_id), ]) helper.insert_data_to_database(data) except Exception as e: if self.raise_send_errors: raise message = kwargs.get('message') if not message: msg_interface = kwargs.get('sentry.interface.Message', {}) message = msg_interface.get('formatted', msg_interface.get('message', 'unknown error')) self.error_logger.error( 'Unable to record event: %s\nEvent was: %r', e, message, exc_info=True)
def dispatch(self, request, project_id=None, *args, **kwargs): helper = ClientApiHelper( agent=request.META.get('HTTP_USER_AGENT'), project_id=project_id, ip_address=request.META['REMOTE_ADDR'], ) origin = None try: origin = helper.origin_from_request(request) response = self._dispatch(request, helper, project_id=project_id, origin=origin, *args, **kwargs) except APIError as e: context = { 'error': unicode(e.msg).encode('utf-8'), } if e.name: context['error_name'] = e.name response = HttpResponse(json.dumps(context), content_type='application/json', status=e.http_status) # Set X-Sentry-Error as in many cases it is easier to inspect the headers response['X-Sentry-Error'] = context['error'] if isinstance(e, APIRateLimited) and e.retry_after is not None: response['Retry-After'] = str(e.retry_after) except Exception: if settings.DEBUG or True: content = traceback.format_exc() else: content = '' traceback.print_exc() response = HttpResponse(content, content_type='text/plain', status=500) # TODO(dcramer): it'd be nice if we had an incr_multi method so # tsdb could optimize this metrics.incr('client-api.all-versions.requests') metrics.incr('client-api.all-versions.responses.%s' % ( response.status_code, )) metrics.incr('client-api.all-versions.responses.%sxx' % ( str(response.status_code)[0], )) if helper.context.version: metrics.incr('client-api.v%s.requests' % ( helper.context.version, )) metrics.incr('client-api.v%s.responses.%s' % ( helper.context.version, response.status_code )) metrics.incr('client-api.v%s.responses.%sxx' % ( helper.context.version, str(response.status_code)[0] )) if response.status_code != 200 and origin: # We allow all origins on errors response['Access-Control-Allow-Origin'] = '*' if origin: response['Access-Control-Allow-Headers'] = \ 'X-Sentry-Auth, X-Requested-With, Origin, Accept, ' \ 'Content-Type, Authentication' response['Access-Control-Allow-Methods'] = \ ', '.join(self._allowed_methods()) return response
def dispatch(self, request, project_id=None, *args, **kwargs): helper = None try: helper = ClientApiHelper( agent=request.META.get("HTTP_USER_AGENT"), project_id=project_id, ip_address=request.META["REMOTE_ADDR"], ) # if the project id is not directly specified get it from the authentication information project_id = _get_project_id_from_request( project_id, request, self.auth_helper_cls, helper ) project_config = get_project_config(project_id, for_store=True) helper.context.bind_project(project_config.project) if kafka_publisher is not None: self._publish_to_kafka(request, project_config) origin = self.auth_helper_cls.origin_from_request(request) response = self._dispatch( request, helper, project_config, origin=origin, *args, **kwargs ) except APIError as e: context = {"error": force_bytes(e.msg, errors="replace")} if e.name: context["error_name"] = e.name response = HttpResponse( json.dumps(context), content_type="application/json", status=e.http_status ) # Set X-Sentry-Error as in many cases it is easier to inspect the headers response["X-Sentry-Error"] = context["error"] if isinstance(e, APIRateLimited) and e.retry_after is not None: response["Retry-After"] = six.text_type(int(math.ceil(e.retry_after))) except Exception as e: # TODO(dcramer): test failures are not outputting the log message # here if settings.DEBUG: content = traceback.format_exc() else: content = "" logger.exception(e) response = HttpResponse(content, content_type="text/plain", status=500) # TODO(dcramer): it'd be nice if we had an incr_multi method so # tsdb could optimize this metrics.incr("client-api.all-versions.requests", skip_internal=False) metrics.incr( "client-api.all-versions.responses.%s" % (response.status_code,), skip_internal=False ) metrics.incr( "client-api.all-versions.responses.%sxx" % (six.text_type(response.status_code)[0],), skip_internal=False, ) if helper is not None and helper.context is not None and helper.context.version: metrics.incr("client-api.v%s.requests" % (helper.context.version,), skip_internal=False) metrics.incr( "client-api.v%s.responses.%s" % (helper.context.version, response.status_code), skip_internal=False, ) metrics.incr( "client-api.v%s.responses.%sxx" % (helper.context.version, six.text_type(response.status_code)[0]), skip_internal=False, ) return response
def dispatch(self, request, project_id=None, *args, **kwargs): helper = ClientApiHelper( agent=request.META.get('HTTP_USER_AGENT'), project_id=project_id, ip_address=request.META['REMOTE_ADDR'], ) origin = None try: origin = helper.origin_from_request(request) response = self._dispatch(request, helper, project_id=project_id, origin=origin, *args, **kwargs) except APIError as e: context = { 'error': force_bytes(e.msg, errors='replace'), } if e.name: context['error_name'] = e.name response = HttpResponse(json.dumps(context), content_type='application/json', status=e.http_status) # Set X-Sentry-Error as in many cases it is easier to inspect the headers response['X-Sentry-Error'] = context['error'] if isinstance(e, APIRateLimited) and e.retry_after is not None: response['Retry-After'] = str(e.retry_after) except Exception: if settings.DEBUG or True: content = traceback.format_exc() else: content = '' traceback.print_exc() response = HttpResponse(content, content_type='text/plain', status=500) # TODO(dcramer): it'd be nice if we had an incr_multi method so # tsdb could optimize this metrics.incr('client-api.all-versions.requests') metrics.incr('client-api.all-versions.responses.%s' % ( response.status_code, )) metrics.incr('client-api.all-versions.responses.%sxx' % ( str(response.status_code)[0], )) if helper.context.version: metrics.incr('client-api.v%s.requests' % ( helper.context.version, )) metrics.incr('client-api.v%s.responses.%s' % ( helper.context.version, response.status_code )) metrics.incr('client-api.v%s.responses.%sxx' % ( helper.context.version, str(response.status_code)[0] )) if response.status_code != 200 and origin: # We allow all origins on errors response['Access-Control-Allow-Origin'] = '*' if origin: response['Access-Control-Allow-Headers'] = \ 'X-Sentry-Auth, X-Requested-With, Origin, Accept, ' \ 'Content-Type, Authentication' response['Access-Control-Allow-Methods'] = \ ', '.join(self._allowed_methods()) return response