Merge branch 'collectd-4.1' into collectd-4.2
[collectd.git] / contrib / collection.cgi
index cffe63b..7da7e1c 100755 (executable)
@@ -209,8 +209,8 @@ sub _find_plugins
     for (@tmp)
     {
       my ($plugin, $instance) = split (m/-/, $_, 2);
-      $plugins{$plugin} = [] if (!$plugins{$plugin});
-      push (@{$plugins{$plugin}}, $instance) if (defined ($instance));
+      $plugins{$plugin} = [] if (!exists $plugins{$plugin});
+      push (@{$plugins{$plugin}}, $instance);
     }
   } # for (@DataDirs)
 
@@ -267,9 +267,11 @@ sub _find_files_for_host
 
     for (@$plugin_instances)
     {
-      my $plugin_instance = $_;
+      my $plugin_instance = defined ($_) ? $_ : '-';
       my %types = _find_types ($host, $plugin,
-       ($plugin_instance ne '-') ? $plugin_instance : undef);
+       ($plugin_instance ne '-')
+       ? $plugin_instance
+       : undef);
 
       $ret->{$plugin}{$plugin_instance} = {};
 
@@ -944,10 +946,10 @@ sub load_graph_definitions
     'GPRINT:max:MAX:%5.1lf%s Max,',
     'GPRINT:avg:LAST:%5.1lf%s Last\l'
     ],
-    charge => [
-    'DEF:avg={file}:charge:AVERAGE',
-    'DEF:min={file}:charge:MIN',
-    'DEF:max={file}:charge:MAX',
+    charge => ['-v', 'Ah',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
     "AREA:max#$HalfBlue",
     "AREA:min#$Canvas",
     "LINE1:avg#$FullBlue:Charge",
@@ -956,18 +958,6 @@ sub load_graph_definitions
     'GPRINT:max:MAX:%5.1lf%sAh Max,',
     'GPRINT:avg:LAST:%5.1lf%sAh Last\l'
     ],
-    charge_percent => [
-    'DEF:avg={file}:percent:AVERAGE',
-    'DEF:min={file}:percent:MIN',
-    'DEF:max={file}:percent:MAX',
-    "AREA:max#$HalfBlue",
-    "AREA:min#$Canvas",
-    "LINE1:avg#$FullBlue:Charge",
-    'GPRINT:min:MIN:%5.1lf%s%% Min,',
-    'GPRINT:avg:AVERAGE:%5.1lf%s%% Avg,',
-    'GPRINT:max:MAX:%5.1lf%s%% Max,',
-    'GPRINT:avg:LAST:%5.1lf%s%% Last\l'
-    ],
     cpu => ['-v', 'CPU load',
     'DEF:avg={file}:value:AVERAGE',
     'DEF:min={file}:value:MIN',
@@ -980,10 +970,10 @@ sub load_graph_definitions
     'GPRINT:max:MAX:%6.2lf%% Max,',
     'GPRINT:avg:LAST:%6.2lf%% Last\l'
     ],
-    current => [
-    'DEF:avg={file}:current:AVERAGE',
-    'DEF:min={file}:current:MIN',
-    'DEF:max={file}:current:MAX',
+    current => ['-v', 'Ampere',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
     "AREA:max#$HalfBlue",
     "AREA:min#$Canvas",
     "LINE1:avg#$FullBlue:Current",
@@ -1301,6 +1291,18 @@ sub load_graph_definitions
     'GPRINT:temp_max:MAX:%4.1lf Max,',
     'GPRINT:temp_avg:LAST:%4.1lf Last\l'
     ],
+    humidity => ['-v', 'Percent',
+    'DEF:temp_avg={file}:value:AVERAGE',
+    'DEF:temp_min={file}:value:MIN',
+    'DEF:temp_max={file}:value:MAX',
+    "AREA:temp_max#$HalfGreen",
+    "AREA:temp_min#$Canvas",
+    "LINE1:temp_avg#$FullGreen:Temperature",
+    'GPRINT:temp_min:MIN:%4.1lf%% Min,',
+    'GPRINT:temp_avg:AVERAGE:%4.1lf%% Avg,',
+    'GPRINT:temp_max:MAX:%4.1lf%% Max,',
+    'GPRINT:temp_avg:LAST:%4.1lf%% Last\l'
+    ],
     if_errors => ['-v', 'Errors/s',
     'DEF:tx_min={file}:tx:MIN',
     'DEF:tx_avg={file}:tx:AVERAGE',
@@ -1588,7 +1590,7 @@ sub load_graph_definitions
     "DEF:val_max={file}:value:MAX",
     "AREA:val_max#$HalfBlue",
     "AREA:val_min#$Canvas",
-    "LINE1:val_avg#$FullBlue:{inst}",
+    "LINE1:val_avg#$FullBlue:Issues/s",
     'GPRINT:val_min:MIN:%5.2lf Min,',
     'GPRINT:val_avg:AVERAGE:%5.2lf Avg,',
     'GPRINT:val_max:MAX:%5.2lf Max,',
@@ -1600,20 +1602,19 @@ sub load_graph_definitions
     "DEF:val_max={file}:value:MAX",
     "AREA:val_max#$HalfBlue",
     "AREA:val_min#$Canvas",
-    "LINE1:val_avg#$FullBlue:{inst}",
+    "LINE1:val_avg#$FullBlue:Issues/s",
     'GPRINT:val_min:MIN:%5.2lf Min,',
     'GPRINT:val_avg:AVERAGE:%5.2lf Avg,',
     'GPRINT:val_max:MAX:%5.2lf Max,',
     'GPRINT:val_avg:LAST:%5.2lf Last'
     ],
-    mysql_octets => ['-v', 'Bytes/s',
+    mysql_octets => ['-v', 'Bits/s',
     'DEF:out_min={file}:tx:MIN',
     'DEF:out_avg={file}:tx:AVERAGE',
     'DEF:out_max={file}:tx:MAX',
     'DEF:inc_min={file}:rx:MIN',
     'DEF:inc_avg={file}:rx:AVERAGE',
     'DEF:inc_max={file}:rx:MAX',
-    'CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF',
     'CDEF:mytime=out_avg,TIME,TIME,IF',
     'CDEF:sample_len_raw=mytime,PREV(mytime),-',
     'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
@@ -1621,18 +1622,25 @@ sub load_graph_definitions
     'CDEF:out_avg_sum=PREV,UN,0,PREV,IF,out_avg_sample,+',
     'CDEF:inc_avg_sample=inc_avg,UN,0,inc_avg,IF,sample_len,*',
     'CDEF:inc_avg_sum=PREV,UN,0,PREV,IF,inc_avg_sample,+',
-    "AREA:out_avg#$HalfGreen",
-    "AREA:inc_avg#$HalfBlue",
+    'CDEF:out_bit_min=out_min,8,*',
+    'CDEF:out_bit_avg=out_avg,8,*',
+    'CDEF:out_bit_max=out_max,8,*',
+    'CDEF:inc_bit_min=inc_min,8,*',
+    'CDEF:inc_bit_avg=inc_avg,8,*',
+    'CDEF:inc_bit_max=inc_max,8,*',
+    'CDEF:overlap=out_bit_avg,inc_bit_avg,GT,inc_bit_avg,out_bit_avg,IF',
+    "AREA:out_bit_avg#$HalfGreen",
+    "AREA:inc_bit_avg#$HalfBlue",
     "AREA:overlap#$HalfBlueGreen",
-    "LINE1:out_avg#$FullGreen:Written",
-    'GPRINT:out_avg:AVERAGE:%5.1lf%s Avg,',
-    'GPRINT:out_max:MAX:%5.1lf%s Max,',
-    'GPRINT:out_avg:LAST:%5.1lf%s Last',
+    "LINE1:out_bit_avg#$FullGreen:Written",
+    'GPRINT:out_bit_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:out_bit_max:MAX:%5.1lf%s Max,',
+    'GPRINT:out_bit_avg:LAST:%5.1lf%s Last',
     'GPRINT:out_avg_sum:LAST:(ca. %5.1lf%sB Total)\l',
-    "LINE1:inc_avg#$FullBlue:Read   ",
-    'GPRINT:inc_avg:AVERAGE:%5.1lf%s Avg,',
-    'GPRINT:inc_max:MAX:%5.1lf%s Max,',
-    'GPRINT:inc_avg:LAST:%5.1lf%s Last',
+    "LINE1:inc_bit_avg#$FullBlue:Read   ",
+    'GPRINT:inc_bit_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:inc_bit_max:MAX:%5.1lf%s Max,',
+    'GPRINT:inc_bit_avg:LAST:%5.1lf%s Last',
     'GPRINT:inc_avg_sum:LAST:(ca. %5.1lf%sB Total)\l'
     ],
     mysql_qcache => ['-v', 'Queries/s',
@@ -1887,6 +1895,18 @@ sub load_graph_definitions
     'GPRINT:ping_avg:AVERAGE:%4.1lf ms Avg,',
     'GPRINT:ping_max:MAX:%4.1lf ms Max,',
     'GPRINT:ping_avg:LAST:%4.1lf ms Last'],
+    power => ['-v', 'Watt',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Watt",
+    'GPRINT:min:MIN:%5.1lf%sW Min,',
+    'GPRINT:avg:AVERAGE:%5.1lf%sW Avg,',
+    'GPRINT:max:MAX:%5.1lf%sW Max,',
+    'GPRINT:avg:LAST:%5.1lf%sW Last\l'
+    ],
     processes => [
     "DEF:running_avg={file}:running:AVERAGE",
     "DEF:running_min={file}:running:MIN",
@@ -1949,18 +1969,27 @@ sub load_graph_definitions
     'GPRINT:sleeping_max:MAX:%5.1lf Max,',
     'GPRINT:sleeping_avg:LAST:%5.1lf Last\l'
     ],
-    ps_rss => [
-    'DEF:avg={file}:byte:AVERAGE',
-    'DEF:min={file}:byte:MIN',
-    'DEF:max={file}:byte:MAX',
-    "AREA:avg#$HalfBlue",
-    "LINE1:avg#$FullBlue:RSS",
-    'GPRINT:min:MIN:%5.1lf%s Min,',
-    'GPRINT:avg:AVERAGE:%5.1lf%s Avg,',
-    'GPRINT:max:MAX:%5.1lf%s Max,',
-    'GPRINT:avg:LAST:%5.1lf%s Last\l'
+    ps_count => ['-v', 'Processes',
+    'DEF:procs_avg={file}:processes:AVERAGE',
+    'DEF:procs_min={file}:processes:MIN',
+    'DEF:procs_max={file}:processes:MAX',
+    'DEF:thrds_avg={file}:threads:AVERAGE',
+    'DEF:thrds_min={file}:threads:MIN',
+    'DEF:thrds_max={file}:threads:MAX',
+    "AREA:thrds_avg#$HalfBlue",
+    "AREA:procs_avg#$HalfRed",
+    "LINE1:thrds_avg#$FullBlue:Threads  ",
+    'GPRINT:thrds_min:MIN:%5.1lf Min,',
+    'GPRINT:thrds_avg:AVERAGE:%5.1lf Avg,',
+    'GPRINT:thrds_max:MAX:%5.1lf Max,',
+    'GPRINT:thrds_avg:LAST:%5.1lf Last\l',
+    "LINE1:procs_avg#$FullRed:Processes",
+    'GPRINT:procs_min:MIN:%5.1lf Min,',
+    'GPRINT:procs_avg:AVERAGE:%5.1lf Avg,',
+    'GPRINT:procs_max:MAX:%5.1lf Max,',
+    'GPRINT:procs_avg:LAST:%5.1lf Last\l'
     ],
-    ps_cputime => [
+    ps_cputime => ['-v', 'Jiffies',
     'DEF:user_avg_raw={file}:user:AVERAGE',
     'DEF:user_min_raw={file}:user:MIN',
     'DEF:user_max_raw={file}:user:MAX',
@@ -1987,27 +2016,7 @@ sub load_graph_definitions
     'GPRINT:syst_max:MAX:%5.1lf%s Max,',
     'GPRINT:syst_avg:LAST:%5.1lf%s Last\l'
     ],
-    ps_count => [
-    'DEF:procs_avg={file}:processes:AVERAGE',
-    'DEF:procs_min={file}:processes:MIN',
-    'DEF:procs_max={file}:processes:MAX',
-    'DEF:thrds_avg={file}:threads:AVERAGE',
-    'DEF:thrds_min={file}:threads:MIN',
-    'DEF:thrds_max={file}:threads:MAX',
-    "AREA:thrds_avg#$HalfBlue",
-    "AREA:procs_avg#$HalfRed",
-    "LINE1:thrds_avg#$FullBlue:Threads  ",
-    'GPRINT:thrds_min:MIN:%5.1lf Min,',
-    'GPRINT:thrds_avg:AVERAGE:%5.1lf Avg,',
-    'GPRINT:thrds_max:MAX:%5.1lf Max,',
-    'GPRINT:thrds_avg:LAST:%5.1lf Last\l',
-    "LINE1:procs_avg#$FullRed:Processes",
-    'GPRINT:procs_min:MIN:%5.1lf Min,',
-    'GPRINT:procs_avg:AVERAGE:%5.1lf Avg,',
-    'GPRINT:procs_max:MAX:%5.1lf Max,',
-    'GPRINT:procs_avg:LAST:%5.1lf Last\l'
-    ],
-    ps_pagefaults => [
+    ps_pagefaults => ['-v', 'Pagefaults/s',
     'DEF:minor_avg={file}:minflt:AVERAGE',
     'DEF:minor_min={file}:minflt:MIN',
     'DEF:minor_max={file}:minflt:MAX',
@@ -2028,6 +2037,17 @@ sub load_graph_definitions
     'GPRINT:major_max:MAX:%5.1lf%s Max,',
     'GPRINT:major_avg:LAST:%5.1lf%s Last\l'
     ],
+    ps_rss => ['-v', 'Bytes',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:avg#$HalfBlue",
+    "LINE1:avg#$FullBlue:RSS",
+    'GPRINT:min:MIN:%5.1lf%s Min,',
+    'GPRINT:avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:max:MAX:%5.1lf%s Max,',
+    'GPRINT:avg:LAST:%5.1lf%s Last\l'
+    ],
     ps_state => ['-v', 'Processes',
     'DEF:avg={file}:value:AVERAGE',
     'DEF:min={file}:value:MIN',
@@ -2076,7 +2096,7 @@ sub load_graph_definitions
     'GPRINT:max:MAX:%6.2lf%sByte Max,',
     'GPRINT:avg:LAST:%6.2lf%sByte Last\l'
     ],
-    ols_swap => [
+    old_swap => [
     'DEF:used_avg={file}:used:AVERAGE',
     'DEF:used_min={file}:used:MIN',
     'DEF:used_max={file}:used:MAX',
@@ -2120,26 +2140,32 @@ sub load_graph_definitions
     'GPRINT:used_max:MAX:%5.1lf%s Max,',
     'GPRINT:used_avg:LAST:%5.1lf%s Last\l'
     ],
+    tcp_connections => ['-v', 'Connections',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Connections",
+    'GPRINT:min:MIN:%4.1lf Min,',
+    'GPRINT:avg:AVERAGE:%4.1lf Avg,',
+    'GPRINT:max:MAX:%4.1lf Max,',
+    'GPRINT:avg:LAST:%4.1lf Last\l'
+    ],
     temperature => ['-v', 'Celsius',
     'DEF:temp_avg={file}:value:AVERAGE',
     'DEF:temp_min={file}:value:MIN',
     'DEF:temp_max={file}:value:MAX',
     'CDEF:average=temp_avg,0.2,*,PREV,UN,temp_avg,PREV,IF,0.8,*,+',
-    'CDEF:derivative=PREV(average),average,-',
-    'CDEF:rising=derivative,-0.01,LT,INF,UNKN,IF',
-    'CDEF:falling=derivative,0.01,GT,INF,UNKN,IF',
-    "AREA:rising#f0fff0",
-    "AREA:falling#fff0f0",
     "AREA:temp_max#$HalfRed",
     "AREA:temp_min#$Canvas",
-    #"LINE1:average#000000",
     "LINE1:temp_avg#$FullRed:Temperature",
     'GPRINT:temp_min:MIN:%4.1lf Min,',
     'GPRINT:temp_avg:AVERAGE:%4.1lf Avg,',
     'GPRINT:temp_max:MAX:%4.1lf Max,',
     'GPRINT:temp_avg:LAST:%4.1lf Last\l'
     ],
-    timeleft => [
+    timeleft => ['-v', 'Minutes',
     'DEF:avg={file}:timeleft:AVERAGE',
     'DEF:min={file}:timeleft:MIN',
     'DEF:max={file}:timeleft:MAX',
@@ -2223,7 +2249,7 @@ sub load_graph_definitions
     'GPRINT:multimeter_max:MAX:%4.1lf Max,',
     'GPRINT:multimeter_avg:LAST:%4.1lf Last\l'
     ],
-    users => [
+    users => ['-v', 'Users',
     'DEF:users_avg={file}:users:AVERAGE',
     'DEF:users_min={file}:users:MIN',
     'DEF:users_max={file}:users:MAX',
@@ -2332,7 +2358,15 @@ sub load_graph_definitions
   $GraphDefs->{'if_tx_errors'} = $GraphDefs->{'if_rx_errors'};
 
   $MetaGraphDefs->{'cpu'} = \&meta_graph_cpu;
+  $MetaGraphDefs->{'if_rx_errors'} = \&meta_graph_if_rx_errors;
+  $MetaGraphDefs->{'if_tx_errors'} = \&meta_graph_if_rx_errors;
   $MetaGraphDefs->{'memory'} = \&meta_graph_memory;
+  $MetaGraphDefs->{'nfs_procedure'} = \&meta_graph_nfs_procedure;
+  $MetaGraphDefs->{'ps_state'} = \&meta_graph_ps_state;
+  $MetaGraphDefs->{'swap'} = \&meta_graph_swap;
+  $MetaGraphDefs->{'mysql_commands'} = \&meta_graph_mysql_commands;
+  $MetaGraphDefs->{'mysql_handler'} = \&meta_graph_mysql_commands;
+  $MetaGraphDefs->{'tcp_connections'} = \&meta_graph_tcp_connections;
 } # load_graph_definitions
 
 sub meta_graph_generic_stack
@@ -2376,17 +2410,21 @@ sub meta_graph_generic_stack
       qq#CDEF:${inst_name}_nnl=${inst_name}_avg,UN,0,${inst_name}_avg,IF#);
   }
 
-  for (my $i = 0; $i < @$sources; $i++)
   {
-    my $inst_data0 = $sources->[@$sources - (1 + $i)];
-    my $inst_data1 = $sources->[@$sources - (($i == 0) ? 1 : $i)];
+    my $inst_data = $sources->[@$sources - 1];
+    my $inst_name = $inst_data->{'name'};
+
+    push (@cmd, qq#CDEF:${inst_name}_stk=${inst_name}_nnl#);
+  }
+  for (my $i = 1; $i < @$sources; $i++)
+  {
+    my $inst_data0 = $sources->[@$sources - ($i + 1)];
+    my $inst_data1 = $sources->[@$sources - $i];
 
     my $inst_name0 = $inst_data0->{'name'};
     my $inst_name1 = $inst_data1->{'name'};
 
-    my $cdef_name = ($i == 0) ? 'nnl' : 'stk';
-
-    push (@cmd, qq#CDEF:${inst_name0}_stk=${inst_name0}_nnl,${inst_name1}_${cdef_name},+#);
+    push (@cmd, qq#CDEF:${inst_name0}_stk=${inst_name0}_nnl,${inst_name1}_stk,+#);
   }
 
   for (my $i = 0; $i < @$sources; $i++)
@@ -2418,7 +2456,7 @@ sub meta_graph_generic_stack
       qq(GPRINT:${inst_name}_min:MIN:$number_format Min,),
       qq(GPRINT:${inst_name}_avg:AVERAGE:$number_format Avg,),
       qq(GPRINT:${inst_name}_max:MAX:$number_format Max,),
-      qq(GPRINT:${inst_name}_avg:LAST:$number_format Last\l),
+      qq(GPRINT:${inst_name}_avg:LAST:$number_format Last\\l),
     );
   }
 
@@ -2445,6 +2483,8 @@ sub meta_graph_cpu
   $opts->{'title'} = "$host/$plugin"
   . (defined ($plugin_instance) ? "-$plugin_instance" : '') . "/$type";
 
+  $opts->{'rrd_opts'} = ['-v', 'Percent'];
+
   my @files = ();
 
   $opts->{'colors'} =
@@ -2506,7 +2546,7 @@ sub meta_graph_memory
   . (defined ($plugin_instance) ? "-$plugin_instance" : '') . "/$type";
   $opts->{'number_format'} = '%5.1lf%s';
 
-  $opts->{'rrd_opts'} = ['-b', '1024'];
+  $opts->{'rrd_opts'} = ['-b', '1024', '-v', 'Bytes'];
 
   my @files = ();
 
@@ -2548,4 +2588,326 @@ sub meta_graph_memory
   return (meta_graph_generic_stack ($opts, $sources));
 } # meta_graph_cpu
 
+sub meta_graph_if_rx_errors
+{
+  confess ("Wrong number of arguments") if (@_ != 5);
+
+  my $host = shift;
+  my $plugin = shift;
+  my $plugin_instance = shift;
+  my $type = shift;
+  my $type_instances = shift;
+
+  my $opts = {};
+  my $sources = [];
+
+  $opts->{'title'} = "$host/$plugin"
+  . (defined ($plugin_instance) ? "-$plugin_instance" : '') . "/$type";
+  $opts->{'number_format'} = '%5.2lf';
+  $opts->{'rrd_opts'} = ['-v', 'Errors/s'];
+
+  my @files = ();
+
+  for (sort @$type_instances)
+  {
+    my $inst = $_;
+    my $file = '';
+    my $title = $opts->{'title'};
+
+    for (@DataDirs)
+    {
+      if (-e "$_/$title-$inst.rrd")
+      {
+       $file = "$_/$title-$inst.rrd";
+       last;
+      }
+    }
+    confess ("No file found for $title") if ($file eq '');
+
+    push (@$sources,
+      {
+       name => $inst,
+       file => $file
+      }
+    );
+  } # for (@$type_instances)
+
+  return (meta_graph_generic_stack ($opts, $sources));
+} # meta_graph_if_rx_errors
+
+sub meta_graph_mysql_commands
+{
+  confess ("Wrong number of arguments") if (@_ != 5);
+
+  my $host = shift;
+  my $plugin = shift;
+  my $plugin_instance = shift;
+  my $type = shift;
+  my $type_instances = shift;
+
+  my $opts = {};
+  my $sources = [];
+
+  $opts->{'title'} = "$host/$plugin"
+  . (defined ($plugin_instance) ? "-$plugin_instance" : '') . "/$type";
+  $opts->{'number_format'} = '%5.2lf';
+
+  my @files = ();
+
+  for (sort @$type_instances)
+  {
+    my $inst = $_;
+    my $file = '';
+    my $title = $opts->{'title'};
+
+    for (@DataDirs)
+    {
+      if (-e "$_/$title-$inst.rrd")
+      {
+       $file = "$_/$title-$inst.rrd";
+       last;
+      }
+    }
+    confess ("No file found for $title") if ($file eq '');
+
+    push (@$sources,
+      {
+       name => $inst,
+       file => $file
+      }
+    );
+  } # for (@$type_instances)
+
+  return (meta_graph_generic_stack ($opts, $sources));
+} # meta_graph_mysql_commands
+
+sub meta_graph_nfs_procedure
+{
+  confess ("Wrong number of arguments") if (@_ != 5);
+
+  my $host = shift;
+  my $plugin = shift;
+  my $plugin_instance = shift;
+  my $type = shift;
+  my $type_instances = shift;
+
+  my $opts = {};
+  my $sources = [];
+
+  $opts->{'title'} = "$host/$plugin"
+  . (defined ($plugin_instance) ? "-$plugin_instance" : '') . "/$type";
+  $opts->{'number_format'} = '%5.1lf%s';
+
+  my @files = ();
+
+  for (sort @$type_instances)
+  {
+    my $inst = $_;
+    my $file = '';
+    my $title = $opts->{'title'};
+
+    for (@DataDirs)
+    {
+      if (-e "$_/$title-$inst.rrd")
+      {
+       $file = "$_/$title-$inst.rrd";
+       last;
+      }
+    }
+    confess ("No file found for $title") if ($file eq '');
+
+    push (@$sources,
+      {
+       name => $inst,
+       file => $file
+      }
+    );
+  } # for (@$type_instances)
+
+  return (meta_graph_generic_stack ($opts, $sources));
+} # meta_graph_nfs_procedure
+
+sub meta_graph_ps_state
+{
+  confess ("Wrong number of arguments") if (@_ != 5);
+
+  my $host = shift;
+  my $plugin = shift;
+  my $plugin_instance = shift;
+  my $type = shift;
+  my $type_instances = shift;
+
+  my $opts = {};
+  my $sources = [];
+
+  $opts->{'title'} = "$host/$plugin"
+  . (defined ($plugin_instance) ? "-$plugin_instance" : '') . "/$type";
+  $opts->{'rrd_opts'} = ['-v', 'Processes'];
+
+  my @files = ();
+
+  $opts->{'colors'} =
+  {
+    'Running'      => '00e000',
+    'Sleeping'  => '0000ff',
+    'Paging'      => 'ffb000',
+    'Zombies'   => 'ff0000',
+    'Blocked'   => 'ff00ff',
+    'Stopped' => 'a000a0'
+  };
+
+  _custom_sort_arrayref ($type_instances,
+    [qw(paging blocked zombies stopped running sleeping)]);
+
+  for (@$type_instances)
+  {
+    my $inst = $_;
+    my $file = '';
+    my $title = $opts->{'title'};
+
+    for (@DataDirs)
+    {
+      if (-e "$_/$title-$inst.rrd")
+      {
+       $file = "$_/$title-$inst.rrd";
+       last;
+      }
+    }
+    confess ("No file found for $title") if ($file eq '');
+
+    push (@$sources,
+      {
+       name => ucfirst ($inst),
+       file => $file
+      }
+    );
+  } # for (@$type_instances)
+
+  return (meta_graph_generic_stack ($opts, $sources));
+} # meta_graph_ps_state
+
+sub meta_graph_swap
+{
+  confess ("Wrong number of arguments") if (@_ != 5);
+
+  my $host = shift;
+  my $plugin = shift;
+  my $plugin_instance = shift;
+  my $type = shift;
+  my $type_instances = shift;
+
+  my $opts = {};
+  my $sources = [];
+
+  $opts->{'title'} = "$host/$plugin"
+  . (defined ($plugin_instance) ? "-$plugin_instance" : '') . "/$type";
+  $opts->{'number_format'} = '%5.1lf%s';
+  $opts->{'rrd_opts'} = ['-v', 'Bytes'];
+
+  my @files = ();
+
+  $opts->{'colors'} =
+  {
+    'Free'     => '00e000',
+    'Cached'   => '0000ff',
+    'Reserved' => 'ffb000',
+    'Used'     => 'ff0000'
+  };
+
+  _custom_sort_arrayref ($type_instances,
+    [qw(free cached reserved used)]);
+
+  for (@$type_instances)
+  {
+    my $inst = $_;
+    my $file = '';
+    my $title = $opts->{'title'};
+
+    for (@DataDirs)
+    {
+      if (-e "$_/$title-$inst.rrd")
+      {
+       $file = "$_/$title-$inst.rrd";
+       last;
+      }
+    }
+    confess ("No file found for $title") if ($file eq '');
+
+    push (@$sources,
+      {
+       name => ucfirst ($inst),
+       file => $file
+      }
+    );
+  } # for (@$type_instances)
+
+  return (meta_graph_generic_stack ($opts, $sources));
+} # meta_graph_swap
+
+sub meta_graph_tcp_connections
+{
+  confess ("Wrong number of arguments") if (@_ != 5);
+
+  my $host = shift;
+  my $plugin = shift;
+  my $plugin_instance = shift;
+  my $type = shift;
+  my $type_instances = shift;
+
+  my $opts = {};
+  my $sources = [];
+
+  $opts->{'title'} = "$host/$plugin"
+  . (defined ($plugin_instance) ? "-$plugin_instance" : '') . "/$type";
+  $opts->{'number_format'} = '%6.2lf';
+
+  $opts->{'rrd_opts'} = ['-v', 'Connections'];
+
+  my @files = ();
+
+  $opts->{'colors'} =
+  {
+    ESTABLISHED          => '00e000',
+    SYN_SENT     => '00e0ff',
+    SYN_RECV     => '00e0a0',
+    FIN_WAIT1    => 'f000f0',
+    FIN_WAIT2    => 'f000a0',
+    TIME_WAIT    => 'ffb000',
+    CLOSE        => '0000f0',
+    CLOSE_WAIT   => '0000a0',
+    LAST_ACK     => '000080',
+    LISTEN       => 'ff0000',
+    CLOSING      => '000000'
+  };
+
+  _custom_sort_arrayref ($type_instances,
+    [reverse qw(ESTABLISHED SYN_SENT SYN_RECV FIN_WAIT1 FIN_WAIT2 TIME_WAIT CLOSE
+    CLOSE_WAIT LAST_ACK CLOSING LISTEN)]);
+
+  for (@$type_instances)
+  {
+    my $inst = $_;
+    my $file = '';
+    my $title = $opts->{'title'};
+
+    for (@DataDirs)
+    {
+      if (-e "$_/$title-$inst.rrd")
+      {
+       $file = "$_/$title-$inst.rrd";
+       last;
+      }
+    }
+    confess ("No file found for $title") if ($file eq '');
+
+    push (@$sources,
+      {
+       name => $inst,
+       file => $file
+      }
+    );
+  } # for (@$type_instances)
+
+  return (meta_graph_generic_stack ($opts, $sources));
+} # meta_graph_tcp_connections
 # vim: shiftwidth=2:softtabstop=2:tabstop=8