How do you know whether your application is running properly with minimal errors after building and deploying it? The fastest and easiest way to monitor your operational Flask web application is to integrate one of the many available fantastic hosted monitoring tools.
In this post we will quickly add Rollbar monitoring to catch errors and visualize our application is running properly. There are also many other great hosted monitoring tools, which you can check out on the monitoring page.
We can use either Python 2 or 3 to build this tutorial, but Python 3 is strongly recommended for all new applications. I used Python 3.6.2 to execute my code. We will also use the following application dependencies throughout the post:
If you need help getting your development environment configured before running this code, take a look at this guide for setting up Python 3 and Flask on Ubuntu 16.04 LTS.
All code in this blog post is available open source under the MIT license on GitHub under the monitor-flask-apps directory of the blog-code-examples repository. Use and abuse the source code as you desire for your own applications.
Change into the directory where you keep your Python virtualenvs. Create a new virtual environment for this project using the following command.
python3 -m venv monitorflask
Activate the virtualenv.
source monitorflask/bin/activate
The command prompt will change after activating the virtualenv:
Remember that you need to activate the virtualenv in every new terminal window where you want to use the virtualenv to run the project.
Flask, Rollbar and Blinker can now be installed into the now-activated virtualenv.
pip install flask==0.12.2 rollbar==0.13.12 blinker==1.4
Our required dependencies should be installed within our virtualenv after a short installation period. Look for output like the following to confirm everything worked.
Installing collected packages: blinker, itsdangerous, click, MarkupSafe, Jinja2, Werkzeug, Flask, idna, urllib3, chardet, certifi, requests, six, rollbar
Running setup.py install for blinker ... done
Running setup.py install for itsdangerous ... done
Running setup.py install for MarkupSafe ... done
Running setup.py install for rollbar ... done
Successfully installed Flask-0.12.2 Jinja2-2.9.6 MarkupSafe-1.0 Werkzeug-0.12.2 blinker-1.4 certifi-2017.4.17 chardet-3.0.4 click-6.7 idna-2.5 itsdangerous-0.24 requests-2.18.1 rollbar-0.13.12 six-1.10.0 urllib3-1.21.1
Now that we have our Python dependencies installed into our virtualenv we can create the initial version of our application.
Create a folder for your project named monitor-flask-apps
. Change into
the folder and then create a file named app.py
with the following
code.
import re
from flask import Flask, render_template, Response
from werkzeug.exceptions import NotFound
app = Flask(__name__)
MIN_PAGE_NAME_LENGTH = 2
@app.route("/<string:page>/")
def show_page(page):
try:
valid_length = len(page) >= MIN_PAGE_NAME_LENGTH
valid_name = re.match('^[a-z]+$', page.lower()) is not None
if valid_length and valid_name:
return render_template("{}.html".format(page))
else:
msg = "Sorry, couldn't find page with name {}".format(page)
raise NotFound(msg)
except:
return Response("404 Not Found")
if __name__ == "__main__":
app.run(debug=True)
The above application code has some standard Flask imports so we can
create a Flask web app and render template files. We have a single
function named show_page
to serve a single Flask route. show_page
checks if the URL path contains only lowercase alpha characters for a
potential page name. If the page name can be found in the templates
folder then the page is rendered, otherwise an exception is thrown
that the page could not be found. We need to create at least one template
file if our function is ever going to return a non-error reponse.
Save app.py
and make a new subdirectory named templates
under your
project directory. Create a new file named battlegrounds.html
and put
the following Jinja2 template markup into it.
<!DOCTYPE html>
<html>
<head>
<title>You found the Battlegrounds GIF!</title>
</head>
<body>
<h1>PUBG so good.</h1>
<img src="https://media.giphy.com/media/3ohzdLMlhId2rJuLUQ/giphy.gif">
</body>
</html>
The above Jinja2 template is basic HTML without any embedded template tags. The template creates a very plain page with a header description of "PUBG so good" and a GIF from this excellent computer game.
Time to run and test our code. Change into the base directory of your
project where app.py
file is located. Execute app.py
using the python
command as follows (make sure your virtualenv is still activated in the
terminal where you are running this command):
python app.py
The Flask development server should start up and display a few lines of output.
What happens when we access the application running on localhost port 5000?
HTTP status 404 page not found, which is what we expected because we only defined a single route and it did not live at the base path.
We created a template named battlegrounds.html
that should be accessible
when we go to
localhost:5000/battlegrounds/.
The application successfully found the battlegrounds.html
template but
that is the only one available. What if we try
localhost:5000/fullstackpython/?
HTTP 500 error. That's no good.
The 404 and 500 errors are obvious to us right now because we are testing the application locally. However, what happens when the app is deployed and a user gets the error in their own web browser? They will typically quit out of frustration and you will never know what happened unless you add some error tracking and application monitoring.
We will now modify our code to add Rollbar to catch and report those errors that occur for our users.
Head to Rollbar's homepage so we can add their hosted monitoring tools to our oft-erroring Flask app.
Click the "Sign Up" button in the upper right-hand corner. Enter your email address, a username and the password you want on the sign up page.
After the sign up page you will see the onboarding flow where you can enter a project name and select a programming language. For project name enter "Battlegrounds" and select that you are monitoring a Python app.
Press the "Continue" button at the bottom to move along. The next screen shows us a few quick instructions to add monitoring to our Flask application.
Let's modify our Flask application to test whether we can properly connect
to Rollbar's service. Change app.py
to include the following highlighted
lines.
import os
import re
import rollbar
from flask import Flask, render_template, Response
from werkzeug.exceptions import NotFound
app = Flask(__name__)
MIN_PAGE_NAME_LENGTH = 2
@app.before_first_request
def add_monitoring():
rollbar.init(os.environ.get('ROLLBAR_SECRET'))
rollbar.report_message('Rollbar is configured correctly')
@app.route("/<string:page>/")
def show_page(page):
try:
valid_length = len(page) >= MIN_PAGE_NAME_LENGTH
valid_name = re.match('^[a-z]+$', page.lower()) is not None
if valid_length and valid_name:
return render_template("{}.html".format(page))
else:
msg = "Sorry, couldn't find page with name {}".format(page)
raise NotFound(msg)
except:
return Response("404 Not Found")
if __name__ == "__main__":
app.run(debug=True)
We added a couple of new imports, os
and rollbar
. os
allows us to
grab environment variable values, such as our Rollbar secret key. rollbar
is the library we installed earlier. The two lines below the Flask app
instantiation are to initialize Rollbar using the Rollbar secret token and
send a message to the service that it started correctly.
The ROLLBAR_SECRET
token needs to be set in an environment variable.
Save an quit the app.py
. Run export ROLLBAR_SECRET='token here'
on the
command line where your virtualenv is activated. This token can be found
on the Rollbar onboarding screen.
I typically store all my environment variables in a file like
template.env and invoke it from the terminal using
the . ./template.env
command. Make sure to avoid committing your secret
tokens to a source control repository, especially if the repository is
public!
After exporting your ROLLBAR_SECRET
key as an environment variable
we can test that Rollbar is working as we run our application. Run it
now using python
:
python app.py
Back in your web browser press the "Done! Go to Dashboard" button. Don't worry about the "Report an Error" section code, we can get back to that in a moment.
If the event hasn't been reported yet we'll see a waiting screen like this one:
Once Flask starts up though, the first event will be populated on the dashboard.
Okay, our first test event has been populated, but we really want to see all the errors from our application, not a test event.
How do we make sure real errors are reported rather than just a simple test event? We just need to add a few more lines of code to our app.
import os
import re
import rollbar
import rollbar.contrib.flask
from flask import Flask, render_template, Response
from flask import got_request_exception
from werkzeug.exceptions import NotFound
app = Flask(__name__)
MIN_PAGE_NAME_LENGTH = 2
@app.before_first_request
def add_monitoring():
rollbar.init(os.environ.get('ROLLBAR_SECRET'))
## delete the next line if you dont want this event anymore
rollbar.report_message('Rollbar is configured correctly')
got_request_exception.connect(rollbar.contrib.flask.report_exception, app)
@app.route("/<string:page>/")
def show_page(page):
try:
valid_length = len(page) >= MIN_PAGE_NAME_LENGTH
valid_name = re.match('^[a-z]+$', page.lower()) is not None
if valid_length and valid_name:
return render_template("{}.html".format(page))
else:
msg = "Sorry, couldn't find page with name {}".format(page)
raise NotFound(msg)
except:
rollbar.report_exc_info()
return Response("404 Not Found")
if __name__ == "__main__":
app.run(debug=True)
The above highlighted code modifies the application so it reports all Flask
errors as well as our HTTP 404 not found issues that happen within the
show_page
function.
Make sure your Flask development server is running and try to go to localhost:5000/b/. You will receive an HTTP 404 exception and it will be reported to Rollbar. Next go to localhost:5000/fullstackpython/ and an HTTP 500 error will occur.
You should see an aggregation of errors as you test out these errors:
Woohoo, we finally have our Flask app reporting all errors that occur for any user back to the hosted Rollbar monitoring service!
We just learned how to catch and handle errors with Rollbar as a hosted monitoring platform in a simple Flask application. Next you will want to add monitoring to your more complicated web apps. You can also check out some of Rollbar's more advanced features such as:
There is a lot more to learn about web development and deployments so keep learning by reading up on Flask and other web frameworks such as Django, Pyramid and Sanic. You can also learn more about integrating Rollbar with Python applications via their Python documentation.
Questions? Let me know via a GitHub issue ticket on the Full Stack Python repository, on Twitter @fullstackpython or @mattmakai.
See something wrong in this blog post? Fork this page's source on GitHub and submit a pull request with a fix.
Fix errors in your Python code before your users see them by monitoring with Rollbar.