base.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. from __future__ import annotations
  2. import logging
  3. import sys
  4. from collections.abc import Mapping
  5. from typing import TYPE_CHECKING, Any, NoReturn
  6. import sentry_plugins
  7. from sentry.exceptions import InvalidIdentity, PluginError
  8. from sentry.shared_integrations.constants import (
  9. ERR_INTERNAL,
  10. ERR_UNAUTHORIZED,
  11. ERR_UNSUPPORTED_RESPONSE_TYPE,
  12. )
  13. from sentry.shared_integrations.exceptions import (
  14. ApiError,
  15. ApiHostError,
  16. ApiUnauthorized,
  17. UnsupportedResponseType,
  18. )
  19. if TYPE_CHECKING:
  20. from django.utils.functional import _StrPromise
  21. class CorePluginMixin:
  22. author: str | None = "Sentry Team"
  23. author_url: str | None = "https://github.com/getsentry/sentry"
  24. version: str | None = sentry_plugins.VERSION
  25. resource_links = [
  26. ("Report Issue", "https://github.com/getsentry/sentry/issues"),
  27. ("View Source", "https://github.com/getsentry/sentry/tree/master/src/sentry_plugins"),
  28. ]
  29. # HACK(dcramer): work around MRO issue with plugin metaclass
  30. logger = logging.getLogger(__name__)
  31. # from `Plugin` metaclass
  32. title: str | _StrPromise
  33. # TODO(dcramer): The following is a possible "better implementation" of the
  34. # core issue implementation, though it would need a compat layer to push
  35. # it upstream
  36. def error_message_from_json(self, data: Mapping[str, Any]) -> str:
  37. return data.get("message", "unknown error")
  38. def message_from_error(self, exc: BaseException) -> str:
  39. if isinstance(exc, ApiUnauthorized):
  40. return ERR_UNAUTHORIZED
  41. elif isinstance(exc, ApiHostError):
  42. return exc.text
  43. elif isinstance(exc, UnsupportedResponseType):
  44. return ERR_UNSUPPORTED_RESPONSE_TYPE.format(content_type=exc.content_type)
  45. elif isinstance(exc, ApiError):
  46. if exc.json:
  47. msg = self.error_message_from_json(exc.json) or "unknown error"
  48. else:
  49. msg = getattr(exc, "text", "unknown error")
  50. return f"Error Communicating with {self.title} (HTTP {exc.code}): {msg}"
  51. else:
  52. return ERR_INTERNAL
  53. def raise_error(self, exc: BaseException, identity: Any = None) -> NoReturn:
  54. if isinstance(exc, ApiUnauthorized):
  55. raise InvalidIdentity(self.message_from_error(exc), identity=identity).with_traceback(
  56. sys.exc_info()[2]
  57. )
  58. elif isinstance(exc, ApiError):
  59. raise PluginError(self.message_from_error(exc)).with_traceback(sys.exc_info()[2])
  60. elif isinstance(exc, PluginError):
  61. raise
  62. else:
  63. self.logger.exception(str(exc))
  64. raise PluginError(self.message_from_error(exc)).with_traceback(sys.exc_info()[2])