diff --git a/eggs.ini b/eggs.ini index 6c369fa992f..5ae3fdbfc30 100644 --- a/eggs.ini +++ b/eggs.ini @@ -23,6 +23,7 @@ pysqlite = 2.3.5 python_lzo = 1.08 threadframe = 0.2 guppy = 0.1.8 +PSI = 0.3b1.1 [eggs:noplatform] amqplib = 0.6.1 @@ -86,6 +87,7 @@ NoseHTML = http://dist.g2.bx.psu.edu/nosehtml-0.2.tar.bz2 Paste = http://cheeseshop.python.org/packages/source/P/Paste/Paste-1.5.1.tar.gz PasteDeploy = http://cheeseshop.python.org/packages/source/P/PasteDeploy/PasteDeploy-1.3.1.tar.gz PasteScript = http://cheeseshop.python.org/packages/source/P/PasteScript/PasteScript-1.3.6.tar.gz +PSI = http://pypi.python.org/packages/source/P/PSI/PSI-0.3b1.1.tar.gz Routes = http://pypi.python.org/packages/source/R/Routes/Routes-1.6.3.tar.gz simplejson = http://cheeseshop.python.org/packages/source/s/simplejson/simplejson-1.5.tar.gz SQLAlchemy = http://pypi.python.org/packages/source/S/SQLAlchemy/SQLAlchemy-0.4.7p1.tar.gz diff --git a/lib/galaxy/web/buildapp.py b/lib/galaxy/web/buildapp.py index 347cd31d34d..0a23b25f913 100644 --- a/lib/galaxy/web/buildapp.py +++ b/lib/galaxy/web/buildapp.py @@ -64,7 +64,12 @@ def app_factory( global_conf, **kwargs ): sys.exit( 1 ) atexit.register( app.shutdown ) # Create the universe WSGI application - webapp = galaxy.web.framework.WebApplication( app, session_cookie='galaxysession' ) + if app.config.log_memory_usage: + from galaxy.web.framework.memdebug import MemoryLoggingWebApplication + webapp = MemoryLoggingWebApplication( app, session_cookie='galaxysession' ) + else: + webapp = galaxy.web.framework.WebApplication( app, session_cookie='galaxysession' ) + # Find controllers add_controllers( webapp, app ) # Force /history to go to /root/history -- needed since the tests assume this webapp.add_route( '/history', controller='root', action='history' ) diff --git a/lib/galaxy/web/framework/base.py b/lib/galaxy/web/framework/base.py index 63fd077608f..76b2cbbf3cd 100644 --- a/lib/galaxy/web/framework/base.py +++ b/lib/galaxy/web/framework/base.py @@ -122,7 +122,7 @@ class WebApplication( object ): # Special key for AJAX debugging, remove to avoid confusing methods kwargs.pop( '_', None ) try: - body = method( trans, **kwargs ) + body = self.call_body_method( method, trans, kwargs ) except Exception, e: body = self.handle_controller_exception( e, trans, **kwargs ) if not body: @@ -140,6 +140,9 @@ class WebApplication( object ): trans.response.wsgi_headeritems() ) return self.make_body_iterable( trans, body ) + def call_body_method( self, method, trans, kwargs ): + return method( trans, **kwargs ) + def make_body_iterable( self, trans, body ): if isinstance( body, ( types.GeneratorType, list, tuple ) ): # Recursively stream the iterable diff --git a/lib/galaxy/web/framework/memdebug.py b/lib/galaxy/web/framework/memdebug.py new file mode 100644 index 00000000000..8f41bcf10f5 --- /dev/null +++ b/lib/galaxy/web/framework/memdebug.py @@ -0,0 +1,26 @@ +""" +Implementation of WebApplication that logs memory usage before and after +calling each controller method. +""" + +import pkg_resources +pkg_resources.require( "PSI" ) +import psi.process + +import os +import logging + +from galaxy.web.framework import WebApplication + +log = logging.getLogger( __name__ ) +pid = os.getpid() + +class MemoryLoggingWebApplication( WebApplication ): + def call_body_method( self, method, trans, kwargs ): + cls = method.im_class + process = psi.process.Process( pid ) + log.debug( "before controller=%s.%s method=%s rss=%d vsz=%d", cls.__module__, cls.__name__, method.__name__, process.rss, process.vsz ) + rval = method( trans, **kwargs ) + process = psi.process.Process( pid ) + log.debug( "after controller=%s.%s method=%s rss=%d vsz=%d", cls.__module__, cls.__name__, method.__name__, process.rss, process.vsz ) + return rval \ No newline at end of file