From ad29ebe86643c60c1c5071d6edecbcbb17861fe0 Mon Sep 17 00:00:00 2001 From: niphlod Date: Sat, 17 Aug 2013 14:02:46 +0200 Subject: [PATCH] profiler now save dumps in a dir --- fcgihandler.py | 2 +- gluon/main.py | 54 +++++++++++++++++++++++++++---------------------- gluon/widget.py | 29 +++++++++++++------------- scgihandler.py | 2 +- wsgihandler.py | 2 +- 5 files changed, 48 insertions(+), 41 deletions(-) diff --git a/fcgihandler.py b/fcgihandler.py index a3d4a5df..7d5719fb 100755 --- a/fcgihandler.py +++ b/fcgihandler.py @@ -42,7 +42,7 @@ import gluon.contrib.gateways.fcgi as fcgi if LOGGING: application = gluon.main.appfactory(wsgiapp=gluon.main.wsgibase, logfilename='httpserver.log', - profilerfilename=None) + profiler_dir=None) else: application = gluon.main.wsgibase diff --git a/gluon/main.py b/gluon/main.py index 4dc3695d..62af77c7 100644 --- a/gluon/main.py +++ b/gluon/main.py @@ -26,6 +26,7 @@ import signal import socket import random import urllib2 +import string try: @@ -40,6 +41,7 @@ from thread import allocate_lock from fileutils import abspath, write_file from settings import global_settings +from utils import web2py_uuid from admin import add_path_first, create_missing_folders, create_missing_app_folders from globals import current @@ -379,7 +381,7 @@ def wsgibase(environ, responder): # ################################################## # access the requested application # ################################################## - + disabled = pjoin(request.folder, 'DISABLED') if not exists(request.folder): if app == rwthread.routes.default_application \ @@ -396,7 +398,7 @@ def wsgibase(environ, responder): % 'invalid request', web2py_error='invalid application') elif request.is_local and exists(disabled): - data = dict([item.strip() for item in line.split(':',1)] + data = dict([item.strip() for item in line.split(':',1)] for line in open(disabled) if line.strip()) if data.get('disabled','True').lower() != 'false': if 'redirect' in data: @@ -605,7 +607,7 @@ def save_password(password, port): def appfactory(wsgiapp=wsgibase, logfilename='httpserver.log', - profilerfilename='profiler.log'): + profiler_dir=None): """ generates a wsgi application that does logging and profiling and calls wsgibase @@ -616,9 +618,22 @@ def appfactory(wsgiapp=wsgibase, [, profilerfilename='profiler.log']]]) """ - if profilerfilename and exists(profilerfilename): - os.unlink(profilerfilename) - locker = allocate_lock() + + if profiler_dir: + profiler_dir = abspath(profiler_dir) + logger.warn('profiler is on. will use dir %s', profiler_dir) + if not os.path.isdir(profiler_dir): + try: + os.makedirs(profiler_dir) + except: + raise BaseException, "Can't create dir %s" % profiler_dir + filepath = pjoin(profiler_dir, 'wtest') + try: + filehandle = open( filepath, 'w' ) + filehandle.close() + os.unlink(filepath) + except IOError: + raise BaseException, "Unable to write to dir %s" % profiler_dir def app_with_logging(environ, responder): """ @@ -636,25 +651,17 @@ def appfactory(wsgiapp=wsgibase, time_in = time.time() ret = [0] - if not profilerfilename: + if not profiler_dir: ret[0] = wsgiapp(environ, responder2) else: import cProfile - import pstats - logger.warn('profiler is on. this makes web2py slower and serial') + prof = cProfile.Profile() + prof.enable() + ret[0] = wsgiapp(environ, responder2) + prof.disable() + destfile = pjoin(profiler_dir, "req_%s.prof" % web2py_uuid()) + prof.dump_stats(destfile) - locker.acquire() - cProfile.runctx('ret[0] = wsgiapp(environ, responder2)', - globals(), locals(), profilerfilename + '.tmp') - stat = pstats.Stats(profilerfilename + '.tmp') - stat.stream = cStringIO.StringIO() - stat.strip_dirs().sort_stats("time").print_stats(80) - profile_out = stat.stream.getvalue() - profile_file = open(profilerfilename, 'a') - profile_file.write('%s\n%s\n%s\n%s\n\n' % - ('=' * 60, environ['PATH_INFO'], '=' * 60, profile_out)) - profile_file.close() - locker.release() try: line = '%s, %s, %s, %s, %s, %s, %f\n' % ( environ['REMOTE_ADDR'], @@ -677,7 +684,6 @@ def appfactory(wsgiapp=wsgibase, return app_with_logging - class HttpServer(object): """ the web2py web server (Rocket) @@ -690,7 +696,7 @@ class HttpServer(object): password='', pid_filename='httpserver.pid', log_filename='httpserver.log', - profiler_filename=None, + profiler_dir=None, ssl_certificate=None, ssl_private_key=None, ssl_ca_certificate=None, @@ -755,7 +761,7 @@ class HttpServer(object): logger.info('SSL is ON') app_info = {'wsgi_app': appfactory(wsgibase, log_filename, - profiler_filename)} + profiler_dir)} self.server = rocket.Rocket(interfaces or tuple(sock_list), method='wsgi', diff --git a/gluon/widget.py b/gluon/widget.py index 2ea47e77..1ba8224a 100644 --- a/gluon/widget.py +++ b/gluon/widget.py @@ -66,9 +66,9 @@ def run_system_tests(options): coverage_config = os.environ.get( "COVERAGE_PROCESS_START", os.path.join('gluon', 'tests', 'coverage.ini')) - - call_args = ['coverage', 'run', '--rcfile=%s' % - coverage_config, + + call_args = ['coverage', 'run', '--rcfile=%s' % + coverage_config, '-m', 'unittest', '-v', 'gluon.tests'] except: sys.stderr.write('Coverage was not installed, skipping\n') @@ -159,7 +159,7 @@ def presentation(root): # Prevent garbage collection of img pnl.image = img - def add_label(text='Change Me', font_size=12, + def add_label(text='Change Me', font_size=12, foreground='#195866', height=1): return Tkinter.Label( master=canvas, @@ -339,7 +339,7 @@ class web2pyDialog(object): if start: #the widget takes care of starting the scheduler if self.options.scheduler and self.options.with_scheduler: - apps = [app.strip() for app + apps = [app.strip() for app in self.options.scheduler.split(',') if app in available_apps] for app in apps: @@ -431,7 +431,7 @@ class web2pyDialog(object): url = self.url + arq self.pagesmenu.add_command( label=url, command=lambda u=url: start_browser(u)) - + def quit(self, justHide=False): """ Finish the program execution """ if justHide: @@ -484,7 +484,7 @@ class web2pyDialog(object): return self.error('invalid port number') # Check for non default value for ssl inputs - if (len(self.options.ssl_certificate) > 0 or + if (len(self.options.ssl_certificate) > 0 or len(self.options.ssl_private_key) > 0): proto = 'https' else: @@ -503,7 +503,7 @@ class web2pyDialog(object): password, pid_filename=options.pid_filename, log_filename=options.log_filename, - profiler_filename=options.profiler_filename, + profiler_dir=options.profiler_dir, ssl_certificate=options.ssl_certificate, ssl_private_key=options.ssl_private_key, ssl_ca_certificate=options.ssl_ca_certificate, @@ -865,9 +865,9 @@ def console(): parser.add_option('-F', '--profiler', - dest='profiler_filename', + dest='profiler_dir', default=None, - help='profiler filename') + help='profiler dir') parser.add_option('-t', '--taskbar', @@ -914,7 +914,7 @@ def console(): dest='run_system_tests', default=False, help=msg) - + msg = ('adds coverage reporting (needs --run_system_tests), ' 'python 2.7 and the coverage module installed. ' 'You can alter the default path setting the environmental ' @@ -925,7 +925,7 @@ def console(): dest='with_coverage', default=False, help=msg) - + if '-A' in sys.argv: k = sys.argv.index('-A') elif '--args' in sys.argv: @@ -1117,7 +1117,8 @@ def start(cron=True): if not options.args is None: sys.argv[:] = options.args run(options.shell, plain=options.plain, bpython=options.bpython, - import_models=options.import_models, startfile=options.run, cronjob=options.cronjob) + import_models=options.import_models, startfile=options.run, + cronjob=options.cronjob) return # ## if -C start cron run (extcron) and exit @@ -1267,7 +1268,7 @@ end tell password=options.password, pid_filename=options.pid_filename, log_filename=options.log_filename, - profiler_filename=options.profiler_filename, + profiler_dir=options.profiler_dir, ssl_certificate=options.ssl_certificate, ssl_private_key=options.ssl_private_key, ssl_ca_certificate=options.ssl_ca_certificate, diff --git a/scgihandler.py b/scgihandler.py index c7f51cfd..2c3fb03c 100755 --- a/scgihandler.py +++ b/scgihandler.py @@ -61,7 +61,7 @@ wsgiapp = WSGIFilterMiddleware(gluon.main.wsgibase, GzipWSGIFilter) if LOGGING: application = gluon.main.appfactory(wsgiapp=wsgiapp, logfilename='httpserver.log', - profilerfilename=None) + profiler_dir=None) else: application = wsgiapp diff --git a/wsgihandler.py b/wsgihandler.py index e98c45e4..eadf2ab1 100644 --- a/wsgihandler.py +++ b/wsgihandler.py @@ -35,7 +35,7 @@ import gluon.main if LOGGING: application = gluon.main.appfactory(wsgiapp=gluon.main.wsgibase, logfilename='httpserver.log', - profilerfilename=None) + profiler_dir=None) else: application = gluon.main.wsgibase