wsgi: Provide python logging compatibility

Provide a compatibility layer in eventlet.wsgi that allows you
to hand a python logger as the log parameter instead of a
filehandle.

If an object that looks like a python logger is passed, we use
it as expected. If not, we assume this is a fileobject that
implements the write() call, and wrap it in a compatiblity layer
that lets us user log() and debug() calls on it, including
optional *args.

https://github.com/eventlet/eventlet/pull/75
This commit is contained in:
Sean Dague
2014-01-22 20:02:44 -05:00
committed by Sergey Shepelev
parent 2b6a7cef37
commit f2aaa0dda9

View File

@@ -225,6 +225,33 @@ class HeadersTooLarge(Exception):
pass pass
def get_logger(log, debug):
if callable(getattr(log, 'info', None)) \
and callable(getattr(log, 'debug', None)):
return log
else:
return LoggerFileWrapper(log, debug)
class LoggerFileWrapper(object):
def __init__(self, log, debug):
self.log = log
self._debug = debug
def info(self, msg, *args, **kwargs):
self.write(msg, *args)
def debug(self, msg, *args, **kwargs):
if self._debug:
self.write(msg, *args)
def write(self, msg, *args):
msg = msg + '\n'
if args:
msg = msg % args
self.log.write(msg)
class FileObjectForHeaders(object): class FileObjectForHeaders(object):
def __init__(self, fp): def __init__(self, fp):
@@ -459,7 +486,7 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
except Exception: except Exception:
self.close_connection = 1 self.close_connection = 1
tb = traceback.format_exc() tb = traceback.format_exc()
self.server.log_message(tb) self.server.log.info(tb)
if not headers_sent: if not headers_sent:
err_body = six.b(tb) if self.server.debug else b'' err_body = six.b(tb) if self.server.debug else b''
start_response("500 Internal Server Error", start_response("500 Internal Server Error",
@@ -485,7 +512,7 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
hook(self.environ, *args, **kwargs) hook(self.environ, *args, **kwargs)
if self.server.log_output: if self.server.log_output:
self.server.log_message(self.server.log_format % { self.server.log.info(self.server.log_format % {
'client_ip': self.get_client_ip(), 'client_ip': self.get_client_ip(),
'client_port': self.client_address[1], 'client_port': self.client_address[1],
'date_time': self.log_date_time_string(), 'date_time': self.log_date_time_string(),
@@ -604,9 +631,9 @@ class Server(BaseHTTPServer.HTTPServer):
self.socket = socket self.socket = socket
self.address = address self.address = address
if log: if log:
self.log = log self.log = get_logger(log, debug)
else: else:
self.log = sys.stderr self.log = get_logger(sys.stderr, debug)
self.app = app self.app = app
self.keepalive = keepalive self.keepalive = keepalive
self.environ = environ self.environ = environ
@@ -660,12 +687,12 @@ class Server(BaseHTTPServer.HTTPServer):
except socket.timeout: except socket.timeout:
# Expected exceptions are not exceptional # Expected exceptions are not exceptional
sock.close() sock.close()
if self.debug: # similar to logging "accepted" in server()
# similar to logging "accepted" in server() self.log.debug('(%s) timed out %r' % (self.pid, address))
self.log_message('(%s) timed out %r' % (self.pid, address))
def log_message(self, message): def log_message(self, message):
self.log.write(message + '\n') warnings.warn('server.log_message is deprecated. Please use server.log.info instead')
self.log.info(message)
try: try:
@@ -789,15 +816,14 @@ def server(sock, site,
if port == ':80': if port == ':80':
port = '' port = ''
serv.log.write("(%s) wsgi starting up on %s://%s%s/\n" % ( serv.log.info("(%s) wsgi starting up on %s://%s%s/" % (
serv.pid, scheme, host, port)) serv.pid, scheme, host, port))
while is_accepting: while is_accepting:
try: try:
client_socket = sock.accept() client_socket = sock.accept()
client_socket[0].settimeout(serv.socket_timeout) client_socket[0].settimeout(serv.socket_timeout)
if debug: serv.log.debug("(%s) accepted %r" % (
serv.log.write("(%s) accepted %r\n" % ( serv.pid, client_socket[1]))
serv.pid, client_socket[1]))
try: try:
pool.spawn_n(serv.process_request, client_socket) pool.spawn_n(serv.process_request, client_socket)
except AttributeError: except AttributeError:
@@ -810,11 +836,11 @@ def server(sock, site,
if support.get_errno(e) not in ACCEPT_ERRNO: if support.get_errno(e) not in ACCEPT_ERRNO:
raise raise
except (KeyboardInterrupt, SystemExit): except (KeyboardInterrupt, SystemExit):
serv.log.write("wsgi exiting\n") serv.log.info("wsgi exiting")
break break
finally: finally:
pool.waitall() pool.waitall()
serv.log.write("(%s) wsgi exited, is_accepting=%s\n" % ( serv.log.info("(%s) wsgi exited, is_accepting=%s" % (
serv.pid, is_accepting)) serv.pid, is_accepting))
try: try:
# NOTE: It's not clear whether we want this to leave the # NOTE: It's not clear whether we want this to leave the