日誌¶
Flask 使用標準 Python logging
模組。關於您的 Flask 應用程式的訊息會使用 app.logger
記錄,其名稱與 app.name
相同。此記錄器也可以用來記錄您自己的訊息。
@app.route('/login', methods=['POST'])
def login():
user = get_user(request.form['username'])
if user.check_password(request.form['password']):
login_user(user)
app.logger.info('%s logged in successfully', user.username)
return redirect(url_for('index'))
else:
app.logger.info('%s failed to log in', user.username)
abort(401)
如果您未設定日誌,Python 的預設日誌層級通常為 ‘warning’。低於設定層級的任何訊息都將不可見。
基本設定¶
當您想要為您的專案設定日誌時,您應該在程式啟動時儘快進行設定。如果在設定日誌之前存取 app.logger
,它將新增一個預設處理器。如果可能,請在建立應用程式物件之前設定日誌。
此範例使用 dictConfig()
來建立一個與 Flask 預設設定相似的日誌設定,但適用於所有日誌。
from logging.config import dictConfig
dictConfig({
'version': 1,
'formatters': {'default': {
'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s',
}},
'handlers': {'wsgi': {
'class': 'logging.StreamHandler',
'stream': 'ext://flask.logging.wsgi_errors_stream',
'formatter': 'default'
}},
'root': {
'level': 'INFO',
'handlers': ['wsgi']
}
})
app = Flask(__name__)
預設設定¶
如果您未自行設定日誌,Flask 將自動新增一個 StreamHandler
到 app.logger
。在請求期間,它會寫入 WSGI 伺服器在 environ['wsgi.errors']
中指定的串流(通常是 sys.stderr
)。在請求之外,它將記錄到 sys.stderr
。
移除預設處理器¶
如果您在存取 app.logger
之後設定了日誌,並且需要移除預設處理器,您可以匯入並移除它
from flask.logging import default_handler
app.logger.removeHandler(default_handler)
以電子郵件將錯誤發送給管理員¶
當在遠端伺服器上執行生產環境的應用程式時,您可能不會經常查看日誌訊息。WSGI 伺服器可能會將日誌訊息發送到檔案,而且只有在使用者告訴您發生錯誤時,您才會檢查該檔案。
為了積極主動地發現和修正錯誤,您可以設定一個 logging.handlers.SMTPHandler
,以便在記錄錯誤及更高等級的訊息時發送電子郵件。
import logging
from logging.handlers import SMTPHandler
mail_handler = SMTPHandler(
mailhost='127.0.0.1',
fromaddr='server-error@example.com',
toaddrs=['admin@example.com'],
subject='Application Error'
)
mail_handler.setLevel(logging.ERROR)
mail_handler.setFormatter(logging.Formatter(
'[%(asctime)s] %(levelname)s in %(module)s: %(message)s'
))
if not app.debug:
app.logger.addHandler(mail_handler)
這需要您在同一伺服器上設定 SMTP 伺服器。請參閱 Python 文件以取得有關設定處理器的更多資訊。
注入請求資訊¶
查看更多關於請求的資訊,例如 IP 位址,可能有助於偵錯某些錯誤。您可以子類別化 logging.Formatter
以注入您自己的欄位,這些欄位可以用於訊息中。您可以變更 Flask 預設處理器、上面定義的郵件處理器或任何其他處理器的格式器。
from flask import has_request_context, request
from flask.logging import default_handler
class RequestFormatter(logging.Formatter):
def format(self, record):
if has_request_context():
record.url = request.url
record.remote_addr = request.remote_addr
else:
record.url = None
record.remote_addr = None
return super().format(record)
formatter = RequestFormatter(
'[%(asctime)s] %(remote_addr)s requested %(url)s\n'
'%(levelname)s in %(module)s: %(message)s'
)
default_handler.setFormatter(formatter)
mail_handler.setFormatter(formatter)
其他函式庫¶
其他函式庫可能會大量使用日誌,而您也希望看到來自這些日誌的相關訊息。最簡單的方法是將處理器新增到根記錄器,而不僅僅是應用程式記錄器。
from flask.logging import default_handler
root = logging.getLogger()
root.addHandler(default_handler)
root.addHandler(mail_handler)
根據您的專案,分別設定您關心的每個記錄器可能比僅設定根記錄器更有用。
for logger in (
logging.getLogger(app.name),
logging.getLogger('sqlalchemy'),
logging.getLogger('other_package'),
):
logger.addHandler(default_handler)
logger.addHandler(mail_handler)
Werkzeug¶
Werkzeug 將基本的請求/回應資訊記錄到 'werkzeug'
記錄器。如果根記錄器沒有設定任何處理器,Werkzeug 會將 StreamHandler
新增到其記錄器。
Flask 擴充套件¶
根據情況,擴充套件可能會選擇記錄到 app.logger
或其自己的具名記錄器。請查閱每個擴充套件的文件以了解詳細資訊。