Reputation: 120
OK, so I'm following the example in the Python 3 docs which is:
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)
Here's my code:
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)
When I try to run the code, I get the following error:
--- 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'
I have spent over an hour googling for a solution. I have not found any answer which is specific to this error.
What is interesting, is if I use the python interpreter from the command line and type in just the logging code (no function), it works. I do not know why the function should cause the error. BTW, I also tried with my call to logging.basicConfig() on the lone after my declaration of LOG_ENDPT. There was no difference in the error.
EDIT - OK, so I learned enough to know that Flask is the reason the logging does not work. I'm still unsure why it does not work, because when I remove the custom format, the error goes away. And yes, I am now aware that the correct call is 'app.logger.debug()' within a Flask function. I've edited my code to reflect this fact.
Upvotes: 2
Views: 11033
Reputation: 120
Eventually, I did find a way to have a custom format while Flask is in use.
I would still appreciate knowing why Flask prevents the use of a custom format via a call to logging.basicConfig(format=FORMAT)
.
Here's my code:
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')
Upvotes: 1