Docs/ModRRDTool: lightygraph.cgi

File lightygraph.cgi, 5.0 kB (added by jello, 4 months ago)

CGI-BIN script to generate graphs on the fly

Line 
1 #!/usr/bin/perl -w
2
3 # lightygraph -- a lighttpd statistics rrdtool frontend
4 # copyright (c) 2008 Joe Nahmias <joe@nahmias.net>
5 # based on mailgraph by David Schweikert <dws@ee.ethz.ch>
6 # released under the GNU General Public License
7
8 use RRDs;
9 use POSIX qw(uname);
10
11 my $VERSION = "0.50";
12
13 my $host = (POSIX::uname())[1];
14 my $scriptname = 'lightygraph';
15 my $xpoints = 600;
16 my $ypoints = 350;
17 my $rrd = '/var/www/lighttpd.rrd';   # path to where the RRD database is
18 my $tmp_dir = '/var/cache/lighttpd'; # temporary directory where to store the images
19
20 my @graphs = (
21         { title => 'Last 4 Hours',   seconds => 60 * 60 *  4     ,   },
22         { title => 'Daily Graphs',   seconds => 60 * 60 * 24     ,   },
23         { title => 'Monthly Graphs', seconds => 60 * 60 * 24 * 30,   },
24 );
25
26 my %color = (         # rrggbb in hex
27         areamin     => 'ffffff',
28         instack     => 'f00000',
29         minmax      => 'a0a0a0',
30         incoming    => 'efb71d',
31         outstack    => '00f000',
32         outgoing    => 'a0a735',
33         reqstack    => '00f000',
34         requests    => '00a735',
35 );
36
37 sub rrd_graph(@)
38 {
39         my ($range, $file, $ypoints, @rrdargs) = @_;
40         # choose carefully the end otherwise rrd will maybe pick the wrong RRA:
41         my $date = localtime(time);
42         $date =~ s|:|\\:|g unless $RRDs::VERSION < 1.199908;
43
44         my ($graphret,$xs,$ys) = RRDs::graph($file,
45                 '--imgformat', 'PNG',
46                 '--width', $xpoints,
47                 '--height', $ypoints,
48                 '--start', "-$range",
49                 '--lazy',
50
51                 @rrdargs,
52
53                 'COMMENT:['.$date.']\r',
54         );
55
56         my $ERR=RRDs::error;
57         die "ERROR: $ERR\n" if $ERR;
58 }
59
60 sub graph_traffic($$)
61 {
62         my ($range, $file) = @_;
63         rrd_graph($range, $file, $ypoints,
64
65             "-v bytes",
66             "-t TrafficWebserver",
67             "DEF:binraw=$rrd:InOctets:AVERAGE",
68             "DEF:binmaxraw=$rrd:InOctets:MAX",
69             "DEF:binminraw=$rrd:InOctets:MIN",
70             "DEF:bout=$rrd:OutOctets:AVERAGE",
71             "DEF:boutmax=$rrd:OutOctets:MAX",
72             "DEF:boutmin=$rrd:OutOctets:MIN",
73             "CDEF:bin=binraw,-1,*",
74             "CDEF:binmax=binmaxraw,-1,*",
75             "CDEF:binmin=binminraw,-1,*",
76             "CDEF:binminmax=binmaxraw,binminraw,-",
77             "CDEF:boutminmax=boutmax,boutmin,-",
78             "AREA:binmin#$color{areamin}:",
79             "STACK:binmax#$color{instack}:",
80             "LINE1:binmin#$color{minmax}:",
81             "LINE1:binmax#$color{minmax}:",
82             "LINE2:bin#$color{incoming}:incoming",
83             "GPRINT:bin:MIN:%.2lf",
84             "GPRINT:bin:AVERAGE:%.2lf",
85             "GPRINT:bin:MAX:%.2lf",
86             "AREA:boutmin#$color{areamin}:",
87             "STACK:boutminmax#$color{outstack}:",
88             "LINE1:boutmin#$color{minmax}:",
89             "LINE1:boutmax#$color{minmax}:",
90             "LINE2:bout#$color{outgoing}:outgoing",
91             "GPRINT:bout:MIN:%.2lf",
92             "GPRINT:bout:AVERAGE:%.2lf",
93             "GPRINT:bout:MAX:%.2lf",
94         );
95 }
96
97 sub graph_requests($$)
98 {
99         my ($range, $file) = @_;
100         rrd_graph($range, $file, $ypoints,
101             "-v req",
102             "-t RequestsperSecond",
103             "-u 1",
104             "DEF:req=$rrd:Requests:AVERAGE",
105             "DEF:reqmax=$rrd:Requests:MAX",
106             "DEF:reqmin=$rrd:Requests:MIN",
107             "CDEF:reqminmax=reqmax,reqmin,-",
108             "AREA:reqmin#$color{areamin}:",
109             "STACK:reqminmax#$color{reqstack}:",
110             "LINE1:reqmin#$color{minmax}:",
111             "LINE1:reqmax#$color{minmax}:",
112             "LINE2:req#$color{requests}:requests",
113         );
114 }
115
116 sub print_html()
117 {
118         print "Content-Type: text/html\n\n";
119
120         print <<HEADER;
121 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
122 <HTML>
123 <HEAD>
124 <TITLE>Webserver Statistics for $host</TITLE>
125 <META HTTP-EQUIV="Refresh" CONTENT="300">
126 <META HTTP-EQUIV="Pragma" CONTENT="no-cache">
127 </HEAD>
128 <BODY BGCOLOR="#FFFFFF">
129 HEADER
130
131         print "<H1>WebServer Statistics for $host</H1>\n";
132         for my $n (0..$#graphs) {
133                 print '<div style="background: #dddddd; width: 632px">';
134                 print "<H2>$graphs[$n]{title}</H2>\n";
135                 print "</div>\n";
136                 print "<P><IMG BORDER=\"0\" SRC=\"$scriptname.cgi?${n}-t\" ALT=\"$scriptname\">\n";
137                 print "<P><IMG BORDER=\"0\" SRC=\"$scriptname.cgi?${n}-r\" ALT=\"$scriptname\">\n";
138         }
139
140         print "</BODY></HTML>\n";
141 }
142
143 sub send_image($)
144 {
145         my ($file)= @_;
146
147         -r $file or do {
148                 print "Content-type: text/plain\n\nERROR: can't find $file\n";
149                 exit 1;
150         };
151
152         print "Content-type: image/png\n";
153         print "Content-length: ".((stat($file))[7])."\n";
154         print "\n";
155         open(IMG, $file) or die;
156         my $data;
157         print $data while read(IMG, $data, 16384)>0;
158 }
159
160 sub main()
161 {
162         my $uri = $ENV{REQUEST_URI} || '';
163         $uri =~ s/\/[^\/]+$//;
164         $uri =~ s/\//,/g;
165         $uri =~ s/(\~|\%7E)/tilde,/g;
166         mkdir $tmp_dir, 0777 unless -d $tmp_dir;
167
168         my $img = $ENV{QUERY_STRING};
169         if(defined $img and $img =~ /\S/) {
170                 if($img =~ /^(\d+)-t$/) {
171                         my $file = "$tmp_dir/${scriptname}_traffic_$1.png";
172                         graph_traffic($graphs[$1]{seconds}, $file);
173                         send_image($file);
174                 }
175                 elsif($img =~ /^(\d+)-r$/) {
176                         my $file = "$tmp_dir/${scriptname}_requests_$1.png";
177                         graph_requests($graphs[$1]{seconds}, $file);
178                         send_image($file);
179                 }
180                 else {
181                         die "ERROR: invalid argument\n";
182                 }
183         }
184         else {
185                 print_html;
186         }
187 }
188
189 main;