Permalink
Browse files

webpy is now needed for a status page, added /memleaks/ and removed a…

… memory leak

git-svn-id: http://evserver.googlecode.com/svn/trunk@92 e9bb6d7e-af12-11dd-bad7-87afd3b02348
  • Loading branch information...
1 parent 5a9aa4b commit a0022cd072f39be9fc034198d34f6877be1d915d majek04 committed Feb 12, 2009
Showing with 140 additions and 88 deletions.
  1. +10 −1 evserver/examples/django_agentpush/views.py
  2. +9 −2 evserver/{ → other}/meminfo.py
  3. +121 −85 evserver/status.py
@@ -6,7 +6,7 @@
PYTHONPATH="$HOME/amqplib-0.6:.." DJANGO_SETTINGS_MODULE=django_agentpush.settings
evserver --listen 127.0.0.1:8080 --framework=django
-Beware, static files are served from ./static directory!
+Beware, static files are served from ./static directory! (relative to current!)
'''
from django.http import HttpResponse
@@ -43,6 +43,10 @@ def send_amqp_message(msg_body):
ch.close()
conn.close()
+ ch.connection = None
+ conn.channels = {}
+ conn.connection = None
+ conn.transport = None
# that is a raw hack that doesn't scale!
@@ -136,6 +140,11 @@ def iterator():
except Exception:
pass
+ ch.connection = None
+ conn.channels = {}
+ conn.connection = None
+ conn.transport = None
+
# build the response
response = HttpResponse(iterator())
for k, v in t.get_headers():
@@ -6,7 +6,7 @@
_scale = {'kB': 1024.0, 'mB': 1024.0*1024.0,
'KB': 1024.0, 'MB': 1024.0*1024.0}
-def memory():
+def _memory():
global _proc_status, _scale
# get pseudo file /proc/<pid>/status
try:
@@ -24,4 +24,11 @@ def memory():
r.append(0.0)
else:
r.append(int (float(v[1]) * _scale[v[2]]) )
- return r
+ return r
+
+
+def memory():
+ try:
+ return _memory()
+ except Exception:
+ return 0,0,0
View
@@ -1,98 +1,134 @@
+'''
+webpy
+python-pydot
+'''
+import web
import server
import time
import gc
import os
import resource
-import meminfo
-
-def wsgi_application(environ, start_response):
- return status_page(environ, start_response)
-'''
import other.objgraph as objgraph
+import other.meminfo as meminfo
import inspect
import random
+import collections
+import operator
+import urllib
+
+urls = (
+ '/$', 'status_page',
+ '/memleaks/$', 'memleaks_page',
+ '/memleaks/([^/]+)/$', 'memleaks_type_page',
+)
+
+
+class status_page:
+ def GET(self):
+ web.header('Content-Type','text/plain', unique=True)
+ web.header('Refresh','3')
+ s = []
+ resources = dict(zip(
+ ('utime', 'stime', 'maxrss', 'ixrss','idrss','isrss','minflt','majflt','nswap','inblock','outblock','msgsnd','msgrcv','nsignals','nvcsw','nivcsw'),
+ resource.getrusage(resource.RUSAGE_SELF)))
+
+ pid, pagesize = os.getpid(), resource.getpagesize()
+
+ vm, rm, sm = meminfo.memory()
+ gc0, gc1, gc2 = gc.get_count()
+ s.append(
+ '''######## PID:%(pid)i total events:%(event_counter)i python objects, unreachable:%(gc_unreachable)i total:%(gc_objects)i dirty:%(gc0)i/%(gc1)i/%(gc2)i file descriptors:%(file_descriptors)i/%(max_descriptors)i \n'''
+ '''######## virt memory:%(vm).0fMiB res memory:%(rm).0fMiB sys cpu time:%(sys).3fs user:%(user).3fs context switches, voluntary:%(vcs)i involuntary:%(ics)i \n''' %
+ {
+ 'pid':pid,
+ 'event_counter':server.event_counter,
+ 'gc0': gc0,
+ 'gc1': gc1,
+ 'gc2': gc2,
+ 'gc_unreachable': len(gc.garbage),
+ 'gc_objects':len(gc.get_objects()),
+ 'file_descriptors':len(os.listdir('/proc/%i/fd' % pid)),
+ 'max_descriptors':resource.getrlimit(resource.RLIMIT_NOFILE)[1],
+ 'vm': vm/1048576.0,
+ 'rm': rm/1048576.0,
+ 'sm': sm/1048576.0,
+ 'vcs':resources['nvcsw'],
+ 'ics':resources['nivcsw'],
+ 'sys':resources['stime'],
+ 'user':resources['utime'],
+ },
+ )
+
+ for vhostdata in server.vhosts:
+ s.append(''' **** %(host)s:%(port)i connections:%(counter)i broken:%(broken)i cpu_time:%(cpu_time).3fs ****\n''' % vhostdata)
+
+ for clock, req in vhostdata['requests'].items():
+ s.append(''' %(host)s:%(port)5s "%(method)s %(url)s %(http)s" %(status_code)3i %(content_length)8i/%(chunks)i/%(context_switches)i (%(cpu_time).3fms)\n''' % {
+ 'host':req.environ['REMOTE_HOST'],
+ 'port':req.environ['REMOTE_PORT'],
+ 'method': req.environ['REQUEST_METHOD'],
+ 'url': req.get_url(),
+ 'http': req.environ['SERVER_PROTOCOL'],
+ 'status_code': req.out_dict['code'],
+ 'content_length':req.content_length,
+ 'chunks':req.chunks_number,
+ 'context_switches':req.context_switches,
+ 'cpu_time':req.all_cpu_time * 1000.0,
+ })
+
+ s.append('\n\n')
+
+ s.append("took %.3fms\n" % ((time.time()-web.ctx.environ['wsgi.now']())*1000.0, ))
+ return ''.join(s)
+
+class memleaks_page:
+ def GET(self):
+ web.header('Content-Type','text/html', unique=True)
+ gc.collect()
+ gc.collect()
+ gc.collect()
+
+
+ typestats = collections.defaultdict(lambda: 0)
+ for o in gc.garbage:
+ typestats[type(o).__name__] += 1
+
+ forgotten_items = sorted(typestats.items(), key=operator.itemgetter(1), reverse=True)
+
+ used_items = objgraph.show_most_common_types(limit=50)
+ if not used_items: used_items = []
+
+ s = []
+ for name, items in [('gc.garbage -> Not collectable items',forgotten_items),
+ ('gc.get_objects -> Collectable items',used_items)]:
+ s.append('''<h3>%s</h3><br/>\n''' % name)
+ for typename, number in items:
+ s.append('''%i: <a href="./%s/">%s</a><br/>\n''' % (number, urllib.quote(typename), typename))
+
+
+ return ''.join(s)
+
+class memleaks_type_page:
+ def GET(self, typename):
+ web.header('Content-Type','image/png', unique=True)
+ gc.collect()
+ gc.collect()
+ gc.collect()
+ print '%r ' % typename
+ obj = random.choice(objgraph.by_type(typename))
+ objgraph.show_backrefs([obj], max_depth=10)
+
+ f = open('objects.png', 'rb')
+ data = f.read()
+ f.close()
+
+ return data
+
+
+# webpy 0.3 specific
+wsgi_application = web.application(urls, globals()).wsgifunc()
-def memleaks(environ, start_response):
- start_response("200 OK", [('Content-Type', 'text/plain')])
- gc.collect()
- gc.collect()
- gc.collect()
- b = objgraph.show_most_common_types(limit=50)
- if not b:
- b = []
- #return ['\n'.join(map(str,b))] #[ '\n\n'.join(['\n'.join(map(str,b)), '\n'.join(map(str, ob)), '\n'.join(ch)] ) ]
- ob = objgraph.by_type('tuple')
- ab = []
- if ob:
- for i in range(10):
- ab.append( ob[random.randint(0, len(ob)-1)] )
- print '%r' % ab
- if ab:
- objgraph.show_backrefs(ab, max_depth=18)
- #ch = objgraph.find_backref_chain(ob[0], inspect.ismodule)
- #if ch:
- # ch = map(str, ch)
- #else:
- return ['\n'.join(map(str,b))] #[ '\n\n'.join(['\n'.join(map(str,b)), '\n'.join(map(str, ob)), '\n'.join(ch)] ) ]
-'''
-
-def status_page(environ, start_response):
- start_response("200 OK", [('Content-Type', 'text/plain'), ('Refresh', '3')])
- s = []
- resources = dict(zip(
- ('utime', 'stime', 'maxrss', 'ixrss','idrss','isrss','minflt','majflt','nswap','inblock','outblock','msgsnd','msgrcv','nsignals','nvcsw','nivcsw'),
- resource.getrusage(resource.RUSAGE_SELF)))
-
- pid = os.getpid()
- pagesize = resource.getpagesize()
-
- vm, rm, sm = meminfo.memory()
- gc0, gc1, gc2 = gc.get_count()
- s.append(
- '''######## PID:%(pid)i total events:%(event_counter)i python objects, unreachable:%(gc_unreachable)i total:%(gc_objects)i dirty:%(gc0)i/%(gc1)i/%(gc2)i file descriptors:%(file_descriptors)i/%(max_descriptors)i \n'''
- '''######## virt memory:%(vm).0fMiB res memory:%(rm).0fMiB sys cpu time:%(sys).3fs user:%(user).3fs context switches, voluntary:%(vcs)i involuntary:%(ics)i \n''' %
- {
- 'pid':pid,
- 'event_counter':server.event_counter,
- 'gc0': gc0,
- 'gc1': gc1,
- 'gc2': gc2,
- 'gc_unreachable': len(gc.garbage),
- 'gc_objects':len(gc.get_objects()),
- 'file_descriptors':len(os.listdir('/proc/%i/fd' % pid)),
- 'max_descriptors':resource.getrlimit(resource.RLIMIT_NOFILE)[1],
- 'vm': vm/1048576.0,
- 'rm': rm/1048576.0,
- 'sm': sm/1048576.0,
- 'vcs':resources['nvcsw'],
- 'ics':resources['nivcsw'],
- 'sys':resources['stime'],
- 'user':resources['utime'],
- },
- )
-
- for vhostdata in server.vhosts:
- s.append(''' **** %(host)s:%(port)i connections:%(counter)i broken:%(broken)i cpu_time:%(cpu_time).3fs ****\n''' % vhostdata)
-
- for clock, req in vhostdata['requests'].items():
- s.append(''' %(host)s:%(port)5s "%(method)s %(url)s %(http)s" %(status_code)3i %(content_length)8i/%(chunks)i/%(context_switches)i (%(cpu_time).3fms)\n''' % {
- 'host':req.environ['REMOTE_HOST'],
- 'port':req.environ['REMOTE_PORT'],
- 'method': req.environ['REQUEST_METHOD'],
- 'url': req.get_url(),
- 'http': req.environ['SERVER_PROTOCOL'],
- 'status_code': req.out_dict['code'],
- 'content_length':req.content_length,
- 'chunks':req.chunks_number,
- 'context_switches':req.context_switches,
- 'cpu_time':req.all_cpu_time * 1000.0,
- })
-
- s.append('\n\n')
-
- s.append("took %.3fms\n" % ((time.time()-req.environ['wsgi.now']())*1000.0, ))
- return [''.join(s)]

0 comments on commit a0022cd

Please sign in to comment.