Ticket #1685: tahoe_stats

File tahoe_stats, 30.0 KB (added by cl, at 2012-03-13T16:57:40Z)
Line 
1#!/usr/bin/env python
2
3import os
4import pickle
5import re
6import sys
7import time
8import math
9
10STAT_VALIDITY = 300 # 5min limit on reporting stats
11
12'''
13You can essentially have munin graph every statistic that
14is obtainable from http://localhost:3456/statistics . Some,
15but not all, of them, are already preconfigured in a hopefully
16sensible way below. To add a new statistic, simply create a
17new "block" with the appropriate information.
18
19Depending on the type of statistic, different munin graph
20configurations make sense. Some further pointers:
21http://munin-monitoring.org/wiki/HowToWritePlugins
22http://munin-monitoring.org/wiki/fieldname.type
23http://munin-monitoring.org/wiki/fieldname.draw
24http://munin-monitoring.org/wiki/fieldname.warning
25
26You will need to experiment with the configuration until it suits your needs;
27the below configuration may, or may not, be suitable for your setup as it is.
28
29An example: to have munin graph the (aggregated) disk usage and disk free
30statistics of the entire grid:
31
32# ensure that /path/to/tahoe_stats is executable (chmod 755)
33cd /etc/munin/plugins/
34ln -s /path/to/tahoe_stats tahoe_storage_used
35ln -s /path/to/tahoe_stats tahoe_storage_avail
36
37# make sure that some file (it doesn't matter which)
38# contains the env.statsfile setting for each and every
39# plugin that you "enabled" above.
40cd /etc/munin/plugin-conf.d/
41cat tahoe_stats.conf
42[tahoe_storage_used]
43env.statsfile /tmp/tahoe-stats.pickle
44[tahoe_storage_avail]
45env.statsfile /tmp/tahoe-stats.pickle
46
47The plugin filename (in /etc/munin/plugins/), the configuration section name
48in the configuration file, and the key in the PLUGINS variable below must match.
49
50In this example, maybe the tahoe_storage_free is the most interesting one, as it
51shows a few "advanced" features. First, it uses the AREASTACK draw method (instead
52of LINE1), which makes the graph contain areas stacked on top of each other, giving
53information about both individual nodes, and the total grid capacity. Furthermore, it
54contains warning and critical settings (plus a description), which will give visual
55alerts if any node goes below 50GB (warning) or 15GB (critical). See the
56'tahoe_storage_free' plugin entry below for reference on how this is defined.
57
58'''
59PLUGINS = {
60    # LOAD AVERAGE
61    'tahoe_runtime_load_avg':
62        { 'statid': 'load_monitor.avg_load',
63          'category': 'stats',
64          'configheader': '\n'.join(['graph_title Tahoe Runtime Load Average',
65                                     'graph_vlabel load',
66                                     'graph_category tahoe',
67                                     'graph_info This graph shows average reactor delay',
68                                     ]),
69          'graph_config': '\n'.join(['%(name)s.label %(name)s',
70                                     '%(name)s.draw LINE1',
71                                     ]),
72          'graph_render': '\n'.join(['%(name)s.value %(value)s',
73                                     ]),
74        },
75
76    'tahoe_runtime_load_peak':
77        { 'statid': 'load_monitor.max_load',
78          'category': 'stats',
79          'configheader': '\n'.join(['graph_title Tahoe Runtime Load Peak',
80                                     'graph_vlabel load',
81                                     'graph_category tahoe',
82                                     'graph_info This graph shows peak reactor delay',
83                                     ]),
84          'graph_config': '\n'.join(['%(name)s.label %(name)s',
85                                     '%(name)s.draw LINE1',
86                                     ]),
87          'graph_render': '\n'.join(['%(name)s.value %(value)s',
88                                     ]),
89        },
90
91    # STORAGE ALLOCATION (BYTES)
92    'tahoe_storage_consumed':
93        { 'statid': 'storage_server.consumed',
94          'category': 'stats',
95          'configheader': '\n'.join(['graph_title Tahoe Storage Server Space Consumed',
96                                     'graph_vlabel bytes',
97                                     'graph_category tahoe_storage_server',
98                                     'graph_info This graph shows space consumed',
99                                     'graph_args --base 1024',
100                                     ]),
101          'graph_config': '\n'.join(['%(name)s.label %(name)s',
102                                     '%(name)s.draw LINE1',
103                                     ]),
104          'graph_render': '\n'.join(['%(name)s.value %(value)s',
105                                     ]),
106        },
107
108    'tahoe_storage_avail':
109        { 'statid': 'storage_server.disk_avail',
110          'category': 'stats',
111          'configheader': '\n'.join(['graph_title Tahoe Storage Server  Disk Available',
112                                     'graph_vlabel bytes',
113                                     'graph_category tahoe_storage_server',
114                                     'graph_info This graph shows disk available',
115                                     'graph_args --base 1024',
116                                     ]),
117          'graph_config': '\n'.join(['%(name)s.label %(name)s',
118#                                     '%(name)s.draw LINE1',
119                                     '%(name)s.draw AREASTACK',
120                                     '%(name)s.warning 53687091200:',
121                                     '%(name)s.critical 16106127360:',
122                                     '%(name)s.info Warn < 50G, Critical < 15G',
123                                     ]),
124          'graph_render': '\n'.join(['%(name)s.value %(value)s',
125                                     ]),
126        },
127
128    'tahoe_storage_used':
129        { 'statid': 'storage_server.disk_used',
130          'category': 'stats',
131          'configheader': '\n'.join(['graph_title Tahoe Storage Server  Disk Used',
132                                     'graph_vlabel bytes',
133                                     'graph_category tahoe_storage_server',
134                                     'graph_info This graph shows disk used',
135                                     'graph_args --base 1024',
136                                     ]),
137          'graph_config': '\n'.join(['%(name)s.label %(name)s',
138#                                     '%(name)s.draw LINE1',
139                                     '%(name)s.draw AREASTACK',
140                                     ]),
141          'graph_render': '\n'.join(['%(name)s.value %(value)s',
142                                     ]),
143        },
144
145    'tahoe_storage_allocated':
146        { 'statid': 'storage_server.allocated',
147          'category': 'stats',
148          'configheader': '\n'.join(['graph_title Tahoe Storage Server Space Allocated',
149                                     'graph_vlabel bytes',
150                                     'graph_category tahoe_storage_server',
151                                     'graph_info This graph shows space allocated',
152                                     'graph_args --base 1024',
153                                     ]),
154          'graph_config': '\n'.join(['%(name)s.label %(name)s',
155                                     '%(name)s.draw LINE1',
156                                     ]),
157          'graph_render': '\n'.join(['%(name)s.value %(value)s',
158                                     ]),
159        },
160
161    'tahoe_storage_bytes_added':
162        { 'statid': 'storage_server.bytes_added',
163          'category': 'counters',
164          'configheader': '\n'.join(['graph_title Tahoe Storage Server Bytes Added',
165                                     'graph_vlabel bytes',
166                                     'graph_category tahoe_storage_server',
167                                     'graph_info This graph shows cummulative bytes added',
168                                     ]),
169          'graph_config': '\n'.join(['%(name)s.label %(name)s',
170#                                     '%(name)s.type DERIVE',
171                                     '%(name)s.min 0',
172                                     '%(name)s.draw LINE1',
173                                     ]),
174          'graph_render': '\n'.join(['%(name)s.value %(value)s',
175                                     ]),
176        },
177
178    'tahoe_storage_bytes_freed':
179        { 'statid': 'storage_server.bytes_freed',
180          'category': 'counters',
181          'configheader': '\n'.join(['graph_title Tahoe Storage Server Bytes Freed',
182                                     'graph_vlabel bytes',
183                                     'graph_category tahoe_storage_server',
184                                     'graph_info This graph shows cummulative bytes freed',
185                                     ]),
186          'graph_config': '\n'.join(['%(name)s.label %(name)s',
187                                     '%(name)s.draw LINE1',
188                                     ]),
189          'graph_render': '\n'.join(['%(name)s.value %(value)s',
190                                     ]),
191        },
192
193    'tahoe_storage_buckets':
194        { 'statid': 'storage_server.total_bucket_count',
195          'category': 'stats',
196          'configheader': '\n'.join(['graph_title Tahoe Storage Server Total Bucket Count',
197                                     'graph_vlabel buckets',
198                                     'graph_category tahoe_storage_server',
199                                     'graph_info This graph shows the total bucket count',
200                                     ]),
201          'graph_config': '\n'.join(['%(name)s.label %(name)s',
202                                     '%(name)s.draw LINE1',
203                                     ]),
204          'graph_render': '\n'.join(['%(name)s.value %(value)s',
205                                     ]),
206        },
207
208    'tahoe_storage_operations_allocate':
209        { 'statid': 'storage_server.allocate',
210          'category': 'counters',
211          'configheader': '\n'.join(['graph_title Tahoe Storage Server Allocate_Bucket Operations',
212                                     'graph_vlabel operations per second',
213                                     'graph_category tahoe_storage_server',
214                                     'graph_info This graph shows how many allocate_buckets operations occured per second. Each immutable file upload causes one such operation per server.',
215                                     ]),
216          'graph_config': '\n'.join(['%(name)s.label %(name)s',
217                                     '%(name)s.type DERIVE',
218                                     '%(name)s.min 0',
219                                     '%(name)s.draw LINE1',
220                                     ]),
221          'graph_render': '\n'.join(['%(name)s.value %(value)s',
222                                     ]),
223        },
224
225    'tahoe_storage_operations_get':
226        { 'statid': 'storage_server.get',
227          'category': 'counters',
228          'configheader': '\n'.join(['graph_title Tahoe Storage Server get_bucket Operations',
229                                     'graph_vlabel operations per second',
230                                     'graph_category tahoe_storage_server',
231                                     'graph_info This graph shows how many get_bucket operations occured per second. Each immutable file download/check causes one such operation per server.',
232                                     ]),
233          'graph_config': '\n'.join(['%(name)s.label %(name)s',
234                                     '%(name)s.type DERIVE',
235                                     '%(name)s.min 0',
236                                     '%(name)s.draw LINE1',
237                                     ]),
238          'graph_render': '\n'.join(['%(name)s.value %(value)s',
239                                     ]),
240        },
241
242    'tahoe_storage_operations_writev':
243        { 'statid': 'storage_server.writev',
244          'category': 'counters',
245          'configheader': '\n'.join(['graph_title Tahoe Storage Server writev Operations',
246                                     'graph_vlabel operations per second',
247                                     'graph_category tahoe_storage_server',
248                                     'graph_info This graph shows how many writev operations occured per second. Each mutable file / dirnode write causes one such operation per server.',
249                                     ]),
250          'graph_config': '\n'.join(['%(name)s.label %(name)s',
251                                     '%(name)s.type DERIVE',
252                                     '%(name)s.min 0',
253                                     '%(name)s.draw LINE1',
254                                     ]),
255          'graph_render': '\n'.join(['%(name)s.value %(value)s',
256                                     ]),
257        },
258
259    'tahoe_storage_operations_readv':
260        { 'statid': 'storage_server.readv',
261          'category': 'counters',
262          'configheader': '\n'.join(['graph_title Tahoe Storage Server readv Operations',
263                                     'graph_vlabel operations per second',
264                                     'graph_category tahoe_storage_server',
265                                     'graph_info This graph shows how many readv operations occured per second. Each dirnode read causes one such operation per server.',
266                                     ]),
267          'graph_config': '\n'.join(['%(name)s.label %(name)s',
268                                     '%(name)s.type DERIVE',
269                                     '%(name)s.min 0',
270                                     '%(name)s.draw LINE1',
271                                     ]),
272          'graph_render': '\n'.join(['%(name)s.value %(value)s',
273                                     ]),
274        },
275
276
277    # HELPER
278    'tahoe_helper_incoming_files':
279        { 'statid': 'chk_upload_helper.incoming_count',
280          'category': 'stats',
281          'configheader': '\n'.join(['graph_title Tahoe Upload Helper Incoming File Count',
282                                     'graph_vlabel n files',
283                                     'graph_category tahoe_upload_helper',
284                                     'graph_info This graph shows number of incoming files',
285                                     ]),
286          'graph_config': '\n'.join(['%(name)s.label %(name)s',
287                                     '%(name)s.draw LINE1',
288                                     ]),
289          'graph_render': '\n'.join(['%(name)s.value %(value)s',
290                                     ]),
291        },
292    'tahoe_helper_incoming_filesize':
293        { 'statid': 'chk_upload_helper.incoming_size',
294          'category': 'stats',
295          'configheader': '\n'.join(['graph_title Tahoe Upload Helper Incoming File Size',
296                                     'graph_vlabel bytes',
297                                     'graph_category tahoe_upload_helper',
298                                     'graph_info This graph shows total size of incoming files',
299                                     ]),
300          'graph_config': '\n'.join(['%(name)s.label %(name)s',
301                                     '%(name)s.draw LINE2',
302                                     ]),
303          'graph_render': '\n'.join(['%(name)s.value %(value)s',
304                                     ]),
305        },
306    'tahoe_helper_incoming_files_old':
307        { 'statid': 'chk_upload_helper.incoming_size_old',
308          'category': 'stats',
309          'configheader': '\n'.join(['graph_title Tahoe Upload Helper Incoming Old Files',
310                                     'graph_vlabel bytes',
311                                     'graph_category tahoe_upload_helper',
312                                     'graph_info This graph shows total size of old incoming files',
313                                     ]),
314          'graph_config': '\n'.join(['%(name)s.label %(name)s',
315                                     '%(name)s.draw LINE1',
316                                     ]),
317          'graph_render': '\n'.join(['%(name)s.value %(value)s',
318                                     ]),
319        },
320
321    'tahoe_helper_encoding_files':
322        { 'statid': 'chk_upload_helper.encoding_count',
323          'category': 'stats',
324          'configheader': '\n'.join(['graph_title Tahoe Upload Helper Encoding File Count',
325                                     'graph_vlabel n files',
326                                     'graph_category tahoe_upload_helper',
327                                     'graph_info This graph shows number of encoding files',
328                                     ]),
329          'graph_config': '\n'.join(['%(name)s.label %(name)s',
330                                     '%(name)s.draw LINE1',
331                                     ]),
332          'graph_render': '\n'.join(['%(name)s.value %(value)s',
333                                     ]),
334        },
335    'tahoe_helper_encoding_filesize':
336        { 'statid': 'chk_upload_helper.encoding_size',
337          'category': 'stats',
338          'configheader': '\n'.join(['graph_title Tahoe Upload Helper Encoding File Size',
339                                     'graph_vlabel bytes',
340                                     'graph_category tahoe_upload_helper',
341                                     'graph_info This graph shows total size of encoding files',
342                                     ]),
343          'graph_config': '\n'.join(['%(name)s.label %(name)s',
344                                     '%(name)s.draw AREA',
345                                     ]),
346          'graph_render': '\n'.join(['%(name)s.value %(value)s',
347                                     ]),
348        },
349    'tahoe_helper_encoding_files_old':
350        { 'statid': 'chk_upload_helper.encoding_size_old',
351          'category': 'stats',
352          'configheader': '\n'.join(['graph_title Tahoe Upload Helper Encoding Old Files',
353                                     'graph_vlabel bytes',
354                                     'graph_category tahoe_upload_helper',
355                                     'graph_info This graph shows total size of old encoding files',
356                                     ]),
357          'graph_config': '\n'.join(['%(name)s.label %(name)s',
358                                     '%(name)s.draw LINE1',
359                                     ]),
360          'graph_render': '\n'.join(['%(name)s.value %(value)s',
361                                     ]),
362        },
363
364    'tahoe_helper_active_uploads':
365        { 'statid': 'chk_upload_helper.active_uploads',
366          'category': 'stats',
367          'configheader': '\n'.join(['graph_title Tahoe Upload Helper Active Files',
368                                     'graph_vlabel n files',
369                                     'graph_category tahoe_upload_helper',
370                                     'graph_info This graph shows number of files actively being processed by the helper',
371                                     ]),
372          'graph_config': '\n'.join(['%(name)s.label %(name)s',
373                                     '%(name)s.draw AREASTACK',
374                                     ]),
375          'graph_render': '\n'.join(['%(name)s.value %(value)s',
376                                     ]),
377        },
378
379    'tahoe_helper_upload_requests':
380        { 'statid': 'chk_upload_helper.upload_requests',
381          'category': 'counters',
382          'configheader': '\n'.join(['graph_title Tahoe Upload Helper Upload Requests',
383                                     'graph_vlabel requests',
384                                     'graph_category tahoe_upload_helper',
385                                     'graph_info This graph shows the number of upload requests arriving at the helper',
386                                     ]),
387          'graph_config': '\n'.join(['%(name)s.label %(name)s',
388                                     '%(name)s.type DERIVE',
389                                     '%(name)s.min 0',
390                                     '%(name)s.draw LINE1',
391                                     ]),
392          'graph_render': '\n'.join(['%(name)s.value %(value)s',
393                                     ]),
394        },
395    'tahoe_helper_upload_already_present':
396        { 'statid': 'chk_upload_helper.upload_already_present',
397          'category': 'counters',
398          'configheader': '\n'.join(['graph_title Tahoe Upload Helper Uploads Already Present',
399                                     'graph_vlabel requests',
400                                     'graph_category tahoe_upload_helper',
401                                     'graph_info This graph shows the number of uploads whose files are already present in the grid',
402                                     ]),
403          'graph_config': '\n'.join(['%(name)s.label %(name)s',
404                                     '%(name)s.type DERIVE',
405                                     '%(name)s.min 0',
406                                     '%(name)s.draw LINE1',
407                                     ]),
408          'graph_render': '\n'.join(['%(name)s.value %(value)s',
409                                     ]),
410        },
411    'tahoe_helper_upload_need_upload':
412        { 'statid': 'chk_upload_helper.upload_need_upload',
413          'category': 'counters',
414          'configheader': '\n'.join(['graph_title Tahoe Upload Helper Uploads Needing Upload',
415                                     'graph_vlabel requests',
416                                     'graph_category tahoe_upload_helper',
417                                     'graph_info This graph shows the number of uploads whose files are not already present in the grid',
418                                     ]),
419          'graph_config': '\n'.join(['%(name)s.label %(name)s',
420                                     '%(name)s.type DERIVE',
421                                     '%(name)s.min 0',
422                                     '%(name)s.draw LINE1',
423                                     ]),
424          'graph_render': '\n'.join(['%(name)s.value %(value)s',
425                                     ]),
426        },
427    'tahoe_helper_encoded_bytes':
428        { 'statid': 'chk_upload_helper.encoded_bytes',
429          'category': 'counters',
430          'configheader': '\n'.join(['graph_title Tahoe Upload Helper Encoded Bytes',
431                                     'graph_vlabel bytes',
432                                     'graph_category tahoe_upload_helper',
433                                     'graph_info This graph shows the number of bytes encoded by the helper',
434                                     ]),
435          'graph_config': '\n'.join(['%(name)s.label %(name)s',
436                                     '%(name)s.type DERIVE',
437                                     '%(name)s.min 0',
438                                     '%(name)s.draw LINE1',
439                                     ]),
440          'graph_render': '\n'.join(['%(name)s.value %(value)s',
441                                     ]),
442        },
443    'tahoe_helper_fetched_bytes':
444        { 'statid': 'chk_upload_helper.fetched_bytes',
445          'category': 'counters',
446          'configheader': '\n'.join(['graph_title Tahoe Upload Helper Fetched Bytes',
447                                     'graph_vlabel bytes',
448                                     'graph_category tahoe_upload_helper',
449                                     'graph_info This graph shows the number of bytes fetched by the helper',
450                                     ]),
451          'graph_config': '\n'.join(['%(name)s.label %(name)s',
452                                     '%(name)s.type DERIVE',
453                                     '%(name)s.min 0',
454                                     '%(name)s.draw LINE1',
455                                     ]),
456          'graph_render': '\n'.join(['%(name)s.value %(value)s',
457                                     ]),
458        },
459
460    # WEBAPI
461    'tahoe_uploader_bytes_uploaded':
462        { 'statid': 'uploader.bytes_uploaded',
463          'category': 'counters',
464          'configheader': '\n'.join(['graph_title Tahoe Uploader Bytes Uploaded',
465                                     'graph_vlabel bytes',
466                                     'graph_category tahoe_traffic',
467                                     'graph_info This graph shows the number of bytes uploaded',
468                                     ]),
469          'graph_config': '\n'.join(['%(name)s.label %(name)s',
470                                     '%(name)s.type DERIVE',
471#                                     '%(name)s.min 0',
472#                                     '%(name)s.draw LINE1',
473                                     '%(name)s.draw AREASTACK',
474                                     ]),
475          'graph_render': '\n'.join(['%(name)s.value %(value)s',
476                                     ]),
477        },
478    'tahoe_uploader_files_uploaded':
479        { 'statid': 'uploader.files_uploaded',
480          'category': 'counters',
481          'configheader': '\n'.join(['graph_title Tahoe Uploader Files Uploaded',
482                                     'graph_vlabel files',
483                                     'graph_category tahoe_traffic',
484                                     'graph_info This graph shows the number of files uploaded',
485                                     ]),
486          'graph_config': '\n'.join(['%(name)s.label %(name)s',
487#                                     '%(name)s.type DERIVE',
488                                     '%(name)s.min 0',
489                                     '%(name)s.draw LINE1',
490                                     ]),
491          'graph_render': '\n'.join(['%(name)s.value %(value)s',
492                                     ]),
493        },
494    'tahoe_downloader_bytes_downloaded':
495        { 'statid': 'downloader.bytes_downloaded',
496          'category': 'counters',
497          'configheader': '\n'.join(['graph_title Tahoe Downloader Bytes Downloaded',
498                                     'graph_vlabel bytes',
499                                     'graph_category tahoe_traffic',
500                                     'graph_info This graph shows the number of bytes downloaded',
501                                     ]),
502          'graph_config': '\n'.join(['%(name)s.label %(name)s',
503                                     '%(name)s.type DERIVE',
504#                                     '%(name)s.min 0',
505#                                     '%(name)s.draw LINE1',
506                                     '%(name)s.draw AREASTACK',
507                                     ]),
508          'graph_render': '\n'.join(['%(name)s.value %(value)s',
509                                     ]),
510        },
511    'tahoe_downloader_files_downloaded':
512        { 'statid': 'uploader.files_downloaded',
513          'category': 'counters',
514          'configheader': '\n'.join(['graph_title Tahoe Downloader Files Downloaded',
515                                     'graph_vlabel files',
516                                     'graph_category tahoe_traffic',
517                                     'graph_info This graph shows the number of files downloaded',
518                                     ]),
519          'graph_config': '\n'.join(['%(name)s.label %(name)s',
520#                                     '%(name)s.type DERIVE',
521                                     '%(name)s.min 0',
522                                     '%(name)s.draw LINE1',
523                                     ]),
524          'graph_render': '\n'.join(['%(name)s.value %(value)s',
525                                     ]),
526        },
527    'tahoe_mutable_files_published':
528        { 'statid': 'mutable.files_published',
529          'category': 'counters',
530          'configheader': '\n'.join(['graph_title Tahoe Mutable Files Published',
531                                     'graph_vlabel files',
532                                     'graph_category tahoe_traffic',
533                                     'graph_info This graph shows the number of mutable files published',
534                                     ]),
535          'graph_config': '\n'.join(['%(name)s.label %(name)s',
536                                     '%(name)s.type DERIVE',
537                                     '%(name)s.min 0',
538                                     '%(name)s.draw LINE1',
539                                     ]),
540          'graph_render': '\n'.join(['%(name)s.value %(value)s',
541                                     ]),
542        },
543    'tahoe_mutable_files_retrieved':
544        { 'statid': 'mutable.files_retrieved',
545          'category': 'counters',
546          'configheader': '\n'.join(['graph_title Tahoe Mutable Files Retrieved',
547                                     'graph_vlabel files',
548                                     'graph_category tahoe_traffic',
549                                     'graph_info This graph shows the number of files retrieved',
550                                     ]),
551          'graph_config': '\n'.join(['%(name)s.label %(name)s',
552                                     '%(name)s.type DERIVE',
553                                     '%(name)s.min 0',
554                                     '%(name)s.draw LINE1',
555                                     ]),
556          'graph_render': '\n'.join(['%(name)s.value %(value)s',
557                                     ]),
558        },
559
560    }
561
562# This will slightly "obfuscate" node names that contain
563# an email address (as is the convention on VolunteerGrid2)
564def smash_name(name):
565    name = re.sub('@([^\\.])+','@***',name)
566    name = re.sub('[^a-zA-Z0-9@\\*-]', '_', name)
567    return name
568
569def open_stats(fname):
570    f = open(fname, 'rb')
571    stats = pickle.load(f)
572    f.close()
573    return stats
574
575def main(argv):
576    graph_name = os.path.basename(argv[0])
577    if graph_name.endswith('.py'):
578        graph_name = graph_name[:-3]
579
580    plugin_conf = PLUGINS.get(graph_name)
581
582    for k,v in os.environ.items():
583        if k.startswith('statsfile'):
584            stats_file = v
585            break
586    else:
587        raise RuntimeError("No 'statsfile' env var found")
588
589    stats = open_stats(stats_file)
590
591    now = time.time()
592    def output_nodes(output_section, check_time):
593        pairs = dict([(smash_name("%s-%s" % (k[:4], v['nickname'])), k) for (k, v) in stats.iteritems()])
594        for name in sorted(pairs.keys()):
595            tubid = pairs.get(name)
596            nodestats = stats.get(tubid)
597            if check_time and math.fabs(now - nodestats.get('timestamp', 0)) > STAT_VALIDITY:
598                continue
599            category = plugin_conf['category']
600            statid = plugin_conf['statid']
601            value = nodestats['stats'][category].get(statid)
602            if value is not None:
603                args = { 'name': name, 'value': value }
604                print plugin_conf[output_section] % args
605
606    if len(argv) > 1:
607        if sys.argv[1] == 'config':
608            print plugin_conf['configheader']
609            output_nodes('graph_config', False)
610            sys.exit(0)
611
612    output_nodes('graph_render', True)
613
614if __name__ == '__main__':
615    main(sys.argv)