[英]Flask - how to write werkzeug logs to log file using RotatingFileHandler?
I've found some somewhat similar questions, but nothing that directly addresses this.我发现了一些类似的问题,但没有直接解决这个问题。
I'm trying to output all Werkzeug logging to a log file.我正在尝试将所有 Werkzeug 日志记录输出到日志文件。 I can get part of the logging to output to the file, but I cannot seem to capture any errors or anything beyond the basic route/request lines.我可以将部分日志记录输出到文件,但我似乎无法捕获任何错误或超出基本路由/请求行的任何内容。
Here is what I have.这就是我所拥有的。 How can I include ALL output from Werkzeug?如何包含 Werkzeug 的所有输出?
if __name__ == '__main__':
configure_app(app)
handler=RotatingFileHandler('server_werkzeug.log', maxBytes=10000000, backupCount=5)
log = logging.getLogger('werkzeug')
log.setLevel(logging.DEBUG)
log.addHandler(handler)
This code works perfectly for logging. 此代码非常适合记录日志。 As for the problem of not logging errors it seems, that you have to specify other loggers, besides 'werkzeug'. 至于不记录错误的问题,似乎您必须指定“ werkzeug”之外的其他记录器。 For traceback errors in Flask it's app.logger what you're looking for. 对于Flask中的追溯错误,您要找的是app.logger 。 And don't forget to set the level to WARNING. 并且不要忘记将级别设置为“警告”。
import logging
import logging.handlers
app = Flask(__name__)
handler = logging.handlers.RotatingFileHandler(
'log.txt',
maxBytes=1024 * 1024)
logging.getLogger('werkzeug').setLevel(logging.DEBUG)
logging.getLogger('werkzeug').addHandler(handler)
app.logger.setLevel(logging.WARNING)
app.logger.addHandler(handler)
You can add other loggers as well, if your app is using some third party tools for like database queries, cron jobs etc. 如果您的应用程序使用某些第三方工具(例如数据库查询,cron作业等),则也可以添加其他记录器。
logging.getLogger('apscheduler.scheduler').setLevel(logging.DEBUG)
logging.getLogger('apscheduler.scheduler').addHandler(handler)
The name of a logger can be found in the terminal window: 记录器的名称可以在终端窗口中找到:
INFO:werkzeug:127.0.0.1 - - [10/Mar/2018 15:41:15] "GET /file.js HTTP/1.1" 200 -
DEBUG:apscheduler.scheduler:Next wakeup is due at 2018-03-10 16:00:00+03:00 (in 1124.668881 seconds)
Use the dictConfig
is a more extendable way. 使用dictConfig
是更可扩展的方法。
from logging.config import dictConfig
dictConfig({
'version': 1,
'handlers': {
'file.handler': {
'class': 'logging.handlers.RotatingFileHandler',
'filename': 'server_werkzeug.log',
'maxBytes': 10000000,
'backupCount': 5,
'level': 'DEBUG',
},
},
'loggers': {
'werkzeug': {
'level': 'DEBUG',
'handlers': ['file.handler'],
},
},
})
If you are interested in separating the access log from other werkzeug
logging calls, you can implement the following monkey patch.如果您有兴趣将访问日志与其他werkzeug
日志记录调用分开,您可以实现以下猴子补丁。
This is handy for doing development work as access logs are very handy for troubleshooting but having werkzeug
printing alongside your other logs is not very helpful for readability.这对于进行开发工作很方便,因为访问日志对于故障排除非常方便,但是将werkzeug
打印在您的其他日志旁边对可读性没有多大帮助。
__access_log_enabled__ = False # Override to enable logger (eg when running code outside of wsgi server)
def log_request(self:werkzeug.serving.WSGIRequestHandler,
code: typing.Union[int, str] = "-",
size: typing.Union[int, str] = "-") -> None:
if not __access_log_enabled__: return
_server_.log_request(handler=self, code=code, size=size)
# where _server_ is your own class for managing the server
werkzeug.serving.WSGIRequestHandler.log_request = log_request
Here is a example consuming this:这是一个使用它的示例:
import werkzeug
import typing
import logging
from logging.handlers import RotatingFileHandler
from datetime import datetime
_server_ = None
class MyServer():
def __init__(self, in_wsgi:bool):
global _server_
_server_ = self
# ...
log_werkzeug = logging.getLogger('werkzeug')
log_werkzeug.setLevel(logging.ERROR)
# This will suppress all logs from werkzeug below Error
# with the exception of the redirected access logs
if not in_wsgi:
self.acc_log = logging.getLogger('qflask_access_log')
handler = RotatingFileHandler('./log/access_non_wsgi.log',
maxBytes=100000,
backupCount=5)
handler.setFormatter(logging.Formatter("%(message)s"))
self.acc_log.addHandler(handler)
self.acc_log.setLevel(logging.INFO)
global __access_log_enabled__
__access_log_enabled__ = True
# ...
# ...
def log_request(self,
handler:werkzeug.serving.WSGIRequestHandler,
code: typing.Union[int, str] = "-",
size: typing.Union[int, str] = "-") -> None:
try:
path = werkzeug.urls.uri_to_iri(handler.path)
msg = f"{handler.command} {path} {handler.request_version}"
except AttributeError:
# path isn't set if the requestline was bad
msg = handler.requestline
code = str(code)
self.acc_log.warning(
f"[{datetime.now().strftime('%y%m%d-%H%M%S.%f')}] {code} {msg} {size}")
This is probably a good feature to have built into werkezug.这可能是 werkezug 内置的一个很好的功能。 In fact with access_log_enabled = False, it will make any server a tiny bit faster.事实上,使用access_log_enabled = False,它会让任何服务器都快一点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.