import asyncio
import logging
import time
log = logging.getLogger(__name__)
@asyncio.coroutine
[docs]def logging_middleware_factory(app, handler):
@asyncio.coroutine
def middleware(request):
"""
:type request: aiohttp.web.Request
"""
start = time.time()
log_request = True
if request.path.startswith('/info'):
log_request = False
ip = request.headers.get("x-forwarded-for")
if not ip:
ip = request.transport.get_extra_info('peername')[0]
# log if desired. can not check logged here because the method
# has not been decorated yet
if log_request:
log.info("=====> New API request: method=%s, from=%s" % (request.method, ip))
request.logged = True
try:
response = (yield from handler(request))
stop = time.time()
if request.logged and log_request:
resp_code = int(response.status)
elapsed = int(((stop - start) * 1000) + 0.5)
if resp_code < 400:
msg = '=====> API request complete: code=%d, time=%dms'
app.statsd.timing(_stats_key("api.{}.complete", request.path), elapsed)
else:
msg = '=====> API request failed: code=%d, time=%dms'
app.statsd.timing(_stats_key("api.{}.failed", request.path), elapsed)
log.info(msg % (resp_code, elapsed))
return response
except:
stop = time.time()
msg = '=====> API request exception: time=%dms'
elapsed = int(((stop - start) * 1000) + 0.5)
log.info(msg % elapsed)
app.statsd.timing(_stats_key("api.{}.exception", request.path), elapsed)
raise
return middleware
def _stats_key(pattern, path):
underscores = path.replace('/', '_')
return pattern.format(underscores.strip("_"))