Beispiel #1
0
    def post_process(self, event, **kwargs):
        rl_key = u"{}:{}".format(self.conf_key, event.project.organization_id)
        # limit segment to 50 requests/second
        limit, window = self.get_rate_limit()
        if limit and window and ratelimits.is_limited(
                rl_key, limit=limit, window=window):
            logger.info(
                "data_forwarding.skip_rate_limited",
                extra={
                    "event_id": event.event_id,
                    "issue_id": event.group_id,
                    "project_id": event.project_id,
                    "organization_id": event.project.organization_id,
                },
            )
            return

        payload = self.get_event_payload(event)
        success = self.forward_event(event, payload)
        if success is False:
            # TODO(dcramer): record failure
            pass
        tsdb.incr(tsdb.models.project_total_forwarded,
                  event.project.id,
                  count=1)
Beispiel #2
0
    def post(self, request, project, helper, **kwargs):
        data = helper.safely_load_json_string(request.body)

        # Do origin check based on the `document-uri` key as explained
        # in `_dispatch`.
        try:
            report = data['csp-report']
        except KeyError:
            raise APIError('Missing csp-report')

        origin = report.get('document-uri')

        # No idea, but this is garbage
        if origin == 'about:blank':
            raise APIForbidden('Invalid document-uri')

        if not is_valid_origin(origin, project):
            if project:
                tsdb.incr(tsdb.models.project_total_received_cors, project.id)
            raise APIForbidden('Invalid document-uri')

        # Attach on collected meta data. This data obviously isn't a part
        # of the spec, but we need to append to the report sentry specific things.
        report['_meta'] = {
            'release': request.GET.get('sentry_release'),
        }

        response_or_event_id = self.process(request,
                                            project=project,
                                            helper=helper,
                                            data=report,
                                            **kwargs)
        if isinstance(response_or_event_id, HttpResponse):
            return response_or_event_id
        return HttpResponse(status=201)
Beispiel #3
0
def process_service_hook(servicehook_id, event, **kwargs):
    from sentry import tsdb
    from sentry.models import ServiceHook

    try:
        servicehook = ServiceHook.objects.get(id=servicehook_id)
    except ServiceHook.DoesNotExist:
        return

    tsdb.incr(tsdb.models.servicehook_fired, servicehook.id)

    if servicehook.version == 0:
        payload = get_payload_v0(event)
    else:
        raise NotImplementedError

    body = json.dumps(payload)

    headers = {
        'Content-Type': 'application/json',
        'X-ServiceHook-Timestamp': int(time()),
        'X-ServiceHook-GUID': servicehook.guid,
        'X-ServiceHook-Signature': servicehook.build_signature(body),
    }

    safe_urlopen(
        url=servicehook.url,
        body=body,
        headers=headers,
        timeout=5,
        verify_ssl=False,
    )
Beispiel #4
0
    def post(self, request, project, helper, **kwargs):
        json_body = helper.safely_load_json_string(request.body)
        report_type = self.security_report_type(json_body)
        if report_type is None:
            raise APIError('Unrecognized security report type')
        interface = get_interface(report_type)

        try:
            instance = interface.from_raw(json_body)
        except jsonschema.ValidationError as e:
            raise APIError('Invalid security report: %s' % str(e).splitlines()[0])

        # Do origin check based on the `document-uri` key as explained in `_dispatch`.
        origin = instance.get_origin()
        if not is_valid_origin(origin, project):
            if project:
                tsdb.incr(tsdb.models.project_total_received_cors, project.id)
            raise APIForbidden('Invalid origin')

        data = {
            'interface': interface.path,
            'report': instance,
            'release': request.GET.get('sentry_release'),
            'environment': request.GET.get('sentry_environment'),
        }

        response_or_event_id = self.process(
            request, project=project, helper=helper, data=data, **kwargs
        )
        if isinstance(response_or_event_id, HttpResponse):
            return response_or_event_id
        return HttpResponse(content_type='application/javascript', status=201)
Beispiel #5
0
    def post(self, request, project, helper, **kwargs):
        json_body = safely_load_json_string(request.body)
        report_type = self.security_report_type(json_body)
        if report_type is None:
            raise APIError('Unrecognized security report type')
        interface = get_interface(report_type)

        try:
            instance = interface.from_raw(json_body)
        except jsonschema.ValidationError as e:
            raise APIError('Invalid security report: %s' %
                           str(e).splitlines()[0])

        # Do origin check based on the `document-uri` key as explained in `_dispatch`.
        origin = instance.get_origin()
        if not is_valid_origin(origin, project):
            if project:
                tsdb.incr(tsdb.models.project_total_received_cors, project.id)
            raise APIForbidden('Invalid origin')

        data = {
            'interface': interface.path,
            'report': instance,
            'release': request.GET.get('sentry_release'),
            'environment': request.GET.get('sentry_environment'),
        }

        response_or_event_id = self.process(request,
                                            project=project,
                                            helper=helper,
                                            data=data,
                                            **kwargs)
        if isinstance(response_or_event_id, HttpResponse):
            return response_or_event_id
        return HttpResponse(content_type='application/javascript', status=201)
Beispiel #6
0
    def post(self, request, project, helper, **kwargs):
        data = helper.safely_load_json_string(request.body)

        # Do origin check based on the `document-uri` key as explained
        # in `_dispatch`.
        try:
            report = data['csp-report']
        except KeyError:
            raise APIError('Missing csp-report')

        origin = report.get('document-uri')

        # No idea, but this is garbage
        if origin == 'about:blank':
            raise APIForbidden('Invalid document-uri')

        if not is_valid_origin(origin, project):
            if project:
                tsdb.incr(tsdb.models.project_total_received_cors,
                          project.id)
            raise APIForbidden('Invalid document-uri')

        # Attach on collected meta data. This data obviously isn't a part
        # of the spec, but we need to append to the report sentry specific things.
        report['_meta'] = {
            'release': request.GET.get('sentry_release'),
        }

        response_or_event_id = self.process(
            request, project=project, helper=helper, data=report, **kwargs
        )
        if isinstance(response_or_event_id, HttpResponse):
            return response_or_event_id
        return HttpResponse(status=201)
Beispiel #7
0
def process_service_hook(servicehook_id, event, **kwargs):
    from sentry import tsdb
    from sentry.models import ServiceHook

    try:
        servicehook = ServiceHook.objects.get(id=servicehook_id)
    except ServiceHook.DoesNotExist:
        return

    tsdb.incr(tsdb.models.servicehook_fired, servicehook.id)

    if servicehook.version == 0:
        payload = get_payload_v0(event)
    else:
        raise NotImplementedError

    body = json.dumps(payload)

    headers = {
        'Content-Type': 'application/json',
        'X-ServiceHook-Timestamp': six.text_type(int(time())),
        'X-ServiceHook-GUID': servicehook.guid,
        'X-ServiceHook-Signature': servicehook.build_signature(body),
    }

    safe_urlopen(
        url=servicehook.url,
        data=body,
        headers=headers,
        timeout=5,
        verify_ssl=False,
    )
Beispiel #8
0
def process_service_hook(servicehook_id, event, **kwargs):
    try:
        servicehook = ServiceHook.objects.get(id=servicehook_id)
    except ServiceHook.DoesNotExist:
        return

    if servicehook.version == 0:
        payload = get_payload_v0(event)
    else:
        raise NotImplementedError

    from sentry import tsdb

    tsdb.incr(tsdb.models.servicehook_fired, servicehook.id)

    headers = {
        "Content-Type": "application/json",
        "X-ServiceHook-Timestamp": str(int(time())),
        "X-ServiceHook-GUID": servicehook.guid,
        "X-ServiceHook-Signature": servicehook.build_signature(json.dumps(payload)),
    }

    safe_urlopen(
        url=servicehook.url, data=json.dumps(payload), headers=headers, timeout=5, verify_ssl=False
    )
Beispiel #9
0
    def _dispatch(self, request, helper, project_id=None, origin=None, *args, **kwargs):
        request.user = AnonymousUser()

        project = self._get_project_from_id(project_id)
        if project:
            helper.context.bind_project(project)
            Raven.tags_context(helper.context.get_tags_context())

        if origin is not None:
            # This check is specific for clients who need CORS support
            if not project:
                raise APIError('Client must be upgraded for CORS support')
            if not is_valid_origin(origin, project):
                tsdb.incr(tsdb.models.project_total_received_cors,
                          project.id)
                raise APIForbidden('Invalid origin: %s' % (origin, ))

        # XXX: It seems that the OPTIONS call does not always include custom headers
        if request.method == 'OPTIONS':
            response = self.options(request, project)
        else:
            auth = self._parse_header(request, helper, project)

            key = helper.project_key_from_auth(auth)

            # Legacy API was /api/store/ and the project ID was only available elsewhere
            if not project:
                project = Project.objects.get_from_cache(id=key.project_id)
                helper.context.bind_project(project)
            elif key.project_id != project.id:
                raise APIError('Two different projects were specified')

            helper.context.bind_auth(auth)
            Raven.tags_context(helper.context.get_tags_context())

            # Explicitly bind Organization so we don't implicitly query it later
            # this just allows us to comfortably assure that `project.organization` is safe.
            # This also allows us to pull the object from cache, instead of being
            # implicitly fetched from database.
            project.organization = Organization.objects.get_from_cache(
                id=project.organization_id)

            response = super(APIView, self).dispatch(
                request=request, project=project, auth=auth, helper=helper, key=key, **kwargs
            )

        if origin:
            if origin == 'null':
                # If an Origin is `null`, but we got this far, that means
                # we've gotten past our CORS check for some reason. But the
                # problem is that we can't return "null" as a valid response
                # to `Access-Control-Allow-Origin` and we don't have another
                # value to work with, so just allow '*' since they've gotten
                # this far.
                response['Access-Control-Allow-Origin'] = '*'
            else:
                response['Access-Control-Allow-Origin'] = origin

        return response
Beispiel #10
0
    def _dispatch(self, request, helper, project_id=None, origin=None, *args, **kwargs):
        request.user = AnonymousUser()

        project = self._get_project_from_id(project_id)
        if project:
            helper.context.bind_project(project)
            Raven.tags_context(helper.context.get_tags_context())

        if origin is not None:
            # This check is specific for clients who need CORS support
            if not project:
                raise APIError('Client must be upgraded for CORS support')
            if not is_valid_origin(origin, project):
                tsdb.incr(tsdb.models.project_total_received_cors,
                          project.id)
                raise APIForbidden('Invalid origin: %s' % (origin, ))

        # XXX: It seems that the OPTIONS call does not always include custom headers
        if request.method == 'OPTIONS':
            response = self.options(request, project)
        else:
            auth = self._parse_header(request, helper, project)

            key = helper.project_key_from_auth(auth)

            # Legacy API was /api/store/ and the project ID was only available elsewhere
            if not project:
                project = Project.objects.get_from_cache(id=key.project_id)
                helper.context.bind_project(project)
            elif key.project_id != project.id:
                raise APIError('Two different projects were specified')

            helper.context.bind_auth(auth)
            Raven.tags_context(helper.context.get_tags_context())

            # Explicitly bind Organization so we don't implicitly query it later
            # this just allows us to comfortably assure that `project.organization` is safe.
            # This also allows us to pull the object from cache, instead of being
            # implicitly fetched from database.
            project.organization = Organization.objects.get_from_cache(
                id=project.organization_id)

            response = super(APIView, self).dispatch(
                request=request, project=project, auth=auth, helper=helper, key=key, **kwargs
            )

        if origin:
            if origin == 'null':
                # If an Origin is `null`, but we got this far, that means
                # we've gotten past our CORS check for some reason. But the
                # problem is that we can't return "null" as a valid response
                # to `Access-Control-Allow-Origin` and we don't have another
                # value to work with, so just allow '*' since they've gotten
                # this far.
                response['Access-Control-Allow-Origin'] = '*'
            else:
                response['Access-Control-Allow-Origin'] = origin

        return response
Beispiel #11
0
 def increment(self, event, count, environment_id, timestamp=None):
     tsdb.incr(
         tsdb.models.group,
         event.group_id,
         count=count,
         environment_id=environment_id,
         timestamp=timestamp,
     )
Beispiel #12
0
def save_event(cache_key=None,
               data=None,
               start_time=None,
               event_id=None,
               **kwargs):
    """
    Saves an event to the database.
    """
    from sentry.event_manager import HashDiscarded, EventManager
    from sentry import tsdb

    if cache_key:
        data = default_cache.get(cache_key)

    if event_id is None and data is not None:
        event_id = data['event_id']

    if data is None:
        metrics.incr('events.failed',
                     tags={
                         'reason': 'cache',
                         'stage': 'post'
                     })
        return

    project = data.pop('project')

    delete_raw_event(project, event_id, allow_hint_clear=True)

    Raven.tags_context({
        'project': project,
    })

    try:
        manager = EventManager(data)
        manager.save(project)
    except HashDiscarded as exc:
        # TODO(jess): remove this before it goes out to a wider audience
        info_logger.info('discarded.hash',
                         extra={
                             'project_id': project,
                             'description': exc.message,
                         })
        tsdb.incr(
            tsdb.models.project_total_received_discarded,
            project,
            timestamp=to_datetime(start_time)
            if start_time is not None else None,
        )
    finally:
        if cache_key:
            default_cache.delete(cache_key)
        if start_time:
            metrics.timing('events.time-to-process',
                           time() - start_time,
                           instance=data['platform'])
Beispiel #13
0
    def post_process(self, event, **kwargs):
        if self.is_ratelimited(event):
            return

        payload = self.get_event_payload(event)
        success = self.forward_event(event, payload)
        if success is False:
            # TODO(dcramer): record failure
            pass
        tsdb.incr(tsdb.models.project_total_forwarded, event.project.id, count=1)
Beispiel #14
0
    def test_str_key_id(self):
        tsdb.incr(tsdb.models.key_total_received, self.key.id, count=1)
        tsdb.incr(tsdb.models.key_total_received, str(self.key.id), count=1)

        response = self.client.get(self.path)
        assert response.status_code == 200

        assert response.status_code == 200, response.content
        assert response.data[-1]["total"] == 2, response.data
        for point in response.data[:-1]:
            assert point["total"] == 0
        assert len(response.data) == 24
Beispiel #15
0
    def test_rate_reached(self, mock_now):
        mock_now.return_value = datetime(2016, 8, 1, 0, 0, 0, 0, tzinfo=timezone.utc)

        snooze = GroupSnooze.objects.create(group=self.group, count=100, window=24 * 60)
        for n in range(6):
            tsdb.incr(
                tsdb.models.group,
                self.group.id,
                count=20,
                timestamp=mock_now() - timedelta(minutes=n),
            )
        assert not snooze.is_valid(test_rates=True)
Beispiel #16
0
    def test_str_key_id(self):
        tsdb.incr(tsdb.models.key_total_received, self.key.id, count=1)
        tsdb.incr(tsdb.models.key_total_received, six.text_type(self.key.id), count=1)

        response = self.client.get(self.path)
        assert response.status_code == 200

        assert response.status_code == 200, response.content
        assert response.data[-1]['total'] == 2, response.data
        for point in response.data[:-1]:
            assert point['total'] == 0
        assert len(response.data) == 24
Beispiel #17
0
    def test_simple(self):
        tsdb.incr(tsdb.models.key_total_received, self.key.id, count=3)
        tsdb.incr(tsdb.models.key_total_blacklisted, self.key.id, count=1)

        response = self.client.get(self.path)
        assert response.status_code == 200

        assert response.status_code == 200, response.content
        assert response.data[-1]['total'] == 3, response.data
        assert response.data[-1]['filtered'] == 1, response.data
        for point in response.data[:-1]:
            assert point['total'] == 0
        assert len(response.data) == 24
    def test_simple(self):
        tsdb.incr(tsdb.models.key_total_received, self.key.id, count=3)
        tsdb.incr(tsdb.models.key_total_blacklisted, self.key.id, count=1)

        response = self.client.get(self.path)
        assert response.status_code == 200

        assert response.status_code == 200, response.content
        assert response.data[-1]['total'] == 3, response.data
        assert response.data[-1]['filtered'] == 1, response.data
        for point in response.data[:-1]:
            assert point['total'] == 0
        assert len(response.data) == 24
Beispiel #19
0
    def test_resolution(self):
        self.login_as(user=self.user)

        org = self.create_organization(owner=self.user)

        tsdb.incr(tsdb.models.organization_total_received, org.id, count=3)

        url = reverse("sentry-api-0-organization-stats", args=[org.slug])
        response = self.client.get("{}?resolution=1d".format(url))

        assert response.status_code == 200, response.content
        assert response.data[-1][1] == 3, response.data
        assert len(response.data) == 1
    def test_resolution(self):
        self.login_as(user=self.user)

        org = self.create_organization(owner=self.user)

        tsdb.incr(tsdb.models.organization_total_received, org.id, count=3)

        url = reverse('sentry-api-0-organization-stats', args=[org.slug])
        response = self.client.get('{}?resolution=1d'.format(url))

        assert response.status_code == 200, response.content
        assert response.data[-1][1] == 3, response.data
        assert len(response.data) == 1
    def test_simple(self):
        self.login_as(user=self.user)

        org = self.create_organization(owner=self.user)

        tsdb.incr(tsdb.models.organization_total_received, org.id, count=3)

        url = reverse('sentry-api-0-organization-stats', args=[org.slug])
        response = self.client.get(url)

        assert response.status_code == 200, response.content
        assert response.data[-1][1] == 3, response.data
        for point in response.data[:-1]:
            assert point[1] == 0
        assert len(response.data) == 24
Beispiel #22
0
def _incr_internal(key, instance=None, tags=None, amount=1):
    from sentry import tsdb

    if _should_sample():
        amount = _sampled_value(amount)
        if instance:
            full_key = '{}.{}'.format(key, instance)
        else:
            full_key = key

        try:
            tsdb.incr(tsdb.models.internal, full_key, count=amount)
        except Exception:
            logger = logging.getLogger('sentry.errors')
            logger.exception('Unable to incr internal metric')
Beispiel #23
0
    def test_simple(self):
        self.login_as(user=self.user)

        org = self.create_organization(owner=self.user)

        tsdb.incr(tsdb.models.organization_total_received, org.id, count=3)

        url = reverse("sentry-api-0-organization-stats", args=[org.slug])
        response = self.client.get(url)

        assert response.status_code == 200, response.content
        assert response.data[-1][1] == 3, response.data
        for point in response.data[:-1]:
            assert point[1] == 0
        assert len(response.data) == 24
Beispiel #24
0
def _incr_internal(key, instance=None, tags=None, amount=1):
    from sentry import tsdb

    if _should_sample():
        amount = _sampled_value(amount)
        if instance:
            full_key = '{}.{}'.format(key, instance)
        else:
            full_key = key

        try:
            tsdb.incr(tsdb.models.internal, full_key, count=amount)
        except Exception:
            logger = logging.getLogger('sentry.errors')
            logger.exception('Unable to incr internal metric')
Beispiel #25
0
    def test_rate_reached(self, mock_now):
        mock_now.return_value = datetime(2016, 8, 1, 0, 0, 0, 0, tzinfo=timezone.utc)

        snooze = GroupSnooze.objects.create(
            group=self.group,
            count=100,
            window=24 * 60,
        )
        for n in range(6):
            tsdb.incr(
                tsdb.models.group,
                self.group.id,
                count=20,
                timestamp=mock_now() - timedelta(minutes=n),
            )
        assert not snooze.is_valid(test_rates=True)
Beispiel #26
0
    def post_process(self, event, **kwargs):
        rl_key = '{}:{}'.format(
            self.conf_key,
            event.project.organization_id,
        )
        # limit segment to 50 requests/second
        limit, window = self.get_rate_limit()
        if limit and window and ratelimits.is_limited(rl_key, limit=limit, window=window):
            return

        payload = self.get_event_payload(event)
        success = self.forward_event(event, payload)
        if success is False:
            # TODO(dcramer): record failure
            pass
        tsdb.incr(tsdb.models.project_total_forwarded, event.project.id, count=1)
Beispiel #27
0
        def worker():
            from sentry import tsdb

            while True:
                key, instance, tags, amount, sample_rate = q.get()
                amount = _sampled_value(amount, sample_rate)
                if instance:
                    full_key = u"{}.{}".format(key, instance)
                else:
                    full_key = key
                try:
                    tsdb.incr(tsdb.models.internal, full_key, count=amount)
                except Exception:
                    logger = logging.getLogger("sentry.errors")
                    logger.exception("Unable to incr internal metric")
                finally:
                    q.task_done()
Beispiel #28
0
        def worker():
            from sentry import tsdb

            while True:
                key, instance, tags, amount = q.get()
                amount = _sampled_value(amount)
                if instance:
                    full_key = u'{}.{}'.format(key, instance)
                else:
                    full_key = key
                try:
                    tsdb.incr(tsdb.models.internal, full_key, count=amount)
                except Exception:
                    logger = logging.getLogger('sentry.errors')
                    logger.exception('Unable to incr internal metric')
                finally:
                    q.task_done()
Beispiel #29
0
def save_event(cache_key=None, data=None, start_time=None, event_id=None, **kwargs):
    """
    Saves an event to the database.
    """
    from sentry.event_manager import HashDiscarded, EventManager
    from sentry import tsdb

    if cache_key:
        data = default_cache.get(cache_key)

    if event_id is None and data is not None:
        event_id = data['event_id']

    if data is None:
        metrics.incr('events.failed', tags={'reason': 'cache', 'stage': 'post'})
        return

    project = data.pop('project')

    delete_raw_event(project, event_id, allow_hint_clear=True)

    Raven.tags_context({
        'project': project,
    })

    try:
        manager = EventManager(data)
        manager.save(project)
    except HashDiscarded as exc:
        # TODO(jess): remove this before it goes out to a wider audience
        info_logger.info(
            'discarded.hash', extra={
                'project_id': project,
                'description': exc.message,
            }
        )
        tsdb.incr(tsdb.models.project_total_received_discarded, project, timestamp=start_time)
    finally:
        if cache_key:
            default_cache.delete(cache_key)
        if start_time:
            metrics.timing(
                'events.time-to-process',
                time() - start_time,
                instance=data['platform'])
Beispiel #30
0
def send_request(servicehook, payload, verify_ssl=None):
    from sentry import tsdb
    tsdb.incr(tsdb.models.servicehook_fired, servicehook.id)

    headers = {
        'Content-Type': 'application/json',
        'X-ServiceHook-Timestamp': six.text_type(int(time())),
        'X-ServiceHook-GUID': servicehook.guid,
        'X-ServiceHook-Signature': servicehook.build_signature(json.dumps(payload)),
    }

    safe_urlopen(
        url=servicehook.url,
        data=json.dumps(payload),
        headers=headers,
        timeout=5,
        verify_ssl=(verify_ssl or False),
    )
    def test_simple(self):
        project = self.create_project()
        hook = ServiceHook.objects.get_or_create(project_id=project.id,
                                                 actor_id=self.user.id,
                                                 url="http://example.com")[0]
        self.login_as(user=self.user)
        path = "/api/0/projects/{}/{}/hooks/{}/stats/".format(
            project.organization.slug, project.slug, hook.guid)

        tsdb.incr(tsdb.models.servicehook_fired, hook.id, count=3)

        response = self.client.get(path)
        assert response.status_code == 200

        assert response.status_code == 200, response.content
        assert response.data[-1]["total"] == 3, response.data
        for point in response.data[:-1]:
            assert point["total"] == 0
        assert len(response.data) == 24
    def test_simple(self):
        self.login_as(user=self.user)

        project1 = self.create_project(name='foo')
        project2 = self.create_project(name='bar')

        tsdb.incr(tsdb.models.project_total_received, project1.id, count=3)
        tsdb.incr(tsdb.models.project_total_received, project2.id, count=5)

        url = reverse('sentry-api-0-project-stats', kwargs={
            'organization_slug': project1.organization.slug,
            'project_slug': project1.slug,
        })
        response = self.client.get(url, format='json')

        assert response.status_code == 200, response.content
        assert response.data[-1][1] == 3, response.data
        for point in response.data[:-1]:
            assert point[1] == 0
        assert len(response.data) == 24
    def post(self, request, sentry_app):
        """
        Increment a TSDB metric relating to Sentry App interactions

        :param string tsdbField         the name of the TSDB model to increment
        :param string componentType     required for 'sentry_app_component_interacted' metric
        """
        # Request should have identifier field stored in TSDBModel
        tsdb_field = request.data.get("tsdbField", "")

        model = getattr(tsdb.models, tsdb_field, None)
        if model is None or model not in TSDB_MODELS:
            return Response(
                {
                    "detail":
                    "The tsdbField must be one of: sentry_app_viewed, sentry_app_component_interacted"
                },
                status=400,
            )

        if model == tsdb.models.sentry_app_component_interacted:
            component_type = request.data.get("componentType", None)
            if component_type is None or component_type not in COMPONENT_TYPES:
                return Response(
                    {
                        "detail":
                        "The field componentType is required and must be one of %s"
                        % (COMPONENT_TYPES)
                    },
                    status=400,
                )

            key = get_component_interaction_key(sentry_app,
                                                request.data["componentType"])
        elif model == tsdb.models.sentry_app_viewed:
            key = sentry_app.id

        # Timestamp is automatically created
        tsdb.incr(model, key)

        return Response({}, status=201)
    def test_simple(self):
        self.login_as(user=self.user)

        project1 = self.create_project(name='foo')
        project2 = self.create_project(name='bar')

        tsdb.incr(tsdb.models.project_total_received, project1.id, count=3)
        tsdb.incr(tsdb.models.project_total_received, project2.id, count=5)

        url = reverse('sentry-api-0-project-stats',
                      kwargs={
                          'organization_slug': project1.organization.slug,
                          'project_slug': project1.slug,
                      })
        response = self.client.get(url, format='json')

        assert response.status_code == 200, response.content
        assert response.data[-1][1] == 3, response.data
        for point in response.data[:-1]:
            assert point[1] == 0
        assert len(response.data) == 24
    def test_simple(self):
        self.login_as(user=self.user)

        team = self.create_team(members=[self.user])
        project_1 = self.create_project(teams=[team], name='a')
        project_2 = self.create_project(teams=[team], name='b')
        team_2 = self.create_team(members=[self.user])
        project_3 = self.create_project(teams=[team_2], name='c')

        tsdb.incr(tsdb.models.project, project_1.id, count=3)
        tsdb.incr(tsdb.models.project, project_2.id, count=5)
        tsdb.incr(tsdb.models.project, project_3.id, count=10)

        url = reverse(
            'sentry-api-0-team-stats',
            kwargs={
                'organization_slug': team.organization.slug,
                'team_slug': team.slug,
            }
        )
        response = self.client.get(url)

        assert response.status_code == 200, response.content
        assert response.data[-1][1] == 8, response.data
        for point in response.data[:-1]:
            assert point[1] == 0
        assert len(response.data) == 24
Beispiel #36
0
def send_request(servicehook, payload, verify_ssl=None):
    from sentry import tsdb
    tsdb.incr(tsdb.models.servicehook_fired, servicehook.id)

    headers = {
        'Content-Type':
        'application/json',
        'X-ServiceHook-Timestamp':
        six.text_type(int(time())),
        'X-ServiceHook-GUID':
        servicehook.guid,
        'X-ServiceHook-Signature':
        servicehook.build_signature(json.dumps(payload)),
    }

    safe_urlopen(
        url=servicehook.url,
        data=json.dumps(payload),
        headers=headers,
        timeout=5,
        verify_ssl=(verify_ssl or False),
    )
    def test_simple(self):
        self.login_as(user=self.user)

        group1 = self.create_group()
        group2 = self.create_group()

        url = '/api/0/issues/{}/stats/'.format(group1.id)
        response = self.client.get(url, format='json')

        assert response.status_code == 200, response.content
        for point in response.data:
            assert point[1] == 0
        assert len(response.data) == 24

        tsdb.incr(tsdb.models.group, group1.id, count=3)
        tsdb.incr(tsdb.models.group, group2.id, count=5)

        response = self.client.get(url, format='json')

        assert response.status_code == 200, response.content
        assert response.data[-1][1] == 3, response.data
        for point in response.data[:-1]:
            assert point[1] == 0
        assert len(response.data) == 24
    def test_simple(self):
        project = self.create_project()
        hook = ServiceHook.objects.get_or_create(
            project_id=project.id,
            actor_id=self.user.id,
            url='http://example.com',
        )[0]
        self.login_as(user=self.user)
        path = '/api/0/projects/{}/{}/hooks/{}/stats/'.format(
            project.organization.slug,
            project.slug,
            hook.guid,
        )

        tsdb.incr(tsdb.models.servicehook_fired, hook.id, count=3)

        response = self.client.get(path)
        assert response.status_code == 200

        assert response.status_code == 200, response.content
        assert response.data[-1]['total'] == 3, response.data
        for point in response.data[:-1]:
            assert point['total'] == 0
        assert len(response.data) == 24
Beispiel #39
0
    def test_simple(self):
        self.login_as(user=self.user)

        group1 = self.create_group()
        group2 = self.create_group()

        url = u'/api/0/issues/{}/stats/'.format(group1.id)
        response = self.client.get(url, format='json')

        assert response.status_code == 200, response.content
        for point in response.data:
            assert point[1] == 0
        assert len(response.data) == 24

        tsdb.incr(tsdb.models.group, group1.id, count=3)
        tsdb.incr(tsdb.models.group, group2.id, count=5)

        response = self.client.get(url, format='json')

        assert response.status_code == 200, response.content
        assert response.data[-1][1] == 3, response.data
        for point in response.data[:-1]:
            assert point[1] == 0
        assert len(response.data) == 24
Beispiel #40
0
    def test_get_error_message_stats(self):
        self.login_as(user=self.user)

        project1 = self.create_project(name="foo")

        STAT_OPTS = {
            "ip-address": 1,
            "release-version": 2,
            "error-message": 3,
            "browser-extensions": 4,
            "legacy-browsers": 5,
            "localhost": 6,
            "web-crawlers": 7,
            "invalid-csp": 8,
        }

        tsdb.incr(
            tsdb.models.project_total_received_ip_address,
            project1.id,
            count=STAT_OPTS["ip-address"],
        )
        tsdb.incr(
            tsdb.models.project_total_received_release_version,
            project1.id,
            count=STAT_OPTS["release-version"],
        )
        tsdb.incr(
            tsdb.models.project_total_received_error_message,
            project1.id,
            count=STAT_OPTS["error-message"],
        )
        tsdb.incr(
            tsdb.models.project_total_received_browser_extensions,
            project1.id,
            count=STAT_OPTS["browser-extensions"],
        )
        tsdb.incr(
            tsdb.models.project_total_received_legacy_browsers,
            project1.id,
            count=STAT_OPTS["legacy-browsers"],
        )
        tsdb.incr(tsdb.models.project_total_received_localhost,
                  project1.id,
                  count=STAT_OPTS["localhost"])
        tsdb.incr(
            tsdb.models.project_total_received_web_crawlers,
            project1.id,
            count=STAT_OPTS["web-crawlers"],
        )
        tsdb.incr(
            tsdb.models.project_total_received_invalid_csp,
            project1.id,
            count=STAT_OPTS["invalid-csp"],
        )

        url = reverse(
            "sentry-api-0-project-stats",
            kwargs={
                "organization_slug": project1.organization.slug,
                "project_slug": project1.slug
            },
        )
        for stat in STAT_OPTS.keys():
            response = self.client.get(url, {"stat": stat}, format="json")
            assert response.status_code == 200, response.content
            assert len(response.data) == 24
            assert response.data[-1][1] == STAT_OPTS[stat], response.data
Beispiel #41
0
def save_event(cache_key=None,
               data=None,
               start_time=None,
               event_id=None,
               **kwargs):
    """
    Saves an event to the database.
    """
    from sentry.event_manager import HashDiscarded, EventManager
    from sentry import quotas, tsdb
    from sentry.models import ProjectKey

    if cache_key:
        data = default_cache.get(cache_key)

    if event_id is None and data is not None:
        event_id = data['event_id']

    if data is None:
        metrics.incr('events.failed',
                     tags={
                         'reason': 'cache',
                         'stage': 'post'
                     })
        return

    project_id = data.pop('project')

    delete_raw_event(project_id, event_id, allow_hint_clear=True)

    Raven.tags_context({
        'project': project_id,
    })

    try:
        manager = EventManager(data)
        manager.save(project_id)
    except HashDiscarded:
        tsdb.incr(
            tsdb.models.project_total_received_discarded,
            project_id,
            timestamp=to_datetime(start_time)
            if start_time is not None else None,
        )

        try:
            project = Project.objects.get_from_cache(id=project_id)
        except Project.DoesNotExist:
            pass
        else:
            project_key = None
            if data.get('key_id') is not None:
                try:
                    project_key = ProjectKey.objects.get_from_cache(
                        id=data['key_id'])
                except ProjectKey.DoesNotExist:
                    pass

            quotas.refund(
                project,
                key=project_key,
                timestamp=start_time,
            )

    finally:
        if cache_key:
            default_cache.delete(cache_key)
        if start_time:
            metrics.timing('events.time-to-process',
                           time() - start_time,
                           instance=data['platform'])
Beispiel #42
0
    def test_get_error_message_stats(self):
        self.login_as(user=self.user)

        project1 = self.create_project(name='foo')

        STAT_OPTS = {
            'ip-address': 1,
            'release-version': 2,
            'error-message': 3,
            'browser-extensions': 4,
            'legacy-browsers': 5,
            'localhost': 6,
            'web-crawlers': 7,
            'invalid-csp': 8,
        }

        tsdb.incr(
            tsdb.models.project_total_received_ip_address,
            project1.id,
            count=STAT_OPTS['ip-address']
        )
        tsdb.incr(
            tsdb.models.project_total_received_release_version,
            project1.id,
            count=STAT_OPTS['release-version']
        )
        tsdb.incr(
            tsdb.models.project_total_received_error_message,
            project1.id,
            count=STAT_OPTS['error-message']
        )
        tsdb.incr(
            tsdb.models.project_total_received_browser_extensions,
            project1.id,
            count=STAT_OPTS['browser-extensions']
        )
        tsdb.incr(
            tsdb.models.project_total_received_legacy_browsers,
            project1.id,
            count=STAT_OPTS['legacy-browsers']
        )
        tsdb.incr(
            tsdb.models.project_total_received_localhost, project1.id, count=STAT_OPTS[
                'localhost']
        )
        tsdb.incr(
            tsdb.models.project_total_received_web_crawlers,
            project1.id,
            count=STAT_OPTS['web-crawlers']
        )
        tsdb.incr(
            tsdb.models.project_total_received_invalid_csp,
            project1.id,
            count=STAT_OPTS['invalid-csp']
        )

        url = reverse(
            'sentry-api-0-project-stats',
            kwargs={
                'organization_slug': project1.organization.slug,
                'project_slug': project1.slug,
            }
        )
        for stat in STAT_OPTS.keys():
            response = self.client.get(url, {'stat': stat}, format='json')
            assert response.status_code == 200, response.content
            assert len(response.data) == 24
            assert response.data[-1][1] == STAT_OPTS[stat], response.data