QueueMetrics FAQs Frequently Asked Questions
QueueMetrics reports
- Completion of any call in the queue appears as Caller Completed.
- Printing and mailing out a report automatically
- Taking an activity trace
- Understanding QueueMetrics agent name rewriting
- I don't see agent sessions without calls
- Why do I get a message "The report exceeds the number of licensed agents"?
- After installing the license key, QM does not even start!
- Why agents that do not logon are not a good idea
- Why aren't all reports showing up in my copy of QM?
- Figures do not match when running hourly versus daily reports
- Help! QueueMetrics reports shows no data at all!
- Why do I see duplicate calls in the reports with a Caller-ID set to '*'?
- Transfers from the queue are not reported in QM
- Using multi-stint mode in reports
- Missing records on KeyPress
- Handling 'Ghost Calls'
- How do I make some queues visible by some users only?
- How to use subqueues
- Tracking hourly call distribution for multiple incoming DIDs
- Why does the Agent report show all Agent levels as "Undefined"?
- Tracking the incoming DID on a queue
- How to set the Caller-ID
- How to monitor multiple queues at once
QueueMetrics real-time page
- How do I enable actions (login, logoff, transfer....) on the Realtime page?
- Why do I get a message "The report exceeds the number of licensed agents"?
- Why agents that do not logon are not a good idea
- What is the time period considered for realtime?
- Detecting realtime timing issues
- AMI connection not working in Asterisk 1.6
- Help! The Real-time page is showing no data!
- How do I modify or turn off the sounds on the Real-time page?
- Tracking timing and time-zone problems in QueueMetrics
- Transfers from the queue are not reported in QM
- Missing records on KeyPress
- How to let Agents access the Realtime page
- Handling 'Ghost Calls'
- How is the field "N.Agents" computed?
- How do I make some queues visible by some users only?
- Why do some calls disappear from the Realtime page?
- How to set the Caller-ID
- How to fix timing problems in the realtime page when using MySQL storage
- How to monitor multiple queues at once
- How to change the realtime page refresh time
- Logged-on agents disappear at midnight
- Non existent calls taken when no agents were available seem to be lagging in the queue
- What do the fields named UNK and BSY mean?
Configuring Agents
- "Agent status cannot be determined" after logging on
- Why do I get wrong agent names displayed?
- AMI connection not working in Asterisk 1.6
- Transfers from the queue are not reported in QM
- How to let Agents access the Realtime page
- Error: "You do not have the rights to perform the requested action."
- Using fully dynamic members with QM 1.4 and Asterisk 1.4
- Using fully dynamic members with QM 1.4 and Asterisk 1.2
- Logged-on agents disappear at midnight
- Fully dynamic agents and QueueMetrics
QueueMetrics installation
- QueueMetrics logs are filling up all of my disk
- "Agent status cannot be determined" after logging on
- Moving a QueueMetrics instance to a new server
- Installing QueueMetrics on a Debian or Ubuntu server
- How do I secure access from a given subnet only?
- How do I run QueueMetrics with Java Security?
- Backing-up a QueueMetrics system
- Metadata file does not match checksum in Yum
- Deploying QueueMetrics with JBoss
- How to install and update QueueMetrics using yum
MySQL storage and QLoaderd
- How do I remove duplicate rows from the queue_log table?
- Can I use logrotate for the queue_log file?
- Repairing a MySQL database
- How to upload an older queue_log file
- How to use subqueues
- The Qloaderd process will stop working at night
QueueMetrics configuration
- QueueMetrics logs are filling up all of my disk
- Backing up and restoring QueueMetrics
- Using UTF-8 encoding
- Updating QueueMetrics and keeping the key and configuration
- AMI connection not working in Asterisk 1.6
- Exception: java.nio.BufferOverflowException - Encoding problems when reading files
- Help! QueueMetrics reports shows no data at all!
- Help! The Real-time page is showing no data!
- Why do I see duplicate calls in the reports with a Caller-ID set to '*'?
- Installing QueueMetrics on a Debian or Ubuntu server
- How do I modify or turn off the sounds on the Real-time page?
- How to let Agents access the Realtime page
- Using a different Asterisk manager port
- How to write internationalized data to the database
- How to use subqueues
- How to change the realtime page refresh time
- Logged-on agents disappear at midnight
Running outbound campaigns
- Configuring ViciDial for QueueMetrics
- Tracking agent extensions for outbound dialing
- Why doesn't my AGI file seem to work
- How to implement a dial-out queue
Common QueueMetrics errors
- IE8 error: "The following error occurred in the Transaction handler: Il verbo '...' non e' stato trovato tra quelli caricati."
- How do I remove duplicate rows from the queue_log table?
- Why do I get a message "The report exceeds the number of licensed agents"?
- After installing the license key, QM does not even start!
- Can I use logrotate for the queue_log file?
- Error: Out of memory error - Tuning Java Memory
- Mixed-up pages after an upgrade
- Exception: java.nio.BufferOverflowException - Encoding problems when reading files
- Tracking timing and time-zone problems in QueueMetrics
- XML-RPC not working: Could not instantiate XMLReader parser
- Error: "You do not have the rights to perform the requested action."
- Metadata file does not match checksum in Yum
- Error: OutOfMemory: Unable to create new native thread
- Some pages won't compile and show JasperException
- Page encoding problems (Getting "JasperException: Exception parsing file" or "JasperException Error: Cannot read file" errors)
- The Qloaderd process will stop working at night
- Why do I get the error 'Bad interpreter' trying to run a shell file or an AGI?
- Why doesn't my AGI file seem to work
- Error: java.sql.SQLException: Cannot convert value '0000-00-00 00:00:00' from column 14 to TIMESTAMP
- Error: "Il verbo '.....' richiede una chiave non disponibile all'utente corrente"
- Java Security errors
- Error: java.sql.SQLException: Access denied for user 'queuemetrics'@'mydb' (using password: YES)
- Error: java.sql.SQLException: Data source rejected establishment of connection, message from server: 'Host 'localhost.localdomain' is not allowed to connect to this MySQL server'
- Error: "Problema update DB: com.mysql.jdbc.MysqlDataTruncation ..."
- Error: java.sql.SQLException: Invalid authorization specification message from server: 'Access denied for user: 'queuemetrics@localhost.localdomain' (Using password: YES)'
- Error: java.lang.NoSuchMethodError
- Error: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
- QueueMetrics does not seem to work with GCJ
- Error: "Il verbo '.....' non consente la creazione di una nuova sessione"
MySQL-related issues
- How do I remove duplicate rows from the queue_log table?
- Can I use logrotate for the queue_log file?
- Using UTF-8 encoding
- Repairing a MySQL database
- How to upload an older queue_log file
- How to write internationalized data to the database
- How to use subqueues
- The Qloaderd process will stop working at night
- How to fix timing problems in the realtime page when using MySQL storage
- Error: java.sql.SQLException: Cannot convert value '0000-00-00 00:00:00' from column 14 to TIMESTAMP
- Error: java.sql.SQLException: Access denied for user 'queuemetrics'@'mydb' (using password: YES)
- Error: java.sql.SQLException: Data source rejected establishment of connection, message from server: 'Host 'localhost.localdomain' is not allowed to connect to this MySQL server'
- Error: "Problema update DB: com.mysql.jdbc.MysqlDataTruncation ..."
- Error: java.sql.SQLException: Invalid authorization specification message from server: 'Access denied for user: 'queuemetrics@localhost.localdomain' (Using password: YES)'
- Error: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
XML-RPC issues
License-related issues
- Can I move the license key when installing a new server?
- Why do I get a message "The report exceeds the number of licensed agents"?
- After installing the license key, QM does not even start!
Advanced configuration
- Error: Out of memory error - Tuning Java Memory
- Using UTF-8 encoding
- Repairing a MySQL database
- Removing Tomcat logging
- Updating the Java SDK
How do I enable actions (login, logoff, transfer....) on the Realtime page?
Since QueueMetrics 12.10, the Realtime page lets you perform a set of actions that are sent to Asterisk for processing. These include:- Logging agents on and off
- Pausing and unpausing agents
- Transferring calls
- Sending SMS
- Listening to live calls
- A security key: each action is enabled by giving your users a specific security key. You should esit the user or class profile and add the required key
- A configuration item: the action is possible only if we tell QM that the action is allowed and how to perform it (that is, where is the Asterisk dialplan it should go in order to have the action performed). If you upgrade from an earlier version, you should manually add the configuration items in your configuration.properties. All such properties start with "callfile.*"
- A dialplan item: the Asterisk dialplan should include an extension (generally in the supplied context named queuemetrics) that actually performs the requested action
- First we add the key RT_TRANSFERCALL to the Admin class. A list of keys for each feature can be found in the Qm user manual, appendix B: Security keys
- Then we add the following configuration item:
callfile.transfercall.enabled=true
callfile.transfercall.channel=Local/10@queuemetrics/n
callfile.transfercall.extension=31
callfile.transfercall.context=queuemetrics - The Asterisk dialplan should include a stanza like:
exten => 31,1,NoOp( " QM: Call redirect ,ade by ${QM_LOGIN} for callID: ${CALLID} to extension ${REDIR_EXT}")
exten => 31,n,ChannelRedirect(${CALLID},from-internal,${REDIR_EXT},1)
exten => 31,n,Hangup
More details can be found in the Qm user manual, appendix C. The [queuemetrics] context
Completion of any call in the queue appears as Caller Completed.
All calls processed by QueueMetrics are reported as if the caller hung up, even when it was the agent hanging up.This is a known issue with FreePBX 2.10 and you can easily fix it by editing the dialplan as explained in the Asterisk Forums.
Printing and mailing out a report automatically
Since QueueMetrics 13.04, it is possible to have QueueMetrics generate a report in PDF or XLS format, and download it or sent it automatically to a group of recipients by e-mail. The following notes only apply to earlier versions of QueueMetrics.It is possible to print a full report to PDF automatically and have it emailed periodically with no human intervention.
In order to run the following script, you need to install the following packages on your server:
yum install htmldoc
yum install nailThe script is as follows:
#! /bin/bash QM_SERVER=http://127.0.0.1:8080
QM_WEBAPP=DAILY
QM_QUEUE=q1
QM_PERIOD=d90
QM_USER=robot
QM_PASS=robot
EMAIL=mu@email
# cleanup images
rm -rf $QM_WEBAPP/
rm -rf img/
# download images
wget -nH -k -K -p "$QM_SERVER/$QM_WEBAPP/qm_rep.do?user=$QM_USER&pass=$QM_PASS&queues=none&period=t1"
mv $QM_WEBAPP/img/ .
wget -o img/shade-histo.gif "$QM_SERVER/$QM_WEBAPP/img/shade-histo.gif"
# download report
wget -nH -k -K -p -l 1 -O report.html "$QM_SERVER/$QM_WEBAPP/qm_rep.do?user=$QM_USER&pass=$QM_PASS&queues=$QM_QUEUE&period=$QM_PERIOD"
# convert to PDF
htmldoc --webpage --size 11x8.5in -f myreport.pdf myreport.html
# mail out
echo "Your daily report is attached as a PDF" | env MAILRC=/dev/null from=qm-server@example.com smtp=mail.example.com nail -n -s"Daily Report" -a myreport.pdf $EMAIL
In order to run the script, make sure that the ROBOT user is enabled in your QueueMetrics installation (it is disabled by default).
QueueMetrics logs are filling up all of my disk
QueueMetrics produces a detailed activity at the container level that lets us diagnose performance issues and technical errors.These logs are NOT automatically deleted in any way so they may end up filling all of the disk space if they are never purged.
As disk space is very cheap these days, we advise in any case to make a backup before removing files and data - what is removed cannot be restored.
The system log
The system log is where QM keeps information about actions performed and failed and successful log-ons. You can purge it manually by running the following queries:
mysql> delete from arch_syslog where sys_dt_creazione < DATE_SUB( NOW(), INTERVAL 90 DAY );
Query OK, 756 rows affected (0.04 sec)
mysql> optimize table arch_syslog;Tomcat log files
Tomcat keeps a running log of all activity and errors. In a standard QM installation, it should be located in /usr/local/queuemetrics/tomcat/logs.
[root@qm ~]# du --human-readable /usr/local/queuemetrics/tomcat/logs/
6.1G /usr/local/queuemetrics/tomcat/logs/
[root@qm ~]# cd /usr/local/queuemetrics/tomcat/logs/
[root@qm logs]# /etc/init.d/queuemetrics stop
[root@qm logs]# rm -f catalina.out
[root@qm logs]# rm -f localhost*.txt
[root@qm logs]# /etc/init.d/queuemetrics start
[root@qm logs]# du --human-readable /usr/local/queuemetrics/tomcat/logs/
20M /usr/local/queuemetrics/tomcat/logs/If you want, it is possible to control the logging made by Tomcat or turn it off altogether - see section "Logs and Logging" of the WombatDialer User Manual at http://wombatdialer.com/manuals/WD_UserManual-chunked/ar01s07.html#_logs_and_logging.
"Agent status cannot be determined" after logging on
After logging on or off from the agent's page, you still see the agent status as"Agent status cannot be determined".When QueueMetrics performs an action, what it actually does is to send a commandto Asterisk over AMI as an Originate request, waits a few seconds and and thenreads back the results from the queue_log.
There may be two issues here:
- if Asterisk is receiving isn't processing the request, then we have no way of knowing that it hasn't been implemented;
- if Asterisk is very slow in processing this request because (for example) it is quite busy, then it is possible that it will take a while for the request to be processed, so when the page reloads, the request may not have been loaded yet.
- Check on the AMI tester from the DBTEST page whether it is possible for QM to send commands to Asterisk and whether the relevant piece of dialplan is present in Asterisk;
- if all is well, you should monitor what Asterisk is doing at the CLI level when you receive a failed log-in/off attempt; whether the agent is actually added to the queue or not and whether the queue_log is updated.
Moving a QueueMetrics instance to a new server
If you need to move your existing QueueMetrics server to a different host and do not want to lose your current data and configuration, you can do that easily using yum. As a side effect, your system will be updated to the latest version. In this tutorial we expect that the MySQL server was on the old QM server and you want to use a new one on your new server, so you will have to move the database as well. Asterisk may be local on the old server or on a separate server altogether.- Stop any qloaderd running, so the current database is in a stable state
- Make a complete backup of your existing system (configuration and database - see below)
- Stop the old QueueMetrics instance
- Install QueueMetrics using yum on your new server
- When it's working (you are able to log in), turn it off
- Edit the memory settings for your new system
- Overwrite the QueueMetrics database on the new server with the database dump from the old server
- Copy
web.xmland the various properties files from theWEB-INF/folder of the old system to the new system - Make sure the access parameters for the database are correct (they usually already are, as the database is searched for on 'localhost')
- Start the new QueueMetrics instance
- When you connect to the new QueueMetrics, it will sense that the database comes from an older version and will automatically update it, if needed
- Edit your qloaderd properties (usually stored in
/etc/sysconfig/qloaderdon the Asterisk server) so that it can upload data to the new database - Restart qloaderd
- Check that it is able to upload data to the new database (you may need to create a MySQL grant so that qloaderd can connect to the new server)
- The new system should be working now!
See also:
- Installing QueueMetrics using yum
- Backing up a QueueMetrics system and Backing up and restoring a QueueMetrics system
- Tuning Java memory
- Access Denied MySQL errors
Taking an activity trace
In order to debug a set of issues with agents not logging in correctly, we often ask users to provide an activity trace. Here is how you should do it.First and foremost, you should take an activity trace only when the PBX is idle; otherwise a number of unrelated log lines are inserted and it is hard to understand the result.
You should open the queue_log file on the PBX that is located in /var/log/asterisk/queue_log - you could e.g. issue the command:
tail -f /var/log/asterisk/queue_log
What you do now is:
- You log the agent on (from either the QM agent's page or your own login scripts)
- You send a call to the agent; have the agent answer it and hang up
- You set a status code for the call
- You pause the agent (from either the QM agent's page or your own scripts). If you do it from the QM web interface, do set a pause code.
- After a few seconds, you unpause the agent
- You log the agent off
Understanding QueueMetrics agent name rewriting
QueueMetrics was built to handle agent names as separate entities from extensions. This raises a few issues with newer versions of Asterisk, as the canonical form Agent/1234 may not be used.In order to do this, it is better if you start by taking an activity trace as described in a separate FAQ here.
The first thing that we have to implement is that if see channels appearing on the log as Local/1234@from-internal, then you have to set:
default.rewriteLocalChannels=trueThe second issue you may have is that if you use a GUI, it is possible that you see the agent names logged in "friendly" format, as e.g mike boo instead of Local/1234@from-internal. The big problem here is that this only applies to calls and not to agents logging on and off.
This typically leads to a situation where, on the real-time page, you see the agent logging on as e.g. "Mike Boo (1234)" (that's the name you gave the agent in QM) and then when he first receives a call, a new entry "agent/mike boo" appears as well.
In order to solve this, we have to tell QM that when it finds mike boo it needs to read it as Agent/1234. We do this by setting a "fiendly name" for the agent, that must be the exact string that the agent appears on the queue_log as, for our agent in the Edit Agents page of QueueMetrics.
I don't see agent sessions without calls
It is possible that when running a custom report, selecting the agents name, the queue and the date and navigating to the "Agents" tab, QueueMetrics shows no information.This happens because QueueMetrics considers an agent session without activity a logging anomaly as it is very unusual for an agent not to take at least one call throughout a shift.
However, QueueMetrics can be configured in order display these agent sessions where no calls were taken by the agent, by setting the following property to TRUE:
default.useRawAgentSessions=true
If true, shows all agent sessions. If false, shows only agent sessions with at least one call handled. (The property defaults to false).
Backing up and restoring QueueMetrics
To make a backup of a working QueueMetrics system, you should backup the following items:- The QM database by typing:
mysqldump -uqueuemetrics -pjavadude queuemetrics > database.sql
File will be located : /root/database.sql
- The web.xml and configuration.properties files being used (You canfind them under the QM webapp under WEB-INF; if you run a recent version ofQM, just look for the System path entry on the Licence page)
Files will be located (e.g.):
/usr/local/queuemetrics/webapps/queuemetrics-1.7.0.2/WEB-INF/
- The queue_log data used for input (it is advisable to this in anycase, even if you use MySQL storage, just to be on the safe side).
Files will be located: /var/log/asterisk
- Create an appropriately named database on the target machine and make it accessible to user 'queuemetrics' password 'javadude'
- Load the file using the mysql command:
input: mysql -uqueuemetrics -pjavadude queuemetrics < database.sql
- Restore web.xml, tpf.properties and configuration.properties under the WEB-INF directory of the new QM instance
- Then open up GUI window where QueueMetrics is located (e.g. http://127.0.0.1:8080/queuemetrics ) and run the DB updater wizard to repair.
IE8 error: "The following error occurred in the Transaction handler: Il verbo '...' non e' stato trovato tra quelli caricati."
This basically means that the controller (the servlet /tpf ) received an empty HTTP request, so it does not know what to do with it.
To resolve the issue make sure that cookies are set to ON in IE8 Enhanced Security Mode.
How do I remove duplicate rows from the queue_log table?
If more than one instance of qloaderd are running concurrently, this will lead to duplicate entries within the queue_log table. These entries must be removed by using the following procedure (requires MySQL 5):1. Stop all qloaderd's - you should see no data being appended
2. Create a new table called queue_log_b that has the same definition as your current queue_log table:
CREATE TABLE `queue_log_b` (
`partition` varchar( 20 ) NOT NULL default '',
`time_id` int( 11 ) unsigned NOT NULL default '0',
`call_id` varchar( 30 ) NOT NULL default '',
`queue` varchar( 30 ) NOT NULL default '',
`agent` varchar( 30 ) NOT NULL default '',
`verb` varchar( 30 ) NOT NULL default '',
`data1` varchar( 200 ) NOT NULL default '',
`data2` varchar( 200 ) NOT NULL default '',
`data3` varchar( 200 ) NOT NULL default '',
`data4` varchar( 200 ) NOT NULL default '',
`data5` varchar( 200 ) NOT NULL default '',
`serverid` varchar( 10 ) NOT NULL default '',
`unique_row_count` int( 10 ) unsigned NOT NULL AUTO_INCREMENT ,
KEY `idx_sel` ( `partition` , `time_id` , `queue` ( 2 ) ) ,
KEY `partizione_b` ( `partition` , `time_id` , `unique_row_count` ) ,
KEY `by_hotdesk` ( `partition` ( 5 ) , `verb` ( 5 ) , `time_id` )
) ENGINE = MYISAM DEFAULT CHARSET = latin1;
3. Copy all data from queue_log to queue_log_b
INSERT INTO queue_log_b
SELECT *
FROM queue_log
4. Delete the queue_log table
TRUNCATE TABLE queue_log5. Copy all unique rows back to queue_log
INSERT INTO queue_log (
SELECT `partition`, `time_id`, `call_id`, `queue`, `agent`,
`verb`, `data1`, `data2`, `data3`, `data4`, `data5`,
`serverid`, MIN(`unique_row_count`)
FROM queue_log_b
GROUP BY `partition`, `time_id`, `call_id`, `queue`,
`agent`, `verb`, `data1`, `data2`, `data3`,
`data4`, `data5`, `serverid`
ORDER BY time_id, MIN(unique_row_count)
)
this may take a while.
6. Restart ONE instance of qloaderd.
7. Do not forget to CLEANUP the temporary table:
DROP table queue_log_b;Can I move the license key when installing a new server?
QueueMetrics licenses are not tied to a specific server; so you can copy yor existing license from one server to another one. Of course you cannot have multiple copies of the same license active at the same time, even on the same server; this goes against the EULA and the licensing terms.The license manager tries to avoid multiple instances of the same license being active at the same time; they maystop working, block each other and even invalidate the key. This is by design a random behavior, so it is hard to tell in advance what exactly will happen.
In case you need to install and test a different server, what we usually do is that we send you a demo key to do complete the installation; then you turn off the old server, copy the key to the new one and start it. It would be better to remove the key from the old server at all, so you do not risk to turn it on accidentally.
Why do I get a message "The report exceeds the number of licensed agents"?
This error is displayed when QM senses that there are more than the maximum licensed number of agents in the dataset it is processing.This may be caused by three reasons:
- You have more agents than your license is valid for (and in this case you should purchase an elargement), or
- You have less agents than your license is valid for, but agents appear under multiple distinct codes, or
- The report covers current and past agents, that in total are more than the licensed number of agents.
You can easily check which one is your case by requesting an unlimited demo key and running the same report that displays the error; go to the "Agents on queue" report and count the number of distinct lines that appear there.
What you can do to mitigate this problem:
- Purchase a larger license key
- If you changed your agent numbering plan, avoid running reports that overlap both agent sets
- Try and run reports that do not include more than the licensed agents
- Edit the dataset manually to use the same code in case the same agent appeared under different codes (e.g. sometimes as Agent/101 other times as SIP/101).
After installing the license key, QM does not even start!
You just installed a new QueueMetrics key that you were sent by Loway; after the installation, the whole QueueMetrics webapp seems to be unavailable and displaying an error like the following one:HTTP Status 404 - /queuemetrics/
-----
type: Status report
message: /queuemetrics/
description: The requested resource (/queuemetrics/) is not available.
-----
Apache Tomcat/5.0.28 When you edit the web.xml file, you should make sure that it remains a valid XML document; in order to spot any mistakes, you can check the validity by issuing the following command after every upgrade:
xmllint web.xml(In case you do not find it on your server, you can install it easily by issuing the command yum install libxml2-devel on Red-Hat basedLinux distributions).
Can I use logrotate for the queue_log file?
On a QueueMetrics system, it is often not necessary to rotate the queue_log file.If you really need to rotate the queue_log file, you can do this provided that you are using SQL data storage and have qloaderd installed. The qloaderd process must be notified as soon as the file are rotated.
The following logrotate directive can be used:
/var/log/asterisk/queue_log {
weekly
missingok
rotate 10
notifempty
sharedscripts
create 0640 asterisk asterisk
postrotate
/etc/rc.d/init.d/qloaderd restart > /dev/null 2> /dev/null
endscript
}For further details about log file rotation, refer to the following link: log file rotation
Why agents that do not logon are not a good idea
Many call-centers prefer to have agents always logged on, that is, the queue always rings the same set of phones 24/7. This is apparently easier to set up, as agents do not have to log on when they start working and off when they stop.We advise against this method of managing agents, because:
- Even if your phones are members of the queue 24/7, it is possible that some of them occasionally go unmanned. As Asterisk has no way of knowing which phones are to be used and which are not, it will simply try and ring them in sequence; if nobody answers, it will try a different one. This raises the wait-time for the callers without giving you any benefit. You may also have callers struck for long periods on queues where nobody answers, because there is nobody to answer but Asterisk is not aware of this!
- As you have extensions and not people as end-points for your queue, it is very hard to tell who did what, whose performance was good and who answered the phone versus those who did a poor job. They all end up in the same statistics. By having people log on, it is easy to distinguish who did what. It is also easy to tell who is available at a given moment, even remotely.
- As a result of both bullets above, agents know they are reponsible for what they do and know their behavior is monitored; so they have all the right incentives to do their best.
- Agents that do not logon at every shift do not appear reliably on the RealTime monitoring in QM - see below.
See also:
What is the time period considered for realtime?
When QueueMetrics has to compute the Real-Time report, it tries to build the current situation based on what happened recently - normally since the last midnight. This usually works fine in the common case where all agents stop working at night and start working by logging on in the morning. On the other side, this produces incorrect results if your call-center works over the 24 hours, because at midnight by default all agents appear to be logged off.This choice was made in order to minimize database searching for QueueMetrics, and it works just fine in the majority of call centers. There are a few cases where this choice may have to be changed:
- If your call center stops daily, but not at midnight, you should tell QM the time when you expect all agents to be logged off. If e.g. at 4 AM you are sure all agents are logged off, you should set:
realtime.startHour=4 - If your call-center never stops, but agents work in shift of 6 hours, you should use a "sliding window" instead; this determines the maximum lookback based on a number of hours before now (make it 1.5x to 2x the length of the shift).
realtime.startHour=s8 - If your agents are always logged on, you should ignore the statuses as reported by QM, as QM has no way to reliably know if they are available or not. QM will generally log them on as they take calls within the given time window. See below for a detailed explanation of why it is not a good idea to have permanent agents.
Why aren't all reports showing up in my copy of QM?
If you updtate to a new version of QueueMetrics that includes new reports, or have new reports custom-developed for you and update your system, you will notice that they will NOT appear after upgrading QM with the old database. This is because the definitions for your existing reports do not include the new blocks that were just created.In order to add the new blocks, do the following:
- With an admin user, select Edit QueueMetrics settings -> Edit reports
- Click on a report, e.g. "All Reports"
- Choose a screen to ad dyour new report to
- When the list of times for the screen is visible, click on "Create new"
- A title and (optionally) a subtitle for the new report
- From "Data Blocks", select the new report block - you should have been given a short code like e.g. UN18 so it is easy to select in from the drop-down box
- Decide whether the new report should be visible in the "All reports" page
Error: Out of memory error - Tuning Java Memory
This error can manifest itself in a multitude of ways, the most common being an error stating:Servlet.service() for servlet LowayTransactionController threw exception java.lang.OutOfMemoryErrorThe problem with Java memory is that it is fixed, i.e. Java will not automatically use free memory unless explicityly told to do so. The default maximum memory size for most JVMs is 64 megabytes maxiumum, and it is not much if multiple users are running multi-megabyte analyses in QueueMetrics.
To tell Tomcat to use more memory than the standard pool, you have to set an environment variable before starting it up:
JAVA_OPTS="-Xms256M -Xmx512M"
export JAVA_OPTSA real-life example for a larger call-center using Sun JDK 1.6 may be the following set:
JAVA_OPTS="-server -Xms3072M -Xmx3072M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:+CMSIncrementalPacing"
export JAVA_OPTSSee http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html for more information on Java memory setting and monitoring.
See also:
- If the error you get is actually "OutOfMemory: Unable to create new native thread", see this FAQ entry.
- If the error you get is actually "java.lang.OutOfMemoryError: PermGen space", then you have to set the maximum PermGen size as detailed in the Advanced Configuration manual.
Detecting realtime timing issues
If you run MySQL storage, it is easy to check whether the time zone on the Asterisk server is correct:- Go to Home -> Edit QueueMetrics settings -> Mysql storage information
- Look at the partition that contains your Asterisk data
- Look at the "To" and "Last heartbeat" values; write them down somewhere
- Send a call to the any queue on the system and look at your watch
- Go again to Home -> Edit QueueMetrics settings -> Mysql storage information so that the page is reloaded
- You should see that the "To" and "last heartbeat" values have changed and show the time the call was placed, answered or closed (whetever happened last)
- If the values have not changed, this means your qloaderd is not running. Try and restart it
- If the values are off from what you looked up on your watch, this means that Asterisk is using a wrong time or - worse - a wrong time zone.
Why do I get wrong agent names displayed?
In order for QM to work correctly, you should not have an agent name associated with an agent at the Asterisk level; in any case, that name should not contain spaces.If in Asterisk you have a configuration like:
myvoip*CLI> agent show
123 (John Doe) available at '1234@from-internal' (musiconhold is 'default')You should remove the agent name from agents.conf or from the realtime table where it is defined; you should make sure that the logging happens as Agent/123 for calls; the in QM you can configure a mnemonic name for the agent so that it apperas in the reports.
Using UTF-8 encoding
QueueMetrics is a fully internationalized application: that is, it handles all user transaction with UTF-8 encodig, and therefore can display and accept any character for any language.Unfortunately, MySQL does not natively use UTF-8 encoding for its tables and will try to use the "current encoding" whenever possible. So you may notice that if you e.g. enter an agent's name using not-Latin characters, when you read it back from disk it appears all garbled or a series of ??? signs.
To make QM fully able to process UTF-8 strings, you should follow the steps detailed here:
1. Run the following commands on all tables of the database but the queue_log table:
ALTER TABLE `agaw_alarms` CONVERT TO CHARACTER SET utf8;
ALTER TABLE `agaw_dati` CONVERT TO CHARACTER SET utf8;
ALTER TABLE `agaw_logs` CONVERT TO CHARACTER SET utf8;
ALTER TABLE `agaw_runs` CONVERT TO CHARACTER SET utf8;
ALTER TABLE `agenti_noti` CONVERT TO CHARACTER SET utf8;
ALTER TABLE `arch_classes` CONVERT TO CHARACTER SET utf8;
ALTER TABLE `arch_syslog` CONVERT TO CHARACTER SET utf8;
ALTER TABLE `arch_users` CONVERT TO CHARACTER SET utf8;
ALTER TABLE `broadcast_msg` CONVERT TO CHARACTER SET utf8;
ALTER TABLE `call_status` CONVERT TO CHARACTER SET utf8;
ALTER TABLE `code_possibili` CONVERT TO CHARACTER SET utf8;
ALTER TABLE `dbversion` CONVERT TO CHARACTER SET utf8;
ALTER TABLE `locations` CONVERT TO CHARACTER SET utf8;
ALTER TABLE `oq_calls` CONVERT TO CHARACTER SET utf8;
ALTER TABLE `oq_notes` CONVERT TO CHARACTER SET utf8;
ALTER TABLE `oq_queues` CONVERT TO CHARACTER SET utf8;
ALTER TABLE `pause_codes` CONVERT TO CHARACTER SET utf8;
ALTER TABLE `qa_data` CONVERT TO CHARACTER SET utf8;
ALTER TABLE `qa_forms` CONVERT TO CHARACTER SET utf8;
ALTER TABLE `qa_forms_items` CONVERT TO CHARACTER SET utf8;
If your system has other tables, please do the conversion on ALL tables.
2. Open the QueueMetrics web.xml and modify the connection string adding, before the </param-value> tag, the string:
&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8<param-value>jdbc:mysql://127.0.0.1/queuemetrics?zeroDateTimeBehavior=convertToNull &jdbcCompliantTruncation=false&user=queuemetrics&password=javadude &useUnicode=true&characterEncoding=utf8&characterSetResults=utf8</param-value>It must all be written on a single line.
3. Then download the latest MySQL java connector binary package you can find at the link:http://dev.mysql.com/downloads/connector/j/5.1.html
Extract the mysql-connector-java-5.1.7-bin.jar file and copy it on your QueueMetrics box, placing in the folder /usr/share/java.
Replace the symbolic link you can find in /usr/local/queuemetrics/webapps/queuemetrics-1.x.x/WEB-INF/lib in order to have it pointing to new connector.
4. Restart the QueueMetrics service issuing a /etc/init.d/queuemetrics restart
This will enable UTF8 support.
Repairing a MySQL database
It sometimes happens that if your database server crashes, you may find that:- QM is not working because it cannot access the database
- Qloaderd is not working because it cannot write to the queue_log table
- You get weird errors when updating from an older version of QM
In order to fix these issues, you should:
- stop MySQL - THIS IS EXTREMELY IMPORTANT
/etc/init.d/mysqld stop - check tables using myisamchk (use the same case as written here):
myisamchk -c /var/lib/mysql/queuemetrics/*.MYI - if any error is shown, repair tables:
myisamchk -r /var/lib/mysql/queuemetrics/*.MYI - after that, restart Mysql:
/etc/init.d/mysqld start
Removing Tomcat logging
QueueMetrics keeps a detailed log of all transactions performed, in order to be able to find which transactions are slow and for forensic analysis (you can never know...). They may end up taking substantial disk space.First, you may want to rotate Tomcat logs using a logrotate job like the following one:
/usr/local/queuemetrics/tomcat/logs/*.* {
missingok
rotate 5
daily
compress
create 0640 root root
postrotate
/etc/init.d/queuemetrics restart > /dev/null 2> /dev/null
endscript
}<Logger className="org.apache.catalina.logger.FileLogger"
prefix="catalina_log." suffix=".txt"
timestamp="true"/> <Logger className="org.apache.catalina.logger.FileLogger"
directory="logs" prefix="localhost_log." suffix=".txt"
timestamp="true"/>Then edit catalina.sh and remove all logging to
"$CATALINA_BASE"/logs/catalina.out 2>&1/dev/null 2>&1Thanks to PSN for input!
Updating QueueMetrics and keeping the key and configuration
When updating QueueMetrics, whether you do that manually or using yum, you need to copy web.xml and configuration.properties from the old installetion to the new one.This is easy to do, as distinct QM applications are stored as:
/usr/local/queuemetrics/webapps/queuemetrics-1.5.0/
/usr/local/queuemetrics/webapps/queuemetrics-1.5.1/
/usr/local/queuemetrics/webapps/queuemetrics-1.5.3/Before the upgrade, make a backup of the QM database; it may be updated by the QM updater on the first run, so it is better to have a copy - just in case.
After the upgrade, have a look at the WEB-INF/README/Updating.txt file - it shows the new parameters and the new security keys that you m,ay have to enable on an existing install in order to unlock the new functionalities.
See also:
Mixed-up pages after an upgrade
After an upgrade, you notice that pages are "mixed up" - that is, not all pages show the new version on their title bar. This may lead to many different errors and malfunctions.This may be caused by two things:
- You have the page in the clients cache. Clean up the browser cache and retry.
- The Tomcat system caches are not updated. Do this to clean them up:
/etc/init.d/queuemetrics stop
rm -rf /usr/local/queuemetrics/tomcat/work/Catalina/*
/etc/init.d/queuemetrics start
Updating the Java SDK
If you want to update the Java SDK you use to run QueueMetrics, it is very easy to do it.Download and install a new version of Java SDK (from SUN, it's better - do not use GCJ).
You can install it anywhere on your system - like imagine you install it as/opt/java/jdk1.6.0b7.
As QueueMetrics accesses its own Java SDK under a symbolic link placed at /usr/local/queuemetrics/java, it is trivial to change that to use a different SDK.
cd /usr/local/queuemetrics
rm -f java
ln -s /opt/java/jdk1.6.0b7 java
To check that the new Java is working, go to the License page and check the Java version that it is using.
Figures do not match when running hourly versus daily reports
Imagine you run a report for Aug 25th, queue A, between 7 and 8 - it says there are 150 answered calls.You run it again, between 7 and 13 and look at the hourly statistics - now it says there are 154 answered calls between 7 and 8.
What happened? that's simple - between 7 and 8, some calls were queued but not yet answered - so you are going to find them, but on the "Lost" page and with status "Ongoing".
You run the report again between 7 and 9, and now you see that the call was answered - because it was answered after 8 am.
If you run a report between 7 and 8, QM only sees data that cam between 7 and 8 - not what happened before of afterwards. It's like being at 8am and asking for future data. If you want to see what happened when you have a full day of data, run a report for a full day and look at the hourly breakdowns.
AMI connection not working in Asterisk 1.6
In order to perform a set of actions in Asterisk (eg. getting Live statistics, starting channel monitoring, logging agents on and off, setting call statuses) QueueMetrics needs to connect to Asterisk over the AMI interface.In Asterisk 1.6 (AMI 1.1), in order to set up its calls, you have to make sure that the account that QM uses has ORIGINATE privileges as well as WRITE.
Exception: java.nio.BufferOverflowException - Encoding problems when reading files
If QueueMetrics crashes with an exception like:[ERR] -- Inner Exception --
Exception: java.nio.BufferOverflowException
Stack trace:
java.nio.BufferOverflowException
at java.nio.charset.CoderResult.throwException(CoderResult.java:259)
at java.lang.StringCoding$CharsetSE.encode(StringCoding.java:344)
at java.lang.StringCoding.encode(StringCoding.java:378)
at java.lang.String.getBytes(String.java:812)
at java.io.UnixFileSystem.getBooleanAttributes0(Native Method)
at java.io.UnixFileSystem.getBooleanAttributes(UnixFileSystem.java:228)
You can anyway force it to UTF-8 by changing JAVA_OPTS in the file /etc/init.d/queuemetrics:
JAVA_OPTS="-Xms512M -Xmx512M -Dfile.encoding=UTF-8"JAVA_OPTS="-Xms512M -Xmx512M -Dfile.encoding=ISO-8859-1"This error might also be triggered when reading a directory that has too many files, e.g. the place where you store audio recordings. You can override this behaviour by using the LocalFilesByDay storage model - it will also be way faster when retrieving recordings. See e.g.: http://astrecipes.net/index.php?n=387 and http://astrecipes.net/index.php?n=388
Help! QueueMetrics reports shows no data at all!
If you have activity in Asterisk but your QueueMetrics reports show no data at all - no calls processed, no agent sessions, you should check the following possible causes:- The qloaderd is not working
If you have set up QueueMetrics to use the SQL storage model, you need to make sure that the loader process on the Asterisk box is actually sending data to the QueueMetrics database. This can be easily checked by looking at the Licence page (where the storage model will be displayed) and if it is correct, by clicking on the Mysql storage information where you will see a growing number of lines in the selected partition if there is Asterisk activity and the loader is actually working. - You are reporting from the wrong partition
Check on the licence page for the storage model and the partition being currently in use. If the partition code is different, no data will be found. - You are asking for the wrong queue
The queue identifier that appears in QueueMetrics must match exactly, letter by letter, the one that appears as the queue name in Asterisk. If this is not so, the queue will not be displayed.
Help! The Real-time page is showing no data!
If the Real-time page will show no data at all - no agents logged on, no calls being processe, you should check the following items:- Make sure that reports are showing data
If they show no data, see this FAQ entry. - The time on the Asterisk server is far off from the time on the QM server
In order for the real-time page to work correctly, the clocks on the Asterisk server, the one on the QM server and the one on the MySQL server must be aligned with a sub-second difference. If this is not so, QM has no way of knowing which calls are in transit and which are terminated.
In order to check this, there is a label on the Licence page that will show if there are differences between QM and its MySQL server. To assess timing differences from the Asterisk box, try and process a call and then run a report where that call appears and check if the time is correct.Luckily, it is trivial to keep the clocks aligned - see this FAQ entry.
Why do I see duplicate calls in the reports with a Caller-ID set to '*'?
If you see all (or many) calls in the Processed Calls or the Lost Calls reports as being present twice with the same start hour, the first time having a correct Caller-ID and the second time displaying '*' in the Caller-ID field, this means that you have duplicate data in your database.This is usually caused by having mutiple instances of the qloaderd running at the same time - maybe you run them manually, or one instance was not stopped correctly during a restart. Stop them all manually and restart just one.
In order to "clean up" the database, use the queuePartialUpdater tool that ships with the qloaderd - it will basically unload a queue_log file and will reload it.
Installing QueueMetrics on a Debian or Ubuntu server
While on RedHat-derived systems a fully automated install using yum is available, on Debian the installation must be performed manually when running as root.First, we make available the repository for Java:
# nano /etc/apt/sources.listdeb http://ftp.hk.debian.org/debian/ etch main contrib non-free
deb-src http://ftp.hk.debian.org/debian/ etch main contrib non-free# apt-get install sun-java5-jdk# update-alternatives --config java
# update-alternatives --config javac
# export JAVA_HOME="/usr/lib/jvm/java-1.5.0-sun"# java -versionjava version "1.5.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_10-b03)
Java HotSpot(TM) Client VM (build 1.5.0_10-b03, mixed mode, sharing)
# apt-get install tomcat5.5 tomcat5.5-admin tomcat5.5-webapps# nano /etc/init.d/tomcat5.5TOMCAT5_SECURITY=yes to no. Now let's prepare the database:
# mysql --user root -p Mysql> CREATE DATABASE queuemetrics;
Mysql> GRANT ALL PRIVILEGES ON queuemetrics.* TO 'queuemetrics'@'localhost' IDENTIFIED BY 'javadude';
Mysql> quit # cd /var/lib/tomcat5.5/webapps
# wget http://queuemetrics.com/download/QueueMetrics-1.5.4-trial.tar.gz
# tar -xvzf QueueMetrics-1.5.4-trial.tar.gz
# mv queuemetrics-1.5.4 queuemetrics # cd /var/lib/tomcat5.5/webapps/queuemetrics/WEB-INF/README/
# mysql --user=queuemetrics --password=javadude queuemetrics < queuemetrics_sample.sql # cd /var/lib/tomcat5.5/webapps/queuemetrics/WEB-INF/lib/
# wget http://mirrors.uol.com.br/pub/mysql/Downloads/Connector-J/mysql-connector-java-5.0.5.tar.gz
# tar -xvzf mysql-connector-java-5.0.0.tar.gz
# cp mysql-connector-java-5.0.5/mysql-connector-java-5.0.5-bin.jar /var/lib/tomcat5.5/webapps/queuemetrics/WEB-INF/lib/http://myserver:8080/queuemetrics to access QM.
How do I modify or turn off the sounds on the Real-time page?
The default Real-time page that ships with QueueMetrics will play sounds when yellow or red alarms are triggered. The sounds played, or whether to play any, are controlled by a couple of system properties in the configuration.properties file:sound.yellowAlarm=http://myserver/audioYellow.wav
sound.redAlarm=http://myserver/audioRed.wavOf course, alarm thresholds are user configurable from the Queue editor page.
How do I secure access from a given subnet only?
Very often, you will want to make sure that the QueueMetrics application is accessible only from a given subnet. Even if QueueMetrics has its own security mechanism built-in, denying access to all clients that have no right to access QM will surely improve security.In order to do so, you just edit the file: /usr/local/queuemetrics/tomcat/conf/Catalina/localhost/queuemetrics.xml so that it looks like the following one.
<Context docBase="/usr/local/queuemetrics/webapps/queuemetrics-1.5.1"
path="/queuemetrics"> <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127.0.0.1"/>
</Context>
- allow="1.2.3.4, 1.2.3.5, 1.2.3.7" to specify multiple IP addresses, or
- allow="128.117.140.*" to specify a full class.
Please note that the queuemetrics.xml file is rebuilt upon automatic update, so you will have to edit it after running "yum update".
How to upload an older queue_log file
Imagine you have a queue_log file that uploads to partition P003, and is missing from timestamp 100 to 150; and imagine that old data is available in a file called queue_log.old- Make sure there is no data in the table for partition P003 between timestamps 100 and 150.
e.g SELECT * FROM queue_log WHERE partition='P003' AND time_id BETWEEN 100 and 150 - Stop importing on partition P003
- Move queue_log data newer than timestamp 150 to a new partition (eg P003B)
e.g. UPDATE queue_log SET partition = 'P003B' WHERE partition='P003' AND time_id > 150 - Run the qloaderd on your queue_log.old file, so that it will load all data.
You will have to watch its log file to se when it ends adding lines. - Check that all data has been loaded
e.g. SELECT count(*) FROM queue_log WHERE partition='P003' AND time_id BETWEEN 100 and 150 - Stop the qloader process
- Move back newer data from P003B to P003
e.g UPDATE queue_log SET partition='P003' WHERE partition='P003B' - Point qloaderd to your normal queue_log file, and restart normal importing
Tracking timing and time-zone problems in QueueMetrics
It sometimes happens that a new QueueMetrics install has time-zone problems on a specified box. Generally speaking, the local time for the QueueMetrics instance should be the same as your own local time, and so should be for the MySQL server and the Asterisk server it relies on.Small timing discrepancies can cause many problems, like calls not shown, wrong call duration and wait times on the realtime page, or even calls not showing at all on the realtime page.
Generally speaking, the first thing you should do if you suspect a timing problem is run a command that will sync the system clock with an high-precision atomic clock on all involved machines, for example:
ntpdate ntp.ien.it
If you want to see the current clock and time zone for the QueueMetrics server and its MySQL instance, just click on the Licence page and those values will be shown. It's important that there is no difference between those values.
If one of the clocks is very different from the current time, it is usually a time zone problem on your box. This can usually be solved/detected running the following commands:
[root@asterisk1 ~]# hwclock --show
[root@asterisk1 ~]# date -R
[root@asterisk1 ~]# date
[root@asterisk1 ~]# more /etc/sysconfig/clock
- Set the TZ environment variable, like export TZ="US/Eastern" in the startup script you use for the QueueMetrics server
- Add the following option to the JAVA_OPTS environment variable: -Duser.timezone=US/Eastern in the startup script you use for the QueueMetrics server.
For example, if you live in a place that is GMT+5, you could change the /etc/init.d/queuemetrics init script so that it has an options line like:
export JAVA_OPTS="-Xms128M -Xmx128M -server -Duser.timezone=GMT+05:00"After saving and restarting QM, if you go to the Realtime page, you should see that the time is now correct.
Transfers from the queue are not reported in QM
If your agents on a queue use to transfer calls out to other callers or to other queues, you may notice that this is not reported correctly by QueueMetrics. You may also notice that if you use agent channels, an agent stays idle after the transfer until the transferred call is over.Unfortunately this is "by design"; this is because when you use the Attended transfer button on the agent's phone, the main PBX is not notified that the call is "handed-over", so it still thinks it's connected to the original agent. The official documentation says that "transfers performed by SIP UA's by way of a reinvite may not always be caught by Asterisk [...] The only way to be 100% sure that you will get this event when a transfer is performed by a queue member is to use the built-in transfer functionality of Asterisk".
So the only way there is to handle this case is then to use so-called "Unattended transfer", that is, setting the t option in the queue and then having your agent press # to start a transfer to a different extension. Unfortunately, this does not give you Attended transfer, that is, speaking to the receiver before handing over the call.
Our real-life workaround is to use the "#" unattended transfers of Asterisk to transfer calls only after having opened up a parallel conversation to negotiate with the receiver. We know it's sub-optimal, but this has been shown to work.
Using multi-stint mode in reports
When QueueMetrics run an activity report, its basic "unit of measurement" is the queue; that is the activity that your call made on a specific queue. This may lead to a situation that is harder to understand if you have spill-over queues in place, that is, if a call is not handled in one queue it is moved to a different one.In order to address this problem, queueMetrics implements a multi-stint analysis mode, where mutiple passages on different queues are "joined together", like in the following example. Imagine this call:
h 10.00.00 enters queue 1
h 10.00.59 exits queue 1
h 10.01.00 enters queue 2
h 10.01.59 exits queue 2
h 10.02.00 enters queue 3
h 10.02.30 answered on queue 3
h 10.03.00 caller hangs uph 10.00.00 lost call on "queue 1", waited for 59 seconds
h 10.01.00 lost call on "queue 2", waited for 59 seconds
h 10.02.00 answered call on "queue 3", waited for 30 seconds, duration 30 secondsh 10.00.00 call enters on queue 3, waits for 2:30, duration 30 secondsIn order to have multi-stint work correctly, you should include ALL the queues that the call was handled upon in the same report - otherwise it will not find out where the call passed.
Of course, in real-life you can run both multi-stint and single-stint analyses when querying the performance of your call-center; you use multi-stint to see the performance from the point of view of the caller, and single-stint to see what happended from the point of view of the providers, e.g. service groups.
XML-RPC not working: Could not instantiate XMLReader parser
If the XML-RPC interface of QueueMetrics is not working, i.e you get no meaningful response, you have to look up on the catalina.out file in order to detect possible problems.Xerces not installed
With Java 1.5 and Tomcat 5.5, you may encounter the problem as an error string stating redstone.xmlrpc.XmlRpcException: Could not instantiate XMLReader parser. This means the Xerces XML parser cannot be found.
If this happens, download Xerces from http://xerces.apache.org/xerces-j/ and put the file called xercesImpl.jar in your queuemetrics/WEB-INF/lib. This should solve your problems.
Missing records on KeyPress
Sometimes calls in Qm seem to go on forever... even if they have been terminated. This is often the case when your users exit the key by pressing a numeric key; some versions of Asterisk don't log this event correctly, so the call appears to be going on and on.In order to check if this is the case, you should monitor your queue_log file when you exit a call by pressing a key; you should expect a line that looks like:
1106553723|1106553678.2598|queue-f|NONE|EXITWITHKEY|3|1exten => s,1,System( echo"${EPOCH}|${UNIQUEID}|myqueue|NONE|EXITWITHKEY|key|1|" >>/var/log/asterisk/queue_log )See also Handling ghost calls.
How to let Agents access the Realtime page
It is possible to let your QueueMetrics agents access the full RealTime page and not just the Agent's page:- Create a new class for agents. You may call it RTAGENTS (Realtime Agents)
- Give your agents the following keys: USER AGENT CHPASSWD REALTIME. For the exact meaning of each key, see Appendix II of the User Manual.
- Create (or select) some agents and assign them to class RTAGENTS.
If you want your agents to be able to see only a subset of all possible queues through the Realtime page, you should see also:How do I make some queues visible by some users only?.
Please consider that running the realtime page instead of the Agent's page is extremely expensive, computationally speaking, so run a few test before deploying this in a 1000-agent setting.
Handling 'Ghost Calls'
Sometimes calls in Qm seem to go on forever... even if they have been terminated. This may be caused by two reasons:- In some versions of Asterisk, some ways of exiting a queue trace no log
Mostly on older (1.0 and 1.2) versions of Asterisk, sometimes you discover that exiting a queue in a certain manner (eg a timeout, a transfer) consistently provides no end-of-call log. This makes it impossible for QM to know that the call is over. - Asterisk sometimes randomly "forgets" to trace some end of call.
This is a problem that happens on most large systems. If this is below 1% of all calls, it should be considered normal. Some installations are almost completely unaffected while others are heavily affected.
QM handles this problem in two ways:
- The realtime page can be instructed about "anomalous" calls that will not be displayed if the wait or talk times are too long. This is what default.maxOngoingWaitTime and default.maxOngoingTalkTime are for (as the definition of "too long" varies from call center to call center).
- Since QM 1.4.5 and when running with a MySQL database, it is possible for certain administrative users to "close" ongoing ghost calls by finding them on the real-time or the historical call list (requires security key CLOSECALLS)
How do I run QueueMetrics with Java Security?
Java Security is a way to fine-tune the grants that a web-application has. This can be quite complex if you do not exactly know what a webapp is doing internally. You can set this by updating a policy file and running Tomcat in secure mode.To make sure you are running under Java Security, you can check the value of the property java.security.policy under the Licence page - if it is set to something like =/usr/local/queuemetrics/tomcat/conf/catalina.policy, then security is enabled.
The following permissions apply to QM 1.4.5 - just add them to your catalina.policy file:
grant codeBase "file:/usr/local/queuemetrics/tomcat/webapps/queuemetrics/-" {
permission java.net.SocketPermission "localhost:3306", "connect,resolve";
permission java.io.FilePermission "/var/log/asterisk/queue_log", "read";
permission java.util.PropertyPermission "*", "read,write";
permission java.lang.RuntimePermission "createClassLoader";
permission java.io.FilePermission "${java.io.tmpdir}/-", "read,write,delete";
// if you use LIVE connection to Asterisk instances:
permission java.net.SocketPermission "127.0.0.1:5038", "connect,resolve";
};- set the correct path for your QM webapp in the grant codeBase line
- set the correct path to your database
- set the cortrect path to the manager port of your Asterisk server
- if you use external XML-RPC services, you should add "connect, resolve" grants for those as well.
Configuring ViciDial for QueueMetrics
ViciDial, a widely-used outbound dialer and campaign manager, can be configured to write its call activity logs directly to the QueueMetrics call database.In ViciDial, this can be enabled as follows (Go to "System Settings"):
- Enable QueueMetrics logging: 1
- QueueMetrics server IP / DB name / DB login / DB password: These values are for the MySQL server that holds the QM database
- QueueMetrics URL: enter a fully qualified URL of your QM system, e.g. http://qmserver:8080/queuemetrics
- QueueMetrics LogID: this is the name of the QM partition ViciDial will write to. E.g. P001, or VIC.
- QueueMetrics EnterQueue Prepend: you can use this switch to prepend the campaign-id to the caller-id so you can run a breakndown using QM's are analysis. In most cases just leave that to NONE.
Backing-up a QueueMetrics system
To make a backup of a working QueueMetrics system, you should backup the following items:- The QM database
- The web.xml and configuration.properties files being used (You can find them under the QM webapp under WEB-INF; if you run a recent version of QM, just look for the System path entry on the Licence page)
- The queue_log data used for input (it is advisable to this in any case, even if you use MySQL storage, just to be on the safe side).
See also:
How is the field "N.Agents" computed?
The first cell of the top realtime panel ("N Agents") is computed as follows:- for each queue, QM looks for all agents that are KNOWN MEMBERS of that queue (that is, they have an association through QM's editor) plus all agents that are logged on dynamically to that queue
- for the grand total (first line) QM looks for all agents that appear in the report - they should match the number of lines of the lowest table
How do I make some queues visible by some users only?
In order to make sure that some users (e.g. supervisors) can only see their queues, you should use QM's security model. When you protect something with a key, this means that you protect it (physically speaking) with a lock that opens if the user holds that key in his keyring. You know that eash user has a keyring, that is the sum of the keys that belong to his current class plus the keys that he individually has.So, if you have a number of supervisors and a number of queues, you could protect each queue individually with a different key, and then give each supervisor individually the required key.
For example, you can do this:
- queueA -> key KA
- queueB -> key KB
- queueC -> no key
- queueD -> key KD
- queueE -> key KE
- supervisor Alice -> keys KA and KD
- supervisor Bob -> keys KB and KE
Please note that if you have an aggregate queue, only the key protecting the aggregate queue will be ckecked, i.e. the checks on the members will NOT be performed (so you can have an aggregate queue that behaves differently in security terms from the set of its members, if you need it).
Using a different Asterisk manager port
It is possible to switch the port QueueMetrics uses to connect to the Asterisk manager interface fom the default port 5038 to any other port - use something like:callfile.dir=tcp:dial:bingo@10.10.3.27:1234Error: "You do not have the rights to perform the requested action."
While working on the "Agent's page" and trying to log-on, log-off or pause an agent, the following error is displayed in the pop-up window after entering the Agent's code and Extension: "You do not have the rights to perform the requested action."This means that QM is trying to connect to Asterisk to run that action, but Asterisk refuses the connection. In order to make it work, the following steps should be hand-checked:
- Are the connect credentials correct?
The credentials supplied in the configuration.properties file should look like:callfile.dir=tcp:dial:bingo@1.2.3.4 - Is the dialplan context [queuemetrics] included?
You can check that by typing the following command in Asterisk:asterisk*CLI> show dialplan queuemetrics[ Context 'queuemetrics' created by 'pbx_config' ]
'10' => 1. Answer() [pbx_config] 2. Wait(10) [pbx_config]
..and a lot more stuff here.... - Are you seeing connection attempts?
If you open the Asterisk CLI, you should see a message when QM connects and disconnects. If you see nothing, there is some setup error (e.g. a firewall) that prevents QM to connect to Asterisk.
Using fully dynamic members with QM 1.4 and Asterisk 1.4
If you run QueueMetrics 1.4.1 or newer, you can fully use the new ADDMEMBER / REMOVEMEMBER to track agents logging on on a queue-by-queue basis. If you run Asterisk 1.4, most of the logging is already done correctly by Asterisk itself.In this example, we assume that:
- All agents are entered as Local/NUM@agents - feel free to use Local/XX@from-internal or whatever matches your system configuration
- The example queue you join here is called my-queue
- You will call the following pieces of dialplan:
- 422XX to log on Agent/XX to the queue my-queue
- 423XX to log off Agent/XX from the queue my-queue
- 416XX to pause Agent/XX (on all queues she's working on)
- 417XX to unpause Agent/XX
; addqueuemember - 422
exten => _422XX,1,Answer
exten => _422XX,2,AddQueueMember(my-queue,Local/${EXTEN:3}@agents)
exten => _422XX,3,Hangup
; removequeuemember - 423
exten => _423XX,1,Answer
exten => _423XX,2,RemoveQueueMember(my-queue,Local/${EXTEN:3}@agents)
exten => _423XX,3,Hangup
; agent pause
exten => _416XX,1,PauseQueueMember(|Agent/${EXTEN:3})
exten => _416XX,n,Hangup()
; agent unpause
exten => _417XX,1,UnpauseQueueMember(|Agent/${EXTEN:3})
exten => _417XX,n,Hangup()
default.rewriteLocalChannels=falseTracking agent extensions for outbound dialing
When you do outbound calling, it's easy to track the extension that is doing outbound calling. It would be nice to match the agent that is logged on to that extension.To do this, we must store the current agent's estension in a global variable:
exten => 2000,1,Answer
exten => 2000,2,NoOp( "QM: Logging on Agent/${AGENTCODE} to extension ${AGENT_EXT}@from-internal" )
exten => 2000,3,AgentCallBackLogin(${AGENTCODE}||${AGENT_EXT}@from-internal)
exten => 2000,4,Set(AGENTE_${AGENT_EXT}=${AGENTCODE}|g)
exten => 2000,5,Hangup
[queuedial]
exten => _7.,1,Set(MY_QUE=300)
exten => _7.,n,Set(MY_NUM=${EXTEN:1})
exten => _7.,n,Set(MY_AGENT=${AGENTE_${CALLERID(num)}})
exten => _7.,n,NoOp,Ag: ${MY_AGENT} N: ${MY_NUM} Q: ${MY_QUE}
......Using fully dynamic members with QM 1.4 and Asterisk 1.2
If you run QueueMetrics 1.4.1 or newer, you can fully use the new ADDMEMBER / REMOVEMEMBER to track agents logging on on a queue-by-queue basis. Unfortunately, Asterisk 1.2 does not automatically log them, so we must resort to something like the following example.In this example, we assume that:
- All agents are entered as Local/NUM@agents - feel free to use Local/XX@from-internal or whatever matches your system configuration
- The example queue you join here is called my-queue
- You will call the following pieces of dialplan:
- 422XX to log on Agent/XX to the queue my-queue
- 423XX to log off Agent/XX from the queue my-queue
- 416XX to pause Agent/XX (on all queues she's working on)
- 417XX to unpause Agent/XX
; addqueuemember - 422
exten => _422XX,1,Answer
exten => _422XX,2,AddQueueMember(my-queue,Local/${EXTEN:3}@agents)
exten => _422XX,3,System( echo "${EPOCH}|${UNIQUEID}|my-queue|Agent/${EXTEN:3}|ADDMEMBER|-" >> /var/log/asterisk/queue_log )
exten => _422XX,4,DBput(dynlogin/log_Agent-${EXTEN:3}=${EPOCH})
exten => _422XX,5,Hangup
; removequeuemember - 423
exten => _423XX,1,Answer
exten => _423XX,2,RemoveQueueMember(my-queue,Local/${EXTEN:3}@agents)
exten => _423XX,3,DBget(ORGEPOCH=dynlogin/log_Agent-${EXTEN:3})
exten => _423XX,4,Set(RV=$[${EPOCH} - ${ORGEPOCH}])
exten => _423XX,5,GotoIf($["${RV}" = "0"]?8:6)
exten => _423XX,6,System( echo "${EPOCH}|${UNIQUEID}|my-queue|Agent/${EXTEN:3}|REMOVEMEMBER|-|${RV}" >> /var/log/asterisk/queue_log )
exten => _423XX,7,DBdel(dynlogin/log_Agent-${EXTEN:3})
exten => _423XX,8,Hangup
; agent pause
exten => _416XX,1,PauseQueueMember(|Agent/${EXTEN:3})
exten => _416XX,n,Hangup()
; agent unpause
exten => _417XX,1,UnpauseQueueMember(|Agent/${EXTEN:3})
exten => _417XX,n,Hangup()
default.rewriteLocalChannels=falseHow to write internationalized data to the database
If you use an internationalized version of QueueMetrics for a language based on a non-Latin character set, you may find yourself unable to write strings in your own language (e.g. the name of a queue) into QueueMetrics. This is usually not caused by QueueMetrics itself (that is completely UTF-8 compliant) but by the underlying MySQL instance.In order to make sure that your charset is accepted by your database:
- Make sure that MySQL is installed in/for your language.
- Run the following commands on all tables of the database but the queue_log table:
ALTER TABLE `call_status` CHARACTER SET utf8;
ALTER TABLE `pause_codes` CHARACTER SET utf8;
.... - Modify the connection string in web.xml so that it ends with:
....&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
How to use subqueues
If you work in an environment where a single queue is used to service a number of different calling clients, it might be of interest to you to enable subqueues; i.e. to have the queue name rewritten appending a client code at the end, so that you can query them from QueueMetrics as if each client was serviced by a dedicated queue.You can also use this technique in order to have very few actual queues in your call center but you still want to differentiate callers based on their incoming DID, or the group they belong to.
To set up this feature you should:
- Be running qloaderd and being successful in using the MySQL storage in QueueMetrics
- Create the new table qlog_opencalls as described in the qloaderd documentation
- Enable subqueues changing the qloader.pl file and setting:
my $use_subqueue = 1; - when you call a queue, you pass the DID code in its URL parameter, e.g.
exten => s,8,Queue(queue-service|t|1234||180) - When qloaderd picks up the call, it will import it as queuename.code; in the example above, it would import the call as queue-service.1234.
Metadata file does not match checksum in Yum
When trying to install or update via Yum, you get an error like: Reading repository metadata in from local files
primary.xml.gz 100% |=========================| 3.7 kB 00:00
http://yum.loway.ch/RPMS/repodata/primary.xml.gz: [Errno -1] Metadata file does not match checksum
Trying other mirror.
Error: failure: repodata/primary.xml.gz from LowayResearch: [Errno 256] No more mirrors to try. yum clean all
cd /var/cache/yum/LowayResearch/
wget --cache=off http://yum.loway.ch/RPMS/repodata/filelists.xml.gz
wget --cache=off http://yum.loway.ch/RPMS/repodata/primary.xml.gz
wget --cache=off http://yum.loway.ch/RPMS/repodata/repomd.xmlError: OutOfMemory: Unable to create new native thread
After running QueueMetrics for a while, the JVM stops with the exception "OutOfMemoryError: unable to create new native thread". This is usually caused by using the wrong JVM / Tomcat / Linux Kernel set, and is usually solved by:- Installing a newer (or older) JDK, or one that is designed right for your hardware
- Installing a newer (or older) Tomcat version
See also: Java thread tuning.
Some pages won't compile and show JasperException
It sometimes happens that some pages of QueueMetrics cannot be opened; they crash during the JSP compilation stage with a "JasperException" showing that the page cannot be compiled.This is often caused by having the wrong system-wide charset encoding, so that the source files cannot be read correctly from the disk.
To check if this is your case, you should go to the Licence Page, click on the [...] link to see all Java properties and check the value of file.encoding that should be ISO-8859-1. If it's anything else, it is a good idea to tell the Java subsystem to use this as a default encoding. To do this, you have to set an environment variable before starting Tomcat:
JAVA_OPTS="-Dfile.encoding=ISO-8859-1 -Xms256M -Xmx512M"
export JAVA_OPTSSee also FAQ: Out of memory error for more information on Java setup variables.
Why do some calls disappear from the Realtime page?
You know that most call centers have a 80/20 rule (80% of the calls taken withing 20 seconds), so it is very abnormal for them to have calls answered after tens of minutes. In order to avoid showing calls that are actually logging anomalies, QueueMetrics considers calls that have been waiting too long or have conversation times too long on the realtime page as errors and does not show them anymore.The basic wait duration is 1000 seconds, but if your call center shows such calls routinely, you can change this feature or turn it off altogether through the following configuration.properties settings:
#If an ongoing call has a wait time that exceeds this value, drop it. 0: ignore
default.maxOngoingWaitTime=1000#If an ongoing call has a talk time that exceeds this value, drop it. 0: ignore
default.maxOngoingTalkTime=2000
Tracking hourly call distribution for multiple incoming DIDs
If you have multiple incoming DIDs pointing to the same queue, and you would like to track the hourly distribution of calls on each DID for planning, there is a simple thing you can do. You create a "virtual queue" for each DID, then when a call comes in into that DID, and before passing it to the actual queue that's servicing it, you write two log lines as if it was a lost call. Then you can define each "virtual queue" in QueueMetrics and run reports on it like you currently do; you will find all calls as "lost" but you do get call count, incoming caller id and hourly/daily/weekly call distribution.In practice what you do is modify the dialplan so that:
[macro-qm-lostcall] exten => s,n, .....
exten => s,n,Macro(qm-lostcall,did-11,${CALLERID(name)})
exten => s,n,Queue(service-q,,30)
exten => s,n, .....
; ${ARG1} - the name for the fake queue
; ${ARG2} - the caller id to be logged
exten => s,1,System( echo "${EPOCH}|${UNIQUEID}.1|${ARG1}|NONE|ENTERQUEUE||${ARG2}" >> /var/log/asterisk/queue_log )
exten => s,2,System( echo "${EPOCH}|${UNIQUEID}.1|${ARG1}|NONE|ABANDON|0|0|0" >> /var/log/asterisk/queue_log )
Now if you want to know what happended through the usual statistics, you run a report for queue service-q, while if you want to know about the incoming DID #11 you run a report for did-11.
See also Tracking the incoming DID on a queue.
Why does the Agent report show all Agent levels as "Undefined"?
The reason is usually pretty simple - because they are undefined. Whenever QueueMetrics runs a report on a queue, it loads the "agent level" information from that very queue definition that is being run - this means that if you use the same queue multiple times, e.g. once by itself, once as a member of an aggregate queue, you'll have to set the agent priority for all cases.In order to assign agents to a queue, you follow the following procedure:
- Go to the queue editor and select the queue you're reporting upon (from the main page, click on "Edit queue")
- Click on the agents icon for the queue you intend to work on (that's the middle icon on the right with little people showing) - you should be driven to a page with "Main", "Wrap" and "Spill" columns
- Click who is who for each level - "Main" is the first line level, "Wrap" is a backup for Main, and "Spill" is the backup for Wrap.
Page encoding problems (Getting "JasperException: Exception parsing file" or "JasperException Error: Cannot read file" errors)
Some JVM's, particularly IBM's, seem to be a bit more picky on page encoding that Sun's. The result is that some pages of QueueMetrics do not get compiled at all, resulting in one of the exceptions above.If this happens to you, please notify Loway of the pages you are having problems with, so that we can fix them for the next version. There is also a simple workaround that will make the page readable in most cases:
- Stop QueueMetrics
- Make a copy of your broken page (in this example we assume it's licence.jsp - copy licence.jsp and call it licence_OLD.jsp)
- Run the command:
iconv --from-code=ISO_8859-1 --to-code=UTF-8 --output licence.jsp licence_OLD.jsp - Restart QM
- See if the culprit page loads
Tracking the incoming DID on a queue
If you have a scenario where you have multiple incoming DIDs pointing to the same queue, and want to track how many calls you received on the queue from each of those DIDs, the easiest thing to do is use the Area Analysis function of QueueMetrics to take care of this automatically.When a call comes in, you add the DID code to the incoming Caller ID, so that you get incoming numbers like "D7-0123456" where D7 means the call was received on DID 7 and 0123456 is the original Caller-ID. Then if you go to the Area Analysis in QueueMetrics, you can ask for a call report based on a number of Caller-ID digits (like 2 in this case, to extract the first two characters of the caller), and it will break down all calls by DID code.
You may also use this same function to track other information associated with the same calls, like multiple IVR choices pointing to the same queue.
For more information on Caller-ID rewriting, see the FAQ entry "How to set the Caller-ID".
If you need a break down of calls by calling DID and time, see Tracking hourly call distribution for multiple incoming DIDs.
Deploying QueueMetrics with JBoss
It is possible to deploy QueueMetrics into a JBoss application server:- Frst, unpack QM and set the necessary config changes (like the JDBC URL in WEB-INF/web.xml)
- Create a WAR file out of the unpacked directory (see this tutorial)
- Drop the war file in the JBoss deploy directory and restart Jboss
How to set the Caller-ID
If you need to rewrite the caller-ID of the incoming call and want the rewritten number to apperar in QueueMetrics, you should set the following Asterisk dialplan variable: CALLERID(num). This variable gets written to the queue_log, so that the information can be picked up by QueueMetrics.The popular TrixBox distro sets the authenticated caller-ID name in the CALLERID(name) variable but not in CALLERID(num); the following piece of diaplan will do the trick:
[from-trunk-custom]
exten => _X.,1,Set(CALLERID(num)=${CALLERID(name)})
exten => _X.,n,Set(CALLERID(name)=${CALLERID(name)})
exten => _X.,n,Goto(from-trunk,${EXTEN},1)
(thanks to Barry for pointing this out).
The Qloaderd process will stop working at night
The Qloaderd process will send data from a machine's queue_log to a MySQL server. It was designed for maximum safety, so that in case there are connection errors it will try resubmitting the same query over and over, but we noticed that with some versions of the DBI it will not be able to reconnect successfully if the MySQL connection was terminated because of inactivity.In order to avoid this, you may want to set the inactivity timeout to a very high value, by editing or adding the following variables in the [server] section of your /etc/my.ini file:
interactive_timeout = 2764800
wait_timeout = 2764800
This will avoid MySQL marking the connection as dead when the CC is inactive for may hours.
Starting from version 1.3, Qloaderd will also issue periodical queries every 15 minutes even when there is no activity to avoid this problem.
How to fix timing problems in the realtime page when using MySQL storage
If you run QueueMetrics with MySQL storage mode, you will likely have QueueMetrics reside on a server that will be different from the one Asterisk is, and might as well be different from the one MySQL is.If the clocks of all or some of those those machines have small discrepancies, this can lead to minor problems with the realtime page, showing calls with negative or positive length offsets and sometimes completely ignoring the shortest of calls.
Those problems will be experienced only with the realtime page, while the standard reports are unaffected (as they compute durations from actual data and not by inferring them from the local time).
To fix those problems, we strongly suggest you use a high-precision time syncing utility like the NTP package found in most Linux distros, and that you run it on all servers involved (Asterisk, QueueMetrics and MySQL) in order to have highly coherent timing and logging data.
To do this, simply run the following command as root to fix your system clock:
ntpdate ntp.ien.it We strongly suggest running it daily using a cron job so that you make sure the servers are consistently time-aligned in the future.
How to monitor multiple queues at once
To monitor multiple queues at just create a composite queue, that is a queue which definition is a set of other queues; they can be inbound, outbound or mixed. To do this, log on as an administration, click on "Edit queues", then fill in the form on the bottom of the page called "Add new queue".Fill-in the following form fields:
- Alias is the name you want your composite queue to be shown as in QueueMetrics
- Queue(s) must be filled with a set of Asterisk queue names separated by the pipe symbol (like A|B|C to monitor queues A, B and C at once)
In thisway you can run a report for a composite queue and see the details of a number of queues at once (this is very useful e.g. for real-time monitoring).
We also suggest creating a queue named "00 All" that will always appear as the first in the drop-down queue selection box and will allow easy access to the overall monitoring.
How to change the realtime page refresh time
You can modify the realtime page refresh rate from the basic 20-second period to any value you choose. Just set the following property:#In how many seconds is the realtime page to refresh?
realtime.refresh_time=18
We do not suggest using a value less than 10 seconds, or the browser will flicker a bit. Time ranges in the 15-30 seconds usually work best. Please consider that decrementing the refresh timeout will add more load on the server.
Logged-on agents disappear at midnight
If your agents work in shifts around midnight, with a plain QueueMetrics installation you will see that they will "disappear" at midnight from the Realtime screen, as if they logged off, though they will continue receiving calls (and calls they receive will be reported correctly). Calls handled over the midnight (i.e. started before the midnight and ending after the midnight) may seem to have been dropped as well from the realtime screen.This is because QueueMetrics will consider agent logon information starting from the last midnight, and this arrangement works great for call centers working during the classical 9-to-5 office hours. If you need a different arrangement, you can use a "sliding window" model, where QM will look for information during a time period you define. For example, to set a sliding window of 12 hours, you would set the following property:
#The hour of the day to start real-time monitoring or sXX: sliding window of XX hours
realtime.startHour=s12
You could also set it to "s18" or "s24" to look back 18 or 24 hours respectively - of course, the longest this period, the more data QM has to process each time.
Non existent calls taken when no agents were available seem to be lagging in the queue
If you enable the maxlen, joinempty, leavewhenempty options in a queue, it is well possible that if a call enters a queue with too many waiters, or no available agents, the call is not queued but terminated immediately. Unfortunately such ghost calls seem to be present in QueueMetrics and never being taken by any agent. This is because Asterisk is not logging the piece of information that tells us that the call was rejected from the queue, so QueueMetrics has no way to know the call is not there anymore.What we do to fix this case is that whenever the queue() command terminates and goes on with the dialplan, we make sure that we output the missing information - and this is in fact pretty easy..
We configure a queue like this:
[myqueue]
exten => s,1,Queue(queuename||)
exten => s,2,System( echo "${EPOCH}|${UNIQUEID}|queuename|NONE|EXITWITHTIMEOUT|1" >> /var/log/asterisk/queue_log )
Of course this is a very simplified case, but you should get the idea of how to do it.
Fully dynamic agents and QueueMetrics
- NOTE: If you run QueueMetrics 1.4.x and would like to enable queue-by-queue logons and logoffs with fully dynamic agents, see here for Asterisk 1.2 or here for Asterisk 1.4.
For example, if your operator works on queue q1 and q2 and q3, you would do like this:
; Add Member - 422
exten => _422XX,1,Answer
exten => _422XX,2,AddQueueMember(q1,SIP/${EXTEN:3})
exten => _422XX,3,AddQueueMember(q2,SIP/${EXTEN:3})
exten => _422XX,4,AddQueueMember(q3,SIP/${EXTEN:3})
exten => _422XX,5,System( echo "${EPOCH}|${UNIQUEID}|NONE|SIP/${EXTEN:3}|AGENTLOGIN|-" >> /var/log/asterisk/queue_log )
exten => _422XX,6,DBput(dynlogin/log_Agent-${EXTEN:3}=${EPOCH})
exten => _422XX,7,Hangup
; Remove Member - 423
exten => _423XX,1,Answer
exten => _423XX,2,RemoveQueueMember(q1,SIP/${EXTEN:3})
exten => _423XX,3,RemoveQueueMember(q2,SIP/${EXTEN:3})
exten => _423XX,4,RemoveQueueMember(q3,SIP/${EXTEN:3})
exten => _423XX,5,DBget(ORGEPOCH=dynlogin/log_Agent-${EXTEN:3})
exten => _423XX,6,Set(RV=$[${EPOCH} - ${ORGEPOCH}])
exten => _423XX,7,GotoIf($["${RV}" = "0"]?10:8)
exten => _423XX,8,System( echo "${EPOCH}|${UNIQUEID}|NONE|SIP/${EXTEN:3}|AGENTLOGOFF|-|${RV}" >> /var/log/asterisk/queue_log )
exten => _423XX,9,DBdel(dynlogin/log_Agent-${EXTEN:3})
exten => _423XX,10,Hangup
If you use Local/XX@ext channel rewriting to Agent/XX, make sure to log 'Agent/${EXTEN:3}' instead of 'SIP/${EXTEN:3}'
As a further alternative, you could have your agents login in the morning to a "fake" extension producing the log line, then join each single queue without producing a log line, and then logging off in the evening to another "fake" extension producing the log line.
As a last alternative, if you need to track the actual logon-logoff times for each queue, what you have to do is to log on each queue by logging to a different agent, like:
- Operator 20 on queue q1 is Agent/q1-20
- Operator 21 on queue q2 is Agent/q2-21
default.rewriteLocalChannels=true
default.rewriteLocalWithQueue=true
; Add Member - 422
exten => _422XX,1,Answer
exten => _422XX,2,AddQueueMember(q1,SIP/${EXTEN:3})
exten => _422XX,3,System( echo "${EPOCH}|${UNIQUEID}|NONE|Agent/q1-${EXTEN:3}|AGENTLOGIN|-" >> /var/log/asterisk/queue_log )
exten => _422XX,4,DBput(dynlogin/log_Agent-q1-${EXTEN:3}=${EPOCH})
exten => _422XX,5,Hangup
; Remove Member - 423
exten => _423XX,1,Answer
exten => _423XX,2,RemoveQueueMember(q1,SIP/${EXTEN:3})
exten => _423XX,3,DBget(ORGEPOCH=dynlogin/log_Agent-q1-${EXTEN:3})
exten => _423XX,4,Set(RV=$[${EPOCH} - ${ORGEPOCH}])
exten => _423XX,5,GotoIf($["${RV}" = "0"]?8:6)
exten => _423XX,6,System( echo "${EPOCH}|${UNIQUEID}|NONE|Agent/q1-${EXTEN:3}|AGENTLOGOFF|-|${RV}" >> /var/log/asterisk/queue_log )
exten => _423XX,7,DBdel(dynlogin/log_Agent-q1-${EXTEN:3})
exten => _423XX,8,Hangup
How to install and update QueueMetrics using yum
Yum is a package manager that is used on a number of Linux systems, notably Red Hat / CentOS and derivatives like Asterisk At Home / TrixBox, in order to ease the installation and update of software packages.If your systems uses yum, you can install QueueMetrics from scratch using the following commands:
wget -P /etc/yum.repos.d http://yum.loway.it/loway.repo
yum install queuemetrics
And then following the on-screen instructions in order to create the database.The first line is needed in order to add Loway Research as one of the authorized repositories into which yum can search for packages.
To update QueueMetrics to the latest version, just use:
yum update queuemetrics
And then have a look at the Updating.txt file in order to modify the database and/or the configuration.properties file if so is needed.
As an alternative, you may want to delete it and reinstall it from scratch, as:
yum erase queuemetrics
yum install queuemetrics
Why do I get the error 'Bad interpreter' trying to run a shell file or an AGI?
If you run a command file that is written in Perl, and the file does not seem to run at all unless it is launched manually with "perl filename.pl" it is very likely that you forgot to convert it from DOS format to UNIX. You usually get the error "bad interpreter" when running it manually.To solve this problem, type dos2unix commandname - the file will be changed from DOS format to UNIX and will be immediately runnable by typing ./commandname
If this is not enough, make sure that the file is executable (chmod a+x commandname) and that the path of the Perl interpreter as specified in the first line is correct for your environment.
What do the fields named UNK and BSY mean?
In the realtime view, there are two fields that may look puzzling: BSY and UNK.- BSY is the number of agents that are currently busy on a different queue.
Like, if you have an agent that is active on queue A and queue B, when he is on conversation in queue A will be counted as BSY on queue B, as he is not actually ready to take calls in queue B. - UNK are unknown agents that are speaking on the queue.
When QueueMetrics tries to determine how many agents are ready for a queue, it takes the total number of known agents and subtracts those who are speaking, those who are on pause and those who are BSY. If an agent shows up in a queue and QM does not know that the agent is working on that queue, the agent is counted in the UNK field.
If you want to avoid having UNK agents, make sure that your QM agents-on-queue configuration actually matches the underlying Asterisk configuration.
Why doesn't my AGI file seem to work
When installing a new AGI script, sometimes Asterisk seems to reporting that the file gets executed with result 0 while the file it is not in fact being executed at all.If it does not, there are a few possible reasons:
- the script does not exist at the given agi-bin location or it is not "visible" to the user running Asterisk (solution: update unix file permisions)
- the script is not executable - try running it manually (do a "chmod a+x queueDial.agi")
- the script is in DOS mode - i.e. uses CR/LF as the line endings - and won't start from the shell (do a "dos2unix queueDial.agi" to fix it)
- check if the file /var/log/asterisk/agi-log.txt is read/writeable by Asterisk
How to implement a dial-out queue
- Note: this FAQ applies to an outdated approach. See the document "Tracing outbound calls through QueueMetrics in TrixBox" version 2.0, available form the Downloads page.
The following is is a piece of real-world dialplan one of our clients is using:
exten => _9XXX.,1,Set(MY_QUE=${EXTEN:1:3})
exten => _9XXX.,2,Set(MY_NUM=${EXTEN:4})
exten => _9XXX.,3,Set(MY_AGENT=${CALLERID(num)})
exten => _9XXX.,4,NoOp,Ag: ${MY_AGENT} N: ${MY_NUM} Q: ${MY_QUE}
exten => _9XXX.,5,MixMonitor(Q-${MY_QUE}-${UNIQUEID}.wav|b|)
exten => _9XXX.,6,DeadAGI(queueDial.agi|${MY_NUM}|Zap/g0/${MY_NUM}|q-${MY_QUE}|Agent/${MY_AGENT})
exten => _9XXX.,7,Congestion
This example needs a three digit campaign number, like '301'. If you have to dial the number 01234567 for campaign #301, you actually dial 9 301 01234567 so that the system knows on which outbound queue the call is being handled. The agent code is inferred from the current terminal it is being used and all calls are saved to disk for future reference with a name that QueueMetrics can understand (so you can listen to them with a click from the mouse).
As this feature requires making a number of changes to the Asterisk configuration, we suggest you proceed one step at a time during its implementation:
- First change the dialplan in order to have a NoOp() console output - like the example above steps 1-4 - so you can see that your changes to the dialplan are correct and do indeed work
- Then try adding the queueDial.agi in that point in the dialplan so that you are sure it is called through the diaplan (you can see it being called through the Asterisk command line interface, though it might not work yet)
- Once you are sure it is called, check if all file permissions are OK and the queueDial.agi does actually what it is supposed to do - places a call and adds lines to the queue_log. If it does not, chances are it is not being executed at all - see "Why doesn't my AGI file seem to work?"
- When everything is ready, configure QM to pick up the new queue you created.
Error: java.sql.SQLException: Cannot convert value '0000-00-00 00:00:00' from column 14 to TIMESTAMP
You are using a version of the MySQL connector that is >= 3.1. To solve this problem add the parameter zeroDateTimeBehavior=convertToNull to your JDBC connection string located in WEB-INF/web.xml, like in the following example:- jdbc:mysql://localhost/queuemetrics?zeroDateTimeBehavior=convertToNull&user=queuemetrics&password=javadude
Error: "Il verbo '.....' richiede una chiave non disponibile all'utente corrente"
You need a key you do not currently have to run the required transaction. Likely, your session timed out for inactivity, so you have no key at all associated with your profile; when you then click on a link, the system tells you that you have to log on again.Java Security errors
On some systems, notably Debian, the Tomcat package is installed by default with Java security policies active; such policies are very restrictive and may block Tomcat when trying to access the database or read files from the local file system.See the entry Running with Java security for an example ruleset that applies to QM 1.4.5.
If this is not possible, you'd better install Tomcat fresh from the tar file as described in the User Manual.
See also the Tomcat Security Manager HOW-TO for a better undertanding of the security manager.
Error: java.sql.SQLException: Access denied for user 'queuemetrics'@'mydb' (using password: YES)
The error means that the user and/or password given in WEB-INF/web.xml do not match credentials supplied with MySQL. On MySQL, try the following line: grant all privileges on queuemetrics.* to 'queuemetrics'@'mydb' identified by 'password';
Error: java.sql.SQLException: Data source rejected establishment of connection, message from server: 'Host 'localhost.localdomain' is not allowed to connect to this MySQL server'
You always think that your machine is localhost when connecting from the same host, but MySQL sometimes thinks that it's localhost.localdomain and so your credentials will not match. On MySQL, try the following line:grant all privileges on queuemetrics.* to 'queuemetrics'@'localhost.localdomain' identified by 'password';
Error: "Problema update DB: com.mysql.jdbc.MysqlDataTruncation ..."
To fix this problem, that comes with the newer versions of MySQL and Connector/J, add the parameter jdbcCompliantTruncation=false to your JDBC URI in WEB-INF/web.xml.Error: java.sql.SQLException: Invalid authorization specification message from server: 'Access denied for user: 'queuemetrics@localhost.localdomain' (Using password: YES)'
You always think that your machine is localhost when connecting from the same host, but MySQL sometimes thinks that it's localhost.localdomain and so your credentials will not match. On MySQL, try the following line:grant all privileges on queuemetrics.* to 'queuemetrics'@'localhost.localdomain' identified by 'password';
Error: java.lang.NoSuchMethodError
This error manifests itself usually after upgrading the webapp and has no apparent meaning, as the required class seems to be present in the compiled jar files. It is usually due to one of the two following causes:- An old version of the compiled classes is being cached by Tomcat, or
- Tomcat is not being restarted, i.e. Tomcat receives the shutdown command but for some reason cannot terminate
- Shut down Tomcat (check with the Unix command ps fax that no instances of java keep running after the required shutdown and - in case they do - kill them manuall with killall -9 java).
- Clean up the Tomcat class cache - delete the entire content of the directory work that is usually located within the main Tomcat directory
- Make sure that there is one and only one QueueMetrics webapp in the entire Tomcat system (look below the webapps directory and delete accordingly)
- Restart Tomcat
Error: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
The Java MySQL driver was not found. Try downloading it again, putting the appropriate JAR file in WEB-INF/lib and restarting the servlet container.QueueMetrics does not seem to work with GCJ
QueueMetrics does not currently work with GCJ 3 and seems to use a lot of CPU and memory on GCJ 4. GCJ is a free Java compiler/interpreter usually found on most Linux distributions but is not currently 100% compatible yet with the standard Java bundle - see http://gcc.gnu.org/java/.You should use an industrial-strength Java SDK instead, like the ones from Sun or IBM. Our suggestion is to go for the latest Sun SDK available.