[comp.lang.perl] Log summaries

brendan@cs.widener.edu (Brendan Kehoe) (04/15/91)

 Has anybody written a program (Perl?) to parse UUCP log files, to
give an idea how much each UUCP connection's being used, and for how
long?

Brendan
-- 
     Brendan Kehoe - Widener Sun Network Manager - brendan@cs.widener.edu
  Widener University in Chester, PA                A Bloody Sun-Dec War Zone
      "Does this person look relaxed to you?  Well, it's actually an
              experiment of Contour's new 565-E chair!"

jv@mh.nl (Johan Vromans) (04/16/91)

>  Has anybody written a program (Perl?) to parse UUCP log files, to
> give an idea how much each UUCP connection's being used, and for how
> long?

Reposting time...

---- Cut Here and feed the following to sh ----
#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 04/16/1991 07:06 UTC by jv@largo
# Source directory /u1/users/jv
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   5454 -r--r--r-- uutraf.pl
#
# ============= uutraf.pl ==============
if test -f 'uutraf.pl' -a X"$1" != X"-c"; then
	echo 'x - skipping uutraf.pl (File already exists)'
else
echo 'x - extracting uutraf.pl (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'uutraf.pl' &&
#!/usr/bin/perl
eval "exec /usr/bin/perl -S $0 $*"
X  if $running_under_some_shell;
do verify_perl_version (3001);
X
# @(#)@ uutraf	1.4 - uutraf.pl
#
# UUCP Traffic Analyzer
#
# Reads /usr/lib/uucp/.Admin/xferstats, and generates a report from it.
# Also understands Ultrix SYSLOG format.
#
# Created by Johan Vromans <jv@mh.nl>
# Loosely based on an idea by Greg Hackney (hack@texbell.swbt.com)
X
# Usage: uutraf [xferstats]
X
$type = "unknown";
X
if ( $#ARGV >= 0 ) {
X    open (STDIN, $ARGV[0]) || die "Cannot open $ARGV[0]";
X    open (IN, $ARGV[0]) || die "Cannot open $ARGV[0]";
X    $line = <IN>;
X    split (/ /, $line);
X    $type = ($_[0] =~ /!/) ? "HDB" : "U";
}
elsif ( -r "/usr/spool/uucp/.Admin/xferstats" ) {
X    open (STDIN, "/usr/spool/uucp/.Admin/xferstats");
X    $type = "HDB";
}
elsif ( -r "/usr/spool/uucp/SYSLOG" ) {
X    open (STDIN, "/usr/spool/uucp/SYSLOG");
X    $type = "U";
}
else { die "Sorry, don't know what"; }
X
if ( $type eq "HDB" ) {
X    $pat = "([^!]+)![^(]+\\(([-0-9:/]+)\\).+([<>])-? (\\d+) / (\\d+)\\.(\\d+) secs";
X    $recv = "<";
}
else {
X    $pat = "\\S+\\s+(\\S+)\\s+\\(([-0-9:/]+)\\)\\s+\\(\\d+\\)\\s+(\\w+) (\\d+) b (\\d+) secs";
X    $recv = "received";
}
X
%hosts = ();		# hosts seen
%bytes_in = ();		# of bytes received from host
%bytes_out = ();	# of bytes sent to host
%secs_in = ();		# of seconds connect for recving
%secs_out = ();		# of seconds connect for sending
%files_in = ();		# of input requests
%files_out = ();	# of output requests
X
# read info, break the lines and tally
X
while ( <STDIN> ) {
X  if ( /^$pat/o ) {
#   print "host $1, date $2, dir $3, bytes $4, secs $5.$6\n";
X    $6 = 0 if $type eq "U";
X    # gather timestamps
X    $last_date = $2;
X    $first_date = $last_date unless defined $first_date;
X
X    # initialize new hosts
X    unless ( defined $hosts{$1} ) {
X      $hosts{$1} = $files_in{$1} = $files_out{$1} = 
X	$bytes_in{$1} = $bytes_out{$1} =
X	  $secs_in{$1} = $secs_out{$1} = 0;
X    }
X
X    # tally
X    if ( $3 eq $recv ) {		# recv
X      $bytes_in{$1} += $4;
X      $files_in{$1}++;
X      $secs_in{$1} += $5 + $6/1000;
X    }
X    else {			# xmit
X      $bytes_out{$1} += $4;
X      $files_out{$1}++;
X      $secs_out{$1} += $5 + $6/1000;
X    }
X  }
X  else {
X    print STDERR "Possible garbage: $_";
X  }
}
X
@hosts = keys (%hosts);
die "No info found, stopped" if $#hosts < 0;
X
################ report section ################
X
$thishost = do gethostname();
$thishost = (defined $thishost) ? "on node $thishost" : "report";
X
format std_head =
@|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"UUCP traffic $thishost from $first_date to $last_date"
X
Remote   -----------K-Bytes----------- ----Hours---- --Avg CPS-- --Files--
X Host         Recv      Sent     Total   Recv   Sent  Recv  Sent Recv Sent
.
format std_out =
@<<<<<<< @>>>>>>>> @>>>>>>>> @>>>>>>>> @>>>>> @>>>>> @>>>> @>>>> @>>> @>>>
$Zhost,   $Zi_bytes, $Zo_bytes, $Zt_bytes, $Zi_hrs, $Zo_hrs, $Zi_acps, $Zo_acps, $Zi_count, $Zo_count
.
X
$^ = "std_head";
$~ = "std_out";
X
do print_dashes ();
X
reset "T";	       # reset totals
X
foreach $host (@hosts) {
X  do print_line ($host, $bytes_in{$host}, $bytes_out{$host},
X		 $secs_in{$host},  $secs_out{$host},
X		 $files_in{$host}, $files_out{$host});
X
}
X
do print_dashes ();
do print_line ("Total", $Ti_bytes, $To_bytes,
X	       $Ti_secs, $To_secs, $Ti_count, $To_count);
X
################ that's it ################
X
sub print_line {
X  reset "Z";		# reset print fields
X  local ($Zhost, 
X	 $Zi_bytes, $Zo_bytes, 
X	 $Zi_secs, $Zo_secs, 
X	 $Zi_count, $Zo_count) = @_;
X  $Ti_bytes += $Zi_bytes;
X  $To_bytes += $Zo_bytes;
X  $Zt_bytes = $Zi_bytes + $Zo_bytes;
X  $Tt_bytes += $Zt_bytes;
X  $Zi_acps = ($Zi_secs > 0) ? sprintf ("%.0f", $Zi_bytes/$Zi_secs) : "0";
X  $Zo_acps = ($Zo_secs > 0) ? sprintf ("%.0f", $Zo_bytes/$Zo_secs) : "0";
X  $Zi_bytes = sprintf ("%.1f", $Zi_bytes/1000);
X  $Zo_bytes = sprintf ("%.1f", $Zo_bytes/1000);
X  $Zt_bytes = sprintf ("%.1f", $Zt_bytes/1000);
X  $Zi_hrs = sprintf ("%.1f", $Zi_secs/3600);
X  $Zo_hrs = sprintf ("%.1f", $Zo_secs/3600);
X  $Ti_secs += $Zi_secs;
X  $To_secs += $Zo_secs;
X  $Ti_count += $Zi_count;
X  $To_count += $Zo_count;
X  write;
}
X
sub print_dashes {
X  $Zhost = $Zi_bytes = $Zo_bytes = $Zt_bytes =
X    $Zi_hrs = $Zo_hrs = $Zi_acps = $Zo_acps = $Zi_count = $Zo_count = 
X      "------------";
X  write;
X  # easy, isn't it?
}
X
################ missing ################
X
sub gethostname {
X  $ENV{"SHELL"} = "/bin/sh";
X  $try = `hostname 2>/dev/null`;
X  chop $try;
X  return $+ if $try =~ /^[-.\w]+$/;
X  $try = `uname -n 2>/dev/null`;
X  chop $try;
X  return $+ if $try =~ /^[-.\w]+$/;
X  $try = `uuname -l 2>/dev/null`;
X  chop $try;
X  return $+ if $try =~ /^[-.\w]+$/;
X  return undef;
}
X
################ verify perl version ################
X
# do verify_perl_version ( [ required , [ message ] ] )
X
sub verify_perl_version {
X  local ($version,$patchlevel) = $] =~ /(\d+.\d+).*\nPatch level: (\d+)/;
X  $version = $version * 1000 + $patchlevel;
X
X  # did the caller pass a required version?
X  if ( $#_ >= 0 ) {
X    local ($req, $msg, @req);
X    @req = split (//, $req = shift);
X    # if the request is valid - check it
X    if ( $#req == 3 && $req > $version ) {
X      if ( $#_ >= 0 ) {	# user supplied message
X	$msg = shift;
X      }
X      else {
X        $msg = "Sorry, this program requires perl " . $req[0] . "." . $req[1] .
X	        " patch level " . $req % 100 ." or later.\nStopped";
X      }
X      die $msg;
X    }
X  }
X  return $version;
}
SHAR_EOF
chmod 0444 uutraf.pl ||
echo 'restore of uutraf.pl failed'
Wc_c="`wc -c < 'uutraf.pl'`"
test 5454 -eq "$Wc_c" ||
	echo 'uutraf.pl: original size 5454, current size' "$Wc_c"
fi
exit 0
-- 
Johan Vromans				       jv@mh.nl via internet backbones
Multihouse Automatisering bv		       uucp: ..!{uunet,hp4nl}!mh.nl!jv
Doesburgweg 7, 2803 PL Gouda, The Netherlands  phone/fax: +31 1820 62911/62500
------------------------ "Arms are made for hugging" -------------------------

chip@tct.com (Chip Salzenberg) (04/16/91)

According to brendan@cs.widener.edu (Brendan Kehoe):
>Has anybody written a program (Perl?) to parse UUCP log files, to
>give an idea how much each UUCP connection's being used, and for how
>long?

Sure.  This one, "uuconstat", is for HDB UUCP.  Shar and enjoy.

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  uuconstat
# Wrapped by chip@count on Tue Apr 16 12:51:17 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'uuconstat' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'uuconstat'\"
else
echo shar: Extracting \"'uuconstat'\" \(3648 characters\)
sed "s/^X//" >'uuconstat' <<'END_OF_FILE'
Xeval 'exec /bin/perl -S $0 ${1+"$@"}'
X	if 0;
X
X# $Id: uuconstat,v 1.3 90/10/23 10:29:08 chip Exp Locker: chip $
X#
X# Print UUCP connect time statistics.
X#
X# $Log:	uuconstat,v $
X# Revision 1.3  90/10/23  10:29:08  chip
X# Don't count "wrong time" as a failure.
X# 
X# Revision 1.2  90/09/28  11:05:53  chip
X# Better function names and output format.
X# 
X# Revision 1.1  90/06/01  12:23:36  chip
X# Initial revision
X# 
X
X$LOGDIR = "/usr/spool/uucp/.Log/uucico";
X
X$verbose = 0;
X$debug = 0;
Xwhile (@ARGV) {
X	$_ = $ARGV[0];
X	last unless s/^-//;
X	shift;
X	last if $_ eq "-";
X	$verbose = 1 if s/v//g;
X	$debug = 1   if s/d//g;
X}
X
Xif (@ARGV == 0) {
X	opendir(LOG, $LOGDIR) || die "$LOGDIR: $!\n";
X	@ARGV = grep($_ ne "." && $_ ne "..", sort readdir(LOG));
X	closedir(LOG);
X}
X
Xformat top =
XUUCP Connect Time Statistics
X
XSystem      Succ  Fail  Tot Time  Avg Time
X----------  ----  ----  --------  --------
X.
X
Xformat STDOUT =
X@<<<<<<<<<  @>>>  @>>>   @>>>>>    @>>>>>
X$system, $success, $failure, $fmt_time, $fmt_avgtime
X.
X
Xformat SUMMARY =
X----------  ----  ----  --------  --------
XTotals      @>>>  @>>>   @>>>>>    @>>>>>
X        $t_success, $t_failure, $fmt_time, $fmt_avgtime
X.
X
Xforeach (@ARGV) {
X	$_ = $LOGDIR."/".$_ unless ($_ eq "-") || m#/#;
X}
X
Xwhile (<>) {
X	chop;
X	next unless s/^\S+\s+(\S+)[^(]+\(/$1 \(/;
X	($system, $dt, $what) = split(/\s+/, $_, 3);
X	$_ = $what;
X
X	@DT = &DT($dt);
X	unless (@DT == 5) {
X		print STDERR "warning: bad date/time at ", $.,
X				" in ", $system, "\n";
X		next;
X	}
X
X	$now = &CTIME(@DT);
X	if (!defined($first_time) || $now lt $first_time) {
X		$first_time = $now;
X	}
X	if (!defined($last_time) || $now gt $last_time) {
X		$last_time = $now;
X	}
X
X	$SYSTEMS{$system} = 1;
X	if (/SUCCEEDED.*call to/) {
X		if (@START && $verbose) {
X			print STDERR "warning: unterminated call to ",
X				$start_system, " at ", &CTIME(@START), "\n";
X		}
X		@START = @DT;
X		$start_system = $system;
X	}
X	elsif (/OK.*complete/
X	    || @START && (/CAUGHT.*sig/ || /INTREXIT/)) {
X		$call_began = &HMS_SECONDS(@START[2..4]);
X		$call_ended = &HMS_SECONDS(@DT[2..4]);
X		if ($call_ended < $call_began) {
X			$call_ended += &ONE_DAY;
X		}
X
X		if ($debug) {
X			print STDERR &CTIME(@START), " to ",
X				&CTIME(@DT), " makes ",
X				($call_ended - $call_began),
X				" seconds.\n";
X		}
X
X		$TIME{$system} += ($call_ended - $call_began);
X		++$SUCCESS{$system};
X		@START = ();
X	}
X	elsif (/WRONG TIME/) {
X		# do nothing
X	}
X	elsif (/CONN FAILED/ || /LOST LINE \(LOGIN\)/) {
X		++$FAILURE{$system};
X	}
X}
X
Xforeach $system (sort keys(%SYSTEMS)) {
X	$time = $TIME{$system};
X	$success = $SUCCESS{$system};
X	$failure = $FAILURE{$system};
X
X	$fmt_time = &FMT_SECONDS($time);
X	$fmt_avgtime = $success ? &FMT_SECONDS($time / $success) : "";
X	write;
X
X	$t_success += $success;
X	$t_failure += $failure;
X	$t_time += $time;
X}
X
Xif ($t_success || $t_failure) {
X	$fmt_time = &FMT_SECONDS($t_time);
X	$fmt_avgtime = $t_success ? &FMT_SECONDS($t_time / $t_success) : "";
X	$~ = "SUMMARY";
X	write;
X}
X
Xif ($first_time && $last_time) {
X	print "\n";
X	print "First attempt: $first_time\n";
X	print "Last attempt:  $last_time\n";
X}
X
Xexit;
X
Xsub DT {
X	local(@X);
X	@X = ($_[0] =~ m#^\((\d+)/(\d+)-(\d+):(\d+):(\d+),\d+,\d+\)#);
X	@X;
X}
X
Xsub HMS_SECONDS {
X	($hour, $minute, $second) = @_;
X
X	return ($hour * 3600) + ($minute * 60) + $second;
X}
X
Xsub ONE_DAY {
X	return 24 * 3600;
X}
X
Xsub FMT_SECONDS {
X	local($i) = @_;
X	local($h, $m, $s);
X
X	$s = $i % 60;
X	$i = int($i / 60);
X	$m = $i % 60;
X	$h = int($i / 60);
X	++$m if $s >= 30;
X	return sprintf("%2d:%02d", $h, $m);
X}
X
Xsub CTIME {
X	($month, $day, $hour, $minute, $second) = @_;
X
X	++$minute if ($second >= 30);
X	sprintf("%02d/%02d %02d:%02d", $month, $day, $hour, $minute);
X}
END_OF_FILE
if test 3648 -ne `wc -c <'uuconstat'`; then
    echo shar: \"'uuconstat'\" unpacked with wrong size!
fi
chmod +x 'uuconstat'
# end of 'uuconstat'
fi
echo shar: End of shell archive.
exit 0

-- 
Brand X Industries Custodial, Refurbishing and Containment Service:
         When You Never, Ever Want To See It Again [tm]
     Chip Salzenberg   <chip@tct.com>, <uunet!pdn!tct!chip>

bill@twg.bc.ca (Bill Irwin) (04/17/91)

chip@tct.com (Chip Salzenberg) writes:

} Sure.  This one, "uuconstat", is for HDB UUCP.  Shar and enjoy.

Do you have this in a /bin/sh flavour?  I don't have Perl.

} --
}      Chip Salzenberg   <chip@tct.com>, <uunet!pdn!tct!chip>
-- 
Bill Irwin    -       The Westrheim Group     -    Vancouver, BC, Canada
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
uunet!van-bc!twg!bill     (604) 431-9600 (voice) |     Your Computer  
bill@twg.bc.ca            (604) 430-4329 (fax)   |    Systems Partner

vince@bcsaic.UUCP (Vince Skahan) (04/18/91)

In article <1991Apr16.070654.15375@pronto.mh.nl> Johan Vromans <jv@mh.nl> writes:
>
>>  Has anybody written a program (Perl?) to parse UUCP log files, to
>> give an idea how much each UUCP connection's being used, and for how
>> long?
>

Here's a HDB UUCP report generator in sh and awk.... it should scream if you
run it through a2p and use split rather than awk-isms   



#------------------------- cut here --------------------------------
#!/bin/sh
 
STATS="/usr/spool/uucp/.Admin/xferstats"
TMP="/tmp/hdb.tmp"
cat $STATS | sort > $TMP			# sort by system then process

awk '{

#
# ------------ sample data for incoming information ------------
#
#dsinc!uucp M (11/9-7:37:59) (C,701,1) [sio1] <- 475 / 5.933 secs, 80 bytes/sec
#
# ----------- sample data for outgoing information --------------
#
#dsinc!bcs212 M (11/9-8:02:16) (C,828,1) [sio1] -> 341 / 0.450 secs, 757 bytes/sec
#
#-------------------------------------------------------------------

BEGIN{

# initialize NAME to nothing
   NAME=" "

# print header

   printf ("\n                        Summary of UUCP Statistics\n")
   printf ("\n                               Total     Incoming     Outgoing      Percent\n")
   printf ("                      Bytes  Bytes/sec   Bytes/sec    Bytes/sec     Outgoing\n")
   printf ("                      -----  ----------  ---------    ---------     --------\n")
}
    
# step through the data file
# outcoming data indicated by ->
# ingoing data indicated by <-
# find which system by /systemname/

# incoming
/<-/ {
     time_in = time_in + $9 
     bytes_in = bytes_in + $7
     total_intime = total_intime + $9
     total_inbytes = total_inbytes + $7
    }                          

#outgoing
/->/ {
     time_out = time_out + $9 
     bytes_out = bytes_out + $7
     total_outtime = total_outtime + $9
     total_outbytes = total_outbytes + $7
    }
 
{

 if  ( $1 != NAME ) 
  {  
    if ( NAME != " " ) 
      {
      printf ("%15s   %7d %7d %11d %11d %13d  \n",  NAME, host_bytes, host_rate, host_inrate, host_outrate, host_pct_out);
      }
      NAME = $1
      host_intime = 0
      host_inbytes = 0
      host_outtime = 0
      host_outbytes = 0
      host_time = 0
      host_bytes = 0
      host_inrate = 0
      host_outrate = 0
      host_pct_out = 0
  }
 if (( ( $1 == NAME ) || ( $1 == " " ) ))
   {                                             
    if ( $6 == "<-" ) {
        host_intime = host_intime + $9 
        host_inbytes = host_inbytes + $7 
        }
     else {
         host_outtime = host_outtime + $9 
         host_outbytes = host_outbytes + $7
         }

    host_time = host_intime + host_outtime
    host_bytes = host_inbytes + host_outbytes

    if ( host_time > 0 ) {
        host_rate = host_bytes/host_time
        }
    if ( host_intime > 0 ) {
        host_inrate = host_inbytes/host_intime
        }
     if ( host_outtime > 0 ) {
        host_outrate = host_outbytes/host_outtime
        }
     if (host_bytes > 0 ) {
        host_pct_out = host_outbytes * 100 / host_bytes
       }
    }
}
END {

# summarize, print the last guy, and print the totals pretty

printf ("%15s   %7d %7d %11d %11d %13d  \n",  NAME, host_bytes, host_rate, host_inrate, host_outrate, host_pct_out)

total_bytes = total_inbytes + total_outbytes
total_time = total_intime + total_outtime

if ( total_time > 0 ) {
    total_rate = total_bytes/total_time
    }
if ( total_intime > 0 ) {
    total_inrate = total_inbytes/total_intime
    }
if ( total_outtime > 0 ) {
    total_outrate = total_outbytes/total_outtime
    }

if (( (total_inbytes > 0 ) || ( total_outbytes > 0 ) ))
  {
  total_bytes = total_inbytes + total_outbytes
  total_time = total_intime + total_outtime
  total_pct_out = total_outbytes * 100 / total_bytes
  printf("\n")
  printf("          total   %7d %7d %11d %11d %13d \n",  total_bytes, total_rate, total_inrate, total_outrate, total_pct_out);
  printf("\n")
  }

}' $TMP

rm $TMP


-- 
Vince Skahan   vince@atc.boeing.com  ...uw-beaver!bcsaic!vince

(what is there in the construction of mobile homes that seems 
	to attract tornadoes ??? )