def _profiler(req): """ This handler wrap the default handler with a profiler. Profiling data is written into CFG_TMPDIR/invenio-profile-stats-datetime.raw, and is displayed at the bottom of the webpage. To use add profile=1 to your url. To change sorting algorithm you can provide profile=algorithm_name. You can add more than one profile requirement like ?profile=time&profile=cumulative. The list of available algorithm is displayed at the end of the profile. """ args = {} if req.args: args = cgi.parse_qs(req.args) if 'profile' in args: if not isUserSuperAdmin(collect_user_info(req)): return _handler(req) if 'memory' in args['profile']: gc.set_debug(gc.DEBUG_LEAK) ret = _handler(req) req.write("\n<pre>%s</pre>" % gc.garbage) gc.collect() req.write("\n<pre>%s</pre>" % gc.garbage) gc.set_debug(0) return ret from cStringIO import StringIO try: import pstats except ImportError: ret = _handler(req) req.write("<pre>%s</pre>" % "The Python Profiler is not installed!") return ret import datetime date = datetime.datetime.now().strftime('%Y%m%d%H%M%S') filename = '%s/invenio-profile-stats-%s.raw' % (CFG_TMPDIR, date) existing_sorts = pstats.Stats.sort_arg_dict_default.keys() required_sorts = [] profile_dump = [] for sort in args['profile']: if sort not in existing_sorts: sort = 'cumulative' if sort not in required_sorts: required_sorts.append(sort) if sys.hexversion < 0x02050000: import hotshot import hotshot.stats pr = hotshot.Profile(filename) ret = pr.runcall(_handler, req) for sort_type in required_sorts: tmp_out = sys.stdout sys.stdout = StringIO() hotshot.stats.load(filename).strip_dirs().sort_stats(sort_type).print_stats() # pylint: disable=E1103 # This is a hack. sys.stdout was replaced by a StringIO. profile_dump.append(sys.stdout.getvalue()) # pylint: enable=E1103 sys.stdout = tmp_out else: import cProfile pr = cProfile.Profile() ret = pr.runcall(_handler, req) pr.dump_stats(filename) for sort_type in required_sorts: strstream = StringIO() pstats.Stats(filename, stream=strstream).strip_dirs().sort_stats(sort_type).print_stats() profile_dump.append(strstream.getvalue()) profile_dump = '\n'.join(profile_dump) profile_dump += '\nYou can use profile=%s or profile=memory' % existing_sorts req.write("\n<pre>%s</pre>" % profile_dump) return ret elif 'debug' in args and args['debug']: #remote_debugger.start(["3"]) # example starting debugger on demand if remote_debugger: debug_starter = remote_debugger.get_debugger(args['debug']) if debug_starter: try: debug_starter() except Exception, msg: # TODO - should register_exception? raise Exception('Cannot start the debugger %s, please read instructions inside remote_debugger module. %s' % (debug_starter.__name__, msg)) else: raise Exception('Debugging requested, but no debugger registered: "%s"' % args['debug']) return _handler(req)
def _profiler(req): """ This handler wrap the default handler with a profiler. Profiling data is written into CFG_TMPDIR/invenio-profile-stats-datetime.raw, and is displayed at the bottom of the webpage. To use add profile=1 to your url. To change sorting algorithm you can provide profile=algorithm_name. You can add more than one profile requirement like ?profile=time&profile=cumulative. The list of available algorithm is displayed at the end of the profile. """ args = {} if req.args: args = cgi.parse_qs(req.args) user_info = collect_user_info(req) # Permissions to run the profiler? if acc_authorize_action(user_info, 'profiling')[0]: return _handler(req) if user_info.get('enable_profiling') and 'profile' not in args: args['profile'] = 'cumulative' # Profiler enabled? if 'profile' in args: if 'memory' in args.get('profile', []): gc.set_debug(gc.DEBUG_LEAK) ret = _handler(req) req.write("\n<pre>%s</pre>" % gc.garbage) gc.collect() req.write("\n<pre>%s</pre>" % gc.garbage) gc.set_debug(0) return ret from cStringIO import StringIO try: import pstats except ImportError: ret = _handler(req) req.write("<pre>%s</pre>" % "The Python Profiler is not installed!") return ret import datetime date = datetime.datetime.now().strftime('%Y%m%d%H%M%S') filename = '%s/invenio-profile-stats-%s.raw' % (CFG_TMPDIR, date) existing_sorts = pstats.Stats.sort_arg_dict_default.keys() required_sorts = [] profile_dump = [] for sort in args['profile']: if sort not in existing_sorts: sort = 'cumulative' if sort not in required_sorts: required_sorts.append(sort) if sys.hexversion < 0x02050000: import hotshot import hotshot.stats pr = hotshot.Profile(filename) ret = pr.runcall(_handler, req) for sort_type in required_sorts: tmp_out = sys.stdout sys.stdout = StringIO() hotshot.stats.load(filename).strip_dirs().sort_stats( sort_type).print_stats() # pylint: disable=E1103 # This is a hack. sys.stdout was replaced by a StringIO. profile_dump.append(sys.stdout.getvalue()) # pylint: enable=E1103 sys.stdout = tmp_out else: import cProfile pr = cProfile.Profile() ret = pr.runcall(_handler, req) for sort_type in required_sorts: strstream = StringIO() pstats.Stats(pr, stream=strstream).strip_dirs().sort_stats( sort_type).print_stats() profile_dump.append(strstream.getvalue()) profile_dump = '\n'.join(profile_dump) profile_dump += '\nYou can use profile=%s or profile=memory' % existing_sorts if req.content_type == 'text/html': req.write("\n<pre>%s</pre>" % profile_dump) return ret elif 'debug' in args and args['debug']: #remote_debugger.start(["3"]) # example starting debugger on demand if remote_debugger: debug_starter = remote_debugger.get_debugger(args['debug']) if debug_starter: try: debug_starter() except Exception, msg: # TODO - should register_exception? raise Exception( 'Cannot start the debugger %s, please read instructions inside remote_debugger module. %s' % (debug_starter.__name__, msg)) else: raise Exception( 'Debugging requested, but no debugger registered: "%s"' % args['debug']) return _handler(req)