159d9e6b90b56cba0ba07892f0bafcc4bc3fa79e
[collectd.git] / contrib / collection.cgi
1 #!/usr/bin/perl
2
3 use strict;
4 use warnings;
5
6 use Carp (qw(cluck confess));
7 use CGI (':cgi');
8 use CGI::Carp ('fatalsToBrowser');
9 use HTML::Entities ('encode_entities');
10 use URI::Escape ('uri_escape');
11 use RRDs ();
12 use Data::Dumper ();
13
14 our $Config = "/etc/collection.conf";
15 our @DataDirs = ();
16 our $LibDir;
17
18 our $ValidTimespan =
19 {
20   hour => 3600,
21   day => 86400,
22   week => 7 * 86400,
23   month => 31 * 86400,
24   year => 366 * 86400
25 };
26
27 our @RRDDefaultArgs = ('-w', '400');
28
29 our $Args = {};
30
31 our $GraphDefs;
32 our $MetaGraphDefs = {};
33 load_graph_definitions ();
34
35 for (qw(action host plugin plugin_instance type type_instance timespan))
36 {
37         $Args->{$_} = param ($_);
38 }
39
40 exit (main ());
41
42 sub read_config
43 {
44         my $fh;
45         open ($fh, "< $Config") or confess ("open ($Config): $!");
46         while (my $line = <$fh>)
47         {
48                 chomp ($line);
49                 next if (!$line);
50                 next if ($line =~ m/^\s*#/);
51                 next if ($line =~ m/^\s*$/);
52
53                 my $key;
54                 my $value;
55
56                 if ($line =~ m/^([A-Za-z]+):\s*"((?:[^"\\]+|\\.)*)"$/)
57                 {
58                         $key = lc ($1); $value = $2;
59                         $value =~ s/\\(.)/$1/g;
60                 }
61                 elsif ($line =~ m/([A-Za-z]+):\s*([0-9]+)$/)
62                 {
63                         $key = lc ($1); $value = 0 + $2;
64                 }
65                 else
66                 {
67                         print STDERR "Cannot parse line: $line\n";
68                         next;
69                 }
70
71                 if ($key eq 'datadir')
72                 {
73                         $value =~ s#/*$##;
74                         push (@DataDirs, $value);
75                 }
76                 elsif ($key eq 'libdir')
77                 {
78                         $value =~ s#/*$##;
79                         $LibDir = $value;
80                 }
81                 else
82                 {
83                         print STDERR "Unknown key: $key\n";
84                 }
85         }
86         close ($fh);
87 } # read_config
88
89 sub validate_args
90 {
91         if ($Args->{'action'} && ($Args->{'action'} =~ m/^(overview|show_host|show_plugin|show_type|show_graph)$/))
92         {
93                 $Args->{'action'} = $1;
94         }
95         else
96         {
97                 $Args->{'action'} = 'overview';
98         }
99
100         if ($Args->{'host'} && ($Args->{'host'} =~ m#/#))
101         {
102                 delete ($Args->{'host'});
103         }
104
105         if ($Args->{'plugin'} && ($Args->{'plugin'} =~ m#/#))
106         {
107                 delete ($Args->{'plugin'});
108         }
109
110         if ($Args->{'type'} && ($Args->{'type'} =~ m#/#))
111         {
112                 delete ($Args->{'type'});
113         }
114
115         if (!$Args->{'plugin'} || ($Args->{'plugin_instance'}
116                 && ($Args->{'plugin_instance'} =~ m#/#)))
117         {
118                 delete ($Args->{'plugin_instance'});
119         }
120
121         if (!$Args->{'type'} || ($Args->{'type_instance'}
122                 && ($Args->{'type_instance'} =~ m#/#)))
123         {
124                 delete ($Args->{'type_instance'});
125         }
126
127         if (defined ($Args->{'timespan'})
128           && ($Args->{'timespan'} =~ m/^(hour|day|week|month|year)$/))
129         {
130           $Args->{'timespan'} = $1;
131         }
132         else
133         {
134           $Args->{'timespan'} = 'day';
135         }
136 } # validate_args
137
138 {
139   my $hosts;
140   sub _find_hosts
141   {
142     if (defined ($hosts))
143     {
144       return (keys %$hosts);
145     }
146
147     $hosts = {};
148
149     for (my $i = 0; $i < @DataDirs; $i++)
150     {
151       my @tmp;
152       my $dh;
153
154       opendir ($dh, $DataDirs[$i]) or next;
155       @tmp = grep { ($_ !~ m/^\./) && (-d $DataDirs[$i] . '/' . $_) } (readdir ($dh));
156       closedir ($dh);
157
158       $hosts->{$_} = 1 for (@tmp);
159     } # for (@DataDirs)
160
161     return (keys %$hosts);
162   } # _find_hosts
163 }
164
165 sub _get_param_host
166 {
167   my %all_hosts = map { $_ => 1 } (_find_hosts ());
168   my @selected_hosts = ();
169   for (param ('host'))
170   {
171     if (defined ($all_hosts{$_}))
172     {
173       push (@selected_hosts, "$_");
174     }
175   }
176   return (@selected_hosts);
177 } # _get_param_host
178
179 sub _get_param_timespan
180 {
181   my $timespan = param ('timespan');
182
183   $timespan ||= 'day';
184   $timespan = lc ($timespan);
185
186   if (!defined ($ValidTimespan->{$timespan}))
187   {
188     $timespan = 'day';
189   }
190
191   return ($timespan);
192 } # _get_param_timespan
193
194 sub _find_plugins
195 {
196   my $host = shift;
197   my %plugins = ();
198
199   for (my $i = 0; $i < @DataDirs; $i++)
200   {
201     my $dir = $DataDirs[$i] . "/$host";
202     my @tmp;
203     my $dh;
204
205     opendir ($dh, $dir) or next;
206     @tmp = grep { ($_ !~ m/^\./) && (-d "$dir/$_") } (readdir ($dh));
207     closedir ($dh);
208
209     for (@tmp)
210     {
211       my ($plugin, $instance) = split (m/-/, $_, 2);
212       $plugins{$plugin} = [] if (!$plugins{$plugin});
213       push (@{$plugins{$plugin}}, $instance) if (defined ($instance));
214     }
215   } # for (@DataDirs)
216
217   return (%plugins);
218 } # _find_plugins
219
220 sub _find_types
221 {
222   my $host = shift;
223   my $plugin = shift;
224   my $plugin_instance = shift;
225   my %types = ();
226
227   for (my $i = 0; $i < @DataDirs; $i++)
228   {
229     my $dir = $DataDirs[$i] . "/$host/$plugin" . (defined ($plugin_instance) ? "-$plugin_instance" : '');
230     my @tmp;
231     my $dh;
232
233     opendir ($dh, $dir) or next;
234     @tmp = grep { ($_ !~ m/^\./) && ($_ =~ m/\.rrd$/i) && (-f "$dir/$_") } (readdir ($dh));
235     closedir ($dh);
236
237     for (@tmp)
238     {
239       my $name = "$_";
240       $name =~ s/\.rrd$//i;
241       my ($type, $instance) = split (m/-/, $name, 2);
242       $types{$type} = [] if (!$types{$type});
243       push (@{$types{$type}}, $instance) if (defined ($instance));
244     }
245   } # for (@DataDirs)
246
247   return (%types);
248 } # _find_types
249
250 sub _find_files_for_host
251 {
252   my $host = shift;
253   my $ret = {};
254
255   my %plugins = _find_plugins ($host);
256   for (keys %plugins)
257   {
258     my $plugin = $_;
259     my $plugin_instances = $plugins{$plugin};
260
261     if (!$plugin_instances || !@$plugin_instances)
262     {
263       $plugin_instances = ['-'];
264     }
265
266     $ret->{$plugin} = {};
267
268     for (@$plugin_instances)
269     {
270       my $plugin_instance = $_;
271       my %types = _find_types ($host, $plugin,
272         ($plugin_instance ne '-') ? $plugin_instance : undef);
273
274       $ret->{$plugin}{$plugin_instance} = {};
275
276       for (keys %types)
277       {
278         my $type = $_;
279         my $type_instances = $types{$type};
280
281         $ret->{$plugin}{$plugin_instance}{$type} = {};
282
283         for (@$type_instances)
284         {
285           $ret->{$plugin}{$plugin_instance}{$type}{$_} = 1;
286         }
287
288         if (!@$type_instances)
289         {
290           $ret->{$plugin}{$plugin_instance}{$type}{'-'} = 1;
291         }
292       } # for (keys %types)
293     } # for (@$plugin_instances)
294   } # for (keys %plugins)
295
296   return ($ret);
297 } # _find_files_for_host
298
299 sub _find_files_for_hosts
300 {
301   my @hosts = @_;
302   my $all_plugins = {};
303
304   for (my $i = 0; $i < @hosts; $i++)
305   {
306     my $tmp = _find_files_for_host ($hosts[$i]);
307     _files_union ($all_plugins, $tmp);
308   }
309
310   return ($all_plugins);
311 } # _find_files_for_hosts
312
313 sub _files_union
314 {
315   my $dest = shift;
316   my $src = shift;
317
318   for (keys %$src)
319   {
320     my $plugin = $_;
321     $dest->{$plugin} ||= {};
322
323     for (keys %{$src->{$plugin}})
324     {
325       my $pinst = $_;
326       $dest->{$plugin}{$pinst} ||= {};
327
328       for (keys %{$src->{$plugin}{$pinst}})
329       {
330         my $type = $_;
331         $dest->{$plugin}{$pinst}{$type} ||= {};
332
333         for (keys %{$src->{$plugin}{$pinst}{$type}})
334         {
335           my $tinst = $_;
336           $dest->{$plugin}{$pinst}{$type}{$tinst} = 1;
337         }
338       }
339     }
340   }
341 } # _files_union
342
343 sub _files_plugin_inst_count
344 {
345   my $src = shift;
346   my $i = 0;
347
348   for (keys %$src)
349   {
350     if (exists ($MetaGraphDefs->{$_}))
351     {
352       $i++;
353     }
354     else
355     {
356       $i = $i + keys %{$src->{$_}};
357     }
358   }
359   return ($i);
360 } # _files_plugin_count
361
362 sub list_hosts
363 {
364   my @hosts = _find_hosts ();
365   @hosts = sort (@hosts);
366
367   print "<ul>\n";
368   for (my $i = 0; $i < @hosts; $i++)
369   {
370     my $host_html = encode_entities ($hosts[$i]);
371     my $host_url = uri_escape ($hosts[$i]);
372
373     print qq(  <li><a href="${\script_name ()}?action=show_host;host=$host_url">$host_html</a></li>\n);
374   }
375   print "</ul>\n";
376 } # list_hosts
377
378 sub _string_to_color
379 {
380   my $color = shift;
381   if ($color =~ m/([0-9A-Fa-f][0-9A-Fa-f])([0-9A-Fa-f][0-9A-Fa-f])([0-9A-Fa-f][0-9A-Fa-f])/)
382   {
383     return ([hex ($1) / 255.0, hex ($2) / 255.0, hex ($3) / 255.0]);
384   }
385   return;
386 } # _string_to_color
387
388 sub _color_to_string
389 {
390   confess ("Wrong number of arguments") if (@_ != 1);
391   return (sprintf ('%02hx%02hx%02hx', map { int (255.0 * $_) } @{$_[0]}));
392 } # _color_to_string
393
394 sub _get_random_color
395 {
396   my ($r, $g, $b) = (rand (), rand ());
397   my $min = 0.0;
398   my $max = 1.0;
399
400   if (($r + $g) < 1.0)
401   {
402     $min = 1.0 - ($r + $g);
403   }
404   else
405   {
406     $max = 2.0 - ($r + $g);
407   }
408
409   $b = $min + (rand () * ($max - $min));
410
411   return ([$r, $g, $b]);
412 } # _get_random_color
413
414 sub _get_faded_color
415 {
416   my $fg = shift;
417   my $bg;
418   my %opts = @_;
419   my $ret = [undef, undef, undef];
420
421   $opts{'background'} ||= [1.0, 1.0, 1.0];
422   $opts{'alpha'} ||= 0.25;
423
424   if (!ref ($opts{'background'}))
425   {
426     $opts{'background'} = _string_to_color ($opts{'background'})
427       or confess ("Cannot parse background color " . $opts{'background'});
428   }
429   $bg = $opts{'background'};
430
431   for (my $i = 0; $i < 3; $i++)
432   {
433     $ret->[$i] = ($opts{'alpha'} * $fg->[$i])
434        + ((1.0 - $opts{'alpha'}) * $bg->[$i]);
435   }
436
437   return ($ret);
438 } # _get_faded_color
439
440 sub _custom_sort_arrayref
441 {
442   my $array_ref = shift;
443   my $array_sort = shift;
444
445   my %elements = map { $_ => 1 } (@$array_ref);
446   splice (@$array_ref, 0);
447
448   for (@$array_sort)
449   {
450     next if (!exists ($elements{$_}));
451     push (@$array_ref, $_);
452     delete ($elements{$_});
453   }
454   push (@$array_ref, sort (keys %elements));
455 } # _custom_sort_arrayref
456
457 sub action_show_host
458 {
459   my @hosts = _get_param_host ();
460   @hosts = sort (@hosts);
461
462   my $all_plugins = {};
463   my $plugins_per_host = {};
464
465   my $timespan = _get_param_timespan ();
466
467   for (my $i = 0; $i < @hosts; $i++)
468   {
469     $plugins_per_host->{$hosts[$i]} = _find_files_for_host ($hosts[$i]);
470     _files_union ($all_plugins, $plugins_per_host->{$hosts[$i]});
471   }
472
473   my $param_host = join (";", map { "host=" . encode_entities ($_) } (@hosts));
474
475   print '<!-- ', Data::Dumper->Dump ([$all_plugins], ['all_plugins']), " -->\n";
476
477   my @plugins = sort (keys %$all_plugins);
478
479   print qq(    <div><a href="${\script_name ()}?action=overview">Back to list of hosts</a></div>\n);
480
481   print <<HTML;
482     <table class="graphs">
483       <tr>
484         <th>Plugin</th>
485 HTML
486   for (my $i = 0; $i < @hosts; $i++)
487   {
488     print "\t<th>", encode_entities ($hosts[$i]), "</th>\n";
489   }
490   print "      </tr>\n";
491   for (my $i = 0; $i < @plugins; $i++)
492   {
493     my $plugin = $plugins[$i];
494     my $plugin_esc = encode_entities ($plugins[$i]);
495
496     my @pinsts = sort (keys %{$all_plugins->{$plugin}});
497
498     for (my $j = 0; $j < @pinsts; $j++)
499     {
500       my $pinst = $pinsts[$j];
501       my $pinst_esc = encode_entities ($pinst);
502       my $title = $plugin . ($pinst ne '-' ? " ($pinst)" : '');
503       my $title_esc = encode_entities ($title);
504
505       my $param_plugin = "plugin=$plugin_esc";
506       if ($pinst ne '-')
507       {
508         $param_plugin .= ";plugin_instance=$pinst_esc";
509       }
510
511       my $files_printed = 0;
512       my $files_num = _files_plugin_inst_count ($all_plugins->{$plugin}{$pinst});
513       next if (!$files_num);
514
515       my $rowspan = ($files_num == 1) ? '' : qq( rowspan="$files_num");
516
517       for (sort (keys %{$all_plugins->{$plugin}{$pinst}}))
518       {
519         my $type = $_;
520         my $type_esc = encode_entities ($type);
521
522         if (exists ($MetaGraphDefs->{$type}))
523         {
524           my $param_type = "type=$type_esc";
525
526           print "      <tr>\n";
527           if ($files_printed == 0)
528           {
529             print "\t<td$rowspan>$title_esc</td>\n";
530           }
531
532           for (my $k = 0; $k < @hosts; $k++)
533           {
534             my $host = $hosts[$k];
535             my $host_esc = encode_entities ($host);
536
537             print "\t<td>";
538             if (exists $plugins_per_host->{$host}{$plugin}{$pinst}{$type})
539             {
540               #print qq(<img src="${\script_name ()}?action=show_graph;host=$host_esc;$param_plugin;$param_type;timespan=$timespan" />);
541               print encode_entities (qq(<img src="${\script_name ()}?action=show_graph;host=$host_esc;$param_plugin;$param_type;timespan=$timespan" />));
542             }
543             print "</td>\n";
544           } # for (my $k = 0; $k < @hosts; $k++)
545
546           print "      </tr>\n";
547
548           $files_printed++;
549           next; # pinst
550         }
551
552         for (sort (keys %{$all_plugins->{$plugin}{$pinst}{$type}}))
553         {
554           my $tinst = $_;
555           my $tinst_esc = encode_entities ($tinst);
556
557           my $param_type = "type=$type_esc";
558           if ($tinst ne '-')
559           {
560             $param_type .= ";type_instance=$tinst_esc";
561           }
562
563           print "      <tr>\n";
564           if ($files_printed == 0)
565           {
566             print "\t<td$rowspan>$title_esc</td>\n";
567           }
568
569           for (my $k = 0; $k < @hosts; $k++)
570           {
571             my $host = $hosts[$k];
572             my $host_esc = encode_entities ($host);
573
574             print "\t<td>";
575             if ($plugins_per_host->{$host}{$plugin}{$pinst}{$type}{$tinst})
576             {
577               #print qq(<img src="${\script_name ()}?action=show_graph;host=$host_esc;$param_plugin;$param_type;timespan=$timespan" />);
578               print encode_entities (qq(<img src="${\script_name ()}?action=show_graph;host=$host_esc;$param_plugin;$param_type;timespan=$timespan" />));
579             }
580             print "</td>\n";
581           } # for (my $k = 0; $k < @hosts; $k++)
582
583           print "      </tr>\n";
584
585           $files_printed++;
586         } # for ($tinst)
587       } # for ($type)
588     } # for (my $j = 0; $j < @pinsts; $j++)
589   } # for (my $i = 0; $i < @plugins; $i++)
590   print "   </table>\n";
591 } # action_show_host
592
593 sub action_show_plugin
594 {
595   my @hosts = _get_param_host ();
596   my $plugin = shift;
597   my $plugin_instance = shift;
598   my $timespan = _get_param_timespan ();
599
600   my $hosts_url = join (';', map { 'host=' . uri_escape ($_) } (@hosts));
601   my $plugin_esc = encode_entities ($plugin);
602   my $plugin_url = uri_escape ($plugin);
603   my $plugin_instance_url = defined ($plugin_instance) ? uri_escape ($plugin_instance) : undef;
604
605   my $all_plugins = {};
606   my $plugins_per_host = {};
607
608   for (my $i = 0; $i < @hosts; $i++)
609   {
610     $plugins_per_host->{$hosts[$i]} = _find_files_for_host ($hosts[$i]);
611     _files_union ($all_plugins, $plugins_per_host->{$hosts[$i]});
612   }
613
614   my $url_prefix = script_name () . "?$hosts_url;plugin=$plugin_url";
615   $url_prefix .= ";plugin_instance=$plugin_instance_url" if (defined ($plugin_instance));
616
617   print qq(    <div><a href="${\script_name ()}?action=show_host;$hosts_url">Back to list of plugins</a></div>\n);
618
619   if (!defined ($all_plugins->{$plugin}))
620   {
621     print qq(    <div class="error">Plugin &quot;${\encode_entities ($plugin)}&quot; not found for host &quot;${\encode_entities (@hosts)}&quot;.</div>\n);
622     return;
623   }
624
625   my @pinsts = sort (keys %{$all_plugins->{$plugin}});
626
627   print <<HTML;
628     <table class="graphs">
629       <tr>
630         <th>Plugin</th>
631 HTML
632   for (my $i = 0; $i < @hosts; $i++)
633   {
634     print "\t<th>", encode_entities ($hosts[$i]), "</th>\n";
635   }
636   print "      </tr>\n";
637
638   for (my $j = 0; $j < @pinsts; $j++)
639   {
640     my $pinst = $pinsts[$j];
641     my $pinst_esc = encode_entities ($pinst);
642     my $title = $plugin . ($pinst ne '-' ? " ($pinst)" : '');
643     my $title_esc = encode_entities ($title);
644
645     my $param_plugin = "plugin=$plugin_esc";
646     if ($pinst ne '-')
647     {
648       $param_plugin .= ";plugin_instance=$pinst_esc";
649     }
650
651     my $files_printed = 0;
652     my $files_num = _files_plugin_inst_count ($all_plugins->{$plugin}{$pinst});
653     next if (!$files_num);
654
655     my $rowspan = ($files_num == 1) ? '' : qq( rowspan="$files_num");
656
657     for (sort (keys %{$all_plugins->{$plugin}{$pinst}}))
658     {
659       my $type = $_;
660       my $type_esc = encode_entities ($type);
661
662       if (exists ($MetaGraphDefs->{$type}))
663       {
664         my $param_type = "type=$type_esc";
665
666         print "      <tr>\n";
667         if ($files_printed == 0)
668         {
669           print "\t<td$rowspan>$title_esc</td>\n";
670         }
671
672         for (my $k = 0; $k < @hosts; $k++)
673         {
674           my $host = $hosts[$k];
675           my $host_esc = encode_entities ($host);
676
677           print "\t<td>";
678           if (exists $plugins_per_host->{$host}{$plugin}{$pinst}{$type})
679           {
680             print qq(<img src="${\script_name ()}?action=show_graph;host=$host_esc;$param_plugin;$param_type;timespan=$timespan" />);
681             #print encode_entities (qq(<img src="${\script_name ()}?action=show_graph;host=$host_esc;$param_plugin;$param_type;timespan=$timespan" />));
682           }
683           print "</td>\n";
684         } # for (my $k = 0; $k < @hosts; $k++)
685
686         print "      </tr>\n";
687
688         $files_printed++;
689         next; # pinst
690       }
691
692       for (sort (keys %{$all_plugins->{$plugin}{$pinst}{$type}}))
693       {
694         my $tinst = $_;
695         my $tinst_esc = encode_entities ($tinst);
696
697         my $param_type = "type=$type_esc";
698         if ($tinst ne '-')
699         {
700           $param_type .= ";type_instance=$tinst_esc";
701         }
702
703         print "      <tr>\n";
704         if ($files_printed == 0)
705         {
706           print "\t<td$rowspan>$title_esc</td>\n";
707         }
708
709         for (my $k = 0; $k < @hosts; $k++)
710         {
711           my $host = $hosts[$k];
712           my $host_esc = encode_entities ($host);
713
714           print "\t<td>";
715           if ($plugins_per_host->{$host}{$plugin}{$pinst}{$type}{$tinst})
716           {
717             print qq(<img src="${\script_name ()}?action=show_graph;host=$host_esc;$param_plugin;$param_type;timespan=$timespan" />);
718             #print encode_entities (qq(<img src="${\script_name ()}?action=show_graph;host=$host_esc;$param_plugin;$param_type;timespan=$timespan" />));
719           }
720           print "</td>\n";
721         } # for (my $k = 0; $k < @hosts; $k++)
722
723         print "      </tr>\n";
724
725         $files_printed++;
726       } # for ($tinst)
727     } # for ($type)
728   } # for (my $j = 0; $j < @pinsts; $j++)
729   print "   </table>\n";
730 } # action_show_plugin
731
732 sub action_show_type
733 {
734   my $host = shift;
735   my $plugin = shift;
736   my $plugin_instance = shift;
737   my $type = shift;
738   my $type_instance = shift;
739
740   my $host_url = uri_escape ($host);
741   my $plugin_url = uri_escape ($plugin);
742   my $plugin_html = encode_entities ($plugin);
743   my $plugin_instance_url = defined ($plugin_instance) ? uri_escape ($plugin_instance) : undef;
744   my $type_url = uri_escape ($type);
745   my $type_instance_url = defined ($type_instance) ? uri_escape ($type_instance) : undef;
746
747   my $url_prefix = script_name () . "?action=show_plugin;host=$host_url;plugin=$plugin_url";
748   $url_prefix .= ";plugin_instance=$plugin_instance_url" if (defined ($plugin_instance));
749
750   print qq(    <div><a href="$url_prefix">Back to plugin &quot;$plugin_html&quot;</a></div>\n);
751
752   $url_prefix = script_name () . "?action=show_graph;host=$host_url;plugin=$plugin_url";
753   $url_prefix .= ";plugin_instance=$plugin_instance_url" if (defined ($plugin_instance));
754   $url_prefix .= ";type=$type_url";
755   $url_prefix .= ";type_instance=$type_instance_url" if (defined ($type_instance));
756
757   for (qw(hour day week month year))
758   {
759     my $timespan = $_;
760
761     print qq#  <div><img src="$url_prefix;timespan=$timespan" /></div>\n#;
762   }
763 } # action_show_type
764
765 sub action_show_graph
766 {
767   my $host = shift;
768   my $plugin = shift;
769   my $plugin_instance = shift;
770   my $type = shift;
771   my $type_instance = shift;
772   my @rrd_args;
773   my $title;
774   
775   my %times = (hour => -3600, day => -86400, week => 7 * -86400, month => 31 * -86400, year => 366 * -86400);
776   my $start_time = $times{$Args->{'timespan'}} || -86400;
777
778   #print STDERR Data::Dumper->Dump ([$Args], ['Args']);
779
780   # FIXME
781   if (exists ($MetaGraphDefs->{$type}))
782   {
783     my %types = _find_types ($host, $plugin, $plugin_instance);
784     return $MetaGraphDefs->{$type}->($host, $plugin, $plugin_instance, $type, $types{$type});
785   }
786
787   return if (!defined ($GraphDefs->{$type}));
788   @rrd_args = @{$GraphDefs->{$type}};
789
790   $title = "$host/$plugin" . (defined ($plugin_instance) ? "-$plugin_instance" : '')
791   . "/$type" . (defined ($type_instance) ? "-$type_instance" : '');
792
793   for (my $i = 0; $i < @DataDirs; $i++)
794   {
795     my $file = $DataDirs[$i] . "/$title.rrd";
796     next if (!-f $file);
797
798     $file =~ s/:/\\:/g;
799     s/{file}/$file/ for (@rrd_args);
800
801     RRDs::graph ('-', '-a', 'PNG', '-s', $start_time, '-t', $title, @RRDDefaultArgs, @rrd_args);
802     if (my $err = RRDs::error ())
803     {
804       die ("RRDs::graph: $err");
805     }
806   }
807 } # action_show_graph
808
809 sub print_selector
810 {
811   my @hosts = _find_hosts ();
812   @hosts = sort (@hosts);
813
814   my %selected_hosts = map { $_ => 1 } (_get_param_host ());
815   my $timespan_selected = _get_param_timespan ();
816
817   print <<HTML;
818     <form action="${\script_name ()}" method="get">
819       <fieldset>
820         <legend>Selector</legend>
821         <select name="host" multiple="multiple" size="10">
822 HTML
823   for (my $i = 0; $i < @hosts; $i++)
824   {
825     my $host = encode_entities ($hosts[$i]);
826     my $selected = defined ($selected_hosts{$hosts[$i]}) ? ' selected="selected"' : '';
827     print qq(\t  <option value="$host"$selected>$host</option>\n);
828   }
829   print "\t</select>\n";
830
831   if (keys %selected_hosts)
832   {
833     my $all_plugins = _find_files_for_hosts (@hosts);
834     my %selected_plugins = map { $_ => 1 } (param ('plugin'));
835
836     print qq(\t<select name="plugin" multiple="multiple" size="10">\n);
837     for (sort (keys %$all_plugins))
838     {
839       my $plugin = $_;
840       my $plugin_html = encode_entities ($plugin);
841       my $selected = (defined ($selected_plugins{$plugin})
842         ? ' selected="selected"' : '');
843       print qq(\t  <option value="$plugin_html"$selected>$plugin</option>\n);
844     }
845     print "</select>\n";
846   } # if (keys %selected_hosts)
847
848   print qq(\t<select name="timespan">\n);
849   for (qw(Hour Day Week Month Year))
850   {
851     my $timespan_uc = $_;
852     my $timespan_lc = lc ($_);
853     my $selected = ($timespan_selected eq $timespan_lc)
854       ? ' selected="selected"' : '';
855     print qq(\t  <option value="$timespan_lc"$selected>$timespan_uc</option>\n);
856   }
857   print <<HTML;
858         </select>
859         <input type="submit" name="button" value="Ok" />
860       </fieldset>
861     </form>
862 HTML
863 }
864
865 sub print_header
866 {
867   print <<HEAD;
868 Content-Type: application/xhtml+xml; charset=utf-8
869 Cache-Control: no-cache
870
871 <?xml version="1.0" encoding="utf-8"?>
872 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
873   "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
874
875 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
876   <head>
877     <title>collection.cgi, Version 2</title>
878     <style type="text/css">
879       img
880       {
881         border: none;
882       }
883       table.graphs
884       {
885         border-collapse: collapse;
886       }
887       table.graphs td,
888       table.graphs th
889       {
890         border: 1px solid black;
891         empty-cells: hide;
892       }
893     </style>
894   </head>
895
896   <body>
897 HEAD
898   print_selector ();
899 } # print_header
900
901 sub print_footer
902 {
903   print <<FOOT;
904   </body>
905 </html>
906 FOOT
907 } # print_footer
908
909 sub main
910 {
911         read_config ();
912         validate_args ();
913
914         if (defined ($Args->{'host'})
915           && defined ($Args->{'plugin'})
916           && defined ($Args->{'type'})
917           && ($Args->{'action'} eq 'show_graph'))
918         {
919           $| = 1;
920           print STDOUT header (-Content_Type => 'image/png');
921           action_show_graph ($Args->{'host'},
922             $Args->{'plugin'}, $Args->{'plugin_instance'},
923             $Args->{'type'}, $Args->{'type_instance'});
924           return (0);
925         }
926
927         print_header ();
928
929         if (!$Args->{'host'})
930         {
931           list_hosts ();
932         }
933         elsif (!$Args->{'plugin'})
934         {
935           action_show_host ($Args->{'host'});
936         }
937         elsif (!$Args->{'type'})
938         {
939           action_show_plugin ($Args->{'plugin'}, $Args->{'plugin_instance'});
940         }
941         else
942         {
943           action_show_type ($Args->{'host'},
944             $Args->{'plugin'}, $Args->{'plugin_instance'},
945             $Args->{'type'}, $Args->{'type_instance'});
946         }
947
948         print_footer ();
949
950         return (0);
951 }
952
953 sub load_graph_definitions
954 {
955   my $Canvas = 'FFFFFF';
956
957   my $FullRed    = 'FF0000';
958   my $FullGreen  = '00E000';
959   my $FullBlue   = '0000FF';
960   my $FullYellow = 'F0A000';
961   my $FullCyan   = '00A0FF';
962   my $FullMagenta= 'A000FF';
963
964   my $HalfRed    = 'F7B7B7';
965   my $HalfGreen  = 'B7EFB7';
966   my $HalfBlue   = 'B7B7F7';
967   my $HalfYellow = 'F3DFB7';
968   my $HalfCyan   = 'B7DFF7';
969   my $HalfMagenta= 'DFB7F7';
970
971   my $HalfBlueGreen = '89B3C9';
972
973   $GraphDefs =
974   {
975     apache_bytes => ['DEF:min_raw={file}:count:MIN',
976     'DEF:avg_raw={file}:count:AVERAGE',
977     'DEF:max_raw={file}:count:MAX',
978     'CDEF:min=min_raw,8,*',
979     'CDEF:avg=avg_raw,8,*',
980     'CDEF:max=max_raw,8,*',
981     'CDEF:mytime=avg_raw,TIME,TIME,IF',
982     'CDEF:sample_len_raw=mytime,PREV(mytime),-',
983     'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
984     'CDEF:avg_sample=avg_raw,UN,0,avg_raw,IF,sample_len,*',
985     'CDEF:avg_sum=PREV,UN,0,PREV,IF,avg_sample,+',
986     "AREA:avg#$HalfBlue",
987     "LINE1:avg#$FullBlue:Bit/s",
988     'GPRINT:min:MIN:%5.1lf%s Min,',
989     'GPRINT:avg:AVERAGE:%5.1lf%s Avg,',
990     'GPRINT:max:MAX:%5.1lf%s Max,',
991     'GPRINT:avg:LAST:%5.1lf%s Last',
992     'GPRINT:avg_sum:LAST:(ca. %5.1lf%sB Total)\l'
993     ],
994     apache_requests => ['DEF:min={file}:count:MIN',
995     'DEF:avg={file}:count:AVERAGE',
996     'DEF:max={file}:count:MAX',
997     "AREA:max#$HalfBlue",
998     "AREA:min#$Canvas",
999     "LINE1:avg#$FullBlue:Requests/s",
1000     'GPRINT:min:MIN:%6.2lf Min,',
1001     'GPRINT:avg:AVERAGE:%6.2lf Avg,',
1002     'GPRINT:max:MAX:%6.2lf Max,',
1003     'GPRINT:avg:LAST:%6.2lf Last'
1004     ],
1005     apache_scoreboard => ['DEF:min={file}:count:MIN',
1006     'DEF:avg={file}:count:AVERAGE',
1007     'DEF:max={file}:count:MAX',
1008     "AREA:max#$HalfBlue",
1009     "AREA:min#$Canvas",
1010     "LINE1:avg#$FullBlue:Processes",
1011     'GPRINT:min:MIN:%6.2lf Min,',
1012     'GPRINT:avg:AVERAGE:%6.2lf Avg,',
1013     'GPRINT:max:MAX:%6.2lf Max,',
1014     'GPRINT:avg:LAST:%6.2lf Last'
1015     ],
1016     bitrate => ['-v', 'Bits/s',
1017     'DEF:avg={file}:value:AVERAGE',
1018     'DEF:min={file}:value:MIN',
1019     'DEF:max={file}:value:MAX',
1020     "AREA:max#$HalfBlue",
1021     "AREA:min#$Canvas",
1022     "LINE1:avg#$FullBlue:Bits/s",
1023     'GPRINT:min:MIN:%5.1lf%s Min,',
1024     'GPRINT:avg:AVERAGE:%5.1lf%s Average,',
1025     'GPRINT:max:MAX:%5.1lf%s Max,',
1026     'GPRINT:avg:LAST:%5.1lf%s Last\l'
1027     ],
1028     charge => [
1029     'DEF:avg={file}:charge:AVERAGE',
1030     'DEF:min={file}:charge:MIN',
1031     'DEF:max={file}:charge:MAX',
1032     "AREA:max#$HalfBlue",
1033     "AREA:min#$Canvas",
1034     "LINE1:avg#$FullBlue:Charge",
1035     'GPRINT:min:MIN:%5.1lf%sAh Min,',
1036     'GPRINT:avg:AVERAGE:%5.1lf%sAh Avg,',
1037     'GPRINT:max:MAX:%5.1lf%sAh Max,',
1038     'GPRINT:avg:LAST:%5.1lf%sAh Last\l'
1039     ],
1040     charge_percent => [
1041     'DEF:avg={file}:percent:AVERAGE',
1042     'DEF:min={file}:percent:MIN',
1043     'DEF:max={file}:percent:MAX',
1044     "AREA:max#$HalfBlue",
1045     "AREA:min#$Canvas",
1046     "LINE1:avg#$FullBlue:Charge",
1047     'GPRINT:min:MIN:%5.1lf%s%% Min,',
1048     'GPRINT:avg:AVERAGE:%5.1lf%s%% Avg,',
1049     'GPRINT:max:MAX:%5.1lf%s%% Max,',
1050     'GPRINT:avg:LAST:%5.1lf%s%% Last\l'
1051     ],
1052     cpu => ['-v', 'CPU load',
1053     'DEF:avg={file}:value:AVERAGE',
1054     'DEF:min={file}:value:MIN',
1055     'DEF:max={file}:value:MAX',
1056     "AREA:max#$HalfBlue",
1057     "AREA:min#$Canvas",
1058     "LINE1:avg#$FullBlue:Percent",
1059     'GPRINT:min:MIN:%6.2lf%% Min,',
1060     'GPRINT:avg:AVERAGE:%6.2lf%% Avg,',
1061     'GPRINT:max:MAX:%6.2lf%% Max,',
1062     'GPRINT:avg:LAST:%6.2lf%% Last\l'
1063     ],
1064     current => [
1065     'DEF:avg={file}:current:AVERAGE',
1066     'DEF:min={file}:current:MIN',
1067     'DEF:max={file}:current:MAX',
1068     "AREA:max#$HalfBlue",
1069     "AREA:min#$Canvas",
1070     "LINE1:avg#$FullBlue:Current",
1071     'GPRINT:min:MIN:%5.1lf%sA Min,',
1072     'GPRINT:avg:AVERAGE:%5.1lf%sA Avg,',
1073     'GPRINT:max:MAX:%5.1lf%sA Max,',
1074     'GPRINT:avg:LAST:%5.1lf%sA Last\l'
1075     ],
1076     df => ['-v', 'Percent', '-l', '0',
1077     'DEF:free_avg={file}:free:AVERAGE',
1078     'DEF:free_min={file}:free:MIN',
1079     'DEF:free_max={file}:free:MAX',
1080     'DEF:used_avg={file}:used:AVERAGE',
1081     'DEF:used_min={file}:used:MIN',
1082     'DEF:used_max={file}:used:MAX',
1083     'CDEF:total=free_avg,used_avg,+',
1084     'CDEF:free_pct=100,free_avg,*,total,/',
1085     'CDEF:used_pct=100,used_avg,*,total,/',
1086     'CDEF:free_acc=free_pct,used_pct,+',
1087     'CDEF:used_acc=used_pct',
1088     "AREA:free_acc#$HalfGreen",
1089     "AREA:used_acc#$HalfRed",
1090     "LINE1:free_acc#$FullGreen:Free",
1091     'GPRINT:free_min:MIN:%5.1lf%sB Min,',
1092     'GPRINT:free_avg:AVERAGE:%5.1lf%sB Avg,',
1093     'GPRINT:free_max:MAX:%5.1lf%sB Max,',
1094     'GPRINT:free_avg:LAST:%5.1lf%sB Last\l',
1095     "LINE1:used_acc#$FullRed:Used",
1096     'GPRINT:used_min:MIN:%5.1lf%sB Min,',
1097     'GPRINT:used_avg:AVERAGE:%5.1lf%sB Avg,',
1098     'GPRINT:used_max:MAX:%5.1lf%sB Max,',
1099     'GPRINT:used_avg:LAST:%5.1lf%sB Last\l'
1100     ],
1101     disk => [
1102     'DEF:rtime_avg={file}:rtime:AVERAGE',
1103     'DEF:rtime_min={file}:rtime:MIN',
1104     'DEF:rtime_max={file}:rtime:MAX',
1105     'DEF:wtime_avg={file}:wtime:AVERAGE',
1106     'DEF:wtime_min={file}:wtime:MIN',
1107     'DEF:wtime_max={file}:wtime:MAX',
1108     'CDEF:rtime_avg_ms=rtime_avg,1000,/',
1109     'CDEF:rtime_min_ms=rtime_min,1000,/',
1110     'CDEF:rtime_max_ms=rtime_max,1000,/',
1111     'CDEF:wtime_avg_ms=wtime_avg,1000,/',
1112     'CDEF:wtime_min_ms=wtime_min,1000,/',
1113     'CDEF:wtime_max_ms=wtime_max,1000,/',
1114     'CDEF:total_avg_ms=rtime_avg_ms,wtime_avg_ms,+',
1115     'CDEF:total_min_ms=rtime_min_ms,wtime_min_ms,+',
1116     'CDEF:total_max_ms=rtime_max_ms,wtime_max_ms,+',
1117     "AREA:total_max_ms#$HalfRed",
1118     "AREA:total_min_ms#$Canvas",
1119     "LINE1:wtime_avg_ms#$FullGreen:Write",
1120     'GPRINT:wtime_min_ms:MIN:%5.1lf%s Min,',
1121     'GPRINT:wtime_avg_ms:AVERAGE:%5.1lf%s Avg,',
1122     'GPRINT:wtime_max_ms:MAX:%5.1lf%s Max,',
1123     'GPRINT:wtime_avg_ms:LAST:%5.1lf%s Last\n',
1124     "LINE1:rtime_avg_ms#$FullBlue:Read ",
1125     'GPRINT:rtime_min_ms:MIN:%5.1lf%s Min,',
1126     'GPRINT:rtime_avg_ms:AVERAGE:%5.1lf%s Avg,',
1127     'GPRINT:rtime_max_ms:MAX:%5.1lf%s Max,',
1128     'GPRINT:rtime_avg_ms:LAST:%5.1lf%s Last\n',
1129     "LINE1:total_avg_ms#$FullRed:Total",
1130     'GPRINT:total_min_ms:MIN:%5.1lf%s Min,',
1131     'GPRINT:total_avg_ms:AVERAGE:%5.1lf%s Avg,',
1132     'GPRINT:total_max_ms:MAX:%5.1lf%s Max,',
1133     'GPRINT:total_avg_ms:LAST:%5.1lf%s Last'
1134     ],
1135     disk_octets => ['-v', 'Bytes/s',
1136     'DEF:out_min={file}:write:MIN',
1137     'DEF:out_avg={file}:write:AVERAGE',
1138     'DEF:out_max={file}:write:MAX',
1139     'DEF:inc_min={file}:read:MIN',
1140     'DEF:inc_avg={file}:read:AVERAGE',
1141     'DEF:inc_max={file}:read:MAX',
1142     'CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF',
1143     'CDEF:mytime=out_avg,TIME,TIME,IF',
1144     'CDEF:sample_len_raw=mytime,PREV(mytime),-',
1145     'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
1146     'CDEF:out_avg_sample=out_avg,UN,0,out_avg,IF,sample_len,*',
1147     'CDEF:out_avg_sum=PREV,UN,0,PREV,IF,out_avg_sample,+',
1148     'CDEF:inc_avg_sample=inc_avg,UN,0,inc_avg,IF,sample_len,*',
1149     'CDEF:inc_avg_sum=PREV,UN,0,PREV,IF,inc_avg_sample,+',
1150     "AREA:out_avg#$HalfGreen",
1151     "AREA:inc_avg#$HalfBlue",
1152     "AREA:overlap#$HalfBlueGreen",
1153     "LINE1:out_avg#$FullGreen:Written",
1154     'GPRINT:out_avg:AVERAGE:%5.1lf%s Avg,',
1155     'GPRINT:out_max:MAX:%5.1lf%s Max,',
1156     'GPRINT:out_avg:LAST:%5.1lf%s Last',
1157     'GPRINT:out_avg_sum:LAST:(ca. %5.1lf%sB Total)\l',
1158     "LINE1:inc_avg#$FullBlue:Read   ",
1159     'GPRINT:inc_avg:AVERAGE:%5.1lf%s Avg,',
1160     'GPRINT:inc_max:MAX:%5.1lf%s Max,',
1161     'GPRINT:inc_avg:LAST:%5.1lf%s Last',
1162     'GPRINT:inc_avg_sum:LAST:(ca. %5.1lf%sB Total)\l'
1163     ],
1164     disk_merged => ['-v', 'Merged Ops/s',
1165     'DEF:out_min={file}:write:MIN',
1166     'DEF:out_avg={file}:write:AVERAGE',
1167     'DEF:out_max={file}:write:MAX',
1168     'DEF:inc_min={file}:read:MIN',
1169     'DEF:inc_avg={file}:read:AVERAGE',
1170     'DEF:inc_max={file}:read:MAX',
1171     'CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF',
1172     "AREA:out_avg#$HalfGreen",
1173     "AREA:inc_avg#$HalfBlue",
1174     "AREA:overlap#$HalfBlueGreen",
1175     "LINE1:out_avg#$FullGreen:Written",
1176     'GPRINT:out_avg:AVERAGE:%6.2lf Avg,',
1177     'GPRINT:out_max:MAX:%6.2lf Max,',
1178     'GPRINT:out_avg:LAST:%6.2lf Last\l',
1179     "LINE1:inc_avg#$FullBlue:Read   ",
1180     'GPRINT:inc_avg:AVERAGE:%6.2lf Avg,',
1181     'GPRINT:inc_max:MAX:%6.2lf Max,',
1182     'GPRINT:inc_avg:LAST:%6.2lf Last\l'
1183     ],
1184     disk_ops => ['-v', 'Ops/s',
1185     'DEF:out_min={file}:write:MIN',
1186     'DEF:out_avg={file}:write:AVERAGE',
1187     'DEF:out_max={file}:write:MAX',
1188     'DEF:inc_min={file}:read:MIN',
1189     'DEF:inc_avg={file}:read:AVERAGE',
1190     'DEF:inc_max={file}:read:MAX',
1191     'CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF',
1192     "AREA:out_avg#$HalfGreen",
1193     "AREA:inc_avg#$HalfBlue",
1194     "AREA:overlap#$HalfBlueGreen",
1195     "LINE1:out_avg#$FullGreen:Written",
1196     'GPRINT:out_avg:AVERAGE:%6.2lf Avg,',
1197     'GPRINT:out_max:MAX:%6.2lf Max,',
1198     'GPRINT:out_avg:LAST:%6.2lf Last\l',
1199     "LINE1:inc_avg#$FullBlue:Read   ",
1200     'GPRINT:inc_avg:AVERAGE:%6.2lf Avg,',
1201     'GPRINT:inc_max:MAX:%6.2lf Max,',
1202     'GPRINT:inc_avg:LAST:%6.2lf Last\l'
1203     ],
1204     disk_time => ['-v', 'Seconds/s',
1205     'DEF:out_min_raw={file}:write:MIN',
1206     'DEF:out_avg_raw={file}:write:AVERAGE',
1207     'DEF:out_max_raw={file}:write:MAX',
1208     'DEF:inc_min_raw={file}:read:MIN',
1209     'DEF:inc_avg_raw={file}:read:AVERAGE',
1210     'DEF:inc_max_raw={file}:read:MAX',
1211     'CDEF:out_min=out_min_raw,1000,/',
1212     'CDEF:out_avg=out_avg_raw,1000,/',
1213     'CDEF:out_max=out_max_raw,1000,/',
1214     'CDEF:inc_min=inc_min_raw,1000,/',
1215     'CDEF:inc_avg=inc_avg_raw,1000,/',
1216     'CDEF:inc_max=inc_max_raw,1000,/',
1217     'CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF',
1218     "AREA:out_avg#$HalfGreen",
1219     "AREA:inc_avg#$HalfBlue",
1220     "AREA:overlap#$HalfBlueGreen",
1221     "LINE1:out_avg#$FullGreen:Written",
1222     'GPRINT:out_avg:AVERAGE:%5.1lf%ss Avg,',
1223     'GPRINT:out_max:MAX:%5.1lf%ss Max,',
1224     'GPRINT:out_avg:LAST:%5.1lf%ss Last\l',
1225     "LINE1:inc_avg#$FullBlue:Read   ",
1226     'GPRINT:inc_avg:AVERAGE:%5.1lf%ss Avg,',
1227     'GPRINT:inc_max:MAX:%5.1lf%ss Max,',
1228     'GPRINT:inc_avg:LAST:%5.1lf%ss Last\l'
1229     ],
1230     dns_traffic => ['DEF:rsp_min_raw={file}:responses:MIN',
1231     'DEF:rsp_avg_raw={file}:responses:AVERAGE',
1232     'DEF:rsp_max_raw={file}:responses:MAX',
1233     'DEF:qry_min_raw={file}:queries:MIN',
1234     'DEF:qry_avg_raw={file}:queries:AVERAGE',
1235     'DEF:qry_max_raw={file}:queries:MAX',
1236     'CDEF:rsp_min=rsp_min_raw,8,*',
1237     'CDEF:rsp_avg=rsp_avg_raw,8,*',
1238     'CDEF:rsp_max=rsp_max_raw,8,*',
1239     'CDEF:qry_min=qry_min_raw,8,*',
1240     'CDEF:qry_avg=qry_avg_raw,8,*',
1241     'CDEF:qry_max=qry_max_raw,8,*',
1242     'CDEF:overlap=rsp_avg,qry_avg,GT,qry_avg,rsp_avg,IF',
1243     'CDEF:mytime=rsp_avg_raw,TIME,TIME,IF',
1244     'CDEF:sample_len_raw=mytime,PREV(mytime),-',
1245     'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
1246     'CDEF:rsp_avg_sample=rsp_avg_raw,UN,0,rsp_avg_raw,IF,sample_len,*',
1247     'CDEF:rsp_avg_sum=PREV,UN,0,PREV,IF,rsp_avg_sample,+',
1248     'CDEF:qry_avg_sample=qry_avg_raw,UN,0,qry_avg_raw,IF,sample_len,*',
1249     'CDEF:qry_avg_sum=PREV,UN,0,PREV,IF,qry_avg_sample,+',
1250     "AREA:rsp_avg#$HalfGreen",
1251     "AREA:qry_avg#$HalfBlue",
1252     "AREA:overlap#$HalfBlueGreen",
1253     "LINE1:rsp_avg#$FullGreen:Responses",
1254     'GPRINT:rsp_avg:AVERAGE:%5.1lf%s Avg,',
1255     'GPRINT:rsp_max:MAX:%5.1lf%s Max,',
1256     'GPRINT:rsp_avg:LAST:%5.1lf%s Last',
1257     'GPRINT:rsp_avg_sum:LAST:(ca. %5.1lf%sB Total)\l',
1258     "LINE1:qry_avg#$FullBlue:Queries  ",
1259     #'GPRINT:qry_min:MIN:%5.1lf %s Min,',
1260     'GPRINT:qry_avg:AVERAGE:%5.1lf%s Avg,',
1261     'GPRINT:qry_max:MAX:%5.1lf%s Max,',
1262     'GPRINT:qry_avg:LAST:%5.1lf%s Last',
1263     'GPRINT:qry_avg_sum:LAST:(ca. %5.1lf%sB Total)\l'
1264     ],
1265     email_count => ['-v', 'Mails',
1266     'DEF:avg={file}:value:AVERAGE',
1267     'DEF:min={file}:value:MIN',
1268     'DEF:max={file}:value:MAX',
1269     "AREA:max#$HalfMagenta",
1270     "AREA:min#$Canvas",
1271     "LINE1:avg#$FullMagenta:Count ",
1272     'GPRINT:min:MIN:%4.1lf Min,',
1273     'GPRINT:avg:AVERAGE:%4.1lf Avg,',
1274     'GPRINT:max:MAX:%4.1lf Max,',
1275     'GPRINT:avg:LAST:%4.1lf Last\l'
1276     ],
1277     email_size => ['-v', 'Bytes',
1278     'DEF:avg={file}:value:AVERAGE',
1279     'DEF:min={file}:value:MIN',
1280     'DEF:max={file}:value:MAX',
1281     "AREA:max#$HalfMagenta",
1282     "AREA:min#$Canvas",
1283     "LINE1:avg#$FullMagenta:Count ",
1284     'GPRINT:min:MIN:%4.1lf Min,',
1285     'GPRINT:avg:AVERAGE:%4.1lf Avg,',
1286     'GPRINT:max:MAX:%4.1lf Max,',
1287     'GPRINT:avg:LAST:%4.1lf Last\l'
1288     ],
1289     spam_score => ['-v', 'Score',
1290     'DEF:avg={file}:value:AVERAGE',
1291     'DEF:min={file}:value:MIN',
1292     'DEF:max={file}:value:MAX',
1293     "AREA:max#$HalfBlue",
1294     "AREA:min#$Canvas",
1295     "LINE1:avg#$FullBlue:Score ",
1296     'GPRINT:min:MIN:%4.1lf Min,',
1297     'GPRINT:avg:AVERAGE:%4.1lf Avg,',
1298     'GPRINT:max:MAX:%4.1lf Max,',
1299     'GPRINT:avg:LAST:%4.1lf Last\l'
1300     ],
1301     spam_check => [
1302     'DEF:avg={file}:hits:AVERAGE',
1303     'DEF:min={file}:hits:MIN',
1304     'DEF:max={file}:hits:MAX',
1305     "AREA:max#$HalfMagenta",
1306     "AREA:min#$Canvas",
1307     "LINE1:avg#$FullMagenta:Count ",
1308     'GPRINT:min:MIN:%4.1lf Min,',
1309     'GPRINT:avg:AVERAGE:%4.1lf Avg,',
1310     'GPRINT:max:MAX:%4.1lf Max,',
1311     'GPRINT:avg:LAST:%4.1lf Last\l'
1312     ],
1313     entropy => ['-v', 'Bits',
1314     'DEF:avg={file}:entropy:AVERAGE',
1315     'DEF:min={file}:entropy:MIN',
1316     'DEF:max={file}:entropy:MAX',
1317     "AREA:max#$HalfBlue",
1318     "AREA:min#$Canvas",
1319     "LINE1:avg#$FullBlue:Bits",
1320     'GPRINT:min:MIN:%4.0lfbit Min,',
1321     'GPRINT:avg:AVERAGE:%4.0lfbit Avg,',
1322     'GPRINT:max:MAX:%4.0lfbit Max,',
1323     'GPRINT:avg:LAST:%4.0lfbit Last\l'
1324     ],
1325     fanspeed => ['-v', 'RPM',
1326     'DEF:avg={file}:value:AVERAGE',
1327     'DEF:min={file}:value:MIN',
1328     'DEF:max={file}:value:MAX',
1329     "AREA:max#$HalfMagenta",
1330     "AREA:min#$Canvas",
1331     "LINE1:avg#$FullMagenta:RPM",
1332     'GPRINT:min:MIN:%4.1lf Min,',
1333     'GPRINT:avg:AVERAGE:%4.1lf Avg,',
1334     'GPRINT:max:MAX:%4.1lf Max,',
1335     'GPRINT:avg:LAST:%4.1lf Last\l'
1336     ],
1337     frequency => ['-v', 'Hertz',
1338     'DEF:avg={file}:frequency:AVERAGE',
1339     'DEF:min={file}:frequency:MIN',
1340     'DEF:max={file}:frequency:MAX',
1341     "AREA:max#$HalfBlue",
1342     "AREA:min#$Canvas",
1343     "LINE1:avg#$FullBlue:Frequency [Hz]",
1344     'GPRINT:min:MIN:%4.1lf Min,',
1345     'GPRINT:avg:AVERAGE:%4.1lf Avg,',
1346     'GPRINT:max:MAX:%4.1lf Max,',
1347     'GPRINT:avg:LAST:%4.1lf Last\l'
1348     ],
1349     frequency_offset => [ # NTPd
1350     'DEF:ppm_avg={file}:ppm:AVERAGE',
1351     'DEF:ppm_min={file}:ppm:MIN',
1352     'DEF:ppm_max={file}:ppm:MAX',
1353     "AREA:ppm_max#$HalfBlue",
1354     "AREA:ppm_min#$Canvas",
1355     "LINE1:ppm_avg#$FullBlue:{inst}",
1356     'GPRINT:ppm_min:MIN:%5.2lf Min,',
1357     'GPRINT:ppm_avg:AVERAGE:%5.2lf Avg,',
1358     'GPRINT:ppm_max:MAX:%5.2lf Max,',
1359     'GPRINT:ppm_avg:LAST:%5.2lf Last'
1360     ],
1361     gauge => ['-v', 'Exec value',
1362     'DEF:temp_avg={file}:value:AVERAGE',
1363     'DEF:temp_min={file}:value:MIN',
1364     'DEF:temp_max={file}:value:MAX',
1365     "AREA:temp_max#$HalfBlue",
1366     "AREA:temp_min#$Canvas",
1367     "LINE1:temp_avg#$FullBlue:Exec value",
1368     'GPRINT:temp_min:MIN:%6.2lf Min,',
1369     'GPRINT:temp_avg:AVERAGE:%6.2lf Avg,',
1370     'GPRINT:temp_max:MAX:%6.2lf Max,',
1371     'GPRINT:temp_avg:LAST:%6.2lf Last\l'
1372     ],
1373     hddtemp => [
1374     'DEF:temp_avg={file}:value:AVERAGE',
1375     'DEF:temp_min={file}:value:MIN',
1376     'DEF:temp_max={file}:value:MAX',
1377     "AREA:temp_max#$HalfRed",
1378     "AREA:temp_min#$Canvas",
1379     "LINE1:temp_avg#$FullRed:Temperature",
1380     'GPRINT:temp_min:MIN:%4.1lf Min,',
1381     'GPRINT:temp_avg:AVERAGE:%4.1lf Avg,',
1382     'GPRINT:temp_max:MAX:%4.1lf Max,',
1383     'GPRINT:temp_avg:LAST:%4.1lf Last\l'
1384     ],
1385     if_errors => ['-v', 'Errors/s',
1386     'DEF:tx_min={file}:tx:MIN',
1387     'DEF:tx_avg={file}:tx:AVERAGE',
1388     'DEF:tx_max={file}:tx:MAX',
1389     'DEF:rx_min={file}:rx:MIN',
1390     'DEF:rx_avg={file}:rx:AVERAGE',
1391     'DEF:rx_max={file}:rx:MAX',
1392     'CDEF:overlap=tx_avg,rx_avg,GT,rx_avg,tx_avg,IF',
1393     'CDEF:mytime=tx_avg,TIME,TIME,IF',
1394     'CDEF:sample_len_raw=mytime,PREV(mytime),-',
1395     'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
1396     'CDEF:tx_avg_sample=tx_avg,UN,0,tx_avg,IF,sample_len,*',
1397     'CDEF:tx_avg_sum=PREV,UN,0,PREV,IF,tx_avg_sample,+',
1398     'CDEF:rx_avg_sample=rx_avg,UN,0,rx_avg,IF,sample_len,*',
1399     'CDEF:rx_avg_sum=PREV,UN,0,PREV,IF,rx_avg_sample,+',
1400     "AREA:tx_avg#$HalfGreen",
1401     "AREA:rx_avg#$HalfBlue",
1402     "AREA:overlap#$HalfBlueGreen",
1403     "LINE1:tx_avg#$FullGreen:TX",
1404     'GPRINT:tx_avg:AVERAGE:%5.1lf%s Avg,',
1405     'GPRINT:tx_max:MAX:%5.1lf%s Max,',
1406     'GPRINT:tx_avg:LAST:%5.1lf%s Last',
1407     'GPRINT:tx_avg_sum:LAST:(ca. %4.0lf%s Total)\l',
1408     "LINE1:rx_avg#$FullBlue:RX",
1409     #'GPRINT:rx_min:MIN:%5.1lf %s Min,',
1410     'GPRINT:rx_avg:AVERAGE:%5.1lf%s Avg,',
1411     'GPRINT:rx_max:MAX:%5.1lf%s Max,',
1412     'GPRINT:rx_avg:LAST:%5.1lf%s Last',
1413     'GPRINT:rx_avg_sum:LAST:(ca. %4.0lf%s Total)\l'
1414     ],
1415     if_collisions => ['-v', 'Collisions/s',
1416     'DEF:min_raw={file}:value:MIN',
1417     'DEF:avg_raw={file}:value:AVERAGE',
1418     'DEF:max_raw={file}:value:MAX',
1419     'CDEF:min=min_raw,8,*',
1420     'CDEF:avg=avg_raw,8,*',
1421     'CDEF:max=max_raw,8,*',
1422     "AREA:max#$HalfBlue",
1423     "AREA:min#$Canvas",
1424     "LINE1:avg#$FullBlue:Collisions/s",
1425     'GPRINT:min:MIN:%5.1lf %s Min,',
1426     'GPRINT:avg:AVERAGE:%5.1lf%s Avg,',
1427     'GPRINT:max:MAX:%5.1lf%s Max,',
1428     'GPRINT:avg:LAST:%5.1lf%s Last\l'
1429     ],
1430     if_dropped => ['-v', 'Packets/s',
1431     'DEF:tx_min={file}:tx:MIN',
1432     'DEF:tx_avg={file}:tx:AVERAGE',
1433     'DEF:tx_max={file}:tx:MAX',
1434     'DEF:rx_min={file}:rx:MIN',
1435     'DEF:rx_avg={file}:rx:AVERAGE',
1436     'DEF:rx_max={file}:rx:MAX',
1437     'CDEF:overlap=tx_avg,rx_avg,GT,rx_avg,tx_avg,IF',
1438     'CDEF:mytime=tx_avg,TIME,TIME,IF',
1439     'CDEF:sample_len_raw=mytime,PREV(mytime),-',
1440     'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
1441     'CDEF:tx_avg_sample=tx_avg,UN,0,tx_avg,IF,sample_len,*',
1442     'CDEF:tx_avg_sum=PREV,UN,0,PREV,IF,tx_avg_sample,+',
1443     'CDEF:rx_avg_sample=rx_avg,UN,0,rx_avg,IF,sample_len,*',
1444     'CDEF:rx_avg_sum=PREV,UN,0,PREV,IF,rx_avg_sample,+',
1445     "AREA:tx_avg#$HalfGreen",
1446     "AREA:rx_avg#$HalfBlue",
1447     "AREA:overlap#$HalfBlueGreen",
1448     "LINE1:tx_avg#$FullGreen:TX",
1449     'GPRINT:tx_avg:AVERAGE:%5.1lf%s Avg,',
1450     'GPRINT:tx_max:MAX:%5.1lf%s Max,',
1451     'GPRINT:tx_avg:LAST:%5.1lf%s Last',
1452     'GPRINT:tx_avg_sum:LAST:(ca. %4.0lf%s Total)\l',
1453     "LINE1:rx_avg#$FullBlue:RX",
1454     #'GPRINT:rx_min:MIN:%5.1lf %s Min,',
1455     'GPRINT:rx_avg:AVERAGE:%5.1lf%s Avg,',
1456     'GPRINT:rx_max:MAX:%5.1lf%s Max,',
1457     'GPRINT:rx_avg:LAST:%5.1lf%s Last',
1458     'GPRINT:rx_avg_sum:LAST:(ca. %4.0lf%s Total)\l'
1459     ],
1460     if_packets => ['-v', 'Packets/s',
1461     'DEF:tx_min={file}:tx:MIN',
1462     'DEF:tx_avg={file}:tx:AVERAGE',
1463     'DEF:tx_max={file}:tx:MAX',
1464     'DEF:rx_min={file}:rx:MIN',
1465     'DEF:rx_avg={file}:rx:AVERAGE',
1466     'DEF:rx_max={file}:rx:MAX',
1467     'CDEF:overlap=tx_avg,rx_avg,GT,rx_avg,tx_avg,IF',
1468     'CDEF:mytime=tx_avg,TIME,TIME,IF',
1469     'CDEF:sample_len_raw=mytime,PREV(mytime),-',
1470     'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
1471     'CDEF:tx_avg_sample=tx_avg,UN,0,tx_avg,IF,sample_len,*',
1472     'CDEF:tx_avg_sum=PREV,UN,0,PREV,IF,tx_avg_sample,+',
1473     'CDEF:rx_avg_sample=rx_avg,UN,0,rx_avg,IF,sample_len,*',
1474     'CDEF:rx_avg_sum=PREV,UN,0,PREV,IF,rx_avg_sample,+',
1475     "AREA:tx_avg#$HalfGreen",
1476     "AREA:rx_avg#$HalfBlue",
1477     "AREA:overlap#$HalfBlueGreen",
1478     "LINE1:tx_avg#$FullGreen:TX",
1479     'GPRINT:tx_avg:AVERAGE:%5.1lf%s Avg,',
1480     'GPRINT:tx_max:MAX:%5.1lf%s Max,',
1481     'GPRINT:tx_avg:LAST:%5.1lf%s Last',
1482     'GPRINT:tx_avg_sum:LAST:(ca. %4.0lf%s Total)\l',
1483     "LINE1:rx_avg#$FullBlue:RX",
1484     #'GPRINT:rx_min:MIN:%5.1lf %s Min,',
1485     'GPRINT:rx_avg:AVERAGE:%5.1lf%s Avg,',
1486     'GPRINT:rx_max:MAX:%5.1lf%s Max,',
1487     'GPRINT:rx_avg:LAST:%5.1lf%s Last',
1488     'GPRINT:rx_avg_sum:LAST:(ca. %4.0lf%s Total)\l'
1489     ],
1490     if_rx_errors => ['-v', 'Errors/s',
1491     'DEF:min={file}:value:MIN',
1492     'DEF:avg={file}:value:AVERAGE',
1493     'DEF:max={file}:value:MAX',
1494     'CDEF:mytime=avg,TIME,TIME,IF',
1495     'CDEF:sample_len_raw=mytime,PREV(mytime),-',
1496     'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
1497     'CDEF:avg_sample=avg,UN,0,avg,IF,sample_len,*',
1498     'CDEF:avg_sum=PREV,UN,0,PREV,IF,avg_sample,+',
1499     "AREA:avg#$HalfBlue",
1500     "LINE1:avg#$FullBlue:Errors/s",
1501     'GPRINT:avg:AVERAGE:%3.1lf%s Avg,',
1502     'GPRINT:max:MAX:%3.1lf%s Max,',
1503     'GPRINT:avg:LAST:%3.1lf%s Last',
1504     'GPRINT:avg_sum:LAST:(ca. %2.0lf%s Total)\l'
1505     ],
1506     ipt_bytes => ['-v', 'Bits/s',
1507     'DEF:min_raw={file}:value:MIN',
1508     'DEF:avg_raw={file}:value:AVERAGE',
1509     'DEF:max_raw={file}:value:MAX',
1510     'CDEF:min=min_raw,8,*',
1511     'CDEF:avg=avg_raw,8,*',
1512     'CDEF:max=max_raw,8,*',
1513     'CDEF:mytime=avg_raw,TIME,TIME,IF',
1514     'CDEF:sample_len_raw=mytime,PREV(mytime),-',
1515     'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
1516     'CDEF:avg_sample=avg_raw,UN,0,avg_raw,IF,sample_len,*',
1517     'CDEF:avg_sum=PREV,UN,0,PREV,IF,avg_sample,+',
1518     "AREA:max#$HalfBlue",
1519     "AREA:min#$Canvas",
1520     "LINE1:avg#$FullBlue:Bits/s",
1521     #'GPRINT:min:MIN:%5.1lf %s Min,',
1522     'GPRINT:avg:AVERAGE:%5.1lf%s Avg,',
1523     'GPRINT:max:MAX:%5.1lf%s Max,',
1524     'GPRINT:avg:LAST:%5.1lf%s Last',
1525     'GPRINT:avg_sum:LAST:(ca. %5.1lf%sB Total)\l'
1526     ],
1527     ipt_packets => ['-v', 'Packets/s',
1528     'DEF:min_raw={file}:value:MIN',
1529     'DEF:avg_raw={file}:value:AVERAGE',
1530     'DEF:max_raw={file}:value:MAX',
1531     'CDEF:min=min_raw,8,*',
1532     'CDEF:avg=avg_raw,8,*',
1533     'CDEF:max=max_raw,8,*',
1534     "AREA:max#$HalfBlue",
1535     "AREA:min#$Canvas",
1536     "LINE1:avg#$FullBlue:Packets/s",
1537     'GPRINT:min:MIN:%5.1lf %s Min,',
1538     'GPRINT:avg:AVERAGE:%5.1lf%s Avg,',
1539     'GPRINT:max:MAX:%5.1lf%s Max,',
1540     'GPRINT:avg:LAST:%5.1lf%s Last\l'
1541     ],
1542     irq => ['-v', 'Issues/s',
1543     'DEF:avg={file}:value:AVERAGE',
1544     'DEF:min={file}:value:MIN',
1545     'DEF:max={file}:value:MAX',
1546     "AREA:max#$HalfBlue",
1547     "AREA:min#$Canvas",
1548     "LINE1:avg#$FullBlue:Issues/s",
1549     'GPRINT:min:MIN:%6.2lf Min,',
1550     'GPRINT:avg:AVERAGE:%6.2lf Avg,',
1551     'GPRINT:max:MAX:%6.2lf Max,',
1552     'GPRINT:avg:LAST:%6.2lf Last\l'
1553     ],
1554     load => ['-v', 'System load',
1555     'DEF:s_avg={file}:shortterm:AVERAGE',
1556     'DEF:s_min={file}:shortterm:MIN',
1557     'DEF:s_max={file}:shortterm:MAX',
1558     'DEF:m_avg={file}:midterm:AVERAGE',
1559     'DEF:m_min={file}:midterm:MIN',
1560     'DEF:m_max={file}:midterm:MAX',
1561     'DEF:l_avg={file}:longterm:AVERAGE',
1562     'DEF:l_min={file}:longterm:MIN',
1563     'DEF:l_max={file}:longterm:MAX',
1564     "AREA:s_max#$HalfGreen",
1565     "AREA:s_min#$Canvas",
1566     "LINE1:s_avg#$FullGreen: 1m average",
1567     'GPRINT:s_min:MIN:%4.2lf Min,',
1568     'GPRINT:s_avg:AVERAGE:%4.2lf Avg,',
1569     'GPRINT:s_max:MAX:%4.2lf Max,',
1570     'GPRINT:s_avg:LAST:%4.2lf Last\n',
1571     "LINE1:m_avg#$FullBlue: 5m average",
1572     'GPRINT:m_min:MIN:%4.2lf Min,',
1573     'GPRINT:m_avg:AVERAGE:%4.2lf Avg,',
1574     'GPRINT:m_max:MAX:%4.2lf Max,',
1575     'GPRINT:m_avg:LAST:%4.2lf Last\n',
1576     "LINE1:l_avg#$FullRed:15m average",
1577     'GPRINT:l_min:MIN:%4.2lf Min,',
1578     'GPRINT:l_avg:AVERAGE:%4.2lf Avg,',
1579     'GPRINT:l_max:MAX:%4.2lf Max,',
1580     'GPRINT:l_avg:LAST:%4.2lf Last'
1581     ],
1582     load_percent => [
1583     'DEF:avg={file}:percent:AVERAGE',
1584     'DEF:min={file}:percent:MIN',
1585     'DEF:max={file}:percent:MAX',
1586     "AREA:max#$HalfBlue",
1587     "AREA:min#$Canvas",
1588     "LINE1:avg#$FullBlue:Load",
1589     'GPRINT:min:MIN:%5.1lf%s%% Min,',
1590     'GPRINT:avg:AVERAGE:%5.1lf%s%% Avg,',
1591     'GPRINT:max:MAX:%5.1lf%s%% Max,',
1592     'GPRINT:avg:LAST:%5.1lf%s%% Last\l'
1593     ],
1594     mails => ['DEF:rawgood={file}:good:AVERAGE',
1595     'DEF:rawspam={file}:spam:AVERAGE',
1596     'CDEF:good=rawgood,UN,0,rawgood,IF',
1597     'CDEF:spam=rawspam,UN,0,rawspam,IF',
1598     'CDEF:negspam=spam,-1,*',
1599     "AREA:good#$HalfGreen",
1600     "LINE1:good#$FullGreen:Good mails",
1601     'GPRINT:good:AVERAGE:%4.1lf Avg,',
1602     'GPRINT:good:MAX:%4.1lf Max,',
1603     'GPRINT:good:LAST:%4.1lf Last\n',
1604     "AREA:negspam#$HalfRed",
1605     "LINE1:negspam#$FullRed:Spam mails",
1606     'GPRINT:spam:AVERAGE:%4.1lf Avg,',
1607     'GPRINT:spam:MAX:%4.1lf Max,',
1608     'GPRINT:spam:LAST:%4.1lf Last',
1609     'HRULE:0#000000'
1610     ],
1611     memory => ['-b', '1024', '-v', 'Bytes',
1612     'DEF:avg={file}:value:AVERAGE',
1613     'DEF:min={file}:value:MIN',
1614     'DEF:max={file}:value:MAX',
1615     "AREA:max#$HalfBlue",
1616     "AREA:min#$Canvas",
1617     "LINE1:avg#$FullBlue:Memory",
1618     'GPRINT:min:MIN:%5.1lf%sbyte Min,',
1619     'GPRINT:avg:AVERAGE:%5.1lf%sbyte Avg,',
1620     'GPRINT:max:MAX:%5.1lf%sbyte Max,',
1621     'GPRINT:avg:LAST:%5.1lf%sbyte Last\l'
1622     ],
1623     old_memory => [
1624     'DEF:used_avg={file}:used:AVERAGE',
1625     'DEF:free_avg={file}:free:AVERAGE',
1626     'DEF:buffers_avg={file}:buffers:AVERAGE',
1627     'DEF:cached_avg={file}:cached:AVERAGE',
1628     'DEF:used_min={file}:used:MIN',
1629     'DEF:free_min={file}:free:MIN',
1630     'DEF:buffers_min={file}:buffers:MIN',
1631     'DEF:cached_min={file}:cached:MIN',
1632     'DEF:used_max={file}:used:MAX',
1633     'DEF:free_max={file}:free:MAX',
1634     'DEF:buffers_max={file}:buffers:MAX',
1635     'DEF:cached_max={file}:cached:MAX',
1636     'CDEF:cached_avg_nn=cached_avg,UN,0,cached_avg,IF',
1637     'CDEF:buffers_avg_nn=buffers_avg,UN,0,buffers_avg,IF',
1638     'CDEF:free_cached_buffers_used=free_avg,cached_avg_nn,+,buffers_avg_nn,+,used_avg,+',
1639     'CDEF:cached_buffers_used=cached_avg,buffers_avg_nn,+,used_avg,+',
1640     'CDEF:buffers_used=buffers_avg,used_avg,+',
1641     "AREA:free_cached_buffers_used#$HalfGreen",
1642     "AREA:cached_buffers_used#$HalfBlue",
1643     "AREA:buffers_used#$HalfYellow",
1644     "AREA:used_avg#$HalfRed",
1645     "LINE1:free_cached_buffers_used#$FullGreen:Free        ",
1646     'GPRINT:free_min:MIN:%5.1lf%s Min,',
1647     'GPRINT:free_avg:AVERAGE:%5.1lf%s Avg,',
1648     'GPRINT:free_max:MAX:%5.1lf%s Max,',
1649     'GPRINT:free_avg:LAST:%5.1lf%s Last\n',
1650     "LINE1:cached_buffers_used#$FullBlue:Page cache  ",
1651     'GPRINT:cached_min:MIN:%5.1lf%s Min,',
1652     'GPRINT:cached_avg:AVERAGE:%5.1lf%s Avg,',
1653     'GPRINT:cached_max:MAX:%5.1lf%s Max,',
1654     'GPRINT:cached_avg:LAST:%5.1lf%s Last\n',
1655     "LINE1:buffers_used#$FullYellow:Buffer cache",
1656     'GPRINT:buffers_min:MIN:%5.1lf%s Min,',
1657     'GPRINT:buffers_avg:AVERAGE:%5.1lf%s Avg,',
1658     'GPRINT:buffers_max:MAX:%5.1lf%s Max,',
1659     'GPRINT:buffers_avg:LAST:%5.1lf%s Last\n',
1660     "LINE1:used_avg#$FullRed:Used        ",
1661     'GPRINT:used_min:MIN:%5.1lf%s Min,',
1662     'GPRINT:used_avg:AVERAGE:%5.1lf%s Avg,',
1663     'GPRINT:used_max:MAX:%5.1lf%s Max,',
1664     'GPRINT:used_avg:LAST:%5.1lf%s Last'
1665     ],
1666     mysql_commands => ['-v', 'Issues/s',
1667     "DEF:val_avg={file}:value:AVERAGE",
1668     "DEF:val_min={file}:value:MIN",
1669     "DEF:val_max={file}:value:MAX",
1670     "AREA:val_max#$HalfBlue",
1671     "AREA:val_min#$Canvas",
1672     "LINE1:val_avg#$FullBlue:{inst}",
1673     'GPRINT:val_min:MIN:%5.2lf Min,',
1674     'GPRINT:val_avg:AVERAGE:%5.2lf Avg,',
1675     'GPRINT:val_max:MAX:%5.2lf Max,',
1676     'GPRINT:val_avg:LAST:%5.2lf Last'
1677     ],
1678     mysql_handler => ['-v', 'Issues/s',
1679     "DEF:val_avg={file}:value:AVERAGE",
1680     "DEF:val_min={file}:value:MIN",
1681     "DEF:val_max={file}:value:MAX",
1682     "AREA:val_max#$HalfBlue",
1683     "AREA:val_min#$Canvas",
1684     "LINE1:val_avg#$FullBlue:{inst}",
1685     'GPRINT:val_min:MIN:%5.2lf Min,',
1686     'GPRINT:val_avg:AVERAGE:%5.2lf Avg,',
1687     'GPRINT:val_max:MAX:%5.2lf Max,',
1688     'GPRINT:val_avg:LAST:%5.2lf Last'
1689     ],
1690     mysql_octets => ['-v', 'Bytes/s',
1691     'DEF:out_min={file}:tx:MIN',
1692     'DEF:out_avg={file}:tx:AVERAGE',
1693     'DEF:out_max={file}:tx:MAX',
1694     'DEF:inc_min={file}:rx:MIN',
1695     'DEF:inc_avg={file}:rx:AVERAGE',
1696     'DEF:inc_max={file}:rx:MAX',
1697     'CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF',
1698     'CDEF:mytime=out_avg,TIME,TIME,IF',
1699     'CDEF:sample_len_raw=mytime,PREV(mytime),-',
1700     'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
1701     'CDEF:out_avg_sample=out_avg,UN,0,out_avg,IF,sample_len,*',
1702     'CDEF:out_avg_sum=PREV,UN,0,PREV,IF,out_avg_sample,+',
1703     'CDEF:inc_avg_sample=inc_avg,UN,0,inc_avg,IF,sample_len,*',
1704     'CDEF:inc_avg_sum=PREV,UN,0,PREV,IF,inc_avg_sample,+',
1705     "AREA:out_avg#$HalfGreen",
1706     "AREA:inc_avg#$HalfBlue",
1707     "AREA:overlap#$HalfBlueGreen",
1708     "LINE1:out_avg#$FullGreen:Written",
1709     'GPRINT:out_avg:AVERAGE:%5.1lf%s Avg,',
1710     'GPRINT:out_max:MAX:%5.1lf%s Max,',
1711     'GPRINT:out_avg:LAST:%5.1lf%s Last',
1712     'GPRINT:out_avg_sum:LAST:(ca. %5.1lf%sB Total)\l',
1713     "LINE1:inc_avg#$FullBlue:Read   ",
1714     'GPRINT:inc_avg:AVERAGE:%5.1lf%s Avg,',
1715     'GPRINT:inc_max:MAX:%5.1lf%s Max,',
1716     'GPRINT:inc_avg:LAST:%5.1lf%s Last',
1717     'GPRINT:inc_avg_sum:LAST:(ca. %5.1lf%sB Total)\l'
1718     ],
1719     mysql_qcache => ['-v', 'Queries/s',
1720     "DEF:hits_min={file}:hits:MIN",
1721     "DEF:hits_avg={file}:hits:AVERAGE",
1722     "DEF:hits_max={file}:hits:MAX",
1723     "DEF:inserts_min={file}:inserts:MIN",
1724     "DEF:inserts_avg={file}:inserts:AVERAGE",
1725     "DEF:inserts_max={file}:inserts:MAX",
1726     "DEF:not_cached_min={file}:not_cached:MIN",
1727     "DEF:not_cached_avg={file}:not_cached:AVERAGE",
1728     "DEF:not_cached_max={file}:not_cached:MAX",
1729     "DEF:lowmem_prunes_min={file}:lowmem_prunes:MIN",
1730     "DEF:lowmem_prunes_avg={file}:lowmem_prunes:AVERAGE",
1731     "DEF:lowmem_prunes_max={file}:lowmem_prunes:MAX",
1732     "DEF:queries_min={file}:queries_in_cache:MIN",
1733     "DEF:queries_avg={file}:queries_in_cache:AVERAGE",
1734     "DEF:queries_max={file}:queries_in_cache:MAX",
1735     "CDEF:unknown=queries_avg,UNKN,+",
1736     "CDEF:not_cached_agg=hits_avg,inserts_avg,+,not_cached_avg,+",
1737     "CDEF:inserts_agg=hits_avg,inserts_avg,+",
1738     "CDEF:hits_agg=hits_avg",
1739     "AREA:not_cached_agg#$HalfYellow",
1740     "AREA:inserts_agg#$HalfBlue",
1741     "AREA:hits_agg#$HalfGreen",
1742     "LINE1:not_cached_agg#$FullYellow:Not Cached      ",
1743     'GPRINT:not_cached_min:MIN:%5.2lf Min,',
1744     'GPRINT:not_cached_avg:AVERAGE:%5.2lf Avg,',
1745     'GPRINT:not_cached_max:MAX:%5.2lf Max,',
1746     'GPRINT:not_cached_avg:LAST:%5.2lf Last\l',
1747     "LINE1:inserts_agg#$FullBlue:Inserts         ",
1748     'GPRINT:inserts_min:MIN:%5.2lf Min,',
1749     'GPRINT:inserts_avg:AVERAGE:%5.2lf Avg,',
1750     'GPRINT:inserts_max:MAX:%5.2lf Max,',
1751     'GPRINT:inserts_avg:LAST:%5.2lf Last\l',
1752     "LINE1:hits_agg#$FullGreen:Hits            ",
1753     'GPRINT:hits_min:MIN:%5.2lf Min,',
1754     'GPRINT:hits_avg:AVERAGE:%5.2lf Avg,',
1755     'GPRINT:hits_max:MAX:%5.2lf Max,',
1756     'GPRINT:hits_avg:LAST:%5.2lf Last\l',
1757     "LINE1:lowmem_prunes_avg#$FullRed:Lowmem Prunes   ",
1758     'GPRINT:lowmem_prunes_min:MIN:%5.2lf Min,',
1759     'GPRINT:lowmem_prunes_avg:AVERAGE:%5.2lf Avg,',
1760     'GPRINT:lowmem_prunes_max:MAX:%5.2lf Max,',
1761     'GPRINT:lowmem_prunes_avg:LAST:%5.2lf Last\l',
1762     "LINE1:unknown#$Canvas:Queries in cache",
1763     'GPRINT:queries_min:MIN:%5.0lf Min,',
1764     'GPRINT:queries_avg:AVERAGE:%5.0lf Avg,',
1765     'GPRINT:queries_max:MAX:%5.0lf Max,',
1766     'GPRINT:queries_avg:LAST:%5.0lf Last\l'
1767     ],
1768     mysql_threads => ['-v', 'Threads',
1769     "DEF:running_min={file}:running:MIN",
1770     "DEF:running_avg={file}:running:AVERAGE",
1771     "DEF:running_max={file}:running:MAX",
1772     "DEF:connected_min={file}:connected:MIN",
1773     "DEF:connected_avg={file}:connected:AVERAGE",
1774     "DEF:connected_max={file}:connected:MAX",
1775     "DEF:cached_min={file}:cached:MIN",
1776     "DEF:cached_avg={file}:cached:AVERAGE",
1777     "DEF:cached_max={file}:cached:MAX",
1778     "DEF:created_min={file}:created:MIN",
1779     "DEF:created_avg={file}:created:AVERAGE",
1780     "DEF:created_max={file}:created:MAX",
1781     "CDEF:unknown=created_avg,UNKN,+",
1782     "CDEF:cached_agg=connected_avg,cached_avg,+",
1783     "AREA:cached_agg#$HalfGreen",
1784     "AREA:connected_avg#$HalfBlue",
1785     "AREA:running_avg#$HalfRed",
1786     "LINE1:cached_agg#$FullGreen:Cached   ",
1787     'GPRINT:cached_min:MIN:%5.1lf Min,',
1788     'GPRINT:cached_avg:AVERAGE:%5.1lf Avg,',
1789     'GPRINT:cached_max:MAX:%5.1lf Max,',
1790     'GPRINT:cached_avg:LAST:%5.1lf Last\l',
1791     "LINE1:connected_avg#$FullBlue:Connected",
1792     'GPRINT:connected_min:MIN:%5.1lf Min,',
1793     'GPRINT:connected_avg:AVERAGE:%5.1lf Avg,',
1794     'GPRINT:connected_max:MAX:%5.1lf Max,',
1795     'GPRINT:connected_avg:LAST:%5.1lf Last\l',
1796     "LINE1:running_avg#$FullRed:Running  ",
1797     'GPRINT:running_min:MIN:%5.1lf Min,',
1798     'GPRINT:running_avg:AVERAGE:%5.1lf Avg,',
1799     'GPRINT:running_max:MAX:%5.1lf Max,',
1800     'GPRINT:running_avg:LAST:%5.1lf Last\l',
1801     "LINE1:unknown#$Canvas:Created  ",
1802     'GPRINT:created_min:MIN:%5.0lf Min,',
1803     'GPRINT:created_avg:AVERAGE:%5.0lf Avg,',
1804     'GPRINT:created_max:MAX:%5.0lf Max,',
1805     'GPRINT:created_avg:LAST:%5.0lf Last\l'
1806     ],
1807     nfs_procedure => ['-v', 'Issues/s',
1808     'DEF:avg={file}:value:AVERAGE',
1809     'DEF:min={file}:value:MIN',
1810     'DEF:max={file}:value:MAX',
1811     "AREA:max#$HalfBlue",
1812     "AREA:min#$Canvas",
1813     "LINE1:avg#$FullBlue:Issues/s",
1814     'GPRINT:min:MIN:%6.2lf Min,',
1815     'GPRINT:avg:AVERAGE:%6.2lf Avg,',
1816     'GPRINT:max:MAX:%6.2lf Max,',
1817     'GPRINT:avg:LAST:%6.2lf Last\l'
1818     ],
1819     nfs3_procedures => [
1820     "DEF:null_avg={file}:null:AVERAGE",
1821     "DEF:getattr_avg={file}:getattr:AVERAGE",
1822     "DEF:setattr_avg={file}:setattr:AVERAGE",
1823     "DEF:lookup_avg={file}:lookup:AVERAGE",
1824     "DEF:access_avg={file}:access:AVERAGE",
1825     "DEF:readlink_avg={file}:readlink:AVERAGE",
1826     "DEF:read_avg={file}:read:AVERAGE",
1827     "DEF:write_avg={file}:write:AVERAGE",
1828     "DEF:create_avg={file}:create:AVERAGE",
1829     "DEF:mkdir_avg={file}:mkdir:AVERAGE",
1830     "DEF:symlink_avg={file}:symlink:AVERAGE",
1831     "DEF:mknod_avg={file}:mknod:AVERAGE",
1832     "DEF:remove_avg={file}:remove:AVERAGE",
1833     "DEF:rmdir_avg={file}:rmdir:AVERAGE",
1834     "DEF:rename_avg={file}:rename:AVERAGE",
1835     "DEF:link_avg={file}:link:AVERAGE",
1836     "DEF:readdir_avg={file}:readdir:AVERAGE",
1837     "DEF:readdirplus_avg={file}:readdirplus:AVERAGE",
1838     "DEF:fsstat_avg={file}:fsstat:AVERAGE",
1839     "DEF:fsinfo_avg={file}:fsinfo:AVERAGE",
1840     "DEF:pathconf_avg={file}:pathconf:AVERAGE",
1841     "DEF:commit_avg={file}:commit:AVERAGE",
1842     "DEF:null_max={file}:null:MAX",
1843     "DEF:getattr_max={file}:getattr:MAX",
1844     "DEF:setattr_max={file}:setattr:MAX",
1845     "DEF:lookup_max={file}:lookup:MAX",
1846     "DEF:access_max={file}:access:MAX",
1847     "DEF:readlink_max={file}:readlink:MAX",
1848     "DEF:read_max={file}:read:MAX",
1849     "DEF:write_max={file}:write:MAX",
1850     "DEF:create_max={file}:create:MAX",
1851     "DEF:mkdir_max={file}:mkdir:MAX",
1852     "DEF:symlink_max={file}:symlink:MAX",
1853     "DEF:mknod_max={file}:mknod:MAX",
1854     "DEF:remove_max={file}:remove:MAX",
1855     "DEF:rmdir_max={file}:rmdir:MAX",
1856     "DEF:rename_max={file}:rename:MAX",
1857     "DEF:link_max={file}:link:MAX",
1858     "DEF:readdir_max={file}:readdir:MAX",
1859     "DEF:readdirplus_max={file}:readdirplus:MAX",
1860     "DEF:fsstat_max={file}:fsstat:MAX",
1861     "DEF:fsinfo_max={file}:fsinfo:MAX",
1862     "DEF:pathconf_max={file}:pathconf:MAX",
1863     "DEF:commit_max={file}:commit:MAX",
1864     "CDEF:other_avg=null_avg,readlink_avg,create_avg,mkdir_avg,symlink_avg,mknod_avg,remove_avg,rmdir_avg,rename_avg,link_avg,readdir_avg,readdirplus_avg,fsstat_avg,fsinfo_avg,pathconf_avg,+,+,+,+,+,+,+,+,+,+,+,+,+,+",
1865     "CDEF:other_max=null_max,readlink_max,create_max,mkdir_max,symlink_max,mknod_max,remove_max,rmdir_max,rename_max,link_max,readdir_max,readdirplus_max,fsstat_max,fsinfo_max,pathconf_max,+,+,+,+,+,+,+,+,+,+,+,+,+,+",
1866     "CDEF:stack_read=read_avg",
1867     "CDEF:stack_getattr=stack_read,getattr_avg,+",
1868     "CDEF:stack_access=stack_getattr,access_avg,+",
1869     "CDEF:stack_lookup=stack_access,lookup_avg,+",
1870     "CDEF:stack_write=stack_lookup,write_avg,+",
1871     "CDEF:stack_commit=stack_write,commit_avg,+",
1872     "CDEF:stack_setattr=stack_commit,setattr_avg,+",
1873     "CDEF:stack_other=stack_setattr,other_avg,+",
1874     "AREA:stack_other#$HalfRed",
1875     "AREA:stack_setattr#$HalfGreen",
1876     "AREA:stack_commit#$HalfYellow",
1877     "AREA:stack_write#$HalfGreen",
1878     "AREA:stack_lookup#$HalfBlue",
1879     "AREA:stack_access#$HalfMagenta",
1880     "AREA:stack_getattr#$HalfCyan",
1881     "AREA:stack_read#$HalfBlue",
1882     "LINE1:stack_other#$FullRed:Other  ",
1883     'GPRINT:other_max:MAX:%5.1lf Max,',
1884     'GPRINT:other_avg:AVERAGE:%5.1lf Avg,',
1885     'GPRINT:other_avg:LAST:%5.1lf Last\l',
1886     "LINE1:stack_setattr#$FullGreen:setattr",
1887     'GPRINT:setattr_max:MAX:%5.1lf Max,',
1888     'GPRINT:setattr_avg:AVERAGE:%5.1lf Avg,',
1889     'GPRINT:setattr_avg:LAST:%5.1lf Last\l',
1890     "LINE1:stack_commit#$FullYellow:commit ",
1891     'GPRINT:commit_max:MAX:%5.1lf Max,',
1892     'GPRINT:commit_avg:AVERAGE:%5.1lf Avg,',
1893     'GPRINT:commit_avg:LAST:%5.1lf Last\l',
1894     "LINE1:stack_write#$FullGreen:write  ",
1895     'GPRINT:write_max:MAX:%5.1lf Max,',
1896     'GPRINT:write_avg:AVERAGE:%5.1lf Avg,',
1897     'GPRINT:write_avg:LAST:%5.1lf Last\l',
1898     "LINE1:stack_lookup#$FullBlue:lookup ",
1899     'GPRINT:lookup_max:MAX:%5.1lf Max,',
1900     'GPRINT:lookup_avg:AVERAGE:%5.1lf Avg,',
1901     'GPRINT:lookup_avg:LAST:%5.1lf Last\l',
1902     "LINE1:stack_access#$FullMagenta:access ",
1903     'GPRINT:access_max:MAX:%5.1lf Max,',
1904     'GPRINT:access_avg:AVERAGE:%5.1lf Avg,',
1905     'GPRINT:access_avg:LAST:%5.1lf Last\l',
1906     "LINE1:stack_getattr#$FullCyan:getattr",
1907     'GPRINT:getattr_max:MAX:%5.1lf Max,',
1908     'GPRINT:getattr_avg:AVERAGE:%5.1lf Avg,',
1909     'GPRINT:getattr_avg:LAST:%5.1lf Last\l',
1910     "LINE1:stack_read#$FullBlue:read   ",
1911     'GPRINT:read_max:MAX:%5.1lf Max,',
1912     'GPRINT:read_avg:AVERAGE:%5.1lf Avg,',
1913     'GPRINT:read_avg:LAST:%5.1lf Last\l'
1914     ],
1915     opcode => [
1916     'DEF:avg={file}:value:AVERAGE',
1917     'DEF:min={file}:value:MIN',
1918     'DEF:max={file}:value:MAX',
1919     "AREA:max#$HalfBlue",
1920     "AREA:min#$Canvas",
1921     "LINE1:avg#$FullBlue:Queries/s",
1922     'GPRINT:min:MIN:%9.3lf Min,',
1923     'GPRINT:avg:AVERAGE:%9.3lf Average,',
1924     'GPRINT:max:MAX:%9.3lf Max,',
1925     'GPRINT:avg:LAST:%9.3lf Last\l'
1926     ],
1927     partition => [
1928     "DEF:rbyte_avg={file}:rbytes:AVERAGE",
1929     "DEF:rbyte_min={file}:rbytes:MIN",
1930     "DEF:rbyte_max={file}:rbytes:MAX",
1931     "DEF:wbyte_avg={file}:wbytes:AVERAGE",
1932     "DEF:wbyte_min={file}:wbytes:MIN",
1933     "DEF:wbyte_max={file}:wbytes:MAX",
1934     'CDEF:overlap=wbyte_avg,rbyte_avg,GT,rbyte_avg,wbyte_avg,IF',
1935     "AREA:wbyte_avg#$HalfGreen",
1936     "AREA:rbyte_avg#$HalfBlue",
1937     "AREA:overlap#$HalfBlueGreen",
1938     "LINE1:wbyte_avg#$FullGreen:Write",
1939     'GPRINT:wbyte_min:MIN:%5.1lf%s Min,',
1940     'GPRINT:wbyte_avg:AVERAGE:%5.1lf%s Avg,',
1941     'GPRINT:wbyte_max:MAX:%5.1lf%s Max,',
1942     'GPRINT:wbyte_avg:LAST:%5.1lf%s Last\l',
1943     "LINE1:rbyte_avg#$FullBlue:Read ",
1944     'GPRINT:rbyte_min:MIN:%5.1lf%s Min,',
1945     'GPRINT:rbyte_avg:AVERAGE:%5.1lf%s Avg,',
1946     'GPRINT:rbyte_max:MAX:%5.1lf%s Max,',
1947     'GPRINT:rbyte_avg:LAST:%5.1lf%s Last\l'
1948     ],
1949     percent => ['-v', 'Percent',
1950     'DEF:avg={file}:percent:AVERAGE',
1951     'DEF:min={file}:percent:MIN',
1952     'DEF:max={file}:percent:MAX',
1953     "AREA:max#$HalfBlue",
1954     "AREA:min#$Canvas",
1955     "LINE1:avg#$FullBlue:Percent",
1956     'GPRINT:min:MIN:%5.1lf%% Min,',
1957     'GPRINT:avg:AVERAGE:%5.1lf%% Avg,',
1958     'GPRINT:max:MAX:%5.1lf%% Max,',
1959     'GPRINT:avg:LAST:%5.1lf%% Last\l'
1960     ],
1961     ping => ['DEF:ping_avg={file}:ping:AVERAGE',
1962     'DEF:ping_min={file}:ping:MIN',
1963     'DEF:ping_max={file}:ping:MAX',
1964     "AREA:ping_max#$HalfBlue",
1965     "AREA:ping_min#$Canvas",
1966     "LINE1:ping_avg#$FullBlue:Ping",
1967     'GPRINT:ping_min:MIN:%4.1lf ms Min,',
1968     'GPRINT:ping_avg:AVERAGE:%4.1lf ms Avg,',
1969     'GPRINT:ping_max:MAX:%4.1lf ms Max,',
1970     'GPRINT:ping_avg:LAST:%4.1lf ms Last'],
1971     processes => [
1972     "DEF:running_avg={file}:running:AVERAGE",
1973     "DEF:running_min={file}:running:MIN",
1974     "DEF:running_max={file}:running:MAX",
1975     "DEF:sleeping_avg={file}:sleeping:AVERAGE",
1976     "DEF:sleeping_min={file}:sleeping:MIN",
1977     "DEF:sleeping_max={file}:sleeping:MAX",
1978     "DEF:zombies_avg={file}:zombies:AVERAGE",
1979     "DEF:zombies_min={file}:zombies:MIN",
1980     "DEF:zombies_max={file}:zombies:MAX",
1981     "DEF:stopped_avg={file}:stopped:AVERAGE",
1982     "DEF:stopped_min={file}:stopped:MIN",
1983     "DEF:stopped_max={file}:stopped:MAX",
1984     "DEF:paging_avg={file}:paging:AVERAGE",
1985     "DEF:paging_min={file}:paging:MIN",
1986     "DEF:paging_max={file}:paging:MAX",
1987     "DEF:blocked_avg={file}:blocked:AVERAGE",
1988     "DEF:blocked_min={file}:blocked:MIN",
1989     "DEF:blocked_max={file}:blocked:MAX",
1990     'CDEF:paging_acc=sleeping_avg,running_avg,stopped_avg,zombies_avg,blocked_avg,paging_avg,+,+,+,+,+',
1991     'CDEF:blocked_acc=sleeping_avg,running_avg,stopped_avg,zombies_avg,blocked_avg,+,+,+,+',
1992     'CDEF:zombies_acc=sleeping_avg,running_avg,stopped_avg,zombies_avg,+,+,+',
1993     'CDEF:stopped_acc=sleeping_avg,running_avg,stopped_avg,+,+',
1994     'CDEF:running_acc=sleeping_avg,running_avg,+',
1995     'CDEF:sleeping_acc=sleeping_avg',
1996     "AREA:paging_acc#$HalfYellow",
1997     "AREA:blocked_acc#$HalfCyan",
1998     "AREA:zombies_acc#$HalfRed",
1999     "AREA:stopped_acc#$HalfMagenta",
2000     "AREA:running_acc#$HalfGreen",
2001     "AREA:sleeping_acc#$HalfBlue",
2002     "LINE1:paging_acc#$FullYellow:Paging  ",
2003     'GPRINT:paging_min:MIN:%5.1lf Min,',
2004     'GPRINT:paging_avg:AVERAGE:%5.1lf Average,',
2005     'GPRINT:paging_max:MAX:%5.1lf Max,',
2006     'GPRINT:paging_avg:LAST:%5.1lf Last\l',
2007     "LINE1:blocked_acc#$FullCyan:Blocked ",
2008     'GPRINT:blocked_min:MIN:%5.1lf Min,',
2009     'GPRINT:blocked_avg:AVERAGE:%5.1lf Average,',
2010     'GPRINT:blocked_max:MAX:%5.1lf Max,',
2011     'GPRINT:blocked_avg:LAST:%5.1lf Last\l',
2012     "LINE1:zombies_acc#$FullRed:Zombies ",
2013     'GPRINT:zombies_min:MIN:%5.1lf Min,',
2014     'GPRINT:zombies_avg:AVERAGE:%5.1lf Average,',
2015     'GPRINT:zombies_max:MAX:%5.1lf Max,',
2016     'GPRINT:zombies_avg:LAST:%5.1lf Last\l',
2017     "LINE1:stopped_acc#$FullMagenta:Stopped ",
2018     'GPRINT:stopped_min:MIN:%5.1lf Min,',
2019     'GPRINT:stopped_avg:AVERAGE:%5.1lf Average,',
2020     'GPRINT:stopped_max:MAX:%5.1lf Max,',
2021     'GPRINT:stopped_avg:LAST:%5.1lf Last\l',
2022     "LINE1:running_acc#$FullGreen:Running ",
2023     'GPRINT:running_min:MIN:%5.1lf Min,',
2024     'GPRINT:running_avg:AVERAGE:%5.1lf Average,',
2025     'GPRINT:running_max:MAX:%5.1lf Max,',
2026     'GPRINT:running_avg:LAST:%5.1lf Last\l',
2027     "LINE1:sleeping_acc#$FullBlue:Sleeping",
2028     'GPRINT:sleeping_min:MIN:%5.1lf Min,',
2029     'GPRINT:sleeping_avg:AVERAGE:%5.1lf Average,',
2030     'GPRINT:sleeping_max:MAX:%5.1lf Max,',
2031     'GPRINT:sleeping_avg:LAST:%5.1lf Last\l'
2032     ],
2033     ps_rss => [
2034     'DEF:avg={file}:byte:AVERAGE',
2035     'DEF:min={file}:byte:MIN',
2036     'DEF:max={file}:byte:MAX',
2037     "AREA:avg#$HalfBlue",
2038     "LINE1:avg#$FullBlue:RSS",
2039     'GPRINT:min:MIN:%5.1lf%s Min,',
2040     'GPRINT:avg:AVERAGE:%5.1lf%s Avg,',
2041     'GPRINT:max:MAX:%5.1lf%s Max,',
2042     'GPRINT:avg:LAST:%5.1lf%s Last\l'
2043     ],
2044     ps_cputime => [
2045     'DEF:user_avg_raw={file}:user:AVERAGE',
2046     'DEF:user_min_raw={file}:user:MIN',
2047     'DEF:user_max_raw={file}:user:MAX',
2048     'DEF:syst_avg_raw={file}:syst:AVERAGE',
2049     'DEF:syst_min_raw={file}:syst:MIN',
2050     'DEF:syst_max_raw={file}:syst:MAX',
2051     'CDEF:user_avg=user_avg_raw,1000000,/',
2052     'CDEF:user_min=user_min_raw,1000000,/',
2053     'CDEF:user_max=user_max_raw,1000000,/',
2054     'CDEF:syst_avg=syst_avg_raw,1000000,/',
2055     'CDEF:syst_min=syst_min_raw,1000000,/',
2056     'CDEF:syst_max=syst_max_raw,1000000,/',
2057     'CDEF:user_syst=syst_avg,UN,0,syst_avg,IF,user_avg,+',
2058     "AREA:user_syst#$HalfBlue",
2059     "AREA:syst_avg#$HalfRed",
2060     "LINE1:user_syst#$FullBlue:User  ",
2061     'GPRINT:user_min:MIN:%5.1lf%s Min,',
2062     'GPRINT:user_avg:AVERAGE:%5.1lf%s Avg,',
2063     'GPRINT:user_max:MAX:%5.1lf%s Max,',
2064     'GPRINT:user_avg:LAST:%5.1lf%s Last\l',
2065     "LINE1:syst_avg#$FullRed:System",
2066     'GPRINT:syst_min:MIN:%5.1lf%s Min,',
2067     'GPRINT:syst_avg:AVERAGE:%5.1lf%s Avg,',
2068     'GPRINT:syst_max:MAX:%5.1lf%s Max,',
2069     'GPRINT:syst_avg:LAST:%5.1lf%s Last\l'
2070     ],
2071     ps_count => [
2072     'DEF:procs_avg={file}:processes:AVERAGE',
2073     'DEF:procs_min={file}:processes:MIN',
2074     'DEF:procs_max={file}:processes:MAX',
2075     'DEF:thrds_avg={file}:threads:AVERAGE',
2076     'DEF:thrds_min={file}:threads:MIN',
2077     'DEF:thrds_max={file}:threads:MAX',
2078     "AREA:thrds_avg#$HalfBlue",
2079     "AREA:procs_avg#$HalfRed",
2080     "LINE1:thrds_avg#$FullBlue:Threads  ",
2081     'GPRINT:thrds_min:MIN:%5.1lf Min,',
2082     'GPRINT:thrds_avg:AVERAGE:%5.1lf Avg,',
2083     'GPRINT:thrds_max:MAX:%5.1lf Max,',
2084     'GPRINT:thrds_avg:LAST:%5.1lf Last\l',
2085     "LINE1:procs_avg#$FullRed:Processes",
2086     'GPRINT:procs_min:MIN:%5.1lf Min,',
2087     'GPRINT:procs_avg:AVERAGE:%5.1lf Avg,',
2088     'GPRINT:procs_max:MAX:%5.1lf Max,',
2089     'GPRINT:procs_avg:LAST:%5.1lf Last\l'
2090     ],
2091     ps_pagefaults => [
2092     'DEF:minor_avg={file}:minflt:AVERAGE',
2093     'DEF:minor_min={file}:minflt:MIN',
2094     'DEF:minor_max={file}:minflt:MAX',
2095     'DEF:major_avg={file}:majflt:AVERAGE',
2096     'DEF:major_min={file}:majflt:MIN',
2097     'DEF:major_max={file}:majflt:MAX',
2098     'CDEF:minor_major=major_avg,UN,0,major_avg,IF,minor_avg,+',
2099     "AREA:minor_major#$HalfBlue",
2100     "AREA:major_avg#$HalfRed",
2101     "LINE1:minor_major#$FullBlue:Minor",
2102     'GPRINT:minor_min:MIN:%5.1lf%s Min,',
2103     'GPRINT:minor_avg:AVERAGE:%5.1lf%s Avg,',
2104     'GPRINT:minor_max:MAX:%5.1lf%s Max,',
2105     'GPRINT:minor_avg:LAST:%5.1lf%s Last\l',
2106     "LINE1:major_avg#$FullRed:Major",
2107     'GPRINT:major_min:MIN:%5.1lf%s Min,',
2108     'GPRINT:major_avg:AVERAGE:%5.1lf%s Avg,',
2109     'GPRINT:major_max:MAX:%5.1lf%s Max,',
2110     'GPRINT:major_avg:LAST:%5.1lf%s Last\l'
2111     ],
2112     ps_state => ['-v', 'Processes',
2113     'DEF:avg={file}:value:AVERAGE',
2114     'DEF:min={file}:value:MIN',
2115     'DEF:max={file}:value:MAX',
2116     "AREA:max#$HalfBlue",
2117     "AREA:min#$Canvas",
2118     "LINE1:avg#$FullBlue:Processes",
2119     'GPRINT:min:MIN:%6.2lf Min,',
2120     'GPRINT:avg:AVERAGE:%6.2lf Avg,',
2121     'GPRINT:max:MAX:%6.2lf Max,',
2122     'GPRINT:avg:LAST:%6.2lf Last\l'
2123     ],
2124     qtype => [
2125     'DEF:avg={file}:value:AVERAGE',
2126     'DEF:min={file}:value:MIN',
2127     'DEF:max={file}:value:MAX',
2128     "AREA:max#$HalfBlue",
2129     "AREA:min#$Canvas",
2130     "LINE1:avg#$FullBlue:Queries/s",
2131     'GPRINT:min:MIN:%9.3lf Min,',
2132     'GPRINT:avg:AVERAGE:%9.3lf Average,',
2133     'GPRINT:max:MAX:%9.3lf Max,',
2134     'GPRINT:avg:LAST:%9.3lf Last\l'
2135     ],
2136     rcode => [
2137     'DEF:avg={file}:value:AVERAGE',
2138     'DEF:min={file}:value:MIN',
2139     'DEF:max={file}:value:MAX',
2140     "AREA:max#$HalfBlue",
2141     "AREA:min#$Canvas",
2142     "LINE1:avg#$FullBlue:Queries/s",
2143     'GPRINT:min:MIN:%9.3lf Min,',
2144     'GPRINT:avg:AVERAGE:%9.3lf Average,',
2145     'GPRINT:max:MAX:%9.3lf Max,',
2146     'GPRINT:avg:LAST:%9.3lf Last\l'
2147     ],
2148     swap => ['-v', 'Bytes', '-b', '1024',
2149     'DEF:avg={file}:value:AVERAGE',
2150     'DEF:min={file}:value:MIN',
2151     'DEF:max={file}:value:MAX',
2152     "AREA:max#$HalfBlue",
2153     "AREA:min#$Canvas",
2154     "LINE1:avg#$FullBlue:Bytes",
2155     'GPRINT:min:MIN:%6.2lf%sByte Min,',
2156     'GPRINT:avg:AVERAGE:%6.2lf%sByte Avg,',
2157     'GPRINT:max:MAX:%6.2lf%sByte Max,',
2158     'GPRINT:avg:LAST:%6.2lf%sByte Last\l'
2159     ],
2160     ols_swap => [
2161     'DEF:used_avg={file}:used:AVERAGE',
2162     'DEF:used_min={file}:used:MIN',
2163     'DEF:used_max={file}:used:MAX',
2164     'DEF:free_avg={file}:free:AVERAGE',
2165     'DEF:free_min={file}:free:MIN',
2166     'DEF:free_max={file}:free:MAX',
2167     'DEF:cach_avg={file}:cached:AVERAGE',
2168     'DEF:cach_min={file}:cached:MIN',
2169     'DEF:cach_max={file}:cached:MAX',
2170     'DEF:resv_avg={file}:resv:AVERAGE',
2171     'DEF:resv_min={file}:resv:MIN',
2172     'DEF:resv_max={file}:resv:MAX',
2173     'CDEF:cach_avg_notnull=cach_avg,UN,0,cach_avg,IF',
2174     'CDEF:resv_avg_notnull=resv_avg,UN,0,resv_avg,IF',
2175     'CDEF:used_acc=used_avg',
2176     'CDEF:resv_acc=used_acc,resv_avg_notnull,+',
2177     'CDEF:cach_acc=resv_acc,cach_avg_notnull,+',
2178     'CDEF:free_acc=cach_acc,free_avg,+',
2179     "AREA:free_acc#$HalfGreen",
2180     "AREA:cach_acc#$HalfBlue",
2181     "AREA:resv_acc#$HalfYellow",
2182     "AREA:used_acc#$HalfRed",
2183     "LINE1:free_acc#$FullGreen:Free    ",
2184     'GPRINT:free_min:MIN:%5.1lf%s Min,',
2185     'GPRINT:free_avg:AVERAGE:%5.1lf%s Avg,',
2186     'GPRINT:free_max:MAX:%5.1lf%s Max,',
2187     'GPRINT:free_avg:LAST:%5.1lf%s Last\n',
2188     "LINE1:cach_acc#$FullBlue:Cached  ",
2189     'GPRINT:cach_min:MIN:%5.1lf%s Min,',
2190     'GPRINT:cach_avg:AVERAGE:%5.1lf%s Avg,',
2191     'GPRINT:cach_max:MAX:%5.1lf%s Max,',
2192     'GPRINT:cach_avg:LAST:%5.1lf%s Last\l',
2193     "LINE1:resv_acc#$FullYellow:Reserved",
2194     'GPRINT:resv_min:MIN:%5.1lf%s Min,',
2195     'GPRINT:resv_avg:AVERAGE:%5.1lf%s Avg,',
2196     'GPRINT:resv_max:MAX:%5.1lf%s Max,',
2197     'GPRINT:resv_avg:LAST:%5.1lf%s Last\n',
2198     "LINE1:used_acc#$FullRed:Used    ",
2199     'GPRINT:used_min:MIN:%5.1lf%s Min,',
2200     'GPRINT:used_avg:AVERAGE:%5.1lf%s Avg,',
2201     'GPRINT:used_max:MAX:%5.1lf%s Max,',
2202     'GPRINT:used_avg:LAST:%5.1lf%s Last\l'
2203     ],
2204     temperature => ['-v', 'Celsius',
2205     'DEF:temp_avg={file}:value:AVERAGE',
2206     'DEF:temp_min={file}:value:MIN',
2207     'DEF:temp_max={file}:value:MAX',
2208     'CDEF:average=temp_avg,0.2,*,PREV,UN,temp_avg,PREV,IF,0.8,*,+',
2209     'CDEF:derivative=PREV(average),average,-',
2210     'CDEF:rising=derivative,-0.01,LT,INF,UNKN,IF',
2211     'CDEF:falling=derivative,0.01,GT,INF,UNKN,IF',
2212     "AREA:rising#f0fff0",
2213     "AREA:falling#fff0f0",
2214     "AREA:temp_max#$HalfRed",
2215     "AREA:temp_min#$Canvas",
2216     #"LINE1:average#000000",
2217     "LINE1:temp_avg#$FullRed:Temperature",
2218     'GPRINT:temp_min:MIN:%4.1lf Min,',
2219     'GPRINT:temp_avg:AVERAGE:%4.1lf Avg,',
2220     'GPRINT:temp_max:MAX:%4.1lf Max,',
2221     'GPRINT:temp_avg:LAST:%4.1lf Last\l'
2222     ],
2223     timeleft => [
2224     'DEF:avg={file}:timeleft:AVERAGE',
2225     'DEF:min={file}:timeleft:MIN',
2226     'DEF:max={file}:timeleft:MAX',
2227     "AREA:max#$HalfBlue",
2228     "AREA:min#$Canvas",
2229     "LINE1:avg#$FullBlue:Time left [min]",
2230     'GPRINT:min:MIN:%5.1lf%s Min,',
2231     'GPRINT:avg:AVERAGE:%5.1lf%s Avg,',
2232     'GPRINT:max:MAX:%5.1lf%s Max,',
2233     'GPRINT:avg:LAST:%5.1lf%s Last\l'
2234     ],
2235     time_offset => [ # NTPd
2236     'DEF:s_avg={file}:seconds:AVERAGE',
2237     'DEF:s_min={file}:seconds:MIN',
2238     'DEF:s_max={file}:seconds:MAX',
2239     "AREA:s_max#$HalfBlue",
2240     "AREA:s_min#$Canvas",
2241     "LINE1:s_avg#$FullBlue:{inst}",
2242     'GPRINT:s_min:MIN:%7.3lf%s Min,',
2243     'GPRINT:s_avg:AVERAGE:%7.3lf%s Avg,',
2244     'GPRINT:s_max:MAX:%7.3lf%s Max,',
2245     'GPRINT:s_avg:LAST:%7.3lf%s Last'
2246     ],
2247     if_octets => ['-v', 'Bits/s', '-l', '0',
2248     'DEF:out_min_raw={file}:tx:MIN',
2249     'DEF:out_avg_raw={file}:tx:AVERAGE',
2250     'DEF:out_max_raw={file}:tx:MAX',
2251     'DEF:inc_min_raw={file}:rx:MIN',
2252     'DEF:inc_avg_raw={file}:rx:AVERAGE',
2253     'DEF:inc_max_raw={file}:rx:MAX',
2254     'CDEF:out_min=out_min_raw,8,*',
2255     'CDEF:out_avg=out_avg_raw,8,*',
2256     'CDEF:out_max=out_max_raw,8,*',
2257     'CDEF:inc_min=inc_min_raw,8,*',
2258     'CDEF:inc_avg=inc_avg_raw,8,*',
2259     'CDEF:inc_max=inc_max_raw,8,*',
2260     'CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF',
2261     'CDEF:mytime=out_avg_raw,TIME,TIME,IF',
2262     'CDEF:sample_len_raw=mytime,PREV(mytime),-',
2263     'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
2264     'CDEF:out_avg_sample=out_avg_raw,UN,0,out_avg_raw,IF,sample_len,*',
2265     'CDEF:out_avg_sum=PREV,UN,0,PREV,IF,out_avg_sample,+',
2266     'CDEF:inc_avg_sample=inc_avg_raw,UN,0,inc_avg_raw,IF,sample_len,*',
2267     'CDEF:inc_avg_sum=PREV,UN,0,PREV,IF,inc_avg_sample,+',
2268     "AREA:out_avg#$HalfGreen",
2269     "AREA:inc_avg#$HalfBlue",
2270     "AREA:overlap#$HalfBlueGreen",
2271     "LINE1:out_avg#$FullGreen:Outgoing",
2272     'GPRINT:out_avg:AVERAGE:%5.1lf%s Avg,',
2273     'GPRINT:out_max:MAX:%5.1lf%s Max,',
2274     'GPRINT:out_avg:LAST:%5.1lf%s Last',
2275     'GPRINT:out_avg_sum:LAST:(ca. %5.1lf%sB Total)\l',
2276     "LINE1:inc_avg#$FullBlue:Incoming",
2277     #'GPRINT:inc_min:MIN:%5.1lf %s Min,',
2278     'GPRINT:inc_avg:AVERAGE:%5.1lf%s Avg,',
2279     'GPRINT:inc_max:MAX:%5.1lf%s Max,',
2280     'GPRINT:inc_avg:LAST:%5.1lf%s Last',
2281     'GPRINT:inc_avg_sum:LAST:(ca. %5.1lf%sB Total)\l'
2282     ],
2283     cpufreq => [
2284     'DEF:cpufreq_avg={file}:value:AVERAGE',
2285     'DEF:cpufreq_min={file}:value:MIN',
2286     'DEF:cpufreq_max={file}:value:MAX',
2287     "AREA:cpufreq_max#$HalfBlue",
2288     "AREA:cpufreq_min#$Canvas",
2289     "LINE1:cpufreq_avg#$FullBlue:Frequency",
2290     'GPRINT:cpufreq_min:MIN:%5.1lf%s Min,',
2291     'GPRINT:cpufreq_avg:AVERAGE:%5.1lf%s Avg,',
2292     'GPRINT:cpufreq_max:MAX:%5.1lf%s Max,',
2293     'GPRINT:cpufreq_avg:LAST:%5.1lf%s Last\l'
2294     ],
2295     multimeter => [
2296     'DEF:multimeter_avg={file}:value:AVERAGE',
2297     'DEF:multimeter_min={file}:value:MIN',
2298     'DEF:multimeter_max={file}:value:MAX',
2299     "AREA:multimeter_max#$HalfBlue",
2300     "AREA:multimeter_min#$Canvas",
2301     "LINE1:multimeter_avg#$FullBlue:Multimeter",
2302     'GPRINT:multimeter_min:MIN:%4.1lf Min,',
2303     'GPRINT:multimeter_avg:AVERAGE:%4.1lf Average,',
2304     'GPRINT:multimeter_max:MAX:%4.1lf Max,',
2305     'GPRINT:multimeter_avg:LAST:%4.1lf Last\l'
2306     ],
2307     users => [
2308     'DEF:users_avg={file}:users:AVERAGE',
2309     'DEF:users_min={file}:users:MIN',
2310     'DEF:users_max={file}:users:MAX',
2311     "AREA:users_max#$HalfBlue",
2312     "AREA:users_min#$Canvas",
2313     "LINE1:users_avg#$FullBlue:Users",
2314     'GPRINT:users_min:MIN:%4.1lf Min,',
2315     'GPRINT:users_avg:AVERAGE:%4.1lf Average,',
2316     'GPRINT:users_max:MAX:%4.1lf Max,',
2317     'GPRINT:users_avg:LAST:%4.1lf Last\l'
2318     ],
2319     voltage => ['-v', 'Voltage',
2320     'DEF:avg={file}:value:AVERAGE',
2321     'DEF:min={file}:value:MIN',
2322     'DEF:max={file}:value:MAX',
2323     "AREA:max#$HalfBlue",
2324     "AREA:min#$Canvas",
2325     "LINE1:avg#$FullBlue:Voltage",
2326     'GPRINT:min:MIN:%5.1lf%sV Min,',
2327     'GPRINT:avg:AVERAGE:%5.1lf%sV Avg,',
2328     'GPRINT:max:MAX:%5.1lf%sV Max,',
2329     'GPRINT:avg:LAST:%5.1lf%sV Last\l'
2330     ],
2331     vs_threads => [
2332     "DEF:total_avg={file}:total:AVERAGE",
2333     "DEF:total_min={file}:total:MIN",
2334     "DEF:total_max={file}:total:MAX",
2335     "DEF:running_avg={file}:running:AVERAGE",
2336     "DEF:running_min={file}:running:MIN",
2337     "DEF:running_max={file}:running:MAX",
2338     "DEF:uninterruptible_avg={file}:uninterruptible:AVERAGE",
2339     "DEF:uninterruptible_min={file}:uninterruptible:MIN",
2340     "DEF:uninterruptible_max={file}:uninterruptible:MAX",
2341     "DEF:onhold_avg={file}:onhold:AVERAGE",
2342     "DEF:onhold_min={file}:onhold:MIN",
2343     "DEF:onhold_max={file}:onhold:MAX",
2344     "LINE1:total_avg#$FullYellow:Total   ",
2345     'GPRINT:total_min:MIN:%5.1lf Min,',
2346     'GPRINT:total_avg:AVERAGE:%5.1lf Avg.,',
2347     'GPRINT:total_max:MAX:%5.1lf Max,',
2348     'GPRINT:total_avg:LAST:%5.1lf Last\l',
2349     "LINE1:running_avg#$FullRed:Running ",
2350     'GPRINT:running_min:MIN:%5.1lf Min,',
2351     'GPRINT:running_avg:AVERAGE:%5.1lf Avg.,',          
2352     'GPRINT:running_max:MAX:%5.1lf Max,',
2353     'GPRINT:running_avg:LAST:%5.1lf Last\l',
2354     "LINE1:uninterruptible_avg#$FullGreen:Unintr  ",
2355     'GPRINT:uninterruptible_min:MIN:%5.1lf Min,',
2356     'GPRINT:uninterruptible_avg:AVERAGE:%5.1lf Avg.,',
2357     'GPRINT:uninterruptible_max:MAX:%5.1lf Max,',
2358     'GPRINT:uninterruptible_avg:LAST:%5.1lf Last\l',
2359     "LINE1:onhold_avg#$FullBlue:Onhold  ",
2360     'GPRINT:onhold_min:MIN:%5.1lf Min,',
2361     'GPRINT:onhold_avg:AVERAGE:%5.1lf Avg.,',
2362     'GPRINT:onhold_max:MAX:%5.1lf Max,',
2363     'GPRINT:onhold_avg:LAST:%5.1lf Last\l'
2364     ],
2365     vs_memory => [
2366     'DEF:vm_avg={file}:vm:AVERAGE',
2367     'DEF:vm_min={file}:vm:MIN',
2368     'DEF:vm_max={file}:vm:MAX',
2369     'DEF:vml_avg={file}:vml:AVERAGE',
2370     'DEF:vml_min={file}:vml:MIN',
2371     'DEF:vml_max={file}:vml:MAX',
2372     'DEF:rss_avg={file}:rss:AVERAGE',
2373     'DEF:rss_min={file}:rss:MIN',
2374     'DEF:rss_max={file}:rss:MAX',
2375     'DEF:anon_avg={file}:anon:AVERAGE',
2376     'DEF:anon_min={file}:anon:MIN',
2377     'DEF:anon_max={file}:anon:MAX',
2378     "LINE1:vm_avg#$FullYellow:VM     ",
2379     'GPRINT:vm_min:MIN:%5.1lf%s Min,',
2380     'GPRINT:vm_avg:AVERAGE:%5.1lf%s Avg.,',
2381     'GPRINT:vm_max:MAX:%5.1lf%s Avg.,',
2382     'GPRINT:vm_avg:LAST:%5.1lf%s Last\l',
2383     "LINE1:vml_avg#$FullRed:Locked ",
2384     'GPRINT:vml_min:MIN:%5.1lf%s Min,',
2385     'GPRINT:vml_avg:AVERAGE:%5.1lf%s Avg.,',
2386     'GPRINT:vml_max:MAX:%5.1lf%s Avg.,',
2387     'GPRINT:vml_avg:LAST:%5.1lf%s Last\l',
2388     "LINE1:rss_avg#$FullGreen:RSS    ",
2389     'GPRINT:rss_min:MIN:%5.1lf%s Min,',
2390     'GPRINT:rss_avg:AVERAGE:%5.1lf%s Avg.,',
2391     'GPRINT:rss_max:MAX:%5.1lf%s Avg.,',
2392     'GPRINT:rss_avg:LAST:%5.1lf%s Last\l',
2393     "LINE1:anon_avg#$FullBlue:Anon.  ",
2394     'GPRINT:anon_min:MIN:%5.1lf%s Min,',
2395     'GPRINT:anon_avg:AVERAGE:%5.1lf%s Avg.,',
2396     'GPRINT:anon_max:MAX:%5.1lf%s Avg.,',
2397     'GPRINT:anon_avg:LAST:%5.1lf%s Last\l',
2398     ],
2399     vs_processes => [
2400     'DEF:proc_avg={file}:total:AVERAGE',
2401     'DEF:proc_min={file}:total:MIN',
2402     'DEF:proc_max={file}:total:MAX',
2403     "AREA:proc_max#$HalfBlue",
2404     "AREA:proc_min#$Canvas",
2405     "LINE1:proc_avg#$FullBlue:Processes",
2406     'GPRINT:proc_min:MIN:%4.1lf Min,',
2407     'GPRINT:proc_avg:AVERAGE:%4.1lf Avg.,',
2408     'GPRINT:proc_max:MAX:%4.1lf Max,',
2409     'GPRINT:proc_avg:LAST:%4.1lf Last\l'
2410     ],
2411   };
2412   $GraphDefs->{'if_multicast'} = $GraphDefs->{'ipt_packets'};
2413   $GraphDefs->{'if_tx_errors'} = $GraphDefs->{'if_rx_errors'};
2414
2415   $MetaGraphDefs->{'cpu'} = \&meta_graph_cpu;
2416   $MetaGraphDefs->{'memory'} = \&meta_graph_memory;
2417 } # load_graph_definitions
2418
2419 sub meta_graph_generic_stack
2420 {
2421   confess ("Wrong number of arguments") if (@_ != 2);
2422
2423   my $opts = shift;
2424   my $sources = shift;
2425   my $i;
2426
2427   my $timespan_str = _get_param_timespan ();
2428   my $timespan_int = (-1) * $ValidTimespan->{$timespan_str};
2429
2430   $opts->{'title'} ||= 'Unknown title';
2431   $opts->{'rrd_opts'} ||= [];
2432   $opts->{'colors'} ||= {};
2433
2434   my @cmd = ('-', '-a', 'PNG', '-s', $timespan_int,
2435     '-t', $opts->{'title'} || 'Unknown title',
2436     @RRDDefaultArgs, @{$opts->{'rrd_opts'}});
2437
2438   my $max_inst_name = 0;
2439
2440   for ($i = 0; $i < @$sources; $i++)
2441   {
2442     my $inst_data = $sources->[$i];
2443     my $inst_name = $inst_data->{'name'} || confess;
2444     my $file = $inst_data->{'file'} || confess;
2445
2446     if (length ($inst_name) > $max_inst_name)
2447     {
2448       $max_inst_name = length ($inst_name);
2449     }
2450
2451     confess ("No such file: $file") if (!-e $file);
2452
2453     push (@cmd,
2454       qq#DEF:${inst_name}_min=$file:value:MIN#,
2455       qq#DEF:${inst_name}_avg=$file:value:AVERAGE#,
2456       qq#DEF:${inst_name}_max=$file:value:MAX#,
2457       qq#CDEF:${inst_name}_nnl=${inst_name}_avg,UN,0,${inst_name}_avg,IF#);
2458   }
2459
2460   for (my $i = 0; $i < @$sources; $i++)
2461   {
2462     my $inst_data0 = $sources->[@$sources - (1 + $i)];
2463     my $inst_data1 = $sources->[@$sources - (($i == 0) ? 1 : $i)];
2464
2465     my $inst_name0 = $inst_data0->{'name'};
2466     my $inst_name1 = $inst_data1->{'name'};
2467
2468     my $cdef_name = ($i == 0) ? 'nnl' : 'stk';
2469
2470     push (@cmd, qq#CDEF:${inst_name0}_stk=${inst_name0}_nnl,${inst_name1}_${cdef_name},+#);
2471   }
2472
2473   for (my $i = 0; $i < @$sources; $i++)
2474   {
2475     my $inst_data = $sources->[$i];
2476     my $inst_name = $inst_data->{'name'};
2477
2478     my $legend = sprintf ('%-*s', $max_inst_name, $inst_name);
2479
2480     my $line_color;
2481     my $area_color;
2482
2483     my $number_format = $opts->{'number_format'} || '%6.1lf';
2484
2485     if (exists ($opts->{'colors'}{$inst_name}))
2486     {
2487       $line_color = $opts->{'colors'}{$inst_name};
2488       $area_color = _string_to_color ($line_color);
2489     }
2490     else
2491     {
2492       $area_color = _get_random_color ();
2493       $line_color = _color_to_string ($area_color);
2494     }
2495     $area_color = _color_to_string (_get_faded_color ($area_color));
2496
2497     push (@cmd, qq(AREA:${inst_name}_stk#$area_color),
2498       qq(LINE1:${inst_name}_stk#$line_color:$legend),
2499       qq(GPRINT:${inst_name}_min:MIN:$number_format Min,),
2500       qq(GPRINT:${inst_name}_avg:AVERAGE:$number_format Avg,),
2501       qq(GPRINT:${inst_name}_max:MAX:$number_format Max,),
2502       qq(GPRINT:${inst_name}_avg:LAST:$number_format Last\l),
2503     );
2504   }
2505
2506   RRDs::graph (@cmd);
2507   if (my $errmsg = RRDs::error ())
2508   {
2509     confess ("RRDs::graph: $errmsg");
2510   }
2511 } # meta_graph_generic_stack
2512
2513 sub meta_graph_cpu
2514 {
2515   confess ("Wrong number of arguments") if (@_ != 5);
2516
2517   my $host = shift;
2518   my $plugin = shift;
2519   my $plugin_instance = shift;
2520   my $type = shift;
2521   my $type_instances = shift;
2522
2523   my $opts = {};
2524   my $sources = [];
2525
2526   $opts->{'title'} = "$host/$plugin"
2527   . (defined ($plugin_instance) ? "-$plugin_instance" : '') . "/$type";
2528
2529   my @files = ();
2530
2531   $opts->{'colors'} =
2532   {
2533     'idle'      => 'ffffff',
2534     'nice'      => '00e000',
2535     'user'      => '0000ff',
2536     'wait'      => 'ffb000',
2537     'system'    => 'ff0000',
2538     'softirq'   => 'ff00ff',
2539     'interrupt' => 'a000a0',
2540     'steal'     => '000000'
2541   };
2542
2543   _custom_sort_arrayref ($type_instances,
2544     [qw(idle nice user wait system softirq interrupt steal)]);
2545
2546   for (@$type_instances)
2547   {
2548     my $inst = $_;
2549     my $file = '';
2550     my $title = $opts->{'title'};
2551
2552     for (@DataDirs)
2553     {
2554       if (-e "$_/$title-$inst.rrd")
2555       {
2556         $file = "$_/$title-$inst.rrd";
2557         last;
2558       }
2559     }
2560     confess ("No file found for $title") if ($file eq '');
2561
2562     push (@$sources,
2563       {
2564         name => $inst,
2565         file => $file
2566       }
2567     );
2568   } # for (@$type_instances)
2569
2570   return (meta_graph_generic_stack ($opts, $sources));
2571 } # meta_graph_cpu
2572
2573 sub meta_graph_memory
2574 {
2575   confess ("Wrong number of arguments") if (@_ != 5);
2576
2577   my $host = shift;
2578   my $plugin = shift;
2579   my $plugin_instance = shift;
2580   my $type = shift;
2581   my $type_instances = shift;
2582
2583   my $opts = {};
2584   my $sources = [];
2585
2586   $opts->{'title'} = "$host/$plugin"
2587   . (defined ($plugin_instance) ? "-$plugin_instance" : '') . "/$type";
2588   $opts->{'number_format'} = '%5.1lf%s';
2589
2590   $opts->{'rrd_opts'} = ['-b', '1024'];
2591
2592   my @files = ();
2593
2594   $opts->{'colors'} =
2595   {
2596     'free'     => '00e000',
2597     'cached'   => '0000ff',
2598     'buffered' => 'ffb000',
2599     'used'     => 'ff0000'
2600   };
2601
2602   _custom_sort_arrayref ($type_instances,
2603     [qw(free cached buffered used)]);
2604
2605   for (@$type_instances)
2606   {
2607     my $inst = $_;
2608     my $file = '';
2609     my $title = $opts->{'title'};
2610
2611     for (@DataDirs)
2612     {
2613       if (-e "$_/$title-$inst.rrd")
2614       {
2615         $file = "$_/$title-$inst.rrd";
2616         last;
2617       }
2618     }
2619     confess ("No file found for $title") if ($file eq '');
2620
2621     push (@$sources,
2622       {
2623         name => $inst,
2624         file => $file
2625       }
2626     );
2627   } # for (@$type_instances)
2628
2629   return (meta_graph_generic_stack ($opts, $sources));
2630 } # meta_graph_cpu
2631
2632 # vim: shiftwidth=2:softtabstop=2:tabstop=8