2013-07-23 55 views
2

我正在爲Web應用程序使用cherrypy(提供WSGI)的瓶子。 CherryPy不會在此設置中記錄網絡訪問。目前,我幾乎使用瓶子的hook plug-in記錄一切,就像這樣:使用瓶子和cherrypy記錄響應內容的長度

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) 

這提供了日誌記錄到標準輸出,就像這樣:

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

這幾乎是正確的,但內容長度總是0.看起來瓶子並不知道cherrypy返回的內容長度。這是一個正確的評估,更重要的是,有沒有辦法檢索它,所以我可以登錄它?

我打開更好的方式來獲得訪問日誌使用瓶和櫻桃。

謝謝!

回答

3

我可以想到幾種方法,但以下是我認爲最好的方法:使用中間件應用程序記錄請求。

下面是一個基於您的問題代碼的完整示例。 (我並沒有改變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) 

這應該做的伎倆;如果沒有,讓我知道,我會幫助。

+1

工作正常,但您的解決方案基本上重複瓶的鉤子插件,除了響應對象具有有效的內容長度。這看起來好像瓶子的鉤子插件中有一個錯誤。 – Trevor

+0

同意。 FWIW,我認爲即使勾子按預期工作,包裝/分層方法也比瓶子的使用鉤更優雅。無論如何,它開心工作! –