#!/usr/bin/perl -w # lla.pl v 0.99p1 # Log Analyser for NS 4.11 LDAP and OpenLDAP # Author : Kris Buytaert # email : kb@ipng.be # rewritten: brian harrison , 2001-01-03 # Todo : # - Fancy html layout # - Open LDAP Support # - Fixing the 0 line in the foreach loops ... # - Cleanup Code # - ReImplement speed measurement # Done: # - Optimize Performance # - Make it possible to run multiple instances on different logfiles # together # Requirements # http://www.cpan.org/doc/FAQs/FAQ/PerlFAQ.html#Data_Dates # Get the modules from http://www.cpan.org/modules/by-module/Time/ # Time-modules-100.010301.tar.gz # Get the modules from http://www.cpan.org/modules/by-module/Date/ # DateManip-5.39.tar.gz require 5.004; use strict; use Getopt::Long; use Time::ParseDate; use Date::Calc qw(:all); use IO::File; use vars qw($debug $webbish); use vars qw(%originatinghost %tally); ########################## Sub Cleanup ################################# sub Cleanup { print "Entering Cleanup\n" if $debug; close DEBUG if $debug >= 3; } ########################## Sub OnScreen ################################# sub Onscreen { print "LDAP Log Analyser\n" if $debug; } ########################## Sub FewParam ################################# sub Fewparam { print <<'_EOH_'; LDAP Log Analyser is generating statistics from your LDAP log file Usage : lla.pl -w INPUTFILE [ > OUTPUTFILE ] Example. : lla.pl -w access > stats.html Copyright by Kris Buytaert 2000 kb@ipng.be This software is released under the terms of the GNU General Public License Main operation mode: -w Generate html output -t Generate flatfile output -m=kb@ipng.be Mail flatfile to emailaddress (may be specified multiple times) _EOH_ exit(); } # conn nrs herstarten / dag to be implemented # We will be analysing the log file checking for # - Originating connections $from[ip] to be implemented # - Bind dn to be implemented # - Srch to be implemented # Actually all possible operations to be implemented # $conn = Total Number of Connections # $sspeed = Sessions / Second # $ospeed = Operations / Second # $sconn = Connections / Session ########################## Sub Report ################################# sub Report { my (%total, %average, %counter); print "\n\nEntering Report\n" if $debug; if ($webbish) { print OUTPUT "LDAP Log Analyse Report"; } # print OUTPUT "Between $starttime and $endtime there were $conntotal sessions started\n"; # print OUTPUT "
" if $webbish; # print OUTPUT "Average speed is about $sspeed\n"; print OUTPUT "
" if $webbish; # Display all originating hosts .. sorted ... my $ip; foreach $ip (sort keys %originatinghost) { print OUTPUT "Connections from $ip = $originatinghost{$ip}\n"; print OUTPUT "
" if $webbish; } print OUTPUT "\n\n\n"; if ($debug >= 3) { my $t; foreach $t (sort keys %{$tally{operations}}) { print DEBUG "==============================="; print DEBUG "Nr Operations $t : $tally{operations}->{$t}\n"; } } my $type; foreach $type ("operations","totaltime","search","bind","result","res0","res32","res65","res103","mod","add") { my $id; while (($id) = each %{$tally{$type}}) { my $n = $tally{$type}->{$id}; # print OUTPUT "Numbers of $type in Session $id : $n\n"; # print OUTPUT "
" if $webbish; $total{$type} += $n; $counter{$type}++; } $average{$type} = $counter{$type} ? $total{$type} / $counter{$type} : 'undef'; print OUTPUT "Average $type per connection = $average{$type}\n"; print OUTPUT "
" if $webbish; } print OUTPUT "" if $webbish; # Mail plain text if needed ... } ######################### Sub Analyse_File ################################# sub Analyse_File { my (%firstline, %lastline); my %session; while (<>) { my ($conn) = / conn=(\d+) /; # Statistics on Originating IP if (/connection from (.*) to (.*)/) { # every time we see a new connection it is a new "session", # even if this conn number has been seen before. $session{$conn}++; $originatinghost{$1}++; } my $session = $session{$conn} || 0; my $id = join '.', $conn, $session; $firstline{$id} = $_ unless $firstline{$id}; $lastline{$id} = $_; # Counting Searches if (/SRCH/) { $tally{search}->{$id}++; } # Counting BIND if (/BIND/) { $tally{bind}->{$id}++; } # Analysing Result Type if (/RESULT/) { $tally{result}->{$id}++; } if (/RESULT err=(\d+)/) { $tally{"res" . $1}->{$id}++; } # MOD if (/MOD/) { $tally{mod}->{$id}++; } # ADD if (/ADD/) { $tally{add}->{$id}++; } } my $id; while (($id) = each %lastline) { # Number of operations in a session my ($op_count) = ($lastline{$id} =~ / op=(\d+) /); $tally{operations}->{$id} = $op_count; print "Nr Operations : $tally{operations}->{$id}\n" if $debug >= 2; print DEBUG "Nr Operations : $tally{operations}->{$id}\n" if $debug >= 3; # Calculating Session Start my ($starttime) = ($firstline{$id} =~ /\[(.*?)\]/); my $startseconds = parsedate($starttime); # Calculating Session End my ($endtime) = ($lastline{$id} =~ /\[(.*?)\]/); my $endseconds = parsedate($endtime); # Calculating Session Time $tally{totaltime}->{$id} = $endseconds - $startseconds; # Analysing Bind Types } undef %firstline; undef %lastline; } ############### Main ####################### # Onscreen; # 0 = no debugging # 1 = light debugging # 2 = code debugging # 3 = debugging to file $debug = 0; open DEBUG, ">debug.log" if $debug >= 3; # Could be done better with select() my $webbish = 0; # 1 = Results in html my $text = 0; # 1 = Results in plain text my @email = (); my $email; GetOptions("debug=i" => \$debug, "w|web|html" => \$webbish, "t|text" => \$text, "m|mail=s@" => \@email); unless ($webbish or $text or @email) { Fewparam(); } foreach (@ARGV) { unless (-e $_) { die "usage has changed. use \"> $_\" to specify the output file instead.\n"; } } if (@email) { my $MailSubject = "LDAP Log Analyse Report"; my $all_email = join ' ', @email; open OUTPUT, "| /bin/mail -s \"$MailSubject\" $all_email"; } else { open OUTPUT, ">&STDOUT"; } # print "Analysing input\n" if $debug; my $analyse_start = time; Analyse_File(); print "Analyse time: ", time - $analyse_start, "\n" if $debug; Report(); Cleanup();