denny@mcmi.uucp (Denny Page) (10/18/89)
Here is version 1.2 of nstats. It contains a fix for a bug in article
totals (1.1 missed rejection totals), explanation of headers, and variable
name changes for running in Perl 3.0.
Thanks to Jim Budler (jim@eda.com) for the note on Perl 3.0.
#!/usr/bin/perl
#
# Nstats - Print C news statistics via Perl
#
# Version 1.2 (10/17/89)
#
#
#
# Author's notes:
#
# Constructive comments and enhancements are solicited (flames are not).
# Please send suggestions or enhancements to denny@mcmi.
#
# Larry Wall has a Very Nice Work in Perl. Many thanks to him.
#
# Denny Page, 1989
#
#
#
# Program notes:
#
# The simplest usage is 'perl nstats ~news/log'. I leave you to find
# more complicated invocations.
#
# While a duplicate is actually a rejected message, it is treated
# separately here. Rejected messages herein are messages that are not
# subscribed to in the sys file or are excluded in the active file.
#
# Junked messages are not displayed in the system summaries. It's not
# your neighbor's fault that you are missing active file entries. If
# you are concerned about receiving junk groups, exclude them in your
# sys or active file. They will then be summarized :-).
#
# The reason for a newsgroup being bad is assigned only once. If the
# reason changes later in the log (such as the sys file being modified
# such that a newsgroup is no longer rejected, but rather is filed in
# junk), no notice will be taken.
#
# Calls to newshist are cached at 25. This may need to be adjusted at
# some sites.
#
# Sitenames are truncated to 15 characters. This could be done better.
#
#
# Output headers have the following meanings:
#
# System Name of the neighboring system.
# Accept Number of accepted articles from system.
# Dup Number of duplicate articles received from system.
# Rej Number of rejected articles from system.
# Sent Number of articles sent to system.
# Sys% Accepted (or duplicate or rejected) articles as a
# percentage of total articles from that system.
# Tot% Accepted (or duplicate) articles as a percentage
# of total accepted (or duplicate) articles.
# Avl% Number of articles sent as a percentage of total
# available (accepted) articles.
#
############################################################
#
# Revision history:
#
# 09/24/89 dny Initial version
# 09/28/89 dny Added category totals
# 10/02/89 dny Fixed link count bug in record_groups
# 10/03/89 dny Cleaned up variable names
# 10/16/89 dny Renamed variables - Perl 3.0
# 10/17/89 dny Fixed bug in rejection counts
#
############################################################
################ ***** Change this ***** ###################
#
$newshist="/usr/local/lib/news/bin/maint/newshist";
#
############################################################
# Record the category of a list of message-ids
sub record_groups {
open(newshist, "-|") || exec $newshist, '--', @_;
while (<newshist>) {
if (s/^.+\t.+\t(.+)\n$/$1/) {
foreach $link (split(/ /)) {
$link =~ s/^([^\.\/]+).*/$1/;
$category{$link}++;
}
}
else {
$category{"*expired*"}++;
}
}
close(newshist);
}
############################################################
$#id_cache = -1;
while (<>) {
($from, $action, $message_id, $text) =
/^.+\s(\S+)\s(.)\s<(.+)>\s(.*)$/;
$from = substr($from, 0, 15);
# Accepted message
if ($action eq '+') {
$accepted{$from}++;
foreach $site (split(/ /, $text)) {
$site = substr($site, 0, 15);
$sent{$site}++;
}
$id_cache[++$#id_cache] = $message_id;
unless ($#id_cache < 25) {
do record_groups(@id_cache);
$#id_cache = -1;
}
next;
}
elsif ($action eq '-') {
# Duplicate
if ($text eq 'duplicate') {
$duplicates{$from}++;
next;
}
$rejected{$from}++;
# Group not in sys
if ($text =~ s/no subscribed groups in `(.+)'/$1/) {
foreach $group (split(/,/, $text)) {
if ($badgroup{$group}++ == 0) {
$badgroup_reason{$group} = "not subscribed in sys";
}
}
next;
}
# Group excluded in active
elsif ($text =~ s/all groups `(.+)' excluded in active/$1/) {
foreach $group (split(/,/, $text)) {
if ($badgroup{$group}++ == 0) {
$badgroup_reason{$group} = "excluded in active";
}
}
next;
}
}
# Junked message
elsif ($action eq 'j') {
$junk{$from}++;
if ($text =~ s/junked due to groups `(.+)'/$1/) {
foreach $group (split(/,/, $text)) {
if ($badgroup{$group}++ == 0) {
$badgroup_reason{$group} = "not in active (junked)";
}
}
next;
}
}
# Ignore ihave/sendme messages
elsif ($action eq 'i') {next;}
elsif ($action eq 's') {next;}
# Unknown input line
print $_;
}
if ($#id_cache >= 0) {
do record_groups(@id_cache);
}
# Collect all sitenames and calc totals
foreach $system (keys(accepted)) {
$systems{$system} = 1;
$total_accepted += $accepted{$system};
}
foreach $system (keys(duplicates)) {
$systems{$system} = 1;
$total_duplicates += $duplicates{$system};
}
foreach $system (keys(rejected)) {
$systems{$system} = 1;
$total_rejected += $rejected{$system};
}
foreach $system (keys(sent)) {
$systems{$system} = 1;
$total_sent += $sent{$system};
}
$total_articles = $total_accepted + $total_duplicates + $total_rejected;
# Print system summaries
print "\nSystem Accept sys% tot% Dup sys% tot% Rej sys% Sent avl%\n";
foreach $system (sort keys(systems)) {
$articles = $accepted{$system} + $duplicates{$system} + $rejected{$system};
if ($accepted{$system} > 0) {
$accepted_pct = ($accepted{$system} * 100) / $articles + 0.5;
$accepted_totpct = ($accepted{$system} * 100) / $total_accepted + 0.5;
}
else {
$accepted_pct = 0;
$accepted_totpct = 0;
}
if ($duplicates{$system} > 0) {
$duplicates_pct = ($duplicates{$system} * 100) / $articles + 0.5;
$duplicates_totpct = ($duplicates{$system} * 100) / $total_duplicates + 0.5;
}
else {
$duplicates_pct = 0;
$duplicates_totpct = 0;
}
if ($rejected{$system} > 0) {
$rejected_pct = ($rejected{$system} * 100) / $articles + 0.5;
}
else {
$rejected_pct = 0;
}
if ($sent{$system} > 0) {
$sent_pct = ($sent{$system} * 100) / $total_accepted + 0.5;
}
else {
$sent_pct = 0;
}
printf "%-15s %5d %3d%% %3d%% %4d %3d%% %3d%% %4d %3d%% %5d %3d%%\n",
$system,
$accepted{$system}, $accepted_pct, $accepted_totpct,
$duplicates{$system}, $duplicates_pct, $duplicates_totpct,
$rejected{$system}, $rejected_pct,
$sent{$system}, $sent_pct;
}
if ($total_accepted > 0) {
$accepted_pct = ($total_accepted * 100) / $total_articles + 0.5;
}
else {
$accepted_pct = 0;
}
if ($total_rejected > 0) {
$rejected_pct = ($total_rejected * 100) / $total_articles + 0.5;
}
else {
$rejected_pct = 0;
}
if ($total_duplicates > 0) {
$duplicates_pct = ($total_duplicates * 100) / $total_articles + 0.5;
}
else {
$duplicates_pct = 0;
}
printf "TOTALS %5d %3d%% %4d %3d%% %4d %3d%% %5d\n",
$total_accepted, $accepted_pct,
$total_duplicates, $duplicates_pct,
$total_rejected, $rejected_pct,
$total_sent;
# Display any bad newsgroups received
@keys = sort(keys(badgroup));
if ($#keys >= 0) {
print "\n\nBad Newsgroups Articles Reason\n";
foreach $group (@keys) {
printf "%-35s %4d %s\n",
$group, $badgroup{$group}, $badgroup_reason{$group};
}
}
# Display news categories received
@keys = sort(keys(category));
if ($#keys >= 0) {
print "\n\nCategories Received Articles\n";
foreach $group (@keys) {
printf "%-35s %4d\n",
$group, $category{$group};
}
}
--
Good health is merely the slowest rate at which one can die.