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)
Exemple #3
0
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)
Exemple #4
0
    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)
                    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)
Exemple #6
0
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'
Exemple #11
0
    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)
Exemple #12
0
    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
        ]
Exemple #14
0
    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)
Exemple #15
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')
Exemple #16
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")
Exemple #17
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()
Exemple #18
0
    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
Exemple #19
0
    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
Exemple #20
0
    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)
Exemple #22
0
    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)
Exemple #23
0
    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
Exemple #24
0
    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)
Exemple #25
0
    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
Exemple #26
0
    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
Exemple #27
0
    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