[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