[cubicweb/monitor] moved munin stats from general states to formula
authorArthur Lutz <arthur.lutz@logilab.fr>
Thu, 28 Apr 2016 12:42:18 +0200
changeset 82 74a5cd26ce9e
parent 81 56a26085fa05
child 83 9552aa7bc024
[cubicweb/monitor] moved munin stats from general states to formula
cubicweb/cubicweb-stats.sls
cubicweb/cubicweb_stats
cubicweb/monitor.sls
munin/plugin-conf.d/cubicweb-stats
munin/plugins/cubicweb_stats
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cubicweb/cubicweb-stats.sls	Thu Apr 28 12:42:18 2016 +0200
@@ -0,0 +1,11 @@
+/usr/share/munin/plugins/cubicweb_stats:
+    file.managed:
+        - source: salt://munin/plugins/cubicweb_stats
+
+/etc/munin/plugins/cubicweb_stats:
+    file.symlink:
+        - target: /usr/share/munin/plugins/cubicweb_stats
+
+/etc/munin/plugin-conf.d/cubicweb-stats:
+    file.managed:  
+        - source: salt://munin/plugin-conf.d/cubicweb-stats
--- a/cubicweb/cubicweb_stats	Thu Apr 28 12:04:05 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,352 +0,0 @@
-#!/usr/bin/env python
-# -*- encoding: utf-8 -*-
-#
-# Wildcard-plugin to monitor cubicweb instances:
-#         http://www.cubicweb.org
-#
-# To monitor a series of CW instances:
-#    ln -s /usr/share/munin/plugins/cubicweb_stats /etc/munin/plugins/
-#
-#
-# Author: David Douard
-#
-# v1.0 05/03/2010 - First draft
-#
-# Copyright (c) 2010 David Douard, Logilab
-#
-# Permission to use, copy, and modify this software with or without fee
-# is hereby granted, provided that this entire notice is included in
-# all source code copies of any software which is or includes a copy or
-# modification of this software.
-#
-# THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
-# IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
-# REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
-# MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
-# PURPOSE.
-#
-#
-# Magic markers
-#%# capabilities=autoconf
-#%# family=auto
-
-import os, sys, re
-from logilab.common.pyro_ext import ns_get_proxy
-
-stats_curves = {
-    'available_cnxsets': ('Available pools', 'LINE2', None),
-    'nb_active_threads': ('Threads', 'LINE2', None),
-    'nb_open_sessions': ('Sessions', 'LINE1', None),
-    }
-
-cache_curves = {
-    'rqlt_st_cache_hit': ("rqlt_st_cache_hit", 'LINE2', "DERIVE"),
-    'rqlt_st_cache_miss': ("rqlt_st_cache_miss", 'LINE2', "DERIVE"),
-    'sql_cache_hit': ("sql_cache_hit", 'LINE2', "DERIVE"),
-    'sql_cache_miss': ("sql_cache_miss", 'LINE2', "DERIVE"),
-    'sql_no_cache': ("sql_no_cache", 'LINE2', "DERIVE")
-    }
-cache_size_curves = {
-    'rqlt_st_cache_size': ("rqlt_st_cache_size", None, None),
-    'rqlt_st_cache_size_max': ("rqlt_st_cache_size_max", None, None),
-    'sql_cache_size': ("sql_cache_size", None, None),
-    'sql_cache_size_max': ("sql_cache_size_max", None, None),
-    }
-repository_cache_size_curves = {
-    'type_source_cache_size': ("type_source_cache_size", None, None),
-    'extid_cache_size': ("extid_cache_size", None, None),
-    }
-cache_percent_curves = {
-    'rqlt_st_cache_hit_percent': ("rqlt_st_cache_hit", None, None),
-    'sql_cache_hit_percent': ("sql_cache_hit", None, None),
-    }
-gc_curves1 = {
-    'Union': ('Union', None, None),
-    'ResultSet': ('ResultSet', None, None),
-    'AppObject': ('AppObject', None, None),
-}
-gc_curves2 = {
-    'Connection': ('Connection', None, None),
-    'Session': ('Session', None, None),
-    }
-
-mem_curves = "VmPeak VmSize VmLck VmHWM VmRSS VmData VmStk VmExe VmLib VmPTE".split()
-mem_curves_infos = {
-    "VmPeak": "Peak virtual memory size.",
-    "VmSize": "Virtual memory size.",
-    "VmLck": "Locked memory size.",
-    "VmHWM": "Peak resident set size ('high water mark').",
-    "VmRSS": "Resident set size.",
-    "VmData": "Size of data segments.",
-    "VmStk": "Size of stacksegments.",
-    "VmExe": "Size of text segments.",
-    "VmLib": "Shared library code size.",
-    "VmPTE": "Page table entries size.",
-    }
-
-
-def find_cw_instances():
-    cmd = "%s list 2>/dev/null" % (os.getenv('cubicweb-ctl','/usr/bin/cubicweb-ctl'))
-    p = os.popen(cmd)
-    in_instancelist = False
-    instances = []
-    for l in p:
-        if in_instancelist:
-            if l.startswith('*'):
-                instances.append(l.split()[1])
-            else:
-                in_instancelist = False
-        elif l.startswith("Available instances"):
-            in_instancelist = True
-
-    p.close()
-    return instances
-
-def get_pid(instance):
-    cmd = "%s status %s 2>/dev/null" % (os.getenv('cubicweb-ctl','/usr/bin/cubicweb-ctl'), instance)
-    p = os.popen(cmd)
-    r = re.compile('^.*[[]%s-[^]]*[]] running with pid (?P<pid>[0-9]+)$' % instance)
-    pid = None
-    for l in p:
-        m = r.match(l)
-        if m:
-            pid = int(m.group('pid'))
-            break
-    else:
-        return None
-    p.close()
-    return pid
-
-def get_vminfos(pid):
-    data = open('/proc/%s/status' % pid).readlines()
-    infos = {}
-
-    for l in data:
-        key, val = l.split(':', 1)
-        key = key.strip()
-        val = val.strip()
-        if val.endswith('kB'):
-            val = int(val.split()[0]) * 1024
-        infos[key] = val
-    return infos
-
-def get_mem():
-    data = open('/proc/meminfo').readlines()
-    infos = {}
-
-    for l in data:
-        key, val = l.split(':', 1)
-        key = key.strip()
-        val = val.strip()
-        if val.endswith('kB'):
-            val = int(val.split()[0]) * 1024
-        infos[key] = val
-    return infos
-
-def get_stats(repo, instance):
-    stats = repo.stats()
-    for k, v in stats.items():
-        if isinstance(v, basestring):
-            if "/" in v:
-                val, maxval = v.split('/')
-                val = int(val)
-                maxval = int(val)
-                stats[k] = val
-                stats['%s_max' % k] = maxval
-    return stats
-
-def get_gc_stats(repo, instance):
-    try:
-        return dict(repo.gc_stats()['lookupclasses'])
-    except (AttributeError, KeyError):
-        return {}
-
-
-def _print_stats_config(instances, mgname, curves, title, info):
-    print('multigraph %s' % mgname)
-    print('graph_title %s' % title)
-    print('graph_category cubicweb')
-    print('graph_args -l 0')
-    print('graph_info %s.' % info)
-    for curve, (name, linetype, curvetype) in curves.items():
-        print('%s.label %s' % (curve, name))
-        if linetype:
-            print('%s.draw %s' % (curve, linetype))
-        if curvetype:
-            print('%s.type %s' % (curve, curvetype))
-    print('')
-
-    for instance in instances:
-        print('multigraph %s.%s' % (mgname, instance))
-        print('graph_title %s %s' % (instance, title))
-        print('graph_category cubicweb')
-        print('graph_args -l 0')
-        print('graph_info %s for %s.' % (info, instance))
-
-        for curve, (name, linetype, curvetype) in curves.items():
-            print('%s.label %s' % (curve, name))
-            if linetype:
-                print('%s.draw %s' % (curve, linetype))
-            if curvetype:
-                print('%s.type %s' % (curve, curvetype))
-        print('')
-
-def print_stats_config(instances):
-    _print_stats_config(instances, 'cubicweb_stats', stats_curves,
-                        'cubicweb instances stats',
-                        'This graph shows the instance usage stats')
-
-    _print_stats_config(instances, 'cubicweb_cache', cache_curves,
-                        'cubicweb instances cache hit',
-                        'This graph shows the instance cache hit evolution')
-
-    _print_stats_config(instances, 'cubicweb_cache_percent', cache_percent_curves,
-                        'cubicweb instances cache hit ratio',
-                        'This graph shows the instance cache hit ratio')
-
-    _print_stats_config(instances, 'cubicweb_cache_size', cache_size_curves,
-                        'cubicweb instances cache size',
-                        'This graph shows the instance cache size')
-
-    _print_stats_config(instances, 'cubicweb_repository_cache_size', repository_cache_size_curves,
-                        'cubicweb instances repository caches size',
-                        'This graph shows the instance repository caches size')
-
-    _print_stats_config(instances, 'cubicweb_gc_objects', gc_curves1,
-                        'cubicweb instances GC counts',
-                        'This graph shows the instance repository GC counts for some objects')
-
-    _print_stats_config(instances, 'cubicweb_gc_cnx_objects', gc_curves2,
-                        'cubicweb instances GC counts of connection-related objets',
-                        'This graph shows the instance repository GC counts of connection-related objets')
-
-
-def print_mem_config(instances):
-    print('multigraph cubicweb_memory')
-    print('graph_title cubicweb memory usage')
-    print('graph_args --base 1024 -l 0 --vertical-label Bytes')
-    print('graph_category cubicweb')
-    print('graph_info This graph shows the total cubicweb memory usage.')
-
-    for curve in "VmPeak", "VmSize", "VmRSS":
-        print('%s.label %s' % (curve, curve))
-        print('%s.draw LINE2' % (curve, ))
-    print('')
-
-    for instance in instances:
-        print('multigraph cubicweb_memory.%s' % instance)
-        print('graph_title %s memory usage' % instance)
-        print('graph_args --base 1024 -l 0 --vertical-label Bytes')
-        print('graph_category cubicweb')
-        print('graph_info This graph shows the instance memory usage.')
-
-        print('graph_order %s' % ' '.join(mem_curves))
-        for curve in mem_curves:
-            print('%s.label %s' % (curve, curve))
-            print('%s.draw LINE2' % (curve, ))
-        print('')
-
-def _print_stats_values(instances, stats, mgname, curves, normed=False):
-    print('multigraph %s' % mgname)
-    for curve in curves:
-        val = 0
-        nval = 0
-        for instance in instances:
-            if stats[instance].get(curve, 0):
-                val += stats[instance][curve]
-                nval += 1
-        if normed and nval:
-            val = float(val)/nval
-        print('%s.value %s' % (curve, val))
-    print('')
-
-    for instance in instances:
-        print('multigraph %s.%s' % (mgname, instance))
-        for curve in curves:
-            print('%s.value %s' % (curve, stats[instance].get(curve, 0)))
-        print('')
-
-def print_stats_values(instances):
-    stats = {}
-    gc_stats = {}
-    for instance in instances[:]:
-        try:
-            repo = ns_get_proxy(instance, "cubicweb", "localhost")
-            stats[instance] = get_stats(repo, instance)
-            gc_stats[instance] = get_gc_stats(repo, instance)
-        except Exception, ex:
-            msg = 'could not get stats for instance [%s]: %s' % (instance, ex)
-            print >> sys.stderr, msg
-            stats[instance] = None
-            gc_stats[instance] = None
-            instances.remove(instance)
-
-    _print_stats_values(instances, stats, 'cubicweb_stats', stats_curves)
-    _print_stats_values(instances, stats, 'cubicweb_cache', cache_curves)
-    _print_stats_values(instances, stats, 'cubicweb_cache_percent',
-                        cache_percent_curves, normed=True)
-    _print_stats_values(instances, stats, 'cubicweb_cache_size',
-                        cache_size_curves)
-    _print_stats_values(instances, stats, 'cubicweb_repository_cache_size',
-                        repository_cache_size_curves)
-    _print_stats_values(instances, gc_stats, 'cubicweb_gc_objects', gc_curves1)
-    _print_stats_values(instances, gc_stats, 'cubicweb_gc_cnx_objects', gc_curves2)
-
-def print_mem_values(instances):
-    mem = {}
-    totalmem = {'VmPeak': 0,
-                'VmSize': 0,
-                'VmRSS': 0,
-                }
-    for instance in instances:
-        pid = get_pid(instance)
-        if pid is None:
-            print >> sys.stderr, 'No process found for instances [%s]' % instance
-            continue
-        infos = get_vminfos(pid)
-        mem[instance] = infos
-        for k in totalmem:
-            totalmem[k] += infos.get(k, 0)
-
-    print('multigraph cubicweb_memory')
-    for curve, tot in totalmem.items():
-        print('%s.value %s' % (curve, tot))
-    print('')
-
-    for instance in instances:
-        if instance not in mem:
-            continue
-        print('multigraph cubicweb_memory.%s' % instance)
-        for curve in mem_curves:
-            print "%s.value %s" % (curve, mem[instance][curve])
-        print('')
-
-def print_config(instances):
-    print_stats_config(instances)
-    print_mem_config(instances)
-
-def print_values(instances):
-    print_stats_values(instances)
-    print_mem_values(instances)
-
-### Main part ###
-plugin_name = os.path.split(sys.argv[0])[1]
-
-instances = find_cw_instances()
-
-# Parse arguments
-if len(sys.argv) > 1:
-    if sys.argv[1] == "config":
-        print_config(instances)
-        sys.exit(0)
-    elif sys.argv[1] == "autoconf":
-        if os.path.exists(os.getenv('cubicweb-ctl', '/usr/bin/cubicweb-ctl')):
-            print('yes')
-            sys.exit(0)
-        else:
-            print('no (cubicweb-ctl not found)')
-            sys.exit(1)
-    elif sys.argv[1] != "":
-        sys.exit(1)
-
-print_values(instances)
--- a/cubicweb/monitor.sls	Thu Apr 28 12:04:05 2016 +0200
+++ b/cubicweb/monitor.sls	Thu Apr 28 12:42:18 2016 +0200
@@ -6,17 +6,22 @@
 # TODO replace by debian package installation
 # cf https://intranet.logilab.fr/jpl/ticket/199142
 /usr/share/munin/plugins/cubicweb_stats:
-    file.managed: 
-        - source: salt://cubicweb/cubicweb_stats
+    file.managed:
+        - source: salt://munin/plugins/cubicweb_stats
 
 /etc/munin/plugins/cubicweb_stats:
     file.symlink:
         - target: /usr/share/munin/plugins/cubicweb_stats
 
+/etc/munin/plugin-conf.d/cubicweb-stats:
+    file.managed:  
+        - source: salt://munin/plugin-conf.d/cubicweb-stats
+
+
 {% set suffix = 'circus' in pillar.get('role') and '_circus' or '' %}
 /usr/lib/nagios/plugins/check_cubicweb{{ suffix }}:
     file.managed:
-        - source: salt://shinken/scripts/check_cubicweb
+        - source: salt://shinken/scripts/check_cubicweb{{ suffix }}
         - mode: 0755
         - watch:
           - service: nagios-nrpe-server
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/munin/plugin-conf.d/cubicweb-stats	Thu Apr 28 12:42:18 2016 +0200
@@ -0,0 +1,4 @@
+[cubicweb_stats]
+user cubicweb
+timeout 60
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/munin/plugins/cubicweb_stats	Thu Apr 28 12:42:18 2016 +0200
@@ -0,0 +1,347 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+#
+# Wildcard-plugin to monitor cubicweb instances:
+#         http://www.cubicweb.org
+#
+# To monitor a series of CW instances:
+#    ln -s /usr/share/munin/plugins/cubicweb_stats /etc/munin/plugins/
+#
+#
+# Author: David Douard
+#
+# v1.0 05/03/2010 - First draft
+#
+# Copyright (c) 2010 David Douard, Logilab
+#
+# Permission to use, copy, and modify this software with or without fee
+# is hereby granted, provided that this entire notice is included in
+# all source code copies of any software which is or includes a copy or
+# modification of this software.
+#
+# THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
+# IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
+# REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
+# MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+# PURPOSE.
+#
+#
+# Magic markers
+#%# capabilities=autoconf
+#%# family=auto
+
+import os, sys, re
+import json
+
+stats_curves = {
+    'available_cnxsets': ('Available pools', 'LINE2', None),
+    'nb_active_threads': ('Threads', 'LINE2', None),
+    'nb_open_sessions': ('Sessions', 'LINE1', None),
+    }
+
+cache_curves = {
+    'rqlt_st_cache_hit': ("rqlt_st_cache_hit", 'LINE2', "DERIVE"),
+    'rqlt_st_cache_miss': ("rqlt_st_cache_miss", 'LINE2', "DERIVE"),
+    'sql_cache_hit': ("sql_cache_hit", 'LINE2', "DERIVE"),
+    'sql_cache_miss': ("sql_cache_miss", 'LINE2', "DERIVE"),
+    'sql_no_cache': ("sql_no_cache", 'LINE2', "DERIVE")
+    }
+cache_size_curves = {
+    'rqlt_st_cache_size': ("rqlt_st_cache_size", None, None),
+    'rqlt_st_cache_size_max': ("rqlt_st_cache_size_max", None, None),
+    'sql_cache_size': ("sql_cache_size", None, None),
+    'sql_cache_size_max': ("sql_cache_size_max", None, None),
+    }
+repository_cache_size_curves = {
+    'type_source_cache_size': ("type_source_cache_size", None, None),
+    'extid_cache_size': ("extid_cache_size", None, None),
+    }
+cache_percent_curves = {
+    'rqlt_st_cache_hit_percent': ("rqlt_st_cache_hit", None, None),
+    'sql_cache_hit_percent': ("sql_cache_hit", None, None),
+    }
+gc_curves1 = {
+    'Union': ('Union', None, None),
+    'ResultSet': ('ResultSet', None, None),
+    'AppObject': ('AppObject', None, None),
+}
+gc_curves2 = {
+    'Connection': ('Connection', None, None),
+    'Session': ('Session', None, None),
+    }
+
+mem_curves = "VmPeak VmSize VmLck VmHWM VmRSS VmData VmStk VmExe VmLib VmPTE".split()
+mem_curves_infos = {
+    "VmPeak": "Peak virtual memory size.",
+    "VmSize": "Virtual memory size.",
+    "VmLck": "Locked memory size.",
+    "VmHWM": "Peak resident set size ('high water mark').",
+    "VmRSS": "Resident set size.",
+    "VmData": "Size of data segments.",
+    "VmStk": "Size of stacksegments.",
+    "VmExe": "Size of text segments.",
+    "VmLib": "Shared library code size.",
+    "VmPTE": "Page table entries size.",
+    }
+
+
+def find_cw_instances():
+    cmd = "%s list instances 2>/dev/null" % (os.getenv('cubicweb-ctl','/usr/bin/cubicweb-ctl'))
+    p = os.popen(cmd)
+    instances = []
+    for l in p:
+        if l.startswith('*'):
+            instances.append(l.split()[1])
+    p.close()
+    return instances
+
+def get_pid(instance):
+    cmd = "%s status %s 2>/dev/null" % (os.getenv('cubicweb-ctl','/usr/bin/cubicweb-ctl'), instance)
+    p = os.popen(cmd)
+    r = re.compile('^.*[[]%s-[^]]*[]] running with pid (?P<pid>[0-9]+)$' % instance)
+    pid = None
+    for l in p:
+        m = r.match(l)
+        if m:
+            pid = int(m.group('pid'))
+            break
+    else:
+        return None
+    p.close()
+    return pid
+
+def get_vminfos(pid):
+    data = open('/proc/%s/status' % pid).readlines()
+    infos = {}
+
+    for l in data:
+        key, val = l.split(':', 1)
+        key = key.strip()
+        val = val.strip()
+        if val.endswith('kB'):
+            val = int(val.split()[0]) * 1024
+        infos[key] = val
+    return infos
+
+def get_mem():
+    data = open('/proc/meminfo').readlines()
+    infos = {}
+
+    for l in data:
+        key, val = l.split(':', 1)
+        key = key.strip()
+        val = val.strip()
+        if val.endswith('kB'):
+            val = int(val.split()[0]) * 1024
+        infos[key] = val
+    return infos
+
+def get_stats(stats):
+    for k, v in stats.items():
+        if isinstance(v, basestring):
+            if "/" in v:
+                val, maxval = v.split('/')
+                val = int(val)
+                maxval = int(val)
+                stats[k] = val
+                stats['%s_max' % k] = maxval
+    return stats
+
+def get_gc_stats(gc_stats):
+    try:
+        return dict(gc_stats['lookupclasses'])
+    except (AttributeError, KeyError):
+        return {}
+
+
+def _print_stats_config(instances, mgname, curves, title, info):
+    print('multigraph %s' % mgname)
+    print('graph_title %s' % title)
+    print('graph_category cubicweb')
+    print('graph_args -l 0')
+    print('graph_info %s.' % info)
+    for curve, (name, linetype, curvetype) in curves.items():
+        print('%s.label %s' % (curve, name))
+        if linetype:
+            print('%s.draw %s' % (curve, linetype))
+        if curvetype:
+            print('%s.type %s' % (curve, curvetype))
+    print('')
+
+    for instance in instances:
+        print('multigraph %s.%s' % (mgname, instance))
+        print('graph_title %s %s' % (instance, title))
+        print('graph_category cubicweb')
+        print('graph_args -l 0')
+        print('graph_info %s for %s.' % (info, instance))
+
+        for curve, (name, linetype, curvetype) in curves.items():
+            print('%s.label %s' % (curve, name))
+            if linetype:
+                print('%s.draw %s' % (curve, linetype))
+            if curvetype:
+                print('%s.type %s' % (curve, curvetype))
+        print('')
+
+def print_stats_config(instances):
+    _print_stats_config(instances, 'cubicweb_stats', stats_curves,
+                        'cubicweb instances stats',
+                        'This graph shows the instance usage stats')
+
+    _print_stats_config(instances, 'cubicweb_cache', cache_curves,
+                        'cubicweb instances cache hit',
+                        'This graph shows the instance cache hit evolution')
+
+    _print_stats_config(instances, 'cubicweb_cache_percent', cache_percent_curves,
+                        'cubicweb instances cache hit ratio',
+                        'This graph shows the instance cache hit ratio')
+
+    _print_stats_config(instances, 'cubicweb_cache_size', cache_size_curves,
+                        'cubicweb instances cache size',
+                        'This graph shows the instance cache size')
+
+    _print_stats_config(instances, 'cubicweb_repository_cache_size', repository_cache_size_curves,
+                        'cubicweb instances repository caches size',
+                        'This graph shows the instance repository caches size')
+
+    _print_stats_config(instances, 'cubicweb_gc_objects', gc_curves1,
+                        'cubicweb instances GC counts',
+                        'This graph shows the instance repository GC counts for some objects')
+
+    _print_stats_config(instances, 'cubicweb_gc_cnx_objects', gc_curves2,
+                        'cubicweb instances GC counts of connection-related objets',
+                        'This graph shows the instance repository GC counts of connection-related objets')
+
+
+def print_mem_config(instances):
+    print('multigraph cubicweb_memory')
+    print('graph_title cubicweb memory usage')
+    print('graph_args --base 1024 -l 0 --vertical-label Bytes')
+    print('graph_category cubicweb')
+    print('graph_info This graph shows the total cubicweb memory usage.')
+
+    for curve in "VmPeak", "VmSize", "VmRSS":
+        print('%s.label %s' % (curve, curve))
+        print('%s.draw LINE2' % (curve, ))
+    print('')
+
+    for instance in instances:
+        print('multigraph cubicweb_memory.%s' % instance)
+        print('graph_title %s memory usage' % instance)
+        print('graph_args --base 1024 -l 0 --vertical-label Bytes')
+        print('graph_category cubicweb')
+        print('graph_info This graph shows the instance memory usage.')
+
+        print('graph_order %s' % ' '.join(mem_curves))
+        for curve in mem_curves:
+            print('%s.label %s' % (curve, curve))
+            print('%s.draw LINE2' % (curve, ))
+        print('')
+
+def _print_stats_values(instances, stats, mgname, curves, normed=False):
+    print('multigraph %s' % mgname)
+    for curve in curves:
+        val = 0
+        nval = 0
+        for instance in instances:
+            if stats[instance].get(curve, 0):
+                val += stats[instance][curve]
+                nval += 1
+        if normed and nval:
+            val = float(val)/nval
+        print('%s.value %s' % (curve, val))
+    print('')
+
+    for instance in instances:
+        print('multigraph %s.%s' % (mgname, instance))
+        for curve in curves:
+            print('%s.value %s' % (curve, stats[instance].get(curve, 0)))
+        print('')
+
+def print_stats_values(instances):
+    stats = {}
+    gc_stats = {}
+    for instance in instances[:]:
+        if '{0}_statsfile'.format(instance) not in os.environ:
+            return {}
+        try:
+            statsfile = os.environ['{0}_statsfile'.format(instance)]
+            instance_stats = json.loads(open(statsfile).readlines()[-1])
+            stats[instance] = get_stats(instance_stats['resources'])
+            gc_stats[instance] = get_gc_stats(instance_stats['memory'])
+        except Exception, ex:
+            msg = 'could not get stats for instance [%s]: %s' % (instance, ex)
+            print >> sys.stderr, msg
+            stats[instance] = None
+            gc_stats[instance] = None
+            instances.remove(instance)
+
+    _print_stats_values(instances, stats, 'cubicweb_stats', stats_curves)
+    _print_stats_values(instances, stats, 'cubicweb_cache', cache_curves)
+    _print_stats_values(instances, stats, 'cubicweb_cache_percent',
+                        cache_percent_curves, normed=True)
+    _print_stats_values(instances, stats, 'cubicweb_cache_size',
+                        cache_size_curves)
+    _print_stats_values(instances, stats, 'cubicweb_repository_cache_size',
+                        repository_cache_size_curves)
+    _print_stats_values(instances, gc_stats, 'cubicweb_gc_objects', gc_curves1)
+    _print_stats_values(instances, gc_stats, 'cubicweb_gc_cnx_objects', gc_curves2)
+
+def print_mem_values(instances):
+    mem = {}
+    totalmem = {'VmPeak': 0,
+                'VmSize': 0,
+                'VmRSS': 0,
+                }
+    for instance in instances:
+        pid = get_pid(instance)
+        if pid is None:
+            print >> sys.stderr, 'No process found for instances [%s]' % instance
+            continue
+        infos = get_vminfos(pid)
+        mem[instance] = infos
+        for k in totalmem:
+            totalmem[k] += infos.get(k, 0)
+
+    print('multigraph cubicweb_memory')
+    for curve, tot in totalmem.items():
+        print('%s.value %s' % (curve, tot))
+    print('')
+
+    for instance in instances:
+        if instance not in mem:
+            continue
+        print('multigraph cubicweb_memory.%s' % instance)
+        for curve in mem_curves:
+            print "%s.value %s" % (curve, mem[instance][curve])
+        print('')
+
+def print_config(instances):
+    print_stats_config(instances)
+    print_mem_config(instances)
+
+def print_values(instances):
+    print_stats_values(instances)
+    print_mem_values(instances)
+
+### Main part ###
+plugin_name = os.path.split(sys.argv[0])[1]
+
+instances = find_cw_instances()
+
+# Parse arguments
+if len(sys.argv) > 1:
+    if sys.argv[1] == "config":
+        print_config(instances)
+        sys.exit(0)
+    elif sys.argv[1] == "autoconf":
+        if os.path.exists(os.getenv('cubicweb-ctl', '/usr/bin/cubicweb-ctl')):
+            print('yes')
+            sys.exit(0)
+        else:
+            print('no (cubicweb-ctl not found)')
+            sys.exit(1)
+    elif sys.argv[1] != "":
+        sys.exit(1)
+
+print_values(instances)