Skip to content

Commit 99ed9b2

Browse files
committed
add new blog post
1 parent 97cd9a5 commit 99ed9b2

File tree

11 files changed

+284
-2
lines changed

11 files changed

+284
-2
lines changed

content/pages/02-development-environments/02-vim.markdown

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ Vim's philosophy is that developers are more productive when they avoid
2020
taking their hands off the keyboard. Code should flow naturally from the
2121
developer's thoughts through the keyboard and onto the screen. Using a mouse
2222
or other peripheral is a detriment to the rate at which a developer's
23-
thoughts become code.
23+
thoughts become code. This "efficiency by keyboard"
24+
[keeps Vim as one of the most popular text editors](https://pragmaticpineapple.com/how-did-vim-become-so-popular/)
25+
despite having been around for decades. Few programming tools have that kind
26+
of staying power.
2427

2528
Vim has a logical, structured command language. When a beginner is learning
2629
the editor she may feel like it is impossible to understand all the key

content/pages/02-development-environments/19-git.markdown

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,12 @@ workflow. These resources will come in handy for specific Git subjects.
141141
important when working with others on a long-lasting project where you
142142
dive through the commit history via `git log` and related commands.
143143

144+
* [How to squash Git commits](https://gitbetter.substack.com/p/how-to-squash-git-commits)
145+
explains how to use the `git rebase` command in interactive mode to
146+
consolidated the number of commits in your history. This technique is
147+
useful when a group of commits are related and it's easier to understand
148+
them as a single commit rather than a collection of smaller commits.
149+
144150
* [Oh shit, Git!](http://ohshitgit.com/) is a profanity-filled description
145151
of tips to get you out of binds you may find yourself in when you get too
146152
tricky with Git commands.

content/pages/03-data/16-pandas.markdown

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,6 @@ is a data structures and analysis library.
126126
* [How to download fundamentals data with Python](http://theautomatic.net/2020/05/05/how-to-download-fundamentals-data-with-python/)
127127
shows how to obtain and use financial data, such as balance sheets,
128128
stock prices, and various ratios to perform your own analysis on.
129+
130+
* [How to convert JSON to Excel with Python and pandas](https://www.marsja.se/how-to-convert-json-to-excel-python-pandas/)
131+
provides instructions for creating a spreadsheet out of JSON file.

content/pages/04-web-development/21-bootstrap.markdown

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ specific situation.
4747
is an awesome tutorial that goes through many of the main Bootstrap
4848
elements such as icons, navigation bars and "jumbotron"-style webpages.
4949

50+
* [Bootstrap 5 tutorial](https://www.youtube.com/watch?v=c9B4TPnak1A) covers
51+
the alpha version of the fifth major revision for Bootstrap.
52+
5053
* [Bootstrap 4: What's New?](https://medium.com/wdstack/bootstrap-4-whats-new-visual-guide-c84dd81d8387)
5154
shows a slew of comparisons for how user interface elements have changed
5255
design over the past several Bootstrap major version iterations.
Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
title: How to Report Errors in Flask Web Apps with Sentry
2+
slug: report-errors-flask-web-apps-sentry
3+
meta: Learn how to use Sentry and the Flask integration to easily report errors in your Python-based web applications.
4+
category: post
5+
date: 2020-06-30
6+
modified: 2020-07-02
7+
newsletters: False
8+
headerimage: /img/headers/flask-sentry.jpg
9+
headeralt: Logos for the implementations used in this blog post. Copyright their respective owners.
10+
11+
12+
[Flask](/flask.html) web applications are highly customizable by developers
13+
thanks to the [framework](/web-frameworks.html)'s extension-based
14+
architecture, but that flexibility can sometimes lead to more errors
15+
when you run the application due to rough edges between the libraries.
16+
17+
Reporting errors is crucial to running a well-functioning Flask web
18+
application, so this tutorial will guide you through adding a free, basic
19+
[Sentry](https://sentry.io) configuration to a fresh Flask project.
20+
21+
22+
## Tutorial Requirements
23+
Ensure you have Python 3 installed, because Python 2 reached its
24+
end-of-life at the beginning of 2020 and is no longer supported.
25+
Preferrably, you should have
26+
[Python 3.7 or greater installed](https://www.python.org/downloads/)
27+
in your [development environment](/development-environments.html).
28+
This tutorial will also use:
29+
30+
* [Flask](/flask.html) web framework,
31+
[version 1.1.2](https://github.com/pallets/flask/releases/tag/1.1.2)
32+
* a hosted Sentry instance on [sentry.io](https://sentry.io), which we'll
33+
need an account to access
34+
* the [Sentry Python helper library](https://pypi.org/project/sentry-sdk/) to
35+
send exception data to our Sentry instance, with the
36+
[Flask integration](https://docs.sentry.io/platforms/python/flask/)
37+
38+
All code in this blog post is available open source under the MIT license
39+
on GitHub under the
40+
[report-errors-flask-web-apps-sentry directory of the blog-code-examples](https://github.com/fullstackpython/blog-code-examples/tree/master/report-errors-flask-web-apps-sentry)
41+
repository. Use the source code as you desire for your own projects.
42+
43+
44+
## Development environment set up
45+
Change into the directory where you keep your Python
46+
[virtual environments](/virtual-environments-virtualenvs-venvs.html).
47+
Create a new virtualenv for this project using the following
48+
command.
49+
50+
Install the Flask and Sentry-SDK code libraries into a new Python
51+
virtual environment using the following commands:
52+
53+
```bash
54+
python -m venv sentryflask
55+
source sentryflask/bin/activate
56+
57+
pip install flask>=1.1.2 sentry-sdk[flask]==0.15.1
58+
```
59+
60+
Note that we installed the Flask integration as part of the Sentry
61+
SDK, which is why the dependency is `sentry-sdk[flask]` rather than
62+
just `sentry-sdk`.
63+
64+
Now that we have all of our dependencies installed we can code up a
65+
little application to show how the error reporting works.
66+
67+
68+
## Creating the application
69+
We have everything we need to start building our application. Create
70+
a new directory for your project. I've called mine
71+
[report-errors-flask-web-apps-sentry](https://github.com/fullstackpython/blog-code-examples/tree/master/report-errors-flask-web-apps-sentry)
72+
in the examples repository but you can use a shorter name if you
73+
prefer. Open a new file named `app.py` and write the following code in it.
74+
75+
```python
76+
# app.py
77+
from flask import Flask, escape, request
78+
79+
80+
app = Flask(__name__)
81+
82+
83+
@app.route('/divide/<int:numerator>/by/<int:denominator>/')
84+
def hello(numerator, denominator):
85+
answer = numerator / denominator
86+
return f'{numerator} can be divided by {denominator} {answer} times.'
87+
88+
```
89+
90+
The above code is a short Flask application that allows input via the URL for
91+
two integer values: a numerator and a denominator.
92+
93+
Save the file and run it using the `flask run` command:
94+
95+
```bash
96+
env FLASK_APP=app.py flask run
97+
```
98+
99+
If you see the following output on the command line that means the development
100+
server is working properly:
101+
102+
```bash
103+
* Serving Flask app "app.py"
104+
* Environment: production
105+
WARNING: This is a development server. Do not use it in a production deployment.
106+
Use a production WSGI server instead.
107+
* Debug mode: off
108+
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
109+
```
110+
111+
Test it by going to http://localhost:5000/divide/50/by/10/ and you will
112+
get the following output in your web browser:
113+
114+
<img src="/img/200630-python-flask-sentry/division-success.png" width="100%" class="shot rnd outl" alt="Successful division of 50 by 10.">
115+
116+
With our base application working, we can now add error reporting for
117+
the situations that do not work as expected.
118+
119+
120+
## Adding Sentry to our app
121+
It's time to add Sentry with the Flask integration into the mix, so that we
122+
can easily see when the route errors out due to bad input.
123+
124+
Sentry can either be [self-hosted](https://github.com/getsentry/onpremise) or
125+
used as a cloud service through [Sentry.io](https://sentry.io). In this
126+
tutorial we will use the cloud hosted version because it's faster than
127+
setting up your own server as well as free for smaller projects.
128+
129+
Go to [Sentry.io's homepage](https://sentry.io).
130+
131+
<img src="/img/200525-sentry/sentry-homepage.jpg" width="100%" class="shot rnd outl" alt="Sentry.io homepage where you can sign up for a free account.">
132+
133+
Sign into your account or sign up for a new free account. You will be at
134+
the main account dashboard after logging in or completing the Sentry sign
135+
up process.
136+
137+
There are no errors logged on our account dashboard yet, which is as
138+
expected because we have not yet connected our account to our Python
139+
application.
140+
141+
<img src="/img/200525-sentry/sentry-empty-dashboard.jpg" width="100%" class="shot rnd outl" alt="Blank Sentry account dashboard.">
142+
143+
You'll want to create a new Sentry Project just for this application so
144+
click "Projects" in the left sidebar to go to the Projects page.
145+
146+
<img src="/img/200525-sentry/create-project.jpg" width="100%" class="shot rnd outl" alt="Button to create a new Sentry project.">
147+
148+
On the Projects page, click the "Create Project" button in the top right
149+
corner of the page.
150+
151+
<img src="/img/200525-sentry/create-new-project-screen.jpg" width="100%" class="shot rnd outl" alt="Create a new Sentry project.">
152+
153+
You can either choose "Flask" or select "Python". I usually just choose
154+
"Python" if I do not yet know what framework I'll be using to build my
155+
application. Next, give your new Project a name and then press the "Create
156+
Project" button. Our new project is ready to integrate with our Python code.
157+
158+
We need the unique identifier for our account and project to authorize our
159+
Python code to send errors to this Sentry instance. The easiest way to get
160+
what we need is to go to the
161+
[Python+Flask documentation page](https://docs.sentry.io/platforms/python/flask/)
162+
and read how to configure the SDK.
163+
164+
<img src="/img/200525-sentry/python-sentry-quickstart.jpg" width="100%" class="shot rnd outl" alt="The Sentry docs show you exactly what you need to export to connect to your account.">
165+
166+
Copy the string parameter for the `init` method and set it
167+
[as an environment variable](https://www.twilio.com/blog/2017/01/how-to-set-environment-variables.html)
168+
rather than having it exposed in your project's code.
169+
170+
```bash
171+
export SENTRY_DSN='https://yourkeygoeshere.ingest.sentry.io/project-number'
172+
```
173+
174+
**Make sure to replace "yourkeygoeshere" with your own unique identifier
175+
and "project-number" with the ID that matches the project you just
176+
created.**
177+
178+
Check that the `SENTRY_DSN` is set properly in your shell using the `echo`
179+
command:
180+
181+
```bash
182+
echo $SENTRY_DSN
183+
```
184+
185+
186+
Update `app.py` with the following highlighted lines of code.
187+
188+
```python
189+
# app.py
190+
~~import os
191+
~~import sentry_sdk
192+
from flask import Flask, escape, request
193+
~~from sentry_sdk.integrations.flask import FlaskIntegration
194+
195+
196+
~~sentry_sdk.init(
197+
~~ dsn=os.getenv('SENTRY_DSN'), integrations=[FlaskIntegration()]
198+
~~)
199+
200+
201+
app = Flask(__name__)
202+
203+
204+
@app.route('/divide/<int:numerator>/by/<int:denominator>/')
205+
def hello(numerator, denominator):
206+
answer = numerator / denominator
207+
return f'{numerator} can be divided by {denominator} {answer} times.'
208+
```
209+
210+
The above new lines of code initialize the Sentry client and allow it to
211+
properly send any errors that occur over to the right Sentry service.
212+
213+
214+
## Testing the Sentry Integration
215+
The Sentry dashboard shows that the service is still waiting for events.
216+
217+
<img src="/img/200630-python-flask-sentry/waiting-for-events.jpg" width="100%" class="shot rnd outl" alt="Sentry dashboard, without any error data shown.">
218+
219+
Let's make an error happen to see if we've properly connected the Flask integration
220+
with our application.
221+
222+
Try to divide by zero, by going to http://localhost:5000/divide/50/by/0/ in
223+
your web browser. You should get an "Internal Server Error".
224+
225+
<img src="/img/200630-python-flask-sentry/internal-server-error.png" width="100%" class="shot rnd outl" alt="Flask HTTP status code 500 for internal server error.">
226+
227+
Back over in the Sentry dashboard, the error appears in the list.
228+
229+
<img src="/img/200630-python-flask-sentry/zero-division-error.png" width="100%" class="shot rnd outl" alt="Sentry dashboard showing the exact ZeroDivisionError.">
230+
231+
We can drill into the error by clicking on it and get a ton more information,
232+
not just about our application but also about the client that visited the
233+
site. This is handy if you have an issue in a specific browser or other
234+
type of client when building an [API](/application-programming-interfaces.html).
235+
236+
<img src="/img/200630-python-flask-sentry/error-details.jpg" width="100%" class="shot rnd outl" alt="ZeroDivisionError error details in the Sentry user interface.">
237+
238+
With that in place, you can now build out the rest of your Flask application
239+
knowing that all of the exceptions will be tracked in Sentry.
240+
241+
242+
## What's next?
243+
We just finished building a Flask app to show how quickly the hosted
244+
version of Sentry can be added to applications so you do not lose
245+
track of your error messages.
246+
247+
Next, you can try one of these tutorials to add other useful features to your
248+
new application:
249+
250+
* [Responding to SMS Text Messages with Python & Flask](/blog/respond-sms-text-messages-python-flask.html)
251+
* [Develop and Run Flask Apps within Docker Containers](/blog/develop-flask-web-apps-docker-containers-macos.html)
252+
* [Add Okta Authentication to an Existing Flask App](/blog/okta-user-auth-existing-flask-web-app.html)
253+
254+
You can also determine what to code next in your Python project by reading
255+
the [Full Stack Python table of contents page](/table-of-contents.html).
256+
257+
Questions? Contact me via Twitter
258+
[@fullstackpython](https://twitter.com/fullstackpython)
259+
or [@mattmakai](https://twitter.com/mattmakai). I am also on GitHub with
260+
the username [mattmakai](https://github.com/mattmakai).
261+
262+
If you see an issue or error in this tutorial, please
263+
[fork the source repository on GitHub](https://github.com/mattmakai/fullstackpython/blob/master/content/posts/200630-report-errors-flask-web-apps-sentry.markdown)
264+
and submit a pull request with the fix.
35.1 KB
Loading
-59.9 KB
Loading
23.6 KB
Loading

static/img/headers/django.jpg

23.9 KB
Loading
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<a href="/learning-programming.html" class="lgi">Learning Programming</a>
2+
<a href="/web-development.html" class="lgi">Web development</a>
3+
<a href="/django.html" class="lgi">Django</a>
4+
<a href="/markdown.html" class="lgi">Markdown</a>

0 commit comments

Comments
 (0)