[Zope-Checkins] SVN: Zope/trunk/src/Products/ZCatalog/ Actually expose the query plan TTW
Hanno Schlichting
hannosch at hannosch.eu
Mon Aug 2 16:14:54 EDT 2010
Log message for revision 115386:
Actually expose the query plan TTW
Changed:
U Zope/trunk/src/Products/ZCatalog/ZCatalog.py
U Zope/trunk/src/Products/ZCatalog/__init__.py
U Zope/trunk/src/Products/ZCatalog/dtml/catalogPlan.dtml
A Zope/trunk/src/Products/ZCatalog/dtml/catalogReport.dtml
U Zope/trunk/src/Products/ZCatalog/plan.py
U Zope/trunk/src/Products/ZCatalog/tests/test_plan.py
-=-
Modified: Zope/trunk/src/Products/ZCatalog/ZCatalog.py
===================================================================
--- Zope/trunk/src/Products/ZCatalog/ZCatalog.py 2010-08-02 19:23:40 UTC (rev 115385)
+++ Zope/trunk/src/Products/ZCatalog/ZCatalog.py 2010-08-02 20:14:54 UTC (rev 115386)
@@ -48,6 +48,7 @@
from Products.ZCatalog.interfaces import IZCatalog
from Products.ZCatalog.ProgressHandler import ZLogHandler
from Products.ZCatalog.ZCatalogIndexes import ZCatalogIndexes
+from .plan import PriorityMap
LOG = logging.getLogger('Zope.ZCatalog')
@@ -103,7 +104,8 @@
{'label': 'Metadata', 'action': 'manage_catalogSchema'},
{'label': 'Find Objects', 'action': 'manage_catalogFind'},
{'label': 'Advanced', 'action': 'manage_catalogAdvanced'},
- {'label': 'Query Report', 'action': 'manage_catalogPlan'},
+ {'label': 'Query Report', 'action': 'manage_catalogReport'},
+ {'label': 'Query Plan', 'action': 'manage_catalogPlan'},
{'label': 'Undo', 'action': 'manage_UndoForm'},
{'label': 'Security', 'action': 'manage_access'},
{'label': 'Ownership', 'action': 'manage_owner'},
@@ -127,6 +129,9 @@
'manage_catalogAdvanced')
manage_catalogAdvanced = DTMLFile('dtml/catalogAdvanced', globals())
+ security.declareProtected(manage_zcatalog_entries, 'manage_catalogReport')
+ manage_catalogReport = DTMLFile('dtml/catalogReport', globals())
+
security.declareProtected(manage_zcatalog_entries, 'manage_catalogPlan')
manage_catalogPlan = DTMLFile('dtml/catalogPlan', globals())
@@ -877,24 +882,39 @@
security.declareProtected(manage_zcatalog_entries, 'getCatalogPlan')
def getCatalogPlan(self):
- """Query time reporting and planning."""
+ """Get a string representation of a query plan"""
+ plan = PriorityMap.get_plan()
+ output = []
+ output.append('queryplan = {')
+ for querykey, details in sorted(plan.items()):
+ output.append(' %s: {' % repr(querykey))
+ for indexname, benchmark in sorted(details.items()):
+ tuplebench = repr(tuple(benchmark))
+ output.append(' %r:\n %s,' % (indexname, tuplebench))
+ output.append(' },')
+ output.append('}')
+ return '\n'.join(output)
+
+ security.declareProtected(manage_zcatalog_entries, 'getCatalogReport')
+ def getCatalogReport(self):
+ """Query time reporting."""
rval = self._catalog.getCatalogPlan().report()
rval.sort(key=operator.itemgetter('duration'), reverse=True)
return rval
security.declareProtected(manage_zcatalog_entries,
- 'manage_resetCatalogPlan')
- def manage_resetCatalogPlan(self, REQUEST=None):
- """Resets the catalog plan."""
+ 'manage_resetCatalogReport')
+ def manage_resetCatalogReport(self, REQUEST=None):
+ """Resets the catalog report."""
self._catalog.getCatalogPlan().reset()
if REQUEST is not None:
REQUEST.response.redirect(REQUEST.URL1 +
- '/manage_catalogPlan?manage_tabs_message=Plan%20cleared')
+ '/manage_catalogReport?manage_tabs_message=Report%20cleared')
security.declareProtected(manage_zcatalog_entries,
- 'manage_editCatalogPlan')
- def manage_editCatalogPlan(self, long_query_time=0.1, REQUEST=None):
+ 'manage_editCatalogReport')
+ def manage_editCatalogReport(self, long_query_time=0.1, REQUEST=None):
"""Edit the long query time."""
if not isinstance(long_query_time, float):
long_query_time = float(long_query_time)
@@ -902,7 +922,7 @@
if REQUEST is not None:
REQUEST.response.redirect(REQUEST.URL1 +
- '/manage_catalogPlan?manage_tabs_message=' +
+ '/manage_catalogReport?manage_tabs_message=' +
'Long%20query%20time%20changed')
InitializeClass(ZCatalog)
Modified: Zope/trunk/src/Products/ZCatalog/__init__.py
===================================================================
--- Zope/trunk/src/Products/ZCatalog/__init__.py 2010-08-02 19:23:40 UTC (rev 115385)
+++ Zope/trunk/src/Products/ZCatalog/__init__.py 2010-08-02 20:14:54 UTC (rev 115386)
@@ -17,6 +17,10 @@
def initialize(context):
+ # Load a default map
+ from Products.ZCatalog.plan import PriorityMap
+ PriorityMap.load_default()
+
context.registerClass(
ZCatalog.ZCatalog,
permission='Add ZCatalogs',
Modified: Zope/trunk/src/Products/ZCatalog/dtml/catalogPlan.dtml
===================================================================
--- Zope/trunk/src/Products/ZCatalog/dtml/catalogPlan.dtml 2010-08-02 19:23:40 UTC (rev 115385)
+++ Zope/trunk/src/Products/ZCatalog/dtml/catalogPlan.dtml 2010-08-02 20:14:54 UTC (rev 115386)
@@ -2,117 +2,12 @@
<dtml-var manage_tabs>
<p class="form-help">
- The <strong>query report</strong> shows catalog queries that
- perform slowly.
+ The <strong>query plan</strong> shows the actual query plan of the
+ current process.
</p>
-<table width="100%" cellspacing="0" cellpadding="2" border="0">
- <tr class="list-header" >
- <td align="left" valign="top">
- <div class="list-nav">
- Mean duration [ms]
- </div>
- </td>
- <td align="left" valign="top">
- <div class="list-nav">
- Hits
- </div>
- </td>
- <td align="left" valign="top">
- <div class="list-nav">
- Query key
- </div>
- </td>
- <td align="left" valign="top">
- <div class="list-nav">
- Recent
- </div>
- </td>
- </tr>
- <dtml-if getCatalogPlan>
- <dtml-in getCatalogPlan mapping>
- <dtml-if sequence-odd>
- <tr class="row-normal">
- <dtml-else>
- <tr class="row-hilite">
- </dtml-if>
- <td align="left" valign="top">
- <div class="list-item">
- <dtml-var expr="'%3.2f' % duration">
- </div>
- </td>
- <td align="left" valign="top">
- <div class="list-item">
- &dtml-counter;
- </div>
- </td>
- <td align="left" valign="top">
- <div class="list-item">
- &dtml-query;
- </div>
- </td>
- <td align="left" valign="top">
- <div class="list-item">
- <dtml-var expr="'%3.2f' % last['duration']">ms
- [<dtml-in expr="last['details']" sort mapping>
- &dtml-id;:
- <dtml-var expr="'%3.2f' % duration">ms /
- &dtml-length; objects,
- </dtml-in>]
- </div>
- </td>
- </tr>
- </dtml-in>
- <tr>
- <td colspan="2" align="left" valign="top">
- <p class="form-help">Resetting the catalog report will reinitialize the report log.</p>
- </td>
- <td colspan="2" align="right" valign="top">
- <form action="manage_resetCatalogPlan" method=POST>
- <div class="form-element">
- <input class="form-element" type="submit" value="Reset Report">
- </div>
- </form>
- </td>
- </tr>
- <dtml-else>
- <tr>
- <td colspan="4" >
- <div class="list-item">
- Report is empty.
- </div>
- </td>
- </tr>
- </dtml-if>
-</table>
+<textarea name="queryplan" cols="70" rows="25" readonly="readonly">
+&dtml-getCatalogPlan;
+</textarea>
-<form action="manage_editCatalogPlan" method="post">
- <table width="100%" style="padding-top:1em;" cellspacing="0" cellpadding="2" border="0">
- <tr class="section-bar">
- <td colspan="3" align="left">
- <div class="form-label">
- Settings
- </div>
- </td>
- </tr>
- <tr>
- <td align="right" valign="middle">
- <div class="list-item">
- Threshold (in seconds)
- </div>
- </td>
- <td align="left" valign="middle">
- <div class="form-element">
- <input name="long_query_time:float" value="&dtml-long_query_time;" />
- </div>
- </td>
- <td align="left" valign="middle">
- <p class="form-help">Only queries whose execution
- takes longer than the configured threshold are considered
- being slow. (Default 0.1 seconds).</p>
- </tr>
- </table>
- <input class="form-element" type="submit" value="Apply settings">
-</form>
-
<dtml-var manage_page_footer>
Copied: Zope/trunk/src/Products/ZCatalog/dtml/catalogReport.dtml (from rev 115378, Zope/trunk/src/Products/ZCatalog/dtml/catalogPlan.dtml)
===================================================================
--- Zope/trunk/src/Products/ZCatalog/dtml/catalogReport.dtml (rev 0)
+++ Zope/trunk/src/Products/ZCatalog/dtml/catalogReport.dtml 2010-08-02 20:14:54 UTC (rev 115386)
@@ -0,0 +1,118 @@
+<dtml-var manage_page_header>
+<dtml-var manage_tabs>
+
+<p class="form-help">
+ The <strong>query report</strong> shows catalog queries that
+ perform slowly.
+</p>
+
+<table width="100%" cellspacing="0" cellpadding="2" border="0">
+ <tr class="list-header" >
+ <td align="left" valign="top">
+ <div class="list-nav">
+ Mean duration [ms]
+ </div>
+ </td>
+ <td align="left" valign="top">
+ <div class="list-nav">
+ Hits
+ </div>
+ </td>
+ <td align="left" valign="top">
+ <div class="list-nav">
+ Query key
+ </div>
+ </td>
+ <td align="left" valign="top">
+ <div class="list-nav">
+ Recent
+ </div>
+ </td>
+ </tr>
+ <dtml-if getCatalogReport>
+ <dtml-in getCatalogReport mapping>
+ <dtml-if sequence-odd>
+ <tr class="row-normal">
+ <dtml-else>
+ <tr class="row-hilite">
+ </dtml-if>
+ <td align="left" valign="top">
+ <div class="list-item">
+ <dtml-var expr="'%3.2f' % duration">
+ </div>
+ </td>
+ <td align="left" valign="top">
+ <div class="list-item">
+ &dtml-counter;
+ </div>
+ </td>
+ <td align="left" valign="top">
+ <div class="list-item">
+ &dtml-query;
+ </div>
+ </td>
+ <td align="left" valign="top">
+ <div class="list-item">
+ <dtml-var expr="'%3.2f' % last['duration']">ms
+ [<dtml-in expr="last['details']" sort mapping>
+ &dtml-id;:
+ <dtml-var expr="'%3.2f' % duration">ms /
+ &dtml-length; objects,
+ </dtml-in>]
+ </div>
+ </td>
+ </tr>
+ </dtml-in>
+ <tr>
+ <td colspan="2" align="left" valign="top">
+ <p class="form-help">Resetting the catalog report will reinitialize the report log.</p>
+ </td>
+ <td colspan="2" align="right" valign="top">
+ <form action="manage_resetCatalogReport" method=POST>
+ <div class="form-element">
+ <input class="form-element" type="submit" value="Reset Report">
+ </div>
+ </form>
+ </td>
+ </tr>
+ <dtml-else>
+ <tr>
+ <td colspan="4" >
+ <div class="list-item">
+ Report is empty.
+ </div>
+ </td>
+ </tr>
+ </dtml-if>
+</table>
+
+<form action="manage_editCatalogReport" method="post">
+ <table width="100%" style="padding-top:1em;" cellspacing="0" cellpadding="2" border="0">
+ <tr class="section-bar">
+ <td colspan="3" align="left">
+ <div class="form-label">
+ Settings
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td align="right" valign="middle">
+ <div class="list-item">
+ Threshold (in seconds)
+ </div>
+ </td>
+ <td align="left" valign="middle">
+ <div class="form-element">
+ <input name="long_query_time:float" value="&dtml-long_query_time;" />
+ </div>
+ </td>
+ <td align="left" valign="middle">
+ <p class="form-help">Only queries whose execution
+ takes longer than the configured threshold are considered
+ being slow. (Default 0.1 seconds).</p>
+ </tr>
+ </table>
+ <input class="form-element" type="submit" value="Apply settings">
+</form>
+
+<dtml-var manage_page_footer>
Modified: Zope/trunk/src/Products/ZCatalog/plan.py
===================================================================
--- Zope/trunk/src/Products/ZCatalog/plan.py 2010-08-02 19:23:40 UTC (rev 115385)
+++ Zope/trunk/src/Products/ZCatalog/plan.py 2010-08-02 20:14:54 UTC (rev 115386)
@@ -42,6 +42,10 @@
value = {}
@classmethod
+ def get_plan(cls):
+ return cls.value.copy()
+
+ @classmethod
def get(cls, key):
return cls.value.get(key, None)
@@ -63,15 +67,18 @@
pmap = resolve(location)
logger.info('loaded priority %d map(s) from %s',
len(pmap), location)
+ # Convert simple benchmark tuples to namedtuples
+ new_plan = {}
+ for querykey, details in pmap.items():
+ new_plan[querykey] = {}
+ for indexname, benchmark in details.items():
+ new_plan[querykey][indexname] = Benchmark(*benchmark)
with cls.lock:
- cls.value = pmap.copy()
+ cls.value = new_plan
except ImportError:
logger.warning('could not load priority map from %s', location)
-# Load a default map
-PriorityMap.load_default()
-
class Reports(object):
"""This holds a structure of nested dicts.
Modified: Zope/trunk/src/Products/ZCatalog/tests/test_plan.py
===================================================================
--- Zope/trunk/src/Products/ZCatalog/tests/test_plan.py 2010-08-02 19:23:40 UTC (rev 115385)
+++ Zope/trunk/src/Products/ZCatalog/tests/test_plan.py 2010-08-02 20:14:54 UTC (rev 115386)
@@ -46,7 +46,7 @@
def test_ReportLength(self):
""" tests the report aggregation """
- self.zcat.manage_resetCatalogPlan()
+ self.zcat.manage_resetCatalogReport()
self.zcat.searchResults(numbers=4, sort_on='num')
self.zcat.searchResults(numbers=1, sort_on='num')
@@ -58,49 +58,49 @@
self.zcat.searchResults(num=[5, 4, 3], sort_on='num')
self.zcat.searchResults(num=(3, 4, 5), sort_on='num')
- self.assertEqual(4, len(self.zcat.getCatalogPlan()))
+ self.assertEqual(4, len(self.zcat.getCatalogReport()))
def test_ReportCounter(self):
""" tests the counter of equal queries """
- self.zcat.manage_resetCatalogPlan()
+ self.zcat.manage_resetCatalogReport()
self.zcat.searchResults(numbers=5, sort_on='num')
self.zcat.searchResults(numbers=6, sort_on='num')
self.zcat.searchResults(numbers=8, sort_on='num')
- r = self.zcat.getCatalogPlan()[0]
+ r = self.zcat.getCatalogReport()[0]
self.assertEqual(r['counter'], 3)
def test_ReportKey(self):
""" tests the query keys for uniqueness """
# query key 1
key = ('sort_on', ('big', 'True'))
- self.zcat.manage_resetCatalogPlan()
+ self.zcat.manage_resetCatalogReport()
self.zcat.searchResults(big=True, sort_on='num')
self.zcat.searchResults(big=True, sort_on='num')
- r = self.zcat.getCatalogPlan()[0]
+ r = self.zcat.getCatalogReport()[0]
self.assertEqual(r['query'], key)
self.assertEqual(r['counter'], 2)
# query key 2
key = ('sort_on', ('big', 'False'))
- self.zcat.manage_resetCatalogPlan()
+ self.zcat.manage_resetCatalogReport()
self.zcat.searchResults(big=False, sort_on='num')
- r = self.zcat.getCatalogPlan()[0]
+ r = self.zcat.getCatalogReport()[0]
self.assertEqual(r['query'], key)
self.assertEqual(r['counter'], 1)
# query key 3
key = ('sort_on', ('num', '[3, 4, 5]'))
- self.zcat.manage_resetCatalogPlan()
+ self.zcat.manage_resetCatalogReport()
self.zcat.searchResults(num=[5, 4, 3], sort_on='num')
self.zcat.searchResults(num=(3, 4, 5), sort_on='num')
- r = self.zcat.getCatalogPlan()[0]
+ r = self.zcat.getCatalogReport()[0]
self.assertEqual(r['query'], key)
self.assertEqual(r['counter'], 2)
More information about the Zope-Checkins
mailing list