Asterisklogparse.pl
From Federal Burro of Information
Jump to navigationJump to search
#!/usr/bin/perl -w use strict; use Data::Dumper; use Getopt::Long; use CGI; use CGI::Carp qw/fatalsToBrowser/; no warnings "uninitialized"; my $cgi = new CGI; my $log= "/var/log/asterisk/queue_log"; my $extension_list="/var/www/html/perl/extension.list"; # command line options: my ($c, $q, $h, $a , $dcl, $queryqueue, $html); # call option # queues option, # help option, # detailed call log option # queryqueue if you want to narrow the view to one queue # html output (my $version) = '$Revision: 1.7 $' =~ /([\d\.]+)/; my %calls; my %queues; my %events ; # from http://www.voip-info.org/wiki/view/Asterisk+log+queue_log # not used reference only. #$events{'RINGNOANSWER'} =0; # agent did not pick up phone. #$events{'REMOVEMEMBER'} =0; # admin funtion, on a schedule I think, for the various shifts. #$events{'ENTERQUEUE'} =0; # call came in #$events{'CONNECT'} =0; # called was connected to and agent #$events{'CONFIGRELOAD'} =0; # admin ignore #$events{'COMPLETECALLER'} =0; # caller hung up #$events{'COMPLETEAGENT'} =0; # agent hung up. #$events{'ADDMEMBER'} =0; # admin funtion, on a schedule I think, for the various shifts. #$events{'ABANDON'} =0; # Zoe noe! #$events{EXITWITHKEY} = 0; # Called press a key and went somewhere else. Ignored my $oldestlog = time; my $newestlog = 0; my %qnames; $qnames{4000} = "Main GTS Queue for Level One"; $qnames{4001} = "SCT Level 2 Queue\'s"; $qnames{4020} = "General Support"; $qnames{4021} = "WSS"; $qnames{4022} = "Archiving"; $qnames{4023} = "Email"; $qnames{4024} = "SPN/SHEP"; $qnames{5000} = "All SCT phones"; $qnames{5001} = "Static for SCT Members"; $qnames{6000} = "SPN Overflow"; my %extensions; if( -f "$extension_list") { open(EXT, "$extension_list" ) || warn "failed to open extension_list $!\n"; } else { warn "extension_list file $extension_list not a file.\n"; } while (<EXT>) { chomp; my ($ext , $person ) = split ( /: / , $_ ); $extensions{$ext} = $person; } my $GetOptresult = GetOptions ( "dcl" => \$dcl, "c" => \$c, "q" => \$q, "h" => \$h, "a" => \$a, "queryqueue=s" => \$queryqueue, "html" => \$html ); # set html for now if ( $cgi->param('q') ) { $html = 1; $q = 1; } if ( $cgi->param('c') ) { $html = 1; $c = 1; } if ( $cgi->param('a') ) { $html = 1; $a = 1; } if ( $cgi->param('queryqueue') ) { if ( $cgi->param('queryqueue') =~ /(\w+)/ ) { $queryqueue = $1; }else { die "queryqueue must be a word, stop faffing about"; } } if ( $h ) { print "$0, version $version usage: $0 [-q] [-a] [-c] [-dcl] [-h] [-queryqueue=<queue>] q : queue stats a : show agents details in queue stats c : calls log dcl : detailed call log h : print this help message html: output to html using queue log: $log using extention list: $extension_list "; exit 1; } if( -f "$log") { open(LOG, "$log" ) || warn "failed to open log $!\n"; } else { warn "log file $log not a file.\n"; } while (<LOG>) { #Fields in queue_log # epoch timestamp of listed action # uniqueid of call # queue name # bridged channel # event # event parameter 1 # event parameter 2 # event parameter 3 chomp; my ($epoch,$callid,$queueid,$channel,$event,$var1,$var2,$var3)= split /\|/; # note that at ML one agent is sat at one channel, channel = agent. # print "Parsed line: $epoch,$callid,$queueid,$channel,$event,$var1,$var2,$var3\n"; # if queryqueue is set then drop all others. next if ( $queryqueue && ( $queueid ne $queryqueue ) ) ; # some stuff we don't track # this would skew numbers otherwise. next if ( $_ =~ /REMOVEMEMBER/ ) ; if ( $dcl ) { $calls{$callid}->{LOG} .= $_ . "\n"; } # global stats ( $epoch < $oldestlog )? ($oldestlog = $epoch) : 1 ; ( $epoch > $newestlog )? ($newestlog = $epoch) : 1 ; ############ # call data ############ $calls{$callid}->{QUEUE} = $queueid; # turn channel into agent # SIP/<number> into <number> $channel =~ /(\d+)/; my $agent = $1; if ( $_ =~ /COMPLETECALLER/ ) { $calls{$callid}->{COMPLETEWHO} = "CALLER"; $calls{$callid}->{COMPLETE} = $epoch; $calls{$callid}->{HOLDTIME} = $var1; $calls{$callid}->{CALLTIME} = $var2; } if ( $_ =~ /COMPLETEAGENT/ ) { $calls{$callid}->{COMPLETEWHO} = "AGENT"; $calls{$callid}->{COMPLETE} = $epoch; $calls{$callid}->{HOLDTIME} = $var1; $calls{$callid}->{CALLTIME} = $var2; } if ( $_ =~ /ENTERQUEUE/ ) { $calls{$callid}->{ENTERQUEUE} = $epoch; } if ( $_ =~ /ABANDON/ ) { $calls{$callid}->{ABANDON} = $epoch; $calls{$callid}->{HOLDTIME_CALC} = $calls{$callid}->{ABANDON} - $calls{$callid}->{ENTERQUEUE}; $calls{$callid}->{HOLDTIME} = $var3; $calls{$callid}->{MSG} .= "Call abandoned\n"; } if ( $_ =~ /CONNECT/ ) { $calls{$callid}->{CONNECT} = $epoch; if ( $calls{$callid}->{ENTERQUEUE} ) { $calls{$callid}->{HOLDTIME_CALC} = $calls{$callid}->{CONNECT} - $calls{$callid}->{ENTERQUEUE}; $calls{$callid}->{HOLDTIME} = $var1; $calls{$callid}->{AGENT} = $agent; } else { $calls{$callid}->{MSG} .= "Call entered queue before log\n"; } } if ( $_ =~ /EXITWITHKEY/ ) { # commented out for now, do not track # $calls{$callid}->{COMPLETE} = $epoch; # $calls{$callid}->{COMPLETEWHO} = "KEY"; # $calls{$callid}->{HOLDTIME} = $epoch - $calls{$callid}->{ENTERQUEUE}; delete ( $calls{$callid} ); } if ( $_ =~ /CONFIGRELOAD/ ) { delete ( $calls{$callid} ); } ############ # queue data ############ if ( $_ =~ /COMPLETECALLER/ ) { $queues{$queueid}->{COMPLETECALLER}++; $queues{$queueid}->{agent}->{$agent}->{COMPLETE}++; } if ( $_ =~ /COMPLETEAGENT/ ) { $queues{$queueid}->{COMPLETEAGENT}++; $queues{$queueid}->{agent}->{$agent}->{COMPLETE}++; } if ( $_ =~ /ABANDON/ ) { $queues{$queueid}->{ABANDON}++; } if ( $_ =~ /RINGNOANSWER/ ) { # only count the ring no answer if the time was more than zero. if ( $var1 != 0 ) { $queues{$queueid}->{agent}->{$agent}->{RINGNOANSWER}++ } } } ############# # Calculate derived data. ############# while ( my ($callid, $value) = each(%calls) ) { my $queueid = $calls{$callid}->{QUEUE}; # agregate holdtime , for calculating average later. if ( $calls{$callid}->{HOLDTIME} ) { if ( ! $calls{$callid}->{ABANDON} ) { $queues{$queueid}->{AGHOLDTIME} += $calls{$callid}->{HOLDTIME}; # picked up calls } else { $queues{$queueid}->{AGABHOLDTIME} += $calls{$callid}->{HOLDTIME}; # not picked up calls } } if ( $calls{$callid}->{ENTERQUEUE} ) { if ( ! $calls{$callid}->{ABANDON} && ! $calls{$callid}->{COMPLETE} && ! $calls{$callid}->{EXITWITHKEY}) { $queues{$queueid}->{INPROGRESS}++; } } } while ( my ($queueid, $value) = each(%queues) ) { $queues{$queueid}->{TOTALPICKEDUP} = $queues{$queueid}->{COMPLETECALLER}+$queues{$queueid}->{COMPLETEAGENT}; # Average holdtime for picked up calls. if ( $queues{$queueid}->{TOTALPICKEDUP} != 0 ) { $queues{$queueid}->{AVERAGEHOLDTIME} = int($queues{$queueid}->{AGHOLDTIME} / $queues{$queueid}->{TOTALPICKEDUP}) ; } else { $queues{$queueid}->{AVERAGEHOLDTIME} = 0; } if ( $queues{$queueid}->{ABANDON} != 0 ) { $queues{$queueid}->{AVERAGEABHOLDTIME} = int ($queues{$queueid}->{AGABHOLDTIME} / $queues{$queueid}->{ABANDON} ); } else { $queues{$queueid}->{AVERAGEABHOLDTIME} = 0; } } ############# # print Stats ############# if ( ! $html ) { print "#########\n"; print "# Global Stats\n"; print "#########\n"; print "Oldest log entry". localtime($oldestlog) ."\n"; print "Newest log entry". localtime($newestlog) ."\n"; } else { my $title = "Call stats"; print $cgi->header; print $cgi->start_html( # -head=>meta({-http_equiv=>'Refresh', -content=>'30'}), -title=>$title, -style=>{-src=>'/blueandyellow.css'}), # -bgcolor=>'#103B68'), $cgi->h1($title); print "Options specified: "; if ( $q ) { print "queue stats, "; }; if ( $a ) { print "agent details for queue stats, "; }; if ( $c ) { print "call stats, "; }; if ( $dcl ) { print "detailed call log, "; }; if ( $queryqueue ) { print "specific queue was requested, "; }; print "<br>\n"; print "Displaying from ". localtime($oldestlog) . " to ". localtime($newestlog) ."\n"; } if ( $c ) { if ( $html ) { print "<pre>"; } while ( my ($callid, $value) = each(%calls) ) { print "####\n# callid $callid\n####\n"; print "QUEUE: ".$calls{$callid}->{QUEUE} ."\n"; print "ENTERQUEUE: ".$calls{$callid}->{ENTERQUEUE} ."\n"; print "HOLDTIME: ".$calls{$callid}->{HOLDTIME} ."\n"; # print "HOLDTIME_CALC: ".$calls{$callid}->{HOLDTIME_CALC}."\n"; # Redundant, was jsut for checking print "ABANDON: ".$calls{$callid}->{ABANDON} ."\n"; print "CONNECT: ".$calls{$callid}->{CONNECT} ."\n"; print "AGENT: ".$extensions{$calls{$callid}->{AGENT}} ."\n"; print "CALLTIME: ".$calls{$callid}->{CALLTIME} ."\n"; print "COMPLETE: ".$calls{$callid}->{COMPLETE} ."\n"; print "COMPLETEWHO: ".$calls{$callid}->{COMPLETEWHO} ."\n"; print "MSG: ".$calls{$callid}->{MSG} ."\n"; if ( $dcl ) { # detailed call log print $calls{$callid}->{LOG}; } } if ( $html ) { print "
"; }
}
if ( $q ) {
if ( ! $html ) { print "#########\n"; print "Queue Stats:\n"; print "#########\n"; while ( my ($queueid, $value) = each(%queues) ) { next if $queueid == 'NONE';
print 'Queue Name: '.$qnames{$queueid}.' ('.$queueid.")\n"; print "Picked up Calls: ".$queues{$queueid}->{TOTALPICKEDUP}."(".$queues{$queueid}->{COMPLETECALLER}."/".$queues{$queueid}->{COMPLETEAGENT}. ")\n"; print "ABANDON: " .$queues{$queueid}->{ABANDON}. "\n"; print "AVERAGE HOLDTIME: ".$queues{$queueid}->{AVERAGEHOLDTIME}." (s)\n"; print "AVERAGE ABANDONED HOLDTIME: ".$queues{$queueid}->{AVERAGEABHOLDTIME}." (s)\n"; print "CALL IN PROGRESS: ".$queues{$queueid}->{INPROGRESS}."\n";
if ( $a ) {my $agents = $queues{$queueid}->{agent}; print "Agents:\n"; while ( my ($key, $value) = each(%$agents) ) { print "Agent: ".$extensions{$key}. " Ringnoanswer: ".$$agents{$key}->{RINGNOANSWER}. " Complete: ".$$agents{$key}->{COMPLETE}."\n"; } } } } else {
print "
Queue Stats
\n"; print "
"; print "\n"; #while ( my ($queueid,$value) = each(%queues) ) { for my $queueid ( sort keys %queues ) { next if $queueid == 'NONE'; print "\n"; } print "Queue(id) | Calls Completed (by Caller/by Agent) |
Average Hold Time (s) (for completed calls) |
Calls Abandoned | Average Abandoned Time (s) | Calls In Progress |
---|---|---|---|---|---|
<a title=\"details\" href=\"/perl/asterisklogparse.pl\?q=1\&queryqueue=$queueid\&c=1\">$qnames{$queueid}</a> ( $queueid ) | $queues{$queueid}->{TOTALPICKEDUP} ( $queues{$queueid}->{COMPLETECALLER} / $queues{$queueid}->{COMPLETEAGENT} ) | $queues{$queueid}->{AVERAGEHOLDTIME} | $queues{$queueid}->{ABANDON} | $queues{$queueid}->{AVERAGEABHOLDTIME} | $queues{$queueid}->{INPROGRESS} |
\n"
}
}