#!/usr/bin/perl
# -*- perl -*-

=head1 NAME

squid - Plugin to monitor squid statistics

=head1 APPLICABLE SYSTEMS

Any system running squid and avialable cache_object://

=head1 CONFIGURATION

The following environment settings are the default configuration.  

  [squid]
   env.squidhost localhost
   env.squidport 3128
   env.squiduser [empty]
   env.squidpasswd [empty]
   env.squidreqtimeout 5

=head1 INTERPRETATION

The plugin shows various statistics, current it:
- efficiency per 5 and 60 min
- traffic
- IP cache
- requests and errors
- storedir max and current size
- memory
- mean object size
- cpu
- median service times per 5 and 60 min
- internal data structures

=head1 MAGIC MARKERS

  #%# family=squid
  #%# capabilities=autoconf

=head1 VERSION

  1.0

=head1 BUGS



=head1 AUTHOR

  Gorlow Maxim aka Sheridan <sheridan@sheridan-home.ru> <- jabber and mail

=head1 LICENSE

GPLv2

=cut

use strict;
use warnings;
use IO::Socket;
use MIME::Base64;
use Munin::Plugin;

need_multigraph();

my $squid_host            = $ENV{squidhost}       || "localhost";
my $squid_port            = $ENV{squidport}       || 3128;
my $squid_user            = $ENV{squiduser}       || "";
my $squid_passwd          = $ENV{squidpasswd}     || "";
my $squid_request_timeout = $ENV{squidreqtimeout} || "5";

sub make_request
{
  my $what = $_[0];
  my $r_text = <<_;
GET cache_object://%s/%s HTTP/1.0
Accept: */*
%s
_
  return sprintf($r_text, $squid_host, $what, &make_auth_header());
}

sub make_auth_header 
{
  if(defined $squid_passwd && $squid_passwd ne "") 
  {
    my $h_text = <<_;
Authorization: Basic %s
Proxy-Authorization: Basic %s
_
    my $auth = MIME::Base64::encode_base64(($squid_user ? $squid_user : "") . ":$squid_passwd", "");
    return sprintf($h_text, $auth, $auth);
  }
  return "";
}

sub squid_requst
{
  my $what = $_[0];
  die "Could not connect: $!\n" unless my $cachemgr = IO::Socket::INET->new(PeerAddr => $squid_host, 
                                                                            PeerPort => $squid_port, 
                                                                            Proto    => 'tcp', 
                                                                            Timeout  => $squid_request_timeout);
  my $request = &make_request($what);
  $cachemgr->syswrite($request, length($request));
  return $cachemgr;
}

if($ARGV[0] and $ARGV[0] eq "autoconf") 
{
  if (squid_requst('menu')->getline ne "") { print "yes\n"; }
  exit 0;
}

if($ARGV[0] and $ARGV[0] eq "config") 
{
  my %config;
  # ------------------------------------------------- squid_efficiency_ -----------------------------------------
  foreach my $time (qw(5 60))
  {
    my $name = sprintf("squid_efficiency_%s", $time);
    $config{$name}{'graph'}{'title'}    = "Cache efficiency in ${time}min";
    $config{$name}{'graph'}{'vlabel'}   = '%';
    $config{$name}{'graph'}{'args'}     = '--lower-limit 0 --upper-limit 100';
    $config{$name}{'graph'}{'scale'}    = 'no';
    $config{$name}{'graph'}{'category'} = 'webserver';
    $config{$name}{'graph'}{'order'}    = 'all bytes memory disk';
    $config{$name}{'field'}{'all'}{'draw'}     = 'AREA';
    $config{$name}{'field'}{'all'}{'label'}    = 'Hits of all requests';
    $config{$name}{'field'}{'bytes'}{'draw'}   = 'LINE1';
    $config{$name}{'field'}{'bytes'}{'label'}  = 'Hits of bytes sent';
    $config{$name}{'field'}{'memory'}{'draw'}  = 'LINE1';
    $config{$name}{'field'}{'memory'}{'label'} = 'Memory hits of hit requests';
    $config{$name}{'field'}{'disk'}{'draw'}    = 'LINE1';
    $config{$name}{'field'}{'disk'}{'label'}   = 'Disk hits of hit requests';
    foreach my $fld (qw(all bytes memory disk))
    {
      $config{$name}{'field'}{$fld}{'max'} = 100;
      $config{$name}{'field'}{$fld}{'min'} = 0;
    }
  }
  # ------------------------------------------------- squid_traffic -----------------------------------------
  $config{'squid_traffic'}{'graph'}{'title'}    = 'Traffic statistics';
  $config{'squid_traffic'}{'graph'}{'vlabel'}   = 'bytes in (-) / out (+) per second';
  $config{'squid_traffic'}{'graph'}{'args'}     = '--base 1000';
  $config{'squid_traffic'}{'graph'}{'category'} = 'webserver';
  $config{'squid_traffic'}{'graph'}{'order'}    = 'client_http_in server_all_in server_http_in server_ftp_in ' .
                                                  'server_other_in icp_in icp_q_in icp_r_in cd_in client_http_hit_out ' .
                                                  'client_http_out server_all_out server_http_out server_ftp_out ' .
                                                  'server_other_out icp_out icp_q_out icp_r_out cd_out';
  $config{'squid_traffic'}{'field'}{'client_http_hit_out'}{'type'}  = 'COUNTER';
  $config{'squid_traffic'}{'field'}{'client_http_hit_out'}{'draw'}  = 'AREA';
  $config{'squid_traffic'}{'field'}{'client_http_hit_out'}{'cdef'}  = 'client_http_hit_out,1024,*';
  $config{'squid_traffic'}{'field'}{'client_http_hit_out'}{'label'} = 'Client HTTP hit (out)';
  $config{'squid_traffic'}{'field'}{'client_http_out'}{'label'}  = 'Client HTTP';
  $config{'squid_traffic'}{'field'}{'server_all_out'}{'label'}   = 'Server all';
  $config{'squid_traffic'}{'field'}{'server_http_out'}{'label'}  = 'Server HTTP';
  $config{'squid_traffic'}{'field'}{'server_ftp_out'}{'label'}   = 'Server FTP';
  $config{'squid_traffic'}{'field'}{'server_other_out'}{'label'} = 'Server other';
  $config{'squid_traffic'}{'field'}{'icp_out'}{'label'}          = 'ICP all';
  $config{'squid_traffic'}{'field'}{'icp_q_out'}{'label'}        = 'ICP queryes';
  $config{'squid_traffic'}{'field'}{'icp_r_out'}{'label'}        = 'ICP replies';
  $config{'squid_traffic'}{'field'}{'cd_out'}{'label'}           = 'Cache digest';
  foreach my $fld (qw(client_http server_all server_http server_ftp server_other icp icp_q icp_r cd))
  {
    my ($namein, $nameout) = (sprintf("%s_in", $fld), sprintf("%s_out", $fld));
    $config{'squid_traffic'}{'field'}{$namein}{'type'}  = 'COUNTER';
    $config{'squid_traffic'}{'field'}{$namein}{'cdef'}  = sprintf("%s,1024,*", $namein);
    $config{'squid_traffic'}{'field'}{$namein}{'label'} = 'none';
    $config{'squid_traffic'}{'field'}{$namein}{'graph'} = 'no';
    $config{'squid_traffic'}{'field'}{$nameout}{'type'}     = 'COUNTER';
    $config{'squid_traffic'}{'field'}{$nameout}{'draw'}     = 'LINE1';
    $config{'squid_traffic'}{'field'}{$nameout}{'cdef'}     = sprintf("%s,1024,*", $nameout);
    $config{'squid_traffic'}{'field'}{$nameout}{'negative'} = $namein;
  }
  # ------------------------------------------------- squid_ipcache -----------------------------------------
  $config{'squid_ipcache'}{'graph'}{'title'}    = 'IP cache statistics';
  $config{'squid_ipcache'}{'graph'}{'vlabel'}   = 'Count';
  $config{'squid_ipcache'}{'graph'}{'args'}     = '--base 1000';# --logarithmic';
  $config{'squid_ipcache'}{'graph'}{'category'} = 'webserver';
  $config{'squid_ipcache'}{'graph'}{'order'}    = 'request hits misses numhits neghits invdreqests entries';
  $config{'squid_ipcache'}{'field'}{'entries'}{'label'}     = 'Entries';
  $config{'squid_ipcache'}{'field'}{'request'}{'label'}     = 'Requests';
  $config{'squid_ipcache'}{'field'}{'hits'}{'label'}        = 'Hits';
  $config{'squid_ipcache'}{'field'}{'neghits'}{'label'}     = 'Negative Hits';
  $config{'squid_ipcache'}{'field'}{'numhits'}{'label'}     = 'Numeric Hits';
  $config{'squid_ipcache'}{'field'}{'misses'}{'label'}      = 'Misses';
  $config{'squid_ipcache'}{'field'}{'invdreqests'}{'label'} = 'Invalid Request';
  $config{'squid_ipcache'}{'field'}{'request'}{'draw'}  = 'AREA';
  $config{'squid_ipcache'}{'field'}{'misses'}{'draw'}   = 'AREA';
  $config{'squid_ipcache'}{'field'}{'hits'}{'draw'}     = 'AREA';
  # ------------------------------------------------- squid_requests -----------------------------------------
  $config{'squid_requests'}{'graph'}{'title'}    = 'Requests statistics';
  $config{'squid_requests'}{'graph'}{'vlabel'}   = 'errors (-) / requests (+) per second';
  $config{'squid_requests'}{'graph'}{'args'}     = '--base 1000';
  $config{'squid_requests'}{'graph'}{'category'} = 'webserver';
  $config{'squid_requests'}{'graph'}{'order'}    = 'client_http_errors server_all_errors server_http_errors ' .
                                                   'server_ftp_errors server_other_errors ' .
                                                   'client_http_hits aborted_requests client_http_requests ' .
                                                   'server_all_requests server_http_requests server_ftp_requests server_other_requests';
  $config{'squid_requests'}{'field'}{'client_http_hits'}{'label'} = 'Client HTTP hits';
  $config{'squid_requests'}{'field'}{'client_http_hits'}{'type'}  = 'COUNTER';
  $config{'squid_requests'}{'field'}{'client_http_hits'}{'draw'}  = 'AREA';
  $config{'squid_requests'}{'field'}{'aborted_requests'}{'label'} = 'Aborted requests';
  $config{'squid_requests'}{'field'}{'aborted_requests'}{'type'}  = 'COUNTER';
  $config{'squid_requests'}{'field'}{'aborted_requests'}{'draw'}  = 'LINE1';
  $config{'squid_requests'}{'field'}{'client_http_requests'}{'label'}  = 'Client HTTP';
  $config{'squid_requests'}{'field'}{'server_all_requests'}{'label'}   = 'Server all';
  $config{'squid_requests'}{'field'}{'server_http_requests'}{'label'}  = 'Server HTTP';
  $config{'squid_requests'}{'field'}{'server_ftp_requests'}{'label'}   = 'Server FTP';
  $config{'squid_requests'}{'field'}{'server_other_requests'}{'label'} = 'Server other';
  foreach my $fld (qw(client_http server_all server_http server_ftp server_other))
  {
    my ($errf, $reqf) = (sprintf("%s_errors", $fld), sprintf("%s_requests", $fld));
    $config{'squid_requests'}{'field'}{$errf}{'type'}  = 'COUNTER';
    $config{'squid_requests'}{'field'}{$errf}{'label'} = 'none';
    $config{'squid_requests'}{'field'}{$errf}{'graph'} = 'no';
    $config{'squid_requests'}{'field'}{$reqf}{'type'}     = 'COUNTER';
    $config{'squid_requests'}{'field'}{$reqf}{'draw'}     = 'LINE1';
    $config{'squid_requests'}{'field'}{$reqf}{'negative'} = $errf;
  }

  # ------------------------------------------------- squid_storedir -----------------------------------------
  $config{'squid_storedir'}{'graph'}{'title'}    = 'Store directory statistics';
  $config{'squid_storedir'}{'graph'}{'vlabel'}   = 'bytes';
  $config{'squid_storedir'}{'graph'}{'args'}     = '--base 1000';
  $config{'squid_storedir'}{'graph'}{'category'} = 'webserver';
  $config{'squid_storedir'}{'graph'}{'order'}    = 'maximum current';
  $config{'squid_storedir'}{'field'}{'maximum'}{'label'} = 'Maximum';
  $config{'squid_storedir'}{'field'}{'maximum'}{'draw'}  = 'AREA';
  $config{'squid_storedir'}{'field'}{'maximum'}{'cdef'}  = 'maximum,1024,*';
  $config{'squid_storedir'}{'field'}{'current'}{'label'} = 'Current';
  $config{'squid_storedir'}{'field'}{'current'}{'draw'}  = 'AREA';
  $config{'squid_storedir'}{'field'}{'current'}{'cdef'}  = 'current,1024,*';
  # ------------------------------------------------- squid_memory -----------------------------------------
  $config{'squid_memory'}{'graph'}{'title'}    = 'Store memory statistics';
  $config{'squid_memory'}{'graph'}{'vlabel'}   = 'bytes';
  $config{'squid_memory'}{'graph'}{'args'}     = '--base 1000';
  $config{'squid_memory'}{'graph'}{'category'} = 'webserver';
  $config{'squid_memory'}{'graph'}{'order'}    = 'mi_tsia mi_ob mi_sb mi_hb mi_fsb mi_fob mi_tiu mi_tf mi_ts ta ma mu';
  $config{'squid_memory'}{'field'}{'mi_tsia'}{'label'} = '[mallinfo()] Total space in arena';
  $config{'squid_memory'}{'field'}{'mi_ob'}{'label'}   = '[mallinfo()] Ordinary blocks';
  $config{'squid_memory'}{'field'}{'mi_sb'}{'label'}   = '[mallinfo()] Small blocks';
  $config{'squid_memory'}{'field'}{'mi_hb'}{'label'}   = '[mallinfo()] Holding blocks';
  $config{'squid_memory'}{'field'}{'mi_fsb'}{'label'}  = '[mallinfo()] Free small blocks';
  $config{'squid_memory'}{'field'}{'mi_fob'}{'label'}  = '[mallinfo()] Free ordinary blocks';
  $config{'squid_memory'}{'field'}{'mi_tiu'}{'label'}  = '[mallinfo()] Total in use';
  $config{'squid_memory'}{'field'}{'mi_tf'}{'label'}   = '[mallinfo()] Total free';
  $config{'squid_memory'}{'field'}{'mi_ts'}{'label'}   = '[mallinfo()] Total size';
  $config{'squid_memory'}{'field'}{'ta'}{'label'}      = 'Total accounted';
  $config{'squid_memory'}{'field'}{'ma'}{'label'}      = 'memPool accounted';
  $config{'squid_memory'}{'field'}{'mu'}{'label'}      = 'memPool unaccounted';
  foreach my $fld (qw(mi_tsia mi_ob mi_sb mi_hb mi_fsb mi_fob mi_tiu mi_tf mi_ts ta ma mu))
  {
     $config{'squid_memory'}{'field'}{$fld}{'draw'}  = 'LINE1';
     $config{'squid_memory'}{'field'}{$fld}{'cdef'}  = sprintf("%s,1024,*", $fld);
  }
  # ------------------------------------------------- squid_meanobject -----------------------------------------
  $config{'squid_meanobject'}{'graph'}{'title'}    = 'Mean object size';
  $config{'squid_meanobject'}{'graph'}{'vlabel'}   = 'bytes';
  $config{'squid_meanobject'}{'graph'}{'args'}     = '--base 1000';
  $config{'squid_meanobject'}{'graph'}{'category'} = 'webserver';
  $config{'squid_meanobject'}{'graph'}{'order'}    = 'mos';
  $config{'squid_meanobject'}{'field'}{'mos'}{'label'} = 'Mean object size';
  $config{'squid_meanobject'}{'field'}{'mos'}{'draw'}  = 'LINE1';
  $config{'squid_meanobject'}{'field'}{'mos'}{'cdef'}  = 'mos,1024,*';
  # ------------------------------------------------- squid_cpu -----------------------------------------
  $config{'squid_cpu'}{'graph'}{'title'}    = 'CPU usage';
  $config{'squid_cpu'}{'graph'}{'vlabel'}   = '%';
  $config{'squid_cpu'}{'graph'}{'args'}     = '--base 1000 --lower-limit 0';
  $config{'squid_cpu'}{'graph'}{'category'} = 'webserver';
  $config{'squid_cpu'}{'graph'}{'scale'}    = 'no';
  $config{'squid_cpu'}{'graph'}{'order'}    = 'cur av5 av60';
  $config{'squid_cpu'}{'field'}{'cur'}{'label'}  = 'Current';
  $config{'squid_cpu'}{'field'}{'cur'}{'draw'}   = 'LINE1';
  $config{'squid_cpu'}{'field'}{'av5'}{'label'}  = '5 minute average';
  $config{'squid_cpu'}{'field'}{'av5'}{'draw'}   = 'LINE1';
  $config{'squid_cpu'}{'field'}{'av60'}{'label'} = '60 minute average';
  $config{'squid_cpu'}{'field'}{'av60'}{'draw'}  = 'LINE1';
  foreach my $fld (qw(cur av5 av60))
  {
    $config{'squid_cpu'}{'field'}{$fld}{'max'} = 100;
    $config{'squid_cpu'}{'field'}{$fld}{'min'} = 0;
  }
  # ------------------------------------------------- squid_ids -----------------------------------------
  $config{'squid_ids'}{'graph'}{'title'}    = 'Internal data structures';
  $config{'squid_ids'}{'graph'}{'vlabel'}   = 'Count';
  $config{'squid_ids'}{'graph'}{'args'}     = '--lower-limit 0';
  $config{'squid_ids'}{'graph'}{'category'} = 'webserver';
  $config{'squid_ids'}{'graph'}{'order'}    = 'se sewmo hoci odo';
  $config{'squid_ids'}{'field'}{'se'}{'label'} = 'StoreEntries';
  $config{'squid_ids'}{'field'}{'se'}{'draw'}  = 'LINE1';
  $config{'squid_ids'}{'field'}{'sewmo'}{'label'} = 'StoreEntries with MemObjects';
  $config{'squid_ids'}{'field'}{'sewmo'}{'draw'}  = 'LINE1';
  $config{'squid_ids'}{'field'}{'hoci'}{'label'}  = 'Hot object cache items';
  $config{'squid_ids'}{'field'}{'hoci'}{'draw'}   = 'LINE1';
  $config{'squid_ids'}{'field'}{'odo'}{'label'}   = 'On-disk objects';
  $config{'squid_ids'}{'field'}{'odo'}{'draw'}    = 'LINE1';
  # ------------------------------------------------- squid_mst -----------------------------------------
  foreach my $time (qw(5 60))
  {
    my $name = sprintf("squid_mst_%s", $time);
    $config{$name}{'graph'}{'title'}    = "Median service times in ${time} minuts";
    $config{$name}{'graph'}{'vlabel'}   = 'seconds';
    $config{$name}{'graph'}{'args'}     = '--base 1000';
    $config{$name}{'graph'}{'category'} = 'webserver';
    $config{$name}{'graph'}{'order'}    = 'hra cm ch nh nmr dl iq';
    $config{$name}{'field'}{'hra'}{'label'} = 'HTTP Requests (All)';
    $config{$name}{'field'}{'hra'}{'draw'}  = 'LINE1';
    $config{$name}{'field'}{'cm'}{'label'}  = 'Cache Misses';
    $config{$name}{'field'}{'cm'}{'draw'}   = 'LINE1';
    $config{$name}{'field'}{'ch'}{'label'}  = 'Cache Hits';
    $config{$name}{'field'}{'ch'}{'draw'}   = 'LINE1';
    $config{$name}{'field'}{'nh'}{'label'}  = 'Near Hits';
    $config{$name}{'field'}{'nh'}{'draw'}   = 'LINE1';
    $config{$name}{'field'}{'nmr'}{'label'} = 'Not-Modified Replies';
    $config{$name}{'field'}{'nmr'}{'draw'}  = 'LINE1';
    $config{$name}{'field'}{'dl'}{'label'}  = 'DNS Lookups';
    $config{$name}{'field'}{'dl'}{'draw'}   = 'LINE1';
    $config{$name}{'field'}{'iq'}{'label'}  = 'ICP Queries';
    $config{$name}{'field'}{'iq'}{'draw'}   = 'LINE1';
  }
  # ------------------------------------------------- out -----------------------------------------
  foreach my $graph (sort keys(%config))
  {
    printf ("multigraph %s\n", $graph);
    foreach my $graph_option (sort keys %{$config{$graph}{'graph'}})
    {
      printf ("graph_%s %s\n", $graph_option, $config{$graph}{'graph'}{$graph_option});
    }
    foreach my $field_option (qw(label type draw graph cdef negative max min))
    {
      foreach my $graph_field (sort keys %{$config{$graph}{'field'}})
      {
        if(exists($config{$graph}{'field'}{$graph_field}{$field_option}))
        {
          printf("%s.%s %s\n",$graph_field , $field_option, $config{$graph}{'field'}{$graph_field}{$field_option});
        }
      }
    }
    print "\n";
  }
  exit 0;
}

my $cm;
my %data;
# -----------------  squid_efficiency_  and squid_memory  --------------------
$cm = squid_requst('info');
while (my $line = $cm->getline) 
{
  # -----------------  squid_efficiency_  --------------------
  if($line =~ /Hits as % of all requests:.*/)        { ($data{'squid_efficiency_5'}{'all'},    $data{'squid_efficiency_60'}{'all'})    = $line =~ /([\d.]+)%/g; next; }
  if($line =~ /Hits as % of bytes sent:.*/)          { ($data{'squid_efficiency_5'}{'bytes'},  $data{'squid_efficiency_60'}{'bytes'})  = $line =~ /([\d.]+)%/g; next; }
  if($line =~ /Memory hits as % of hit requests:.*/) { ($data{'squid_efficiency_5'}{'memory'}, $data{'squid_efficiency_60'}{'memory'}) = $line =~ /([\d.]+)%/g; next; }
  if($line =~ /Disk hits as % of hit requests:.*/)   { ($data{'squid_efficiency_5'}{'disk'},   $data{'squid_efficiency_60'}{'disk'})   = $line =~ /([\d.]+)%/g; next; }
  # -----------------  squid_memory  --------------------
  if($line =~ /Total space in arena:.*/)     { $data{'squid_memory'}{'mi_tsia'} = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /^\s+Ordinary blocks:.*/)      { $data{'squid_memory'}{'mi_ob'}   = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /^\s+Small blocks:.*/)         { $data{'squid_memory'}{'mi_sb'}   = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /Holding blocks:.*/)           { $data{'squid_memory'}{'mi_hb'}   = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /^\s+Free Small blocks:.*/)    { $data{'squid_memory'}{'mi_fsb'}  = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /^\s+Free Ordinary blocks:.*/) { $data{'squid_memory'}{'mi_fob'}  = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /Total in use:.*/)             { $data{'squid_memory'}{'mi_tiu'}  = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /Total free:.*/)               { $data{'squid_memory'}{'mi_tf'}   = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /Total size:.*/)               { $data{'squid_memory'}{'mi_ts'}   = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /Total accounted.*/)           { $data{'squid_memory'}{'ta'}      = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /memPool accounted.*/)         { $data{'squid_memory'}{'ma'}      = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /memPool unaccounted.*/)       { $data{'squid_memory'}{'mu'}      = ($line =~ /(\d+)/g)[0]; next; }
  # -----------------  squid_meanobject  --------------------
  if($line =~ /Mean Object Size.*/) { $data{'squid_meanobject'}{'mos'} = ($line =~ /([\d\.]+)/g)[0]; next; }
  # -----------------  squid_cpu  --------------------
  if($line =~ /^\s+CPU Usage:.*/)                { $data{'squid_cpu'}{'cur'}  = ($line =~ /([\d\.]+)%/g)[0]; next; }
  if($line =~ /^\s+CPU Usage, 5 minute avg:.*/)  { $data{'squid_cpu'}{'av5'}  = ($line =~ /([\d\.]+)%/g)[0]; next; }
  if($line =~ /^\s+CPU Usage, 60 minute avg:.*/) { $data{'squid_cpu'}{'av60'} = ($line =~ /([\d\.]+)%/g)[0]; next; }
  # -----------------  squid_mst  --------------------
  if($line =~ /^\s+HTTP Requests \(All\):.*/)  { ($data{'squid_mst_5'}{'hra'}, $data{'squid_mst_60'}{'hra'}) = $line =~ /([\d.]+)/g; next;  }
  if($line =~ /^\s+Cache Misses:.*/)           { ($data{'squid_mst_5'}{'cm'},  $data{'squid_mst_60'}{'cm'})  = $line =~ /([\d.]+)/g; next;  }
  if($line =~ /^\s+Cache Hits:.*/)             { ($data{'squid_mst_5'}{'ch'},  $data{'squid_mst_60'}{'ch'})  = $line =~ /([\d.]+)/g; next;  }
  if($line =~ /^\s+Near Hits:.*/)              { ($data{'squid_mst_5'}{'nh'},  $data{'squid_mst_60'}{'nh'})  = $line =~ /([\d.]+)/g; next;  }
  if($line =~ /^\s+Not-Modified Replies:.*/)   { ($data{'squid_mst_5'}{'nmr'}, $data{'squid_mst_60'}{'nmr'}) = $line =~ /([\d.]+)/g; next;  }
  if($line =~ /^\s+DNS Lookups:.*/)            { ($data{'squid_mst_5'}{'dl'},  $data{'squid_mst_60'}{'dl'})  = $line =~ /([\d.]+)/g; next;  }
  if($line =~ /^\s+ICP Queries:.*/)            { ($data{'squid_mst_5'}{'iq'},  $data{'squid_mst_60'}{'iq'})  = $line =~ /([\d.]+)/g; next;  }
  # -----------------  squid_ids  --------------------
  if($line =~ /^\s+\d+\s+StoreEntries\s+$/)               { $data{'squid_ids'}{'se'}    = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /^\s+\d+\s+StoreEntries with MemObjects.*/) { $data{'squid_ids'}{'sewmo'} = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /^\s+\d+\s+Hot Object Cache Items.*/)       { $data{'squid_ids'}{'hoci'}  = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /^\s+\d+\s+on-disk objects.*/)              { $data{'squid_ids'}{'odo'}   = ($line =~ /(\d+)/g)[0]; next; }
}

# -----------------  squid_ipcache  --------------------
$cm = squid_requst('ipcache');
while (my $line = $cm->getline) 
{
  if($line =~ /IPcache Entries:.*/)         { $data{'squid_ipcache'}{'entries'}     = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /IPcache Requests:.*/)        { $data{'squid_ipcache'}{'request'}     = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /IPcache Hits:.*/)            { $data{'squid_ipcache'}{'hits'}        = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /IPcache Negative Hits:.*/)   { $data{'squid_ipcache'}{'neghits'}     = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /IPcache Numeric Hits:.*/)    { $data{'squid_ipcache'}{'numhits'}     = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /IPcache Misses:.*/)          { $data{'squid_ipcache'}{'misses'}      = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /IPcache Invalid Request:.*/) { $data{'squid_ipcache'}{'invdreqests'} = ($line =~ /(\d+)/g)[0]; next; }
}

# -----------------  squid_traffic and squid_requests  --------------------
$cm = squid_requst('counters');
while (my $line = $cm->getline)
{
  # squid_traffic
  if($line =~ /client_http.hit_kbytes_out =.*/) { $data{'squid_traffic'}{'client_http_hit_out'} = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /client_http.kbytes_in =.*/)      { $data{'squid_traffic'}{'client_http_in'}      = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /client_http.kbytes_out =.*/)     { $data{'squid_traffic'}{'client_http_out'}     = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /server.all.kbytes_in =.*/)       { $data{'squid_traffic'}{'server_all_in'}       = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /server.all.kbytes_out =.*/)      { $data{'squid_traffic'}{'server_all_out'}      = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /server.http.kbytes_in =.*/)      { $data{'squid_traffic'}{'server_http_in'}      = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /server.http.kbytes_out =.*/)     { $data{'squid_traffic'}{'server_http_out'}     = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /server.ftp.kbytes_in =.*/)       { $data{'squid_traffic'}{'server_ftp_in'}       = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /server.ftp.kbytes_out =.*/)      { $data{'squid_traffic'}{'server_ftp_out'}      = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /server.other.kbytes_in =.*/)     { $data{'squid_traffic'}{'server_other_in'}     = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /server.other.kbytes_out =.*/)    { $data{'squid_traffic'}{'server_other_out'}    = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /icp.kbytes_sent =.*/)            { $data{'squid_traffic'}{'icp_out'}             = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /icp.kbytes_recv =.*/)            { $data{'squid_traffic'}{'icp_in'}              = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /icp.q_kbytes_sent =.*/)          { $data{'squid_traffic'}{'icp_q_out'}           = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /icp.r_kbytes_sent =.*/)          { $data{'squid_traffic'}{'icp_r_out'}           = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /icp.q_kbytes_recv =.*/)          { $data{'squid_traffic'}{'icp_q_in'}            = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /icp.r_kbytes_recv =.*/)          { $data{'squid_traffic'}{'icp_r_in'}            = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /cd.kbytes_sent =.*/)             { $data{'squid_traffic'}{'cd_in'}               = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /cd.kbytes_recv =.*/)             { $data{'squid_traffic'}{'cd_out'}              = ($line =~ /(\d+)/g)[0]; next; }
  # squid_requests
  if($line =~ /client_http.requests =.*/)       { $data{'squid_requests'}{'client_http_requests'}  = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /client_http.hits =.*/)           { $data{'squid_requests'}{'client_http_hits'}      = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /client_http.errors =.*/)         { $data{'squid_requests'}{'client_http_errors'}    = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /server.all.requests =.*/)        { $data{'squid_requests'}{'server_all_requests'}   = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /server.all.errors =.*/)          { $data{'squid_requests'}{'server_all_errors'}     = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /server.http.requests =.*/)       { $data{'squid_requests'}{'server_http_requests'}  = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /server.http.errors =.*/)         { $data{'squid_requests'}{'server_http_errors'}    = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /server.ftp.requests =.*/)        { $data{'squid_requests'}{'server_ftp_requests'}   = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /server.ftp.errors =.*/)          { $data{'squid_requests'}{'server_ftp_errors'}     = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /server.other.requests =.*/)      { $data{'squid_requests'}{'server_other_requests'} = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /server.other.errors =.*/)        { $data{'squid_requests'}{'server_other_errors'}   = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /aborted_requests =.*/)           { $data{'squid_requests'}{'aborted_requests'}      = ($line =~ /(\d+)/g)[0]; next; }
}

# -----------------  squid_storedir  --------------------
$cm = squid_requst('storedir');
while (my $line = $cm->getline)
{
  if($line =~ /Maximum Swap Size.*:*/)       { $data{'squid_storedir'}{'maximum'} = ($line =~ /(\d+)/g)[0]; next; }
  if($line =~ /Current Store Swap Size.*:*/) { $data{'squid_storedir'}{'current'} = ($line =~ /(\d+)/g)[0]; next; }
}
# --------------------- print ----------------
foreach my $mgraph (sort keys(%data))
{
  printf ("multigraph %s\n", $mgraph);
  foreach my $fld (sort keys %{$data{$mgraph}})
  {
    printf ("%s.value %s\n", $fld, $data{$mgraph}{$fld});
  }
  print "\n";
}

# for Munin Plugin Gallery
# graph_category webserver

