1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
|
Flask
=====
Installation
------------
If you haven't already, install raven with its explicit Flask dependencies::
pip install raven[flask]
Setup
-----
The first thing you'll need to do is to initialize Raven under your application::
from raven.contrib.flask import Sentry
sentry = Sentry(app, dsn='___DSN___')
If you don't specify the ``dsn`` value, we will attempt to read it from
your environment under the ``SENTRY_DSN`` key.
Extended Setup
--------------
You can optionally configure logging too:
.. sourcecode:: python
import logging
from raven.contrib.flask import Sentry
sentry = Sentry(app, logging=True, level=logging.ERROR, \
logging_exclusions=("logger1", "logger2", ...))
Building applications on the fly? You can use Raven's ``init_app`` hook:
.. sourcecode:: python
sentry = Sentry(dsn='http://public_key:secret_key@example.com/1')
def create_app():
app = Flask(__name__)
sentry.init_app(app)
return app
You can pass parameters in the ``init_app`` hook:
.. sourcecode:: python
sentry = Sentry()
def create_app():
app = Flask(__name__)
sentry.init_app(app, dsn='___DSN___', logging=True,
level=logging.ERROR,
logging_exclusions=("logger1", "logger2", ...))
return app
Settings
--------
Additional settings for the client can be configured using
``SENTRY_CONFIG`` in your application's configuration:
.. sourcecode:: python
class MyConfig(object):
SENTRY_CONFIG = {
'dsn': '___DSN___',
'include_paths': ['myproject'],
'release': raven.fetch_git_sha(os.path.dirname(__file__)),
}
If `Flask-Login <https://pypi.python.org/pypi/Flask-Login/>`_ is used by
your application (including `Flask-Security
<https://pypi.python.org/pypi/Flask-Security/>`_), user information will
be captured when an exception or message is captured. By default, only
the ``id`` (current_user.get_id()), ``is_authenticated``, and
``is_anonymous`` is captured for the user. If you would like additional
attributes on the ``current_user`` to be captured, you can configure them
using ``SENTRY_USER_ATTRS``:
.. sourcecode:: python
class MyConfig(object):
SENTRY_USER_ATTRS = ['username', 'first_name', 'last_name', 'email']
``email`` will be captured as ``sentry.interfaces.User.email``, and any
additional attributes will be available under
``sentry.interfaces.User.data``
You can specify the types of exceptions that should not be reported by
Sentry client in your application by setting the ``ignore_exceptions``
configuration value:
.. sourcecode:: python
class MyExceptionType(Exception):
def __init__(self, message):
super(MyExceptionType, self).__init__(message)
app = Flask(__name__)
app.config['SENTRY_CONFIG'] = {
'ignore_exceptions': [MyExceptionType],
}
Usage
-----
Once you've configured the Sentry application it will automatically
capture uncaught exceptions within Flask. If you want to send additional
events, a couple of shortcuts are provided on the Sentry Flask middleware
object.
Capture an arbitrary exception by calling ``captureException``:
.. sourcecode:: python
try:
1 / 0
except ZeroDivisionError:
sentry.captureException()
Log a generic message with ``captureMessage``:
.. sourcecode:: python
sentry.captureMessage('hello, world!')
Getting The Last Event ID
-------------------------
If possible, the last Sentry event ID is stored in the request context
``g.sentry_event_id`` variable. This allow to present the user an error
ID if have done a custom error 500 page.
.. sourcecode:: html+jinja
<h2>Error 500</h2>
{% if g.sentry_event_id %}
<p>The error identifier is {{ g.sentry_event_id }}</p>
{% endif %}
.. _python-flask-user-feedback:
User Feedback
-------------
To enable user feedback for crash reports just make sure you have a custom
`500` error handler and render out a HTML snippet for bringing up the
crash dialog:
.. sourcecode:: python
from flask import Flask, g, render_template
from raven.contrib.flask import Sentry
app = Flask(__name__)
sentry = Sentry(app, dsn='___DSN___')
@app.errorhandler(500)
def internal_server_error(error):
return render_template('500.html',
event_id=g.sentry_event_id,
public_dsn=sentry.client.get_public_dsn('https')
)
And in the error template (``500.html``) you can then do this:
.. sourcecode:: html+jinja
<!-- Sentry JS SDK 2.1.+ required -->
<script src="https://cdn.ravenjs.com/2.3.0/raven.min.js"></script>
{% if event_id %}
<script>
Raven.showReportDialog({
eventId: '{{ event_id }}',
dsn: '{{ public_dsn }}'
});
</script>
{% endif %}
That's it!
For more details on this feature, see the :doc:`User Feedback guide
<../../../learn/user-feedback>`.
Dealing With Proxies
--------------------
When your Flask application is behind a proxy such as nginx, Sentry will
use the remote address from the proxy, rather than from the actual
requesting computer. By using ``ProxyFix`` from `werkzeug.contrib.fixers
<http://werkzeug.pocoo.org/docs/0.10/contrib/fixers/#werkzeug.contrib.fixers.ProxyFix>`_
the Flask ``.wsgi_app`` can be modified to send the actual ``REMOTE_ADDR``
along to Sentry. ::
from werkzeug.contrib.fixers import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app)
This may also require `changes
<http://flask.pocoo.org/docs/0.10/deploying/wsgi-standalone/#proxy-setups>`_
to the proxy configuration to pass the right headers if it isn't doing so
already.
Signals
-------
Raven uses `blinker <https://github.com/jek/blinker>`_ to emit a signal
(called ``logging_configured``) after logging has been configured for the
client. You may `bind to that signal <https://pythonhosted.org/blinker/#subscribing-to-signals>`_
in your application to do any additional configuration to the logging
handler ``SentryHandler``.
.. sourcecode:: python
from raven.contrib.flask import Sentry, logging_configured
from flask import Flask, g, render_template
from raven.contrib.flask import Sentry
app = Flask(__name__)
sentry = Sentry(app, dsn='___DSN___', logging=True)
@logging_configured.connect
def internal_server_error(sender, sentry_handler=None, **kwargs):
# configure sentry_handler here
sentry_handler.addFilter(some_filter)
|