1 |
#!/usr/bin/perl -w |
2 |
# i-scream central monitoring system |
3 |
# http://www.i-scream.org |
4 |
# Copyright (C) 2000-2004 i-scream |
5 |
# |
6 |
# This program is free software; you can redistribute it and/or |
7 |
# modify it under the terms of the GNU General Public License |
8 |
# as published by the Free Software Foundation; either version 2 |
9 |
# of the License, or (at your option) any later version. |
10 |
# |
11 |
# This program is distributed in the hope that it will be useful, |
12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
# GNU General Public License for more details. |
15 |
# |
16 |
# You should have received a copy of the GNU General Public License |
17 |
# along with this program; if not, write to the Free Software |
18 |
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
19 |
# |
20 |
# $Id$ |
21 |
|
22 |
use strict; |
23 |
use Getopt::Long; |
24 |
|
25 |
my $progname = "statgrab-make-mrtg-config"; |
26 |
my $statgrab = "statgrab"; |
27 |
my $workdir = undef; |
28 |
|
29 |
my $kib = 1024; |
30 |
my $mib = $kib * $kib; |
31 |
|
32 |
# Type 0 is plain integers. |
33 |
my $KIBIBYTES = 1; |
34 |
my $PERCENT = 2; |
35 |
|
36 |
# Print an entry in the MRTG config file. |
37 |
sub entry ($$$$$$$$$$) { |
38 |
my ($title, $vali, $valo, $max, $ylegend, $yunit, $legendi, $legendo, $gauge, $type) = @_; |
39 |
my $name = $vali; |
40 |
my $options = ""; |
41 |
$options .= " noo" unless defined $valo; |
42 |
$options .= " gauge" if $gauge; |
43 |
my $sgoptions = ""; |
44 |
$sgoptions .= " -o -p" if $type == $PERCENT; |
45 |
|
46 |
print "\n"; |
47 |
print "Title[$name]: $title\n"; |
48 |
print "PageTop[$name]: $title\n"; |
49 |
print "MaxBytes[$name]: $max\n"; |
50 |
print "YLegend[$name]: $ylegend\n"; |
51 |
print "ShortLegend[$name]: $yunit\n"; |
52 |
print "LegendI[$name]: $legendi\n"; |
53 |
print "LegendO[$name]: $legendo\n" if defined $valo; |
54 |
if ($type == $KIBIBYTES) { |
55 |
print "kMG[$name]: Ki,Mi,Gi,Ti\n"; |
56 |
} |
57 |
$valo = "const.0" unless defined $valo; |
58 |
print "Options[$name]:$options\n" if $options ne ""; |
59 |
print "Target[$name]: `$statgrab$sgoptions -m $vali $valo`\n"; |
60 |
} |
61 |
|
62 |
my $package_version = '@PACKAGE_VERSION@'; |
63 |
my $package_bugreport = '@PACKAGE_BUGREPORT@'; |
64 |
my $help_text = <<EOF; |
65 |
Usage: $progname [OPTION]... |
66 |
Generate MRTG configuration from statgrab output and write it to stdout. |
67 |
|
68 |
--no-header Don't print MRTG global options; useful if you |
69 |
want to include the output of this script in |
70 |
another MRTG config file |
71 |
--workdir PATH Use PATH for MRTG's WorkDir option |
72 |
--statgrab PATH Specify location of statgrab binary |
73 |
(default "statgrab") |
74 |
--help Display this help and exit |
75 |
|
76 |
Version $package_version - report bugs to $package_bugreport. |
77 |
EOF |
78 |
|
79 |
sub fatal ($) { |
80 |
my ($message) = @_; |
81 |
die "$progname: $message\n"; |
82 |
} |
83 |
|
84 |
sub main () { |
85 |
GetOptions('statgrab=s' => \$statgrab, |
86 |
'workdir=s' => \$workdir, |
87 |
'no-header' => \my $no_header, |
88 |
'help' => \my $help) or die $help_text; |
89 |
if ($help) { |
90 |
print "$help_text"; |
91 |
exit 0; |
92 |
} |
93 |
|
94 |
unless ($no_header or defined $workdir) { |
95 |
fatal "must specify --workdir or --no-header" |
96 |
} |
97 |
|
98 |
my %stats = (); |
99 |
my %toplevel = (); |
100 |
my %disks = (); |
101 |
my %fss = (); |
102 |
my %nets = (); |
103 |
open STATGRAB, "$statgrab|" or fatal "can't run statgrab"; |
104 |
while (<STATGRAB>) { |
105 |
chomp; |
106 |
/^([^=]*) = (.*)$/ or fatal "bad line in statgrab output"; |
107 |
$stats{$1} = $2; |
108 |
|
109 |
my @parts = split /\./, $1; |
110 |
$toplevel{$parts[0]} = 1; |
111 |
$disks{$parts[1]} = 1 if $parts[0] eq "disk"; |
112 |
$fss{$parts[1]} = 1 if $parts[0] eq "fs"; |
113 |
$nets{$parts[1]} = 1 if $parts[0] eq "net"; |
114 |
} |
115 |
close STATGRAB; |
116 |
|
117 |
unless ($no_header) { |
118 |
print "WorkDir: $workdir\n"; |
119 |
print "Options[^]: growright\n"; |
120 |
print "WriteExpires: Yes\n"; |
121 |
} |
122 |
|
123 |
if (exists $toplevel{"cpu"}) { |
124 |
entry("CPU idle", "cpu.idle", undef, "100", "Idle", "%", "idle", undef, 1, $PERCENT); |
125 |
entry("CPU iowait", "cpu.iowait", undef, "100", "iowait", "%", "iowait", undef, 1, $PERCENT); |
126 |
entry("CPU kernel", "cpu.kernel", undef, "100", "Kernel", "%", "kernel", undef, 1, $PERCENT); |
127 |
entry("CPU nice", "cpu.nice", undef, "100", "Nice", "%", "nice", undef, 1, $PERCENT); |
128 |
entry("CPU swap", "cpu.swap", undef, "100", "Swap", "%", "swap", undef, 1, $PERCENT); |
129 |
entry("CPU user", "cpu.user", undef, "100", "User", "%", "user", undef, 1, $PERCENT); |
130 |
} |
131 |
|
132 |
foreach my $disk (sort keys %disks) { |
133 |
my $name = $stats{"disk.$disk.disk_name"}; |
134 |
entry("Disk $name IO", "disk.$disk.read_bytes", "disk.$disk.write_bytes", 100*$mib, "IO rate", "B/s", "read", "write", 0, 0); |
135 |
} |
136 |
|
137 |
foreach my $fs (sort keys %fss) { |
138 |
my $name = $stats{"fs.$fs.mnt_point"}; |
139 |
my $size = $stats{"fs.$fs.size"}; |
140 |
my $inodes = $stats{"fs.$fs.total_inodes"}; |
141 |
entry("Filesystem $name space usage", "fs.$fs.used", undef, $size, "Space used", "B", "used", undef, 1, 0); |
142 |
entry("Filesystem $name inode usage", "fs.$fs.used_inodes", undef, $inodes, "Inodes used", "inodes", "used", undef, 1, 0); |
143 |
} |
144 |
|
145 |
if (exists $toplevel{"load"}) { |
146 |
entry("Load average over 1 minute", "load.min1", undef, 100, "Load average", "running", "load", undef, 1, 0); |
147 |
entry("Load average over 5 minutes", "load.min5", undef, 100, "Load average", "running", "load", undef, 1, 0); |
148 |
entry("Load average over 15 minutes", "load.min15", undef, 100, "Load average", "running", "load", undef, 1, 0); |
149 |
} |
150 |
|
151 |
if (exists $toplevel{"mem"}) { |
152 |
my $total = $stats{"mem.total"}; |
153 |
entry("Memory usage", "mem.used", "mem.cache", $total, "Memory usage", "B", "total", "cache", 1, 0); |
154 |
} |
155 |
|
156 |
foreach my $net (sort keys %nets) { |
157 |
my $name = $stats{"net.$net.interface_name"}; |
158 |
# FIXME should be able to discover interface speed |
159 |
entry("Network interface $name IO", "net.$net.rx", "net.$net.tx", 100*$mib, "Network IO", "B", "rx", "tx", 0, 0); |
160 |
} |
161 |
|
162 |
if (exists $toplevel{"page"}) { |
163 |
# FIXME what's a sensible maximum? |
164 |
entry("Paging IO", "page.in", "page.out", 1000, "Paging IO", "pages", "in", "out", 0, 0); |
165 |
} |
166 |
|
167 |
if (exists $toplevel{"proc"}) { |
168 |
# FIXME mildly silly assumption |
169 |
my $maxproc = 65536; |
170 |
entry("Processes running", "proc.running", undef, $maxproc, "Running", "procs", "running", undef, 1, 0); |
171 |
entry("Processes sleeping", "proc.sleeping", undef, $maxproc, "Sleeping", "procs", "running", undef, 1, 0); |
172 |
entry("Processes stopped", "proc.stopped", undef, $maxproc, "Stopped", "procs", "running", undef, 1, 0); |
173 |
entry("Processes", "proc.total", undef, $maxproc, "Total", "procs", "running", undef, 1, 0); |
174 |
entry("Processes zombie", "proc.zombie", undef, $maxproc, "Zombie", "procs", "running", undef, 1, 0); |
175 |
} |
176 |
|
177 |
if (exists $toplevel{"swap"}) { |
178 |
my $swapsize = $stats{"swap.total"}; |
179 |
entry("Swap usage", "swap.used", undef, $swapsize, "Swap usage", "B", "used", undef, 1, 0); |
180 |
} |
181 |
|
182 |
if (exists $toplevel{"user"}) { |
183 |
entry("Users", "user.num", undef, 1000, "Users", "users", "users", undef, 1, 0); |
184 |
} |
185 |
} |
186 |
|
187 |
main(); |