#!/usr/bin/perl -w # babysit v0.4 # # 0.4 (9/16/03) # Added color options. # 0.5 (7/7/04) # added stuff to use enviornment variables $starttime = scalar(localtime); $tomcat_date = `date +%Y-%m-%d`; chomp ($tomcat_date); $color = 0; $short = 0; if ( @ARGV ) { foreach $option (@ARGV) { $short = "1" if ( $option =~ /-short/i ); $color = "1" if ( $option =~ /-color/i ); $sysstat = "1" if ( $option =~ /-sysstat/i ); } } $sysstat = "0" unless ( $sysstat ); if ( $short eq "0" ) { warn "You can use the -short option if you want more compact results..\n"; } if ( $color eq "0" ) { warn "You can use the -color option for more color..\n"; } $debug = 0; $tail = "/usr/bin/tail"; @inputlog = "/var/log/httpd/*.log /opt/qpass/var/log/tomcat/localhost_log.${tomcat_date}.txt /opt/qpass/var/log/tomcat/localhost_access.${tomcat_date}.txt"; if ( -f "/home/monitor/stats/sar.log" ) { print "/opt/stats/sar.log detected adding stats to system ...\n"; push @inputlog, ("/opt/stats/sar.log"); } open(MODULES,"/proc/modules") || warn "Could not open /proc/modules: $!\n"; @modules = ; close(MODULES); foreach (@modules) { if ( /basp/ ) { print "Basp Load Balancing driver detected, automatically adjusting load values to compensate\n"; $basp = "true"; } else { $basp = "false"; } } warn "Reading file @{inputlog}..\n\n"; $counter200 = 0; $counter301 = 0; $counter302 = 0; $counter304 = 0; $counter400 = 0; $counter404 = 0; $counter500 = 0; $totalcost = 0; $totalqty = 0; $totalpurch = 0; $totalhits = 0; $totalcostfirst = 0; $bigcounterbobo = 0; $counterbobo200 = 0; $counterbobo500 = 0; $counterbobo302 = 0; $counterbobo304 = 0; $counterbobo400 = 0; $counterbobo404 = 0; $siteangel = 0; $redalert = 0; $totalxmlapi = 0; $siteangelresponsetime = 0; $redalertresponsetime = 0; $totalpurchresponsetime = 0; $averagepurchresponsetime = 0; $xmlapiresponsetime = 0; $totalxmlapiresponsetime = 0; $averagexmlapiresponsetime = 0; $totalsiteangelresponsetime = 0; $totalredalertresponsetime = 0; $averagesiteangelresponsetime = 0; $averageredalertresponsetime = 0; $product = 0; $popresponsetime = 0; $totalpopresponsetime = 0; $totalpop = 0; $averagepopresponsetime = 0; $infospace_ticket_response_time = 0; $totalinfospace_ticket_response_time = 0; $totalinfospace = 0; $averageinfospace_ticket_response_time = 0; $cpu_user = "0"; $cpu_idle = "0"; $total_sockets = "0"; $original_load1 = "0"; $original_load5 = "0"; $load1 = "0"; $load5 = "0"; tail(); sub tail { $SIG{'INT'} = 'stats_generator'; open(TAIL,"$tail -n 1 -f @inputlog|") || die "Cannot open $tail on file ${inputlog}: $!\n"; while () { if ( /java.lang.ClassCastException/ ) { $cast = $_; chomp($cast); print "\e[33;41m\e[1m!!\e[0m\e[37;41m\e $_ \e[33;41m\e[1m!!\e[0m\n\n\n"; } if ( $sysstat eq "1" ) { # weblyn54.qpass.aws 30 1089183617 - plist-sz 1321 #if ( /.*([0-9]{8,}).*plist-sz.*/ ) { $sar_update = $1; } if ( /.*30.*[0-9]{8,}.*all.*\%user\s+(.*)/ ) { $cpu_user = $1; } if ( /.*30.*[0-9]{8,}.*all.*\%idle\s+(.*)/ ) { $cpu_idle = $1; } if ( /.*30.*[0-9]{8,}.*totsck\s+(.*)/ ) { $total_sockets = $1; } if ( /.*30.*[0-9]{8,}.*ldavg-1\s+(.*)/ ) { $original_load1 = $1; } if ( /.*30.*[0-9]{8,}.*ldavg-5\s+(.*)/ ) { $original_load5 = $1; } if ( $basp eq "true" && $original_load1 ne "0" && $original_load5 ne "0" ) { $load1 = sprintf("%0.2f", ($original_load1 - 1.0)); $load5 = sprintf("%0.2f", ($original_load5 - 1.0)); print "aah?\n"; } else { #print "ehhh?\n"; $load1 = $original_load1; $load5 = $original_load5; } } # # this will scan for mod_jk errors # if ( /\w+ (\w+) (\d+) (\d+)\:(\d+)\:(\d+) (\d+).*Error ajp_process_callback - write failed/ ) { $month = $1; $day = $2; $hour = $3; $minute = $4; $second = $5; $year = $6; print "Status: CPU(User/Idle): $cpu_user\%\/$cpu_idle\% Open Sockets: $total_sockets Load1: $load1 Load5: $load5\n" if ( $sysstat eq "1" ); print "\[$day\/$month\/$year\:$hour\:$minute\:$second\] \e[33;41m\e[1m!!\e[0m\e[37;41m\e[1m TOMCAT OUT OF AJP13 THREADS \e[33;41m\e[1m!!\e[0m\n\n"; } if ( /\w+ (\w+) (\d+) (\d+)\:(\d+)\:(\d+) (\d+).*No more workers left.*can not submit the request/ ) { $month = $1; $day = $2; $hour = $3; $minute = $4; $second = $5; $year = $6; print "Status: CPU(User/Idle): $cpu_user\%\/$cpu_idle\% Open Sockets: $total_sockets Load1: $load1 Load5: $load5\n" if ( $sysstat eq "1" ); print "\[$day\/$month\/$year\:$hour\:$minute\:$second\] \e[33;41m\e[1m!!\e[0m\e[37;41m\e[1m TOMCAT OUT OF AJP THREADS \e[33;41m\e[1m!!\e[0m\n\n"; } if ( /\w+ (\w+) (\d+) (\d+)\:(\d+)\:(\d+) (\d+).*All tomcat instances failed.*no more workers left/ ) { $month = $1; $day = $2; $hour = $3; $minute = $4; $second = $5; $year = $6; print "Status: CPU(User/Idle): $cpu_user\%\/$cpu_idle\% Open Sockets: $total_sockets Load1: $load1 Load5: $load5\n" if ( $sysstat eq "1" ); print "\[$day\/$month\/$year\:$hour\:$minute\:$second\] \e[33;41m\e[1m!!\e[0m\e[37;41m\e[1m TOMCAT OUT OF AJP THREADS \e[33;41m\e[1m!!\e[0m\n\n"; } if ( /\w+ (\w+) (\d+) (\d+)\:(\d+)\:(\d+) (\d+).*Error connecting to tomcat.* Tomcat is probably not started or is/ ) { $month = $1; $day = $2; $hour = $3; $minute = $4; $second = $5; $year = $6; print "Status: CPU(User/Idle): $cpu_user\%\/$cpu_idle\% Open Sockets: $total_sockets Load1: $load1 Load5: $load5\n" if ( $sysstat eq "1" ); print "\[$day\/$month\/$year\:$hour\:$minute\:$second\] \e[33;41m\e[1m!!\e[0m\e[37;41m\e[1m TOMCAT OUT OF AJP THREADS \e[33;41m\e[1m!!\e[0m\n\n"; } # # this will scan for tomcat threads spawning # if ( /.*Ajp13Processor\[8009\]\[(.*)\].* Starting background thread.*/ ) { print "$_\n"; } if ( /.*HttpProcessor\[8080\]\[(.*)\].* Starting background thread.*/ ) { print "$_\n"; } if ( /No processor available.*rejecting this connection.*/ ) { print "$_\n"; } $vendor = AWS if ( /\/var\/log\/httpd\/awireless.*/ ); $vendor = Alltel if ( /var\/log\/httpd\/alltel.*/ ); $vendor = Cingular if ( /\/var\/log\/httpd\/cingular.*/ ); $vendor = Nextel if ( /\/var\/log\/httpd\/nextel.*/ ); $vendor = "(Unknown vendor)" unless ( $vendor ); # format of regex: # $1 = IP address (1.2.3.4) # $2 = Day of month (24) # $3 = Month (Jun) # $4 = Year (2003) # $5 = Hour (24-hour clock) # $6 = Minute # $7 = Second # $8 = Query # $9 = HTTP Response code # $10 = Bytes Sent # $11 = User Agent # $12 = HTTP Response time (microseconds) # # $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 #################### ##### ##### ##### ##### ##### ##### ######## ############ ########### ######## ########### if ( /(\d+\.\d+\.\d+\.\d+)\s\-\s\-\s\[(\d+)\/(\w+)\/(\d+):(\d+):(\d+):(\d+)\s+\-\d+\]\s(\".*\")\s([0-9]{3,3})\s([0-9]{1,})\s(\".*\")\s([0-9]{4,})/ ) { $totalhits++; $ip = $1; $day = $2; $month = $3; $year = $4; $hour = $5; $minute = $6; $second = $7; $query = $8; $result = $9; # $bytes = $10; $agent = $11; $time = $12; $counter200++ if ( $result && $result eq "200" ); $counter301++ if ( $result && $result eq "301" ); $counter302++ if ( $result && $result eq "302" ); $counter304++ if ( $result && $result eq "304" ); $counter400++ if ( $result && $result eq "400" ); $counter404++ if ( $result && $result eq "404" ); $counter500++ if ( $result && $result eq "500" ); $bigcounter++ if ( $result =~ /[0-9]{3,3}/ ); $http_error++ if ( $result && $result eq "500" ); # # This Scans for successful purchases and reports # if ( $query =~ /GET.*AuthAmount=(.*)\&AuthThreshold.*Quantity=([0-9]).*\&AuthAmountCurrencyID.*\&description=(.*)\&product.*host=(.*)%2Eqpass.*/ || $query =~ /GET \/cingularrecordpurchase.do\?AuthAmount=(.*)\&AuthThreshold.*Quantity=([0-9]).*\&AuthAmountCurrencyID.*\&description=(.*)\&product.*host=(.*)%2Eqpass.*/ ) { $cost = sprintf("%0.2f", $1); $purchresponsetime = sprintf("%0.3f", ($time/1000000)); $totalpurchresponsetime += $time; $totalcostfirst += $cost; $totalcost = sprintf("%0.2f", $totalcostfirst); $qty = $2; $totalqty += $qty; $product = $3; utf_convert(); $host = $4; $totalpurch++; $averagepurchresponsetime = sprintf("%0.3f", (($totalpurchresponsetime/$totalpurch)/1000000)); $engine = "(Unknown Engine)"; $engine = "BigIP Engine Pool" if ( $ip =~ /12.129.8.230/ ); $engine = "englyn11" if ( $ip =~ /192.168.20.234/ ); $engine = "englyn12" if ( $ip =~ /192.168.20.237/ ); $engine = "englyn13" if ( $ip =~ /193.168.20.231/ ); $engine = "englyn02" if ( $ip =~ /192.168.30.174/ || $ip =~ /192.168.30.175/ || $ip =~ /192.168.30.176/ ); $engine = "englyn01" if ( $ip =~ /192.168.30.100/ || $ip =~ /192.168.30.101/ || $ip =~ /192.168.30.102/ ); $engine = "englyn05" if ( $ip =~ /192.168.30.77/ || $ip =~ /192.168.30.78/ || $ip =~ /192.168.30.79/ ); $engine = "ecwwwa03" if ( $ip =~ /192.168.20.110/ ); print "Status: CPU(User/Idle): $cpu_user\%\/$cpu_idle\% Open Sockets: $total_sockets Load1: $load1 Load5: $load5\n" if ( $sysstat eq "1" ); print "[${totalhits}] Total: \$${totalcost} from $totalqty purchases (average $averagepurchresponsetime)\n"; print "\[$day\/$month\/$year\:$hour\:$minute\:$second\] Purchased $qty item(s)/(${product}) for \$${cost} from $host on ${vendor}($engine) in ${purchresponsetime}s\n\n" if ( $short && $color eq "0" ); print "\[$day\/$month\/$year\:$hour\:$minute\:$second\] \e[33;44m\e[1mPurchased\e[0m $qty item(s)/(${product}) for \$${cost} from $host on ${vendor}($engine) in ${purchresponsetime}s\n\n" if ( $short && $color eq "1" ); } # # This scans for Siteangel and Red alert # if ( $agent =~ /SiteAngel/ && $result =~ /200/ ) { $siteangel++; $totalsiteangelresponsetime += $time; $siteangelresponsetime = sprintf("%0.3f", ($time/1000000)); $averagesiteangelresponsetime = sprintf("%0.3f", (($totalsiteangelresponsetime/$siteangel)/1000000)); print "Status: CPU(User/Idle): $cpu_user\%\/$cpu_idle\% Open Sockets: $total_sockets Load1: $load1 Load5: $load5\n" if ( $sysstat eq "1" ); print "[${totalhits}] SiteAngel: $siteangel accesses (average $averagesiteangelresponsetime)\n"; print "\[$day\/$month\/$year\:$hour\:$minute\:$second\] SiteAngel retrieved $query in $siteangelresponsetime seconds\n\n" if ( $color eq "0" ); print "\[$day\/$month\/$year\:$hour\:$minute\:$second\] \e[37;42m\e[1mSiteAngel retrieved\e[0m $query in $siteangelresponsetime seconds\n\n" if ( $color eq "1"); } if ( $agent =~ /RedAlert/ && $result =~ /200/ ) { $redalert++; $totalredalertresponsetime += $time; $redalertresponsetime = sprintf("%0.3f", ($time/1000000)); $averageredalertresponsetime = sprintf("%0.3f", (($totalredalertresponsetime/$redalert)/1000000)); print "Status: CPU(User/Idle): $cpu_user\%\/$cpu_idle\% Open Sockets: $total_sockets Load1: $load1 Load5: $load5\n" if ( $sysstat eq "1" ); print "[${totalhits}] RedAlert: $redalert accesses (average $averageredalertresponsetime)\n"; print "\[$day\/$month\/$year\:$hour\:$minute\:$second\] Red Alert retrieved $query in $redalertresponsetime seconds\n\n" if ( $color eq "0" ); print "\[$day\/$month\/$year\:$hour\:$minute\:$second\] \e[37;42m\e[1mRed Alert retrieved \e[0m $query in $redalertresponsetime seconds\n\n" if ( $color eq "1" ); } # # This scans for PurchaseXMLAPI Stuff # if ( $query =~ /POST.*services\/Purch.*Po.* HTTP\/1.*/ && $result =~ /200/ ) { $xmlapiresponsetime = sprintf("%0.3f", ($time/1000000)); $totalxmlapiresponsetime += $time; $totalxmlapi++; $averagexmlapiresponsetime = sprintf("%0.3f", (($totalxmlapiresponsetime/$totalxmlapi)/1000000)); print "Status: CPU(User/Idle): $cpu_user\%\/$cpu_idle\% Open Sockets: $total_sockets Load1: $load1 Load5: $load5\n" if ( $sysstat eq "1" ); print "[${totalhits}] XML API Accesses: $totalxmlapi (average $averagexmlapiresponsetime)\n"; print "\[$day\/$month\/$year\:$hour\:$minute\:$second\] PurchaseXMLAPI Access from $ip for $vendor which took $xmlapiresponsetime seconds to process \n\n" if ( $short && $color eq "0" ); print "\[$day\/$month\/$year\:$hour\:$minute\:$second\] \e[36;40m\e[1mPurchase XMLAPI Access\e[0m for ${vendor}(${ip}) in ${xmlapiresponsetime}s \n\n" if ( $short && $color eq "1" ); } # # This scans for redirects from the engine # if ( $query =~ /GET.*pop.do.*QPCU.*QDesc=(.*)&QIID=.*/ ) { $product = $1; utf_convert(); $popresponsetime = sprintf("%0.3f", ($time/1000000)); $totalpopresponsetime += $time; $totalpop++; $averagepopresponsetime = sprintf("%0.3f", (($totalpopresponsetime/$totalpop)/1000000)); print "Status: CPU(User/Idle): $cpu_user\%\/$cpu_idle\% Open Sockets: $total_sockets Load1: $load1 Load5: $load5\n" if ( $sysstat eq "1" ); print "[${totalhits}] Engine Redirect(pop): $totalpop (average $averagepopresponsetime)\n"; print "\[$day\/$month\/$year\:$hour\:$minute\:$second\] Engine Redirect from $ip for ($product) on $vendor in ${popresponsetime}s \n\n" if ( $short && $color eq "0" ); print "\[$day\/$month\/$year\:$hour\:$minute\:$second\] \e[35;40m\e[1mEngine Redirect\e[0m from $ip for ($product) on $vendor in ${popresponsetime}s \n\n" if ( $short && $color eq "1" ); } # # This scans for cingular -> infospace traffic # if ( $query =~ /GET.*cingularpop.do.*Ticket=MDA.*/ ) { $infospace_ticket_response_time = sprintf("%0.3f", ($time/1000000)); $totalinfospace_ticket_response_time += $time; $totalinfospace++; $averageinfospace_ticket_response_time = sprintf("%0.3f", (($totalinfospace_ticket_response_time/$totalinfospace)/1000000)); print "Status: CPU(User/Idle): $cpu_user\%\/$cpu_idle\% Open Sockets: $total_sockets Load1: $load1 Load5: $load5\n" if ( $sysstat eq "1" ); print "[${totalhits}] Infospace Ticket Request: $totalinfospace (average $averageinfospace_ticket_response_time)\n"; print "\[$day\/$month\/$year\:$hour\:$minute\:$second\] Infospace Ticket Login from $ip on $vendor in ${infospace_ticket_response_time}s \n\n" if ( $short && $color eq "0" ); print "\[$day\/$month\/$year\:$hour\:$minute\:$second\] \e[32;40m\e[1mInfospace Ticket Login\e[0m from $ip on $vendor in ${infospace_ticket_response_time}s \n\n" if ( $short && $color eq "1" ); } if ( $query =~ /POST \/paymentprocessorcontroller\/AwsRequestHandler.*/ ) { $total += $time; $responsetime = sprintf("%0.3f", ($time/1000000)); $counterbobo200++ if ( $result && $result eq "200" ); $counterbobo301++ if ( $result && $result eq "301" ); $counterbobo302++ if ( $result && $result eq "302" ); $counterbobo304++ if ( $result && $result eq "304" ); $counterbobo400++ if ( $result && $result eq "400" ); $counterbobo404++ if ( $result && $result eq "404" ); $counterbobo500++ if ( $result && $result eq "500" ); $bigcounterbobo++ if ( $result && $result =~ /[0-9]{3,3}/ ); $average = sprintf("%0.3f", (($total/$bigcounterbobo)/1000000)); print "Status: CPU(User/Idle): $cpu_user\%\/$cpu_idle\% Open Sockets: $total_sockets Load1: $load1 Load5: $load5\n" if ( $sysstat eq "1" ); print "[${totalhits}] WARNING!! HTTP 500 Response code!(Total: $http_error)\n" if ( $result eq "500" && $color eq "0" ); print "\e[33;41m\e[1m!!\e[0m\e[37;41m\e[1m WARNING!! HTTP 500 Response code!\e[33;41m\e[1m!!\e[0m(Total: $http_error)\n" if ( $result eq "500" && $color eq "1" ); print "[${totalhits}]BOBO: Response time $responsetime (average: $average)\t"; print "\n"; print "$_\n\n" unless ( $short ); print "\[$day\/$month\/$year\:$hour\:$minute\:$second\] $result $time \n\n" if ( $short ); next; } print "$_" if ( $debug > 10 ); print "Status: CPU(User/Idle): $cpu_user\%\/$cpu_idle\% Open Sockets: $total_sockets Load1: $load1 Load5: $load5\n" if ( $sysstat eq "1" && $result && $result eq "500" ); print "[${totalhits}] HTTP/500 Detected!\n$_\n" if ( $result && $result eq "500" && $color eq "0" ); print "\e[33;41m\e[1m!!\e[0m\e[37;41m\e[1m HTTP/500 Detected! \e[33;41m\e[1m!!\e[0m\n$_\n" if ( $result && $result eq "500" && $color eq "1" ); } } close(TAIL) || warn "Cannot close $tail on file ${inputlog}: $!\n"; } sub stats_generator { print "\n\n"; print "Script Start time: $starttime\n"; print "STATS:\n"; print "======================================================================\n"; print "HTTP RESPONSE CODES(all): ( $totalhits )\n"; print "======================================================================\n"; print "Total Queries Examined: $bigcounter\n"; print "HTTP/200: $counter200\n" if ( $counter200 && $counter200 > 0 ); print "HTTP/500: $counter500\n" if ( $counter500 && $counter500 > 0 ); print "HTTP/301: $counter302\n" if ( $counter301 && $counter301 > 0 ); print "HTTP/302: $counter302\n" if ( $counter302 && $counter302 > 0 ); print "HTTP/304: $counter304\n" if ( $counter304 && $counter304 > 0 ); print "HTTP/400: $counter400\n" if ( $counter400 && $counter400 > 0 ); print "HTTP/404: $counter404\n" if ( $counter404 && $counter404 > 0 ); print "\n"; print "======================================================================\n"; print "HTTP RESPONSE CODES(Bobo Only):\n"; print "======================================================================\n"; print "Total BOBO Queries examined: $bigcounterbobo\n"; print "HTTP/200: $counterbobo200\n" if ( $counterbobo200 && $counterbobo200 > 0 ); print "HTTP/500: $counterbobo500\n" if ( $counterbobo500 && $counterbobo500 > 0 ); print "\n"; print "HTTP/301: $counterbobo302\n" if ( $counterbobo301 && $counterbobo301 > 0 ); print "HTTP/302: $counterbobo302\n" if ( $counterbobo302 && $counterbobo302 > 0 ); print "HTTP/304: $counterbobo304\n" if ( $counterbobo304 && $counterbobo304 > 0 ); print "HTTP/400: $counterbobo400\n" if ( $counterbobo400 && $counterbobo400 > 0 ); print "HTTP/404: $counterbobo404\n" if ( $counterbobo404 && $counterbobo404 > 0 ); print "======================================================================\n"; print "Misc Information:\n"; print "======================================================================\n"; print "Purchases:\n"; print "Collected \$" . sprintf("%0.2f", $totalcost) . " from $totalqty items\n"; print "Purchases: $totalpurch items (avg ${averagepurchresponsetime}s)\n"; print "POP Redirects: $totalpop times (avg ${averagepopresponsetime}s)\n"; print "\n"; print "Purchase XMLAPI Accesses : $totalxmlapi times (avg ${averagexmlapiresponsetime}s)\n"; print "Infospace Ticket Logins: $totalinfospace times (avg ${averageinfospace_ticket_response_time}s)\n"; print "Siteangel detected $siteangel times (avg ${averagesiteangelresponsetime}s)\n"; print "Red Alert detected $redalert times (avg ${averageredalertresponsetime}s)\n"; print "\n"; die "Exiting ...\n"; } sub utf_convert { $product =~ s/\+/ /g; $product =~ s/\%1./ ./g; $product =~ s/\%21/\!/g; $product =~ s/\%22/\"/g; $product =~ s/\%24/\%/g; $product =~ s/\%27/\'/g; $product =~ s/\%28/\(/g; $product =~ s/\%29/\)/g; $product =~ s/\%2C/\,/g; $product =~ s/\%2E/\./g; $product =~ s/\%2B/\+/g; $product =~ s/\%26/\&/g; $product =~ s/\%3B/\;/g; $product =~ s/\%3F/\?/g; $product =~ s/\%2D/\-/g; $product =~ s/\%5F/\_/g; $product =~ s/\"\;/\"/g; }