From b6825564c720849547ce0851ca56d0ef2d457308 Mon Sep 17 00:00:00 2001 From: Edward Betts Date: Sat, 25 Nov 2023 11:41:53 +0000 Subject: [PATCH] Send error mail to admin Closes: #8 --- geocode/error_mail.py | 72 +++++++++++++++++++++++++++++++++++++++++++ lookup.py | 2 ++ 2 files changed, 74 insertions(+) create mode 100644 geocode/error_mail.py diff --git a/geocode/error_mail.py b/geocode/error_mail.py new file mode 100644 index 0000000..a1d627f --- /dev/null +++ b/geocode/error_mail.py @@ -0,0 +1,72 @@ +"""Send mail to admin when an error happens.""" + +import logging +from logging import Formatter +from logging.handlers import SMTPHandler + +import flask +from flask import g, request + +PROJECT = "geocode" + + +class MySMTPHandler(SMTPHandler): + """Custom SMTP handler to change mail subject.""" + + def getSubject(self, record: logging.LogRecord) -> str: + """Specify subject line for error mails.""" + subject = ( + f"{PROJECT} error: {record.exc_info[0].__name__}" + if (record.exc_info and record.exc_info[0]) + else f"{PROJECT} error: {record.pathname}:{record.lineno:d}" + ) + + if qid := getattr(g, "qid", None): + subject += f" {qid}" + + if label := getattr(g, "label", None): + subject += f": {label}" + + return subject + + +class RequestFormatter(Formatter): + """Custom logging formatter to include request.""" + + def format(self, record: logging.LogRecord) -> str: + """Record includes request.""" + record.request = request + return super().format(record) + + +def setup_error_mail(app: flask.Flask) -> None: + """Send mail to admins when an error happens.""" + formatter = RequestFormatter( + """ + Message type: {levelname} + Location: {pathname:s}:{lineno:d} + Module: {module:s} + Function: {funcName:s} + Time: {asctime:s} + GET args: {request.args!r} + URL: {request.url} + + Message: + + {message:s} + """, + style="{", + ) + + mail_handler = MySMTPHandler( + app.config["SMTP_HOST"], + app.config["MAIL_FROM"], + app.config["ADMINS"], + app.name + " error", + timeout=30, + ) + mail_handler.setFormatter(formatter) + + mail_handler.setLevel(logging.ERROR) + app.logger.propagate = True + app.logger.addHandler(mail_handler) diff --git a/lookup.py b/lookup.py index c79b53b..c0529fb 100755 --- a/lookup.py +++ b/lookup.py @@ -12,11 +12,13 @@ from werkzeug.wrappers import Response import geocode from geocode import database, model, scotland, wikidata +from geocode.error_mail import setup_error_mail city_of_london_qid = "Q23311" app = Flask(__name__) app.config.from_object("config.default") database.init_app(app) +setup_error_mail(app) Tags = typing.Mapping[str, str] logging_enabled = True