예제 #1
0
    def __exit__(self, exc_type, exc_value, tb):
        # type: (Any, Any, Any) -> None
        current_len = len(self._hub._stack)
        if current_len < self._original_len:
            logger.error(
                "Scope popped too soon. Popped %s scopes too many.",
                self._original_len - current_len,
            )
            return
        elif current_len > self._original_len:
            logger.warning(
                "Leaked %s scopes: %s",
                current_len - self._original_len,
                self._hub._stack[self._original_len:],
            )

        layer = self._hub._stack[self._original_len - 1]
        del self._hub._stack[self._original_len - 1:]

        if layer[1] != self._layer[1]:
            logger.error(
                "Wrong scope found. Meant to pop %s, but popped %s.",
                layer[1],
                self._layer[1],
            )
        elif layer[0] != self._layer[0]:
            warning = (
                "init() called inside of pushed scope. This might be entirely "
                "legitimate but usually occurs when initializing the SDK inside "
                "a request handler or task/job function. Try to initialize the "
                "SDK as early as possible instead.")
            logger.warning(warning)
예제 #2
0
    def _send_request(
            self,
            body,  # type: bytes
            headers,  # type: Dict[str, str]
            endpoint_type="store",  # type: EndpointType
    ):
        # type: (...) -> None
        response = self._session.request(
            "POST",
            str(self._auth.get_api_url(endpoint_type)),
            body=body,
            headers=headers,
        )

        self._update_rate_limits(response)
        if response.status == 429:
            # if we hit a 429.  Something was rate limited but we already
            # acted on this in `self._update_rate_limits`.
            pass

        elif response.status >= 300 or response.status < 200:
            logger.error(
                "Unexpected status code: %s (body: %s)",
                response.status,
                response.data,
            )
예제 #3
0
    def _send_request(
            self,
            body,  # type: bytes
            headers,  # type: Dict[str, str]
    ):
        # type: (...) -> None
        headers.update({
            "User-Agent": str(self._auth.client),
            "X-Sentry-Auth": str(self._auth.to_header()),
        })
        response = self._pool.request("POST",
                                      str(self._auth.store_api_url),
                                      body=body,
                                      headers=headers)

        try:
            self._update_rate_limits(response)

            if response.status == 429:
                # if we hit a 429.  Something was rate limited but we already
                # acted on this in `self._update_rate_limits`.
                pass

            elif response.status >= 300 or response.status < 200:
                logger.error(
                    "Unexpected status code: %s (body: %s)",
                    response.status,
                    response.data,
                )
        finally:
            response.close()
예제 #4
0
 def _capture_internal_exception(
         self,
         exc_info  # type: _OptExcInfo
 ):
     # type: (...) -> Any
     """Capture an exception that is likely caused by a bug in the SDK
     itself."""
     logger.error("Internal error in sentry_sdk",
                  exc_info=exc_info)  # type: ignore
예제 #5
0
    def _capture_internal_exception(
        self, exc_info  # type: Any
    ):
        # type: (...) -> Any
        """
        Capture an exception that is likely caused by a bug in the SDK
        itself.

        These exceptions do not end up in Sentry and are just logged instead.
        """
        logger.error("Internal error in sentry_sdk", exc_info=exc_info)  # type: ignore
예제 #6
0
    def _send_request(
            self,
            body,  # type: bytes
            headers,  # type: Dict[str, str]
            endpoint_type="store",  # type: EndpointType
            envelope=None,  # type: Optional[Envelope]
    ):
        # type: (...) -> None

        def record_loss(reason):
            # type: (str) -> None
            if envelope is None:
                self.record_lost_event(reason, data_category="error")
            else:
                for item in envelope.items:
                    self.record_lost_event(reason, item=item)

        headers.update({
            "User-Agent": str(self._auth.client),
            "X-Sentry-Auth": str(self._auth.to_header()),
        })
        try:
            response = self._pool.request(
                "POST",
                str(self._auth.get_api_url(endpoint_type)),
                body=body,
                headers=headers,
            )
        except Exception:
            self.on_dropped_event("network")
            record_loss("network_error")
            raise

        try:
            self._update_rate_limits(response)

            if response.status == 429:
                # if we hit a 429.  Something was rate limited but we already
                # acted on this in `self._update_rate_limits`.  Note that we
                # do not want to record event loss here as we will have recorded
                # an outcome in relay already.
                self.on_dropped_event("status_429")
                pass

            elif response.status >= 300 or response.status < 200:
                logger.error(
                    "Unexpected status code: %s (body: %s)",
                    response.status,
                    response.data,
                )
                self.on_dropped_event("status_{}".format(response.status))
                record_loss("network_error")
        finally:
            response.close()
예제 #7
0
    def _wait_flush(self, timeout, callback):
        # type: (float, Optional[Any]) -> None
        initial_timeout = min(0.1, timeout)
        if not self._timed_queue_join(initial_timeout):
            pending = self._queue.qsize() + 1
            logger.debug("%d event(s) pending on flush", pending)
            if callback is not None:
                callback(pending, timeout)

            if not self._timed_queue_join(timeout - initial_timeout):
                pending = self._queue.qsize() + 1
                logger.error("flush timed out, dropped %s events", pending)
예제 #8
0
    def _send_event(
            self,
            event  # type: Event
    ):
        # type: (...) -> None
        if self._disabled_until is not None:
            if datetime.utcnow() < self._disabled_until:
                return
            self._disabled_until = None

        body = io.BytesIO()
        with gzip.GzipFile(fileobj=body, mode="w") as f:
            f.write(json.dumps(event, allow_nan=False).encode("utf-8"))

        assert self.parsed_dsn is not None
        logger.debug(
            "Sending event, type:%s level:%s event_id:%s project:%s host:%s" %
            (
                event.get("type") or "null",
                event.get("level") or "null",
                event.get("event_id") or "null",
                self.parsed_dsn.project_id,
                self.parsed_dsn.host,
            ))
        response = self._pool.request(
            "POST",
            str(self._auth.store_api_url),
            body=body.getvalue(),
            headers={
                "User-Agent": str(self._auth.client),
                "X-Sentry-Auth": str(self._auth.to_header()),
                "Content-Type": "application/json",
                "Content-Encoding": "gzip",
            },
        )

        try:
            if response.status == 429:
                self._disabled_until = datetime.utcnow() + timedelta(
                    seconds=self._retry.get_retry_after(response) or 60)
                return

            elif response.status >= 300 or response.status < 200:
                logger.error(
                    "Unexpected status code: %s (body: %s)",
                    response.status,
                    response.data,
                )
        finally:
            response.close()

        self._disabled_until = None
예제 #9
0
 def _target(self):
     while True:
         callback = self._queue.get()
         try:
             if callback is _TERMINATOR:
                 break
             try:
                 callback()
             except Exception:
                 logger.error("Failed processing job", exc_info=True)
         finally:
             self._queue.task_done()
         sleep(0)
예제 #10
0
    def _send_request(
        self,
        body,  # type: bytes
        headers,  # type: Dict[str, str]
        endpoint_type="store",  # type: EndpointType
    ):
        # type: (...) -> None
        headers.update(
            {
                "User-Agent": str(self._auth.client),
                "X-Sentry-Auth": str(self._auth.to_header()),
            }
        )
        try:
            response = self._pool.request(
                "POST",
                str(self._auth.get_api_url(endpoint_type)),
                body=body,
                headers=headers,
            )
        except Exception:
            self.on_dropped_event("network")
            raise

        try:
            self._update_rate_limits(response)

            if response.status == 429:
                # if we hit a 429.  Something was rate limited but we already
                # acted on this in `self._update_rate_limits`.
                self.on_dropped_event("status_429")
                pass

            elif response.status >= 300 or response.status < 200:
                logger.error(
                    "Unexpected status code: %s (body: %s)",
                    response.status,
                    response.data,
                )
                self.on_dropped_event("status_{}".format(response.status))
        finally:
            response.close()
예제 #11
0
 def _capture_internal_exception(self, exc_info):
     """Capture an exception that is likely caused by a bug in the SDK
     itself."""
     logger.error("Internal error in sentry_sdk", exc_info=exc_info)
예제 #12
0
 def on_full_queue(self, callback):
     # type: (Optional[Any]) -> None
     logger.error("background worker queue full, dropping event")