Created
February 4, 2014 13:41
-
-
Save zerodeux/8803753 to your computer and use it in GitHub Desktop.
WSGI basic profiling middleware based on POSIX getrusage (simple mods from Gawel's)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
__doc__ = """ | |
Profiling middleware. Log wallclock, utime, stime and idle time. | |
Copy the file in your source tree and wrap your application with the RUsage | |
middleware:: | |
from wsgi_profile import RUsage | |
application = WSGIAppilcation() | |
application = RUsage(application) | |
You can also use a paste config file:: | |
[pipeline:main] | |
pipeline = profile yourapp | |
[filter:profile] | |
paste.filter_factory = wsgi_profile:rusage | |
[app:yourapp] | |
# [app:main] | |
""" | |
import resource | |
import logging | |
import time | |
import os | |
import ldap_profile | |
log = logging.getLogger(__name__) | |
class Stats(object): | |
stats_keys = ['ru_utime', 'ru_stime'] | |
fmt = ( | |
'%(path)-40s - time: %(time)6.3f - ' | |
'stime: %(ru_stime)6.3f - utime: %(ru_utime)6.3f - idle: %(idle)6.3f ' | |
) | |
def __init__(self, environ): | |
self.iterator = None | |
self.path = ( | |
'%(REQUEST_METHOD)s %(PATH_INFO)s?%(QUERY_STRING)s') % environ | |
self.time = time.time() | |
self.bstats = resource.getrusage(resource.RUSAGE_SELF) | |
def log_stats(self): | |
estats = resource.getrusage(resource.RUSAGE_SELF) | |
stats = {'path': self.path} | |
for k in self.stats_keys: | |
stats[k] = getattr(estats, k) - getattr(self.bstats, k) | |
stats['time'] = time.time() - self.time | |
stats['idle'] = stats['time'] - (stats['ru_utime'] + stats['ru_stime']) | |
log.info(self.fmt, stats) | |
def __iter__(self): | |
return self | |
def next(self): | |
try: | |
return self.iterator.next() | |
except StopIteration: | |
self.log_stats() | |
raise StopIteration() | |
__next__ = next | |
class RUsage(object): | |
def __init__(self, app): | |
self.app = app | |
def __call__(self, environ, start_response): | |
_, ext = os.path.splitext(environ['PATH_INFO']) | |
if ext in ('.js', '.css', '.png', '.jpg', '.gif'): | |
return self.app(environ, start_response) | |
stats = Stats(environ) | |
iterator = self.app(environ, start_response) | |
if isinstance(iterator, list): | |
stats.log_stats() | |
return iterator | |
else: | |
stats.iterator = iterator | |
return iter(stats) | |
def rusage(*args, **kwargs): | |
"""Middleware factory""" | |
return RUsage |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment