import os.path import time import rrdtool import pylab from django.db.models import F from django.conf import settings from djeuscan.models import Package CHARTS_ROOT = os.path.join(settings.EUSCAN_ROOT, 'var', 'charts') CHARTS_URL = os.path.join(settings.EUSCAN_ROOT, 'var', 'charts') CHARTS_TTL = (24 * 60 * 60) pylab.rcParams['font.size'] = 10.0 pylab.rcParams['axes.titlesize'] = 10.0 pylab.rcParams['xtick.labelsize'] = 8.0 pylab.rcParams['legend.fontsize'] = 8.0 def chart_alive(name): path = os.path.join(CHARTS_ROOT, name) if not os.path.exists(path): return False if os.path.getmtime(__file__) > os.path.getmtime(path): return False if os.path.getmtime(path) + CHARTS_TTL < time.time(): return False return True def rrd_name(**kwargs): name = "" if 'category' in kwargs and kwargs['category']: name = 'category-%s' % kwargs['category'] elif 'herd' in kwargs and kwargs['herd']: name = 'herd-%d' % kwargs['herd'].id elif 'maintainer' in kwargs and kwargs['maintainer']: name = 'maintainer-%d' % kwargs['maintainer'].id else: name = 'world' return name def chart_name(name, **kwargs): name = name.replace('_', '-') if 'category' in kwargs and kwargs['category']: name += '-%s' % kwargs['category'] if 'herd' in kwargs and kwargs['herd']: name += '-h-%d' % kwargs['herd'].id if 'maintainer' in kwargs and kwargs['maintainer']: name += '-m-%d' % kwargs['maintainer'].id for kw in ('-small', '-weekly', '-monthly', '-yearly'): if kw in kwargs: name += kw return name + ".png" def getpackages(**kwargs): pkgs = Package.objects if 'category' in kwargs and kwargs['category']: pkgs = Package.objects.for_category(kwargs['category']) if 'herd' in kwargs and kwargs['herd']: pkgs = Package.objects.for_herd(kwargs['herd']) if 'maintainer' in kwargs and kwargs['maintainer']: pkgs = Package.objects.for_maintainer(kwargs['maintainer']) return pkgs def cached_pylab_chart(f): def new_f(*args, **kwds): name = chart_name(f.func_name, **kwds) if not chart_alive(name): f(*args, **kwds) pylab.savefig(os.path.join(CHARTS_ROOT, name)) pylab.close() return name new_f.func_name = f.func_name return new_f @cached_pylab_chart def pie_versions(**kwargs): gpk = getpackages(**kwargs) n_packaged = gpk.n_packaged() n_overlay = gpk.n_overlay() n_upstream = gpk.n_upstream() pylab.figure(1, figsize=(3.5, 3.5)) if n_overlay: labels = 'Gentoo', 'Overlays', 'Upstream' fracs = [n_packaged, n_overlay, n_upstream] colors = '#008000', '#0B17FD', '#FF0000' else: labels = 'Gentoo', 'Upstream' fracs = [n_packaged, n_upstream] colors = '#008000', '#FF0000' pylab.pie(fracs, labels=labels, colors=colors, autopct='%1.1f%%', shadow=True) pylab.title('Versions', bbox={'facecolor': '0.8', 'pad': 5}) @cached_pylab_chart def pie_packages(**kwargs): gpk = getpackages(**kwargs) n_packages = gpk.count() n_packages_uptodate_main = gpk.filter(n_versions=F('n_packaged')).count() n_packages_uptodate_all = gpk.filter(n_versions=F('n_packaged') + \ F('n_overlay')).count() n_packages_outdated = n_packages - n_packages_uptodate_all n_packages_uptodate_ovl = n_packages_uptodate_all - \ n_packages_uptodate_main pylab.figure(1, figsize=(3.5, 3.5)) if n_packages_uptodate_ovl: labels = 'Ok (gentoo)', 'Ok (overlays)', 'Outdated' fracs = [n_packages_uptodate_main, n_packages_uptodate_ovl, n_packages_outdated] colors = '#008000', '#0B17FD', '#FF0000' else: labels = 'Ok (gentoo)', 'Outdated' fracs = [n_packages_uptodate_main, n_packages_outdated] colors = '#008000', '#FF0000' pylab.pie(fracs, labels=labels, colors=colors, autopct='%1.1f%%', shadow=True) pylab.title('Packages', bbox={'facecolor': '0.8', 'pad': 5}) def rrd_path(name): res = str(os.path.join(settings.RRD_ROOT, name)) if res.endswith(".rrd"): return res else: return res + ".rrd" def rrd_create(name, start=None): if start is None: start = int(time.time()) path = rrd_path(name) if not os.path.exists(path): rrdtool.create(path, '--step', '86400', '--start', '%s' % int(start - 10), 'DS:n_packages_gentoo:GAUGE:4294967295:0:U', 'DS:n_packages_overlay:GAUGE:4294967295:0:U', 'DS:n_packages_outdated:GAUGE:4294967295:0:U', 'DS:n_versions_gentoo:GAUGE:4294967295:0:U', 'DS:n_versions_overlay:GAUGE:4294967295:0:U', 'DS:n_versions_upstream:GAUGE:4294967295:0:U', 'RRA:AVERAGE:0.5:1:100', 'RRA:AVERAGE:0.5:5:200', 'RRA:AVERAGE:0.5:10:200') def rrd_update(name, datetime, values): now = time.mktime(datetime.timetuple()) rrd_create(name, now) rrdtool.update( rrd_path(name), '%d:%d:%d:%d:%d:%d:%d' % \ (now, values.n_packages_gentoo, values.n_packages_overlay, values.n_packages_outdated, values.n_versions_gentoo, values.n_versions_overlay, values.n_versions_upstream) ) """ [-s|--start time] [-e|--end time] [-S|--step seconds] [-t|--title string] [-v|--vertical-label string] [-w|--width pixels] [-h|--height pixels] [-j|--only-graph] [-D|--full-size-mode][-u|--upper-limit value] [-l|--lower-limit value] [-u|--upper-limit value] [-l|--lower-limit value] [-r|--rigid] [-A|--alt-autoscale] [-M|--alt-autoscale-max] [-J|--alt-autoscale-min] """ def cached_rrd_chart(f): def new_f(*args, **kwds): if 'period' not in kwds: kwds['period'] = '-yearly' name = chart_name(f.func_name, **kwds) path = os.path.join(CHARTS_ROOT, name) if not chart_alive(name): kwds['title'] = '%s (%s)' % (f.func_name, kwds['period']) kwds['steps'] = kwds['period'] kwds['vertical-label'] = f.func_name kwds['rrd'] = rrd_path(rrd_name(**kwds)) rrd_create(kwds['rrd']) # create the rrd file if it's not present kwds['path'] = path kwds['end'] = 'now' if kwds['period'] == '-weekly': kwds['start'] = 'now-4weeks' elif kwds['period'] == '-monthly': kwds['start'] = 'now-12months' else: kwds['start'] = 'now-4years' if '-small' in kwds and kwds['-small']: kwds['width'] = '100' kwds['height'] = '30' kwds['graph-mode'] = '--only-graph' else: kwds['width'] = '500' kwds['height'] = '170' kwds['graph-mode'] = '--full-size-mode' f(*args, **kwds) return name new_f.func_name = f.func_name return new_f @cached_rrd_chart def packages(**kwargs): path = str(kwargs['path']) rrd = kwargs['rrd'] rrdtool.graph( path, '--imgformat', 'PNG', '--width', kwargs['width'], '--height', kwargs['height'], kwargs['graph-mode'], '--color', 'CANVAS#FFFFFF00', '--color', 'BACK#FFFFFF00', '--start', kwargs['start'], '--end', kwargs['end'], '--vertical-label', kwargs['vertical-label'], '--title', kwargs['title'], '--lower-limit', '0', 'DEF:n_packages_gentoo=%s:n_packages_gentoo:AVERAGE' % rrd, 'DEF:n_packages_overlay=%s:n_packages_overlay:AVERAGE' % rrd, 'DEF:n_packages_outdated=%s:n_packages_outdated:AVERAGE' % rrd, 'LINE1.25:n_packages_gentoo#008000:Gentoo', 'LINE1.25:n_packages_overlay#0B17FD:Overlay', 'LINE1.25:n_packages_outdated#FF0000:Outdated' ) @cached_rrd_chart def versions(**kwargs): path = str(kwargs['path']) rrd = kwargs['rrd'] rrdtool.graph( path, '--imgformat', 'PNG', '--width', kwargs['width'], '--height', kwargs['height'], kwargs['graph-mode'], '--color', 'CANVAS#FFFFFF00', '--color', 'BACK#FFFFFF00', '--start', kwargs['start'], '--end', kwargs['end'], '--vertical-label', kwargs['vertical-label'], '--title', kwargs['title'], '--lower-limit', '0', 'DEF:n_versions_gentoo=%s:n_versions_gentoo:AVERAGE' % rrd, 'DEF:n_versions_overlay=%s:n_versions_overlay:AVERAGE' % rrd, 'DEF:n_versions_outdated=%s:n_versions_upstream:AVERAGE' % rrd, 'LINE1.25:n_versions_gentoo#008000:Gentoo', 'LINE1.25:n_versions_overlay#0B17FD:Overlay', 'LINE1.25:n_versions_outdated#FF0000:Outdated' )