1 #!/usr/bin/perl
3 ################################################################################
4 #
5 # collectd2html.pl
6 #
7 # Description:
8 # Generate an html page with all rrd data gathered by collectd.
9 #
10 # Usage:
11 # collectd2html.pl
12 #
13 # When run on <host>, it generated <host>.html and <host>.dir, the latter
14 # containing all necessary images.
15 #
16 #
17 # Copyright 2006 Vincent Stehlé <vincent.stehle@free.fr>
18 #
19 # Patch to configure the data directory and hostname by Eddy Petrisor
20 # <eddy.petrisor@gmail.com>.
21 #
22 # This program is free software; you can redistribute it and/or modify
23 # it under the terms of the GNU General Public License as published by
24 # the Free Software Foundation; either version 2 of the License, or
25 # (at your option) any later version.
26 #
27 # This program is distributed in the hope that it will be useful,
28 # but WITHOUT ANY WARRANTY; without even the implied warranty of
29 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 # GNU General Public License for more details.
31 #
32 # You should have received a copy of the GNU General Public License
33 # along with this program; if not, write to the Free Software
34 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35 #
36 ################################################################################
38 use warnings;
39 use strict;
40 use Fatal qw(open close);
41 use File::Basename;
42 use Getopt::Long qw(:config no_ignore_case bundling pass_through);
44 my $DIR = "/var/lib/collectd";
45 my $HOST = undef;
46 my $IMG_FMT = "PNG";
47 my $RECURSIVE = 1;
49 GetOptions (
50 "host=s" => \$HOST,
51 "data-dir=s" => \$DIR,
52 "image-format=s" => \$IMG_FMT,
53 "recursive" => \$RECURSIVE
54 );
56 if (($DIR !~ m/\/rrd\/?$/) && (-d "$DIR/rrd")) {
57 $DIR .= "/rrd";
58 }
60 if (defined($HOST) && ($DIR !~ m/\/$HOST\/?$/) && (-d "$DIR/$HOST")) {
61 $DIR .= "/$HOST";
62 }
64 my @COLORS = (0xff7777, 0x7777ff, 0x55ff55, 0xffcc77, 0xff77ff, 0x77ffff,
65 0xffff77, 0x55aaff);
66 my @tmp = `/bin/hostname -f`; chomp(@tmp);
67 $HOST = $tmp[0] if (! defined $HOST);
68 my $svg_p = ($IMG_FMT eq "SVG");
69 my $IMG_SFX = $svg_p ? ".svg" : ".png";
70 my $IMG_DIR = "${HOST}.dir";
71 my $HTML = "${HOST}.html";
73 ################################################################################
74 #
75 # fade_component
76 #
77 # Description:
78 # Fade a color's component to the white.
79 #
80 ################################################################################
81 sub fade_component($)
82 {
83 my($component) = @_;
84 return (($component + 255 * 5) / 6);
85 }
87 ################################################################################
88 #
89 # fade_color
90 #
91 # Description:
92 # Fade a color to the white.
93 #
94 ################################################################################
95 sub fade_color($)
96 {
97 my($color) = @_;
98 my $r = 0;
100 for my $i (0 .. 2){
101 my $shft = ($i * 8);
102 my $component = (($color >> $shft) & 255);
103 $r |= (fade_component($component) << $shft);
104 }
106 return $r;
107 }
109 ################################################################################
110 #
111 # main
112 #
113 ################################################################################
114 system("rm -fR $IMG_DIR");
115 system("mkdir -p $IMG_DIR");
116 local *OUT;
117 open(OUT, ">$HTML");
118 my $title="Rrd plot for $HOST";
120 print OUT <<END;
121 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
122 "http://www.w3.org/TR/html4/loose.dtd">
123 <html>
124 <head>
125 <title>$title</title>
126 </head>
127 <body>
128 <center>
129 END
131 # list interesting rrd
132 my @rrds;
133 my @list;
135 if ($RECURSIVE) {
136 @list = `find $DIR -type f -name '*.rrd'`;
137 }
138 else {
139 @list = `ls $DIR/*.rrd`;
140 }
141 chomp(@list);
143 @list = sort @list;
144 foreach my $rrd (@list){
145 $rrd =~ m/^$DIR\/(.*)\.rrd$/;
146 push(@rrds, $1);
147 }
149 # table of contents
150 print OUT <<END;
151 <A name="top"></A><H1>$title</H1>
152 <P>
153 END
155 foreach my $bn (@rrds){
156 my $cleaned_bn = $bn;
157 $cleaned_bn =~ tr/%\//__/;
158 print OUT <<END;
159 <A href="#$cleaned_bn">$bn</A>
160 END
161 }
163 print OUT <<END;
164 </P>
165 END
167 # graph interesting rrd
168 for (my $i = 0; $i < scalar(@rrds); ++$i) {
169 my $bn = $rrds[$i];
170 print "$bn\n";
172 my $rrd = $list[$i];
173 my $cmd = "rrdtool info $rrd |grep 'ds\\[' |sed 's/^ds\\[//'"
174 ." |sed 's/\\].*//' |sort |uniq";
175 my @dss = `$cmd`; chomp(@dss);
177 # all DEF
178 my $j = 0;
179 my $defs = "";
181 foreach my $ds (@dss){
182 $defs .= " DEF:${ds}_avg=$rrd:$ds:AVERAGE"
183 ." DEF:${ds}_max=$rrd:$ds:MAX ";
184 }
186 # all AREA
187 $j = 0;
189 foreach my $ds (@dss){
190 my $color = $COLORS[$j % scalar(@COLORS)]; $j++;
191 my $faded_color = fade_color($color);
192 $defs .= sprintf(" AREA:${ds}_max#%06x ", $faded_color);
193 }
195 # all LINE
196 $j = 0;
198 foreach my $ds (@dss){
199 my $color = $COLORS[$j % scalar(@COLORS)]; $j++;
200 $defs .= sprintf(" LINE2:${ds}_avg#%06x:$ds"
201 ." GPRINT:${ds}_avg:AVERAGE:%%5.1lf%%sAvg"
202 ." GPRINT:${ds}_max:MAX:%%5.1lf%%sMax"
203 , $color);
204 }
206 my $cleaned_bn = $bn;
207 $cleaned_bn =~ tr/%\//__/;
208 print OUT <<END;
209 <A name="$cleaned_bn"></A><H1>$bn</H1>
210 END
212 # graph various ranges
213 foreach my $span qw(1hour 1day 1week 1month){
214 system("mkdir -p $IMG_DIR/" . dirname($bn));
215 my $img = "$IMG_DIR/${bn}-$span$IMG_SFX";
217 my $cmd = "rrdtool graph $img"
218 ." -t \"$bn $span\" --imgformat $IMG_FMT --width 600 --height 100"
219 ." --start now-$span --end now --interlaced"
220 ." $defs >/dev/null 2>&1";
221 system($cmd);
223 my $cleaned_img = $img; $cleaned_img =~ s/%/%25/g;
224 if (! $svg_p) {
225 print OUT <<END;
226 <P><IMG src="$cleaned_img" alt="${bn} $span"></P>
227 END
228 } else {
229 print OUT <<END;
230 <P><object data="$cleaned_img" type="image/svg+xml"
231 width="670" height="179">
232 ${bn} $span</object></P>
233 END
234 }
235 }
237 print OUT <<END;
238 <A href="#top">[top]</A>
239 END
240 }
242 print OUT <<END;
243 </center>
244 </body>
245 </html>
246 END
248 close(OUT);