def test_captures_error_in_iteration(self): iterable = ErroringIterable() app = ExampleApp(iterable) middleware = Sentry(app, client=self.client) response = middleware(self.request.environ, lambda *args: None) with self.assertRaises(ValueError): response = list(response) self.assertEquals(len(self.client.events), 1) event = self.client.events.pop(0) assert 'exception' in event exc = event['exception']['values'][-1] self.assertEquals(exc['type'], 'ValueError') self.assertEquals(exc['value'], 'hello world') self.assertEquals(event['level'], logging.ERROR) self.assertEquals(event['message'], 'ValueError: hello world') assert 'request' in event http = event['request'] self.assertEquals(http['url'], 'http://localhost/an-error') self.assertEquals(http['query_string'], 'foo=bar') self.assertEquals(http['method'], 'GET') # self.assertEquals(http['data'], {'foo': 'bar'}) headers = http['headers'] self.assertTrue('Host' in headers, headers.keys()) self.assertEquals(headers['Host'], 'localhost:80') env = http['env'] self.assertTrue('SERVER_NAME' in env, env.keys()) self.assertEquals(env['SERVER_NAME'], 'localhost') self.assertTrue('SERVER_PORT' in env, env.keys()) self.assertEquals(env['SERVER_PORT'], '80')
def test_error_handler(self): client = TempStoreClient() middleware = Sentry(self.app, client=client) request = webob.Request.blank('/an-error?foo=bar') response = middleware(request.environ, lambda *args: None) with self.assertRaises(ValueError): response = list(response) self.assertEquals(len(client.events), 1) event = client.events.pop(0) self.assertTrue('sentry.interfaces.Exception' in event) exc = event['sentry.interfaces.Exception'] self.assertEquals(exc['type'], 'ValueError') self.assertEquals(exc['value'], 'hello world') self.assertEquals(event['level'], logging.ERROR) self.assertEquals(event['message'], 'ValueError: hello world') self.assertTrue('sentry.interfaces.Http' in event) http = event['sentry.interfaces.Http'] self.assertEquals(http['url'], 'http://localhost/an-error') self.assertEquals(http['query_string'], 'foo=bar') self.assertEquals(http['method'], 'GET') # self.assertEquals(http['data'], {'foo': 'bar'}) headers = http['headers'] self.assertTrue('Host' in headers, headers.keys()) self.assertEquals(headers['Host'], 'localhost:80') env = http['env'] self.assertTrue('SERVER_NAME' in env, env.keys()) self.assertEquals(env['SERVER_NAME'], 'localhost') self.assertTrue('SERVER_PORT' in env, env.keys()) self.assertEquals(env['SERVER_PORT'], '80')
def make_app_from_environ(): app = App( dataset=os.environ.get('BIGQUERY_DATASET', 'reload'), table=os.environ.get('BIGQUERY_TABLE', 'page'), pubsub_project=os.environ.get('PUBSUB_PROJECT', 'internal-sentry'), pubsub_topic=os.environ.get('PUBSUB_TOPIC', 'analytics-events'), ) return Sentry(app, client)
def wrap_wsgi(app): from raven.middleware import Sentry client = get_client() _log.info('Attaching raven middleware...') return Sentry(app, client)
def serialize_exception(e): from raven.conf import setup_logging, EXCLUDE_LOGGER_DEFAULTS tmp = {} conf = get_config() client = Client(conf["SENTRY_CLIENT_DSN"]) if conf["ENABLE_LOGGING"]: # future enhancement: add exclude loggers option EXCLUDE_LOGGER_DEFAULTS += ('werkzeug', ) handler = ContextSentryHandler(client) setup_logging(handler, exclude=EXCLUDE_LOGGER_DEFAULTS) if conf["ALLOW_ORM_WARNING"]: openerp.addons.web.controllers.main._serialize_exception = serialize_exception openerp.addons.report.controllers.main._serialize_exception = serialize_exception # wrap the main wsgi app openerp.service.wsgi_server.application = Sentry( openerp.service.wsgi_server.application, client=client) if conf["INCLUDE_USER_CONTEXT"]: client.extra_context(get_user_context()) # fire the first message if isinstance(e, openerp.osv.osv.except_osv): tmp["exception_type"] = "except_osv" elif isinstance(e, openerp.exceptions.Warning): tmp["exception_type"] = "warning" elif isinstance(e, openerp.exceptions.AccessError): tmp["exception_type"] = "access_error" elif isinstance(e, openerp.exceptions.AccessDenied): tmp["exception_type"] = "access_denied" t = sys.exc_info() if "exception_type" not in tmp: client.captureException(t) debug = "Ошибка отправлена разработчикам, они занимаются устранением проблемы" else: debug = t tmp.update({ "name": type(e).__module__ + "." + type(e).__name__ if type(e).__module__ else type(e).__name__, "debug": debug, "message": ustr(e), "arguments": to_jsonable(e.args), }) return tmp
def test_close(self): iterable = SimpleIteratable() app = ExampleApp(iterable) middleware = Sentry(app, client=self.client) response = middleware(self.request.environ, lambda *args: None) list(response) # exhaust iterator response.close() self.assertTrue(iterable.closed, True)
def initialize_raven(config, client_cls=None): """ Setup an instance of :class:`raven.Client`. :param config: Sentry configuration :param client: class used to instantiate the raven client. """ enabled = config.get("sentry_enabled", False) if not (HAS_RAVEN and enabled): return if config.get("sentry_odoo_dir") and config.get("sentry_release"): _logger.debug( "Both sentry_odoo_dir and sentry_release defined, choosing sentry_release" ) options = dict() # only set release when there is a value, sentry will use the # SENTRY_RELEASE environment variable if nothing is set. release = config.get( "sentry_release", get_odoo_commit(config.get("sentry_odoo_dir")) ) if release: options[RELEASE_OPTION] = release for option in const.get_sentry_options(): if option.key == RELEASE_OPTION: # do not reprocess release continue value = config.get("sentry_%s" % option.key, option.default) if isinstance(option.converter, collections.Callable): value = option.converter(value) options[option.key] = value level = config.get("sentry_logging_level", const.DEFAULT_LOG_LEVEL) exclude_loggers = const.split_multiple( config.get("sentry_exclude_loggers", const.DEFAULT_EXCLUDE_LOGGERS) ) if level not in const.LOG_LEVEL_MAP: level = const.DEFAULT_LOG_LEVEL client_cls = client_cls or raven.Client client = client_cls(**options) handler = OdooSentryHandler( config.get("sentry_include_context", True), client=client, level=const.LOG_LEVEL_MAP[level], ) if exclude_loggers: handler.addFilter( LoggerNameFilter(exclude_loggers, name="sentry.logger.filter") ) raven.conf.setup_logging(handler) wsgi_server.application = Sentry(wsgi_server.application, client=client) client.captureMessage("Starting Odoo Server") return client
def wsgi_capture_exceptions(app): """Wrap a WSGI app with some kind of unhandled exception capture. If a Sentry client is configured, then this will send unhandled exceptions to Sentry. Otherwise, it will send them as part of the middleware. """ if _sentry_client is None: return WSGILoggingMiddleware(app) else: return Sentry(app, _sentry_client)
def test_systemexit_0_is_ignored(self): iterable = ExitingIterable(lambda: SystemExit(0)) app = ExampleApp(iterable) middleware = Sentry(app, client=self.client) response = middleware(self.request.environ, lambda *args: None) with self.assertRaises(SystemExit): response = list(response) self.assertEquals(len(self.client.events), 0)
def wrap_errorhandling(application): """If Sentry is to be activated wrap the app in it.""" # We use a Sentry WSGI Middleware to catch erros which are not # handled by the framework. Usually higher layers should catch # and display errors. import gaetk2.tools.sentry from gaetk2.config import gaetkconfig from raven.middleware import Sentry if not gaetkconfig.SENTRY_DSN: return application return Sentry(application, gaetk2.tools.sentry.sentry_client)
def make_app_from_environ(): from werkzeug.middleware.proxy_fix import ProxyFix from raven.middleware import Sentry app = App( dataset=os.environ.get("BIGQUERY_DATASET", "reload"), table=os.environ.get("BIGQUERY_TABLE", "page"), pubsub_project=os.environ.get("PUBSUB_PROJECT", "internal-sentry"), pubsub_topic=os.environ.get("PUBSUB_TOPIC", "analytics-events"), datadog_prefix=os.environ.get("DATADOG_PREFIX", ""), datadog_host=os.environ.get("DATADOG_HOST", "127.0.0.1"), datadog_port=int(os.environ.get("DATADOG_PORT", 8125)), ) return ProxyFix(Sentry(app, client))
def make_filter_app(app, global_conf, **app_conf): """Create a WSGI filter and return application ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the environment and fill conf dictionary. environment.load_environment(global_conf, app_conf) # Dispatch request to controllers. app = controllers.make_router(app) # Init request-dependant environment app = environment_setter(app) ## app = language_detector(app) # Repair badly encoded query in request URL. app = request_query_encoding_fixer(app) # # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) # # Handle Python exceptions # if not conf['debug']: # app = ErrorMiddleware(app, global_conf, **conf['errorware']) if conf['static_files']: # Serve static files static_app = StaticURLParser(conf['static_files_dir']) app = Cascade([static_app, app]) if conf['sentry.dsn']: from raven import Client from raven.middleware import Sentry client = Client( dsn=conf.get('sentry.dsn'), site=conf.get('sentry.site'), ) app = Sentry(app, client=client) return app
def initialize_raven(config, client_cls=None): ''' Setup an instance of :class:`raven.Client`. :param config: Sentry configuration :param client: class used to instantiate the raven client. ''' enabled = config.get('sentry_enabled', False) if not (HAS_RAVEN and enabled): return if config.get('sentry_odoo_dir') and config.get('sentry_release'): _logger.debug( 'Both sentry_odoo_dir and sentry_release defined, choosing sentry_release' ) options = { 'release': config.get('sentry_release', get_odoo_commit(config.get('sentry_odoo_dir'))), } for option in const.get_sentry_options(): value = config.get('sentry_%s' % option.key, option.default) if isinstance(option.converter, collections.Callable): value = option.converter(value) options[option.key] = value level = config.get('sentry_logging_level', const.DEFAULT_LOG_LEVEL) exclude_loggers = const.split_multiple( config.get('sentry_exclude_loggers', const.DEFAULT_EXCLUDE_LOGGERS)) if level not in const.LOG_LEVEL_MAP: level = const.DEFAULT_LOG_LEVEL client_cls = client_cls or raven.Client client = client_cls(**options) handler = OdooSentryHandler( config.get('sentry_include_context', True), client=client, level=const.LOG_LEVEL_MAP[level], ) if exclude_loggers: handler.addFilter( LoggerNameFilter(exclude_loggers, name='sentry.logger.filter')) raven.conf.setup_logging(handler) wsgi_server.application = Sentry(wsgi_server.application, client=client) client.captureMessage('Starting Odoo Server') return client
def test_keyboard_interrupt_is_captured(self): iterable = ExitingIterable(lambda: KeyboardInterrupt()) app = ExampleApp(iterable) middleware = Sentry(app, client=self.client) response = middleware(self.request.environ, lambda *args: None) with self.assertRaises(KeyboardInterrupt): response = list(response) self.assertEquals(len(self.client.events), 1) event = self.client.events.pop(0) assert 'exception' in event exc = event['exception']['values'][-1] self.assertEquals(exc['type'], 'KeyboardInterrupt') self.assertEquals(exc['value'], '') self.assertEquals(event['level'], logging.ERROR)
def test_systemexit_is_captured(self): iterable = ExitingIterable(lambda: SystemExit(1)) app = ExampleApp(iterable) middleware = Sentry(app, client=self.client) response = middleware(self.request.environ, lambda *args: None) with self.assertRaises(SystemExit): response = list(response) self.assertEquals(len(self.client.events), 1) event = self.client.events.pop(0) assert 'exception' in event exc = event['exception']['values'][-1] self.assertEquals(exc['type'], 'SystemExit') self.assertEquals(exc['value'], '1') self.assertEquals(event['level'], logging.ERROR) self.assertEquals(event['message'], 'SystemExit: 1')
def build_application(): config = { "core": { "build_secrets": os.environ["BUILD_SECRETS"], "freenode_verification": os.environ["FREENODE_VERIFICATION"], }, "s3": { "aws_access_key_id": os.environ["AWS_ACCESS_KEY_ID"], "aws_secret_access_key": os.environ["AWS_SECRET_ACCESS_KEY"], "bucket": "topaz-builds", }, "database": { "uri": os.environ["DATABASE_URL"], }, } app = Application(config, S3Storage) app = SharedDataMiddleware(app, { "/static/": os.path.join(os.path.dirname(__file__), os.pardir, "static"), }) return Sentry(app, Client(os.environ["SENTRY_DSN"]))
def __init__(self, config, engine=None, redis=None): self.config = convert_to_attr_dict(config) # Connect to the database if engine is None and self.config.get("database", {}).get("url"): engine = sqlalchemy.create_engine(self.config.database.url) self.engine = engine # Create our redis connection if redis is None and self.config.get("redis", {}).get("url"): redis = redispy.StrictRedis.from_url(self.config.redis.url) self.redis = redis # Create our Store instance and associate our store modules with it self.models = AttributeDict() for name, mod_path in self.model_names.items(): mod_name, klass = mod_path.rsplit(":", 1) mod = importlib.import_module(mod_name) self.models[name] = getattr(mod, klass)( self, self.metadata, self.engine, self.redis, ) # Create our Search Index instance and associate our mappings with it self.search = Index(self.models, self.config.search) self.search.register(ProjectMapping) # Set up our URL routing self.urls = urls.urls # Initialize our Translations engine self.trans = babel.support.NullTranslations() # Setup our Jinja2 Environment self.templates = jinja2.Environment( autoescape=True, auto_reload=self.config.debug, extensions=[ "jinja2.ext.i18n", ], loader=jinja2.PackageLoader("warehouse"), ) # Install Babel self.templates.filters.update({ "package_type_display": packaging_helpers.package_type_display, "format_number": babel.numbers.format_number, "format_decimal": babel.numbers.format_decimal, "format_percent": babel.numbers.format_percent, "format_date": babel.dates.format_date, "format_datetime": babel.dates.format_datetime, "format_time": babel.dates.format_time, }) # Install our translations self.templates.install_gettext_translations(self.trans, newstyle=True) # Add our Powered By Middleware self.wsgi_app = PoweredBy(self.wsgi_app, "Warehouse {} ({})".format( warehouse.__version__, warehouse.__build__, )) # Add our Content Security Policy Middleware if not self.config.theme_debug: self.wsgi_app = guard.ContentSecurityPolicy( self.wsgi_app, self.config.security.csp, ) if "sentry" in self.config: self.wsgi_app = Sentry(self.wsgi_app, Client(**self.config.sentry)) # Serve the static files that are packaged as part of Warehouse self.wsgi_app = SharedDataMiddleware( self.wsgi_app, { "/static/": os.path.abspath( os.path.join( os.path.dirname(warehouse.__file__), "static", ), ), }, ) # configure logging logging.config.dictConfig(self.config.logging)
def app(self): return Sentry(self.wsgi_app, RavenClient(self.SENTRY_DSN))
import os from django.conf import settings from django.core.wsgi import get_wsgi_application from raven import Client from raven.middleware import Sentry from raven.transport.http import HTTPTransport os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.production') application = get_wsgi_application() if os.environ.get('DJANGO_SETTINGS_MODULE') == 'config.settings.production': application = Sentry( get_wsgi_application(), Client(dsn=settings.SENTRY_DSN, transport=HTTPTransport))
from __future__ import unicode_literals from raven import Client from raven.middleware import Sentry import bugbuzz_service # TODO: logging config? application = bugbuzz_service.main({}) # configure sentry middleware if it's avaiable if application.registry.settings.get('sentry.dsn'): application = Sentry(application, Client(application.registry.settings['sentry.dsn']))
def __init__(self, config, engine=None, redis_class=redis.StrictRedis): self.config = AttributeDict(config) self.metadata = db.metadata # configure logging logging.config.dictConfig(self.config.logging) # Connect to the database if engine is None and self.config.get("database", {}).get("url"): engine = sqlalchemy.create_engine(self.config.database.url) self.engine = engine # Create our redis connections self.redises = { key: redis_class.from_url(url) for key, url in self.config.redis.items() } # Create our Store instance and associate our store modules with it self.db = AttributeDict() for name, klass in self.db_classes.items(): self.db[name] = klass( self, self.metadata, self.engine, self.redises["downloads"], ) # Create our Search Index instance and associate our mappings with it self.search = Index(self.db, self.config.search) self.search.register(ProjectMapping) # Set up our URL routing self.urls = urls.urls # Initialize our Translations engine self.translations = babel.support.NullTranslations() # Setup our Jinja2 Environment self.templates = jinja2.Environment( autoescape=True, auto_reload=self.config.debug, extensions=[ "jinja2.ext.i18n", ], loader=jinja2.PackageLoader("warehouse"), ) # Install Babel self.templates.filters.update({ "package_type_display": packaging_helpers.package_type_display, "format_number": babel.numbers.format_number, "format_decimal": babel.numbers.format_decimal, "format_percent": babel.numbers.format_percent, "format_date": babel.dates.format_date, "format_datetime": babel.dates.format_datetime, "format_time": babel.dates.format_time, }) # Install our translations self.templates.install_gettext_translations( self.translations, newstyle=True, ) # Setup our password hasher self.passlib = passlib.context.CryptContext( schemes=[ "bcrypt_sha256", "bcrypt", "django_bcrypt", "unix_disabled", ], default="bcrypt_sha256", deprecated=["auto"], ) # Setup our session storage self.session_store = RedisSessionStore( self.redises["sessions"], session_class=Session, ) # Add our Content Security Policy Middleware img_src = ["'self'"] if self.config.camo: camo_parsed = urllib.parse.urlparse(self.config.camo.url) img_src += [ "{}://{}".format(camo_parsed.scheme, camo_parsed.netloc), "https://secure.gravatar.com", ] else: img_src += ["*"] self.wsgi_app = guard.ContentSecurityPolicy( self.wsgi_app, { "default-src": ["'self'"], "font-src": ["'self'", "data:"], "img-src": img_src, "style-src": ["'self'", "cloud.typography.com"], }, ) if "sentry" in self.config: self.wsgi_app = Sentry(self.wsgi_app, Client(**self.config.sentry)) # Serve the static files that are packaged as part of Warehouse self.wsgi_app = WhiteNoise( self.wsgi_app, root=self.static_dir, prefix=self.static_path, max_age=31557600, ) # Add our Powered By Middleware self.wsgi_app = HeaderRewriterFix( self.wsgi_app, add_headers=[ ( "X-Powered-By", "Warehouse {__version__} ({__build__})".format( __version__=warehouse.__version__, __build__=warehouse.__build__, ), ), ], ) # Previously PyPI used a hand written disaptch method which depended # on things like the request's content type or url parameters. In order # to sanely support that in Warehouse we use this middleware to rewrite # those to "internal" URLs which we can then dispatch based on. self.wsgi_app = LegacyRewriteMiddleware(self.wsgi_app) # This is last because we want it processed first in the stack of # middlewares. This will ensure that we strip X-Forwarded-* headers # if the request doesn't come from Fastly self.wsgi_app = XForwardedTokenMiddleware( self.wsgi_app, self.config.site.access_token, )
def sentry_filter_factory(app, global_conf, **kwargs): client = Client(**kwargs) return Sentry(app, client)
def setup_sentry_wsgi(app, dsn): return Sentry(app, Client(dsn))
from raven import Client from raven.middleware import Sentry from yafas import config from yafas.app import YafasApp app = YafasApp() SENTRY_DSN = config['SENTRY_DSN'] api = Sentry(app.api, Client(SENTRY_DSN)) if SENTRY_DSN else app.api
# entry point for the Django loop import os from raven import Client from raven.middleware import Sentry from raven_settings import DSN import djcelery djcelery.setup_loader() client = Client(DSN) os.environ.update(DJANGO_SETTINGS_MODULE='homedisplay.settings') from django.core.wsgi import get_wsgi_application application = get_wsgi_application() application = Sentry(application, client=client)
import os from django.core.wsgi import get_wsgi_application from raven import Client from raven.middleware import Sentry application = get_wsgi_application() if 'SENTRY_DSN' in os.environ: application = Sentry(application, Client())
super(ContextSentryHandler, self).emit(rec) client = Client(CLIENT_DSN) if LOGGING_LEVEL not in LOGLEVELS: LOGGING_LEVEL = 'warn' if ENABLE_LOGGING: # future enhancement: add exclude loggers option EXCLUDE_LOGGER_DEFAULTS += ('werkzeug',) handler = ContextSentryHandler( client=client, level=LOGLEVELS[LOGGING_LEVEL], allow_orm=ALLOW_ORM_WARNING) setup_logging(handler, exclude=EXCLUDE_LOGGER_DEFAULTS) if ALLOW_ORM_WARNING: openerp.addons.web.controllers.main._serialize_exception = \ serialize_exception openerp.addons.report.controllers.main._serialize_exception = \ serialize_exception # wrap the main wsgi app openerp.service.wsgi_server.application = Sentry( openerp.service.wsgi_server.application, client=client) if INCLUDE_USER_CONTEXT: client.extra_context(get_user_context()) # Fire the first message client.captureMessage('Starting Odoo Server')
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with Yith Library Server. If not, see <http://www.gnu.org/licenses/>. import os import os.path from newrelic import agent agent.initialize() from paste.deploy import loadapp from pyramid.paster import setup_logging from raven.middleware import Sentry from waitress import serve basedir = os.path.dirname(os.path.realpath(__file__)) conf_file = os.path.join(basedir, 'yithlibraryserver', 'config-templates', 'production.ini') application = loadapp('config:%s' % conf_file) application = agent.WSGIApplicationWrapper(Sentry(application)) setup_logging(conf_file) if __name__ == "__main__": port = int(os.environ.get("PORT", 5000)) scheme = os.environ.get("SCHEME", "https") serve(application, host='0.0.0.0', port=port, url_scheme=scheme)
import os from paste.deploy import loadapp from waitress import serve from raven import Client from raven.middleware import Sentry if __name__ == "__main__": port = int(os.environ.get("PORT", 5000)) sentry_url = os.environ.get('SENTRY_URL') app = loadapp('config:production.ini', relative_to='.') if sentry_url: app = Sentry(app, Client(sentry_url)) serve(app, host='0.0.0.0', port=port)
}) def float_to_time(hours): "Converts a float of hours into readable hours and mins" return "%dh %dm" % (hours, (hours * 60) % 60) app.jinja_env.filters['float_to_time'] = float_to_time babelized_app = Babel(app) application = babelized_app.app.wsgi_app application = Sentry( application, Client( 'http://*****:*****@sentry.openlabs.co.in/10' )) # If the file is launched from the CLI then launch the app using the debug # web server built into werkzeug if __name__ == '__main__': class NereidTestMiddleware(object): def __init__(self, app, site): self.app = app self.site = site def __call__(self, environ, start_response): environ['HTTP_HOST'] = self.site return self.app(environ, start_response)