【问题标题】:How do I customize Tornado's access logs如何自定义 Tornado 的访问日志
【发布时间】:2016-11-05 12:32:17
【问题描述】:

我有一个通过 Tornado 运行的 Flask 应用程序:

import os
import logging
import sys
from flask import Flask, request, jsonify
from tornado.wsgi import WSGIContainer
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop

app = Flask(__name__)

@app.route("/test", methods=["GET"])
def healthz():
    return jsonify(message="OK!"), 200

@app.errorhandler(404)
def not_found(error):

    return jsonify(error="Requested page does not exist."), 404

def run_app():

    http_server = HTTPServer(WSGIContainer(app))
    http_server.listen(port=9000)
    IOLoop.instance().start()

if __name__ == '__main__':

    logFormat = "timestamp=%(asctime)s pid=%(process)d loglevel=%(levelname)s %(message)s"
    logging.basicConfig(
        stream=sys.stdout,
        level=logging.INFO,
        format=logFormat
    )

    run_app()

我正在使用自定义日志并获得如下输出:

timestamp=2016-11-05 12:26:39,287 pid=23356 loglevel=INFO 200 GET /test (10.0.2.2) 0.63ms
timestamp=2016-11-05 12:26:10,306 pid=23356 loglevel=WARNING 404 GET / (10.0.2.2) 0.67ms

如何修改 Tornado 的访问日志显示如下:

status_code=200 method=GET URL=/test ip=10.0.2.2 duration=0.63ms

所以我最终在标准输出中得到了这个:

timestamp=2016-11-05 12:26:10,306 pid=23356 loglevel=INFO status_code=200 method=GET URL=/test ip=10.0.2.2 duration=0.63ms

【问题讨论】:

    标签: python http logging flask tornado


    【解决方案1】:

    我会覆盖 WSGIContainer 的日志功能:

    from tornado.log import access_log
    from tornado.wsgi import WSGIContainer
    
    class MyWSGI(WSGIContainer):
        def _log(self, status_code, request):
            if status_code < 400:
                log_method = access_log.info
            elif status_code < 500:
                log_method = access_log.warning
            else:
                log_method = access_log.error
    
            request_time = 1000.0 * request.request_time()
            log_method(
                "status_code=%s method=%s URL=%s ip=%s duration=%.2fms",
                status_code, request.method,
                request.uri, request.remote_ip, request_time)
    

    然后使用 MyWSGI 代替 WSGIContainer。

    【讨论】:

      【解决方案2】:

      无论您使用哪个 WSGI 服务器,您都可以使用 wsgi-request-logger 来执行此操作:

      def log_formatter(status_code, environ, content_length, *, rt_us=None, **kwargs):
          rt_ms = rt_us / 1000.0
          return "status_code={status_code} method={environ[REQUEST_METHOD]} path=environ[PATH_INFO] ip={environ[REMOTE_ADDR]} duration={rt_ms}ms".format(**locals())
      
      def run_app():
          logging_app = WSGILogger(app, [], log_formatter)
          import tornado.log
          tornado.log.access_log.addFilter(lambda record: False)
      
          http_server = HTTPServer(WSGIContainer(logging_app))
          http_server.listen(port=9000)
          IOLoop.instance().start()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-05-04
        • 1970-01-01
        • 2016-06-07
        • 1970-01-01
        • 1970-01-01
        • 2022-11-28
        • 1970-01-01
        相关资源
        最近更新 更多