From b34ae2cffe94817e62fbb87109e4cc6f0f2a8da7 Mon Sep 17 00:00:00 2001 From: Sandy Carter Date: Tue, 26 Aug 2014 16:27:23 -0400 Subject: [PATCH] Add sentry integration module Module for enabling raven initializing to report to sentry. Based on feedback from my presentation at odoo days 2014 --- .travis.yml | 2 +- sentry_logger/__init__.py | 51 +++++++++++ sentry_logger/__openerp__.py | 62 ++++++++++++++ sentry_logger/odoo_sentry_client.py | 123 +++++++++++++++++++++++++++ sentry_logger/odoo_sentry_handler.py | 32 +++++++ 5 files changed, 269 insertions(+), 1 deletion(-) create mode 100644 sentry_logger/__init__.py create mode 100644 sentry_logger/__openerp__.py create mode 100644 sentry_logger/odoo_sentry_client.py create mode 100644 sentry_logger/odoo_sentry_handler.py diff --git a/.travis.yml b/.travis.yml index e71384052..fbd4b8c32 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ install: - git clone https://github.com/OCA/maintainer-quality-tools.git ${HOME}/maintainer-quality-tools - export PATH=${HOME}/maintainer-quality-tools/travis:${PATH} - travis_install_nightly - - sudo pip install python-ldap + - sudo pip install python-ldap raven raven_sanitize_openerp bzr GitPython - printf '[options]\n\nrunning_env = dev' > ${HOME}/.openerp_serverrc script: diff --git a/sentry_logger/__init__.py b/sentry_logger/__init__.py new file mode 100644 index 000000000..888be4dc3 --- /dev/null +++ b/sentry_logger/__init__.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2010 - 2014 Savoir-faire Linux +# (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################### + +import logging +import cgitb + +from openerp.tools import config + +from .odoo_sentry_client import OdooClient +from .odoo_sentry_handler import OdooSentryHandler + + +root_logger = logging.root + +processors = ( + 'raven.processors.SanitizePasswordsProcessor', + 'raven_sanitize_openerp.OpenerpPasswordsProcessor' +) +if config.get(u'sentry_dsn'): + cgitb.enable() + # Get DSN info from config file or ~/.openerp_serverrc (recommended) + dsn = config.get('sentry_dsn') + # Create Client + client = OdooClient( + dsn=dsn, + processors=processors, + ) + handler = OdooSentryHandler(client, level=logging.ERROR) + root_logger.addHandler(handler) +else: + root_logger.warn(u"Sentry DSN not defined in config file") + client = None diff --git a/sentry_logger/__openerp__.py b/sentry_logger/__openerp__.py new file mode 100644 index 000000000..22708001a --- /dev/null +++ b/sentry_logger/__openerp__.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2010 - 2014 Savoir-faire Linux +# (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +{ + 'name': "sentry", + + 'summary': "Sentry integration", + 'description': """ +Sentry +====== + +Integration with Sentry Error reporting engine. + +Insert sentry DSN to ~/.openerp_serverrc with value: + sentry_dsn = sync+ + +Contributors +------------ +* Sandy Carter (sandy.carter@savoirfairelinux.com) +""", + + 'author': "Savoir-faire Linux", + 'website': "http://www.savoirfairelinux.com", + + # Categories can be used to filter modules in modules listing + # Check /addons/base/module/module_data.xml of the full list + 'category': 'Extra Tools', + 'version': '1.0', + + # any module necessary for this one to work correctly + 'depends': ['base'], + 'external_dependencies': { + 'python': ['raven', 'raven_sanitize_openerp', 'bzrlib', 'git'], + }, + 'data': [ + ], + + 'demo': [ + ], + + 'tests': [ + ], +} diff --git a/sentry_logger/odoo_sentry_client.py b/sentry_logger/odoo_sentry_client.py new file mode 100644 index 000000000..1e18252ac --- /dev/null +++ b/sentry_logger/odoo_sentry_client.py @@ -0,0 +1,123 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2010 - 2014 Savoir-faire Linux +# (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################### + +import logging +import platform +import os +import sys +from raven import Client +try: + from bzrlib.branch import Branch as Bzr + from bzrlib.errors import NotBranchError +except ImportError: + Bzr = False +try: + from git import Git, GitCommandError +except ImportError: + Git = False + +from openerp.tools import config +_logger = logging.getLogger(__name__) + + +class OdooClient(Client): + """Subclass raven.Client to be able to report Module versions and + commit numbers""" + + def __init__(self, dsn=None, **options): + """Set up Sentry Client, add version numbers to sentry package + Send a message when Activate + """ + # Send the following library versions and include all eggs in sys.path + include_paths = [ + 'openerp', + 'sentry', + 'raven', + 'raven_sanitize_openerp', + ] + [os.path.basename(i).split('-')[0] + for i in sys.path if i.endswith('.egg')] + # Add tags, OS and bzr revisions for Server and Addons + tags = { + 'OS': (" ".join(platform.linux_distribution()).strip() or + " ".join(platform.win32_ver()).strip() or + " ".join((platform.system(), platform.release(), + platform.machine()))), + } + self.revnos = {} + super(OdooClient, self).__init__( + dsn=dsn, include_paths=include_paths, tags=tags, **options) + self.set_rev_versions() + # Create and test message for Sentry + self.captureMessage(u'Sentry Tracking Activated!') + + def set_rev_versions(self): + """Given path, get source and revno, careful not to raise any + exceptions""" + paths = set(config.get('addons_path').split(',')) + bzr_paths = ( + p for p in paths if os.path.exists(os.path.join(p, '.bzr')) + ) + git_paths = ( + p for p in paths if os.path.exists(os.path.join(p, '.git')) + ) + if Bzr: + self.set_rev_bzr_version(bzr_paths) + if Git: + self.set_rev_git_version(git_paths) + + def set_rev_bzr_version(self, paths): + for path in paths: + try: + branch, rel_path = Bzr.open_containing(path) + branch.lock_read() + # Clean name + name = branch.get_parent() + name = name.replace(u'bazaar.launchpad.net/', u'lp:') + name = name.replace(u'%7E', u'~') + name = name.replace(u'%2Bbranch/', u'') + name = name.replace(u'bzr+ssh://', u'') + self.revnos[name] = u'r%i' % branch.revno() + branch.unlock() + except NotBranchError: + continue + finally: + if branch.is_locked(): + branch.unlock() + + def set_rev_git_version(self, paths): + for path in paths: + try: + git_repo = Git(path) + name = os.path.basename(path) + self.revnos[name] = git_repo.log('-1', pretty='%H') + except GitCommandError: + continue + + def build_msg(self, event_type, data=None, date=None, + time_spent=None, extra=None, stack=None, public_key=None, + tags=None, **kwargs): + """Add revnos to msg's modules""" + res = super(OdooClient, self).build_msg( + event_type, data, date, time_spent, extra, stack, public_key, + tags, **kwargs) + res['modules'] = dict(res['modules'].items() + self.revnos.items()) + return res diff --git a/sentry_logger/odoo_sentry_handler.py b/sentry_logger/odoo_sentry_handler.py new file mode 100644 index 000000000..454ae668f --- /dev/null +++ b/sentry_logger/odoo_sentry_handler.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# ############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2010 - 2014 Savoir-faire Linux +# (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################### + +from openerp.osv.orm import except_orm +from raven.handlers.logging import SentryHandler + + +class OdooSentryHandler(SentryHandler, object): + + def can_record(self, record): + if record.exc_info and record.exc_info[0] is except_orm: + return False + return super(OdooSentryHandler, self).can_record(record)