Last active
May 23, 2021 07:25
-
-
Save ivanleoncz/dbf29670761cbaed4c5c787d9c9c006b to your computer and use it in GitHub Desktop.
Demonstration of logging feature for a Flask App.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#/usr/bin/python3 | |
""" Demonstration of logging feature for a Flask App. """ | |
from logging.handlers import RotatingFileHandler | |
from flask import Flask, request, jsonify | |
from time import strftime | |
__author__ = "@ivanleoncz" | |
import logging | |
import traceback | |
app = Flask(__name__) | |
@app.route("/") | |
@app.route("/index") | |
def get_index(): | |
""" Function for / and /index routes. """ | |
return "Welcome to Flask! " | |
@app.route("/data") | |
def get_data(): | |
""" Function for /data route. """ | |
data = { | |
"Name":"Ivan Leon", | |
"Occupation":"Software Developer", | |
"Technologies":"[Python, Flask, JavaScript, Java, SQL]" | |
} | |
return jsonify(data) | |
@app.route("/error") | |
def get_nothing(): | |
""" Route for intentional error. """ | |
return foobar # intentional non-existent variable | |
@app.after_request | |
def after_request(response): | |
""" Logging after every request. """ | |
# This avoids the duplication of registry in the log, | |
# since that 500 is already logged via @app.errorhandler. | |
if response.status_code != 500: | |
ts = strftime('[%Y-%b-%d %H:%M]') | |
logger.error('%s %s %s %s %s %s', | |
ts, | |
request.remote_addr, | |
request.method, | |
request.scheme, | |
request.full_path, | |
response.status) | |
return response | |
@app.errorhandler(Exception) | |
def exceptions(e): | |
""" Logging after every Exception. """ | |
ts = strftime('[%Y-%b-%d %H:%M]') | |
tb = traceback.format_exc() | |
logger.error('%s %s %s %s %s 5xx INTERNAL SERVER ERROR\n%s', | |
ts, | |
request.remote_addr, | |
request.method, | |
request.scheme, | |
request.full_path, | |
tb) | |
return "Internal Server Error", 500 | |
if __name__ == '__main__': | |
# maxBytes to small number, in order to demonstrate the generation of multiple log files (backupCount). | |
handler = RotatingFileHandler('app.log', maxBytes=10000, backupCount=3) | |
# getLogger(__name__): decorators loggers to file + werkzeug loggers to stdout | |
# getLogger('werkzeug'): decorators loggers to file + nothing to stdout | |
logger = logging.getLogger(__name__) | |
logger.setLevel(logging.ERROR) | |
logger.addHandler(handler) | |
app.run(host="127.0.0.1",port=8000) | |
# ---> getLogger(__name__) | |
# | |
# $ python3 simple_app_logging.py | |
# * Running on http://127.0.0.1:8000/ (Press CTRL+C to quit) | |
# 127.0.0.1 - - [11/Mar/2018 18:55:39] "GET / HTTP/1.1" 200 - | |
# 127.0.0.1 - - [11/Mar/2018 18:55:47] "GET /data HTTP/1.1" 200 - | |
# 127.0.0.1 - - [11/Mar/2018 18:55:50] "GET /error HTTP/1.1" 500 - | |
# | |
# $ cat app.log | |
# [2018-Mar-11 18:55] 127.0.0.1 GET http /? 200 OK | |
# [2018-Mar-11 18:55] 127.0.0.1 GET http /data? 200 OK | |
# [2018-Mar-11 18:55] 127.0.0.1 GET http /error? 5xx INTERNAL SERVER ERROR | |
# Traceback (most recent call last): | |
# File "/usr/local/lib/python3.4/dist-packages/flask/app.py", line 1612, in full_dispatch_request | |
# rv = self.dispatch_request() | |
# File "/usr/local/lib/python3.4/dist-packages/flask/app.py", line 1598, in dispatch_request | |
# return self.view_functions[rule.endpoint](**req.view_args) | |
# File "simple_app_logging.py", line 37, in get_nothing | |
# return foobar # intentional non-existent variable | |
# NameError: name 'foobar' is not defined | |
# ---> getLogger('werkzeug') | |
# | |
# $ python3 simple_app_logging.py | |
# | |
# | |
# | |
# $ cat app.log | |
# [2018-Mar-11 18:44] 127.0.0.1 GET http /? 200 OK | |
# [2018-Mar-11 18:44] 127.0.0.1 GET http /data? 200 OK | |
# [2018-Mar-11 18:45] 127.0.0.1 GET http /error? 5xx INTERNAL SERVER ERROR | |
# Traceback (most recent call last): | |
# File "/usr/local/lib/python3.4/dist-packages/flask/app.py", line 1612, in full_dispatch_request | |
# rv = self.dispatch_request() | |
# File "/usr/local/lib/python3.4/dist-packages/flask/app.py", line 1598, in dispatch_request | |
# return self.view_functions[rule.endpoint](**req.view_args) | |
# File "simple_app_logging.py", line 37, in get_nothing | |
# return foobar # intentional non-existent variable | |
# NameError: name 'foobar' is not defined | |
# For more info: https://stackoverflow.com/questions/14037975/how-do-i-write-flasks-excellent-debug-log-message-to-a-file-in-production/39284642#39284642 | |
# |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Flask's documentation reads "As of Flask 0.7 this function might not be executed at the end of the request in case an unhandled exception occurred." That's the situation where I care about logging. Anyone encountered problems with that?