Merge "Add accurate timestamps in proxy log"

This commit is contained in:
Jenkins 2013-12-03 03:51:42 +00:00 committed by Gerrit Code Review
commit 645d1c93c5
2 changed files with 28 additions and 19 deletions

View File

@ -131,7 +131,7 @@ class ProxyLoggingMiddleware(object):
return value return value
def log_request(self, req, status_int, bytes_received, bytes_sent, def log_request(self, req, status_int, bytes_received, bytes_sent,
request_time): start_time, end_time):
""" """
Log a request. Log a request.
@ -139,7 +139,8 @@ class ProxyLoggingMiddleware(object):
:param status_int: integer code for the response status :param status_int: integer code for the response status
:param bytes_received: bytes successfully read from the request body :param bytes_received: bytes successfully read from the request body
:param bytes_sent: bytes yielded to the WSGI server :param bytes_sent: bytes yielded to the WSGI server
:param request_time: time taken to satisfy the request, in seconds :param start_time: timestamp request started
:param end_time: timestamp request completed
""" """
if self.req_already_logged(req): if self.req_already_logged(req):
return return
@ -152,12 +153,17 @@ class ProxyLoggingMiddleware(object):
logged_headers = '\n'.join('%s: %s' % (k, v) logged_headers = '\n'.join('%s: %s' % (k, v)
for k, v in req.headers.items()) for k, v in req.headers.items())
method = self.method_from_req(req) method = self.method_from_req(req)
end_gmtime_str = time.strftime('%d/%b/%Y/%H/%M/%S',
time.gmtime(end_time))
duration_time_str = "%.4f" % (end_time - start_time)
start_time_str = "%.9f" % start_time
end_time_str = "%.9f" % end_time
self.access_logger.info(' '.join( self.access_logger.info(' '.join(
quote(str(x) if x else '-', QUOTE_SAFE) quote(str(x) if x else '-', QUOTE_SAFE)
for x in ( for x in (
get_remote_client(req), get_remote_client(req),
req.remote_addr, req.remote_addr,
time.strftime('%d/%b/%Y/%H/%M/%S', time.gmtime()), end_gmtime_str,
method, method,
the_request, the_request,
req.environ.get('SERVER_PROTOCOL'), req.environ.get('SERVER_PROTOCOL'),
@ -170,9 +176,11 @@ class ProxyLoggingMiddleware(object):
req.headers.get('etag', None), req.headers.get('etag', None),
req.environ.get('swift.trans_id'), req.environ.get('swift.trans_id'),
logged_headers, logged_headers,
'%.4f' % request_time, duration_time_str,
req.environ.get('swift.source'), req.environ.get('swift.source'),
','.join(req.environ.get('swift.log_info') or ''), ','.join(req.environ.get('swift.log_info') or ''),
start_time_str,
end_time_str
))) )))
self.mark_req_logged(req) self.mark_req_logged(req)
# Log timing and bytes-transfered data to StatsD # Log timing and bytes-transfered data to StatsD
@ -181,7 +189,7 @@ class ProxyLoggingMiddleware(object):
# down (egregious errors will get logged by the proxy server itself). # down (egregious errors will get logged by the proxy server itself).
if metric_name: if metric_name:
self.access_logger.timing(metric_name + '.timing', self.access_logger.timing(metric_name + '.timing',
request_time * 1000) (end_time - start_time) * 1000)
self.access_logger.update_stats(metric_name + '.xfer', self.access_logger.update_stats(metric_name + '.xfer',
bytes_received + bytes_sent) bytes_received + bytes_sent)
@ -263,7 +271,7 @@ class ProxyLoggingMiddleware(object):
status_int = status_int_for_logging(client_disconnect) status_int = status_int_for_logging(client_disconnect)
self.log_request( self.log_request(
req, status_int, input_proxy.bytes_received, bytes_sent, req, status_int, input_proxy.bytes_received, bytes_sent,
time.time() - start_time) start_time, time.time())
try: try:
iterable = self.app(env, my_start_response) iterable = self.app(env, my_start_response)
@ -271,8 +279,8 @@ class ProxyLoggingMiddleware(object):
req = Request(env) req = Request(env)
status_int = status_int_for_logging(start_status=500) status_int = status_int_for_logging(start_status=500)
self.log_request( self.log_request(
req, status_int, input_proxy.bytes_received, 0, req, status_int, input_proxy.bytes_received, 0, start_time,
time.time() - start_time) time.time())
raise raise
else: else:
return iter_response(iterable) return iter_response(iterable)

View File

@ -14,7 +14,6 @@
# limitations under the License. # limitations under the License.
import unittest import unittest
import time
from urllib import unquote from urllib import unquote
import cStringIO as StringIO import cStringIO as StringIO
from logging.handlers import SysLogHandler from logging.handlers import SysLogHandler
@ -152,7 +151,8 @@ class TestProxyLogging(unittest.TestCase):
app = proxy_logging.ProxyLoggingMiddleware(FakeApp(), {}) app = proxy_logging.ProxyLoggingMiddleware(FakeApp(), {})
app.access_logger = FakeLogger() app.access_logger = FakeLogger()
req = Request.blank(bad_path, environ={'REQUEST_METHOD': 'GET'}) req = Request.blank(bad_path, environ={'REQUEST_METHOD': 'GET'})
app.log_request(req, 123, 7, 13, 2.71828182846) now = 10000.0
app.log_request(req, 123, 7, 13, now, now + 2.71828182846)
self.assertEqual([], app.access_logger.log_dict['timing']) self.assertEqual([], app.access_logger.log_dict['timing'])
self.assertEqual([], app.access_logger.log_dict['update_stats']) self.assertEqual([], app.access_logger.log_dict['update_stats'])
@ -254,7 +254,8 @@ class TestProxyLogging(unittest.TestCase):
app = proxy_logging.ProxyLoggingMiddleware(FakeApp(), {}) app = proxy_logging.ProxyLoggingMiddleware(FakeApp(), {})
app.access_logger = FakeLogger() app.access_logger = FakeLogger()
req = Request.blank('/v1/a/', environ={'REQUEST_METHOD': method}) req = Request.blank('/v1/a/', environ={'REQUEST_METHOD': method})
app.log_request(req, 299, 11, 3, 1.17) now = 10000.0
app.log_request(req, 299, 11, 3, now, now + 1.17)
self.assertTiming('account.%s.299.timing' % exp_method, app, self.assertTiming('account.%s.299.timing' % exp_method, app,
exp_timing=1.17 * 1000) exp_timing=1.17 * 1000)
self.assertUpdateStats('account.%s.299.xfer' % exp_method, self.assertUpdateStats('account.%s.299.xfer' % exp_method,
@ -280,7 +281,8 @@ class TestProxyLogging(unittest.TestCase):
app.access_logger = FakeLogger() app.access_logger = FakeLogger()
req = Request.blank('/v1/a/c', req = Request.blank('/v1/a/c',
environ={'REQUEST_METHOD': method}) environ={'REQUEST_METHOD': method})
app.log_request(req, 911, 4, 43, 1.01) now = 10000.0
app.log_request(req, 911, 4, 43, now, now + 1.01)
self.assertTiming('container.%s.911.timing' % exp_method, app, self.assertTiming('container.%s.911.timing' % exp_method, app,
exp_timing=1.01 * 1000) exp_timing=1.01 * 1000)
self.assertUpdateStats('container.%s.911.xfer' % exp_method, self.assertUpdateStats('container.%s.911.xfer' % exp_method,
@ -706,16 +708,13 @@ class TestProxyLogging(unittest.TestCase):
app = proxy_logging.ProxyLoggingMiddleware(FakeApp(), {}) app = proxy_logging.ProxyLoggingMiddleware(FakeApp(), {})
app.access_logger = FakeLogger() app.access_logger = FakeLogger()
req = Request.blank('/', environ={'REQUEST_METHOD': 'GET'}) req = Request.blank('/', environ={'REQUEST_METHOD': 'GET'})
with mock.patch.multiple('time', with mock.patch('time.time',
time=mock.MagicMock( mock.MagicMock(
side_effect=[10000000.0, 10000001.0]), side_effect=[10000000.0, 10000001.0])):
gmtime=mock.MagicMock(
side_effect=[
time.gmtime(10000001.00001)])):
resp = app(req.environ, start_response) resp = app(req.environ, start_response)
resp_body = ''.join(resp) resp_body = ''.join(resp)
log_parts = self._log_parts(app) log_parts = self._log_parts(app)
self.assertEquals(len(log_parts), 18) self.assertEquals(len(log_parts), 20)
self.assertEquals(log_parts[0], '-') self.assertEquals(log_parts[0], '-')
self.assertEquals(log_parts[1], '-') self.assertEquals(log_parts[1], '-')
self.assertEquals(log_parts[2], '26/Apr/1970/17/46/41') self.assertEquals(log_parts[2], '26/Apr/1970/17/46/41')
@ -735,6 +734,8 @@ class TestProxyLogging(unittest.TestCase):
self.assertEquals(log_parts[15], '1.0000') self.assertEquals(log_parts[15], '1.0000')
self.assertEquals(log_parts[16], '-') self.assertEquals(log_parts[16], '-')
self.assertEquals(log_parts[17], '-') self.assertEquals(log_parts[17], '-')
self.assertEquals(log_parts[18], '10000000.000000000')
self.assertEquals(log_parts[19], '10000001.000000000')
if __name__ == '__main__': if __name__ == '__main__':