Flask for Python
Learn how to set up Sentry in your Flask app, capture your first errors and traces, and view them in Sentry.
If you're using stream mode, this page's references to "transaction" should be applied to service spans instead. See Streamed Spans for more information.
You need:
- A Sentry account and project
- Your application up and running
- Flask:
1.1.4+(SDK <3.0)2.0.0+(SDK 3.0+)
- Python:
3.6+(SDK <3.0)3.7+(SDK 3.0+)
Run the command for your preferred package manager to add the Sentry SDK to your application:
pip install "sentry-sdk"
pip install "sentry-sdk"
uv add "sentry-sdk"
poetry add "sentry-sdk"
Choose the features you want to configure, and this guide will show you how:
Configuration should happen as early as possible in your application's lifecycle.
If you have the flask package in your dependencies, the Flask integration will be enabled and installed for all your apps automatically when you initialize the Sentry SDK. The SDK hooks into Flask's signals, not anything on the app object.
Import and initialize the SDK in your app's entry point:
import sentry_sdk
# ___PRODUCT_OPTION_START___ metrics
from sentry_sdk import metrics
# ___PRODUCT_OPTION_END___ metrics
sentry_sdk.init(
dsn="___PUBLIC_DSN___",
# Add data like request headers and IP for users, if applicable;
# see https://docs.sentry.io/platforms/python/data-management/data-collected/ for more info
send_default_pii=True,
# ___PRODUCT_OPTION_START___ performance
# Set traces_sample_rate to 1.0 to capture 100%
# of transactions for tracing.
traces_sample_rate=1.0,
# ___PRODUCT_OPTION_END___ performance
# ___PRODUCT_OPTION_START___ profiling
# To collect profiles for all profile sessions,
# set `profile_session_sample_rate` to 1.0.
profile_session_sample_rate=1.0,
# Profiles will be automatically collected while
# there is an active span.
profile_lifecycle="trace",
# ___PRODUCT_OPTION_END___ profiling
)
import sentry_sdk
# ___PRODUCT_OPTION_START___ metrics
from sentry_sdk import metrics
# ___PRODUCT_OPTION_END___ metrics
sentry_sdk.init(
dsn="___PUBLIC_DSN___",
# Add data like request headers and IP for users, if applicable;
# see https://docs.sentry.io/platforms/python/data-management/data-collected/ for more info
send_default_pii=True,
# ___PRODUCT_OPTION_START___ performance
# Set traces_sample_rate to 1.0 to capture 100%
# of transactions for tracing.
traces_sample_rate=1.0,
# ___PRODUCT_OPTION_END___ performance
# ___PRODUCT_OPTION_START___ profiling
# To collect profiles for all profile sessions,
# set `profile_session_sample_rate` to 1.0.
profile_session_sample_rate=1.0,
# Profiles will be automatically collected while
# there is an active span.
profile_lifecycle="trace",
# ___PRODUCT_OPTION_END___ profiling
)
To further customize your setup, review the Options section below.
Sentry automatically captures errors and reports issues for you. You can also expect the following for your Flask app:
- If you use
flask-login, and you've setsend_default_pii=Truein your call toinit, user data (such as current user ID, email address, username) will be attached to error events. - Request data will be attached to all events: HTTP method, URL, headers, form data, JSON payloads. Sentry excludes raw bodies and multipart file uploads.
- Logs emitted by any
app.loggeror any logger will be recorded by the Logging integration (this integration is enabled by default).
Let's test your setup and confirm that data reaches your Sentry project.
Errors triggered from a Python shell like IPython will not trigger Sentry's error monitoring. Make sure you're running the examples from a file instead.
To verify that Sentry captures errors and creates issues in your Sentry project, add this intentional error to your application:
import sentry_sdk
from flask import Flask
sentry_sdk.init(...) # same as above
app = Flask(__name__)
@app.route("/")
def hello_world():
1 / 0 # raises an error
return "<p>Hello, World!</p>"
import sentry_sdk
from flask import Flask
sentry_sdk.init(...) # same as above
app = Flask(__name__)
@app.route("/")
def hello_world():
1 / 0 # raises an error
return "<p>Hello, World!</p>"
To test your tracing configuration, create a custom transaction and span:
import sentry_sdk
with sentry_sdk.start_transaction(op="task", name="Transaction Name"):
span = sentry_sdk.start_span(name="Custom Span Name")
span.finish()
import sentry_sdk
with sentry_sdk.start_transaction(op="task", name="Transaction Name"):
span = sentry_sdk.start_span(name="Custom Span Name")
span.finish()
import sentry_sdk
with sentry_sdk.traces.start_span(name="Service Span Name", attributes={"sentry.op": "task"}, parent_span=None):
span = sentry_sdk.traces.start_span(name="Custom Span Name")
span.end()
To verify that Sentry catches your logs (which are enabled by default), add some log statements to your application:
import sentry_sdk
sentry_sdk.logger.info("This is an info log message")
sentry_sdk.logger.warning("This is a warning message")
sentry_sdk.logger.error("This is an error message")
import sentry_sdk
sentry_sdk.logger.info("This is an info log message")
sentry_sdk.logger.warning("This is a warning message")
sentry_sdk.logger.error("This is an error message")
Send test metrics from your app to verify that metrics are arriving in Sentry:
from sentry_sdk import metrics
metrics.count("checkout.failed", 1)
metrics.gauge("queue.depth", 42)
metrics.distribution("cart.amount_usd", 187.5)
from sentry_sdk import metrics
metrics.count("checkout.failed", 1)
metrics.gauge("queue.depth", 42)
metrics.distribution("cart.amount_usd", 187.5)
Now, head over to your project on Sentry.io to view the collected data (it takes a couple of moments for the data to appear).
In stream mode, these options still work as described, but apply to service spans instead of transactions.
Add FlaskIntegration explicitly to your sentry_sdk.init() call to set options for FlaskIntegration to change its behavior:
import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration
sentry_sdk.init(
# ...
integrations = [
FlaskIntegration(
transaction_style="url",
http_methods_to_capture=("GET",),
),
],
)
import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration
sentry_sdk.init(
# ...
integrations = [
FlaskIntegration(
transaction_style="url",
http_methods_to_capture=("GET",),
),
],
)
You can pass the following keyword arguments to FlaskIntegration():
transaction_style
| Type | string |
|---|---|
| Default | "endpoint" |
How to name transactions that show up in Sentry tracing. The default is "endpoint".
In the code example, the transaction name will be:
/myurl/<foo>if you settransaction_style="url"myendpointif you settransaction_style="endpoint"
@app.route("/myurl/<foo>")
def myendpoint():
return "<p>Hello, World!</p>"
@app.route("/myurl/<foo>")
def myendpoint():
return "<p>Hello, World!</p>"
http_methods_to_capture
| Available since | 2.15.0 |
|---|---|
| Type | Tuple[str, ...] |
| Default | ("CONNECT", "DELETE", "GET", "PATCH", "POST", "PUT", "TRACE",) |
A tuple containing all the HTTP methods (as uppercase strings) that should create a transaction in Sentry. The default is ("CONNECT", "DELETE", "GET", "PATCH", "POST", "PUT", "TRACE",).
Note that OPTIONS and HEAD are excluded by default.
At this point, you should have integrated Sentry into your application and should already be sending data to your Sentry project.
Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are:
- Explore practical guides on what to monitor, log, track, and investigate after setup
- Continue to customize your configuration
- Learn more about manually capturing errors or messages
- Dive straight into the API with our API docs
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").