[Checkins] SVN: z3ext.profiler/trunk/ added portlet profiler

Nikolay Kim fafhrd91 at gmail.com
Mon Jul 13 05:35:34 EDT 2009


Log message for revision 101843:
  added portlet profiler

Changed:
  U   z3ext.profiler/trunk/CHANGES.txt
  U   z3ext.profiler/trunk/setup.py
  A   z3ext.profiler/trunk/src/z3ext/profiler/configlet.py
  U   z3ext.profiler/trunk/src/z3ext/profiler/configure.zcml
  A   z3ext.profiler/trunk/src/z3ext/profiler/edit.pt
  A   z3ext.profiler/trunk/src/z3ext/profiler/interfaces.py
  A   z3ext.profiler/trunk/src/z3ext/profiler/pagelet.py
  A   z3ext.profiler/trunk/src/z3ext/profiler/portlet.py
  A   z3ext.profiler/trunk/src/z3ext/profiler/stats.py

-=-
Modified: z3ext.profiler/trunk/CHANGES.txt
===================================================================
--- z3ext.profiler/trunk/CHANGES.txt	2009-07-13 09:33:05 UTC (rev 101842)
+++ z3ext.profiler/trunk/CHANGES.txt	2009-07-13 09:35:33 UTC (rev 101843)
@@ -2,6 +2,15 @@
 CHANGES
 =======
 
+
+2.0.0 (Unreleased)
+------------------
+
+- Use configlet for profiler
+
+- Added profiler for pagelets, portlets, pageelements
+
+
 1.1.0 (2008-03-28)
 ------------------
 

Modified: z3ext.profiler/trunk/setup.py
===================================================================
--- z3ext.profiler/trunk/setup.py	2009-07-13 09:33:05 UTC (rev 101842)
+++ z3ext.profiler/trunk/setup.py	2009-07-13 09:35:33 UTC (rev 101843)
@@ -21,7 +21,7 @@
 def read(*rnames):
     return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
 
-version='1.2.0dev'
+version='2.0.0dev'
 
 
 setup(name = 'z3ext.profiler',
@@ -51,6 +51,12 @@
 			  'zope.app.wsgi',
                           'zope.app.folder',
 			  'zope.app.publisher',
+			  'z3ext.cache',
+                          'z3ext.layout',
+                          'z3ext.portlet',
+                          'z3ext.pageelement',
+                          'z3ext.controlpanel',
+                          'z3ext.wizard',
                           ],
       include_package_data = True,
       zip_safe = False

Added: z3ext.profiler/trunk/src/z3ext/profiler/configlet.py
===================================================================
--- z3ext.profiler/trunk/src/z3ext/profiler/configlet.py	                        (rev 0)
+++ z3ext.profiler/trunk/src/z3ext/profiler/configlet.py	2009-07-13 09:35:33 UTC (rev 101843)
@@ -0,0 +1,28 @@
+##############################################################################
+#
+# Copyright (c) 2009 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" 
+
+$Id:  2007-12-12 12:27:02Z fafhrd $
+"""
+from zope.app.component.hooks import getSite
+from zope.traversing.interfaces import IContainmentRoot
+
+
+class ProfilerConfiglet(object):
+
+    def isAvailable(self):
+        if not IContainmentRoot.providedBy(getSite()):
+            return False
+
+        return super(ProfilerConfiglet, self).isAvailable()

Modified: z3ext.profiler/trunk/src/z3ext/profiler/configure.zcml
===================================================================
--- z3ext.profiler/trunk/src/z3ext/profiler/configure.zcml	2009-07-13 09:33:05 UTC (rev 101842)
+++ z3ext.profiler/trunk/src/z3ext/profiler/configure.zcml	2009-07-13 09:35:33 UTC (rev 101843)
@@ -1,14 +1,31 @@
 <configure
    xmlns="http://namespaces.zope.org/zope"
+   xmlns:z3ext="http://namespaces.zope.org/z3ext"
    xmlns:browser="http://namespaces.zope.org/browser">
 
-  <browser:page
-     name="z3ext.profiler"
-     for="zope.app.folder.interfaces.IRootFolder"
-     template="view.pt"
-     class=".view.Profiler"
+  <z3ext:configlet
      title="Profiler"
-     menu="zmi_actions"
+     name="system.profiler"
+     schema=".interfaces.IProfilerConfiglet"
+     class=".configlet.ProfilerConfiglet"
      permission="zope.ManageServices" />
 
+  <!-- browser view -->
+  <z3ext:pagelet
+     name="index.html"
+     for=".interfaces.IProfilerConfiglet"
+     class="z3ext.controlpanel.browser.wizard.ConfigletEditWizard"
+     permission="z3ext.Configure" />
+
+  <z3ext:pagelet
+     name="portlet"
+     type="wizard.step"
+     title="Portlet"
+     label="Portlet Profiler"
+     for=".interfaces.IProfilerConfiglet
+	  z3ext.controlpanel.browser.interfaces.IConfigletEditWizard"
+     template="edit.pt"
+     class=".portlet.PortletProfiler"
+     weight="200" />
+
 </configure>

Added: z3ext.profiler/trunk/src/z3ext/profiler/edit.pt
===================================================================
--- z3ext.profiler/trunk/src/z3ext/profiler/edit.pt	                        (rev 0)
+++ z3ext.profiler/trunk/src/z3ext/profiler/edit.pt	2009-07-13 09:35:33 UTC (rev 101843)
@@ -0,0 +1,80 @@
+<tal:block content="structure view/@@pagelet/form" />
+
+<div tal:condition="stats" tal:define="stats view/listStats">
+  <h2>Statistics</h2>
+  <br />
+
+  <div class="z-table-container">
+    <table class="z-table">
+      <tbody>
+	<tr class="even">
+	  <th>Select request:</th>
+	  <td><select name="stats" tal:define="default request/stats|nothing">
+	      <option tal:repeat="stat stats"
+		      tal:attributes="value stat/uri;
+				      selected python:stat['uri'] == default"
+		      tal:content="string:${stat/uri} (${stat/calls} calls)"></option>
+	    </select>
+	  </td>
+	</tr>
+	<tr class="odd">
+	  <th>Number of records:</th>
+	  <td><input type="text" name="limit:int" 
+		     tal:attributes="value request/limit|string:500" />
+	  </td>
+	</tr>
+	<tr class="even">
+	  <th>Mode:</th>
+	  <td>
+	    <select name="mode"
+		    tal:define="default request/mode|string:stats">
+	      <option tal:repeat="item python:('stats', 'callees', 'callers')"
+		      tal:content="item" 
+		      tal:attributes="value item; selected python:item == default">
+	      </option>
+	    </select>
+	  </td>
+	</tr>
+	<tr class="odd">
+	  <th>Sort on:</th>
+	  <td><select name="sorton"
+		      tal:define="default request/sorton|string:time">
+	      <option tal:repeat="item python:(
+				  ('time', 'internal time'),
+				  ('cumulative', 'cumulative time'),
+				  ('calls', 'call count'),
+				  ('pcalls', 'primitive call count'),
+				  ('name', 'function name'),
+				  ('file', 'file name'),
+				  ('module', 'module name'),
+				  ('line', 'line number'),
+				  ('nfl', 'name/file/line'),
+				  ('stdname', 'standard name'))"
+		      tal:attributes="value python:item[0]; 
+				      selected python:item[0] == default"
+		      tal:content="python:item[1]"></option>
+	    </select>
+	  </td>
+	</tr>
+	<tr class="even">
+	  <th>Stdname regexp:</th>
+	  <td><input name="stdnameRe" 
+		     tal:attributes="value request/stdnameRe|nothing" /></td>
+	</tr>
+	<tr class="odd">
+	  <th>Strip dirs:</th>
+	  <td><input type="checkbox" name="stripdirs:bool"
+		     tal:attributes="checked request/stripdirs|nothing" />
+	  </td>
+	</tr>
+      </tbody>
+    </table>
+  </div>
+  
+  <br />
+  <input class="z-form-button" type="submit" name="view_stats" value="Update"/>
+  
+  <br />
+  <br />
+  <pre tal:content="view/viewStats"></pre>
+</div>

Added: z3ext.profiler/trunk/src/z3ext/profiler/interfaces.py
===================================================================
--- z3ext.profiler/trunk/src/z3ext/profiler/interfaces.py	                        (rev 0)
+++ z3ext.profiler/trunk/src/z3ext/profiler/interfaces.py	2009-07-13 09:35:33 UTC (rev 101843)
@@ -0,0 +1,37 @@
+##############################################################################
+#
+# Copyright (c) 2009 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" 
+
+$Id:  2007-12-12 12:27:02Z fafhrd $
+"""
+from zope import interface, schema
+from z3ext.widget.list import SimpleList
+
+
+class IPortletProfiler(interface.Interface):
+    """ portlet profiler """
+
+    pnumber = schema.Int(
+        title = u'Number of calls',
+        default = 1,
+        required = True)
+
+    portlets = SimpleList(
+        title = u'Portlet ids',
+        default = [],
+        required = True)
+
+
+class IProfilerConfiglet(IPortletProfiler):
+    """ profiler """

Added: z3ext.profiler/trunk/src/z3ext/profiler/pagelet.py
===================================================================
--- z3ext.profiler/trunk/src/z3ext/profiler/pagelet.py	                        (rev 0)
+++ z3ext.profiler/trunk/src/z3ext/profiler/pagelet.py	2009-07-13 09:35:33 UTC (rev 101843)
@@ -0,0 +1,19 @@
+##############################################################################
+#
+# Copyright (c) 2009 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" 
+
+$Id:  2007-12-12 12:27:02Z fafhrd $
+"""
+
+pageletNames = []

Added: z3ext.profiler/trunk/src/z3ext/profiler/portlet.py
===================================================================
--- z3ext.profiler/trunk/src/z3ext/profiler/portlet.py	                        (rev 0)
+++ z3ext.profiler/trunk/src/z3ext/profiler/portlet.py	2009-07-13 09:35:33 UTC (rev 101843)
@@ -0,0 +1,108 @@
+##############################################################################
+#
+# Copyright (c) 2009 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" 
+
+$Id:  2007-12-12 12:27:02Z fafhrd $
+"""
+import time, profile
+from zope.component import queryMultiAdapter
+from z3ext.layoutform.interfaces import ISaveAction
+from z3ext.layoutform import button, Fields, PageletEditForm
+from z3ext.wizard.step import WizardStepForm
+from z3ext.portlet.manager import PortletManagerBase
+from z3ext.portlet.interfaces import IPortletManagerView
+from z3ext.statusmessage.interfaces import IStatusMessage
+from z3ext.cache import configlet as cacheconfiglet
+
+from DMstats import Stats
+from stats import ProfilerStatistics
+from interfaces import IPortletProfiler
+
+
+class PortletProfiler(WizardStepForm, PageletEditForm, ProfilerStatistics):
+
+    fields = Fields(IPortletProfiler)
+
+    buttons = PageletEditForm.buttons.copy()
+    handlers = PageletEditForm.handlers.copy()
+
+    def getStats(self):
+        global _stats
+        return _stats
+
+    @button.buttonAndHandler(u'Run Profiler')
+    def handleProfiler(self, action):
+        configlet = self.getContent()
+
+        installProfiler(configlet.pnumber, configlet.portlets)
+        IStatusMessage(self.request).add(u'Profiler has started.')
+
+
+_calls = 1
+_stats = {}
+_portlets = []
+
+originalMethod = PortletManagerBase.render
+
+
+def renderPortletManager(self):
+    if not self.portlets or not self.isAvailable():
+        return u''
+
+    view = queryMultiAdapter((self, self.request), IPortletManagerView)
+    if view is not None:
+        return view.updateAndRender()
+
+    portlets = []
+
+    for portlet in self.portlets:
+        if portlet.__name__ in _portlets:
+            uri = 'portlet: %s'%portlet.__name__
+            prof = profile.Profile(time.time)
+
+            cache = cacheconfiglet.cache
+            cacheconfiglet.cache = None
+
+            response = prof.runcall(portlet.updateAndRender)
+
+            cacheconfiglet.cache = cache
+
+            if _stats.has_key(uri):
+                _stats[uri][0].add(prof)
+                _stats[uri][1] = _stats[uri][1] + 1
+            else:
+                _stats[uri] = ([Stats(prof), 1])
+
+            global _calls
+            if _calls > 0:
+                _calls = _calls - 1
+
+            if _calls <= 0:
+                PortletManagerBase.render = originalMethod
+
+            portlets.append(response)
+        else:
+            portlets.append(portlet.updateAndRender())
+
+    return u'\n'.join(portlets)
+
+
+def installProfiler(calls, portlets):
+    global _calls, _stats, _portlets
+
+    _calls = calls
+    _stats = {}
+    _portlets = tuple(portlets)
+
+    PortletManagerBase.render = renderPortletManager

Added: z3ext.profiler/trunk/src/z3ext/profiler/stats.py
===================================================================
--- z3ext.profiler/trunk/src/z3ext/profiler/stats.py	                        (rev 0)
+++ z3ext.profiler/trunk/src/z3ext/profiler/stats.py	2009-07-13 09:35:33 UTC (rev 101843)
@@ -0,0 +1,76 @@
+##############################################################################
+#
+# Copyright (c) 2009 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" 
+
+$Id:  2007-12-12 12:27:02Z fafhrd $
+"""
+from cStringIO import StringIO
+
+
+class ProfilerStatistics(object):
+
+    def getStats(self):
+        raise NotImplemented()
+
+    def listStats(self):
+        stats = []
+        for uri, info in self.getStats().items():
+            stats.append({'uri': uri, 'calls': info[1]})
+
+        return stats
+
+    def viewStats(self):
+        stats = self.getStats()
+        request = self.request
+
+        if not stats:
+            return u''
+
+        uri = request.get('stats', None)
+
+        info = stats.get(uri)
+        if not info:
+            info = stats.items()[0][1]
+
+        stats = info[0]
+
+        output = StringIO()
+
+        stripdirs = request.get('stripdirs', False)
+        if stripdirs:
+            stats.strip_dirs()
+
+        sorton = request.get('sorton', 'time')
+        stats.sort_stats(sorton)
+
+        mode = request.get('mode', 'stats')
+        stdnameRe = request.get('stdnameRe', '')
+        limit = int(request.get('limit', 500))
+
+        if stdnameRe:
+            stats.setOutputFile(output)
+            getattr(stats, 'show%s' % mode.capitalize())(str(stdnameRe), limit)
+            res = output.getvalue()
+            if not res: 
+                res = 'No matching functions'
+            return res
+        else:
+            stats.stream = output
+
+            try:
+                getattr(stats, 'print_%s'%mode)(limit)
+            finally:
+                pass
+
+            return output.getvalue()



More information about the Checkins mailing list