Package metrics4Asterisk.parse

Source Code of metrics4Asterisk.parse.CallMapper

package metrics4Asterisk.parse;

import metrics4Asterisk.metrics.CallMetric;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import metrics4Asterisk.util.Constants;
import org.apache.log4j.Logger;

/**
*
* The CallMapper class will parse an Asterisk queue log file and create CallMetric objects
* from the log's entries.
* @author Lance Stine
*/
public class CallMapper extends LogMapper<CallMetric> {

    private static final Logger logger = Logger.getLogger(CallMapper.class);

    /**
     * The results from the parse
     * @return
     */
    private Map<String, CallMetric> map;

    /**
     * A reg ex pattern for call ids
     */
    private Pattern pattern;

    /**
     * Construct an object that will map all calls in queue names provided in the validQueues argument
     * @param validQueues
     */
    public CallMapper(final Set<String> validQueues) {
        pattern = Pattern.compile(Constants.CALLIDREGEX);
        super.setValidValues(validQueues);
        int i = super.getValidValues() == null ? 0 : super.getValidValues().size();
        map = new HashMap<String, CallMetric>(i);
    }

    /**
     * This method will add the following rows to a map:
     * <pre>
     * 1203342126|1203342117.252|superqueue|NONE|ENTERQUEUE||anonymous
     * 1203342228|1203342010.239|superqueue|Local/6042@internal/n|COMPLETECALLER|88|122|2
     * 1203342407|1203342299.256|superqueue|Local/6009@internal/n|CONNECT|99|1203342402.257
     * 1203344442|1203344431.377|superqueue|NONE|ABANDON|5|5|2
     * 1203344444|1203344256.367|superqueue|Local/6009@internal/n|COMPLETEAGENT|12|167|1
     * The transfer event is not implemented for now. However its format is like the complete event.
     *
     * 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
     *
     * The event parameters vary. Here is their description from the asterisk docs:
     * COMPLETECALLER(holdtime|calltime|origposition)
     * ABANDON(position|origposition|waittime)
     * COMPLETEAGENT(holdtime|calltime|origposition)
     * TRANSFER(extension,context)
     * CONNECT(holdtime)
     *
     * There are duplicate paramters in the log. For instance hold time is in both complete and connect events.
     * This application will ignore the duplicate parameters from the connect event and only use them in complete events.
     *
     * Any call that has an event that is not in the rowValues argument will not be completley processed. This means that talkTime
     * may not be calculated. The best way to deal with this is to check for a 0 in a CallMetrick's exitQueueTime field. Discard any of
     * these objects from totals or show a warning that there are uncompleted calls in the data.
     *
     *
     * Problems in asterisk logging exist. Look at this line from my log file:
     * 1194666863|1194666521.24146|superqueue||CONNECT|332|1194666839.24152
     * There is no extension. This same call ID had a matching completed event without an extension as well. Always write code to
     * list anomalies like this so that the accuracy of the application isn't ruined by bad log files.
     *
     * </pre>
     * @param rowValues an array of row values
     * @param logRecordTime the time in milliseconds for this row's data
     */
    public void processRow(final String[] rowValues, final long logRecordTime) {
        String callId = rowValues[1];
        Matcher matcher = pattern.matcher(callId);

        //Only process rows with a call ID.
        if (matcher.matches()) {
            logger.debug("matching call ID " + callId);

            try {
                if (!super.getValidValues().contains(rowValues[2])) {
                    logger.debug("skipped queue " + rowValues[2]);
                    return;
                }

                String event = rowValues[4];
               
                if (!map.containsKey(callId)) {
                    if (event.equals("ENTERQUEUE")) {
                        CallMetric callMetric = new CallMetric();
                        callMetric.setEnterQueueTime(logRecordTime);
                        String queueName = rowValues[2];
                        callMetric.setQueueName(queueName);
                        callMetric.setCallId(callId);
                        logger.debug("added metric " + callMetric);
                        map.put(callId, callMetric);
                    } else {
                        logger.warn(callId + "|" + event + ": not in call map but something other than enter queue called");
                    }
                } else {
                    if (event.equals("ENTERQUEUE")) {
                        logger.warn(callId + ": ENTERQUEUE event with a key already in map");
                        return;
                    }

                    CallMetric callMetric = map.get(callId);
                    if (callMetric == null) {
                        logger.error(callId + ": not in map but should be.");
                        return;
                    }

                    logger.debug(event);
                    if (event.equals("ABANDON")) {
                        String waitTime = rowValues[7];
                        callMetric.setWaitTime(Integer.parseInt(waitTime));

                    } else if (event.equals("COMPLETECALLER") || event.equals("COMPLETEAGENT")) {
                        String talkTime = rowValues[6];
                        callMetric.setTalkTime(Integer.parseInt(talkTime));
                        String waitTime = rowValues[5];
                        callMetric.setExitQueueTime(logRecordTime);
                        callMetric.setWaitTime(Integer.parseInt(waitTime));
                    } else if (event.equals("CONNECT")) {
                        String extension = rowValues[3];
                        callMetric.setExtension(extension);
                        String connectTime = rowValues[0];
                        //make the unix timestamp into miliseconds
                        long longconnectTime = Long.parseLong(connectTime) * 1000l;
                        callMetric.setEnterQueueTime(longconnectTime);
                    }
                    logger.debug("metric is " + callMetric);
                }

            } catch (Exception e) {
                logger.error("Row ignored by exception ", e);
            }
        }
    }


    public Map<String, CallMetric> getMap() {
        return map;
    }
}
TOP

Related Classes of metrics4Asterisk.parse.CallMapper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.