From 3e2112a0af1e3572fd848f761d47f84250cf234d Mon Sep 17 00:00:00 2001 From: Mark Reynolds Date: Tue, 15 Jan 2013 15:36:33 -0500 Subject: [PATCH 125/225] Ticket 419 - logconv.pl - improve memory management Bug Description: logconv.pl memory usage is very high, and doesn't appear to be efficient. Fix Description: For verbose stats/hashes/arrays we now write this information to disk, and read it in and process it when printing the report. This dramatically improved memory growth when dealing with larger and larger log sets. Also updated the oids which some were incorrect, but many new oids were missing. Added stats for "Paged Searches", and "Max BER size exceeded". Finally, renamed most variables to be readable names, removed redundant counters, and other generic imrpovements. https://fedorahosted.org/389/ticket/419 Reviewed by: Noriko(Thanks!) (cherry picked from commit 16651d642bf6f7ba624f62cac867b495253b4f3f) (cherry picked from commit 9866682da7fb35e16922d94404c4265701fc797a) (cherry picked from commit aba08ee08425ac9dd9e914635714c8ae0ea6e54f) --- ldap/admin/src/logconv.pl | 2639 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2639 insertions(+) create mode 100755 ldap/admin/src/logconv.pl diff --git a/ldap/admin/src/logconv.pl b/ldap/admin/src/logconv.pl new file mode 100755 index 0000000..7ea7f09 --- /dev/null +++ b/ldap/admin/src/logconv.pl @@ -0,0 +1,2639 @@ +#!/usr/bin/env perl + +# +# BEGIN COPYRIGHT BLOCK +# This Program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; version 2 of the License. +# +# This Program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple +# Place, Suite 330, Boston, MA 02111-1307 USA. +# +# In addition, as a special exception, Red Hat, Inc. gives You the additional +# right to link the code of this Program with code not covered under the GNU +# General Public License ("Non-GPL Code") and to distribute linked combinations +# including the two, subject to the limitations in this paragraph. Non-GPL Code +# permitted under this exception must only link to the code of this Program +# through those well defined interfaces identified in the file named EXCEPTION +# found in the source code files (the "Approved Interfaces"). The files of +# Non-GPL Code may instantiate templates or use macros or inline functions from +# the Approved Interfaces without causing the resulting work to be covered by +# the GNU General Public License. Only Red Hat, Inc. may make changes or +# additions to the list of Approved Interfaces. You must obey the GNU General +# Public License in all respects for all of the Program code and other code used +# in conjunction with the Program except the Non-GPL Code covered by this +# exception. If you modify this file, you may extend this exception to your +# version of the file, but you are not obligated to do so. If you do not wish to +# provide this exception without modification, you must delete this exception +# statement from your version and license this file solely under the GPL without +# exception. +# +# +# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. +# Copyright (C) 2013 Red Hat, Inc. +# All rights reserved. +# END COPYRIGHT BLOCK +# + +# +# Check for usage +# +use Time::Local; +use IO::File; +use Getopt::Long; + +Getopt::Long::Configure ("bundling"); +Getopt::Long::Configure ("permute"); + +if ($#ARGV < 0){; +&displayUsage; +} + +####################################### +# # +# parse commandline switches # +# # +####################################### + +$file_count = 0; +$arg_count = 0; +$logversion = "7.0"; +$sizeCount = "20"; +$startFlag = 0; +$startTime = 0; +$endFlag = 0; +$endTime = 0; +$reportStats = ""; +$dataLocation = "/tmp"; +$s_stats = new_stats_block( ); +$m_stats = new_stats_block( ); + +GetOptions( + 'd|rootDN=s' => \$rootDN, + 'v|version' => sub { print "Access Log Analyzer v$logversion\n"; exit (0); }, + 'V|verbose' => sub { $verb = "yes"; }, + 'D|data=s' => \$dataLocation, + 'X|excludeIP=s' => \$excludeIP[$xi++], + 's|sizeLimit=s' => \$sizeCount, + 'S|startTime=s' => \$startTime, + 'E|endTime=s' => \$endTime, + 'B|bind=s' => sub { $reportBinds = "yes"; $bindReportDN=($_[1]) }, + 'm|reportFileSecs=s' => sub { my ($opt,$value) = @_; $s_stats = new_stats_block($value); $reportStats = "-m";}, + 'M|reportFileMins=s' => sub { my ($opt,$value) = @_; $m_stats = new_stats_block($value); $reportStats = "-M";}, + 'h|help' => sub { displayUsage() }, + # usage options '-efcibaltnxgjuiryp' + 'e' => sub { $usage = $usage . "e"; }, + 'f' => sub { $usage = $usage . "f"; }, + 'c' => sub { $usage = $usage . "c"; }, + 'i' => sub { $usage = $usage . "i"; }, + 'b' => sub { $usage = $usage . "b"; }, + 'a' => sub { $usage = $usage . "a"; }, + 'l' => sub { $usage = $usage . "l"; }, + 't' => sub { $usage = $usage . "t"; }, + 'n' => sub { $usage = $usage . "n"; }, + 'x' => sub { $usage = $usage . "x"; }, + 'g' => sub { $usage = $usage . "g"; }, + 'j' => sub { $usage = $usage . "j"; }, + 'u' => sub { $usage = $usage . "u"; }, + 'r' => sub { $usage = $usage . "r"; }, + 'y' => sub { $usage = $usage . "y"; }, + 'p' => sub { $usage = $usage . "p"; } +); + +# +# setup the report Bind DN if any +# +if($reportBinds eq "yes"){ + $bindReportDN =~ tr/A-Z/a-z/; + if($bindReportDN eq "all"){ + $bindReportDN = ""; + } + if($bindReportDN eq "anonymous"){ + $bindReportDN = "Anonymous"; + } +} + +# +# set the default root DN +# +if($rootDN eq ""){ + $rootDN = "cn=directory manager"; +} + +# +# get the logs +# +while($arg_count <= $#ARGV){ + $files[$file_count] = $ARGV[$arg_count]; + $file_count++; + $arg_count++; +} + +if($file_count == 0){ + if($reportStats){ + print "Usage error for option $reportStats, either the output file or access log is missing!\n\n"; + } else { + print "There are no access logs specified!\n\n"; + } + exit 1; +} + +if ($sizeCount eq "all"){$sizeCount = "100000";} + +####################################### +# # +# Initialize Arrays and variables # +# # +####################################### + +print "\nAccess Log Analyzer $logversion\n"; +print "\nCommand: logconv.pl @ARGV\n\n"; + +$rootDNBindCount = 0; +$anonymousBindCount = 0; +$unindexedSrchCount = 0; +$vlvNotesCount= 0; +$srchCount = 0; +$fdTaken = 0; +$fdReturned = 0; +$highestFdTaken = 0; +$unbindCount = 0; +$cmpCount = 0; +$modCount = 0; +$delCount = 0; +$addCount = 0; +$modrdnCount = 0; +$abandonCount = 0; +$extopCount = 0; +$vlvCount = 0; +$errorCount = 0; +$proxiedAuthCount = 0; +$serverRestartCount = 0; +$resourceUnavailCount = 0; +$brokenPipeCount = 0; +$v2BindCount = 0; +$v3BindCount = 0; +$vlvSortCount = 0; +$connResetByPeerCount = 0; +$isVlvNotes = 0; +$successCount = 0; +$sslCount = 0; +$sslClientBindCount = 0; +$sslClientFailedCount = 0; +$objectclassTopCount= 0; +$pagedSearchCount = 0; +$bindCount = 0; +$filterCount = 0; +$baseCount = 0; +$scopeCount = 0; +$allOps = 0; +$allResults = 0; +$badPwdCount = 0; +$saslBindCount = 0; +$internalOpCount = 0; +$entryOpCount = 0; +$referralCount = 0; +$anyAttrs = 0; +$persistentSrchCount = 0; +$maxBerSizeCount = 0; +$connectionCount = 0; +$timerange = 0; +$simConnection = 0; +$maxsimConnection = 0; +$firstFile = 1; +$elapsedDays = 0; +$logCount = 0; +$limit = 25000; # number of lines processed to trigger output + +# hash files +$ATTR = "$dataLocation/attr.logconv"; +$RC = "$dataLocation/rc.logconv"; +$SRC = "$dataLocation/src.logconv"; +$RSRC = "$dataLocation/rsrc.logconv"; +$EXCOUNT = "$dataLocation/excount.logconv"; +$CONN_HASH = "$dataLocation/conn_hash.logconv"; +$IP_HASH = "$dataLocation/ip_hash.logconv"; +$CONNCOUNT = "$dataLocation/conncount.logconv"; +$NENTRIES = "$dataLocation/nentries.logconv"; +$FILTER = "$dataLocation/filter.logconv"; +$BASE = "$dataLocation/base.logconv"; +$DS6XBADPWD = "$dataLocation/ds6xbadpwd.logconv"; +$SASLMECH = "$dataLocation/saslmech.logconv"; +$BINDLIST = "$dataLocation/bindlist.logconv"; +$ETIME = "$dataLocation/etime.logconv"; +$OID = "$dataLocation/oid.logconv"; + +# array files +$SRCH_CONN = "$dataLocation/srchconn.logconv"; +$SRCH_OP = "$dataLocation/srchop.logconv"; +$DEL_CONN = "$dataLocation/delconn.logconv"; +$DEL_OP = "$dataLocation/delop.logconv"; +$MOD_CONN = "$dataLocation/modconn.logconv"; +$MOD_OP = "$dataLocation/modop.logconv"; +$ADD_CONN = "$dataLocation/addconn.logconv"; +$ADD_OP = "$dataLocation/addop.logconv"; +$MODRDN_CONN = "$dataLocation/modrdnconn.logconv"; +$MODRDN_OP = "$dataLocation/modrdnop.logconv"; +$CMP_CONN = "$dataLocation/cmpconn.logconv"; +$CMP_OP = "$dataLocation/cmpop.logconv"; +$TARGET_CONN = "$dataLocation/targetconn.logconv"; +$TARGET_OP = "$dataLocation/targetop.logconv"; +$MSGID = "$dataLocation/msgid.logconv"; +$BIND_CONN = "$dataLocation/bindconn.logconv"; +$BIND_OP = "$dataLocation/bindop.logconv"; +$UNBIND_CONN = "$dataLocation/unbindconn.logconv"; +$UNBIND_OP = "$dataLocation/unbindop.logconv"; +$EXT_CONN = "$dataLocation/extconn.logconv"; +$EXT_OP = "$dataLocation/extop.logconv"; +$NOTES_ETIME = "$dataLocation/notesetime.logconv"; +$NOTES_CONN = "$dataLocation/notesconn.logconv"; +$NOTES_OP = "$dataLocation/notesop.logconv"; +$NOTES_TIME = "$dataLocation/notestime.logconv"; +$NOTES_NENTRIES = "$dataLocation/notesnentries.logconv"; +$BADPWDCONN = "$dataLocation/badpwdconn.logconv"; +$BADPWDOP = "$dataLocation/badpwdop.logconv"; +$BADPWDIP = "$dataLocation/badpwdip.logconv"; + +# info files +$BINDINFO = "$dataLocation/bindinfo.logconv"; +$BASEINFO = "$dataLocation/baseinfo.logconv"; +$FILTERINFO = "$dataLocation/filterinfo.logconv"; +$SCOPEINFO = "$dataLocation/scopeinfo.logconv"; + +$err[0] = "Successful Operations\n"; +$err[1] = "Operations Error(s)\n"; +$err[2] = "Protocal Errors\n"; +$err[3] = "Time Limit Exceeded\n"; +$err[4] = "Size Limit Exceeded\n"; +$err[5] = "Compare False\n"; +$err[6] = "Compare True\n"; +$err[7] = "Strong Authentication Not Supported\n"; +$err[8] = "Strong Authentication Required\n"; +$err[9] = "Partial Results\n"; +$err[10] = "Referral Received\n"; +$err[11] = "Administrative Limit Exceeded (Look Through Limit)\n"; +$err[12] = "Unavailable Critical Extension\n"; +$err[13] = "Confidentiality Required\n"; +$err[14] = "SASL Bind in Progress\n"; +$err[16] = "No Such Attribute\n"; +$err[17] = "Undefined Type\n"; +$err[18] = "Inappropriate Matching\n"; +$err[19] = "Constraint Violation\n"; +$err[20] = "Type or Value Exists\n"; +$err[21] = "Invalid Syntax\n"; +$err[32] = "No Such Object\n"; +$err[33] = "Alias Problem\n"; +$err[34] = "Invalid DN Syntax\n"; +$err[35] = "Is Leaf\n"; +$err[36] = "Alias Deref Problem\n"; +$err[48] = "Inappropriate Authentication (No password presented, etc)\n"; +$err[49] = "Invalid Credentials (Bad Password)\n"; +$err[50] = "Insufficent (write) Privledges\n"; +$err[51] = "Busy\n"; +$err[52] = "Unavailable\n"; +$err[53] = "Unwilling To Perform\n"; +$err[54] = "Loop Detected\n"; +$err[60] = "Sort Control Missing\n"; +$err[61] = "Index Range Error\n"; +$err[64] = "Naming Violation\n"; +$err[65] = "Objectclass Violation\n"; +$err[66] = "Not Allowed on Non Leaf\n"; +$err[67] = "Not Allowed on RDN\n"; +$err[68] = "Already Exists\n"; +$err[69] = "No Objectclass Mods\n"; +$err[70] = "Results Too Large\n"; +$err[71] = "Effect Multiple DSA's\n"; +$err[80] = "Other :-)\n"; +$err[81] = "Server Down\n"; +$err[82] = "Local Error\n"; +$err[83] = "Encoding Error\n"; +$err[84] = "Decoding Error\n"; +$err[85] = "Timeout\n"; +$err[86] = "Authentication Unknown\n"; +$err[87] = "Filter Error\n"; +$err[88] = "User Canceled\n"; +$err[89] = "Parameter Error\n"; +$err[90] = "No Memory\n"; +$err[91] = "Connect Error\n"; +$err[92] = "Not Supported\n"; +$err[93] = "Control Not Found\n"; +$err[94] = "No Results Returned\n"; +$err[95] = "More Results To Return\n"; +$err[96] = "Client Loop\n"; +$err[97] = "Referral Limit Exceeded\n"; + + +$conn{"A1"} = "A1"; +$conn{"B1"} = "B1"; +$conn{"B4"} = "B4"; +$conn{"T1"} = "T1"; +$conn{"T2"} = "T2"; +$conn{"B2"} = "B2"; +$conn{"B3"} = "B3"; +$conn{"R1"} = "R1"; +$conn{"P1"} = "P1"; +$conn{"P2"} = "P2"; +$conn{"U1"} = "U1"; + +$connmsg{"A1"} = "Client Aborted Connections"; +$connmsg{"B1"} = "Bad Ber Tag Encountered"; +$connmsg{"B4"} = "Server failed to flush data (response) back to Client"; +$connmsg{"T1"} = "Idle Timeout Exceeded"; +$connmsg{"T2"} = "IO Block Timeout Exceeded or NTSSL Timeout"; +$connmsg{"B2"} = "Ber Too Big"; +$connmsg{"B3"} = "Ber Peek"; +$connmsg{"R1"} = "Revents"; +$connmsg{"P1"} = "Plugin"; +$connmsg{"P2"} = "Poll"; +$connmsg{"U1"} = "Cleanly Closed Connections"; + +%monthname = ( + "Jan" => 0, + "Feb" => 1, + "Mar" => 2, + "Apr" => 3, + "May" => 4, + "Jun" => 5, + "Jul" => 6, + "Aug" => 7, + "Sep" => 8, + "Oct" => 9, + "Nov" => 10, + "Dec" => 11, + +); + +openDataFiles(); + +########################################## +# # +# Parse Access Logs # +# # +########################################## + +if ($files[$#files] =~ m/access.rotationinfo/) { $file_count--; } + +print "Processing $file_count Access Log(s)...\n\n"; + +#print "Filename\t\t\t Total Lines\n"; +#print "--------------------------------------------------\n"; + +if ($file_count > 1 && $files[0] =~ /\/access$/){ + $files[$file_count] = $files[0]; + $file_count++; + $skipFirstFile = 1; +} +$logCount = $file_count; + +for ($count=0; $count < $file_count; $count++){ + # we moved access to the end of the list, so if its the first file skip it + if($file_count > 1 && $count == 0 && $skipFirstFile == 1){ + next; + } + $logsize = `wc -l $files[$count]`; + $logsize =~ /([0-9]+)/; + $linesProcessed = 0; $lineBlockCount = 0; + $logCount--; + if($logCount < 10 ){ + # add a zero for formatting purposes + $logCountStr = "0" . $logCount; + } else { + $logCountStr = $logCount; + } + print sprintf "[%s] %-30s\tlines: %7s\n",$logCountStr, $files[$count], $1; + + open(LOG,"$files[$count]") or do { openFailed($!, $files[$count]) }; + $firstline = "yes"; + while(){ + unless ($endFlag) { + if ($firstline eq "yes"){ + if (/^\[/) { + $logline = $_; + $firstline = "no"; + } + $linesProcessed++;$lineBlockCount++; + } elsif (/^\[/ && $firstline eq "no"){ + &parseLine(); + $logline = $_; + } else { + $logline = $logline . $_; + $logline =~ s/\n//; + } + } + } + &parseLine(); + close (LOG); + print_stats_block( $s_stats ); + print_stats_block( $m_stats ); + $totalLineCount = $totalLineCount + $linesProcessed; + if($linesProcessed => $limit){print sprintf " %10s Lines Processed\n\n",--$linesProcessed;} +} + +print "\n\nTotal Log Lines Analysed: " . ($totalLineCount - 1) . "\n"; + +$allOps = $srchCount + $modCount + $addCount + $cmpCount + $delCount + $modrdnCount + $bindCount + $extopCount + $abandonCount + $vlvCount; + +################################################################## +# # +# Calculate the total elapsed time of the processed access logs # +# # +################################################################## + +# if we are using startTime & endTime then we need to clean it up for our processing + +if($startTime){ + if ($start =~ / *([0-9a-z:\/]+)/i){$start=$1;} +} +if($endTime){ + if ($end =~ / *([0-9a-z:\/]+)/i){$end =$1;} +} + +# +# Get the start time in seconds +# + +$logStart = $start; + +if ($logStart =~ / *([0-9A-Z\/]+)/i ){ + $logDate = $1; + @dateComps = split /\//, $logDate; + + $timeMonth = 1 +$monthname{$dateComps[1]}; + $timeMonth = $timeMonth * 3600 *24 * 30; + $timeDay= $dateComps[0] * 3600 *24; + $timeYear = $dateComps[2] *365 * 3600 * 24; + $dateTotal = $timeMonth + $timeDay + $timeYear; +} + +if ($logStart =~ / *(:[0-9:]+)/i ){ + $logTime = $1; + @timeComps = split /:/, $logTime; + + $timeHour = $timeComps[1] * 3600; + $timeMinute = $timeComps[2] *60; + $timeSecond = $timeComps[3]; + $timeTotal = $timeHour + $timeMinute + $timeSecond; +} + +$startTotal = $timeTotal + $dateTotal; + +# +# Get the end time in seconds +# + +$logEnd = $end; + +if ($logEnd =~ / *([0-9A-Z\/]+)/i ){ + $logDate = $1; + @dateComps = split /\//, $logDate; + + $endDay = $dateComps[0] *3600 * 24; + $endMonth = 1 + $monthname{$dateComps[1]}; + $endMonth = $endMonth * 3600 * 24 * 30; + $endYear = $endTotal + $dateComps[2] *365 * 3600 * 24 ; + $dateTotal = $endDay + $endMonth + $endYear; +} + +if ($logEnd =~ / *(:[0-9:]+)/i ){ + $logTime = $1; + @timeComps = split /:/, $logTime; + + $endHour = $timeComps[1] * 3600; + $endMinute = $timeComps[2] *60; + $endSecond = $timeComps[3]; + $timeTotal = $endHour + $endMinute + $endSecond; +} + +$endTotal = $timeTotal + $dateTotal; + +# +# Tally the numbers +# +$totalTimeInSecs = $endTotal - $startTotal; +$remainingTimeInSecs = $totalTimeInSecs; + +# +# Calculate the elapsed time +# + +# days +while(($remainingTimeInSecs - 86400) > 0){ + $elapsedDays++; + $remainingTimeInSecs = $remainingTimeInSecs - 86400; + +} + +# hours +while(($remainingTimeInSecs - 3600) > 0){ + $elapsedHours++; + $remainingTimeInSecs = $remainingTimeInSecs - 3600; +} + +# minutes +while($remainingTimeInSecs - 60 > 0){ + $elapsedMinutes++; + $remainingTimeInSecs = $remainingTimeInSecs - 60; +} + +# seconds +$elapsedSeconds = $remainingTimeInSecs; + +# Initialize empty values +if($elapsedHours eq ""){ + $elapsedHours = "0"; +} +if($elapsedMinutes eq ""){ + $elapsedMinutes = "0"; +} +if($elapsedSeconds eq ""){ + $elapsedSeconds = "0"; +} + +&closeDataFiles(); + + +##################################### +# # +# Display Basic Results # +# # +##################################### + + +print "\n\n----------- Access Log Output ------------\n"; +print "\nStart of Logs: $start\n"; +print "End of Logs: $end\n\n"; + +if($elapsedDays eq "0"){ + print "Processed Log Time: $elapsedHours Hours, $elapsedMinutes Minutes, $elapsedSeconds Seconds\n\n"; +} else { + print "Processed Log Time: $elapsedDays Days, $elapsedHours Hours, $elapsedMinutes Minutes, $elapsedSeconds Seconds\n\n"; +} + +# +# Check here if we are producing any unqiue reports +# + +if($reportBinds eq "yes"){ + &displayBindReport(); +} + +# +# Continue with standard report +# + +print "Restarts: $serverRestartCount\n"; +print "Total Connections: $connectionCount\n"; +print "SSL Connections: $sslCount\n"; +print "Peak Concurrent Connections: $maxsimConnection\n"; +print "Total Operations: $allOps\n"; +print "Total Results: $allResults\n"; +if ($allOps ne "0"){ + print sprintf "Overall Performance: %.1f%\n\n" , ($perf = ($tmp = ($allResults / $allOps)*100) > 100 ? 100.0 : $tmp) ; + } +else { + print "Overall Performance: No Operations to evaluate\n\n"; +} + +$searchStat = sprintf "(%.2f/sec) (%.2f/min)\n",($srchCount / $totalTimeInSecs), $srchCount / ($totalTimeInSecs/60); +$modStat = sprintf "(%.2f/sec) (%.2f/min)\n",$modCount / $totalTimeInSecs, $modCount/($totalTimeInSecs/60); +$addStat = sprintf "(%.2f/sec) (%.2f/min)\n",$addCount/$totalTimeInSecs, $addCount/($totalTimeInSecs/60); +$deleteStat = sprintf "(%.2f/sec) (%.2f/min)\n",$delCount/$totalTimeInSecs, $delCount/($totalTimeInSecs/60); +$modrdnStat = sprintf "(%.2f/sec) (%.2f/min)\n",$modrdnCount/$totalTimeInSecs, $modrdnCount/($totalTimeInSecs/60); +$compareStat = sprintf "(%.2f/sec) (%.2f/min)\n",$cmpCount/$totalTimeInSecs, $cmpCount/($totalTimeInSecs/60); +$bindCountStat = sprintf "(%.2f/sec) (%.2f/min)\n",$bindCount/$totalTimeInSecs, $bindCount/($totalTimeInSecs/60); + +format STDOUT = +Searches: @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<< + $srchCount, $searchStat +Modifications: @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<< + $modCount, $modStat +Adds: @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<< + $addCount, $addStat +Deletes: @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<< + $delCount, $deleteStat +Mod RDNs: @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<< + $modrdnCount, $modrdnStat +Compares: @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<< + $cmpCount, $compareStat +Binds: @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<< + $bindCount $bindCountStat +. +write STDOUT; + +print "\n"; +print "Proxied Auth Operations: $proxiedAuthCount\n"; +print "Persistent Searches: $persistentSrchCount\n"; +print "Internal Operations: $internalOpCount\n"; +print "Entry Operations: $entryOpCount\n"; +print "Extended Operations: $extopCount\n"; +print "Abandoned Requests: $abandonCount\n"; +print "Smart Referrals Received: $referralCount\n"; +print "\n"; +print "VLV Operations: $vlvCount\n"; +print "VLV Unindexed Searches: $vlvNotesCount\n"; +print "SORT Operations: $vlvSortCount\n"; +print "\n"; +print "Entire Search Base Queries: $objectclassTopCount\n"; +print "Paged Searches: $pagedSearchCount\n"; +print "Unindexed Searches: $unindexedSrchCount\n"; +if ($verb eq "yes" || $usage =~ /u/){ + if ($unindexedSrchCount > 0){ + %conn_hash = getHashFromFile($CONN_HASH); + @notesConn = getArrayFromFile($NOTES_CONN); + @notesOp = getArrayFromFile($NOTES_OP); + @notesEtime = getArrayFromFile($NOTES_ETIME); + @notesTime = getArrayFromFile($NOTES_TIME); + @notesNentries = getArrayFromFile($NOTES_NENTRIES); + getInfoArraysFromFile($BASEINFO); + @base_val = @fileArray1; + @base_conn = @fileArray2; + @base_op = @fileArray3; + getInfoArraysFromFile($SCOPEINFO); + @scope_val = @fileArray1; + @scope_conn = @fileArray2; + @scope_op = @fileArray3; + getInfoArraysFromFile($FILTERINFO); + @filter_val = @fileArray1; + @filter_conn = @fileArray2; + @filter_op = @fileArray3; + + $notesCount = "1"; + for ($n = 0; $n <= $#notesEtime; $n++){ + @alreadyseenDN = (); + if($conn_hash{$notesConn[$n]} eq ""){ + $unindexedIp = "?"; + } else { + $unindexedIp = $conn_hash{$notesConn[$n]}; + } + print "\n Unindexed Search #".$notesCount."\n"; $notesCount++; + print " - Date/Time: $notesTime[$n]\n"; + print " - Connection Number: $notesConn[$n]\n"; + print " - Operation Number: $notesOp[$n]\n"; + print " - Etime: $notesEtime[$n]\n"; + print " - Nentries: $notesNentries[$n]\n"; + print " - IP Address: $unindexedIp\n"; + + for ($nnn = 0; $nnn < $baseCount; $nnn++){ + if ($notesConn[$n] eq $base_conn[$nnn] && $notesOp[$n] eq $base_op[$nnn]){ + print " - Search Base: $base_val[$nnn]\n"; + last; + } + } + for ($nnn = 0; $nnn < $scopeCount; $nnn++){ + if ($notesConn[$n] eq $scope_conn[$nnn] && $notesOp[$n] eq $scope_op[$nnn]){ + print " - Search Scope: $scope_val[$nnn]\n"; + last; + } + } + for ($nnn = 0; $nnn < $filterCount; $nnn++){ + if ($notesConn[$n] eq $filter_conn[$nnn] && $notesOp[$n] eq $filter_op[$nnn]){ + print " - Search Filter: $filter_val[$nnn]\n"; + last; + } + } + } + undef %conn_hash; + undef @notesConn; + undef @notesOp; + undef @notesEtime; + undef @notesTime; + undef @notesNentries; + undef @notesIp; + undef @filter_val; + undef @filter_conn; + undef @filter_op; + undef @base_val; + undef @base_conn; + undef @base_op; + undef @scope_val; + undef @scope_conn; + undef @scope_op; + } +} # end of unindexed search report + +print "\n"; +print "FDs Taken: $fdTaken\n"; +print "FDs Returned: $fdReturned\n"; +print "Highest FD Taken: $highestFdTaken\n\n"; +print "Broken Pipes: $brokenPipeCount\n"; +if ($brokenPipeCount > 0){ + foreach $key (sort { $rc{$b} <=> $rc{$a} } keys %rc) { + if ($rc{$key} > 0){ + if ($conn{$key} eq ""){$conn{$key} = "**Unknown**";} + push @etext, sprintf " - %-4s (%2s) %-40s\n",$rc{$key},$conn{$key},$connmsg{$key +}; + } + } + print @etext; + print "\n"; +} + +print "Connections Reset By Peer: $connResetByPeerCount\n"; +if ($connResetByPeerCount > 0){ + foreach $key (sort { $src{$b} <=> $src{$a} } keys %src) { + if ($src{$key} > 0){ + if ($conn{$key} eq ""){$conn{$key} = "**Unknown**";} + push @retext, sprintf " - %-4s (%2s) %-40s\n",$src{$key},$conn{$key},$connmsg{$key +}; + } + } + print @retext; + print "\n"; +} + +print "Resource Unavailable: $resourceUnavailCount\n"; +if ($resourceUnavailCount > 0){ + foreach $key (sort { $rsrc{$b} <=> $rsrc{$a} } keys %rsrc) { + if ($rsrc{$key} > 0){ + if ($conn{$key} eq ""){$conn{$key} = "**Resource Issue**";} + push @rtext, sprintf " - %-4s (%2s) %-40s\n",$rsrc{$key},$conn{$key},$connmsg{$key}; + } + } + print @rtext; +} +print "Max BER Size Exceeded: $maxBerSizeCount\n"; +print "\n"; +print "Binds: $bindCount\n"; +print "Unbinds: $unbindCount\n"; +print "\n LDAP v2 Binds: $v2BindCount\n"; +print " LDAP v3 Binds: $v3BindCount\n"; +print " SSL Client Binds: $sslClientBindCount\n"; +print " Failed SSL Client Binds: $sslClientFailedCount\n"; +print " SASL Binds: $saslBindCount\n"; +if ($saslBindCount > 0){ + foreach $saslb ( sort {$saslmech{$b} <=> $saslmech{$a} } (keys %saslmech) ){ + printf " %-4s %-12s\n",$saslmech{$saslb}, $saslb; + } +} + +print "\n Directory Manager Binds: $rootDNBindCount\n"; +print " Anonymous Binds: $anonymousBindCount\n"; +$otherBindCount = $bindCount -($rootDNBindCount + $anonymousBindCount); +print " Other Binds: $otherBindCount\n\n"; + +########################################################################## +# Verbose Logging Section # +########################################################################## + +################################### +# # +# Display Connection Latency # +# # +################################### + +if ($verb eq "yes" || $usage =~ /y/){ + print "\n\n----- Connection Latency Details -----\n\n"; + print " (in seconds)\t\t<=1\t2\t3\t4-5\t6-10\t11-15\t>15\n"; + print " --------------------------------------------------------------------------\n"; + print " (# of connections)\t"; + for ($i=0; $i <=$#latency; $i++) { + print "$latency[$i]\t"; + } +} + +################################### +# # +# Display Open Connections # +# # +################################### + +if ($verb eq "yes" || $usage =~ /p/){ + if ($openConnection[0] ne ""){ + print "\n\n----- Current Open Connection IDs ----- \n\n"; + for ($i=0; $i <= $#openConnection ; $i++) { + if ($openConnection[$i]) { + print "Conn Number: $i (" . getIPfromConn($i) . ")\n"; + } + } + } +} + +################################### +# # +# Display Error Codes # +# # +################################### + +if ($usage =~ /e/i || $verb eq "yes"){ + print "\n\n----- Errors -----\n"; + + %er = sort( {$b <=> $a} %er); + for ($i = 0; $i<98; $i++){ + if ($err[$i] ne "" && $errorCode[$i] >0) { + push @errtext, sprintf "%-8s %12s %-25s","err=$i",$errorCode[$i],$err[$i]; + } + } + + for ($i = 0; $i < $#errtext; $i++){ + for ($ii = 0; $ii < $#errtext; $ii++){ + $yy="0"; + $zz="0"; + while ($errtext[$ii] =~ /(\w+)\s/g){ + $errornum[$yy]="$1"; + $yy++; + } + while ($errtext[$ii+1] =~ /(\w+)\s/g){ + $errornum2[$zz]="$1"; + $zz++; + } + if ($errornum2[1] > $errornum[1]){ + $tmp = $errtext[$ii]; + $errtext[$ii] = $errtext[$ii+1]; + $errtext[$ii+1] = $tmp; + } + } + } + for ($i = 0; $i <= $#errtext; $i++){ + $errtext[$i] =~ s/\n//g; + print "\n" . $errtext[$i]; + } +} + +#################################### +# # +# Print Failed Logins # +# # +#################################### + +if ($verb eq "yes" || $usage =~ /f/ ){ + if ($badPwdCount > 0){ + print "\n\n----- Top $sizeCount Failed Logins ------\n\n"; + + if ($ds6x eq "true"){ + %ds6xbadpwd = getCounterHashFromFile($DS6XBADPWD); + $ds6loop = 0; + foreach $ds6bp (sort { $ds6xbadpwd{$b} <=> $ds6xbadpwd{$a} } keys %ds6xbadpwd) { + if ($eloop > $sizeCount){ last; } + printf "%-4s %-40s\n", $ds6xbadpwd{$ds6bp}, $ds6bp; + $ds6loop++; + } + undef %ds6xbadpwd; + } else { + getInfoArraysFromFile($BINDINFO); + @bindVal = @fileArray1; + @bindConn = @fileArray2; + @bindOp = @fileArray3; + @badPasswordConn = getArrayFromFile($BADPWDCONN); + @badPasswordOp = getArrayFromFile($BADPWDOP); + @badPasswordIp = getArrayFromFile($BADPWDIP); + for ($ii =0 ; $ii < $badPwdCount; $ii++){ + for ($i = 0; $i < $bindCount; $i++){ + if ($badPasswordConn[$ii] eq $bindConn[$i] && $badPasswordOp[$ii] eq $bindOp[$i] ){ + $badPassword{ "$bindVal[$i]" } = $badPassword{ "$bindVal[$i]" } + 1; + } + } + } + # sort the new hash of $badPassword{} + $bpTotal = 0; + $bpCount = 0; + foreach $badpw (sort {$badPassword{$b} <=> $badPassword{$a} } keys %badPassword){ + if ($bpCount > $sizeCount){ last;} + $bpCount++; + $bpTotal = $bpTotal + $badPassword{"$badpw"}; + printf "%-4s %-40s\n", $badPassword{"$badpw"}, $badpw; + } + print "\nFrom the IP address(s) :\n\n"; + for ($i=0; $i<$badPwdCount; $i++) { + print "\t\t$badPasswordIp[$i]\n"; + } + if ($bpTotal > $badPwdCount){ + print "\n** Warning : Wrongly reported failed login attempts : ". ($bpTotal - $badPwdCount) . "\n"; + } + undef @bindVal; + undef @bindConn; + undef @bindOp; + undef @badPasswordConn; + undef @badPasswordOp; + undef @badPasswordIp; + } # this ends the if $ds6x = true + } +} + +#################################### +# # +# Print Connection Codes # +# # +#################################### + + +if ($connCodeCount > 0){ + if ($usage =~ /c/i || $verb eq "yes"){ + print "\n\n----- Total Connection Codes -----\n\n"; + %conncount = &getCounterHashFromFile($CONNCOUNT); + + foreach $key (sort { $conncount{$b} <=> $conncount{$a} } keys %conncount) { + if ($conncount{$key} > 0){ + push @conntext, sprintf "%-4s %6s %-40s\n",$key,$conncount{$key},$connmsg{ $key }; + } + } + print @conntext; + undef %conncount; + } +} + +######################################## +# # +# Gather and Process all unique IPs # +# # +######################################## + +if ($usage =~ /i/i || $verb eq "yes"){ + %ip_hash = getTwoDimHashFromFile($IP_HASH); + %exCount = getCounterHashFromFile($EXCOUNT); + @ipkeys = keys %ip_hash; + @exxCount = keys %exCount; + $ip_count = ($#ipkeys + 1)-($#exxCount + 1); + if ($ip_count > 0){ + print "\n\n----- Top $sizeCount Clients -----\n\n"; + print "Number of Clients: $ip_count\n\n"; + foreach $key (sort { $ip_hash{$b}{"count"} <=> $ip_hash{$a}{"count"} } keys %ip_hash) { + $exc = "no"; + if ($ccount > $sizeCount){ last;} + $ccount++; + for ($xxx =0; $xxx <= $#excludeIP; $xxx++){ + if ($excludeIP[$xxx] eq $key){$exc = "yes";} + } + if ($exc ne "yes"){ + if ($ip_hash{ $key }{"count"} eq ""){$ip_hash{ $key }{"count"} = "?";} + printf "[%s] Client: %s\n",$ccount, $key; + printf "%10s - Connections\n", $ip_hash{ $key }{"count"}; + foreach $code (sort { $ip_hash{ $key }{$b} <=> $ip_hash{ $key }{$a} } keys %{$ip_hash{ $key }}) { + if ($code eq 'count' ) { next; } + printf "%10s - %s (%s)\n", $ip_hash{ $key }{ $code }, $code, $connmsg{ $code }; + } + print "\n"; + } + } + } + undef %exCount; + undef %ip_hash; +} + +################################### +# # +# Gather All unique Bind DN's # +# # +################################### + +if ($usage =~ /b/i || $verb eq "yes"){ + %bindlist = getCounterHashFromFile($BINDLIST); + @bindkeys = keys %bindlist; + $bind_count = $#bindkeys + 1; + if ($bind_count > 0){ + print "\n\n----- Top $sizeCount Bind DN's -----\n\n"; + print "Number of Unique Bind DN's: $bind_count\n\n"; + $bindcount = 0; + foreach $dn (sort { $bindlist{$b} <=> $bindlist{$a} } keys %bindlist) { + if ($bindcount < $sizeCount){ + printf "%-8s %-40s\n", $bindlist{ $dn },$dn; + } + $bindcount++; + } + } + undef %bindlist; +} + +######################################### +# # +# Gather and process search bases # +# # +######################################### + +if ($usage =~ /a/i || $verb eq "yes"){ + %base = getCounterHashFromFile($BASE); + @basekeys = keys %base; + $base_count = $#basekeys + 1; + if ($base_count > 0){ + print "\n\n----- Top $sizeCount Search Bases -----\n\n"; + print "Number of Unique Search Bases: $base_count\n\n"; + $basecount = 0; + foreach $bas (sort { $base{$b} <=> $base{$a} } keys %base) { + if ($basecount < $sizeCount){ + printf "%-8s %-40s\n", $base{ $bas },$bas; + } + $basecount++; + } + } + undef %base; +} + +######################################### +# # +# Gather and process search filters # +# # +######################################### + +if ($usage =~ /l/ || $verb eq "yes"){ + %filter = getCounterHashFromFile($FILTER); + @filterkeys = keys %filter; + $filter_count = $#filterkeys + 1; + if ($filter_count > 0){ + print "\n\n----- Top $sizeCount Search Filters -----\n"; + print "\nNumber of Unique Search Filters: $filter_count\n\n"; + $filtercount = 0; + foreach $filt (sort { $filter{$b} <=> $filter{$a} } keys %filter){ + if ($filtercount < $sizeCount){ + printf "%-8s %-40s\n", $filter{$filt}, $filt; + } + $filtercount++; + } + } + undef %filter; +} + +######################################### +# # +# Gather and Process the unique etimes # +# # +######################################### + +if ($usage =~ /t/i || $verb eq "yes"){ + %etime = getCounterHashFromFile($ETIME); + # + # print most often etimes + # + print "\n\n----- Top $sizeCount Most Frequent etimes -----\n\n"; + $eloop = 0; + foreach $et (sort { $etime{$b} <=> $etime{$a} } keys %etime) { + if ($eloop == $sizeCount) { last; } + if ($retime ne "2"){ + $first = $et; + $retime = "2"; + } + printf "%-8s %-12s\n", $etime{ $et }, "etime=$et"; + $eloop++; + } + # + # print longest etimes + # + print "\n\n----- Top $sizeCount Longest etimes -----\n\n"; + $eloop = 0; + foreach $et (sort { $b <=> $a } (keys %etime)) { + if ($eloop == $sizeCount) { last; } + printf "%-12s %-10s\n","etime=$et",$etime{ $et }; + $eloop++; + } + undef %etime; +} + +####################################### +# # +# Gather and Process unique nentries # +# # +####################################### + + +if ($usage =~ /n/i || $verb eq "yes"){ + %nentries = getCounterHashFromFile($NENTRIES); + print "\n\n----- Top $sizeCount Largest nentries -----\n\n"; + $eloop = 0; + foreach $nentry (sort { $b <=> $a } (keys %nentries)){ + if ($eloop == $sizeCount) { last; } + printf "%-18s %12s\n","nentries=$nentry", $nentries{ $nentry }; + $eloop++; + } + print "\n\n----- Top $sizeCount Most returned nentries -----\n\n"; + $eloop = 0; + foreach $nentry (sort { $nentries{$b} <=> $nentries{$a} } (keys %nentries)){ + if ($eloop == $sizeCount) { last; } + printf "%-12s %-14s\n", $nentries{ $nentry }, "nentries=$nentry"; + $eloop++; + } + print "\n"; + undef %nentries; +} + +########################################## +# # +# Gather and process extended operations # +# # +########################################## + +if ($usage =~ /x/i || $verb eq "yes"){ + if ($extopCount > 0){ + %oid = getCounterHashFromFile($OID); + print "\n\n----- Extended Operations -----\n\n"; + foreach $oids (sort { $oid{$b} <=> $oid{$a} } (keys %oid) ){ + if ($oids eq "2.16.840.1.113730.3.5.1"){ $oidmessage = "Transaction Request"} #depreciated? + elsif ($oids eq "2.16.840.1.113730.3.5.2"){ $oidmessage = "Transaction Response"} #depreciated? + elsif ($oids eq "2.16.840.1.113730.3.5.3"){ $oidmessage = "Start Replication Request (incremental update)"} + elsif ($oids eq "2.16.840.1.113730.3.5.4"){ $oidmessage = "Replication Response"} + elsif ($oids eq "2.16.840.1.113730.3.5.5"){ $oidmessage = "End Replication Request (incremental update)"} + elsif ($oids eq "2.16.840.1.113730.3.5.6"){ $oidmessage = "Replication Entry Request"} + elsif ($oids eq "2.16.840.1.113730.3.5.7"){ $oidmessage = "Start Bulk Import"} + elsif ($oids eq "2.16.840.1.113730.3.5.8"){ $oidmessage = "Finished Bulk Import"} + elsif ($oids eq "2.16.840.1.113730.3.5.9"){ $oidmessage = "DS71 Replication Entry Request"} + elsif ($oids eq "2.16.840.1.113730.3.6.1"){ $oidmessage = "Incremental Update Replication Protocol"} + elsif ($oids eq "2.16.840.1.113730.3.6.2"){ $oidmessage = "Total Update Replication Protocol (Initialization)"} + elsif ($oids eq "2.16.840.1.113730.3.4.13"){ $oidmessage = "Replication Update Info Control"} + elsif ($oids eq "2.16.840.1.113730.3.6.4"){ $oidmessage = "DS71 Replication Incremental Update Protocol"} + elsif ($oids eq "2.16.840.1.113730.3.6.3"){ $oidmessage = "DS71 Replication Total Update Protocol"} + elsif ($oids eq "2.16.840.1.113730.3.5.12"){ $oidmessage = "DS90 Start Replication Request"} + elsif ($oids eq "2.16.840.1.113730.3.5.13"){ $oidmessage = "DS90 Replication Response"} + elsif ($oids eq "1.2.840.113556.1.4.841"){ $oidmessage = "Replication Dirsync Control"} + elsif ($oids eq "1.2.840.113556.1.4.417"){ $oidmessage = "Replication Return Deleted Objects"} + elsif ($oids eq "1.2.840.113556.1.4.1670"){ $oidmessage = "Replication WIN2K3 Active Directory"} + elsif ($oids eq "2.16.840.1.113730.3.6.5"){ $oidmessage = "Replication CleanAllRUV"} + elsif ($oids eq "2.16.840.1.113730.3.6.6"){ $oidmessage = "Replication Abort CleanAllRUV"} + elsif ($oids eq "2.16.840.1.113730.3.6.7"){ $oidmessage = "Replication CleanAllRUV Get MaxCSN"} + elsif ($oids eq "2.16.840.1.113730.3.6.8"){ $oidmessage = "Replication CleanAllRUV Check Status"} + elsif ($oids eq "2.16.840.1.113730.3.5.10"){ $oidmessage = "DNA Plugin Request"} + elsif ($oids eq "2.16.840.1.113730.3.5.11"){ $oidmessage = "DNA Plugin Response"} + elsif ($oids eq "1.3.6.1.4.1.1466.20037"){ $oidmessage = "Start TLS"} + elsif ($oids eq "1.3.6.1.4.1.4203.1.11.1"){ $oidmessage = "Password Modify"} + elsif ($oids eq "2.16.840.1.113730.3.4.20"){ $oidmessage = "MTN Control Use One Backend"} + else {$oidmessage = "Other"} + printf "%-6s %-23s %-60s\n", $oid{ $oids }, $oids, $oidmessage; + } + undef %oid; + } +} + +############################################ +# # +# Print most commonly requested attributes # +# # +############################################ + +if ($usage =~ /r/i || $verb eq "yes"){ + if ($anyAttrs > 0){ + %attr = getCounterHashFromFile($ATTR); + print "\n\n----- Top $sizeCount Most Requested Attributes -----\n\n"; + $eloop = 0; + foreach $mostAttr (sort { $attr{$b} <=> $attr{$a} } (keys %attr) ){ + if ($eloop eq $sizeCount){ last; } + printf "%-10s %-19s\n", $attr{$mostAttr}, $mostAttr; + $eloop++; + } + undef %attr; + } +} + +############################# +# # +# abandoned operation stats # +# # +############################# + +if ($usage =~ /g/i || $verb eq "yes"){ + $abandonTotal = $srchCount + $delCount + $modCount + $addCount + $modrdnCount + $bindCount + $extopCount + $cmpCount; + if ($verb eq "yes" && $abandonCount > 0 && $abandonTotal > 0){ + %conn_hash = getHashFromFile($CONN_HASH); + @srchConn = getArrayFromFile($SRCH_CONN); + @srchOp = getArrayFromFile($SRCH_OP); + @delConn = getArrayFromFile($DEL_CONN); + @delOp = getArrayFromFile($DEL_OP); + @targetConn = getArrayFromFile($TARGET_CONN); + @targetOp = getArrayFromFile($TARGET_OP); + @msgid = getArrayFromFile($MSGID); + @addConn = getArrayFromFile($ADD_CONN); + @addOp = getArrayFromFile($ADD_OP); + @modConn = getArrayFromFile($MOD_CONN); + @modOp = getArrayFromFile($MOD_OP); + @cmpConn = getArrayFromFile($CMP_CONN); + @cmpOp = getArrayFromFile($CMP_OP); + @modrdnConn = getArrayFromFile($MODRDN_CONN); + @modrdnOp = getArrayFromFile($MODRDN_OP); + @bindConn = getArrayFromFile($BIND_CONN); + @bindOp = getArrayFromFile($BIND_OP); + @unbindConn = getArrayFromFile($UNBIND_CONN); + @unbindOp = getArrayFromFile($UNBIND_OP); + @extConn = getArrayFromFile($EXT_CONN); + @extOp = getArrayFromFile($EXT_OP); + + print "\n\n----- Abandon Request Stats -----\n\n"; + + for ($g = 0; $g < $abandonCount; $g++){ + for ($sc = 0; $sc < $srchCount; $sc++){ + if ($srchConn[$sc] eq $targetConn[$g] && $srchOp[$sc] eq $targetOp[$g] ){ + print " - SRCH conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n"; + } + } + for ($dc = 0; $dc < $delCount; $dc++){ + if ($delConn[$dc] eq $targetConn[$g] && $delOp[$dc] eq $targetOp[$g]){ + print " - DEL conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n"; + } + } + for ($adc = 0; $adc < $addCount; $adc++){ + if ($addConn[$adc] eq $targetConn[$g] && $addOp[$adc] eq $targetOp[$g]){ + print " - ADD conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n"; + } + } + for ($mc = 0; $mc < $modCount; $mc++){ + if ($modConn[$mc] eq $targetConn[$g] && $modOp[$mc] eq $targetOp[$g]){ + print " - MOD conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n"; + } + } + for ($cc = 0; $cc < $cmpCount; $cc++){ + if ($cmpConn[$mdc] eq $targetConn[$g] && $cmpOp[$mdc] eq $targetOp[$g]){ + print " - CMP conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n"; + } + } + for ($mdc = 0; $mdc < $modrdnCount; $mdc++){ + if ($modrdnConn[$mdc] eq $targetConn[$g] && $modrdnOp[$mdc] eq $targetOp[$g]){ + print " - MODRDN conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n"; + } + } + for ($bcb = 0; $bcb < $bindCount; $bcb++){ + if ($bindConn[$bcb] eq $targetConn[$g] && $bindOp[$bcb] eq $targetOp[$g]){ + print " - BIND conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n"; + } + } + for ($ubc = 0; $ubc < $unbindCount; $ubc++){ + if ($unbindConn[$ubc] eq $targetConn[$g] && $unbindOp[$ubc] eq $targetOp[$g]){ + print " - UNBIND conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n"; + } + } + for ($ec = 0; $ec < $extopCount; $ec++){ + if ($extConn[$ec] eq $targetConn[$g] && $extOp[$ec] eq $targetOp[$g]){ + print " - EXT conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n"; + } + } + } + } +} +print "\n"; + +####################################### +# # +# Recommendations # +# # +####################################### + +if ($usage =~ /j/i || $verb eq "yes"){ + %conncount = getCounterHashFromFile($CONNCOUNT); + print "\n----- Recommendations -----\n"; + $recCount = "1"; + if ($unindexedSrchCount > 0){ + print "\n $recCount. You have unindexed searches, this can be caused from a search on an unindexed attribute, or your returned results exceeded the allidsthreshold. Unindexed searches are not recommended. To refuse unindexed searches, switch \'nsslapd-require-index\' to \'on\' under your database entry (e.g. cn=UserRoot,cn=ldbm database,cn=plugins,cn=config).\n"; + $recCount++; + } + if ($conncount{"T1"} > 0){ + print "\n $recCount. You have some connections that are are being closed by the idletimeout setting. You may want to increase the idletimeout if it is set low.\n"; + $recCount++; + } + if ($conncount{"T2"} > 0){ + print "\n $recCount. You have some coonections that are being closed by the ioblocktimeout setting. You may want to increase the ioblocktimeout.\n"; + $recCount++; + } + # compare binds to unbinds, if the difference is more than 30% of the binds, then report a issue + if (($bindCount - $unbindCount) > ($bindCount*.3)){ + print "\n $recCount. You have a significant difference between binds and unbinds. You may want to investigate this difference.\n"; + $recCount++; + } + # compare fds taken and return, if the difference is more than 30% report a issue + if (($fdTaken -$fdReturned) > ($fdTaken*.3)){ + print "\n $recCount. You have a significant difference between file descriptors taken and file descriptors returned. You may want to investigate this difference.\n"; + $recCount++; + } + if ($rootDNBindCount > ($bindCount *.2)){ + print "\n $recCount. You have a high number of Directory Manager binds. The Directory Manager account should only be used under certain circumstances. Avoid using this account for client applications.\n"; + $recCount++; + } + if ($errorCount > $successCount){ + print "\n $recCount. You have more unsuccessful operations than successful operations. You should investigate this difference.\n"; + $recCount++; + } + if ($conncount{"U1"} < ($connCodeCount - $conncount{"U1"})){ + print "\n $recCount. You have more abnormal connection codes than cleanly closed connections. You may want to investigate this difference.\n"; + $recCount++; + } + if ($first > 0){ + print "\n $recCount. You have a majority of etimes that are greater than zero, you may want to investigate this performance problem.\n"; + $recCount++; + } + if ($objectclassTopCount > ($srchCount *.25)){ + print "\n $recCount. You have a high number of searches that query the entire search base. Although this is not necessarily bad, it could be resource intensive if the search base contains many entries.\n"; + $recCount++; + } + if ($recCount == 1){ + print "\nNone.\n"; + } + print "\n"; + undef %conncount; +} + +# +# We're done, clean up the data files +# +removeDataFiles(); + +exit (0); + +####################### +# # +# Display Usage # +# # +####################### + +sub displayUsage { + + print "Usage:\n\n"; + + print " ./logconv.pl [-h] [-d|--rootdn ] [-s|--sizeLimit ] [-v|verison] [-Vi|verbose]\n"; + print " [-S|--startTime ] [-E|--endTime ] \n"; + print " [-efcibaltnxrgjuyp] [ access log ... ... ]\n\n"; + + print "- Commandline Switches:\n\n"; + + print " -h, --help help/usage\n"; + print " -d, --rootDN default is \"cn=directory manager\"\n"; + print " -D, --data default is \"/tmp\"\n"; + print " -s, --sizeLimit default is 20\n"; + print " -X, --excludeIP E.g. Load balancers\n"; + print " -v, --version show version of tool\n"; + print " -S, --startTime