Add sentry exception monitoring.
This commit is contained in:
parent
b30d0976f0
commit
fe665118bb
8 changed files with 77 additions and 8 deletions
2
app.py
2
app.py
|
@ -11,6 +11,7 @@ import features
|
||||||
from storage import Storage
|
from storage import Storage
|
||||||
from data.userfiles import Userfiles
|
from data.userfiles import Userfiles
|
||||||
from util.analytics import Analytics
|
from util.analytics import Analytics
|
||||||
|
from util.exceptionlog import Sentry
|
||||||
from data.billing import Billing
|
from data.billing import Billing
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,3 +45,4 @@ storage = Storage(app)
|
||||||
userfiles = Userfiles(app)
|
userfiles = Userfiles(app)
|
||||||
analytics = Analytics(app)
|
analytics = Analytics(app)
|
||||||
billing = Billing(app)
|
billing = Billing(app)
|
||||||
|
sentry = Sentry(app)
|
||||||
|
|
|
@ -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.
|
# 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',
|
CLIENT_WHITELIST = ['SERVER_HOSTNAME', 'PREFERRED_URL_SCHEME', 'GITHUB_CLIENT_ID',
|
||||||
'GITHUB_LOGIN_CLIENT_ID', 'MIXPANEL_KEY', 'STRIPE_PUBLISHABLE_KEY',
|
'GITHUB_LOGIN_CLIENT_ID', 'MIXPANEL_KEY', 'STRIPE_PUBLISHABLE_KEY',
|
||||||
'ENTERPRISE_LOGO_URL']
|
'ENTERPRISE_LOGO_URL', 'SENTRY_PUBLIC_DSN']
|
||||||
|
|
||||||
|
|
||||||
def getFrontendVisibleConfig(config_dict):
|
def getFrontendVisibleConfig(config_dict):
|
||||||
|
@ -102,6 +102,11 @@ class DefaultConfig(object):
|
||||||
# Analytics
|
# Analytics
|
||||||
ANALYTICS_TYPE = "FakeAnalytics"
|
ANALYTICS_TYPE = "FakeAnalytics"
|
||||||
|
|
||||||
|
# Exception logging
|
||||||
|
EXCEPTION_LOG_TYPE = 'FakeSentry'
|
||||||
|
SENTRY_DSN = None
|
||||||
|
SENTRY_PUBLIC_DSN = None
|
||||||
|
|
||||||
# Github Config
|
# Github Config
|
||||||
GITHUB_TOKEN_URL = 'https://github.com/login/oauth/access_token'
|
GITHUB_TOKEN_URL = 'https://github.com/login/oauth/access_token'
|
||||||
GITHUB_USER_URL = 'https://api.github.com/user'
|
GITHUB_USER_URL = 'https://api.github.com/user'
|
||||||
|
|
|
@ -155,6 +155,7 @@ def render_page_template(name, **kwargs):
|
||||||
feature_set=json.dumps(features.get_features()),
|
feature_set=json.dumps(features.get_features()),
|
||||||
config_set=json.dumps(getFrontendVisibleConfig(app.config)),
|
config_set=json.dumps(getFrontendVisibleConfig(app.config)),
|
||||||
mixpanel_key=app.config.get('MIXPANEL_KEY', ''),
|
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(),
|
is_debug=str(app.config.get('DEBUGGING', False)).lower(),
|
||||||
show_chat=features.OLARK_CHAT,
|
show_chat=features.OLARK_CHAT,
|
||||||
cache_buster=cache_buster,
|
cache_buster=cache_buster,
|
||||||
|
|
|
@ -30,3 +30,6 @@ git+https://github.com/NateFerrero/oauth2lib.git
|
||||||
alembic
|
alembic
|
||||||
sqlalchemy
|
sqlalchemy
|
||||||
python-magic
|
python-magic
|
||||||
|
reportlab==2.7
|
||||||
|
blinker
|
||||||
|
raven
|
||||||
|
|
|
@ -6,10 +6,11 @@ Flask-Principal==0.4.0
|
||||||
Flask-RESTful==0.2.12
|
Flask-RESTful==0.2.12
|
||||||
Jinja2==2.7.2
|
Jinja2==2.7.2
|
||||||
Mako==0.9.1
|
Mako==0.9.1
|
||||||
MarkupSafe==0.19
|
MarkupSafe==0.21
|
||||||
Pillow==2.4.0
|
Pillow==2.4.0
|
||||||
PyGithub==1.24.1
|
PyGithub==1.24.1
|
||||||
PyMySQL==0.6.1
|
PyMySQL==0.6.2
|
||||||
|
PyPDF2==1.21
|
||||||
SQLAlchemy==0.9.4
|
SQLAlchemy==0.9.4
|
||||||
Werkzeug==0.9.4
|
Werkzeug==0.9.4
|
||||||
alembic==0.6.4
|
alembic==0.6.4
|
||||||
|
@ -23,8 +24,8 @@ ecdsa==0.11
|
||||||
gevent==1.0
|
gevent==1.0
|
||||||
greenlet==0.4.2
|
greenlet==0.4.2
|
||||||
gunicorn==18.0
|
gunicorn==18.0
|
||||||
hiredis==0.1.2
|
hiredis==0.1.3
|
||||||
html5lib==1.0b3
|
html5lib==0.999
|
||||||
itsdangerous==0.24
|
itsdangerous==0.24
|
||||||
jsonschema==2.3.0
|
jsonschema==2.3.0
|
||||||
lockfile==0.9.1
|
lockfile==0.9.1
|
||||||
|
@ -35,15 +36,15 @@ mixpanel-py==3.1.2
|
||||||
mock==1.0.1
|
mock==1.0.1
|
||||||
git+https://github.com/NateFerrero/oauth2lib.git
|
git+https://github.com/NateFerrero/oauth2lib.git
|
||||||
paramiko==1.13.0
|
paramiko==1.13.0
|
||||||
peewee==2.2.2
|
peewee==2.2.3
|
||||||
py-bcrypt==0.4
|
py-bcrypt==0.4
|
||||||
pyPdf==1.13
|
|
||||||
pycrypto==2.6.1
|
pycrypto==2.6.1
|
||||||
python-daemon==1.6
|
python-daemon==1.6
|
||||||
python-dateutil==2.2
|
python-dateutil==2.2
|
||||||
python-digitalocean==0.7
|
python-digitalocean==0.7
|
||||||
python-magic==0.4.6
|
python-magic==0.4.6
|
||||||
pytz==2014.2
|
pytz==2014.2
|
||||||
|
raven==4.2.1
|
||||||
redis==2.9.1
|
redis==2.9.1
|
||||||
reportlab==2.7
|
reportlab==2.7
|
||||||
requests==2.2.1
|
requests==2.2.1
|
||||||
|
@ -51,4 +52,4 @@ six==1.6.1
|
||||||
stripe==1.14.0
|
stripe==1.14.0
|
||||||
websocket-client==0.11.0
|
websocket-client==0.11.0
|
||||||
wsgiref==0.1.2
|
wsgiref==0.1.2
|
||||||
xhtml2pdf==0.0.5
|
xhtml2pdf==0.0.6
|
||||||
|
|
|
@ -778,7 +778,18 @@ quayApp = angular.module('quay', quayDependencies, function($provide, cfpLoading
|
||||||
olark('api.chat.updateVisitorStatus', {snippet: 'username: ' + userResponse.username});
|
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');
|
CookieService.putPermanent('quay.loggedin', 'true');
|
||||||
|
} else {
|
||||||
|
if (window.Raven !== undefined) {
|
||||||
|
Raven.setUser();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt_callback) {
|
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) {
|
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
|
// Based off of a solution found here: http://stackoverflow.com/questions/20325480/angularjs-whats-the-best-practice-to-add-ngif-to-a-directive-programmatically
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.2.0/js/bootstrap-datepicker.min.js"></script>
|
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.2.0/js/bootstrap-datepicker.min.js"></script>
|
||||||
|
|
||||||
<script src="//cdn.jsdelivr.net/g/bootbox@4.1.0,underscorejs@1.5.2,restangular@1.2.0,d3js@3.3.3,momentjs"></script>
|
<script src="//cdn.jsdelivr.net/g/bootbox@4.1.0,underscorejs@1.5.2,restangular@1.2.0,d3js@3.3.3,momentjs"></script>
|
||||||
|
<script src="//cdn.ravenjs.com/1.1.14/jquery,native/raven.min.js"></script>
|
||||||
|
|
||||||
<script src="https://checkout.stripe.com/checkout.js"></script>
|
<script src="https://checkout.stripe.com/checkout.js"></script>
|
||||||
|
|
||||||
|
@ -73,6 +74,12 @@
|
||||||
<script src="/static/{{ script_path }}?v={{ cache_buster }}"></script>
|
<script src="/static/{{ script_path }}?v={{ cache_buster }}"></script>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
{% if sentry_public_dsn %}
|
||||||
|
<script type="text/javascript">
|
||||||
|
Raven.config('{{ sentry_public_dsn }}').install();
|
||||||
|
</script>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if mixpanel_key %}
|
{% if mixpanel_key %}
|
||||||
<!-- start Mixpanel --><script type="text/javascript">
|
<!-- start Mixpanel --><script type="text/javascript">
|
||||||
(function(e,b){if(!b.__SV){var a,f,i,g;window.mixpanel=b;a=e.createElement("script");a.type="text/javascript";a.async=!0;a.src=("https:"===e.location.protocol?"https:":"http:")+'//cdn.mxpnl.com/libs/mixpanel-2.2.min.js';f=e.getElementsByTagName("script")[0];f.parentNode.insertBefore(a,f);b._i=[];b.init=function(a,e,d){function f(b,h){var a=h.split(".");2==a.length&&(b=b[a[0]],h=a[1]);b[h]=function(){b.push([h].concat(Array.prototype.slice.call(arguments,0)))}}var c=b;"undefined"!==
|
(function(e,b){if(!b.__SV){var a,f,i,g;window.mixpanel=b;a=e.createElement("script");a.type="text/javascript";a.async=!0;a.src=("https:"===e.location.protocol?"https:":"http:")+'//cdn.mxpnl.com/libs/mixpanel-2.2.min.js';f=e.getElementsByTagName("script")[0];f.parentNode.insertBefore(a,f);b._i=[];b.init=function(a,e,d){function f(b,h){var a=h.split(".");2==a.length&&(b=b[a[0]],h=a[1]);b[h]=function(){b.push([h].concat(Array.prototype.slice.call(arguments,0)))}}var c=b;"undefined"!==
|
||||||
|
|
28
util/exceptionlog.py
Normal file
28
util/exceptionlog.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
from raven.contrib.flask import Sentry as FlaskSentry
|
||||||
|
|
||||||
|
class FakeSentry(object):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Sentry(object):
|
||||||
|
def __init__(self, app=None):
|
||||||
|
self.app = app
|
||||||
|
if app is not None:
|
||||||
|
self.state = self.init_app(app)
|
||||||
|
else:
|
||||||
|
self.state = None
|
||||||
|
|
||||||
|
def init_app(self, app):
|
||||||
|
sentry_type = app.config.get('EXCEPTION_LOG_TYPE', 'FakeSentry')
|
||||||
|
|
||||||
|
if sentry_type == 'Sentry':
|
||||||
|
sentry = FlaskSentry(app)
|
||||||
|
else:
|
||||||
|
sentry = FakeSentry()
|
||||||
|
|
||||||
|
# register extension with app
|
||||||
|
app.extensions = getattr(app, 'extensions', {})
|
||||||
|
app.extensions['sentry'] = sentry
|
||||||
|
return sentry
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
return getattr(self.state, name, None)
|
Reference in a new issue