#!/usr/bin/perl -w
+# Program for updating an rrd with info from innduct and inn logs
+# Needs to be run once inside a lock
+
+# rrd-graphs/newstailer - part of rrd-graphs, a tool for online graphs
+# Copyright 2010, 2012 Ian Jackson
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+# killall newstailer
+# with-lock-ex -f data/news/lock sh -xc \
+# "rm data/news/*.rrd; ./newstailer -Odata/news/ -D \
+# /var/log/news/news.notice.{6,5,4,3,2,1}.gz /var/log/news/news.notice{.0,} ''"
+
use strict qw(refs vars);
use POSIX;
die unless @ARGV;
my $totail= pop @ARGV;
-if ($debug) { open DEBUG, ">& STDERR" or die $!; }
+if ($debug) { open DEBUG, ">& STDOUT" or die $!; }
+
+our %details;
+
+
+our @detail_defaults=
+ (
+ Step => 60,
+ DstArguments => "7200:0:U",
+ Xff => 0.5,
+ Archives => [ [ 3600*4, 60 ], # 4hr, 1min resolution
+ [ 3600*25, 180 ], # 25h, 3min resolution
+ [ 86400*8, 600 ], # 8d, 10min resolution
+ [ 86400*7*14, 3600*2 ], # 14wks, 2hr resolution
+ [ 86400*366, 3600*6 ], # 1yr, 6hr resolution
+ [ 86400*366*3, 3600*24 ] ], # 3yr, 1d resolution
+ );
our @fields_in= qw(seconds accepted refused rejected duplicate
accepted_size duplicate_size);
-our $tmpl_in= join ':',@fields_in;
-our %details= (
- 'in' => {
- Step => 60,
- DstArguments => "7200:0:U",
- Xff => 0.5,
- Archives => [ [ 3600*4, 60 ], # 4hr, 1min resolution
- [ 3600*25, 180 ], # 25h, 3min resolution
- [ 86400*14*5, 3600 ], # 14wks, 1hr resolution
- [ 86400*370*2, 3600*24 ] ], # 2yr+, 1day resolution
- }
-);
+$details{'in'}= {
+ Fields => \@fields_in,
+ @detail_defaults
+};
+
+our @fields_out= qw(missing offered deferred
+ accepted unwanted rejected body_missing);
+$details{'out'}= {
+ Fields => \@fields_out,
+ @detail_defaults
+};
+
our ($time,$host,$peer,$conn,$stats);
-sub create_rrd ($$$) {
- my ($inout, $path, $fields) = @_;
+sub create_rrd ($$) {
+ my ($inout, $path) = @_;
my $details= $details{$inout};
my @sargs= ($path, '--start','now-1y', '--step',$details->{Step});
my @largs;
- push @largs, "DS:$_:ABSOLUTE:$details->{DstArguments}" foreach @$fields;
+ push @largs, "DS:$_:ABSOLUTE:$details->{DstArguments}"
+ foreach @{ $details{$inout}{Fields} };
foreach (@{ $details->{Archives} }) {
my ($whole,$reso) = @$_;
my $steps= $reso / $details->{Step};
$rrdupdate->{DoneUpto}= $h->{'last_update'};
}
-sub find_or_create_rrd ($$) {
- my ($inout, $fields) = @_;
+sub find_or_create_rrd ($) {
+ my ($inout) = @_;
my $rrd= {
Path => "${outpfx}${host}${sep}${peer}_${inout}.rrd",
};
get_rrd_info($rrd, $rrd->{Path});
} else {
$!==&ENOENT or die "$rrd->{Path} $!";
- create_rrd($inout, $rrd->{Path}, $fields);
+ create_rrd($inout, $rrd->{Path});
$rrd->{DoneUpto}= 0;
}
return $rrd;
our @rrd_blockedupdates;
our $rrd_blockedupdate_time;
-sub update_rrd ($$$$) {
- my ($inout,$tmpl,$vals,$fields) = @_;
+sub update_rrd ($$) {
+ my ($inout,$vals) = @_;
my $rrd= $rrds{$host,$peer,$inout};
if (!$rrd) {
- $rrd= $rrds{$host,$peer,$inout}= find_or_create_rrd($inout, $fields);
- $rrd->{Template}= $tmpl;
+ $rrd= $rrds{$host,$peer,$inout}= find_or_create_rrd($inout);
+ $rrd->{Template}= join ':', @{ $details{$inout}{Fields} };
}
return if $time <= $rrd->{DoneUpto};
our %in_conns;
sub inbound_connected () {
- print DEBUG "inbound connected $host $peer $conn\n" if $debug>=2;
+ print DEBUG "inbound $time connected $host $peer $conn\n" if $debug>=2;
$in_conns{$host,$peer,$conn} = [ (0) x @fields_in ];
}
sub inbound_closed () {
- print DEBUG "inbound closed $host $peer $conn\n" if $debug>=2;
+ print DEBUG "inbound $time closed $host $peer $conn\n" if $debug>=2;
delete $in_conns{$host,$peer,$conn};
}
sub inbound_stats () {
$_= $stats.' ';
- my %s;
s/(?<=[a-z]) (?=[a-z])/_/g;
my $hpc= $in_conns{$host,$peer,$conn};
if (!$hpc) {
- print DEBUG "inbound UNKNOWN $host $peer $conn $stats\n";
+ print DEBUG "inbound $time UNKNOWN $host $peer $conn $stats\n";
$in_conns{$host,$peer,$conn}= $hpc= [ (undef) x @fields_in ];
} else {
- print DEBUG "inbound stats $host $peer $conn $stats\n" if $debug>=2;
+ print DEBUG "inbound $time stats $host $peer $conn $stats\n"
+ if $debug>=2;
}
+ my %s;
while (s/^([a-z_]+) (\d+)\s//) { $s{$1}= $2; }
my @v;
foreach my $f (@fields_in) {
$hpc->[@v]= $this;
push @v, defined($last) ? $this - $last : 'U';
}
- update_rrd('in',$tmpl_in,\@v,\@fields_in);
+ update_rrd('in',\@v);
}
sub outbound_stats () {
- print "$host $peer OUT $stats\n";
+ print DEBUG "outbound $time stats $host $peer $stats\n" if $debug>=2;
+ $_= " $stats ";
+ s/missing(?=\=\d+ \()/body_missing/;
+ s/\([^()]*\)/ /;
+ my %s;
+ while (s/ ([a-z]\w+)\=(\d+) / /) { $s{$1}= $2; }
+ my @v;
+ foreach my $f (@fields_out) {
+ my $this= $s{$f};
+ push @v, defined($this) ? $this : 'U';
+ }
+ update_rrd('out',\@v);
}
sub run ($) {
($time,$host,$process,$pid,$msg) = @$sl;
actually_update_rrds();
next unless exists $dohosts{$host};
- #print join("|", map { defined($_) ? $_ : "<undef>" } @$sl), "\n";
+ print DEBUG "logfile ",
+ join("|", map { defined($_) ? $_ : "<undef>" } @$sl), "\n"
+ if $debug>=3;
if ($process eq 'innd' && !defined $pid) {
if (($peer,$conn) = $msg =~
m/^($host_re) connected ($conn_re)(?: streaming allowed)?$/) {
inbound_connected()
} elsif (($peer,$conn,$cc,$stats) = $msg =~
- m/^($host_re):($conn_re) (closed|checkpoint) (seconds .*)$/) {
+ m/^($host_re):($conn_re) (closed|checkpoint) (seconds .*)$/) {
inbound_stats();
inbound_closed() if $cc eq 'closed';
}
} elsif ($process eq 'innduct') {
if (($peer,$stats) = $msg =~
- m/^($host_re)\| (?:completed|processed) \S+ (read=.*)$/) {
+ m/^($host_re)\| notice: (?:completed|processed) \S+ (read=.*)$/) {
outbound_stats();
}
}