[Checkins] SVN: zc.z3monitor/branches/dev/ Initial version.

Jim Fulton jim at zope.com
Tue May 1 18:21:12 EDT 2007


Log message for revision 74980:
  Initial version.
  

Changed:
  A   zc.z3monitor/branches/dev/buildout.cfg
  A   zc.z3monitor/branches/dev/setup.py
  A   zc.z3monitor/branches/dev/src/
  A   zc.z3monitor/branches/dev/src/zc/
  A   zc.z3monitor/branches/dev/src/zc/__init__.py
  A   zc.z3monitor/branches/dev/src/zc/z3monitor/
  A   zc.z3monitor/branches/dev/src/zc/z3monitor/README.txt
  A   zc.z3monitor/branches/dev/src/zc/z3monitor/__init__.py
  A   zc.z3monitor/branches/dev/src/zc/z3monitor/configure.zcml
  A   zc.z3monitor/branches/dev/src/zc/z3monitor/tests.py

-=-
Added: zc.z3monitor/branches/dev/buildout.cfg
===================================================================
--- zc.z3monitor/branches/dev/buildout.cfg	2007-05-01 22:15:07 UTC (rev 74979)
+++ zc.z3monitor/branches/dev/buildout.cfg	2007-05-01 22:21:11 UTC (rev 74980)
@@ -0,0 +1,58 @@
+[buildout]
+develop = .
+parts = instance test
+
+[zope3]
+recipe = zc.recipe.zope3checkout
+url = svn://svn.zope.org/repos/main/Zope3/trunk
+
+[app]
+recipe = zc.zope3recipes:app
+eggs = zc.z3monitor
+servers = zserver
+site.zcml =
+  <include package="zope.app.zcmlfiles" />
+  <include package="zope.app.securitypolicy" />
+  <include package="zope.app.securitypolicy" file="meta.zcml" />
+  <include package="zope.app.authentication" />
+  <include package="zope.app.server" />
+  <securityPolicy
+    component="zope.app.securitypolicy.zopepolicy.ZopeSecurityPolicy" />
+  <role id="zope.Anonymous" title="Everybody"
+                 description="All users have this role implicitly" />
+  <role id="zope.Manager" title="Site Manager" />
+  <role id="zope.Member" title="Site Member" />
+  <grantAll role="zope.Manager" />
+  <unauthenticatedPrincipal
+    id="zope.anybody"
+    title="Unauthenticated User" 
+    />
+  <principal
+      id="zope.manager"
+      title="Manager"
+      login="jim"
+      password_manager="SHA1"
+      password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+      />
+  <grant
+      role="zope.Manager"
+      principal="zope.manager"
+      />
+  <include package="zc.z3monitor" />
+
+[instance]
+recipe = zc.zope3recipes:instance
+application = app
+zope.conf =
+   ${database:zconfig}
+   <product-config zc.z3monitor>
+      port 8000
+   </product-config>
+
+[database]
+recipe = zc.recipe.filestorage
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = zc.z3monitor
+extra-paths = ${zope3:location}/src


Property changes on: zc.z3monitor/branches/dev/buildout.cfg
___________________________________________________________________
Name: svn:eol-style
   + native

Added: zc.z3monitor/branches/dev/setup.py
===================================================================
--- zc.z3monitor/branches/dev/setup.py	2007-05-01 22:15:07 UTC (rev 74979)
+++ zc.z3monitor/branches/dev/setup.py	2007-05-01 22:21:11 UTC (rev 74980)
@@ -0,0 +1,18 @@
+from setuptools import setup, find_packages
+
+name = 'zc.z3monitor'
+setup(
+    name = name,
+    version = '0.1',
+    author = 'Jim Fulton',
+    author_email = 'jim at zope.com',
+    description = 'Zope 3 Monitor',
+    license = 'ZPL 2.1',
+    keywords = 'zope3',
+    
+    packages = find_packages('src'),
+    namespace_packages = ['zc'],
+    package_dir = {'': 'src'},
+    install_requires = ['setuptools', 'zc.ngi'],
+    zip_safe = False,
+    )


Property changes on: zc.z3monitor/branches/dev/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.z3monitor/branches/dev/src/zc/__init__.py
===================================================================
--- zc.z3monitor/branches/dev/src/zc/__init__.py	2007-05-01 22:15:07 UTC (rev 74979)
+++ zc.z3monitor/branches/dev/src/zc/__init__.py	2007-05-01 22:21:11 UTC (rev 74980)
@@ -0,0 +1,5 @@
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)


Property changes on: zc.z3monitor/branches/dev/src/zc/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.z3monitor/branches/dev/src/zc/z3monitor/README.txt
===================================================================
--- zc.z3monitor/branches/dev/src/zc/z3monitor/README.txt	2007-05-01 22:15:07 UTC (rev 74979)
+++ zc.z3monitor/branches/dev/src/zc/z3monitor/README.txt	2007-05-01 22:21:11 UTC (rev 74980)
@@ -0,0 +1,136 @@
+Zope 3 Monitor Server
+=====================
+
+The Zope 3 monitor server is a server that runs in a Zope 3 process
+and that provides a command-line interface to request various bits of
+information.  The server is zc.ngi based, so we can use the zc.ngi
+testing infreastructure to demonstrate it.
+
+    >>> import zc.ngi.testing
+    >>> import zc.z3monitor
+    
+    >>> connection = zc.ngi.testing.TextConnection()
+    >>> server = zc.z3monitor.Server(connection)
+    
+It accesses databases as utilities.  Let's create some test databases
+and register them as utilities.
+
+    >>> from ZODB.tests.util import DB
+    >>> main = DB()
+    >>> from zope import component
+    >>> import ZODB.interfaces
+    >>> component.provideUtility(main, ZODB.interfaces.IDatabase)
+    >>> other = DB()
+    >>> component.provideUtility(other, ZODB.interfaces.IDatabase, 'other')
+
+We also need to able activity monitoring in the databases:
+
+    >>> import ZODB.ActivityMonitor
+    >>> main.setActivityMonitor(ZODB.ActivityMonitor.ActivityMonitor())
+    >>> other.setActivityMonitor(ZODB.ActivityMonitor.ActivityMonitor())
+
+To get information about the process overall, use the monitor
+command:
+
+    >>> connection.test_input('monitor\n')
+    0 
+    VmSize:	   35284 kB 
+    VmRSS:	   28764 kB 
+    -> CLOSE
+
+The minimal output has:
+
+- The number of open database connections to the main database, which
+  is the database registered without a name.
+- The virual memory size, and
+- The resident memory size.
+
+If there are old database connections, they will be listed.  By
+default, connections are considered old if they are greater than 100
+seconds old.  If you pass a value of 0, you'll see all connections.
+Let's create a couple of connections and then call z2monitor again
+with a value of 0:
+
+    >>> conn1 = main.open()
+    >>> conn2 = main.open()
+
+    >>> connection.test_input('monitor 0\n')
+    2 
+    VmSize:	   36560 kB 
+    VmRSS:	   28704 kB 
+    0.0    (0) 
+    0.0    (0) 
+    -> CLOSE
+
+The extra lone of output gine connection debug info.
+If we set some additional input, we'll see it:
+
+    >>> conn1.setDebugInfo('/foo')
+    >>> conn2.setDebugInfo('/bar')
+
+    >>> connection.test_input('monitor 0\n')
+    2 
+    VmSize:	   13048 kB 
+    VmRSS:	   10084 kB 
+    0.0   /bar (0) 
+    0.0   /foo (0) 
+    -> CLOSE
+
+    >>> conn1.close()
+    >>> conn2.close()
+
+To get information about a database, give the dbinfo command followed
+by a database name:
+
+    >>> connection.test_input('dbinfo\n')
+    0   0   2 
+    -> CLOSE
+
+Let's open a connection and do some work:
+    
+    >>> conn = main.open()
+    >>> conn.root()['a'] = 1
+    >>> import transaction
+    >>> transaction.commit()
+    >>> conn.root()['a'] = 1
+    >>> transaction.commit()
+    >>> conn.close()
+
+    >>> connection.test_input('dbinfo\n')
+    1   2   3 
+    -> CLOSE
+
+The dbinfo command returns 3 values:
+
+- number of database loads 
+
+- number of database stores
+
+- number of connections in the last five minutes
+
+You can specify a database name.  So, to get statistics for the other
+database, we'll specify the name it was registered with:
+
+    >>> connection.test_input('dbinfo other\n')
+    0   0   0 
+    -> CLOSE
+
+You can use '-' to name the main database:
+
+    >>> connection.test_input('dbinfo -\n')
+    1   2   3 
+    -> CLOSE
+
+You can specify a number of seconds to sample. For example, to get
+data for the last 10 seconds:
+
+    >>> connection.test_input('dbinfo - 10\n')
+    1   2   3 
+    -> CLOSE
+
+.. Edge case to make sure that deltat is used:
+
+    >>> connection.test_input('dbinfo - 0\n')
+    0   0   0 
+    -> CLOSE
+    


Property changes on: zc.z3monitor/branches/dev/src/zc/z3monitor/README.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: zc.z3monitor/branches/dev/src/zc/z3monitor/__init__.py
===================================================================
--- zc.z3monitor/branches/dev/src/zc/z3monitor/__init__.py	2007-05-01 22:15:07 UTC (rev 74979)
+++ zc.z3monitor/branches/dev/src/zc/z3monitor/__init__.py	2007-05-01 22:21:11 UTC (rev 74980)
@@ -0,0 +1,148 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation 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.
+#
+##############################################################################
+"""Zope 3 Monitor Server
+
+$Id$
+"""
+
+import os, re, time, traceback
+
+import ZODB.ActivityMonitor
+import ZODB.interfaces
+
+import zope.component
+import zope.interface
+import zope.publisher.browser
+import zope.publisher.interfaces.browser
+import zope.security.proxy
+import zope.traversing.interfaces
+import zope.app.appsetup.interfaces
+import zope.app.appsetup.product
+import zope.app.publication.interfaces
+
+import zc.ngi.adapters
+
+class Server:
+
+    def __init__(self, connection):
+        connection = zc.ngi.adapters.Lines(connection)
+        self.connection = connection
+        connection.setHandler(self)
+
+    def handle_input(self, connection, data):
+        args = data.strip().split()
+        if not args:
+            return
+        command = args.pop(0)
+        try:
+            command = getattr(self, 'command_'+command)
+        except AttributeError:
+            connection.write('invalid command %r\n' % command)
+        else:
+            try:
+                command(connection, *args)
+            except Exception, v:
+
+                traceback.print_exc(100, connection)
+                print >> connection, "%s: %s\n" % (v.__class__.__name__, v)
+
+        connection.write(zc.ngi.END_OF_DATA)
+
+    def handle_close(self, connection, reason):
+        pass
+
+    def command_help(self, connection):
+        print >> connection, "Commands: help z2monitor dbinfo"
+
+    opened_time_search = re.compile('[(](\d+[.]\d*)s[)]').search
+    def command_monitor(self, connection, long=100):
+        min = float(long)
+        db = zope.component.getUtility(ZODB.interfaces.IDatabase)
+
+        result = []
+        nconnections = 0
+        for data in db.connectionDebugInfo():
+            opened = data['opened']
+            if not opened:
+                continue
+            nconnections += 1
+            age = float(self.opened_time_search(opened).group(1))
+            if age < min:
+                continue
+            result.append((age, data['info']))
+
+        result.sort()
+                
+        print >>connection, str(nconnections)
+        for status in getStatus():
+            print >>connection, status
+        for age, info in result:
+            print >>connection, age, info.encode('utf-8')
+
+    def command_dbinfo(self, connection, database='', deltat=300):
+        if database == '-':
+            database = ''
+        db = zope.component.getUtility(ZODB.interfaces.IDatabase, database)
+
+        am = db.getActivityMonitor()
+        if am is None:
+            data = -1, -1, -1
+        else:
+            now = time.time()
+            analysis = am.getActivityAnalysis(now-int(deltat), now, 1)[0]
+            data = (analysis['loads'],
+                    analysis['stores'],
+                    analysis['connections'],
+                    )
+        print >> connection, data[0], data[1], data[2]
+
+
+ at zope.component.adapter(zope.app.appsetup.interfaces.IDatabaseOpenedEvent)
+def initialize(opened_event):
+    for name, db in zope.component.getUtilitiesFor(ZODB.interfaces.IDatabase):
+        if db.getActivityMonitor() is None:
+            db.setActivityMonitor(ZODB.ActivityMonitor.ActivityMonitor())
+    
+    config = zope.app.appsetup.product.getProductConfiguration(__name__)
+    port = int(config['port'])
+    import zc.ngi.async
+    zc.ngi.async.listener(('', port), Server)
+
+ at zope.component.adapter(
+    zope.traversing.interfaces.IContainmentRoot,
+    zope.app.publication.interfaces.IBeforeTraverseEvent,
+    )
+def save_request_in_connection_info(object, event):
+    object = zope.security.proxy.getObject(object)
+    connection = getattr(object, '_p_jar', None)
+    if connection is None:
+        return
+    path = event.request.get('PATH_INFO')
+    if path is not None:
+        connection.setDebugInfo(path)
+
+class Test(zope.publisher.browser.BrowserPage):
+    zope.component.adapts(zope.interface.Interface,
+                          zope.publisher.interfaces.browser.IBrowserRequest)
+
+    def __call__(self):
+        time.sleep(30)
+        return 'OK'
+
+pid = os.getpid()
+def getStatus(want=('VmSize', 'VmRSS')):
+    for line in open('/proc/%s/status' % pid):
+        if (line.split(':')[0] in want):
+            yield line.strip()
+   


Property changes on: zc.z3monitor/branches/dev/src/zc/z3monitor/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.z3monitor/branches/dev/src/zc/z3monitor/configure.zcml
===================================================================
--- zc.z3monitor/branches/dev/src/zc/z3monitor/configure.zcml	2007-05-01 22:15:07 UTC (rev 74979)
+++ zc.z3monitor/branches/dev/src/zc/z3monitor/configure.zcml	2007-05-01 22:21:11 UTC (rev 74980)
@@ -0,0 +1,12 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    >
+  <subscriber handler=".initialize" />
+  <subscriber handler=".save_request_in_connection_info" />
+  <adapter
+      name="sleeptest"
+      factory=".Test"
+      permission="zope.Public"
+      provides="zope.publisher.interfaces.browser.IBrowserPage"
+      />
+</configure>


Property changes on: zc.z3monitor/branches/dev/src/zc/z3monitor/configure.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: zc.z3monitor/branches/dev/src/zc/z3monitor/tests.py
===================================================================
--- zc.z3monitor/branches/dev/src/zc/z3monitor/tests.py	2007-05-01 22:15:07 UTC (rev 74979)
+++ zc.z3monitor/branches/dev/src/zc/z3monitor/tests.py	2007-05-01 22:21:11 UTC (rev 74980)
@@ -0,0 +1,31 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+import re, unittest
+from zope.testing import doctest, renormalizing
+
+import logging, sys
+
+
+def test_suite():
+    return unittest.TestSuite((
+        doctest.DocFileSuite(
+            'README.txt',
+            checker=renormalizing.RENormalizing([
+                (re.compile("Vm(Size|RSS):\s+\d+\s+kB"), 'Vm\\1 NNN kB'),
+                (re.compile("\d\d+\s+\d\d+\s+\d+"), 'RRR WWW C'),
+                (re.compile("\d+[.]\d+ seconds"), 'N.NNNNNN seconds'),
+                ]),
+            ),
+        
+        ))


Property changes on: zc.z3monitor/branches/dev/src/zc/z3monitor/tests.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native



More information about the Checkins mailing list