diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..d68d852
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,24 @@
+$Id: ChangeLog,v 1.2 2002/01/04 17:13:26 kas Exp $
+
+Fri Jan 4 18:00:39 CET 2002
+
+Directory mode almost fully implemented.
+Bumped the version number to 0.3
+
+
+Wed Jan 2 17:57:31 CET 2002
+
+The Directory[] directive is now visible in the URL.
+
+
+Tue Dec 18 14:06:29 CET 2001
+
+Implemented the following mrtg.cfg directives:
+ Unscaled, WithPeak, XZoom, YZoom
+Fixed the wrong behaviour of XScale, YScale.
+Added $version as the separate variable.
+Fixed the global options so that the graph still starts at y_min=0, even
+ if there is no time when the variable is near 0.
+Fixed the [^], [_], and [$] behaviour for multiple configuration files
+ (the value should not remain defined from the previous cfg. file).
+
diff --git a/FAQ b/FAQ
index 0a9aa76..cd32725 100644
--- a/FAQ
+++ b/FAQ
@@ -1,4 +1,4 @@
-$Id: FAQ,v 1.3 2001/12/17 17:30:36 kas Exp $
+$Id: FAQ,v 1.4 2002/01/04 17:18:17 kas Exp $
Q: What is this?
A: The mrtg-rrd.cgi scripts is a replacement for the 14all.cgi script
@@ -52,8 +52,7 @@ A: No, but it understands a very large subset of MRTG directives. See the
Q: Why to develop another 14all.cgi?
A: This script tries to produce its output as much similar to the original
MRTG output as possible. It also implements (I believe) much bigger
- subset of MRTG configuration directives than 14all.cgi. On the other
- hand, it doesn't do the directory index files (yet).
+ subset of MRTG configuration directives than 14all.cgi.
Q: Where can I find the newest version?
A: Look at http://www.fi.muni.cz/~kas/mrtg-rrd/ - this is the project home
diff --git a/Makefile b/Makefile
index dbca3b3..373fd26 100644
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,10 @@
-# $Id: Makefile,v 1.1 2001/12/17 15:38:07 kas Exp $
+# $Id: Makefile,v 1.3 2002/01/04 17:16:05 kas Exp $
-FILES = COPYING FAQ TODO Makefile mrtg-rrd.cgi
+FILES = COPYING FAQ TODO Makefile mrtg-rrd.cgi ChangeLog
TARGETS = mrtg-rrd.fcgi
-VERSION = 0.1
+VERSION = 0.3
all: $(TARGETS)
diff --git a/TODO b/TODO
index 32e41e4..5a244af 100644
--- a/TODO
+++ b/TODO
@@ -1,4 +1,4 @@
-$Id: TODO,v 1.1 2001/12/17 15:06:37 kas Exp $
+$Id: TODO,v 1.3 2002/01/04 17:13:27 kas Exp $
Unimplemented mrtg.cfg directives
=================================
@@ -9,17 +9,12 @@ NoMib2: (and displaying system uptime) I don't want to query routers from
Language: TODO
Libadd: (handled separately) Don't want to mess with more BEGIN{} statements.
RouterUptime: I don't want to query the routers from the CGI.
-Unscaled: don't know how to tell this to rrdgraph
-WithPeak: don't know how to tell this to rrdgraph
Extension: (has no meaning)
-Directory: (partly implemented - reads the directive, but it is not visible in URL)
-XZoom: don't know how to tell this to rrdgraph
-YZoom: don't know how to tell this to rrdgraph
YTics: don't know how to tell this to rrdgraph
YTicsFactor: don't know how to tell this to rrdgraph
Step: don't know what this should do
Option:
- growright: it is the default (don't know how to make growleft grapsh)
+ growright: it is the default (don't know how to make growleft graphs)
noi: TODO
noo: TODO
SetEnv: Makes sense only for Target[]. Not implemented.
@@ -31,10 +26,20 @@ Other TODO/missing items
Option for setting the image format (PNG/GIF).
-Directory/all graphs listing.
+More customizable directory listing.
Exact time of the previous VRULE (for month and year graphs).
The MRTG-like legend on the X axis of the daily graph (every 2nd hour
instead of every 6th our and ":00" appended).
+
+Known bugs
+==========
+
+* It should complain if the RRD::graph() fails.
+* Directory mode does not honour the "Suppress[]: d" and refers to the daily
+ graph unconditionally.
+* Directory mode does not generate the "WIDHT=" and "HEIGHT=" parameters
+ to the tag.
+
diff --git a/mrtg-rrd.cgi b/mrtg-rrd.cgi
index e8b199a..0134f5f 100755
--- a/mrtg-rrd.cgi
+++ b/mrtg-rrd.cgi
@@ -1,6 +1,6 @@
#!/usr/bin/perl -w
#
-# $Id: mrtg-rrd.cgi,v 1.3 2001/12/17 17:17:42 kas Exp $
+# $Id: mrtg-rrd.cgi,v 1.6 2002/01/04 17:13:27 kas Exp $
#
# mrtg-rrd.cgi: The script for generating graphs for MRTG statistics.
#
@@ -31,10 +31,13 @@ use POSIX qw(strftime);
use lib '/usr/lib/perl5/5.00503/i386-linux';
use RRDs;
-use vars qw(@config_files @all_config_files %targets %config $config_time);
+use vars qw(@config_files @all_config_files %targets %config $config_time
+ %directories $version);
# EDIT THIS to reflect all your MRTG config files
-BEGIN { @config_files = qw(/home/fadmin/mrtg/mrtg.cfg); }
+BEGIN { @config_files = qw(/home/fadmin/mrtg/new/mrtg.cfg); }
+
+$version = '0.3';
sub handler ($)
{
@@ -42,15 +45,29 @@ sub handler ($)
try_read_config();
- my ($stat, $ext) = ($q->path_info() =~
- /^\/(.+)(\.html|-(day|week|month|year)\.png)$/);
+ my $path = $q->path_info();
+ $path =~ s/^\///;
+ $path =~ s/\/$//;
+ if (defined $directories{$path}) {
+ if ($q->path_info() =~ /\/$/) {
+ print_dir($path);
+ } else {
+ print "Location: ", $q->url(-path_info=>1), "/\n\n";
+ }
+ return;
+ }
+
+ my ($dir, $stat, $ext) = ($q->path_info() =~
+ /^(.*)\/([^\/]+)(\.html|-(day|week|month|year)\.png)$/);
-# $stat ||= 'ares.fi.muni.cz.eth2';
-# $ext ||= '.html';
+ $dir =~ s/^\///;
print_error("Undefined statistics")
unless defined $targets{$stat};
+ print_error("Incorrect directory")
+ unless defined $targets{$stat}{direcory} || $targets{$stat}{directory} eq $dir;
+
my $tgt = $targets{$stat};
common_args($stat, $tgt, $q);
@@ -89,7 +106,7 @@ sub do_html($)
my @month = do_image($tgt, 'month');
my @year = do_image($tgt, 'year');
- http_headers('text/html', $tgt);
+ http_headers('text/html');
print <<'EOF';
@@ -122,55 +139,38 @@ EOF
html_graph($tgt, 'month', 'Monthly', '2 Hour', \@month);
html_graph($tgt, 'year', 'Yearly', '1 Day', \@year);
- print <<"EOF" unless defined $tgt->{options}{nolegend};
-
-
-$tgt->{colname1} ### |
-$tgt->{legend1} |
-$tgt->{colname2} ### |
-$tgt->{legend2} |
-EOF
- print <<"EOF" unless defined $tgt->{options}{nobanner};
-
+ unless (defined $tgt->{options}{nolegend}) {
+ print <
-
-
-
+
+
+
+ $tgt->{colname1} ### |
+ $tgt->{legend1} |
+
+
+ $tgt->{colname2} ### |
+ $tgt->{legend2} |
+EOF
+ if ($tgt->{withpeak} ne '') {
+ print <
+
+ $tgt->{colname3} ### |
+ $tgt->{legend3} |
+
+
+ $tgt->{colname4} ### |
+ $tgt->{legend4} |
+EOF
+ }
+ print <
EOF
+ }
+
+ print_banner() unless defined $tgt->{options}{nobanner};
+
print $tgt->{pagefoot} if defined $tgt->{pagefoot};
print "\n", <<'EOF';
@@ -204,8 +204,8 @@ sub html_graph($$$$$)
my $x = $params->[1];
my $y = $params->[2];
- $x *= $tgt->{xscale} if defined $tgt->{xscale};
- $y *= $tgt->{yscale} if defined $tgt->{yscale};
+ $x *= $tgt->{xzoom} if defined $tgt->{xzoom};
+ $y *= $tgt->{yzoom} if defined $tgt->{yzoom};
my $kilo = $tgt->{kilo};
my @kmg = split(',', $tgt->{kmg});
@@ -309,9 +309,9 @@ sub do_percent($$)
@percent;
}
-sub http_headers($$)
+sub http_headers($)
{
- my ($content_type, $target) = @_;
+ my ($content_type) = @_;
print <<"EOF";
Content-Type: $content_type
@@ -325,7 +325,7 @@ EOF
print "\n";
}
-sub do_image($$$)
+sub do_image($$)
{
my ($target, $ext) = @_;
@@ -341,39 +341,65 @@ sub do_image($$$)
my $oldsec;
my $back;
+ my $unscaled;
+ my $withpeak;
+
if ($ext eq 'day') {
$seconds = strftime("%s", @t);
$back = 30*3600; # 30 hours
$oldsec = $seconds - 86400;
+ $unscaled = 1 if $target->{unscaled} =~ /d/;
+ $withpeak = 1 if $target->{withpeak} =~ /d/;
} elsif ($ext eq 'week') {
$seconds = strftime("%s", @t);
$t[6] = ($t[6]+6) % 7;
$seconds -= $t[6]*86400;
$back = 8*86400; # 8 days
$oldsec = $seconds - 7*86400;
+ $unscaled = 1 if $target->{unscaled} =~ /w/;
+ $withpeak = 1 if $target->{withpeak} =~ /w/;
} elsif ($ext eq 'month') {
$t[3] = 1;
$seconds = strftime("%s", @t);
$back = 36*86400; # 36 days
$oldsec = $seconds - 30*86400; # FIXME (the right # of days!!)
+ $unscaled = 1 if $target->{unscaled} =~ /m/;
+ $withpeak = 1 if $target->{withpeak} =~ /m/;
} elsif ($ext eq 'year') {
$t[3] = 1;
$t[4] = 0;
$seconds = strftime("%s", @t);
$back = 396*86400; # 365 + 31 days
$oldsec = $seconds - 365*86400; # FIXME (the right # of days!!)
+ $unscaled = 1 if $target->{unscaled} =~ /y/;
+ $withpeak = 1 if $target->{withpeak} =~ /y/;
} else {
print_error("Unknown file extension: $ext");
}
- my @rv = RRDs::graph($file, '-s', "-$back", @{$target->{args}},
- "VRULE:$oldsec#ff0000", "VRULE:$seconds#ff0000");
+ my @local_args;
+
+ if ($unscaled) {
+ @local_args = ('-u', $target->{maxbytes1});
+ push @local_args, '--rigid' unless defined $target->{absmax};
+ }
+
+ my @local_args_end;
+
+ if ($withpeak) {
+ push @local_args_end, 'LINE1:maxin'.$target->{col3}.':MaxIn',
+ 'LINE1:maxout'.$target->{col4}.':MaxOut';
+ }
+
+ my @rv = RRDs::graph($file, '-s', "-$back", @local_args,
+ @{$target->{args}}, "VRULE:$oldsec#ff0000",
+ "VRULE:$seconds#ff0000", @local_args_end);
# In array context just return the values
return @rv if wantarray;
# Not in array context ==> print out the PNG file.
- http_headers('image/png', $target);
+ http_headers('image/png');
open PNG, "<$file" or print_error("Can't open $file: $!");
my $buf;
@@ -392,20 +418,20 @@ sub common_args($$$)
$target->{name} = $name;
- if (defined $target->{directory}) {
- $target->{directory} .= '/'
- unless $target->{directory} =~ /\/$/;
- } else {
- $target->{directory} = '';
- }
+ $target->{directory} = ''
+ unless defined $target->{directory};
+
+ my $tdir = $target->{directory};
+ $tdir .= '/'
+ unless $tdir eq '' || $tdir =~ /\/$/;
- $target->{url} = $q->url . '/' . $name;
+ $target->{url} = $q->url . '/' . $tdir . $name;
my $dir = $config{workdir};
$dir = $config{logdir}
if defined $config{logdir};
- $target->{rrd} = $dir . '/' . $target->{directory} . $name . '.rrd';
+ $target->{rrd} = $dir . '/' . $tdir . $name . '.rrd';
%{$target->{options}} = ()
unless defined %{$target->{options}};
@@ -416,13 +442,13 @@ sub common_args($$$)
$target->{suppress} ||= '';
- $target->{day} = $dir . '/' . $target->{directory} . $name
- . '-day.png' unless $target->{suppress} =~ /d/;
- $target->{week} = $dir . '/' . $target->{directory} . $name
+ $target->{day} = $dir . '/' . $tdir . $name
+ . '-day.png' unless $tdir =~ /d/;
+ $target->{week} = $dir . '/' . $tdir . $name
. '-week.png' unless $target->{suppress} =~ /w/;
- $target->{month} = $dir . '/' . $target->{directory} . $name
+ $target->{month} = $dir . '/' . $tdir . $name
. '-month.png' unless $target->{suppress} =~ /m/;
- $target->{year} = $dir . '/' . $target->{directory} . $name
+ $target->{year} = $dir . '/' . $tdir . $name
. '-year.png' unless $target->{suppress} =~ /y/;
$target->{maxbytes1} = $target->{maxbytes}
@@ -435,7 +461,7 @@ sub common_args($$$)
push @args, '--lazy', '-c', 'FONT#000000', '-c',
'MGRID#000000', '-c', 'FRAME#000000',
- '-g';
+ '-g', '-l', '0';
$target->{background} = '#f5f5f5'
unless defined $target->{background};
@@ -455,11 +481,21 @@ sub common_args($$$)
push @args, '-b', $target->{kilo}
if defined $target->{kilo};
- push @args, '-w', $target->{xsize}
- if defined $target->{xsize};
+ if (defined $target->{xsize}) {
+ if (defined $target->{xscale}) {
+ push @args, '-w', $target->{xsize}*$target->{xscale};
+ } else {
+ push @args, '-w', $target->{xsize};
+ }
+ }
- push @args, '-h', $target->{ysize}
- if defined $target->{ysize};
+ if (defined $target->{ysize}) {
+ if (defined $target->{yscale}) {
+ push @args, '-h', $target->{ysize}*$target->{yscale};
+ } else {
+ push @args, '-h', $target->{ysize};
+ }
+ }
my $scale = 1;
@@ -477,6 +513,10 @@ sub common_args($$$)
unless defined $target->{legend1};
$target->{legend2} = 'Outgoing Traffic in Bits per Second'
unless defined $target->{legend2};
+ $target->{legend3} = 'Peak Incoming Traffic in Bits per Second'
+ unless defined $target->{legend3};
+ $target->{legend4} = 'Peak Outgoing Traffic in Bits per Second'
+ unless defined $target->{legend4};
$target->{shortlegend} = 'b/s'
unless defined $target->{shortlegend};
} else {
@@ -486,6 +526,10 @@ sub common_args($$$)
unless defined $target->{legend1};
$target->{legend2} = 'Outgoing Traffic in Bytes per Second'
unless defined $target->{legend2};
+ $target->{legend3} = 'Peak Incoming Traffic in Bytes per Second'
+ unless defined $target->{legend3};
+ $target->{legend4} = 'Peak Outgoing Traffic in Bytes per Second'
+ unless defined $target->{legend4};
$target->{shortlegend} = 'B/s'
unless defined $target->{shortlegend};
}
@@ -494,10 +538,16 @@ sub common_args($$$)
push @args, "DEF:in0=$target->{rrd}:ds0:AVERAGE",
"CDEF:in=in0,$scale,*",
"DEF:out0=$target->{rrd}:ds1:AVERAGE",
- "CDEF:out=out0,$scale,*";
+ "CDEF:out=out0,$scale,*",
+ "DEF:maxin0=$target->{rrd}:ds0:MAX",
+ "CDEF:maxin=maxin0,$scale,*",
+ "DEF:maxout0=$target->{rrd}:ds1:MAX",
+ "CDEF:maxout=maxout0,$scale,*";
} else {
push @args, "DEF:in=$target->{rrd}:ds0:AVERAGE",
- "DEF:out=$target->{rrd}:ds1:AVERAGE";
+ "DEF:out=$target->{rrd}:ds1:AVERAGE",
+ "DEF:maxin=$target->{rrd}:ds0:MAX",
+ "DEF:maxout=$target->{rrd}:ds1:MAX";
}
my $i=1;
@@ -559,6 +609,9 @@ sub try_read_config()
colours => 'GREEN#00cc00,BLUE#0000ff,DARK GREEN#006600,MAGENTA#ff00ff,AMBER#ef9f4f',
legendi => ' In:',
legendo => ' Out:',
+ unscaled => '',
+ withpeak => '',
+ directory => '',
);
%config = (
@@ -569,16 +622,21 @@ sub try_read_config()
%targets = ();
- %{$targets{_}} = %defaults;
- %{$targets{'^'}} = ();
- %{$targets{'$'}} = ();
-
@all_config_files = @config_files;
+ my $order = 0;
for my $cfgfile (@config_files) {
- read_mrtg_config($cfgfile, \%defaults);
+ %{$targets{_}} = %defaults;
+ %{$targets{'^'}} = ();
+ %{$targets{'$'}} = ();
+
+ read_mrtg_config($cfgfile, \%defaults, \$order);
}
+ delete $targets{'^'};
+ delete $targets{_};
+ delete $targets{'$'};
+
if (defined $config{pathadd}) {
$ENV{PATH} .= ':'.$config{pathadd};
}
@@ -587,14 +645,16 @@ sub try_read_config()
# use lib $config{libadd}
# }
+ parse_directories();
+
$config_time = time;
}
-sub read_mrtg_config($$);
+sub read_mrtg_config($$$);
-sub read_mrtg_config($$)
+sub read_mrtg_config($$$)
{
- my ($file, $def) = @_;
+ my ($file, $def, $order) = @_;
my %defaults = %$def;
@@ -620,6 +680,7 @@ sub read_mrtg_config($$)
my ($tgt, $opt, $val) = (lc($2), lc($1), $3);
unless (exists $targets{$tgt}) {
%{$targets{$tgt}} = %{$targets{_}};
+ $targets{$tgt}{order} = ++$$order;
}
if ($tgt eq '_' && $val eq '') {
if ($defaults{$opt}) {
@@ -643,7 +704,7 @@ sub read_mrtg_config($$)
next;
} elsif (/^Include *: *(\S*)$/) {
push @all_config_files, $1;
- read_mrtg_config($1, $def);
+ read_mrtg_config($1, $def, $order);
next;
} elsif (/^([\w\d]+) *: *(\S*)$/) {
my ($opt, $val) = (lc($1), lc($2));
@@ -654,8 +715,118 @@ sub read_mrtg_config($$)
}
}
-sub dump_targets() {
+sub parse_directories {
+ %directories = ();
+ # FIXME: the sort is expensive
+ for my $name (sort { $targets{$a}{order} <=> $targets{$b}{order} } keys %targets) {
+ my $dir = $targets{$name}{directory}
+ if defined $targets{$name}{directory};
+ $dir = '' unless defined $dir;
+
+ my $prefix = '';
+ for my $component (split /\/+/, $dir) {
+ add_dir($prefix, $component);
+ $prefix .= $component . '/';
+ }
+
+ add_dir($dir, $name);
+
+ }
+}
+
+sub add_dir($$) {
+ my ($dir, $name) = @_;
+
+ @{$directories{$dir}} = () unless defined $directories{$dir};
+ push (@{$directories{$dir}}, $name)
+ unless defined $directories{$dir.$name};
+}
+
+sub print_dir($) {
+ my ($dir) = @_;
+
+ my $dir1 = $dir . '/';
+
+ http_headers('text/html');
+
+ print <
+
+MRTG: Directory $dir1
+
+MRTG graphs and subdirectories in directory $dir1
+
+
+EOF
+ for my $item (@{$directories{$dir}}) {
+ if (defined $targets{$item}) {
+ my $itemname = $item;
+ $itemname = $targets{$item}{title}
+ if defined $targets{$item}{title};
+ print <$itemname
+
+
+EOF
+ } else {
+ print <$item/
+EOF
+ }
+ }
+
+ print "
\n";
+ print_banner();
+ print "\n