Skip to content

Commit fec99a7

Browse files
committed
Properly setup Flask logging to stderr
Sometimes there is nothing, sometimes lines are duplicated. Duplicated lines problem appears, because Python root logger handler and Flask's `werkzeug` logger handler both write the same message. `cheat.sh` is hit, because it sets this root logging handler. Normally `werkzeug` doesn't setup its own handler if it sees that there are some handlers that process its messages. This in case of `cheat.sh` resulted in no stderr logging at all. No Exceptions either. Because `werkzeug` catches the exceptions and logs them. Hovewer, sometimes `werkzeug` starts too early, befora app is imported (pallets/werkzeug#1969) and sets its logger anyway, before the app itself, resulting in duplicating lines. In that case app root handler needs to skip lines from `werkzeug`. Kudos to @brandon-rhodes for `logging_tree` awesomeness
1 parent a4be5d8 commit fec99a7

File tree

1 file changed

+22
-0
lines changed

1 file changed

+22
-0
lines changed

bin/app.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,34 @@
3737

3838
from stateful_queries import save_query, last_query
3939

40+
4041
if not os.path.exists(os.path.dirname(CONFIG["path.log.main"])):
4142
os.makedirs(os.path.dirname(CONFIG["path.log.main"]))
4243
logging.basicConfig(
4344
filename=CONFIG["path.log.main"],
4445
level=logging.DEBUG,
4546
format='%(asctime)s %(message)s')
47+
# Fix Flask "exception and request logging" to `stderr`.
48+
#
49+
# When Flask's werkzeug detects that logging is already set, it
50+
# doesn't add its own logger that prints exceptions.
51+
stderr_handler = logging.StreamHandler()
52+
logging.getLogger().addHandler(stderr_handler)
53+
#
54+
# Alter log format to disting log lines from everything else
55+
stderr_handler.setFormatter(logging.Formatter('%(filename)s:%(lineno)s: %(message)s'))
56+
#
57+
# Sometimes werkzeug starts logging before an app is imported
58+
# (https://github.com/pallets/werkzeug/issues/1969)
59+
# resulting in duplicating lines. In that case we need root
60+
# stderr handler to skip lines from werkzeug.
61+
class SkipFlaskLogger(object):
62+
def filter(self, record):
63+
if record.name != 'werkzeug':
64+
return True
65+
if logging.getLogger('werkzeug').handlers:
66+
stderr_handler.addFilter(SkipFlaskLogger())
67+
4668

4769
app = Flask(__name__) # pylint: disable=invalid-name
4870
app.jinja_loader = jinja2.ChoiceLoader([

0 commit comments

Comments
 (0)