source: branches/fc11-dev/noc/ng/cgi-bin/show.cgi @ 2802

Last change on this file since 2802 was 42, checked in by presbrey, 18 years ago
scripts.mit.edu NOC graphing
File size: 7.3 KB
Line 
1#!/usr/bin/perl
2
3# File:    $Id: show.cgi,v 1.22 2006/04/12 09:42:16 sauber Exp $
4# Author:  (c) Soren Dossing, 2005
5# License: OSI Artistic License
6#          http://www.opensource.org/licenses/artistic-license.php
7
8use strict;
9use RRDs;
10use CGI qw/:standard/;
11
12# Configuration
13my $configfile = '/home/nagios/ng/etc/nagiosgraph.conf';
14
15# Main program - change nothing below
16
17my %Config;
18
19# Read in configuration data
20#
21sub readconfig {
22  die "config file not found" unless -r $configfile;
23
24  # Read configuration data
25  open FH, $configfile;
26    while (<FH>) {
27      s/\s*#.*//;    # Strip comments
28      /^(\w+)\s*=\s*(.*?)\s*$/ and do {
29        $Config{$1} = $2;
30        debug(5, "CGI Config $1:$2");
31      };
32    }
33  close FH;
34
35  # Make sure log file can be written to
36  unless ( -w $Config{logfile} ) {
37    my $msg = "Log file $Config{logfile} not writable";
38    print header(-type => "text/html", -expires => 0);
39    print p($msg);
40    debug (2, "CGI Config $msg");
41    return undef;
42  }
43
44  # Make sure rrddir is readable
45  unless ( -r $Config{rrddir} ) {
46    my $msg = "rrd dir $Config{rrddir} not readable";
47    print header(-type => "text/html", -expires => 0);
48    print p($msg);
49    debug (2, "CGI Config $msg");
50    return undef;
51  }
52
53  return 1;
54}
55
56# Write debug information to log file
57#
58sub debug {
59  my($l, $text) = @_;
60  if ( $l <= $Config{debug} ) {
61    $l = qw(none critical error warn info debug)[$l];
62    $text =~ s/(\w+)/$1 $l:/;
63    open LOG, ">>$Config{logfile}";
64      print LOG scalar localtime;
65      print LOG " $text\n";
66    close LOG;
67  }
68}
69
70# URL encode a string
71#
72sub urlencode {
73  $_[0] =~ s/([\W])/"%" . uc(sprintf("%2.2x",ord($1)))/eg;
74  return $_[0];
75}
76
77# Get list of matching rrd files
78#
79sub dbfilelist {
80  my($host,$service) = @_;
81  my $hs = urlencode "${host}_${service}";
82  my @rrd;
83  opendir DH, $Config{rrddir};
84    @rrd = grep s/^${hs}_(.+)\.rrd$/$1/, readdir DH;
85  closedir DH;
86  return @rrd;
87}
88
89# Find graphs and values
90#
91sub graphinfo {
92  my($host,$service,@db) = @_;
93  my(@rrd,$ds,$f,$dsout,@values,$hs,%H,%R);
94
95  $hs = urlencode "${host}_${service}";
96
97  debug(5, 'CGI @db=' . join '&', @db);
98
99  # Determine which files to read lines from
100  if ( @db ) {
101    my $n = 0;
102    for my $d ( @db ) {
103      my($db,@lines) = split ',', $d;
104      $rrd[$n]{file} = $hs . urlencode("_$db") . '.rrd';
105      for my $l ( @lines ) {
106        my($line,$unit) = split '~', $l;
107        if ( $unit ) {
108          $rrd[$n]{line}{$line}{unit} = $unit if $unit;
109        } else {
110          $rrd[$n]{line}{$line} = 1;
111        }
112      }
113      $n++;
114    }
115    debug(4, "CGI Specified $hs db files in $Config{rrddir}: "
116           . join ', ', map { $_->{file} } @rrd);
117  } else {
118    @rrd = map {{ file=>$_ }}
119           map { "${hs}_${_}.rrd" }
120           dbfilelist($host,$service);
121    debug(4, "CGI Listing $hs db files in $Config{rrddir}: "
122           . join ', ', map { $_->{file} } @rrd);
123  }
124
125  for $f ( @rrd ) {
126    unless ( $f->{line} ) {
127      $ds = RRDs::info "$Config{rrddir}/$f->{file}";
128      debug(2, "CGI RRDs::info ERR " . RRDs::error) if RRDs::error;
129      map { $f->{line}{$_} = 1}
130      grep {!$H{$_}++}
131      map { /ds\[(.*)\]/; $1 }
132      grep /ds\[(.*)\]/,
133      keys %$ds;
134    }
135    debug(5, "CGI DS $f->{file} lines: "
136           . join ', ', keys %{ $f->{line} } );
137  }
138  return \@rrd;
139}
140
141# Choose a color for service
142#
143sub hashcolor {
144  my$c=$Config{colorscheme};
145  map{
146    $c=(51*$c+ord)%(216)
147  } split//,"$_[0]x";
148  my($i,$n,$m,@h);
149  @h=(51*int$c/36,
150      51*int$c/6%6,
151      51*($c%6));
152#debug(2, "hashcolor $_[0], $c, $h[0]");
153  for$i(0..2){
154        $m=$i if$h[$i]<$h[$m];
155        $n=$i if$h[$i]>$h[$n]
156  }
157  $h[$m]=102 if$h[$m]>102;
158  $h[$n]=153 if$h[$n]<153;
159#debug(2, "hashcolor $_[0]\t$c\t$h[0]\t$h[1]\t$h[2]");
160  #$c=sprintf"%06X",$h[2]+$h[1]*256+$h[0]*16**4;
161  $n = $h[2]+$h[1]*256+$h[0]*16**4;
162  $c=sprintf"%06X",$n;
163#debug(2, "hashcolor $_[0]\t$n\t$c");
164  return $c;
165}
166
167# Generate all the parameters for rrd to produce a graph
168#
169sub rrdline {
170  my($host,$service,$geom,$rrdopts,$G,$time) = @_;
171  my($g,$f,$v,$c,@ds);
172
173  @ds = ('-', '-a', 'PNG', '--start', "-$time");
174  # Identify where to pull data from and what to call it
175  for $g ( @$G ) {
176    $f = $g->{file};
177    debug(5, "CGI file=$f");
178    for $v ( sort keys %{ $g->{line} } ) {
179      $c = hashcolor($v);
180      debug(5, "CGI file=$f line=$v color=$c");
181      my $sv = "$v";
182      push @ds , "DEF:$sv=$Config{rrddir}/$f:$v:AVERAGE"
183               , "LINE2:${sv}#$c:$sv"
184               , "GPRINT:$sv:MAX:Max\\: %6.2lf%s"
185               , "GPRINT:$sv:AVERAGE:Avg\\: %6.2lf%s"
186               , "GPRINT:$sv:MIN:Min\\: %6.2lf%s"
187               , "GPRINT:$sv:LAST:Cur\\: %6.2lf%s\\n";
188    }
189  }
190
191  # Dimensions of graph if geom is specified
192  if ( $geom ) {
193    my($w,$h) = split 'x', $geom;
194    push @ds, '-w', $w, '-h', $h;
195  }
196  # Additional parameters to rrd graph, if specified
197  if ( $rrdopts ) {
198    push @ds, split /\s+/, $rrdopts;
199  }
200  return @ds;
201}
202
203# Write a pretty page with various graphs
204#
205sub page {
206  my($h,$s,$d,$o,@db) = @_;
207
208  # Reencode rrdopts
209  $o = urlencode $o;
210
211  # Detect available db files
212  @db = dbfilelist($h,$s) unless @db;
213  debug(5, "CGI dbfilelist @db");
214
215  # Define graph sizes
216  #   Daily   =  33h =   118800s
217  #   Weekly  =   9d =   777600s
218  #   Monthly =   5w =  3024000s
219  #   Yearly  = 400d = 34560000s
220  my @T=(['dai',118800], ['week',777600], ['month',3024000], ['year',34560000]);
221  print h1("Nagiosgraph");
222  print p("Performance data for ".strong("Host: ").tt($h).' &#183; '.strong("Service: ").tt($s));
223  for my $l ( @T ) {
224    my($p,$t) = ($l->[0],$l->[1]);
225    print h2(ucfirst $p . "ly");
226    if ( @db ) {
227      for my $g ( @db ) {
228        my $arg = join '&', "host=$h", "service=$s", "db=$g", "graph=$t",
229                            "geom=$d", "rrdopts=$o";
230        my @gl = split ',', $g;
231        my $ds = shift @gl;
232        print div({-class => "graphs"}, img( {-src => "?$arg", -alt => "Graph"} ) );
233        print div({-class => "graph_description"}, cite(strong($ds).br().small(join(", ", @gl))));
234      }
235    } else {
236      my $arg = join '&', "host=$h", "service=$s", "graph=$t",
237                          "geom=$d", "rrdopts=$o";
238      print div({-class => "graphs"}, img( {-src => "?$arg", -alt => "Graph"} ) );
239    }
240  }
241}
242
243exit unless readconfig();
244
245# Expect host, service and db input
246my $host = param('host') if param('host');
247my $service = param('service') if param('service');
248my @db = param('db') if param('db');
249my $graph = param('graph') if param('graph');
250my $geom = param('geom') if param('geom');
251my $rrdopts = param('rrdopts') if param('rrdopts');
252
253# Draw a graph or a page
254if ( $graph ) {
255  $| = 1; # Make sure headers arrive before image data
256  print header(-type => "image/png");
257  # Figure out db files and line labels
258  my $G = graphinfo($host,$service,@db);
259  my @ds = rrdline($host,$service,$geom,$rrdopts,$G,$graph);
260  debug(4, "CGI RRDs::graph ". join ' ', @ds);
261  RRDs::graph(@ds);
262  debug(2, "CGI RRDs::graph ERR " . RRDs::error) if RRDs::error;
263  exit;
264} else {
265  my @style;
266  if ($Config{stylesheet}) {
267    @style = ( -style => {-src => "$Config{stylesheet}"} );
268  }
269  print header, start_html(-id=>"nagiosgraph", -title => "nagiosgraph: $host-$service",
270    -meta => { -http_equiv => "Refresh", -content => "300" },
271    @style
272    );
273  page($host,$service,$geom,$rrdopts,@db);
274  print div({-id => "footer"}, hr(), small( "Created by ". a( {-href=>"http://nagiosgraph.sf.net/"}, "nagiosgraph"). "." ));
275  print end_html();
276}
Note: See TracBrowser for help on using the repository browser.