1 ##########################################################
2 # INN module for innreport (3.*).
4 # Sample file tested with INN 2.4, 2.3, 2.2, 1.7.2 and 1.5.1
6 # (c) 1997-1999 by Fabien Tassin <fta@sofaraway.org>
8 ##########################################################
10 # TODO: add the map file.
12 package innreport_inn;
17 my %ctlinnd = ('a', 'addhist', 'D', 'allow',
18 'b', 'begin', 'c', 'cancel',
19 'u', 'changegroup', 'd', 'checkfile',
20 'e', 'drop', 'f', 'flush',
21 'g', 'flushlogs', 'h', 'go',
22 'i', 'hangup', 's', 'mode',
23 'j', 'name', 'k', 'newgroup',
24 'l', 'param', 'm', 'pause',
25 'v', 'readers', 't', 'refile',
26 'C', 'reject', 'o', 'reload',
27 'n', 'renumber', 'z', 'reserve',
28 'p', 'rmgroup', 'A', 'send',
29 'q', 'shutdown', 'B', 'signal',
30 'r', 'throttle', 'w', 'trace',
31 'x', 'xabort', 'y', 'xexec',
32 'E', 'logmode', 'F', 'feedinfo',
33 'T', 'filter', 'P', 'perl',);
35 my %timer_names = (idle => 'idle',
36 hishave => 'history lookup',
37 hisgrep => 'history grep',
38 hiswrite => 'history write',
39 hissync => 'history sync',
40 nntpread => 'nntp read',
41 artparse => 'article parse',
42 artclean => 'article cleanup',
43 artwrite => 'article write',
44 artcncl => 'article cancel',
45 artlog => 'article logging',
46 sitesend => 'site send',
47 overv => 'overview write',
48 perl => 'perl filter',
49 python => 'python filter',
50 datamove => 'data move'
53 my %innfeed_timer_names = (
55 'blstats' => 'backlog stats',
56 'stsfile' => 'status file',
57 'newart' => 'article new',
58 'prepart' => 'article prepare',
59 'readart' => 'article read',
60 'read' => 'data read',
61 'write' => 'data write',
65 my %nnrpd_timer_names = (
67 'newnews' => 'newnews',
71 foreach (values %timer_names) {
72 $innd_time_min{$_} = $MIN;
73 $innd_time_max{$_} = $MAX;
74 $innd_time_time{$_} = 0; # to avoid a warning... Perl < 5.004
75 $innd_time_num{$_} = 0; # ...
77 $innd_time_times = 0; # ...
80 foreach (values %innfeed_timer_names) {
81 $innfeed_time_min{$_} = $MIN;
82 $innfeed_time_max{$_} = $MAX;
83 $innfeed_time_time{$_} = 0; # to avoid a warning... Perl < 5.004
84 $innfeed_time_num{$_} = 0; # ...
86 $innfeed_time_times = 0; # ...
89 foreach (values %nnrpd_timer_names) {
90 $nnrpd_time_min{$_} = $MIN;
91 $nnrpd_time_max{$_} = $MAX;
92 $nnrpd_time_time{$_} = 0; # to avoid a warning... Perl < 5.004
93 $nnrpd_time_num{$_} = 0; # ...
95 $nnrpd_time_times = 0; # ...
97 # collect: Used to collect the data.
99 my ($day, $hour, $prog, $res, $left, $CASE_SENSITIVE) = @_;
101 return 1 if $left =~ /Reading config from (\S+)$/o;
104 ## inn (from the "news" log file - not from "news.notice")
106 if ($prog eq "inn") {
108 if ($res =~ m/[\+j]/o) {
110 $inn_flow{"$day $hour"}++;
113 # Memorize the size. This can only be done with INN >= 1.5xx and
116 # server <msg-id> size [feeds]
118 # server <msg-id> (filename) size [feeds]
120 my ($s) = $left =~ /^\S+ \S+ (?:\(\S+\) )?(\d+)(?: |$)/o;
122 $inn_flow_size{"$day $hour"} += $s;
123 $inn_flow_size_total += $s;
128 # 437 Duplicate article
129 if ($left =~ /(\S+) <[^>]+> 437 Duplicate(?: article)?$/o) {
131 $server = lc $server unless $CASE_SENSITIVE;
132 $inn_badart{$server}++;
133 $inn_duplicate{$server}++;
137 if ($left =~ /(\S+) <[^>]+> 437 Unapproved for \"([^\"]+)\"$/o) {
138 my ($server, $group) = ($1, $2);
139 $server = lc $server unless $CASE_SENSITIVE;
140 $inn_badart{$server}++;
141 $inn_unapproved{$server}++;
142 $inn_unapproved_g{$group}++;
146 if ($left =~ /(\S+) <[^>]+> 437 Too old -- /o) {
148 $server = lc $server unless $CASE_SENSITIVE;
149 $inn_badart{$server}++;
150 $inn_tooold{$server}++;
153 # 437 Unwanted site ... in path
154 if ($left =~ /(\S+) <[^>]+> 437 Unwanted site (\S+) in path$/o) {
155 my ($server, $site) = ($1, $2);
156 $server = lc $server unless $CASE_SENSITIVE;
157 $inn_badart{$server}++;
158 $inn_uw_site{$server}++;
159 $inn_site_path{$site}++;
162 # 437 Unwanted newsgroup "..."
163 if ($left =~ /(\S+) <[^>]+> 437 Unwanted newsgroup \"(\S+)\"$/o) {
164 my ($server, $group) = ($1, $2);
165 ($group) = split(/,/, $group);
166 $server = lc $server unless $CASE_SENSITIVE;
167 $inn_badart{$server}++;
168 $inn_uw_ng_s{$server}++;
169 $inn_uw_ng{$group}++;
172 # 437 Unwanted distribution "..."
173 if ($left =~ /(\S+) <[^>]+> 437 Unwanted distribution \"(\S+)\"$/o) {
174 my ($server, $dist) = ($1, $2);
175 $server = lc $server unless $CASE_SENSITIVE;
176 $inn_badart{$server}++;
177 $inn_uw_dist_s{$server}++;
178 $inn_uw_dist{$dist}++;
181 # 437 Linecount x != y +- z
182 if ($left =~ /(\S+) <[^>]+> 437 Linecount/o) {
184 $server = lc $server unless $CASE_SENSITIVE;
185 $inn_badart{$server}++;
186 $inn_linecount{$server}++;
189 # 437 No colon-space in "xxxx" header
190 if ($left =~ /(\S+) <[^>]+> 437 No colon-space in \"[^\"]+\" header/o) {
192 $server = lc $server unless $CASE_SENSITIVE;
193 $inn_badart{$server}++;
194 $innd_others{$server}++;
195 $innd_no_colon_space{$server}++;
198 # 437 Article posted in the future -- "xxxxx"
199 if ($left =~ /(\S+) <[^>]+> 437 Article posted in the future -- \"[^\"]+\"/o) {
201 $server = lc $server unless $CASE_SENSITIVE;
202 $innd_posted_future{$server}++;
203 $innd_others{$server}++;
204 $inn_badart{$server}++;
207 # 437 article includes "....."
208 if ($left =~ /(\S+) <[^>]+> 437 article includes/o) {
210 $server = lc $server unless $CASE_SENSITIVE;
211 $innd_strange_strings{$server}++;
212 $innd_others{$server}++;
213 $inn_badart{$server}++;
217 if ($left =~ /(\S+) <[^>]+> Cancelling/o) {
220 # all others are just counted as "Other"
221 if ($left =~ /(\S+) /o) {
223 $server = lc $server unless $CASE_SENSITIVE;
224 $inn_badart{$server}++;
225 $innd_others{$server}++;
232 if ($prog eq "innd") {
233 ## Note for innd logs:
234 ## there's a lot of entries detected but still not used
235 ## (because of a lack of interest).
237 # think it's a dotquad
238 return 1 if $left =~ /^think it\'s a dotquad$/o;
239 if ($left =~ /^SERVER /o) {
240 # SERVER perl filtering enabled
241 return 1 if $left =~ /^SERVER perl filtering enabled$/o;
242 # SERVER perl filtering disabled
243 return 1 if $left =~ /^SERVER perl filtering disabled$/o;
244 # SERVER Python filtering enabled
245 return 1 if $left =~ /^SERVER Python filtering enabled$/o;
246 # SERVER Python filtering disabled
247 return 1 if $left =~ /^SERVER Python filtering disabled$/o;
248 # SERVER cancelled +id
249 return 1 if $left =~ /^SERVER cancelled /o;
252 return 1 if $left =~ /^defined python methods$/o;
253 return 1 if $left =~ /^reloading pyfilter$/o;
254 return 1 if $left =~ /^reloaded pyfilter OK$/o;
255 return 1 if $left =~ /^python interpreter initialized OK$/o;
256 return 1 if $left =~ /^python method \w+ not found$/o;
257 return 1 if $left =~ /^python: First load, so I can do initialization stuff\.$/o;
258 return 1 if $left =~ /^python: filter_before_reload executing\.\.\.$/o;
259 return 1 if $left =~ /^python: I\'m just reloading, so skip the formalities\.$/o;
260 return 1 if $left =~ /^python: spamfilter successfully hooked into INN$/o;
261 return 1 if $left =~ /^python: state change from \w+ to \w+ - /o;
262 return 1 if $left =~ /^python: filter_close running, bye!$/o;
264 if ($left =~ /^rejecting\[perl\] <[^>]+> \d+ (.*)/o) {
265 $innd_filter_perl{$1}++;
269 if ($left =~ /^rejecting\[python\] <[^>]+> \d+ (.*)/o) {
270 $innd_filter_python{$1}++;
274 return 1 if $left =~ /^\S+ closed lost \d+/o;
275 # new control command
276 if ($left =~ /^ctlinnd command (\w)(:.*)?/o) {
278 my $cmd = $ctlinnd{$command};
279 $cmd = $command unless $cmd;
280 return 1 if $cmd eq 'flush'; # to avoid a double count
281 $innd_control{"$cmd"}++;
284 # old control command (by letter)
285 if ($left =~ /^(\w)$/o) {
287 my $cmd = $ctlinnd{$command};
288 $cmd = $command unless $cmd;
289 return 1 if $cmd eq 'flush'; # to avoid a double count
290 $innd_control{"$cmd"}++;
293 # old control command (letter + reason)
294 if ($left =~ /^(\w):.*$/o) {
296 my $cmd = $ctlinnd{$command};
297 $cmd = $command unless $cmd;
298 return 1 if $cmd eq 'flush'; # to avoid a double count
299 $innd_control{"$cmd"}++;
303 return 1 if $left =~ /\S+ opened \S+:\d+:file$/o;
305 return 1 if $left =~ /\S+ buffered$/o;
307 return 1 if $left =~ /\S+ spawned \S+:\d+:proc:\d+$/o;
308 return 1 if $left =~ /\S+ spawned \S+:\d+:file$/o;
310 return 1 if $left =~ /\S+ running$/o;
312 if ($left =~ /(\S+):\d+:proc:\d+ sleeping$/o) {
314 $server = lc $server unless $CASE_SENSITIVE;
315 $innd_blocked{$server}++;
319 if ($left =~ /(\S+):\d+:proc:\d+ blocked sleeping/o) {
321 $server = lc $server unless $CASE_SENSITIVE;
322 $innd_blocked{$server}++;
325 if ($left =~ /(\S+):\d+ blocked sleeping/o) {
327 $server = lc $server unless $CASE_SENSITIVE;
328 $innd_blocked{$server}++;
332 return 1 if $left =~ m/^\S+ restarted$/o;
334 return 1 if $left =~ m/^\S+ starting$/o;
336 return 1 if $left =~ m/^\S+:\d+ readclose+$/o;
338 if ($left =~ m/^(\S+) rejected 502$/) {
340 $server = lc $server unless $CASE_SENSITIVE;
341 $innd_no_permission{$server}++;
345 if ($left =~ m/^(\S+) rejected 505$/) {
347 $server = lc $server unless $CASE_SENSITIVE;
348 $innd_too_many_connects_per_minute{$server}++;
352 if ($left =~ /^(\S+) connected \d+/o) {
354 $server = lc $server unless $CASE_SENSITIVE;
355 $innd_connect{$server}++;
358 # closed (with times)
359 if ($left =~ /(\S+):\d+ closed seconds (\d+) accepted (\d+) refused (\d+) rejected (\d+) duplicate (\d+) accepted size (\d+) duplicate size (\d+)(?: rejected size (\d+))?$/o) {
360 my ($server, $seconds, $accepted, $refused, $rejected, $duplicate, $accptsize, $dupsize) =
361 ($1, $2, $3, $4, $5, $6, $7, $8);
362 $server = lc $server unless $CASE_SENSITIVE;
363 $innd_seconds{$server} += $seconds;
364 $innd_accepted{$server} += $accepted;
365 $innd_refused{$server} += $refused;
366 $innd_rejected{$server} += $rejected;
367 $innd_stored_size{$server} += $accptsize;
368 $innd_duplicated_size{$server} += $dupsize;
370 } elsif ($left =~ /(\S+):\d+ closed seconds (\d+) accepted (\d+) refused (\d+) rejected (\d+)$/o) {
371 # closed (with times)
372 my ($server, $seconds, $accepted, $refused, $rejected) =
373 ($1, $2, $3, $4, $5);
374 $server = lc $server unless $CASE_SENSITIVE;
375 $innd_seconds{$server} += $seconds;
376 $innd_accepted{$server} += $accepted;
377 $innd_refused{$server} += $refused;
378 $innd_rejected{$server} += $rejected;
381 # closed (without times (?))
382 return 1 if $left =~ m/\S+ closed$/o;
383 # closed (for a cancel feed - MODE CANCEL)
384 return 1 if $left =~ m/localhost:\d+ closed seconds \d+ cancels \d+$/o;
386 return 1 if $left =~ m/^\S+:\d+ checkpoint /o;
387 # if ($left =~ /(\S+):\d+ checkpoint seconds (\d+) accepted (\d+)
388 # refused (\d+) rejected (\d+)$/) {
390 # my ($server, $seconds, $accepted, $refused, $rejected) =
391 # ($1, $2, $3, $4, $5);
392 # $innd_seconds{$server} += $seconds;
393 # $innd_accepted{$server} += $accepted;
394 # $innd_refused{$server} += $refused;
395 # $innd_rejected{$server} += $rejected;
400 if ($left =~ /(\S+) flush$/o) {
401 $innd_control{"flush"}++;
405 if ($left =~ /flush_file/) {
406 $innd_control{"flush_file"}++;
409 # too many connections from site
410 if ($left =~ /too many connections from (\S+)/o) {
411 $innd_max_conn{$1}++;
414 # overview exit 0 elapsed 23 pid 28461
415 return 1 if $left =~ m/\S+ exit \d+ .*$/o;
416 # internal rejecting huge article
417 if ($left =~ /(\S+) internal rejecting huge article/o) {
419 $server =~ s/:\d+$//o;
420 $server = lc $server unless $CASE_SENSITIVE;
421 $innd_huge{$server}++;
424 # internal closing free channel
425 if ($left =~ /(\S+) internal closing free channel/o) {
426 $innd_misc{"Free channel"}++;
430 return 1 if $left =~ /\S+ internal/o;
432 return 1 if $left =~ /\S+ wakeup$/o;
434 if ($left =~ /(\S+) throttled? /) {
435 $innd_control{"throttle"}++;
439 # ME time X nnnn X(X) [...]
440 # The exact timers change from various versions of INN, so try to deal
441 # with this in a general fashion.
442 if ($left =~ m/^\S+\s+ # ME
443 time\s(\d+)\s+ # time
444 ((?:\S+\s\d+\(\d+\)\s*)+) # timer values
446 $innd_time_times += $1;
449 while ($timers =~ /(\S+) (\d+)\((\d+)\)\s*/g) {
450 my $name = $timer_names{$1} || $1;
451 my $average = $2 / ($3 || 1);
452 $innd_time_time{$name} += $2;
453 $innd_time_num{$name} += $3;
454 $innd_time_min{$name} = $average
455 if ($3 && $innd_time_min{$name} > $average);
456 $innd_time_max{$name} = $average
457 if ($3 && $innd_time_max{$name} < $average);
461 # ME time xx idle xx(xx) [ bug ? a part of timer ?]
462 return 1 if $left =~ m/^ME time \d+ idle \d+\(\d+\)\s*$/o;
463 # ME HISstats x hitpos x hitneg x missed x dne
466 # HIShitpos: the entry existed in the cache and in history.
467 # HIShitneg: the entry existed in the cache but not in history.
468 # HISmisses: the entry was not in the cache, but was in the history file.
469 # HISdne: the entry was not in cache or history.
470 if ($left =~ m/^ME\ HISstats # ME HISstats
471 \ (\d+)\s+hitpos # hitpos
472 \ (\d+)\s+hitneg # hitneg
473 \ (\d+)\s+missed # missed
476 $innd_his{'Positive hits'} += $1;
477 $innd_his{'Negative hits'} += $2;
478 $innd_his{'Cache misses'} += $3;
479 $innd_his{'Do not exist'} += $4;
482 # SERVER history cache final: 388656 lookups, 1360 hits
483 if ($left =~ m/^SERVER history cache final: (\d+) lookups, (\d+) hits$/) {
484 $innd_cache{'Lookups'} += $1;
485 $innd_cache{'Hits'} += $2;
488 # bad_hosts (appears after a "cant gesthostbyname" from a feed)
489 return 1 if $left =~ m/\S+ bad_hosts /o;
491 return 1 if $left =~ m/\S+ cant read/o;
493 return 1 if $left =~ m/\S+ cant write/o;
495 return 1 if $left =~ m/\S+ cant flush/o;
497 return 1 if $left =~ m/\S+ spoolwake$/o;
499 return 1 if $left =~ m/\S+ spooling/o;
501 return 1 if $left =~ m/^DEBUG /o;
503 return 1 if $left =~ m/\S+ NCmode /o;
505 return 1 if $left =~ m/\S+ outgoing/o;
507 return 1 if $left =~ m/\S+ inactive/o;
509 return 1 if $left =~ m/\S+ timeout/o;
511 return 1 if $left =~ m/\S+ lcsetup/o;
513 return 1 if $left =~ m/\S+ rcsetup/o;
515 return 1 if $left =~ m/\S+ flush_all/o;
517 return 1 if $left =~ m/\S+ buffered$/o;
519 return 1 if $left =~ m/\S+ descriptors/o;
521 return 1 if $left =~ m/\S+ ccsetup/o;
523 return 1 if $left =~ m/\S+ renumbering/o;
525 return 1 if $left =~ m/\S+ renumber /o;
527 if ($left =~ m/\S+ ihave_from_me /o) {
528 $controlchan_ihave_site{'ME'}++;
532 if ($left =~ m/\S+ sendme_from_me /o) {
533 $controlchan_sendme_site{'ME'}++;
537 if ($left =~ m/\S+ newgroup (\S+) as (\S)/o) {
538 $innd_newgroup{$1} = $2;
542 if ($left =~ m/\S+ rmgroup (\S+)$/o) {
547 if ($left =~ m/\S+ change_group (\S+) to (\S)/o) {
548 $innd_changegroup{$1} = $2;
552 if ($left =~ m/(\S+) paused /o) {
553 $innd_control{"paused"}++;
557 return 1 if $left =~ m/\S+ throttled/o;
559 if ($left =~ m/(\S+) reload/o) {
560 $innd_control{"reload"}++;
564 if ($left =~ m/(\S+) shutdown/o) {
565 $innd_control{"shutdown"}++;
568 # SERVER servermode paused
569 return 1 if ($left =~ /(\S+) servermode paused$/o);
570 # SERVER servermode running
571 return 1 if ($left =~ /(\S+) servermode running$/o);
572 # SERVER flushlogs paused
573 if ($left =~ /(\S+) flushlogs /) {
574 $innd_control{"flushlogs"}++;
577 # think it's a dotquad
578 return 1 if $left =~ /think it\'s a dotquad: /o;
580 if ($left =~ /(\S+) bad_ihave /) {
582 $server =~ s/:\d+$//o;
583 $server = lc $server unless $CASE_SENSITIVE;
584 $innd_bad_ihave{$server}++;
588 if ($left =~ /(\S+) bad_messageid/o) {
590 $server =~ s/:\d+$//o;
591 $server = lc $server unless $CASE_SENSITIVE;
592 $innd_bad_msgid{$server}++;
596 if ($left =~ /(\S+) bad_sendme /o) {
598 $server =~ s/:\d+$//o;
599 $server = lc $server unless $CASE_SENSITIVE;
600 $innd_bad_sendme{$server}++;
604 if ($left =~ /(\S+) bad_command /o) {
606 $server =~ s/:\d+$//o;
607 $server = lc $server unless $CASE_SENSITIVE;
608 $innd_bad_command{$server}++;
612 if ($left =~ /(\S+) bad_newsgroup /o) {
614 $server =~ s/:\d+$//o;
615 $innd_bad_newsgroup{$server}++;
616 $server = lc $server unless $CASE_SENSITIVE;
619 if ($left =~ m/ cant /o) {
620 # cant select Bad file number
621 if ($left =~ / cant select Bad file number/o) {
622 $innd_misc{"Bad file number"}++;
626 if ($left =~ / cant gethostbyname/o) {
627 $innd_misc{"gethostbyname error"}++;
630 # cant accept RCreader
631 if ($left =~ / cant accept RCreader /o) {
632 $innd_misc{"RCreader"}++;
635 # cant sendto CCreader
636 if ($left =~ / cant sendto CCreader /o) {
637 $innd_misc{"CCreader"}++;
640 # cant (other) skipped - not particularly interesting
643 # bad_newsfeeds no feeding sites
644 return 1 if $left =~ /\S+ bad_newsfeeds no feeding sites/o;
645 # CNFS: cycbuff rollover - possibly interesting
646 return 1 if $left =~ /CNFS(?:-sm)?: cycbuff \S+ rollover to cycle/o;
647 # CNFS: CNFSflushallheads: flushing - possibly interesting
648 return 1 if $left =~ /CNFS(?:-sm)?: CNFSflushallheads: flushing /o;
649 # CNFS: metacycbuff rollover with SEQUENTIAL
650 return 1 if $left =~ /CNFS(?:-sm)?: metacycbuff \S+ cycbuff is moved to /o;
651 # Cleanfeed status reports
652 return 1 if $left =~ /^filter: status/o;
653 return 1 if $left =~ /^filter: Reloading bad files/o;
657 if ($prog eq "innfeed") {
659 if ($left =~ /(\S+):\d+ connected$/) {
661 $server = lc $server unless $CASE_SENSITIVE;
662 $innfeed_connect{$server}++;
666 return 1 if $left =~ m/\S+:\d+ closed periodic$/o;
668 return 1 if $left =~ m/\S+:\d+ periodic close$/o;
670 return 1 if $left =~ m/\S+:\d+ final seconds \d+ offered \d+ accepted \d+ refused \d+ rejected \d+/o;
672 return 1 if $left =~ m/\S+ global seconds \d+ offered \d+ accepted \d+ refused \d+ rejected \d+ missing \d+/o;
673 # final (real) (new format)
674 if ($left =~ /(\S+) final seconds (\d+) offered (\d+) accepted (\d+) refused (\d+) rejected (\d+) missing (\d+) accsize (\d+) rejsize (\d+) spooled (\d+)/o) {
675 my ($server, $seconds, $offered, $accepted, $refused, $rejected,
676 $missing, $accepted_size, $rejected_size, $spooled) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);
677 $server = lc $server unless $CASE_SENSITIVE;
678 $innfeed_seconds{$server} += $seconds;
679 $innfeed_offered{$server} += $offered;
680 $innfeed_accepted{$server} += $accepted;
681 $innfeed_refused{$server} += $refused;
682 $innfeed_rejected{$server} += $rejected;
683 $innfeed_missing{$server} += $missing;
684 $innfeed_spooled{$server} += $spooled;
685 $innfeed_accepted_size{$server} += $accepted_size;
686 $innfeed_rejected_size{$server} += $rejected_size;
688 } elsif ($left =~ /(\S+) final seconds (\d+) offered (\d+) accepted (\d+) refused (\d+) rejected (\d+) missing (\d+) spooled (\d+)/o) {
689 my ($server, $seconds, $offered, $accepted, $refused, $rejected,
690 $missing, $spooled) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);
691 $server = lc $server unless $CASE_SENSITIVE;
692 $innfeed_seconds{$server} += $seconds;
693 $innfeed_offered{$server} += $offered;
694 $innfeed_accepted{$server} += $accepted;
695 $innfeed_refused{$server} += $refused;
696 $innfeed_rejected{$server} += $rejected;
697 $innfeed_missing{$server} += $missing;
698 $innfeed_spooled{$server} += $spooled;
701 # final (only seconds & spooled)
702 if ($left =~ /(\S+) final seconds (\d+) spooled (\d+)/o) {
703 my ($server, $seconds, $spooled) = ($1, $2, $3);
704 $server = lc $server unless $CASE_SENSITIVE;
705 $innfeed_seconds{$server} += $seconds;
706 $innfeed_spooled{$server} += $spooled;
710 return 1 if $left =~ m/\S+ checkpoint seconds/o;
711 # ME file xxxx shrunk from yyyy to zzz
712 if ($left =~ /^ME file (.*)\.output shrunk from (\d+) to (\d+)$/) {
713 my ($file, $s1, $s2) = ($1, $2, $3);
714 $file =~ s|^.*/([^/]+)$|$1|; # keep only the server name
715 $innfeed_shrunk{$file} += $s1 - $s2;
719 # ME time X nnnn X(X) [...]
720 return 1 if $left =~ m/backlogstats/;
721 if ($left =~ m/^\S+\s+ # ME
722 time\s(\d+)\s+ # time
723 ((?:\S+\s\d+\(\d+\)\s*)+) # timer values
725 $innfeed_time_times += $1;
728 while ($timers =~ /(\S+) (\d+)\((\d+)\)\s*/g) {
729 my $name = $innfeed_timer_names{$1} || $1;
730 my $average = $2 / ($3 || 1);
731 $innfeed_time_time{$name} += $2;
732 $innfeed_time_num{$name} += $3;
733 $innfeed_time_min{$name} = $average
734 if ($3 && $innfeed_time_min{$name} > $average);
735 $innfeed_time_max{$name} = $average
736 if ($3 && $innfeed_time_max{$name} < $average);
740 # xxx grabbing external tape file
741 return 1 if $left =~ m/ grabbing external tape file/o;
742 # hostChkCxns - maxConnections was
743 return 1 if $left =~ m/hostChkCxns - maxConnections was /o;
745 return 1 if $left =~ m/\S+ cxnsleep .*$/o;
747 return 1 if $left =~ m/\S+ idle tearing down connection$/o;
749 return 1 if $left =~ m/\S+ remote .*$/o;
751 return 1 if $left =~ m/\S+ spooling no active connections$/o;
753 return 1 if $left =~ m/(?:SERVER|ME) articles total \d+ bytes \d+/o;
755 return 1 if $left =~ m/(?:SERVER|ME) articles active \d+ bytes \d+/o;
756 # connect : Connection refused
757 return 1 if $left =~ m/connect : Connection refused/o;
758 # connect : Network is unreachable
759 return 1 if $left =~ m/connect : Network is unreachable/o;
760 # connect : Address family not supported by protocol
761 return 1 if $left =~ m/connect : Address family not supported by protocol/o;
762 # connect : No route to host
763 return 1 if $left =~ m/connect : No route to host/o;
764 # connection vanishing
765 return 1 if $left =~ m/connection vanishing/o;
766 # can't resolve hostname
767 return 1 if $left =~ m/can\'t resolve hostname/o;
768 # new hand-prepared backlog file
769 return 1 if $left =~ m/new hand-prepared backlog file/o;
770 # flush re-connect failed
771 return 1 if $left =~ m/flush re-connect failed/o;
772 # internal QUIT while write pending
773 return 1 if $left =~ m/internal QUIT while write pending/o;
774 # ME source lost . Exiting
775 return 1 if $left =~ m/(?:SERVER|ME) source lost . Exiting/o;
776 # ME starting innfeed (+version & date)
777 return 1 if $left =~ m/(?:SERVER|ME) starting (?:innfeed|at)/o;
778 # ME finishing at (date)
779 return 1 if $left =~ m/(?:SERVER|ME) finishing at /o;
780 # mode no-CHECK entered
781 return 1 if $left =~ m/mode no-CHECK entered/o;
782 # mode no-CHECK exited
783 return 1 if $left =~ m/mode no-CHECK exited/o;
785 return 1 if $left =~ m/^(\S+) closed$/o;
786 # global (+ seconds offered accepted refused rejected missing)
787 return 1 if $left =~ m/^(\S+) global/o;
788 # idle connection still has articles
789 return 1 if $left =~ m/^(\S+) idle connection still has articles$/o;
790 # missing article for IHAVE-body
791 return 1 if $left =~ m/^(\S+) missing article for IHAVE-body$/o;
793 return 1 if $left =~ m/^cannot continue/o;
794 if ($left =~ /^(?:SERVER|ME)/o) {
795 # ME dropping articles into ...
796 return 1 if $left =~ / dropping articles into /o;
798 return 1 if $left =~ / dropped /o;
799 # ME internal bad data in checkpoint file
800 return 1 if $left =~ m/ internal bad data in checkpoint/o;
801 # ME two filenames for same article
802 return 1 if $left =~ m/ two filenames for same article/o;
803 # ME unconfigured peer
804 return 1 if $left =~ m/ unconfigured peer/o;
805 # exceeding maximum article size
806 return 1 if $left =~ m/ exceeding maximum article byte/o;
807 # no space left on device errors
808 return 1 if $left =~ m/ ioerr fclose/o;
809 return 1 if $left =~ m/ lock failed for host/o;
810 return 1 if $left =~ m/ lock file pid-write/o;
811 return 1 if $left =~ m/ locked cannot setup peer/o;
812 return 1 if $left =~ m/ received shutdown signal/o;
814 return 1 if $left =~ m/ unconfigured peer/o;
816 return 1 if $left =~ m/ lock/o;
817 # ME exception: getsockopt (0): Socket operation on non-socket
818 return 1 if $left =~ m/ exception: getsockopt /o;
819 # ME config aborting fopen (...) Permission denied
820 return 1 if $left =~ m/ config aborting fopen /o;
821 # ME cant chmod innfeed.pid....
822 return 1 if $left =~ m/ cant chmod \S+\/innfeed.pid/o;
823 return 1 if $left =~ m/ tape open failed /o;
824 return 1 if $left =~ m/ oserr open checkpoint file:/o;
825 # ME finishing (quickly)
826 return 1 if $left =~ m/\(quickly\) /o;
827 # ME config: value of streaming is not a boolean
828 return 1 if $left =~ m/config: value of \S+ is not/o;
830 # hostChkCxn - now: x.xx, prev: x.xx, abs: xx, curr: x
831 return 1 if $left =~ m/ hostChkCxn - now/o;
832 # loading path_to_config_file/innfeed.conf
833 return 1 if $left =~ m/loading /o;
834 # Finnaly, to avoid problems with strange error lines, ignore them.
835 #return 1 if ($left =~ /ME /);
839 if ($prog eq "innxmit") {
840 # 437 Duplicate article
841 if ($left =~ /(\S+) rejected [^\s]+ \(.*?\) 437 Duplicate article$/o) {
843 $server = lc $server unless $CASE_SENSITIVE;
844 $innxmit_badart{$server}++;
845 $innxmit_duplicate{$server}++;
849 if ($left =~ /(\S+) rejected [^\s]+ \(.*\) 437 Unapproved for \"(.*?)\"$/o) {
850 my ($server, $group) = ($1, $2);
851 $server = lc $server unless $CASE_SENSITIVE;
852 $innxmit_badart{$server}++;
853 $innxmit_unapproved{$server}++;
854 $innxmit_unapproved_g{$group}++;
858 if ($left =~ /(\S+) rejected [^\s]+ \(.*\) 437 Too old -- \".*?\"$/o) {
860 $server = lc $server unless $CASE_SENSITIVE;
861 $innxmit_badart{$server}++;
862 $innxmit_tooold{$server}++;
865 # 437 Unwanted site ... in path
867 /(\S+) rejected [^\s]+ \(.*?\) 437 Unwanted site (\S+) in path$/o) {
868 my ($server, $site) = ($1, $2);
869 $server = lc $server unless $CASE_SENSITIVE;
870 $innxmit_badart{$server}++;
871 $innxmit_uw_site{$server}++;
872 # $innxmit_site_path{$site}++;
875 # 437 Unwanted newsgroup "..."
877 /(\S+) rejected [^\s]+ \(.*?\) 437 Unwanted newsgroup \"(\S+)\"$/o) {
878 my ($server, $group) = ($1, $2);
879 $server = lc $server unless $CASE_SENSITIVE;
880 $innxmit_badart{$server}++;
881 $innxmit_uw_ng_s{$server}++;
882 $innxmit_uw_ng{$group}++;
885 # 437 Unwanted distribution "..."
887 /(\S+) rejected [^\s]+ \(.*?\) 437 Unwanted distribution \"(\S+)\"$/o) {
888 my ($server, $dist) = ($1, $2);
889 $server = lc $server unless $CASE_SENSITIVE;
890 $innxmit_badart{$server}++;
891 $innxmit_uw_dist_s{$server}++;
892 $innxmit_uw_dist{$dist}++;
895 # xx rejected foo.bar/12345 (foo/bar/12345) 437 Unwanted distribution "..."
896 if ($left =~ /^(\S+) rejected .* 437 Unwanted distribution \"(\S+)\"$/o) {
897 my ($server, $dist) = ($1, $2);
898 $server = lc $server unless $CASE_SENSITIVE;
899 $innxmit_badart{$server}++;
900 $innxmit_uw_dist_s{$server}++;
901 $innxmit_uw_dist{$dist}++;
904 # 437 Linecount x != y +- z
905 if ($left =~ /(\S+) rejected [^\s]+ \(.*?\) 437 Linecount/o) {
907 $server = lc $server unless $CASE_SENSITIVE;
908 $innxmit_badart{$server}++;
909 $innxmit_linecount{$server}++;
912 # 437 Newsgroup name illegal -- "xxx"
913 if ($left =~ /(\S+) rejected .* 437 Newsgroup name illegal -- "[^\"]*"$/) {
915 $server = lc $server unless $CASE_SENSITIVE;
916 $innxmit_others{$server}++;
917 $innxmit_badart{$server}++;
921 return 1 if ($left =~ /\d+ Streaming retries$/o);
923 if ($left =~ /(\S+) ihave failed/o) {
925 $server = lc $server unless $CASE_SENSITIVE;
926 $innxmit_ihfail{$server} = 1;
927 if ($left = /436 \S+ NNTP \S+ out of space/o) {
928 $innxmit_nospace{$server}++;
931 if ($left = /400 \S+ space/o) {
932 $innxmit_nospace{$server}++;
935 if ($left = /400 Bad file/o) {
936 $innxmit_crefused{$server}++;
939 if ($left = /480 Transfer permission denied/o) {
940 $innxmit_crefused{$server}++;
946 /(\S+) stats offered (\d+) accepted (\d+) refused (\d+) rejected (\d+) missing (\d+) accsize (\d+) rejsize (\d+)$/o) {
947 my ($server, $offered, $accepted, $refused, $rejected, $missing, $accbytes, $rejbytes) =
948 ($1, $2, $3, $4, $5, $6, $7, $8);
949 $server = lc $server unless $CASE_SENSITIVE;
950 $innxmit_offered{$server} += $offered;
951 $innxmit_offered{$server} -= $innxmit_ihfail{$server}
952 if ($innxmit_ihfail{$server});
953 $innxmit_accepted{$server} += $accepted;
954 $innxmit_refused{$server} += $refused;
955 $innxmit_rejected{$server} += $rejected;
956 $innxmit_missing{$server} += $missing;
957 $innxmit_accepted_size{$server} += $accbytes;
958 $innxmit_rejected_size{$server} += $rejbytes;
959 $innxmit_site{$server}++;
960 $innxmit_ihfail{$server} = 0;
965 /(\S+) stats offered (\d+) accepted (\d+) refused (\d+) rejected (\d+)$/o) {
966 my ($server, $offered, $accepted, $refused, $rejected) =
967 ($1, $2, $3, $4, $5);
968 $server = lc $server unless $CASE_SENSITIVE;
969 $innxmit_offered{$server} += $offered;
970 $innxmit_offered{$server} -= $innxmit_ihfail{$server}
971 if ($innxmit_ihfail{$server});
972 $innxmit_accepted{$server} += $accepted;
973 $innxmit_refused{$server} += $refused;
974 $innxmit_rejected{$server} += $rejected;
975 $innxmit_site{$server}++;
976 $innxmit_ihfail{$server} = 0;
980 if ($left =~ /(\S+) times user (\S+) system (\S+) elapsed (\S+)$/o) {
981 my ($server, $user, $system, $elapsed) = ($1, $2, $3, $4);
982 $server = lc $server unless $CASE_SENSITIVE;
983 $innxmit_times{$server} += $elapsed;
987 if ($left =~ /(\S+) connect \S+ 400 No space/o) {
989 $server = lc $server unless $CASE_SENSITIVE;
990 $innxmit_nospace{$server}++;
991 $innxmit_site{$server}++;
994 # connect & NNTP no space
995 if ($left =~ /(\S+) connect \S+ 400 \S+ out of space/o) {
997 $server = lc $server unless $CASE_SENSITIVE;
998 $innxmit_nospace{$server}++;
999 $innxmit_site{$server}++;
1003 if ($left =~ /(\S+) connect \S+ 400 loadav/o) {
1005 if ($left =~ /expir/i) {
1006 $server = lc $server unless $CASE_SENSITIVE;
1007 $innxmit_expire{$server}++;
1008 $innxmit_site{$server}++;
1012 # connect 400 (other)
1013 if ($left =~ /(\S+) connect \S+ 400/o) {
1015 $server = lc $server unless $CASE_SENSITIVE;
1016 $innxmit_crefused{$server}++;
1017 $innxmit_site{$server}++;
1021 if ($left =~ /(\S+) connect failed/o) {
1023 $server = lc $server unless $CASE_SENSITIVE;
1024 $innxmit_cfail_host{$server}++;
1025 $innxmit_site{$server}++;
1028 # authenticate failed
1029 if ($left =~ /(\S+) authenticate failed/o) {
1031 $server = lc $server unless $CASE_SENSITIVE;
1032 $innxmit_afail_host{$server}++;
1033 $innxmit_site{$server}++;
1036 # xxx ihave failed 400 loadav [innwatch:hiload] yyy gt zzz
1037 if ($left =~ /^(\S+) ihave failed 400 loadav/o) {
1039 $server = lc $server unless $CASE_SENSITIVE;
1040 $innxmit_hiload{$server}++;
1044 return 1 if ($left =~ /\S+ ihave failed/o);
1045 # requeued (....) 436 No space
1046 return 1 if ($left =~ /\S+ requeued \S+ 436 No space/o);
1047 # requeued (....) 400 No space
1048 return 1 if ($left =~ /\S+ requeued \S+ 400 No space/o);
1049 # requeued (....) 436 Can't write history
1050 return 1 if ($left =~ /\S+ requeued \S+ 436 Can\'t write history/o);
1051 # unexpected response code
1052 return 1 if ($left =~ /unexpected response code /o);
1057 if ($prog eq "nntplink") {
1058 $left =~ s/^(\S+):/$1/;
1060 if ($left =~ /(\S+) EOF /o) {
1062 $server = lc $server unless $CASE_SENSITIVE;
1063 $nntplink_site{$server}++;
1064 $nntplink_eof{$server}++;
1068 if ($left =~ /(\S+) Broken pipe$/o) {
1070 $server = lc $server unless $CASE_SENSITIVE;
1071 $nntplink_site{$server}++;
1072 $nntplink_bpipe{$server}++;
1075 # already running - won't die
1076 return 1 if $left =~ /\S+ nntplink.* already running /o;
1077 # connection timed out
1078 if ($left =~ /(\S+) connection timed out/o) {
1080 $server = lc $server unless $CASE_SENSITIVE;
1081 $nntplink_site{$server}++;
1082 $nntplink_bpipe{$server}++;
1085 # greeted us with 400 No space
1086 if ($left =~ /(\S+) greeted us with 400 No space/o) {
1088 $server = lc $server unless $CASE_SENSITIVE;
1089 $nntplink_site{$server}++;
1090 $nntplink_nospace{$server}++;
1093 # greeted us with 400 loadav
1094 if ($left =~ /(\S+) greeted us with 400 loadav/o) {
1096 $server = lc $server unless $CASE_SENSITIVE;
1097 $nntplink_site{$server}++;
1098 $nntplink_hiload{$server}++;
1101 # greeted us with 400 (other)
1102 if ($left =~ /(\S+) greeted us with 400/o) {
1104 $server = lc $server unless $CASE_SENSITIVE;
1105 $nntplink_site{$server}++;
1106 if ($left =~ /expir/i) {
1107 $nntplink_expire{$server}++;
1109 $nntplink_fail{$server}++;
1113 # greeted us with 502
1114 if ($left =~ /(\S+) greeted us with 502/o) {
1116 $server = lc $server unless $CASE_SENSITIVE;
1117 $nntplink_site{$server}++;
1118 $nntplink_auth{$server}++;
1122 if ($left =~ /(\S+) sent authinfo/o) {
1124 $server = lc $server unless $CASE_SENSITIVE;
1125 $nntplink_site{$server}++;
1126 $nntplink_auth{$server}++;
1130 if ($left =~ /(\S+) socket\(\): /o) {
1132 $server = lc $server unless $CASE_SENSITIVE;
1133 $nntplink_site{$server}++;
1134 $nntplink_sockerr{$server}++;
1138 if ($left =~ /(\S+) select\(\) /o) {
1140 $server = lc $server unless $CASE_SENSITIVE;
1141 $nntplink_site{$server}++;
1142 $nntplink_selecterr{$server}++;
1146 if ($left =~ /(\S+) sent IHAVE/o) {
1148 $server = lc $server unless $CASE_SENSITIVE;
1149 $nntplink_ihfail{$server}++;
1150 if (($left =~ / 436 /) && ($left =~ / out of space /)) {
1151 $nntplink_fake_connects{$server}++;
1152 $nntplink_nospace{$server}++;
1156 # article .... failed(saved): 436 No space
1157 if ($left =~ /(\S+) .* failed\(saved\): 436 No space$/o) {
1159 $server = lc $server unless $CASE_SENSITIVE;
1160 $nntplink_nospace{$server}++;
1163 # article .. 400 No space left on device writing article file -- throttling
1164 if ($left =~ /(\S+) .* 400 No space left on device writing article file -- throttling$/o) {
1166 $server = lc $server unless $CASE_SENSITIVE;
1167 $nntplink_nospace{$server}++;
1171 if ($left =~ /(\S+) stats (\d+) offered (\d+) accepted (\d+) rejected (\d+) failed (\d+) connects$/o) {
1172 my ($server, $offered, $accepted, $rejected, $failed, $connects) =
1173 ($1, $2, $3, $4, $5, $6);
1174 $server = lc $server unless $CASE_SENSITIVE;
1175 $nntplink_offered{$server} += $offered - $nntplink_ihfail{$server}++;
1176 $nntplink_accepted{$server} += $accepted;
1177 $nntplink_rejected{$server} += $rejected;
1178 $nntplink_failed{$server} += $failed;
1179 $nntplink_connects{$server} += $connects;
1180 $nntplink_ihfail{$server} = 0;
1181 if ($nntplink_fake_connects{$server}) {
1182 $nntplink_site{$server} += $nntplink_fake_connects{$server};
1183 $nntplink_fake_connects{$server} = 0;
1185 $nntplink_site{$server}++;
1190 if ($left =~ /(\S+) xmit user (\S+) system (\S+) elapsed (\S+)$/o) {
1191 my ($server, $user, $system, $elapsed) = ($1, $2, $3, $4);
1192 $server = lc $server unless $CASE_SENSITIVE;
1193 $nntplink_times{$server} += $elapsed;
1197 return 1 if $left =~ /\S+ xfer/o;
1198 # Links down .. x hours
1199 if ($left =~ /(\S+) Links* down \S+ \d+/o) {
1200 # Collected but not used
1202 # $server = lc $server unless $CASE_SENSITIVE;
1203 # $nntplink_down{$server} += $hours;
1207 if ($left =~ /^(\S+) \S+ \S+ \S+ 503 Timeout/o) {
1208 # Collected but not used
1210 # $server = lc $server unless $CASE_SENSITIVE;
1211 # $nntplink_timeout{$server}++;
1214 # read() error while reading reply
1215 if ($left =~ /^(\S+): read\(\) error while reading reply/o) {
1217 $server = lc $server unless $CASE_SENSITIVE;
1218 $nntplink_failed{$server}++;
1221 # Password file xxxx not found
1222 return 1 if $left =~ /^\S+ Password file \S+ not found/;
1224 return 1 if $left =~ /^\S+ \S+ \S+ No such/;
1226 return 1 if $left =~ /^\S+ \S+ already running/;
1227 # error reading version from datafile
1228 return 1 if $left =~ /error reading version from datafile/;
1232 if ($prog =~ /^nnrpd(?:-ssl)?$/)
1234 # Fix a small bug of nnrpd (inn 1.4*)
1235 $left =~ s/^ /\? /o;
1236 # Another bug (in INN 1.5b1)
1237 return 1 if $left =~ /^\020\002m$/o; # ^P^Bm
1238 # bad_history at num for <ref>
1239 return 1 if $left =~ /bad_history at \d+ for /o;
1241 return 1 if $left =~ /\S+ timeout short$/o;
1242 # < or > + (blablabla)
1243 return 1 if $left =~ /^\S+ [\<\>] /o;
1244 # cant opendir ... I/O error
1245 return 1 if $left =~ /\S+ cant opendir \S+ I\/O error$/o;
1246 # perl filtering enabled
1247 return 1 if $left =~ /perl filtering enabled$/o;
1248 # Python filtering enabled
1249 return 1 if $left =~ /Python filtering enabled$/o;
1250 return 1 if $left =~ /^python interpreter initialized OK$/o;
1251 return 1 if $left =~ /^python method \S+ not found$/o;
1252 return 1 if $left =~ /^python authenticate method succeeded, return code \d+, error string /o;
1253 return 1 if $left =~ /^python access method succeeded$/o;
1254 return 1 if $left =~ /^python dynamic method \(\w+ access\) succeeded, refusion string: /o;
1255 return 1 if $left =~ /^python: .+ module successfully hooked into nnrpd$/o;
1256 return 1 if $left =~ /^python: nnrpd .+ class instance created$/o;
1257 return 1 if $left =~ /^python: n_a authenticate\(\) invoked: hostname \S+, ipaddress \S+, interface \S+, user /o;
1258 return 1 if $left =~ /^python: n_a access\(\) invoked: hostname \S+, ipaddress \S+, interface \S+, user /o;
1259 return 1 if $left =~ /^python: n_a dynamic\(\) invoked against type \S+, hostname \S+, ipaddress \S+, interface \S+, user /o;
1260 return 1 if $left =~ /^python: authentication by username succeeded$/o;
1261 return 1 if $left =~ /^python: authentication by username failed$/o;
1262 return 1 if $left =~ /^python: authentication access by IP address succeeded$/o;
1263 return 1 if $left =~ /^python: authentication access by IP address failed$/o;
1264 return 1 if $left =~ /^python: dynamic access module successfully hooked into nnrpd$/o;
1265 return 1 if $left =~ /^python: dynamic authorization access for read access granted$/o;
1266 return 1 if $left =~ /^python: dynamic authorization access type is not known: /o;
1268 if ($left =~ /(\S+) (\([0-9a-fA-F:.]*\) )?connect$/o) {
1270 $cust = lc $cust unless $CASE_SENSITIVE;
1271 my $dom = &host2dom($cust);
1272 $nnrpd_dom_connect{$dom}++;
1273 $nnrpd_connect{$cust}++;
1277 if ($left =~ /(\S+) group (\S+) (\d+)$/o) {
1278 my ($cust, $group, $num) = ($1, $2, $3);
1280 $nnrpd_group{$group} += $num;
1281 my ($hierarchy) = $group =~ /^([^\.]+).*$/o;
1282 $nnrpd_hierarchy{$hierarchy} += $num;
1287 if ($left =~ /(\S+) post failed (.*)$/o) {
1288 my ($cust, $error) = ($1, $2);
1289 $nnrpd_post_error{$error}++;
1293 return 1 if $left =~ /\S+ post ok/o;
1295 if ($left =~ /(\S+) posts received (\d+) rejected (\d+)$/o) {
1296 my ($cust, $received, $rejected) = ($1, $2, $3);
1297 $cust = lc $cust unless $CASE_SENSITIVE;
1298 my $dom = &host2dom($cust);
1299 $nnrpd_dom_post_ok{$dom} += $received;
1300 $nnrpd_dom_post_rej{$dom} += $rejected;
1301 $nnrpd_post_ok{$cust} += $received;
1302 $nnrpd_post_rej{$cust} += $rejected;
1305 # noperm post without permission
1306 if ($left =~ /(\S+) noperm post without permission/o) {
1308 $cust = lc $cust unless $CASE_SENSITIVE;
1309 my $dom = &host2dom($cust);
1310 $nnrpd_dom_post_rej{$dom} ++;
1311 $nnrpd_post_rej{$cust} ++;
1315 if ($left =~ /(\S+) no_(permission|access)$/o) {
1317 $cust = lc $cust unless $CASE_SENSITIVE;
1318 my $dom = &host2dom($cust);
1319 $nnrpd_no_permission{$cust}++;
1320 $nnrpd_dom_no_permission{$dom}++;
1324 if ($left =~ /(\S+) bad_auth$/o) {
1326 $cust = lc $cust unless $CASE_SENSITIVE;
1327 my $dom = &host2dom($cust);
1328 $nnrpd_dom_no_permission{$dom}++;
1329 $nnrpd_no_permission{$cust}++;
1332 # Authentication failure
1333 # User not known to the underlying authentication module
1334 return 1 if $left =~ / ckpasswd: pam_authenticate failed: /o;
1335 return 1 if $left =~ / ckpasswd: user .+ unknown$/o;
1337 if ($left =~ /\S+ user (\S+)$/o) {
1339 $nnrpd_auth{$user}++;
1342 # unrecognized + command
1343 if ($left =~ /(\S+) unrecognized (.*)$/o) {
1344 my ($cust, $error) = ($1, $2);
1345 $cust = lc $cust unless $CASE_SENSITIVE;
1346 my $dom = &host2dom($cust);
1347 $error = "_null command_" if ($error !~ /\S/);
1348 $error =~ s/^(xmotd) .*$/$1/i if ($error =~ /^xmotd .*$/i);
1349 $nnrpd_dom_unrecognized{$dom}++;
1350 $nnrpd_unrecognized{$cust}++;
1351 $nnrpd_unrecogn_cmd{$error}++;
1355 if ($left =~ /(\S+) exit articles (\d+) groups (\d+)$/o) {
1356 my ($cust, $articles, $groups) = ($1, $2, $3);
1357 $cust = lc $cust unless $CASE_SENSITIVE;
1358 my $dom = &host2dom($cust) || '?';
1359 $nnrpd_connect{$cust}++, $nnrpd_dom_connect{$dom}++ if $cust eq '?';
1360 $nnrpd_groups{$cust} += $groups;
1361 $nnrpd_dom_groups{$dom} += $groups;
1362 $nnrpd_articles{$cust} += $articles;
1363 $nnrpd_dom_articles{$dom} += $articles;
1367 if ($left =~ /(\S+) times user (\S+) system (\S+) idle (\S+) elapsed (\S+)$/o) {
1368 my ($cust, $user, $system, $idle, $elapsed) = ($1, $2, $3, $4, $5);
1369 $cust = lc $cust unless $CASE_SENSITIVE;
1370 my $dom = &host2dom($cust);
1371 $nnrpd_times{$cust} += $elapsed;
1372 $nnrpd_resource_user{$cust} += $user;
1373 $nnrpd_resource_system{$cust} += $system;
1374 $nnrpd_resource_idle{$cust} += $idle;
1375 $nnrpd_resource_elapsed{$cust} += $elapsed;
1376 $nnrpd_dom_times{$dom} += $elapsed;
1380 if ($left =~ /(\S+) artstats get (\d+) time (\d+) size (\d+)$/o) {
1381 my ($cust, $articles, $time, $bytes) = ($1, $2, $3, $4);
1382 $cust = lc $cust unless $CASE_SENSITIVE;
1383 my $dom = &host2dom($cust);
1384 $nnrpd_bytes{$cust} += $bytes;
1385 $nnrpd_dom_bytes{$dom} += $bytes;
1389 if ($left =~ /(\S+) timeout$/o) {
1391 $cust = lc $cust unless $CASE_SENSITIVE;
1392 my $dom = &host2dom($cust);
1393 $nnrpd_dom_timeout{$dom}++;
1394 $nnrpd_timeout{$cust}++;
1398 if ($left =~ /(\S+) timeout in post$/o) {
1400 $cust = lc $cust unless $CASE_SENSITIVE;
1401 my $dom = &host2dom($cust);
1402 $nnrpd_dom_timeout{$dom}++;
1403 $nnrpd_timeout{$cust}++;
1406 # can't read: Connection timed out
1407 if ($left =~ /(\S+) can\'t read: Connection timed out$/o) {
1409 $cust = lc $cust unless $CASE_SENSITIVE;
1410 my $dom = &host2dom($cust);
1411 $nnrpd_dom_timeout{$dom}++;
1412 $nnrpd_timeout{$cust}++;
1415 # can't read: Operation timed out
1416 if ($left =~ /(\S+) can\'t read: Operation timed out$/o) {
1418 $cust = lc $cust unless $CASE_SENSITIVE;
1419 my $dom = &host2dom($cust);
1420 $nnrpd_dom_timeout{$dom}++;
1421 $nnrpd_timeout{$cust}++;
1424 # can't read: Connection reset by peer
1425 if ($left =~ /(\S+) can\'t read: Connection reset by peer$/o) {
1427 $cust = lc $cust unless $CASE_SENSITIVE;
1428 my $dom = &host2dom($cust);
1429 $nnrpd_dom_reset_peer{$dom}++;
1430 $nnrpd_reset_peer{$cust}++;
1433 # can't read: Network is unreachable
1434 return 1 if $left =~ /(\S+) can\'t read: Network is unreachable$/o;
1435 # gethostbyaddr: xxx.yyy.zzz != a.b.c.d
1436 if ($left =~ /^gethostbyaddr: (.*)$/o) {
1438 $nnrpd_gethostbyaddr{$msg}++;
1441 # cant gethostbyaddr
1442 if ($left =~ /\? cant gethostbyaddr (\S+) .*$/o) {
1444 $nnrpd_gethostbyaddr{$ip}++;
1448 if ($left =~ /\? cant getpeername/o) {
1449 # $nnrpd_getpeername++;
1450 $nnrpd_gethostbyaddr{"? (can't getpeername)"}++;
1454 return 1 if $left =~ /^\S+ can\'t getsockname$/o;
1455 # reverse lookup failed
1456 return 1 if $left =~ /^\? reverse lookup for \S+ failed: .* -- using IP address for access$/o;
1458 # ME time X nnnn X(X) [...]
1459 # The exact timers change from various versions of INN, so try to deal
1460 # with this in a general fashion.
1461 if ($left =~ m/^\S+\s+ # ME
1462 time\s(\d+)\s+ # time
1463 ((?:\S+\s\d+\(\d+\)\s*)+) # timer values
1465 $nnrpd_time_times += $1;
1468 while ($timers =~ /(\S+) (\d+)\((\d+)\)\s*/g) {
1469 my $name = $nnrpd_timer_names{$1} || $1;
1470 my $average = $2 / ($3 || 1);
1471 $nnrpd_time_time{$name} += $2;
1472 $nnrpd_time_num{$name} += $3;
1474 my $min = $nnrpd_time_min{$name};
1475 $nnrpd_time_min{$name} = $average
1476 if (defined($min) && $min > $average);
1477 my $max = $nnrpd_time_max{$name};
1478 $nnrpd_time_max{$name} = $average
1479 if (defined($max) && $max < $average);
1484 # ME dropping articles into ...
1485 return 1 if $left =~ /ME dropping articles into /o;
1486 # newnews (interesting but ignored till now)
1487 return 1 if $left =~ /^\S+ newnews /o;
1488 # cant fopen (ignored too)
1489 return 1 if $left =~ /^\S+ cant fopen /o;
1490 # can't read: No route to host
1491 return 1 if $left =~ /can\'t read: No route to host/o;
1492 # can't read: Broken pipe
1493 return 1 if $left =~ /can\'t read: Broken pipe/o;
1495 return 1 if $left =~ /^\S+ eof in post$/o;
1497 return 1 if $left =~ /^ioctl: /o;
1499 return 1 if $left =~ /^\S+ overstats count \d+ hit \d+ miss \d+ time \d+ size \d+ dbz \d+ seek \d+ get \d+ artcheck \d+$/o;
1501 return 1 if $left =~ /^starttls: \S+ with cipher \S+ \(\d+\/\d+ bits\) no authentication$/o;
1505 if ($prog eq "inndstart") {
1506 # cant bind Address already in use
1507 # cant bind Permission denied
1508 return 1 if $left =~ /cant bind /o;
1509 # cant setgroups Operation not permitted
1510 return 1 if $left =~ /cant setgroups /o;
1514 if ($prog eq "overchan") {
1516 if ($left =~ /timings (\d+) arts (\d+) of (\d+) ms$/o) {
1517 my ($articles, $work_time, $run_time) = ($1, $2, $3);
1518 # ??? What to do with numbers
1524 if ($prog eq "batcher") {
1526 if ($left =~ /(\S+) times user (\S+) system (\S+) elapsed (\S+)$/o) {
1527 my ($server, $user, $system, $elapsed) = ($1, $2, $3, $4);
1528 $server = lc $server unless $CASE_SENSITIVE;
1529 # $batcher_user{$server} += $user;
1530 # $batcher_system{$server} += $system;
1531 $batcher_elapsed{$server} += $elapsed;
1535 if ($left =~ /(\S+) stats batches (\d+) articles (\d+) bytes (\d+)$/o) {
1536 my ($server, $batches, $articles, $bytes) = ($1, $2, $3, $4);
1537 $server = lc $server unless $CASE_SENSITIVE;
1538 $batcher_offered{$server} += $batches;
1539 $batcher_articles{$server} += $articles;
1540 $batcher_bytes{$server} += $bytes;
1546 if ($prog eq "rnews") {
1547 # rejected connection
1548 if ($left =~ /rejected connection (.*)$/o) {
1549 $rnews_rejected{$1}++;
1553 if ($left =~ /(cant open_remote .*)$/o) {
1554 $rnews_rejected{$1}++;
1557 # rejected 437 Unwanted newsgroup
1558 if ($left =~ /rejected 437 Unwanted newsgroup \"(.*)\"$/o) {
1559 $rnews_bogus_ng{$1}++;
1562 # rejected 437 Unapproved for "xx"
1563 if ($left =~ /rejected 437 Unapproved for \"(.*)\"$/o) {
1564 $rnews_unapproved{$1}++;
1567 # rejected 437 Unwanted distribution
1568 if ($left =~ /rejected 437 Unwanted distribution (.*)$/o) {
1569 $rnews_bogus_dist{$1}++;
1572 # rejected 437 Bad "Date"
1573 if ($left =~ /rejected 437 Bad \"Date\" (.*)$/o) {
1574 $rnews_bogus_date{$1}++;
1577 # rejected 437 Article posted in the future
1578 if ($left =~ /rejected 437 Article posted in the future -- \"(.*)\"$/o) {
1579 $rnews_bogus_date{"(future) $1"}++;
1582 # rejected 437 Too old -- "..."
1583 if ($left =~ /rejected 437 Too old -- (.*)$/o) {
1587 # rejected 437 Linecount...
1588 if ($left =~ /rejected 437 (Linecount) \d+ \!= \d+/o) {
1592 # rejected 437 Duplicate
1593 if ($left =~ /rejected 437 Duplicate$/o) {
1597 # rejected 437 Duplicate article
1598 if ($left =~ /rejected 437 (Duplicate article)/o) {
1602 # rejected 437 No colon-space ...
1603 if ($left =~ /rejected 437 No colon-space in \"(.*)\" header$/o) {
1604 $rnews_no_colon_space++;
1607 # duplicate <msg-id> path..
1608 if ($left =~ /^duplicate /o) {
1612 # offered <msg-id> feed
1613 if ($left =~ /^offered \S+ (\S+)/o) {
1615 $host = lc $host unless $CASE_SENSITIVE;
1616 # Small hack used to join article spooled when innd is throttle.
1617 # In this situation, the hostname is a 8 hex digits string
1618 # To avoid confusions with real feeds, the first character is forced
1619 # to be a '3' or a '4' (will work between 9/7/1995 and 13/7/2012).
1620 $host = "Local postings" if $host =~ /^[34][0-9a-f]{7}$/;
1621 $rnews_host{$host}++;
1624 # rejected 437 ECP rejected
1625 return 1 if $left =~ m/rejected 437 ECP rejected/o;
1626 # rejected 437 "Subject" header too long
1627 return 1 if $left =~ m/header too long/o;
1628 # rejected 437 Too long line in header 1163 bytes
1629 return 1 if $left =~ m/rejected 437 Too long line in header/o;
1630 # rejected 437 Too many newsgroups (meow)
1631 return 1 if $left =~ m/rejected 437 Too many newsgroups/o;
1632 # rejected 437 Space before colon in "<a" header
1633 return 1 if $left =~ m/rejected 437 Space before colon in/o;
1634 # rejected 437 EMP (phl)
1635 return 1 if $left =~ m/rejected 437 EMP/o;
1636 # rejected 437 Scoring filter (8)
1637 return 1 if $left =~ m/rejected 437 Scoring filter/o;
1638 # bad_article missing Message-ID
1639 return 1 if $left =~ m/bad_article missing Message-ID/o;
1640 # cant unspool saving to xxx
1641 return 1 if $left =~ m/cant unspool saving to/o;
1646 if ($prog eq "ncmspool") {
1647 # <article> good signature from foo@bar.com
1648 if ($left =~ /good signature from (.*)/o) {
1649 $nocem_goodsigs{$1}++;
1654 # <article> bad signature from foo@bar.com
1655 if ($left =~ /bad signature from (.*)/o) {
1656 $nocem_badsigs{$1}++;
1657 $nocem_goodsigs{$1} = 0 unless ($nocem_goodsigs{$1});
1662 # <article> contained 123 new 456 total ids
1663 if ($left =~ /contained (\d+) new (\d+) total ids/o) {
1664 $nocem_newids += $1;
1665 $nocem_newids{$nocem_lastid} += $1;
1666 $nocem_totalids += $2;
1667 $nocem_totalids{$nocem_lastid} += $2;
1675 if ($prog eq "nocem") {
1676 if ($left =~ /processed notice .* by (.*) \((\d+) ids,/o) {
1677 $nocem_goodsigs{$1}++;
1680 $nocem_newids += $2;
1681 $nocem_newids{$nocem_lastid} += $2;
1682 $nocem_totalids += $2;
1683 $nocem_totalids{$nocem_lastid} += $2;
1686 if ($left =~ /Article <[^>]*>: (.*) \(ID [[:xdigit:]]*\) not in keyring/o) {
1687 $nocem_badsigs{$1}++;
1688 $nocem_goodsigs{$1} = 0 unless ($nocem_goodsigs{$1});
1693 if ($left =~ /Article <[^>]*>: bad signature from (.*)/o) {
1694 $nocem_badsigs{$1}++;
1695 $nocem_goodsigs{$1} = 0 unless ($nocem_goodsigs{$1});
1700 if ($left =~ /Article <[^>]*>: malformed signature/o) {
1701 $nocem_badsigs{'N/A'}++;
1702 $nocem_goodsigs{'N/A'} = 0 unless ($nocem_goodsigs{'N/A'});
1704 $nocem_lastid = 'N/A';
1713 if ($prog eq "controlchan") {
1714 # loaded /x/y/z/foo.pl
1715 return 1 if $left =~ m/^loaded /;
1717 return 1 if $left =~ m/^starting/;
1718 # skipping rmgroup x@y (pgpverify failed) in <foo@bar>
1719 if ($left =~ m/^skipping \S+ (\S+) \(pgpverify failed\) in /) {
1720 $controlchan_skippgp{$1}++;
1721 $controlchan_who{$1}++;
1724 if ($left =~ m/^control_(sendme|ihave), [^,]+, (\S+), doit,/o) {
1725 if ($1 eq "sendme") {
1726 $controlchan_sendme_site{$2}++;
1728 $controlchan_ihave_site{$2}++;
1732 # control_XXgroup, foo.bar [moderated] who who /x/y/12, peer, action, 1
1734 # Various other random junk can end up in the moderated field, like y,
1735 # unmoderated, m, etc. depending on what the control message says. It
1736 # can even have multiple words, which we still don't handle.
1737 if ($left =~ m/^control_(\S+), # type of msg
1738 \s(?:\S+)? # newsgroup name
1744 \s([^=,]+(?:=\S+)?), # action
1747 if ($1 eq 'newgroup') {
1748 $controlchan_new{$3}++;
1749 } elsif ($1 eq 'rmgroup') {
1750 $controlchan_rm{$3}++;
1752 $controlchan_other{$3}++;
1754 $controlchan_who{$3}++;
1755 $controlchan_ok{$3} += $5;
1759 $controlchan_doit{$email}++ if $action eq 'doit';
1762 # checkgroups processed (no change or not)
1763 return 1 if $left =~ /^checkgroups by \S+ processed/o;
1768 if ($prog eq "crosspost") {
1769 # seconds 1001 links 3182 0 symlinks 0 0 mkdirs 0 0
1770 # missing 13 toolong 0 other 0
1771 if ($left =~ /^seconds\ (\d+)
1772 \ links\ (\d+)\ (\d+)
1773 \ symlinks\ (\d+)\ (\d+)
1774 \ mkdirs\ (\d+)\ (\d+)
1779 $crosspost_time += $1;
1780 $crosspost{'Links made'} += $2;
1781 $crosspost{'Links failed'} += $3;
1782 $crosspost{'Symlinks made'} += $4;
1783 $crosspost{'Symlinks failed'} += $5;
1784 $crosspost{'Mkdirs made'} += $6;
1785 $crosspost{'Mkdirs failed'} += $7;
1786 $crosspost{'Files missing'} += $8;
1787 $crosspost{'Paths too long'} += $9;
1788 $crosspost{'Others'} += $10;
1795 if ($prog eq "cnfsstat") {
1796 # Class ALT for groups matching "alt.*" article size min/max: 0/1048576
1797 # Buffer T3, len: 1953 Mbytes, used: 483.75 Mbytes (24.8%) 0 cycles
1798 if ($left =~ m|^Class\ (\S+)\ for\ groups\ matching\ \S+
1799 (\ article\ size\ min/max:\ \d+/\d+)?
1801 \ len:\ ([\d.]+)\s+Mbytes,
1802 \ used:\ ([\d.]+)\ Mbytes\ \(\s*[\d.]+%\)
1805 my ($class, $buffer, $size, $used, $cycles) = ($1, $3, $4, $5, $6);
1806 my ($h, $m, $s) = $hour =~ m/^(\d+):(\d+):(\d+)$/;
1807 my $time = $h * 3600 + $m * 60 + $s;
1808 $size *= 1024 * 1024;
1809 $used *= 1024 * 1024;
1810 $cnfsstat{$buffer} = $class;
1812 # If the size changed, invalidate all of our running fill rate stats.
1813 if (!exists($cnfsstat_size{$buffer}) || $size != $cnfsstat_size{$buffer}) {
1814 delete $cnfsstat_rate{$buffer};
1815 delete $cnfsstat_samples{$buffer};
1816 delete $cnfsstat_time{$buffer};
1817 $cnfsstat_size{$buffer} = $size;
1819 elsif ($cnfsstat_time{$buffer}) {
1820 # We want to gather the rate at which cycbuffs fill. Store a
1821 # running total of bytes/second and a total number of samples.
1822 # Ideally we'd want a weighted average of those samples by the
1823 # length of the sample period, but we'll ignore that and assume
1824 # cnfsstat runs at a roughly consistent interval.
1825 my ($period, $added);
1826 $period = $time - $cnfsstat_time{$buffer};
1827 $period = 86400 - $cnfsstat_time{$buffer} + $time if $period <= 0;
1828 $added = $used - $cnfsstat_used{$buffer};
1829 if ($cycles > $cnfsstat_cycles{$buffer}) {
1830 $added += $size * ($cycles - $cnfsstat_cycles{$buffer});
1833 $cnfsstat_rate{$buffer} += $added / $period;
1834 $cnfsstat_samples{$buffer}++;
1837 $cnfsstat_used{$buffer} = $used;
1838 $cnfsstat_cycles{$buffer} = $cycles;
1839 $cnfsstat_time{$buffer} = $time;
1844 # Ignore following programs :
1845 return 1 if ($prog eq "uxfxn");
1846 return 1 if ($prog eq "beverage");
1847 return 1 if ($prog eq "newsx");
1848 return 1 if ($prog eq "demmf");
1849 return 1 if ($prog eq "nnnn");
1850 return 1 if ($prog eq "slurp");
1854 #################################
1855 # Adjust some values..
1858 my ($first_date, $last_date) = @_;
1865 if (%nnrpd_connect) {
1866 my $c = keys (%nnrpd_connect);
1867 foreach $serv (keys (%nnrpd_connect)) {
1868 my $dom = &host2dom($serv);
1869 if ($nnrpd_no_permission{$serv}) {
1870 $nnrpd_dom_connect{$dom} -= $nnrpd_connect{$serv}
1871 if defined $nnrpd_dom_connect{$dom} && defined $nnrpd_connect{$serv};
1872 $nnrpd_dom_groups{$dom} -= $nnrpd_groups{$serv}
1873 if defined $nnrpd_dom_groups{$dom} && defined $nnrpd_groups{$serv};
1874 $nnrpd_dom_times{$dom} -= $nnrpd_times{$serv}
1875 if defined $nnrpd_dom_times{$dom};
1876 $nnrpd_connect{$serv} -= $nnrpd_no_permission{$serv};
1877 $nnrpd_groups{$serv} -= $nnrpd_no_permission{$serv}
1878 if defined $nnrpd_groups{$serv};
1879 delete $nnrpd_connect{$serv} unless $nnrpd_connect{$serv};
1880 delete $nnrpd_groups{$serv} unless $nnrpd_groups{$serv};
1881 delete $nnrpd_times{$serv} unless $nnrpd_times{$serv};
1882 delete $nnrpd_usr_times{$serv} unless $nnrpd_usr_times{$serv};
1883 delete $nnrpd_sys_times{$serv} unless $nnrpd_sys_times{$serv};
1884 delete $nnrpd_dom_connect{$dom} unless $nnrpd_dom_connect{$dom};
1885 delete $nnrpd_dom_groups{$dom} unless $nnrpd_dom_groups{$dom};
1886 delete $nnrpd_dom_times{$dom} unless $nnrpd_dom_times{$dom};
1890 if $nnrpd_groups{$serv} || $nnrpd_post_ok{$serv};
1892 undef %nnrpd_connect unless $c;
1894 foreach $serv (keys (%nnrpd_groups)) {
1895 $curious = "ok" unless $nnrpd_groups{$serv} || $nnrpd_post_ok{$serv} ||
1896 $nnrpd_articles{$serv};
1903 foreach $key (keys (%innd_connect)) {
1904 $innd_offered{$key} = ($innd_accepted{$key} || 0)
1905 + ($innd_refused{$key} || 0)
1906 + ($innd_rejected{$key} || 0);
1907 $innd_offered_size{$key} = ($innd_stored_size{$key} || 0)
1908 + ($innd_duplicated_size{$key} || 0);
1912 # adjust min/max of innd timer stats.
1913 if (%innd_time_min) {
1914 foreach $key (keys (%innd_time_min)) {
1915 $innd_time_min{$key} = 0 if ($innd_time_min{$key} == $MIN);
1916 $innd_time_max{$key} = 0 if ($innd_time_max{$key} == $MAX);
1918 #$innd_time_min{$key} /= 1000;
1919 #$innd_time_max{$key} /= 1000;
1922 if (%innfeed_time_min) {
1923 foreach $key (keys (%innfeed_time_min)) {
1924 $innfeed_time_min{$key} = 0 if ($innfeed_time_min{$key} == $MIN);
1925 $innfeed_time_max{$key} = 0 if ($innfeed_time_max{$key} == $MAX);
1928 if (%nnrpd_time_min) {
1929 foreach $key (keys (%nnrpd_time_min)) {
1930 $nnrpd_time_min{$key} = 0 if ($nnrpd_time_min{$key} == $MIN);
1931 $nnrpd_time_max{$key} = 0 if ($nnrpd_time_max{$key} == $MAX);
1934 # remove the innd timer stats if not used.
1935 unless ($innd_time_times) {
1936 undef %innd_time_min;
1937 undef %innd_time_max;
1938 undef %innd_time_num;
1939 undef %innd_time_time;
1941 # same thing for innfeed timer
1942 unless ($innfeed_time_times) {
1943 undef %innfeed_time_min;
1944 undef %innfeed_time_max;
1945 undef %innfeed_time_num;
1946 undef %innfeed_time_time;
1948 # same thing for nnrpd timer
1949 unless ($nnrpd_time_times) {
1950 undef %nnrpd_time_min;
1951 undef %nnrpd_time_max;
1952 undef %nnrpd_time_num;
1953 undef %nnrpd_time_time;
1956 # adjust the crosspost stats.
1958 foreach $key (keys (%crosspost)) {
1959 $crosspost_times{$key} = $crosspost_time ?
1960 sprintf "%.2f", $crosspost{$key} / $crosspost_time * 60 : "?";
1966 my ($prev_dd, $prev_d, $prev_h) = ("", -1, -1);
1968 foreach $day (sort datecmp keys (%inn_flow)) {
1969 my ($r, $h) = $day =~ /^(.*) (\d+)$/;
1970 my $d = index ("JanFebMarAprMayJunJulAugSepOctNovDec",
1971 substr ($r,0,3)) / 3 * 31 + substr ($r, 4, 2);
1972 $prev_h = $h if ($prev_h == -1);
1973 if ($prev_d == -1) {
1977 if ($r eq $prev_dd) { # Same day and same month ?
1978 if ($h != $prev_h) {
1979 if ($h == $prev_h + 1) {
1984 for ($j = $prev_h + 1; $j < $h; $j++) {
1985 my $t = sprintf "%02d", $j;
1986 $inn_flow{"$r $t"} = 0;
1994 # then end of the first day...
1995 for ($j = ($prev_h == 23) ? 24 : $prev_h + 1; $j < 24; $j++) {
1996 my $t = sprintf "%02d", $j;
1997 $inn_flow{"$prev_dd $t"} = 0;
2000 # all the days between (if any)
2001 # well, we can forget them as it is supposed to be a tool
2004 # the beginning of the last day..
2005 for ($j = 0; $j < $h; $j++) {
2006 my $t = sprintf "%02d", $j;
2007 $inn_flow{"$r $t"} = 0;
2015 my (%hash, %hash_time, %hash_size, $date, $delay);
2016 foreach $day (sort datecmp keys (%inn_flow)) {
2017 my ($r, $h) = $day =~ /^(.*) (\d+)$/o;
2020 my ($t) = $first_date =~ m/:(\d\d:\d\d)$/o;
2021 $date = "$day:$t - $h:59:59";
2022 $t =~ m/(\d\d):(\d\d)/o;
2023 $delay = 3600 - $1 * 60 - $2;
2026 $date = "$day:00:00 - $h:59:59";
2029 $hash{$date} = $inn_flow{$day};
2030 $hash_size{$date} = $inn_flow_size{$day};
2031 $inn_flow_labels{$date} = $h;
2032 $hash_time{$date} = $delay;
2034 my ($h, $t) = $last_date =~ m/ (\d+):(\d\d:\d\d)$/o;
2035 my ($h2) = $date =~ m/ (\d+):\d\d:\d\d /o;
2037 $date2 =~ s/$h2:59:59$/$h:$t/;
2038 $hash{$date2} = $hash{$date};
2039 delete $hash{"$date"};
2040 $hash_size{$date2} = $hash_size{$date};
2041 delete $hash_size{"$date"};
2042 $t =~ m/(\d\d):(\d\d)/o;
2043 $hash_time{$date2} = $hash_time{$date} - ($h2 == $h) * 3600 + $1 * 60 + $2;
2044 delete $hash_time{"$date"};
2045 $inn_flow_labels{$date2} = $h;
2047 %inn_flow_time = %hash_time;
2048 %inn_flow_size = %hash_size;
2051 if (%innd_bad_ihave) {
2053 my $msg = 'Bad ihave control messages received';
2054 foreach $key (keys %innd_bad_ihave) {
2055 $innd_misc_stat{$msg}{$key} = $innd_bad_ihave{$key};
2058 if (%innd_bad_msgid) {
2060 my $msg = 'Bad Message-ID\'s offered';
2061 foreach $key (keys %innd_bad_msgid) {
2062 $innd_misc_stat{$msg}{$key} = $innd_bad_msgid{$key};
2065 if (%innd_bad_sendme) {
2067 my $msg = 'Ignored sendme control messages received';
2068 foreach $key (keys %innd_bad_sendme) {
2069 $innd_misc_stat{$msg}{$key} = $innd_bad_sendme{$key};
2072 if (%innd_bad_command) {
2074 my $msg = 'Bad command received';
2075 foreach $key (keys %innd_bad_command) {
2076 $innd_misc_stat{$msg}{$key} = $innd_bad_command{$key};
2079 if (%innd_bad_newsgroup) {
2081 my $msg = 'Bad newsgroups received';
2082 foreach $key (keys %innd_bad_newsgroup) {
2083 $innd_misc_stat{$msg}{$key} = $innd_bad_newsgroup{$key};
2086 if (%innd_posted_future) {
2088 my $msg = 'Article posted in the future';
2089 foreach $key (keys %innd_posted_future) {
2090 $innd_misc_stat{$msg}{$key} = $innd_posted_future{$key};
2093 if (%innd_no_colon_space) {
2095 my $msg = 'No colon-space in header';
2096 foreach $key (keys %innd_no_colon_space) {
2097 $innd_misc_stat{$msg}{$key} = $innd_no_colon_space{$key};
2102 my $msg = 'Huge articles';
2103 foreach $key (keys %innd_huge) {
2104 $innd_misc_stat{$msg}{$key} = $innd_huge{$key};
2107 if (%innd_blocked) {
2109 my $msg = 'Blocked server feeds';
2110 foreach $key (keys %innd_blocked) {
2111 $innd_misc_stat{$msg}{$key} = $innd_blocked{$key};
2114 if (%innd_strange_strings) {
2116 my $msg = 'Including strange strings';
2117 foreach $key (keys %innd_strange_strings) {
2118 $innd_misc_stat{$msg}{$key} = $innd_strange_strings{$key};
2121 if (%rnews_bogus_ng) {
2123 my $msg = 'Unwanted newsgroups';
2124 foreach $key (keys %rnews_bogus_ng) {
2125 $rnews_misc{$msg}{$key} = $rnews_bogus_ng{$key};
2128 if (%rnews_bogus_dist) {
2130 my $msg = 'Unwanted distributions';
2131 foreach $key (keys %rnews_bogus_dist) {
2132 $rnews_misc{$msg}{$key} = $rnews_bogus_dist{$key};
2135 if (%rnews_unapproved) {
2137 my $msg = 'Articles unapproved';
2138 foreach $key (keys %rnews_unapproved) {
2139 $rnews_misc{$msg}{$key} = $rnews_unapproved{$key};
2142 if (%rnews_bogus_date) {
2144 my $msg = 'Bad Date';
2145 foreach $key (keys %rnews_bogus_date) {
2146 $rnews_misc{$msg}{$key} = $rnews_bogus_date{$key};
2150 $rnews_misc{'Too old'}{'--'} = $rnews_too_old if $rnews_too_old;
2151 $rnews_misc{'Bad linecount'}{'--'} = $rnews_linecount if $rnews_linecount;
2152 $rnews_misc{'Duplicate articles'}{'--'} = $rnews_duplicate
2153 if $rnews_duplicate;
2154 $rnews_misc{'No colon-space'}{'--'} = $rnews_no_colon_space
2155 if $rnews_no_colon_space;
2157 if (%nnrpd_groups) {
2159 foreach $key (keys (%nnrpd_connect)) {
2160 unless ($nnrpd_groups{"$key"} || $nnrpd_post_ok{"$key"} ||
2161 $nnrpd_articles{"$key"}) {
2162 $nnrpd_curious{$key} = $nnrpd_connect{$key};
2163 undef $nnrpd_connect{$key};
2169 sub report_unwanted_ng {
2171 open (FILE, "$file") && do {
2173 my ($c, $n) = $_ =~ m/^\s*(\d+)\s+(.*)$/;
2174 next unless defined $n;
2175 $n =~ s/^newsgroup //o; # for pre 1.8 logs
2176 $inn_uw_ng{$n} += $c;
2181 unlink ("${file}.old");
2182 rename ($file, "${file}.old");
2184 open (FILE, "> $file") && do {
2186 foreach $g (sort {$inn_uw_ng{$b} <=> $inn_uw_ng{$a}} (keys (%inn_uw_ng))) {
2187 printf FILE "%d %s\n", $inn_uw_ng{$g}, $g;
2190 chmod(0660, "$file");
2192 unlink ("${file}.old");
2195 ###########################################################################
2197 # Compare 2 dates (+hour)
2199 # ex: "May 12 06" for May 12, 6:00am
2201 # The 2 dates are near. The range is less than a few days that's why we
2202 # can cheat to determine the order. It is only important if one date
2203 # is in January and the other in December.
2205 my($date1) = substr($a, 4, 2) * 24;
2206 my($date2) = substr($b, 4, 2) * 24;
2207 $date1 += index("JanFebMarAprMayJunJulAugSepOctNovDec",substr($a,0,3)) * 288;
2208 $date2 += index("JanFebMarAprMayJunJulAugSepOctNovDec",substr($b,0,3)) * 288;
2209 if ($date1 - $date2 > 300 * 24) {
2210 $date2 += 288 * 3 * 12;
2212 elsif ($date2 - $date1 > 300 * 24) {
2213 $date1 += 288 * 3 * 12;
2215 $date1 += substr($a, 7, 2);
2216 $date2 += substr($b, 7, 2);
2223 $host =~ m/^[^\.]+(.*)/;
2224 $host =~ m/^[\d\.]+$/ ? "unresolved" : $1 ? "*$1" : "?";