Skip to content

Commit 62823bd

Browse files
committed
WSGILogger(..., ip_header='HTTP_X_FORWARDED_FOR', ...) kw arg
This new keyword argument allows to use headers such as X-Forwarded-For for the 'host' field in your logging. This is useful if you run behind a reverse proxy. You have to specify the header as it will be provided by the WSGI environment, in this case it would be HTTP_X_FORWARDED_FOR. All characters are in uppercase and dashes will be replaced by underscores. If you don't specify the keyword argument, it defaults to None. Then, or whenever the header is not found in the WSGI environment, the logged host will default to the REMOTE_ADDR.
1 parent a59b4ef commit 62823bd

File tree

1 file changed

+17
-9
lines changed

1 file changed

+17
-9
lines changed

requestlogger/__init__.py

+17-9
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,14 @@
2828
class WSGILogger(object):
2929
""" This is the generalized WSGI middleware for any style request logging. """
3030

31-
def __init__(self, application, handlers, formatter=None, propagate=True, **kw):
31+
def __init__(self, application, handlers, formatter=None, propagate=True, ip_header=None, **kwargs):
3232
self.formatter = formatter or WSGILogger.standard_formatter
3333
self.logger = logging.getLogger('requestlogger')
3434
self.logger.propagate = propagate
3535
self.logger.setLevel(logging.DEBUG)
3636
for handler in handlers:
3737
self.logger.addHandler(handler)
38+
self.ip_header = ip_header
3839
self.application = application
3940

4041
def __call__(self, environ, start_response):
@@ -52,7 +53,7 @@ def custom_start_response(status, response_headers, exc_info=None):
5253
retval = self.application(environ, custom_start_response)
5354
runtime = int((clock() - start) * 10**6)
5455
content_length = content_lengths[0] if content_lengths else len(b''.join(retval))
55-
msg = self.formatter(status_codes[0], environ, content_length, rt_us=runtime)
56+
msg = self.formatter(status_codes[0], environ, content_length, ip_header=self.ip_header, rt_us=runtime)
5657
self.logger.info(msg)
5758
return retval
5859

@@ -80,7 +81,14 @@ def format_NCSA_log(status_code, environ, content_length, **kwargs):
8081

8182
# Let's collect log values
8283
val = dict()
83-
val['host'] = environ.get('REMOTE_ADDR', '')
84+
ip_header = kwargs.get('ip_header', None)
85+
if ip_header:
86+
try:
87+
val['host'] = environ.get(ip_header, '')
88+
except:
89+
val['host'] = environ.get('REMOTE_ADDR', '')
90+
else:
91+
val['host'] = environ.get('REMOTE_ADDR', '')
8492
val['logname'] = '-'
8593
val['user'] = '-'
8694
date = dt.now(tz=Local)
@@ -102,19 +110,19 @@ def format_NCSA_log(status_code, environ, content_length, **kwargs):
102110
return FORMAT.format(**val)
103111

104112
@staticmethod
105-
def format_with_response_time(*args, **kw):
113+
def format_with_response_time(*args, **kwargs):
106114
"""
107-
The dict kw should contain 'rt_us', the response time in milliseconds.
115+
The dict kwargs should contain 'rt_us', the response time in milliseconds.
108116
This is the format for TinyLogAnalyzer:
109117
https://pypi.python.org/pypi/TinyLogAnalyzer
110118
"""
111-
rt_us = kw.get('rt_us')
112-
return ApacheFormatters.format_NCSA_log(*args) + " {0}/{1}".format(int(rt_us/1000000), rt_us)
119+
rt_us = kwargs.get('rt_us')
120+
return ApacheFormatters.format_NCSA_log(*args, **kwargs) + " {0}/{1}".format(int(rt_us/1000000), rt_us)
113121

114122

115-
def log(handlers, formatter=ApacheFormatter(), **kw):
123+
def log(handlers, formatter=ApacheFormatter(), **kwargs):
116124
"""Decorator for logging middleware."""
117125
def decorator(application):
118-
return WSGILogger(application, handlers, **kw)
126+
return WSGILogger(application, handlers, **kwargs)
119127
return decorator
120128

0 commit comments

Comments
 (0)