[IMP] sentry: black, isort
parent
165715b747
commit
532bdbdbfe
|
@ -22,41 +22,44 @@ except ImportError:
|
||||||
|
|
||||||
|
|
||||||
def get_odoo_commit(odoo_dir):
|
def get_odoo_commit(odoo_dir):
|
||||||
'''Attempts to get Odoo git commit from :param:`odoo_dir`.'''
|
"""Attempts to get Odoo git commit from :param:`odoo_dir`."""
|
||||||
if not odoo_dir:
|
if not odoo_dir:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
return raven.fetch_git_sha(odoo_dir)
|
return raven.fetch_git_sha(odoo_dir)
|
||||||
except raven.exceptions.InvalidGitRepository:
|
except raven.exceptions.InvalidGitRepository:
|
||||||
_logger.debug(
|
_logger.debug('Odoo directory: "%s" not a valid git repository', odoo_dir)
|
||||||
'Odoo directory: "%s" not a valid git repository', odoo_dir)
|
|
||||||
|
|
||||||
|
|
||||||
def initialize_raven(config, client_cls=None):
|
def initialize_raven(config, client_cls=None):
|
||||||
'''
|
"""
|
||||||
Setup an instance of :class:`raven.Client`.
|
Setup an instance of :class:`raven.Client`.
|
||||||
|
|
||||||
:param config: Sentry configuration
|
:param config: Sentry configuration
|
||||||
:param client: class used to instantiate the raven client.
|
:param client: class used to instantiate the raven client.
|
||||||
'''
|
"""
|
||||||
enabled = config.get('sentry_enabled', False)
|
enabled = config.get("sentry_enabled", False)
|
||||||
if not (HAS_RAVEN and enabled):
|
if not (HAS_RAVEN and enabled):
|
||||||
return
|
return
|
||||||
|
|
||||||
if config.get('sentry_odoo_dir') and config.get('sentry_release'):
|
if config.get("sentry_odoo_dir") and config.get("sentry_release"):
|
||||||
_logger.debug('Both sentry_odoo_dir and sentry_release defined, choosing sentry_release')
|
_logger.debug(
|
||||||
|
"Both sentry_odoo_dir and sentry_release defined, choosing sentry_release"
|
||||||
|
)
|
||||||
options = {
|
options = {
|
||||||
'release': config.get('sentry_release', get_odoo_commit(config.get('sentry_odoo_dir'))),
|
"release": config.get(
|
||||||
|
"sentry_release", get_odoo_commit(config.get("sentry_odoo_dir"))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
for option in const.get_sentry_options():
|
for option in const.get_sentry_options():
|
||||||
value = config.get('sentry_%s' % option.key, option.default)
|
value = config.get("sentry_%s" % option.key, option.default)
|
||||||
if isinstance(option.converter, collections.Callable):
|
if isinstance(option.converter, collections.Callable):
|
||||||
value = option.converter(value)
|
value = option.converter(value)
|
||||||
options[option.key] = value
|
options[option.key] = value
|
||||||
|
|
||||||
level = config.get('sentry_logging_level', const.DEFAULT_LOG_LEVEL)
|
level = config.get("sentry_logging_level", const.DEFAULT_LOG_LEVEL)
|
||||||
exclude_loggers = const.split_multiple(
|
exclude_loggers = const.split_multiple(
|
||||||
config.get('sentry_exclude_loggers', const.DEFAULT_EXCLUDE_LOGGERS)
|
config.get("sentry_exclude_loggers", const.DEFAULT_EXCLUDE_LOGGERS)
|
||||||
)
|
)
|
||||||
if level not in const.LOG_LEVEL_MAP:
|
if level not in const.LOG_LEVEL_MAP:
|
||||||
level = const.DEFAULT_LOG_LEVEL
|
level = const.DEFAULT_LOG_LEVEL
|
||||||
|
@ -64,18 +67,18 @@ def initialize_raven(config, client_cls=None):
|
||||||
client_cls = client_cls or raven.Client
|
client_cls = client_cls or raven.Client
|
||||||
client = client_cls(**options)
|
client = client_cls(**options)
|
||||||
handler = OdooSentryHandler(
|
handler = OdooSentryHandler(
|
||||||
config.get('sentry_include_context', True),
|
config.get("sentry_include_context", True),
|
||||||
client=client,
|
client=client,
|
||||||
level=const.LOG_LEVEL_MAP[level],
|
level=const.LOG_LEVEL_MAP[level],
|
||||||
)
|
)
|
||||||
if exclude_loggers:
|
if exclude_loggers:
|
||||||
handler.addFilter(LoggerNameFilter(
|
handler.addFilter(
|
||||||
exclude_loggers, name='sentry.logger.filter'))
|
LoggerNameFilter(exclude_loggers, name="sentry.logger.filter")
|
||||||
|
)
|
||||||
raven.conf.setup_logging(handler)
|
raven.conf.setup_logging(handler)
|
||||||
wsgi_server.application = Sentry(
|
wsgi_server.application = Sentry(wsgi_server.application, client=client)
|
||||||
wsgi_server.application, client=client)
|
|
||||||
|
|
||||||
client.captureMessage('Starting Odoo Server')
|
client.captureMessage("Starting Odoo Server")
|
||||||
return client
|
return client
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,24 +1,18 @@
|
||||||
# Copyright 2016-2017 Versada <https://versada.eu/>
|
# Copyright 2016-2017 Versada <https://versada.eu/>
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
{
|
{
|
||||||
'name': 'Sentry',
|
"name": "Sentry",
|
||||||
'summary': 'Report Odoo errors to Sentry',
|
"summary": "Report Odoo errors to Sentry",
|
||||||
'version': '12.0.1.0.0',
|
"version": "12.0.1.0.0",
|
||||||
'category': 'Extra Tools',
|
"category": "Extra Tools",
|
||||||
'website': 'https://odoo-community.org/',
|
"website": "https://odoo-community.org/",
|
||||||
'author': 'Mohammed Barsi,'
|
"author": "Mohammed Barsi,"
|
||||||
'Versada,'
|
"Versada,"
|
||||||
'Nicolas JEUDY,'
|
"Nicolas JEUDY,"
|
||||||
'Odoo Community Association (OCA)',
|
"Odoo Community Association (OCA)",
|
||||||
'license': 'AGPL-3',
|
"license": "AGPL-3",
|
||||||
'application': False,
|
"application": False,
|
||||||
'installable': True,
|
"installable": True,
|
||||||
'external_dependencies': {
|
"external_dependencies": {"python": ["raven"]},
|
||||||
'python': [
|
"depends": ["base"],
|
||||||
'raven',
|
|
||||||
]
|
|
||||||
},
|
|
||||||
'depends': [
|
|
||||||
'base',
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,76 +14,72 @@ except ImportError:
|
||||||
_logger.debug('Cannot import "raven". Please make sure it is installed.')
|
_logger.debug('Cannot import "raven". Please make sure it is installed.')
|
||||||
|
|
||||||
|
|
||||||
def split_multiple(string, delimiter=',', strip_chars=None):
|
def split_multiple(string, delimiter=",", strip_chars=None):
|
||||||
'''Splits :param:`string` and strips :param:`strip_chars` from values.'''
|
"""Splits :param:`string` and strips :param:`strip_chars` from values."""
|
||||||
if not string:
|
if not string:
|
||||||
return []
|
return []
|
||||||
return [v.strip(strip_chars) for v in string.split(delimiter)]
|
return [v.strip(strip_chars) for v in string.split(delimiter)]
|
||||||
|
|
||||||
|
|
||||||
SentryOption = collections.namedtuple(
|
SentryOption = collections.namedtuple("SentryOption", ["key", "default", "converter"])
|
||||||
'SentryOption', ['key', 'default', 'converter'])
|
|
||||||
|
|
||||||
# Mapping of Odoo logging level -> Python stdlib logging library log level.
|
# Mapping of Odoo logging level -> Python stdlib logging library log level.
|
||||||
LOG_LEVEL_MAP = dict([
|
LOG_LEVEL_MAP = {
|
||||||
(getattr(odoo.loglevels, 'LOG_%s' % x), getattr(logging, x))
|
getattr(odoo.loglevels, "LOG_%s" % x): getattr(logging, x)
|
||||||
for x in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'NOTSET')
|
for x in ("CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "NOTSET")
|
||||||
])
|
}
|
||||||
DEFAULT_LOG_LEVEL = 'warn'
|
DEFAULT_LOG_LEVEL = "warn"
|
||||||
|
|
||||||
ODOO_USER_EXCEPTIONS = [
|
ODOO_USER_EXCEPTIONS = [
|
||||||
'odoo.exceptions.AccessDenied',
|
"odoo.exceptions.AccessDenied",
|
||||||
'odoo.exceptions.AccessError',
|
"odoo.exceptions.AccessError",
|
||||||
'odoo.exceptions.DeferredException',
|
"odoo.exceptions.DeferredException",
|
||||||
'odoo.exceptions.MissingError',
|
"odoo.exceptions.MissingError",
|
||||||
'odoo.exceptions.RedirectWarning',
|
"odoo.exceptions.RedirectWarning",
|
||||||
'odoo.exceptions.UserError',
|
"odoo.exceptions.UserError",
|
||||||
'odoo.exceptions.ValidationError',
|
"odoo.exceptions.ValidationError",
|
||||||
'odoo.exceptions.Warning',
|
"odoo.exceptions.Warning",
|
||||||
'odoo.exceptions.except_orm',
|
"odoo.exceptions.except_orm",
|
||||||
]
|
]
|
||||||
DEFAULT_IGNORED_EXCEPTIONS = ','.join(ODOO_USER_EXCEPTIONS)
|
DEFAULT_IGNORED_EXCEPTIONS = ",".join(ODOO_USER_EXCEPTIONS)
|
||||||
|
|
||||||
PROCESSORS = (
|
PROCESSORS = (
|
||||||
'raven.processors.SanitizePasswordsProcessor',
|
"raven.processors.SanitizePasswordsProcessor",
|
||||||
'odoo.addons.sentry.logutils.SanitizeOdooCookiesProcessor',
|
"odoo.addons.sentry.logutils.SanitizeOdooCookiesProcessor",
|
||||||
)
|
)
|
||||||
DEFAULT_PROCESSORS = ','.join(PROCESSORS)
|
DEFAULT_PROCESSORS = ",".join(PROCESSORS)
|
||||||
|
|
||||||
EXCLUDE_LOGGERS = (
|
EXCLUDE_LOGGERS = ("werkzeug",)
|
||||||
'werkzeug',
|
DEFAULT_EXCLUDE_LOGGERS = ",".join(EXCLUDE_LOGGERS)
|
||||||
)
|
|
||||||
DEFAULT_EXCLUDE_LOGGERS = ','.join(EXCLUDE_LOGGERS)
|
|
||||||
|
|
||||||
DEFAULT_TRANSPORT = 'threaded'
|
DEFAULT_TRANSPORT = "threaded"
|
||||||
|
|
||||||
|
|
||||||
def select_transport(name=DEFAULT_TRANSPORT):
|
def select_transport(name=DEFAULT_TRANSPORT):
|
||||||
return {
|
return {
|
||||||
'requests_synchronous': raven.transport.RequestsHTTPTransport,
|
"requests_synchronous": raven.transport.RequestsHTTPTransport,
|
||||||
'requests_threaded': raven.transport.ThreadedRequestsHTTPTransport,
|
"requests_threaded": raven.transport.ThreadedRequestsHTTPTransport,
|
||||||
'synchronous': raven.transport.HTTPTransport,
|
"synchronous": raven.transport.HTTPTransport,
|
||||||
'threaded': raven.transport.ThreadedHTTPTransport,
|
"threaded": raven.transport.ThreadedHTTPTransport,
|
||||||
}.get(name, DEFAULT_TRANSPORT)
|
}.get(name, DEFAULT_TRANSPORT)
|
||||||
|
|
||||||
|
|
||||||
def get_sentry_options():
|
def get_sentry_options():
|
||||||
return [
|
return [
|
||||||
SentryOption('dsn', '', str.strip),
|
SentryOption("dsn", "", str.strip),
|
||||||
SentryOption('install_sys_hook', False, None),
|
SentryOption("install_sys_hook", False, None),
|
||||||
SentryOption('transport', DEFAULT_TRANSPORT, select_transport),
|
SentryOption("transport", DEFAULT_TRANSPORT, select_transport),
|
||||||
SentryOption('include_paths', '', split_multiple),
|
SentryOption("include_paths", "", split_multiple),
|
||||||
SentryOption('exclude_paths', '', split_multiple),
|
SentryOption("exclude_paths", "", split_multiple),
|
||||||
SentryOption('machine', defaults.NAME, None),
|
SentryOption("machine", defaults.NAME, None),
|
||||||
SentryOption('auto_log_stacks', defaults.AUTO_LOG_STACKS, None),
|
SentryOption("auto_log_stacks", defaults.AUTO_LOG_STACKS, None),
|
||||||
SentryOption('capture_locals', defaults.CAPTURE_LOCALS, None),
|
SentryOption("capture_locals", defaults.CAPTURE_LOCALS, None),
|
||||||
SentryOption('string_max_length', defaults.MAX_LENGTH_STRING, None),
|
SentryOption("string_max_length", defaults.MAX_LENGTH_STRING, None),
|
||||||
SentryOption('list_max_length', defaults.MAX_LENGTH_LIST, None),
|
SentryOption("list_max_length", defaults.MAX_LENGTH_LIST, None),
|
||||||
SentryOption('site', None, None),
|
SentryOption("site", None, None),
|
||||||
SentryOption('include_versions', True, None),
|
SentryOption("include_versions", True, None),
|
||||||
SentryOption(
|
SentryOption("ignore_exceptions", DEFAULT_IGNORED_EXCEPTIONS, split_multiple),
|
||||||
'ignore_exceptions', DEFAULT_IGNORED_EXCEPTIONS, split_multiple),
|
SentryOption("processors", DEFAULT_PROCESSORS, split_multiple),
|
||||||
SentryOption('processors', DEFAULT_PROCESSORS, split_multiple),
|
SentryOption("environment", None, None),
|
||||||
SentryOption('environment', None, None),
|
SentryOption("release", None, None),
|
||||||
SentryOption('release', None, None),
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -18,56 +18,50 @@ except ImportError:
|
||||||
|
|
||||||
|
|
||||||
def get_request_info(request):
|
def get_request_info(request):
|
||||||
'''
|
"""
|
||||||
Returns context data extracted from :param:`request`.
|
Returns context data extracted from :param:`request`.
|
||||||
|
|
||||||
Heavily based on flask integration for Sentry: https://git.io/vP4i9.
|
Heavily based on flask integration for Sentry: https://git.io/vP4i9.
|
||||||
'''
|
"""
|
||||||
urlparts = urllib.parse.urlsplit(request.url)
|
urlparts = urllib.parse.urlsplit(request.url)
|
||||||
return {
|
return {
|
||||||
'url': '%s://%s%s' % (urlparts.scheme, urlparts.netloc, urlparts.path),
|
"url": "{}://{}{}".format(urlparts.scheme, urlparts.netloc, urlparts.path),
|
||||||
'query_string': urlparts.query,
|
"query_string": urlparts.query,
|
||||||
'method': request.method,
|
"method": request.method,
|
||||||
'headers': dict(get_headers(request.environ)),
|
"headers": dict(get_headers(request.environ)),
|
||||||
'env': dict(get_environ(request.environ)),
|
"env": dict(get_environ(request.environ)),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_extra_context():
|
def get_extra_context():
|
||||||
'''
|
"""
|
||||||
Extracts additional context from the current request (if such is set).
|
Extracts additional context from the current request (if such is set).
|
||||||
'''
|
"""
|
||||||
request = odoo.http.request
|
request = odoo.http.request
|
||||||
try:
|
try:
|
||||||
session = getattr(request, 'session', {})
|
session = getattr(request, "session", {})
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
ctx = {}
|
ctx = {}
|
||||||
else:
|
else:
|
||||||
ctx = {
|
ctx = {
|
||||||
'tags': {
|
"tags": {"database": session.get("db", None)},
|
||||||
'database': session.get('db', None),
|
"user": {
|
||||||
},
|
"login": session.get("login", None),
|
||||||
'user': {
|
"uid": session.get("uid", None),
|
||||||
'login': session.get('login', None),
|
|
||||||
'uid': session.get('uid', None),
|
|
||||||
},
|
|
||||||
'extra': {
|
|
||||||
'context': session.get('context', {}),
|
|
||||||
},
|
},
|
||||||
|
"extra": {"context": session.get("context", {})},
|
||||||
}
|
}
|
||||||
if request.httprequest:
|
if request.httprequest:
|
||||||
ctx.update({
|
ctx.update({"request": get_request_info(request.httprequest)})
|
||||||
'request': get_request_info(request.httprequest),
|
|
||||||
})
|
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
|
||||||
class LoggerNameFilter(logging.Filter):
|
class LoggerNameFilter(logging.Filter):
|
||||||
'''
|
"""
|
||||||
Custom :class:`logging.Filter` which allows to filter loggers by name.
|
Custom :class:`logging.Filter` which allows to filter loggers by name.
|
||||||
'''
|
"""
|
||||||
|
|
||||||
def __init__(self, loggers, name=''):
|
def __init__(self, loggers, name=""):
|
||||||
super(LoggerNameFilter, self).__init__(name=name)
|
super(LoggerNameFilter, self).__init__(name=name)
|
||||||
self._exclude_loggers = set(loggers)
|
self._exclude_loggers = set(loggers)
|
||||||
|
|
||||||
|
@ -76,12 +70,12 @@ class LoggerNameFilter(logging.Filter):
|
||||||
|
|
||||||
|
|
||||||
class OdooSentryHandler(SentryHandler):
|
class OdooSentryHandler(SentryHandler):
|
||||||
'''
|
"""
|
||||||
Customized :class:`raven.handlers.logging.SentryHandler`.
|
Customized :class:`raven.handlers.logging.SentryHandler`.
|
||||||
|
|
||||||
Allows to add additional Odoo and HTTP request data to the event which is
|
Allows to add additional Odoo and HTTP request data to the event which is
|
||||||
sent to Sentry.
|
sent to Sentry.
|
||||||
'''
|
"""
|
||||||
|
|
||||||
def __init__(self, include_extra_context, *args, **kwargs):
|
def __init__(self, include_extra_context, *args, **kwargs):
|
||||||
super(OdooSentryHandler, self).__init__(*args, **kwargs)
|
super(OdooSentryHandler, self).__init__(*args, **kwargs)
|
||||||
|
@ -94,12 +88,10 @@ class OdooSentryHandler(SentryHandler):
|
||||||
|
|
||||||
|
|
||||||
class SanitizeOdooCookiesProcessor(SanitizePasswordsProcessor):
|
class SanitizeOdooCookiesProcessor(SanitizePasswordsProcessor):
|
||||||
'''
|
"""
|
||||||
Custom :class:`raven.processors.Processor`.
|
Custom :class:`raven.processors.Processor`.
|
||||||
|
|
||||||
Allows to sanitize sensitive Odoo cookies, namely the "session_id" cookie.
|
Allows to sanitize sensitive Odoo cookies, namely the "session_id" cookie.
|
||||||
'''
|
"""
|
||||||
|
|
||||||
KEYS = FIELDS = frozenset([
|
KEYS = FIELDS = frozenset(["session_id"])
|
||||||
'session_id',
|
|
||||||
])
|
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
# Copyright 2016-2017 Versada <https://versada.eu/>
|
# Copyright 2016-2017 Versada <https://versada.eu/>
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
from . import (
|
from . import test_client, test_logutils
|
||||||
test_client,
|
|
||||||
test_logutils,
|
|
||||||
)
|
|
||||||
|
|
|
@ -20,25 +20,25 @@ def log_handler_by_class(logger, handler_cls):
|
||||||
|
|
||||||
|
|
||||||
def remove_logging_handler(logger_name, handler_cls):
|
def remove_logging_handler(logger_name, handler_cls):
|
||||||
'''Removes handlers of specified classes from a :class:`logging.Logger`
|
"""Removes handlers of specified classes from a :class:`logging.Logger`
|
||||||
with a given name.
|
with a given name.
|
||||||
|
|
||||||
:param string logger_name: name of the logger
|
:param string logger_name: name of the logger
|
||||||
|
|
||||||
:param handler_cls: class of the handler to remove. You can pass a tuple of
|
:param handler_cls: class of the handler to remove. You can pass a tuple of
|
||||||
classes to catch several classes
|
classes to catch several classes
|
||||||
'''
|
"""
|
||||||
logger = logging.getLogger(logger_name)
|
logger = logging.getLogger(logger_name)
|
||||||
for handler in log_handler_by_class(logger, handler_cls):
|
for handler in log_handler_by_class(logger, handler_cls):
|
||||||
logger.removeHandler(handler)
|
logger.removeHandler(handler)
|
||||||
|
|
||||||
|
|
||||||
class InMemoryClient(raven.Client):
|
class InMemoryClient(raven.Client):
|
||||||
'''A :class:`raven.Client` subclass which simply stores events in a list.
|
"""A :class:`raven.Client` subclass which simply stores events in a list.
|
||||||
|
|
||||||
Extended based on the one found in raven-python to avoid additional testing
|
Extended based on the one found in raven-python to avoid additional testing
|
||||||
dependencies: https://git.io/vyGO3
|
dependencies: https://git.io/vyGO3
|
||||||
'''
|
"""
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
self.events = []
|
self.events = []
|
||||||
|
@ -52,14 +52,12 @@ class InMemoryClient(raven.Client):
|
||||||
|
|
||||||
def has_event(self, event_level, event_msg):
|
def has_event(self, event_level, event_msg):
|
||||||
for event in self.events:
|
for event in self.events:
|
||||||
if (event.get('level') == event_level and
|
if event.get("level") == event_level and event.get("message") == event_msg:
|
||||||
event.get('message') == event_msg):
|
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class TestClientSetup(unittest.TestCase):
|
class TestClientSetup(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestClientSetup, self).setUp()
|
super(TestClientSetup, self).setUp()
|
||||||
self.logger = logging.getLogger(__name__)
|
self.logger = logging.getLogger(__name__)
|
||||||
|
@ -68,57 +66,54 @@ class TestClientSetup(unittest.TestCase):
|
||||||
# when the module is loaded. After that, subsequent calls to
|
# when the module is loaded. After that, subsequent calls to
|
||||||
# setup_logging will not re-add our handler. We explicitly remove
|
# setup_logging will not re-add our handler. We explicitly remove
|
||||||
# OdooSentryHandler handler so we can test with our in-memory client.
|
# OdooSentryHandler handler so we can test with our in-memory client.
|
||||||
remove_logging_handler('', OdooSentryHandler)
|
remove_logging_handler("", OdooSentryHandler)
|
||||||
|
|
||||||
def assertEventCaptured(self, client, event_level, event_msg):
|
def assertEventCaptured(self, client, event_level, event_msg):
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
client.has_event(event_level, event_msg),
|
client.has_event(event_level, event_msg),
|
||||||
msg='Event: "%s" was not captured' % event_msg
|
msg='Event: "%s" was not captured' % event_msg,
|
||||||
)
|
)
|
||||||
|
|
||||||
def assertEventNotCaptured(self, client, event_level, event_msg):
|
def assertEventNotCaptured(self, client, event_level, event_msg):
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
client.has_event(event_level, event_msg),
|
client.has_event(event_level, event_msg),
|
||||||
msg='Event: "%s" was captured' % event_msg
|
msg='Event: "%s" was captured' % event_msg,
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_initialize_raven_sets_dsn(self):
|
def test_initialize_raven_sets_dsn(self):
|
||||||
config = {
|
config = {
|
||||||
'sentry_enabled': True,
|
"sentry_enabled": True,
|
||||||
'sentry_dsn': 'http://public:secret@example.com/1',
|
"sentry_dsn": "http://public:secret@example.com/1",
|
||||||
}
|
}
|
||||||
client = initialize_raven(config, client_cls=InMemoryClient)
|
client = initialize_raven(config, client_cls=InMemoryClient)
|
||||||
self.assertEqual(client.remote.base_url, 'http://example.com')
|
self.assertEqual(client.remote.base_url, "http://example.com")
|
||||||
|
|
||||||
def test_capture_event(self):
|
def test_capture_event(self):
|
||||||
config = {
|
config = {
|
||||||
'sentry_enabled': True,
|
"sentry_enabled": True,
|
||||||
'sentry_dsn': 'http://public:secret@example.com/1',
|
"sentry_dsn": "http://public:secret@example.com/1",
|
||||||
}
|
}
|
||||||
level, msg = logging.WARNING, 'Test event, can be ignored'
|
level, msg = logging.WARNING, "Test event, can be ignored"
|
||||||
client = initialize_raven(config, client_cls=InMemoryClient)
|
client = initialize_raven(config, client_cls=InMemoryClient)
|
||||||
self.logger.log(level, msg)
|
self.logger.log(level, msg)
|
||||||
self.assertEventCaptured(client, level, msg)
|
self.assertEventCaptured(client, level, msg)
|
||||||
|
|
||||||
def test_ignore_exceptions(self):
|
def test_ignore_exceptions(self):
|
||||||
config = {
|
config = {
|
||||||
'sentry_enabled': True,
|
"sentry_enabled": True,
|
||||||
'sentry_dsn': 'http://public:secret@example.com/1',
|
"sentry_dsn": "http://public:secret@example.com/1",
|
||||||
'sentry_ignore_exceptions': 'odoo.exceptions.UserError',
|
"sentry_ignore_exceptions": "odoo.exceptions.UserError",
|
||||||
}
|
}
|
||||||
level, msg = logging.WARNING, 'Test UserError'
|
level, msg = logging.WARNING, "Test UserError"
|
||||||
client = initialize_raven(config, client_cls=InMemoryClient)
|
client = initialize_raven(config, client_cls=InMemoryClient)
|
||||||
|
|
||||||
handlers = list(
|
handlers = list(log_handler_by_class(logging.getLogger(), OdooSentryHandler))
|
||||||
log_handler_by_class(logging.getLogger(), OdooSentryHandler)
|
|
||||||
)
|
|
||||||
self.assertTrue(handlers)
|
self.assertTrue(handlers)
|
||||||
handler = handlers[0]
|
handler = handlers[0]
|
||||||
try:
|
try:
|
||||||
raise exceptions.UserError(msg)
|
raise exceptions.UserError(msg)
|
||||||
except exceptions.UserError:
|
except exceptions.UserError:
|
||||||
exc_info = sys.exc_info()
|
exc_info = sys.exc_info()
|
||||||
record = logging.LogRecord(
|
record = logging.LogRecord(__name__, level, __file__, 42, msg, (), exc_info)
|
||||||
__name__, level, __file__, 42, msg, (), exc_info)
|
|
||||||
handler.emit(record)
|
handler.emit(record)
|
||||||
self.assertEventNotCaptured(client, level, msg)
|
self.assertEventNotCaptured(client, level, msg)
|
||||||
|
|
|
@ -9,69 +9,62 @@ from ..logutils import SanitizeOdooCookiesProcessor
|
||||||
|
|
||||||
|
|
||||||
class TestOdooCookieSanitizer(unittest.TestCase):
|
class TestOdooCookieSanitizer(unittest.TestCase):
|
||||||
|
|
||||||
def test_cookie_as_string(self):
|
def test_cookie_as_string(self):
|
||||||
data = {
|
data = {
|
||||||
'request': {
|
"request": {
|
||||||
'cookies': 'website_lang=en_us;'
|
"cookies": "website_lang=en_us;"
|
||||||
'session_id=hello;'
|
"session_id=hello;"
|
||||||
'Session_ID=hello;'
|
"Session_ID=hello;"
|
||||||
'foo=bar',
|
"foo=bar"
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proc = SanitizeOdooCookiesProcessor(mock.Mock())
|
proc = SanitizeOdooCookiesProcessor(mock.Mock())
|
||||||
result = proc.process(data)
|
result = proc.process(data)
|
||||||
|
|
||||||
self.assertTrue('request' in result)
|
self.assertTrue("request" in result)
|
||||||
http = result['request']
|
http = result["request"]
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
http['cookies'],
|
http["cookies"],
|
||||||
'website_lang=en_us;'
|
"website_lang=en_us;"
|
||||||
'session_id={m};'
|
"session_id={m};"
|
||||||
'Session_ID={m};'
|
"Session_ID={m};"
|
||||||
'foo=bar'.format(
|
"foo=bar".format(m=proc.MASK),
|
||||||
m=proc.MASK,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_cookie_as_string_with_partials(self):
|
def test_cookie_as_string_with_partials(self):
|
||||||
data = {
|
data = {"request": {"cookies": "website_lang=en_us;session_id;foo=bar"}}
|
||||||
'request': {
|
|
||||||
'cookies': 'website_lang=en_us;session_id;foo=bar',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
proc = SanitizeOdooCookiesProcessor(mock.Mock())
|
proc = SanitizeOdooCookiesProcessor(mock.Mock())
|
||||||
result = proc.process(data)
|
result = proc.process(data)
|
||||||
|
|
||||||
self.assertTrue('request' in result)
|
self.assertTrue("request" in result)
|
||||||
http = result['request']
|
http = result["request"]
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
http['cookies'],
|
http["cookies"], "website_lang=en_us;session_id;foo=bar".format(m=proc.MASK)
|
||||||
'website_lang=en_us;session_id;foo=bar'.format(m=proc.MASK),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_cookie_header(self):
|
def test_cookie_header(self):
|
||||||
data = {
|
data = {
|
||||||
'request': {
|
"request": {
|
||||||
'headers': {
|
"headers": {
|
||||||
'Cookie': 'foo=bar;'
|
"Cookie": "foo=bar;"
|
||||||
'session_id=hello;'
|
"session_id=hello;"
|
||||||
'Session_ID=hello;'
|
"Session_ID=hello;"
|
||||||
'a_session_id_here=hello',
|
"a_session_id_here=hello"
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proc = SanitizeOdooCookiesProcessor(mock.Mock())
|
proc = SanitizeOdooCookiesProcessor(mock.Mock())
|
||||||
result = proc.process(data)
|
result = proc.process(data)
|
||||||
|
|
||||||
self.assertTrue('request' in result)
|
self.assertTrue("request" in result)
|
||||||
http = result['request']
|
http = result["request"]
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
http['headers']['Cookie'],
|
http["headers"]["Cookie"],
|
||||||
'foo=bar;'
|
"foo=bar;"
|
||||||
'session_id={m};'
|
"session_id={m};"
|
||||||
'Session_ID={m};'
|
"Session_ID={m};"
|
||||||
'a_session_id_here={m}'.format(m=proc.MASK))
|
"a_session_id_here={m}".format(m=proc.MASK),
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue