Quantcast
Channel: PBX Hacks » FacetPhone
Viewing all articles
Browse latest Browse all 4

Concurrent Line Usage

$
0
0

PBX Metrics…  One of the first things folks want to do with a fancy phone system is to gain access to the data that previously may have been a huge mystery.  Call centers live and die by various metrics or measurements like average handle time, occupancy rate, etc. but sometimes even basic data like maximum concurrent calls can be elusive.  Knowledge is power and also lends itself to saving big bucks!  Recently a client about to change phone service had to figure out how many outside lines they really needed.  They had 15 or 16 lines, the client thought they probably only needed 9 or 10.  No need to guess I said, lets look at the data…

Their FacetPhone system has super detailed logs about almost everything that the PBX thinks and does.  Of particular interest here is line state changes.  By examining line state changes it is easy to calculate how many lines are in use at a given point in time and tracking the max in use over a period of time provides a real hard metric that matches reality.  A line state could be things like “idle”, “ringing”, “disabled”, “connected”, etc.  The PBX process of FacetPhone (fp_pbx) logs line state changes like this:

2009-03-17 12:00:37 fp_pbx   :MSGS  :  #<line=23><user_line_stat=1>

Where “user_line_stat” can be one of:

  • 0 – Disabled
  • 1 – Idle
  • 2 – Ringing
  • 3 – Dialing
  • 4 – Connected to Station
  • 5 – Connected to IVR
  • 6 – On Hold
  • 7 – Out of Order
  • 8 – Idle w/Auto-attendant

Knowing that, we can break things down into whether the line state indicates the line is in use or is not in use.  A state of “Disabled”, “Idle”, “Out of Order”, or “Idle w/Auto-attendant” would be for a line not currently in use.  A state of “Ringing”, “Dialing”, “Connected to Station”, “Connected to IVR”, or “On Hold” would be for a line that is currently in use.  Okay!  Now we must simply follow the log entries and every time a line changes from a “not in use” state to an “in use” state we add to the current lines in use counter.  Every time a line state changes from an “in use” state to a “not in use” state we subtract from the current lines in use counter.  This task is not too overwhelming when you think about it like that.  There is no need to calculate call start times plus durations and try to figure out if the timeline of one call touches the timeline of another call or anything like that at all…  A simple UNIX/Linux shell script can handle this task quite nicely!

There are so many ways to do this… but if we want to make a pretty report out of the line state changes, and provide the maximum concurrent call data that the client needs, here is one way to do that…

First, “grep” out the pertinent log entries — no need to parse through things we are not interested in for this…

grep -h "fp_pbx.*user_line_stat" $LOGS

This will provide us a stream of only log entries like the one above.  Useful information from these log entries are:  date, time, line number, and state.  One could use a combination of “echo’s” and “cut’s” to parse out the data, but the powerful “sed” command can do it in one fell swoop:

| sed -n -u 's/^\([^ ]*\) \([^ ]*\).*line=\([0-9]*\)><user_line_stat=\([0-9]*\)
>.*$/\1 \2 \3 \4/p'

Okay, that is a little tricky looking, but it is really not too bad if you understand a little about regular expressions…  We’re using the “sed” substitute command (s/xxx/yyy/) which substitutes the replacement string (yyy) for the matched regular expression (xxx) in its input.  In our log entry, I’ve highlited the stuff we want to parse out to use in our report:

2009-03-17 12:00:37 fp_pbx   :MSGS  :  #<line=23><user_line_stat=1>

The trick we’re using here is to use sub-expression matching to grab part of our pattern to use later with the special escapes “\1″, “\2″, “\3″, and “\4″.  A sub-expressionss is matched inside a left and right parenthesis.   The first matching sub-expression can be referred to later as “\1″, the second as “\2″, etc.  So to put a matching sub-expression with the date in “\1″ we match from the beginning up to the first space with “^\(^ ]*\)”, then after skipping 1 space we do the same thing to put the time into “\2″.  All of the digits after the “line=” are put in “\3″ with “\([0-9]*\)” and then the same for putting the line state in “\4″.  Bottom line is that this “sed” command takes the log entry line above and spits out what we are interested in:

2009-03-17 12:00:37 23 1

Let’s take that stream of line state information and read it in to variables for counting and reporting…

| while read DATE TIME Y Z

So now it is just a matter of keeping track of the old line state and comparing it to the new new line state and when a line changes from a “not in use” state” to an “in use” state, then bump the concurrent lines in use counter up by one and when a line changes from an “in use” state to a “not in use” state reduce the counter by one.  Keep track of the high count to get a max lines in use at any given point number.  That’s it — pretty easy!  To turn this into an interesting report that shows the line states at every point, we can keep each line’s state in per line variables with a character code indicator so at a glance one can tell the state of any given line at any given point in time by reading the report.  At each line state change we print out all of the line states and end up with a report that looks like this:

    FacetPhone Concurrent Lines in Use & Status Report

    Line State Codes:

        x - Disabled                T - Connected (Talking)
        : - Out of Order            I - Connected to IVR
        R - Ringing                 H - On Hold
        D - Dialing                 _ - Idle

    Columns: C - Current, H - High, L - Line#, S - State, 1234567890 - Lines

   DATE      TIME    C  H L #=S  1234567890 1234567890 1234567890 1234567890 1234567890
2012-10-01 16:01:29  1  1 L 1=_  _T________ __________ __________ __________ __________
2012-10-01 16:01:34  2  2 L23=D  _T________ __________ __D_______ __________ __________
2012-10-01 16:01:34  2  2 L23=T  _T________ __________ __T_______ __________ __________
2012-10-01 16:01:34  3  3 L 1=R  RT________ __________ __T_______ __________ __________
2012-10-01 16:01:34  3  3 L 1=I  IT________ __________ __T_______ __________ __________
2012-10-01 16:01:38  3  3 L 1=T  TT________ __________ __T_______ __________ __________
2012-10-01 16:10:13  3  3 L 2=T  TT________ __________ __T_______ __________ __________
2012-10-01 16:20:09  4  4 L 3=R  TTR_______ __________ __T_______ __________ __________
2012-10-01 16:20:15  4  4 L 3=T  TTT_______ __________ __T_______ __________ __________
2012-10-01 16:21:05  3  4 L 3=_  TT________ __________ __T_______ __________ __________
2012-10-01 16:28:59  4  4 L22=D  TT________ __________ _DT_______ __________ __________
2012-10-01 16:29:00  4  4 L22=T  TT________ __________ _TT_______ __________ __________
2012-10-01 16:29:00  5  5 L 3=R  TTR_______ __________ _TT_______ __________ __________
2012-10-01 16:29:05  4  5 L22=_  TTR_______ __________ __T_______ __________ __________
2012-10-01 16:29:05  3  5 L 3=_  TT________ __________ __T_______ __________ __________
2012-10-01 16:29:05  3  5 L 3=_  TT________ __________ __T_______ __________ __________
2012-10-01 16:29:28  4  5 L22=D  TT________ __________ _DT_______ __________ __________
2012-10-01 16:29:28  4  5 L22=T  TT________ __________ _TT_______ __________ __________
2012-10-01 16:29:43  3  5 L22=_  TT________ __________ __T_______ __________ __________
2012-10-01 16:30:18  2  5 L 2=_  T_________ __________ __T_______ __________ __________

    Maximum Concurrent Calls: 5
    7423 Line State Changes Parsed

Okay!  There’s our answer… The most calls the client had at any given moment was 5.  They’ve been paying for 15 or 16 lines for years but the most they actually used at any given moment during our reporting period was 5 lines.  Quite often perception benefits from a reality check – engineering is the art of doing for 10 shillings what any fool can do for a pound…  Here is the source of the complete reporting script.  Hopefully it can give you some ideas about how easily a custom report can be created.

FACETPHONEDIR=/usr/facetphone
[ -f /etc/facetphonedir ] && . /etc/facetphonedir

[ -f "$1" ] && LOGS="$*" || {
    LOGS="$FACETPHONEDIR/logs/`date +%Y_%m`/facetphone.log*"
    LOGS="$LOGS $FACETPHONEDIR/logs/facetphone.log"
}

MAXLN=`sed -n '$s/<line=\([0-9]*\).*/\1/p' $FACETPHONEDIR/config/lines.cfg` I=0 STATES= HEADER="   DATE      TIME    C  H L #=S " while [ $I -lt $MAXLN ] do     I=`expr 1 + $I`     eval LINE$I=_     J=`expr $I % 10`     [ $J = 1 ] \ 	&& { HEADER="$HEADER 1"; STATES="$STATES \$LINE$I"; } \ 	|| { HEADER="$HEADER$J"; STATES="$STATES\$LINE$I"; } done LEGEND="    Line State Codes:         x - Disabled                T - Connected (Talking)         : - Out of Order            I - Connected to IVR         R - Ringing                 H - On Hold         D - Dialing                 _ - Idle     Columns: C - Current, H - High, L - Line#, S - State, 1234567890 - Lines" echo -e "\n    FacetPhone Concurrent Lines in Use & Status Report" echo -e "\n$LEGEND\n" echo "$HEADER" COUNT=0 HIGH=0 I=0 grep -h "fp_pbx.*user_line_stat" $LOGS \     | ( sed  -n -u 's/^\([^ ]*\) \([^ ]*\).*line=\([0-9]*\)>.*$/\1 \2 \3 \4/p'; echo FIN; ) \
    | while read DATE TIME Y Z; do

	[ "$DATE" = "FIN" ] && {
	    echo -e "\n    Maximum Concurrent Calls: $HIGH"
	    echo "    $I Line State Changes Parsed"
	    break
	}

	I=`expr 1 + $I`
	[ `expr $I % 40` = "0" ] && { echo; echo "$HEADER"; }

        [ "$Z" = "0" ] && Z=x       # Disabled
        [ "$Z" = "1" ] && Z=_       # Idle
        [ "$Z" = "2" ] && Z=R       # Ringing
        [ "$Z" = "3" ] && Z=D       # Dialing
        [ "$Z" = "4" ] && Z=T       # Connected - Station
        [ "$Z" = "5" ] && Z=I       # Connected - IVR
        [ "$Z" = "6" ] && Z=H       # On Hold
        [ "$Z" = "7" ] && Z=:       # Out of Order
        [ "$Z" = "8" ] && Z=_       # Idle - Auto-attendant

        OLDZ=`eval echo \\$LINE$Y`
        [ "$OLDZ" = "_" -o "$OLDZ" = ":" -o "$OLDZ" = "x" ] \
	    && [ "$Z" != "_" -a "$Z" != ":" -a "$Z" != "x" ] \
		&& COUNT=`expr $COUNT + 1`
        [ "$OLDZ" != "_" -a "$OLDZ" != ":" -a "$OLDZ" != "x" ] \
	    && [ "$Z" = "_" -o "$Z" = ":" -o "$Z" = "x" ] \
		&& COUNT=`expr $COUNT - 1`

        [ "$COUNT" -gt "$HIGH" ] && HIGH=$COUNT
        eval LINE$Y=$Z

        printf "%s %s%3d%3d L%2d=%c  " $DATE $TIME $COUNT $HIGH $Y $Z
	eval echo $STATES
    done

echo -e "\n$LEGEND\n"

Viewing all articles
Browse latest Browse all 4

Latest Images

Trending Articles





Latest Images