logging with custom format throwing "ValueError: Formatting field not found in record" when Flask is involved

logging with custom format throwing "ValueError: Formatting field not found in record" when Flask is involved

好的,所以我将按照 Python 3 文档中的示例进行操作,即:

FORMAT = '%(asctime)-15s %(clientip)s %(user)-8s %(message)s'
logging.basicConfig(format=FORMAT)
d = {'clientip': '192.168.0.1', 'user': 'fbloggs'}
logging.warning('Protocol problem: %s', 'connection reset', extra=d)

这是我的代码:

from flask import Flask
import logging

FORMAT = '%(asctime)s, %(endpt)s, %(message)s'
LOG_ENDPT = 'endpoint was reached'
. . .
@app.route("/status")
def status():
  app.logger.debug(LOG_ENDPT, extra={'endpt':'status'})
. . .
if __name__ == "__main__":
  logging.basicConfig(filename="app.log", format=FORMAT, level=logging.DEBUG)

当我尝试 运行 代码时,出现以下错误:

--- Logging error ---
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/logging/__init__.py", line 434, in format
    return self._format(record)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/logging/__init__.py", line 430, in _format
    return self._fmt % record.__dict__
KeyError: 'endpt'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/logging/__init__.py", line 1083, in emit
    msg = self.format(record)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/logging/__init__.py", line 927, in format
    return fmt.format(record)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/logging/__init__.py", line 666, in format
    s = self.formatMessage(record)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/logging/__init__.py", line 635, in formatMessage
    return self._style.format(record)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/logging/__init__.py", line 436, in format
    raise ValueError('Formatting field not found in record: %s' % e)
ValueError: Formatting field not found in record: 'endpt'

我花了一个多小时在谷歌上搜索解决方案。我没有找到任何特定于此错误的答案。

有趣的是,如果我从命令行使用 python 解释器并仅输入日志代码(无功能),它就可以工作。我不知道为什么函数会导致错误。 顺便说一句,在声明 LOG_ENDPT 之后,我还尝试单独调用 logging.basicConfig()。错误没有区别。

编辑 - 好的,所以我学到了足够多的知识,知道 Flask 是日志记录不起作用的原因。我仍然不确定为什么它不起作用,因为当我删除自定义格式时,错误消失了。 是的,我现在知道在 Flask 函数中正确的调用是 'app.logger.debug()' 。我已经编辑了我的代码以反映这一事实。

最终,我确实找到了一种在使用 Flask 时拥有自定义格式的方法。 我仍然很高兴知道为什么 Flask 通过调用 logging.basicConfig(format=FORMAT) 来阻止使用自定义格式。 这是我的代码:

import logging
from flask import Flask, json
from logging.config import dictConfig

dictConfig({
  'version': 1,
  'formatters': {
    'default': {
      'format': '[%(asctime)s]:%(levelname)s:%(message)s',
    }
  },
  'handlers': {
    'wsgi': {
      'class': 'logging.StreamHandler',
      'stream': 'ext://flask.logging.wsgi_errors_stream',
      'formatter': 'default'
    },
    'file': {
      'class': 'logging.FileHandler',
      'filename': 'app.log',
      'formatter': 'default'
    }
  },
  'root': {
    'level': 'DEBUG',
#    'handlers': ['wsgi','file']
    'handlers': ['file']
  }
})

MSG_ENDPT_FMT = '%s endpoint was reached'

app = Flask(__name__)

@app.route("/")
def hello():
  return "Hello World!"

@app.route("/status")
def status():
  app.logger.debug(MSG_ENDPT_FMT, 'status')
  response = app.response_class(
    response=json.dumps({"result":"OK - healthy"}),
    status=200,
    mimetype='application/json'
  )
  return response

@app.route("/metrics")
def metrics():
  app.logger.debug(MSG_ENDPT_FMT, 'metrics')
  response = app.response_class(
    response=json.dumps({"status":"success","code":0,"data":{"UserCount":140,"UserCountActive":23}}),
    status=200,
    mimetype='application/json'
  )
  return response

if __name__ == "__main__":
  app.run(host='0.0.0.0')