You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

113 lines
3.8 KiB

  1. # Copyright 2016-2017 Versada <https://versada.eu/>
  2. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
  3. import logging
  4. import odoo.http
  5. from odoo.service import wsgi_server
  6. from odoo.tools import config as odoo_config
  7. from . import const
  8. from .logutils import SanitizeOdooCookiesProcessor, fetch_git_sha
  9. from .logutils import InvalidGitRepository, get_extra_context
  10. import collections
  11. _logger = logging.getLogger(__name__)
  12. HAS_SENTRY_SDK = True
  13. try:
  14. import sentry_sdk
  15. from sentry_sdk.integrations.wsgi import SentryWsgiMiddleware
  16. from sentry_sdk.integrations.threading import ThreadingIntegration
  17. from sentry_sdk.integrations.logging import ignore_logger
  18. except ImportError: # pragma: no cover
  19. HAS_SENTRY_SDK = False # pragma: no cover
  20. _logger.debug("Cannot import 'sentry-sdk'.\
  21. Please make sure it is installed.") # pragma: no cover
  22. def before_send(event, hint):
  23. """ Add context to event if include_context is True
  24. and sanitize sensitive data """
  25. if event.setdefault("tags", {})["include_context"]:
  26. cxtest = get_extra_context(odoo.http.request)
  27. info_request = ["tags", "user", "extra", "request"]
  28. for item in info_request:
  29. info_item = event.setdefault(item, {})
  30. info_item.update(cxtest.setdefault(item, {}))
  31. raven_processor = SanitizeOdooCookiesProcessor()
  32. raven_processor.process(event)
  33. return event
  34. def get_odoo_commit(odoo_dir):
  35. """Attempts to get Odoo git commit from :param:`odoo_dir`."""
  36. if not odoo_dir:
  37. return
  38. try:
  39. return fetch_git_sha(odoo_dir)
  40. except InvalidGitRepository:
  41. _logger.debug(
  42. "Odoo directory: '%s' not a valid git repository", odoo_dir)
  43. def initialize_sentry(config):
  44. """ Setup an instance of :class:`sentry_sdk.Client`.
  45. :param config: Sentry configuration
  46. :param client: class used to instantiate the sentry_sdk client.
  47. """
  48. enabled = config.get("sentry_enabled", False)
  49. if not (HAS_SENTRY_SDK and enabled):
  50. return
  51. _logger.info("Initializing sentry...")
  52. if config.get("sentry_odoo_dir") and config.get("sentry_release"):
  53. _logger.debug("Both sentry_odoo_dir and \
  54. sentry_release defined, choosing sentry_release")
  55. options = {
  56. "release": config.get("sentry_release",
  57. get_odoo_commit(config.get("sentry_odoo_dir"))),
  58. }
  59. for option in const.get_sentry_options():
  60. value = config.get('sentry_%s' % option.key, option.default)
  61. if isinstance(option.converter, collections.Callable):
  62. value = option.converter(value)
  63. options[option.key] = value
  64. exclude_loggers = const.split_multiple(
  65. config.get("sentry_exclude_loggers", const.DEFAULT_EXCLUDE_LOGGERS)
  66. )
  67. # Change name `ignore_exceptions` (with raven)
  68. # to `ignore_errors' (sentry_sdk)
  69. options["ignore_errors"] = options["ignore_exceptions"]
  70. del options["ignore_exceptions"]
  71. options["before_send"] = before_send
  72. options["integrations"] = [options["logging_level"],
  73. ThreadingIntegration(propagate_hub=True)]
  74. # Remove logging_level, since in sentry_sdk is include in 'integrations'
  75. del options["logging_level"]
  76. client = sentry_sdk.init(**options)
  77. sentry_sdk.set_tag("include_context",
  78. config.get("sentry_include_context", True))
  79. if exclude_loggers:
  80. for item in exclude_loggers:
  81. ignore_logger(item)
  82. wsgi_server.application = SentryWsgiMiddleware(wsgi_server.application)
  83. with sentry_sdk.push_scope() as scope:
  84. scope.set_extra("debug", False)
  85. sentry_sdk.capture_message("Starting Odoo Server", "info")
  86. return client
  87. def post_load():
  88. initialize_sentry(odoo_config)