Created
July 13, 2010 17:34
-
-
Save kamipo/474214 to your computer and use it in GitHub Desktop.
munin.psgi
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use strict; | |
use warnings; | |
use Plack::Builder; | |
use Plack::App::Directory; | |
use Munin; | |
use Date::Manip; | |
use POSIX qw(strftime); | |
use File::Slurp; | |
my $GRAPHER = "/usr/share/munin/munin-graph"; | |
my $conffile = "/etc/munin/munin.conf"; | |
my %TIMES = ( | |
"day" => [qw/ --noweek --nomonth --noyear --nosumweek --nosumyear/], | |
"week" => [qw/--noday --nomonth --noyear --nosumweek --nosumyear/], | |
"month" => [qw/--noday --noweek --noyear --nosumweek --nosumyear/], | |
"year" => [qw/--noday --noweek --nomonth --nosumweek --nosumyear/], | |
"week-sum" => [qw/--noday --noweek --nomonth --noyear --nosumyear/], | |
"year-sum" => [qw/--noday --noweek --nomonth --noyear --nosumweek/], | |
); | |
my %period = ( | |
"day" => 300, | |
"week" => 1800, | |
"month" => 7200, | |
"year" => 86400, | |
"week-sum" => 1800, | |
"year-sum" => 86400, | |
); | |
my $config = munin_readconfig($conffile); | |
sub munin_cgi_graph { | |
my $scale = "day"; | |
my $host = ""; | |
my $serv = ""; | |
my $dom = ""; | |
my $path = $_[0]->{PATH_INFO} || ""; | |
$path =~ s/^\///; | |
($dom, $host, $serv) = split /\//, $path; | |
($serv, $scale) = split /-/, $serv, 2; | |
$scale =~ s/\.png$//; | |
verify_parameters($dom, $host, $serv, $scale); | |
my $filename = get_picture_filename($config, $dom, $host, $serv, $scale); | |
my $time = time; | |
if (-f $filename) { | |
my @sstats = stat($filename); | |
my $slast_modified = strftime("%a, %d %b %Y %H:%M:%S %Z", localtime($sstats[9])); | |
if (defined $_[0]->{HTTP_IF_MODIFIED_SINCE} and | |
!modified(gmtime(time+($period{$scale}-($time%$period{$scale}))), $sstats[9]-1)) { | |
return [ | |
304, | |
[ | |
'Content-Type' => 'image/png', | |
'Expires' => strftime("%a, %d %b %Y %H:%M:%S GMT", gmtime(time+($period{$scale}-($time%$period{$scale})))), | |
'Last-Modified' => $slast_modified, | |
], | |
[] | |
]; | |
} | |
} | |
if (!graph_usable($filename, $time, $scale)) { | |
draw_graph($host, $serv, $TIMES{$scale}); | |
if (! -f $filename) { | |
return [ | |
500, | |
[ | |
'Content-Type' => 'image/png', | |
], | |
[] | |
]; | |
} | |
} | |
my @stats = stat($filename); | |
my $last_modified = strftime("%a, %d %b %Y %H:%M:%S %Z", localtime ($stats[9])); | |
return [ | |
200, | |
[ | |
'Content-Type' => 'image/png', | |
'Expires' => strftime("%a, %d %b %Y %H:%M:%S GMT", gmtime(time+($period{$scale}-($time%$period{$scale})))), | |
'Last-Modified' => $last_modified, | |
], | |
[scalar read_file($filename)] | |
]; | |
} | |
sub get_picture_filename { | |
my $config = shift; | |
my $domain = shift; | |
my $name = shift; | |
my $service = shift; | |
my $scale = shift; | |
return "$config->{'htmldir'}/$domain/$name-$service-$scale.png"; | |
} | |
sub verify_parameters { | |
my $dom = shift; | |
my $host = shift; | |
my $serv = shift; | |
my $scale = shift; | |
if (!$dom) { | |
print STDERR "Warning: Request for graph without specifying domain. Bailing out.\n"; | |
exit 1; | |
} | |
if (!$host) { | |
print STDERR "Warning: Request for graph without specifying host. Bailing out.\n"; | |
exit 1; | |
} | |
if (!$serv) { | |
print STDERR "Warning: Request for graph without specifying service. Bailing out.\n"; | |
exit 1; | |
} | |
if (!$scale) { | |
print STDERR "Warning: Request for graph without specifying scale. Bailing out.\n"; | |
exit 1; | |
} | |
else { | |
if (!defined $TIMES{$scale}) { | |
print STDERR "Warning: Weird scale setting \"$scale\". Bailing out.\n"; | |
exit 1; | |
} | |
} | |
} | |
sub graph_usable { | |
my $filename = shift; | |
my $time = shift; | |
my $scale = shift; | |
if (-f $filename) { | |
my @stats = stat(_); | |
my $expire = ($stats[9] - $time%$period{$scale}+$period{$scale})-$time; | |
if ($expire >= 0) { | |
return 1; | |
} else { | |
return 0; | |
} | |
} | |
return 0; | |
} | |
sub draw_graph { | |
my $host = shift; | |
my $serv = shift; | |
my $scale = shift; | |
$serv =~ s/[^\w_\/"'\[\]\(\)+=-]/_/; $serv =~ /^(.+)$/; $serv = $1; #" | |
$host =~ s/[^\w_\/"'\[\]\(\)+=-]/_/; $host =~ /^(.+)$/; $host = $1; #" | |
my @params = ($GRAPHER); | |
push @params, @$scale; | |
push @params, "--skip-locking", "--skip-stats", "--nolazy"; | |
push @params, "--host", $host, "--service", $serv; | |
push @params, "STDERR>&STDOUT"; | |
my $file = "/dev/null"; | |
unless (open (IN, "-|")) { | |
%ENV=(); | |
exec @params; | |
} | |
$file = join(' ', <IN>); | |
close(IN); | |
return $file; | |
} | |
sub modified { | |
my $since_string = shift; | |
my $created = shift; | |
my $ifmodsec = UnixDate(ParseDateString($since_string), "%s"); | |
return 1 if ($ifmodsec < $created); | |
return 0; | |
} | |
# main | |
if (!defined $config->{'cgiurl_graph'}) { | |
if (defined $config->{'cgiurl'}) { | |
$config->{'cgiurl_graph'} = $config->{'cgiurl'} . "/munin-cgi-graph"; | |
} | |
else { | |
$config->{'cgiurl_graph'} = "/cgi-bin/munin-cgi-graph"; | |
} | |
} | |
builder { | |
mount $config->{'cgiurl_graph'} => \&munin_cgi_graph; | |
mount '/' => Plack::App::Directory->new({root => $config->{htmldir}})->to_app; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment