diff --git a/app.py b/app.py index 2a99a2446..aa663418c 100644 --- a/app.py +++ b/app.py @@ -11,6 +11,7 @@ import features from storage import Storage from data.userfiles import Userfiles from util.analytics import Analytics +from util.exceptionlog import Sentry from data.billing import Billing @@ -44,3 +45,4 @@ storage = Storage(app) userfiles = Userfiles(app) analytics = Analytics(app) billing = Billing(app) +sentry = Sentry(app) diff --git a/config.py b/config.py index 2d8f659df..f08e555db 100644 --- a/config.py +++ b/config.py @@ -32,7 +32,7 @@ def logs_init_builder(level=logging.DEBUG, # values are set to the frontend, DO NOT PLACE ANY SECRETS OR KEYS in this list. CLIENT_WHITELIST = ['SERVER_HOSTNAME', 'PREFERRED_URL_SCHEME', 'GITHUB_CLIENT_ID', 'GITHUB_LOGIN_CLIENT_ID', 'MIXPANEL_KEY', 'STRIPE_PUBLISHABLE_KEY', - 'ENTERPRISE_LOGO_URL'] + 'ENTERPRISE_LOGO_URL', 'SENTRY_PUBLIC_DSN'] def getFrontendVisibleConfig(config_dict): @@ -102,6 +102,11 @@ class DefaultConfig(object): # Analytics ANALYTICS_TYPE = "FakeAnalytics" + # Exception logging + EXCEPTION_LOG_TYPE = 'FakeSentry' + SENTRY_DSN = None + SENTRY_PUBLIC_DSN = None + # Github Config GITHUB_TOKEN_URL = 'https://github.com/login/oauth/access_token' GITHUB_USER_URL = 'https://api.github.com/user' diff --git a/endpoints/common.py b/endpoints/common.py index 1a81648aa..e9bd7b7c6 100644 --- a/endpoints/common.py +++ b/endpoints/common.py @@ -155,6 +155,7 @@ def render_page_template(name, **kwargs): feature_set=json.dumps(features.get_features()), config_set=json.dumps(getFrontendVisibleConfig(app.config)), mixpanel_key=app.config.get('MIXPANEL_KEY', ''), + sentry_public_dsn=app.config.get('SENTRY_PUBLIC_DSN', ''), is_debug=str(app.config.get('DEBUGGING', False)).lower(), show_chat=features.OLARK_CHAT, cache_buster=cache_buster, diff --git a/requirements-nover.txt b/requirements-nover.txt index 2d0d91c34..f038ba905 100644 --- a/requirements-nover.txt +++ b/requirements-nover.txt @@ -30,3 +30,6 @@ git+https://github.com/NateFerrero/oauth2lib.git alembic sqlalchemy python-magic +reportlab==2.7 +blinker +raven diff --git a/requirements.txt b/requirements.txt index 45afa158b..daea582a9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,10 +6,11 @@ Flask-Principal==0.4.0 Flask-RESTful==0.2.12 Jinja2==2.7.2 Mako==0.9.1 -MarkupSafe==0.19 +MarkupSafe==0.21 Pillow==2.4.0 PyGithub==1.24.1 -PyMySQL==0.6.1 +PyMySQL==0.6.2 +PyPDF2==1.21 SQLAlchemy==0.9.4 Werkzeug==0.9.4 alembic==0.6.4 @@ -23,8 +24,8 @@ ecdsa==0.11 gevent==1.0 greenlet==0.4.2 gunicorn==18.0 -hiredis==0.1.2 -html5lib==1.0b3 +hiredis==0.1.3 +html5lib==0.999 itsdangerous==0.24 jsonschema==2.3.0 lockfile==0.9.1 @@ -35,15 +36,15 @@ mixpanel-py==3.1.2 mock==1.0.1 git+https://github.com/NateFerrero/oauth2lib.git paramiko==1.13.0 -peewee==2.2.2 +peewee==2.2.3 py-bcrypt==0.4 -pyPdf==1.13 pycrypto==2.6.1 python-daemon==1.6 python-dateutil==2.2 python-digitalocean==0.7 python-magic==0.4.6 pytz==2014.2 +raven==4.2.1 redis==2.9.1 reportlab==2.7 requests==2.2.1 @@ -51,4 +52,4 @@ six==1.6.1 stripe==1.14.0 websocket-client==0.11.0 wsgiref==0.1.2 -xhtml2pdf==0.0.5 +xhtml2pdf==0.0.6 diff --git a/static/js/app.js b/static/js/app.js index 775dc1bf9..4dd16996f 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -778,7 +778,18 @@ quayApp = angular.module('quay', quayDependencies, function($provide, cfpLoading olark('api.chat.updateVisitorStatus', {snippet: 'username: ' + userResponse.username}); } + if (window.Raven !== undefined) { + Raven.setUser({ + email: userResponse.email, + id: userResponse.username + }); + } + CookieService.putPermanent('quay.loggedin', 'true'); + } else { + if (window.Raven !== undefined) { + Raven.setUser(); + } } if (opt_callback) { @@ -1366,6 +1377,17 @@ quayApp = angular.module('quay', quayDependencies, function($provide, cfpLoading }]); } + if (window.__config && window.__config.SENTRY_PUBLIC_DSN) { + quayApp.config(function($provide) { + $provide.decorator("$exceptionHandler", function($delegate) { + return function(ex, cause) { + $delegate(ex, cause); + Raven.captureException(ex, {extra: {cause: cause}}); + }; + }); + }); + } + function buildConditionalLinker($animate, name, evaluator) { // Based off of a solution found here: http://stackoverflow.com/questions/20325480/angularjs-whats-the-best-practice-to-add-ngif-to-a-directive-programmatically diff --git a/templates/base.html b/templates/base.html index 482264242..01f0e6f6c 100644 --- a/templates/base.html +++ b/templates/base.html @@ -58,6 +58,7 @@ + @@ -73,6 +74,12 @@ {% endfor %} + {% if sentry_public_dsn %} + + {% endif %} + {% if mixpanel_key %}