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 %}