【问题标题】:logging response content length using bottle and cherrypy使用瓶子和cherrypy记录响应内容长度
【发布时间】:2013-07-23 22:10:18
【问题描述】:

我正在使用带有cherrypy(提供WSGI)的bottle 用于Web 应用程序。 CherryPy 在此设置中不记录 Web 访问。目前,我几乎使用瓶子的hook plug-in 记录所有内容,如下所示:

import bottle
from bottle import route, static_file, get, post, error, request, template, redirect, response, hook

@hook('after_request')
def log_after_request():
    try:
        length = response.content_length
    except:
        try:
            length = len(response.body)
        except:
            length = '???'
    print '{ip} - - [{time}] "{method} {uri} {protocol}" {status} {length}'.format(
        ip=request.environ.get('REMOTE_ADDR'),
        time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
        method=request.environ.get('REQUEST_METHOD'),
        uri=request.environ.get('REQUEST_URI'),
        protocol=request.environ.get('SERVER_PROTOCOL'),
        status=response.status_code,
        length=length,
    )

@route('/index.html')
def index_handler():
    return '<h1>Hello, world!</h1>'

app = bottle.default_app()
bottle.run(host='0.0.0.0', port='80', app=app, server='cherrypy', request_queue_size=300, debug=True)

这会向 STDOUT 提供日志条目,如下所示:

192.168.1.1 - - [2013-07-23 17:04:04] "GET /index.html HTTP/1.1" 200 0

这几乎是正确的,除了内容长度始终为 0。瓶子似乎不知道cherrypy返回的内容长度。这是一个正确的评估吗?更重要的是,有没有办法检索它,以便我可以记录它?

我愿意接受更好的方法来使用bottle和cherrypy获取访问日志。

谢谢!

【问题讨论】:

    标签: python logging cherrypy bottle content-length


    【解决方案1】:

    我可以想到几种方法,但这是我认为最好的一种:使用中间件应用程序来记录请求。

    这是基于您问题中的代码的完整示例。 (我没有改log_after_request;大部分动作都在AccessLogMiddleware.__call__。)

    import datetime
    import bottle
    from bottle import route, static_file, get, post, error, request, template, redirect, response, hook
    
    # unchanged from OP
    @route('/index.html')
    def index_handler():
        return '<h1>Hello, world!</h1>'
    
    # unchanged from OP
    def log_after_request():
        try:
            length = response.content_length
        except:
            try:
                length = len(response.body)
            except:
                length = '???'
        print 'MYLOG:', '{ip} - - [{time}] "{method} {uri} {protocol}" {status} {length}'.format(
            ip=request.environ.get('REMOTE_ADDR'),
            time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            method=request.environ.get('REQUEST_METHOD'),
            uri=request.environ.get('REQUEST_URI'),
            protocol=request.environ.get('SERVER_PROTOCOL'),
            status=response.status_code,
            length=length,
        )
    
    # code I've added begins here
    class AccessLogMiddleware(object):
        def __init__(self, app):
            self.app = app
    
        def __call__(self, e, h):
            # call bottle and store the return value
            ret_val = self.app(e, h)
    
            # log the request
            log_after_request()
    
            # return bottle's return value
            return ret_val
    
    
    app = bottle.app()
    logged_app = AccessLogMiddleware(app)
    bottle.run(host='0.0.0.0', port='8000', app=logged_app)
    

    这应该可以解决问题;如果没有,请告诉我,我会提供帮助。

    【讨论】:

    • 这行得通,但您的解决方案基本上复制了瓶子的钩子插件,除了响应对象具有有效的内容长度。这让我觉得瓶子的钩子插件中有一个错误。
    • 同意。 FWIW,我确实认为包装/分层方法比瓶子的使用钩子更优雅,即使钩子确实按预期工作。无论如何,很高兴它成功了!
    【解决方案2】:

    当您更新到尚未正式发布的 Bottle 0.13-dev 分支时,原始问题中的代码现在可以使用。最新的稳定版 0.12.18 发布的分支仍然存在这个 bug,并且响应内容长度仍然会返回 0。

    更新到 0.13(您可以在此处获取:https://github.com/bottlepy/bottle)后,代码现在可以工作了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-23
      相关资源
      最近更新 更多