1 | #!/usr/bin/perl -w #-d
|
---|
2 | #
|
---|
3 | # sar/iostat graphing tool based on rrdtool
|
---|
4 | # (c) 2004 B. Cornec HP <bruno.cornec@hp.com>
|
---|
5 | # Licensed under the GPL or Artistic License
|
---|
6 | #
|
---|
7 | # Original Charter: Monitor CPU/Load/Net_eth0|2 (io/s)/Disk (io/s)
|
---|
8 | # 1 mesure par 20 seconde
|
---|
9 | # So the script has been developped first with that context in mind
|
---|
10 | # trying to be generic enough to be expandable later on
|
---|
11 | # More work needs to be done, some code factorized, ...
|
---|
12 | #
|
---|
13 | use strict; # Always :-)
|
---|
14 | use RRDs; # for data management and graphing
|
---|
15 | use Data::Dumper; # for debug
|
---|
16 | use HTML::AsSubs; # for HTML generation
|
---|
17 | use Storable; # for data exchange
|
---|
18 | use Date::Manip; # for timestamp
|
---|
19 | use Config::Auto; # for config file
|
---|
20 | use sario2rrd qw(from_epoch);
|
---|
21 | # local common functions
|
---|
22 |
|
---|
23 |
|
---|
24 | # Avoid localisation problems in sar
|
---|
25 | $ENV{LANG}="C";
|
---|
26 |
|
---|
27 | #
|
---|
28 | # Begin of configuration options
|
---|
29 | #
|
---|
30 | my $dir = "sar2rrd"; # Place under the html dir of user apache
|
---|
31 | # Under that directory you should have one
|
---|
32 | # directory per machine and in it all the
|
---|
33 | # files resulting form the sar and iostat
|
---|
34 | # commands (saxx and ioxx). Look at the
|
---|
35 | # cron file and related script
|
---|
36 |
|
---|
37 | my ($l,$p,$uid,$gid,$q,$c,$gc,$apache,$empty) = getpwnam("apache") or die "apache not in passwd file";
|
---|
38 | my $base = "$apache/html/$dir";
|
---|
39 | my $config = Config::Auto::parse("$base/$dir.conf");
|
---|
40 | my @machines = @{$config->{machines}};
|
---|
41 |
|
---|
42 | my $debug = 0;
|
---|
43 | foreach my $a (@ARGV) {
|
---|
44 | $debug++ if ($a =~ /-v/);
|
---|
45 | $| = 1; # Flush STDOUT
|
---|
46 | }
|
---|
47 | my $m;
|
---|
48 | my %t;
|
---|
49 | my %attrio = %{ retrieve("$base/$config->{svgio}") };
|
---|
50 | my %attrsar = %{ retrieve("$base/$config->{svgsar}") };
|
---|
51 |
|
---|
52 | my $h = "$base/index.html";
|
---|
53 | open (MAIN, "> $h") || die "Unable to create $h : $!";
|
---|
54 | my @hm = (h1("sar2rrd - sar/iostats monitoring via rrdtool"),
|
---|
55 | p("List of systems to monitor:"));
|
---|
56 | my @index;
|
---|
57 | my @tmp1;
|
---|
58 | my @tmp2;
|
---|
59 |
|
---|
60 | print Dumper($config) if ($debug > 1);
|
---|
61 |
|
---|
62 | foreach $m (@machines) {
|
---|
63 | @tmp1 = ();
|
---|
64 | @tmp2 = ();
|
---|
65 | #
|
---|
66 | # The graphs/HTML generation
|
---|
67 | #
|
---|
68 | push @index,li(a({href=>"$m/index.html"}, "$m"));
|
---|
69 | my $hm = "$base/$m/index.html";
|
---|
70 | open (MACHINE, "> $hm") || die "Unable to create $hm : $!";
|
---|
71 | my @hhm = (h1("sar2rrd - Monitoring $m"));
|
---|
72 | my $img="$base/$m/img";
|
---|
73 | print "Graphing rrd base for $m under $img\n" if ($debug > 0);
|
---|
74 | printf "Between %s/%s and %s/%s for sar\n",from_epoch($attrsar{$m}{mintmst}),$attrsar{$m}{mintmst},ParseDate("epoch $attrsar{$m}{maxtmst}"),$attrsar{$m}{maxtmst} if ($debug > 0);
|
---|
75 | printf "Between %s (%s) and %s (%s) for iostat\n",ParseDate("epoch $attrio{$m}{mintmst}"),$attrio{$m}{mintmst},ParseDate("epoch $attrio{$m}{maxtmst}"),$attrio{$m}{maxtmst} if ($debug > 0);
|
---|
76 | print "Generating " if ($debug > 0);
|
---|
77 | mkdir "$img",0755 if (not (-d "$img"));
|
---|
78 | unlink <$img/*.png>;
|
---|
79 | print "mem.png " if ($debug > 0);
|
---|
80 | RRDs::graph("$img/mem.png","-s $attrsar{$m}{mintmst}","-e $attrsar{$m}{maxtmst}","-L KB","-v KiloBytes","-aPNG","-t Memory Report","DEF:s1=$base/$m/$config->{rrdsar}:memoryfree:AVERAGE","AREA:s1#00ee22:Free Memory");
|
---|
81 | my $rrderror = RRDs::error;
|
---|
82 | die "Problem while generating graph: $rrderror\n" if ($rrderror);
|
---|
83 | print "load.png " if ($debug > 0);
|
---|
84 | RRDs::graph("$img/load.png","-s",$attrsar{$m}{mintmst},"-e",$attrsar{$m}{maxtmst},"-S",$config->{step},"-aPNG","-t","Load Report","DEF:s1=$base/$m/$config->{rrdsar}:load1:AVERAGE","DEF:s2=$base/$m/$config->{rrdsar}:load5:AVERAGE","DEF:s3=$base/$m/$config->{rrdsar}:runq:AVERAGE","LINE2:s1#00b6e4:Load 1m","LINE2:s2#00ee22:Load 5m","LINE2:s3#ff0000:Run Queue");
|
---|
85 | $rrderror = RRDs::error;
|
---|
86 | die "Problem while generating graph: $rrderror\n" if ($rrderror);
|
---|
87 | push @tmp1,td(img({src=>"$config->{http}/$dir/$m/img/mem.png"}));
|
---|
88 | push @tmp1,td(img({src=>"$config->{http}/$dir/$m/img/load.png"}));
|
---|
89 | push @tmp1,HTML::AsSubs::tr(@tmp1);
|
---|
90 |
|
---|
91 | my $col = 0;
|
---|
92 | foreach my $i (@{$attrsar{$m}{measures}},@{$attrio{$m}{measures}}) {
|
---|
93 | if ($i =~ /^eth/) {
|
---|
94 | $i =~ s/-[inout]+//;
|
---|
95 | next if (-f "$img/$i.png");
|
---|
96 | print "$i.png " if ($debug > 0);
|
---|
97 | RRDs::graph("$img/$i.png","-s",$attrsar{$m}{mintmst},"-e",$attrsar{$m}{maxtmst},"-S",$config->{step},"-aPNG","-t","Network Report","DEF:s1=$base/$m/$config->{rrdsar}:$i-in:AVERAGE","DEF:s2=$base/$m/$config->{rrdsar}:$i-out:AVERAGE","LINE2:s1#ff0000:$i (in)","LINE2:s2#00ee22:$i (out)");
|
---|
98 | push @tmp2,td(img({src=>"$config->{http}/$dir/$m/img/$i.png"}));
|
---|
99 | $col++;
|
---|
100 | if ($col == 2) {
|
---|
101 | push @tmp1,HTML::AsSubs::tr(@tmp2);
|
---|
102 | @tmp2 = ();
|
---|
103 | $col = 0;
|
---|
104 | }
|
---|
105 |
|
---|
106 | }
|
---|
107 | if (($i =~ /^sd/) || ($i =~ /^hd/) || ($i =~ /^cciss/)) {
|
---|
108 | $i =~ s/-[inout]+//;
|
---|
109 | next if (-f "$img/$i.png");
|
---|
110 | print "$i.png " if ($debug > 0);
|
---|
111 | RRDs::graph("$img/$i.png","-s",$attrio{$m}{mintmst},"-e",$attrio{$m}{maxtmst},"-S",$config->{step},"-aPNG","-t","Disk Report","DEF:s1=$base/$m/$config->{rrdio}:$i-in:AVERAGE","DEF:s2=$base/$m/$config->{rrdio}:$i-out:AVERAGE","LINE2:s1#ff0000:$i (in)","LINE2:s2#00ee22:$i (out)");
|
---|
112 | push @tmp2,td(img({src=>"$config->{http}/$dir/$m/img/$i.png"}));
|
---|
113 | $col++;
|
---|
114 | if ($col == 2) {
|
---|
115 | push @tmp1,HTML::AsSubs::tr(@tmp2);
|
---|
116 | @tmp2 = ();
|
---|
117 | $col = 0;
|
---|
118 | }
|
---|
119 | }
|
---|
120 | if (($i =~ /^cpu/) || ($i =~ /^all/)) {
|
---|
121 | $i =~ s/-[a-z]+//;
|
---|
122 | next if (-f "$img/$i.png");
|
---|
123 | print "$i.png " if ($debug > 0);
|
---|
124 | RRDs::graph("$img/$i.png","-s",$attrsar{$m}{mintmst},"-e",$attrsar{$m}{maxtmst},"-S",$config->{step},"-aPNG","-t","CPU Report","DEF:s1=$base/$m/$config->{rrdsar}:$i-idle:AVERAGE","DEF:s2=$base/$m/$config->{rrdsar}:$i-nice:AVERAGE","DEF:s3=$base/$m/$config->{rrdsar}:$i-system:AVERAGE","DEF:s4=$base/$m/$config->{rrdsar}:$i-user:AVERAGE","AREA:s1#00b6e4:$i (idle)","STACK:s2#00ee22:$i (nice)","STACK:s3#ff0000:$i (system)","STACK:s4#000000:$i (user)");
|
---|
125 | push @tmp2,td(img({src=>"$config->{http}/$dir/$m/img/$i.png"}));
|
---|
126 | $col++;
|
---|
127 | if ($col == 2) {
|
---|
128 | push @tmp1,HTML::AsSubs::tr(@tmp2);
|
---|
129 | @tmp2 = ();
|
---|
130 | $col = 0;
|
---|
131 | }
|
---|
132 | }
|
---|
133 | }
|
---|
134 | $rrderror = RRDs::error;
|
---|
135 | die "Problem while generating graph: $rrderror\n" if ($rrderror);
|
---|
136 | print "\n" if ($debug > 0);
|
---|
137 | push @hhm,table(@tmp1);
|
---|
138 | my $hhm = body(@hhm);
|
---|
139 | print MACHINE $hhm->as_HTML;
|
---|
140 | close(MACHINE);
|
---|
141 | }
|
---|
142 | push @hm,ul(@index);
|
---|
143 | my $hm = body(@hm);
|
---|
144 | print MAIN $hm->as_HTML;
|
---|
145 | close MAIN;
|
---|
146 | print "Point your browser to $config->{http}/$dir/index.html\n" if ($debug > 0);
|
---|