ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/experimental/reports/graphing/graph.pl
Revision: 1.1
Committed: Sat Mar 9 19:53:24 2002 UTC (22 years, 8 months ago) by tdb
Content type: text/plain
Branch: MAIN
Log Message:
Graphing of most of the i-scream data. This is intended as an alternative
to the current MySQL/DBReporter style of daily graph generation.
This is split into two sections:
watch.pl connects to the i-scream client interface, parses all the data
and stores it in rrdtool database files. This is still very incomplete and
somewhat messy code :)
graph.pl generates graphs from the rrdtool database files created by the
previous script. It drops these images into a directory structure for
viewing over the web.
The php pages provide an easy way to view these graphs during development,
but it is expected in the long term to integrate this into the i-scream
reports pages.
Finally XMLParser.pm is a wrapper to the XML parsing to create i-scream
style XMLPacket hashes :)

File Contents

# Content
1 #!/usr/bin/perl -w
2
3 # -----------------------------------------------------------
4 # i-scream graph generation script
5 # http://www.i-scream.org.uk
6 #
7 # Generates graphs from rrd databases for i-scream data.
8 #
9 # $Author$
10 # $Id$
11 #------------------------------------------------------------
12
13 ## TODO
14 # possibly make more configurable?
15 # -- allow configurable periods of graphs
16 # -- comments, types, etc
17 # -- move all to external config file
18
19 $| = 1;
20 use strict;
21 use RRDs;
22
23 # Base directory for images
24 # (a directory will be constructed for each host under this)
25 my($imgdir) = "/home/tdb/public_html/rrd";
26
27 # Location of RRD databases
28 my($rrddir) = "/u1/i-scream/rrd";
29
30 # / converted to a decimal then hex'd
31 my($hex_slash) = "_2f";
32 # _ converted to a decimal then hex'd
33 my($hex_underscore) = "_5f";
34
35 # Read the contents of the base directory
36 # and pull out the list of subdirectories (except . and .. :)
37 opendir(DIR, $rrddir);
38 my(@rrddirlist) = grep { -d "$rrddir/$_" && !/^\.$/ && !/^\.\.$/ } readdir(DIR);
39 closedir DIR;
40
41 # look through each directoty, as they might
42 # contain rrds for a particular machine
43 foreach my $machine (@rrddirlist) {
44 # Read the contents of the directory
45 opendir(DIR, "$rrddir/$machine");
46 my(@rrdlist) = grep { /\.rrd$/ && -f "$rrddir/$machine/$_" } readdir(DIR);
47 closedir DIR;
48
49 # See what rrd we have, and generate the graphs accordingly
50 foreach my $rrd (@rrdlist) {
51 chomp $rrd;
52 if($rrd =~ /^(cpu)\.rrd$/) {
53 my(@data);
54 push @data, "LINE2:$1:idle#00FF00:idle cpu";
55 push @data, "LINE2:$1:user#0000FF:user cpu";
56 push @data, "LINE2:$1:kernel#00FFFF:kernel cpu";
57 push @data, "LINE2:$1:swap#FF00FF:swap cpu";
58 push @data, "LINE2:$1:iowait#FF0000:iowait cpu";
59 &makegraph($machine, $1, "CPU Usage for $machine", \@data);
60 }
61 if($rrd =~ /^(mem)\.rrd$/) {
62 my(@data);
63 push @data, "LINE2:$1:free#00FF00:free memory";
64 push @data, "LINE2:$1:total#0000FF:total memory";
65 &makegraph($machine, $1, "Memory Usage for $machine", \@data);
66 }
67 if($rrd =~ /^(load)\.rrd$/) {
68 my(@data);
69 push @data, "LINE2:$1:load1#00FF00:1 minute load average";
70 push @data, "LINE2:$1:load5#0000FF:5 minute load average";
71 push @data, "LINE2:$1:load15#FF0000:15 minute load average";
72 &makegraph($machine, $1, "Loads for $machine", \@data);
73 }
74 if($rrd =~ /^(proc)\.rrd$/) {
75 my(@data);
76 push @data, "LINE2:$1:cpu#00FF00:cpu processes";
77 push @data, "LINE2:$1:sleeping#0000FF:sleeping processes";
78 push @data, "LINE2:$1:stopped#00FFFF:stopped processes";
79 push @data, "LINE2:$1:total#FF00FF:total processes";
80 push @data, "LINE2:$1:zombie#FF0000:zombie processes";
81 &makegraph($machine, $1, "Processes on $machine", \@data);
82 }
83 if($rrd =~ /^(swap)\.rrd$/) {
84 my(@data);
85 push @data, "LINE2:$1:free#00FF00:free swap";
86 push @data, "LINE2:$1:total#0000FF:total swap";
87 &makegraph($machine, $1, "Swap Usage for $machine", \@data);
88 }
89 if($rrd =~ /^(users)\.rrd$/) {
90 my(@data);
91 push @data, "LINE2:$1:count#00FF00:user count";
92 &makegraph($machine, $1, "User Count for $machine", \@data);
93 }
94 if($rrd =~ /^(disk)-(\S+).rrd$/) {
95 my(@data);
96 push @data, "LINE2:$1-$2:kbytes#0000FF:total size";
97 push @data, "LINE2:$1-$2:used#00FF00:used";
98 my($type) = $1;
99 my($name) = $2;
100 my($nicename) = $2;
101 $nicename =~ s/$hex_slash/\//g;
102 $nicename =~ s/$hex_underscore/_/g;
103 &makegraph($machine, "$type-$name", "Disk Usage for $machine on $nicename", \@data);
104 }
105 # probably a queue with a name like this :)
106 if($rrd =~ /^(\d+)_0\.rrd$/) {
107 my(@data);
108 my(@rawdata);
109 my($baserrd) = $1;
110 my($i) = 0;
111 while( -f "$rrddir/$machine/$baserrd\_$i.rrd" ) {
112 push @data, "LINE2:$baserrd\_$i:size" . &get_colour($i) . ":queue$i size ";
113 ++$i;
114 }
115 push @data, "LINE2:$baserrd\_0:total#FF0000:packets/sec - currently";
116 push @rawdata, "GPRINT:total:LAST:\"%lf %spackets/sec\"";
117 my($comment);
118 if(-f "$rrddir/$machine/$baserrd.def") {
119 open(DEF, "$rrddir/$machine/$baserrd.def");
120 $comment = <DEF>;
121 chomp $comment if defined $comment;
122 }
123 $comment = "unknown queue" if not defined $comment;
124 &makegraph($machine, $baserrd, $comment, \@data, \@rawdata);
125 }
126 }
127 }
128
129 #
130 # subroutine to make some graphs
131 #
132 # $machine = name of the machine
133 # (eg. kernow.ukc.ac.uk)
134 # $type = the type of graph for the machine
135 # (eg. cpu)
136 # $title = the title for the graph
137 # (eg. kernow CPU usage)
138 # $dataref = a reference to an array containing information for the graph
139 # elements of format: "gtype:rrdname:name#colour:comment with spaces"
140 # $rawcmdref = a reference to an array containing raw rrd commands
141 # elements a single command each, no spaces
142 #
143 sub makegraph() {
144 my($machine, $type, $title, $dataref, $rawcmdref) = @_;
145 # pass in these arrays by reference
146 my(@data) = @$dataref if defined $dataref;
147 my(@rawcmd) = @$rawcmdref if defined $rawcmdref;
148 # check if directory exists for images
149 if(! -d "$imgdir/$machine") {
150 # not sure on this umask, but it seems to work?
151 mkdir "$imgdir/$machine", 0777;
152 }
153 my(@rrdcmd);
154 foreach my $dataitem (@data) {
155 # dataitem should be: "gtype:rrdname:name#colour:comment with spaces"
156 if($dataitem =~ /^(\S+):(\S+):(\S+)#(.{6}):(.*)$/) {
157 push @rrdcmd, "DEF:$3=$rrddir/$machine/$2.rrd:$3:MAX";
158 push @rrdcmd, "$1:$3#$4:$5";
159 }
160 }
161 push @rrdcmd, "--title=$title";
162 push @rrdcmd, "--imgformat=PNG";
163 push @rrdcmd, "--lower-limit=0";
164 # add any further raw commands
165 push @rrdcmd, @rawcmd;
166 RRDs::graph ("$imgdir/$machine/$type-3h.png", "--start=-10800", @rrdcmd);
167 my($err_3h) = RRDs::error;
168 print STDERR "Error generating 3h graph for $machine\_$type: $err_3h\n" if $err_3h;
169 RRDs::graph ("$imgdir/$machine/$type-1d.png", "--start=-86400", @rrdcmd);
170 my($err_1d) = RRDs::error;
171 print STDERR "Error generating 1d graph for $machine\_$type: $err_1d\n" if $err_1d;
172 RRDs::graph ("$imgdir/$machine/$type-1w.png", "--start=-604800", @rrdcmd);
173 my($err_1w) = RRDs::error;
174 print STDERR "Error generating 1w graph for $machine\_$type: $err_1w\n" if $err_1w;
175 RRDs::graph ("$imgdir/$machine/$type-1m.png", "--start=-2678400", @rrdcmd);
176 my($err_1m) = RRDs::error;
177 print STDERR "Error generating 1m graph for $machine\_$type: $err_1m\n" if $err_1m;
178 return;
179 }
180
181 # hacky subroutine to return a colour
182 # could be done much better somehow :/
183 sub get_colour {
184 my($col) = @_;
185 if($col == 0) {
186 return "#0000FF";
187 }
188 elsif($col == 1) {
189 return "#00FF00";
190 }
191 elsif($col == 2) {
192 return "#FF00FF";
193 }
194 elsif($col == 3) {
195 return "#FFFF00";
196 }
197 elsif($col == 4) {
198 return "#00FFFF";
199 }
200 else {
201 return "#000066";
202 }
203 }