21. Listening to calls using Pluggable Modules (PM)

Since QueueMetrics 1.4.7, the retrieval of audio recordings uses a different paradigm called Pluggable Modules. This makes it feasible to set up different modules to match the configuration of the existing system and to use them natively.

Pluggable modules are used in two areas:

In order to control which module is called, two configuration properties are set:

Each configuration property is set to the complete name of a Java class that implements the required server. Such names must be set exactly as described, or an exception will be raised. Each module can then have its own configuration properties to control its own behaviour.

21.1. PMs to match Recorded Calls

These PMs are used to find audio recordings.

21.1.1. Plain old recordings: LocalFiles

Module name: LocalFiles

Full Java Path:

it.loway.app.queuemetrics.callListen.listeners.LocalFiles

Properties used:

default.monitored_calls in a single-server environment, or cluster.SERVER.monitored_calls in a cluster

Available since:

1.4.7

This is the standard search method that comes with QueueMetrics. Basically, all directories under default.monitored_calls are explored recursively, and all audio files matching the Asterisk ID of the main call that was queued are retrieved. Therefore the call files found can be zero or more.

This PM is sub-optimal for very large call centres, where the cost of scanning through all recordings (maybe on remotely mounted disks) could take a significant time. If you are in such an environment, see the LocalFilesByDay entry.

This PM is used by default if no other server is specified in the configuration.properties file.

21.1.2. Large storage with recordings: LocalFilesByDay

Module name: LocalFilesByDay

Full Java Path:

it.loway.app.queuemetrics.callListen.listeners.LocalFilesByDay

Properties used:

default.monitored_calls in a single-server environment, or cluster.SERVER.monitored_calls in a cluster audio.lookBack for how many hours before or after midnight is a call considered a “borderline” case (default 4).

Available since:

1.4.7

This PM works exactly like the LocalFiles one, but allows using placeholders in the file path; this way, you can set the default recordings directory to handle only a subset of all recordings.

For example, if you set default.monitored_calls to /var/myrecordings/%YY-%MM/ when trying to listen to a call that was made on Jan 9, 2007 will expand to /var/myrecordings/2007-01/ therefore making the directory scanning much more manageable.

Valid placeholders include:

  • %YY → the 4-digit year when the call was made
  • %MM → the 2-digit month when the call was made
  • %DD → the 2-digit day of month when the call was made
  • %SE → in a clustered environment, the server name (all lower case)
  • %QU → the queue name (all lower case)

Though this is unlikely, it is possible that a call gets recorded on a given day and then gets queued on a different day, e.g. for calls that happen around midnight. QM handles this case by double-checking all calls within a boundary of n hours from the midnight in both the days that are divided by that midnight. This behaviour can be set using the audio.lookBack property.

Asterisk can easily adapt to recording files in a way that is compatible with this storage model, like e.g.:

. . . .
exten => 999,n,Set(MONITOR_FILENAME=/audio-nas/${STRFTIME(${EPOCH},,%Y-%m/%d)}/call-${UNIQUEID}.wav)
exten => 999,n,Queue(778,t,,)
. . . .

Will store audio files as:

/audio-nas/2011-03/10/call-123456.7890.wav

The nice part is that Asterisk will automatically create missing directories, as needed.

21.1.3. Using an external server: ClassicXmlRpcRecordings

Module name: ClassicXmlRpcRecordings

Full Java Path:

it.loway.app.queuemetrics.callListen.listeners.ClassicXmlRpcRecordings

Properties used:

default.audioRpcServer (non-clustered) or cluster.SERVER. audioRpcServer The address of the XML-RPC server implementing the QMAudio.findStoredFile interface.

Available since:

1.4.7

This is the standard XML-RPC implementation and makes it easy to create a completely custom scheme to handle recordings. The output of this function must be a single URL that can either stream the audio file or launch a player to stream that call. This is completely user-configurable.

The details of how to write an XML-RPC server for the QMAudio.findStoredFile interface can be found on the XML-RPC guide for QueueMetrics. We ship a sample implementation of such a server in the xmlrpc_audio_server.php server that comes with QueueMetrics.

See also section Section 23.11, “Enabling XML-RPC call listening and streaming”.

21.1.4. External audio recorder: OrekaWeb

Module name: OrekaWeb

Full Java Path:

it.loway.app.queuemetrics.callListen.listeners.OrekaWeb

Properties used:

* oreka.jdbcUrl points to the server where the OrekaWeb database is stored. Firewalls and MySQL user setup must allow a JDBC connection coming from the QueueMetrics server. * oreka.sipHeader is the name of the tag to be tracked in the Oreka system. If missing, it’s X-Unique-ID. * oreka.web is the URL of an OrekaWeb application - QM uses Oreka’s applets for video playback. * oreka.playersize lets you set the size of the player, e.g. "1024x780"

Available since:

1.5.1

This PM lets you offline all the audio recording to an Oreka system - see http://oreka.sourceforge.net/

This PM lets you playback audio (and optionally video) of recorder calls stored in Oreka. In order to listen to live calls, it is possible tp use either some Asterisk-based method, e.g. ClassicQMListenerRT below, or an Oreka-based methos like OrekaWebRT below.

It needs the JDBC URI to point to the Oreka database; the database must contain the following tables: orktag, orksegment, orktape, orkservice, orktagtype.

[Warning]Warning

In order to have QueueMetrics associate the Asterisk call-ids correctly, you must configure Asterisk and Oreka to store the call-id of the main leg of the call, the one upon which the Queue() command is called.

21.1.4.1. Propagating the SIP header

As Oreka is a passive recording solution based on SIP, and the call’s UniqueId is used to match a call in QueueMetrics, it is necessary for you to add the UniqueId information to the SIP headers.

If/how this can be done depends on the kind of channels you have as members of the queue.

If you have static or dynamic SIP phones as members of the queue, e.g.

  [myQueue]
  ....
  member => SIP/1234
  member => SIP/1235

you can simply use the following piece of dialplan:

  ....
  exten => s,n,SIPAddHeader(X-Unique-ID: ${UNIQUEID})
  exten => s,n,Queue(myQueue|t|30)
  ....

If instead you have other types of channels as members of the queue, e.g.

  [myQueue]
  ....
  member => Agent/101
  member => Local/102@agents

then you need to store the UniqueID in an inherited variable, e.g.

  ...
  exten => 411,2,Set(__MASTERID=${UNIQUEID})
  exten => 411,3,Queue(myQueue|t|30)

  [agents]
  exten => _XXX,1,SipAddHeader(X-Unique-ID: ${MASTERID})
  exten => _XXX,2,Dial(SIP/${EXTEN}|300)

This makes it possible to use Oreka in all common usage scenarios.

21.1.4.2. Configuring event capture in Oreka

You need to modify OrkAudio’s config.xml, under the <VoIpPlugin> section:

  <SipExtractFields>X-Unique-ID</SipExtractFields>

And restart OrkAudio.

21.1.4.3. Which version of Oreka do I need?

The minimal software you can use seems to be the commercial version (Orecx TR). This includes G729 Codec and Live Monitoring.

21.1.4.4. Video playback

Orecx is able to capture and store along with the audio recording of the call a screen capture of the agent’s workstation while the call was made. The importance of such a feature is obvious.

If a video recording is present for a given call, then the audio file will be followed by the string "[vid]" to show that it’s a joint audio and video recording.

In order to play it back, QM will not stream it through a browser but will open up the VNC player that ships with OrkWeb; therefore you must configure the oreka.web property. The applet is not used in case of audio-only recordings.

21.1.5. Using multiple PMs at once: MultiListener

Module name: MultiListener

Full Java Path:

it.loway.app.queuemetrics.callListen.listeners.MultiListener

Properties used:

’audio.multi’ lets you define a set of PMs to be queried for files (enter their names, separated by pipe) ’audio.multi.*’ specifies the properties of each listener.

Available since:

1.7.0

This PM lets you query multiple PMs in the order you specify to look for the call you are looking for. A common scenario may be the following one:

  • All calls are recorded to a local volume, e.g. /queues/audio. This is where files just recorded are held.
  • A nightly process compresses the files to MP3 and moves them to a large NAS device mounted under /mnt/nas, where they are stored separated by day.

In order to retrieve calls, we want QM to first check in /queues/audio; if nothing is found, then we will look under /mnt/nas/2010-11-23. This can be implemented with the following configuration:

# define the PM and the search order
audio.server=it.loway.app.queuemetrics.callListen.listeners.MultiListener
audio.multi=loc|nas

# first PM: local calls
audio.multi.loc=it.loway.app.queuemetrics.callListen.listeners.LocalFiles
audio.multi.loc.default.monitored_calls=/queues/audio

# second PM: NAS storage
audio.multi.nas=it.loway.app.queuemetrics.callListen.listeners.LocalFilesByDay
audio.multi.nas.default.monitored_calls=/mnt/nas/%YY-%MM-%DD

What we do here is the following:

  • We first define a MultiListener and tell it via the audio.multi property to actually query a PM called "loc" first and one called "nas" if nothing is found. You can have as many PMs as you need and you canset their names as you best see fit.
  • We specify the PM to be used for "loc" in the audio.multi.loc property. Properties to be set for it are appended to the audio.multi.PMNAME. hierarchy, as we do in this example to set the default.monitored_calls property.
  • As you can see, you can have multiple PMs of the same type as well as different, and ecah can have their own configuration properties.

21.2. PMs to match Live Calls

These PMs are used to listen to live calls.

21.2.1. Live calls through QueueMetrics: ClassicQMListenerRT

Module name: ClassicQMListenerRT

Full Java Path:

it.loway.app.queuemetrics.callListen.RTlisteners.ClassicQMListenerRT

Properties used:

For listening to inbound calls: callfile.monitoring.channel, callfile.monitoring.extension, callfile.monitoring.context; For listening to outbound calls: callfile.outmonitoring.channel, callfile.outmonitoring.extension, callfile.outmonitoring.context; In a single-server environment: callfile.dir (points to a local call-file directory or a manager interface port); In a clustered environment: cluster.SERVER.manager (points to each Asterisk server’s manager interface port)

Available since:

1.4.7

This is the standard QM behaviour: when listening to inbound or outbound calls, a popup appears and asks for a local extension. That local extension is connected to the live channel so that the local user can listen to the ongoing call.

In order for this to work, the dial-plan on each Asterisk server must implement the correct logic - an example is given in the [queuemetrics] context that comes with QueueMetrics.

This PM is used by default if no other server is specified in the configuration.properties file.

21.2.2. Live calls through an external module: ClassicXmlRpcListenerRT

Module name: ClassicXmlRpcListenerRT

Full Java Path:

it.loway.app.queuemetrics.callListen.RTlisteners.ClassicXmlRpcListenerRT

Properties used:

default.audioRpcServer (non-clustered) or cluster.SERVER. audioRpcServer The address of the XML-RPC server implementing the QMAudio.listenOngoingCalls interface.

Available since:

1.4.7

This is the standard XML-RPC implementation and makes it easy to create a completely custom scheme to handle live monitoring. The output of this function must be a single URL that will launch a player to stream that call. This is completely user-configurable.

The details of how to write an XML-RPC server for the QMAudio. listenOngoingCalls interface can be found on the XML-RPC guide for QueueMetrics. We ship a sample implementation of such a server in the xmlrpc_audio_server.php server that comes with QueueMetrics.

See also section Section 23.11, “Enabling XML-RPC call listening and streaming”

21.2.3. Live calls through Oreka: OrekaWebRT

Module name: OrekaWebRT

Full Java Path:

it.loway.app.queuemetrics.callListen.RTlisteners.OrekaWebRT

Properties used:

oreka.rtserver is the master property that tells QM if Oreka is clustered or not oreka.web is the URL of an OrekaWeb application - QM uses Oreka’s applets for playback. oreka.rtserver.xxx is used for clustered configurations.

Available since:

1.5.2

This PM lets your supervisors monitor agents using a web-based interface provided by Oreka. The supervisors will simply click on a live call and it will be streamed to them through their browser (note: a window will open and will close immediately before the popup opens. This is expected behaviour).

In order for this PM to work, your system configuration must matche these criteria:

  • You should be using Callback agents, where the agent extension is correctly filled in at logon time
  • Pop-up windows should be openable by QM - this feature is disabled by default in most modern browsers.
  • You should also select a way for this PM to choose on which Oreka server the call must be listened on.

Do not forget to set the oreka.web property in any case in order to download the playback applet.

21.2.3.1. Using only one Oreka server

If you are deploying only one Oreka server, you should set the address of the live listening port by setting oreka.rtserver to fixed and then entering the live streaming port as follows:

oreka.rtserver=fixed
oreka.rtserver.address=http://hostname:59120/?type=stream&localparty=#AGENTEXT#

This will work even on a clustered system, as long as there is only one Oreka server. Note how the agent extension is expanded in the string (see below for the full list of expansion tokens).

21.2.3.2. Using a cluster of Oreka servers

If you have a set of Oreka servers (likely because you have a cluster of Asterisk servers), you can associate a separate Oreka server to each box in the cluster. You do so by setting oreka.rtserver to cluster and then entering the live streaming port for each member of the cluster, as follows:

oreka.rtserver=cluster
oreka.rtserver.aleph=http://ork_aleph:59120/?type=stream&localparty=#AGENTEXT#
oreka.rtserver.beth=http://ork_beth:59120/?type=stream&localparty=#AGENTEXT#

In this example, all calls processed on server "aleph" will be searched on server "ork_aleph", while all calls processed on server "beth" will be processed on server "ork_beth".

21.2.3.3. Using multiple Oreka servers with UniqueID

If you have a set of Oreka servers that are not linked one-by-one to a set of Asterisk boxes, you can associate a separate Oreka server to each call in the cluster, by prepending a digit to the call’s UniqueID that will be used to know on which server each call is being handled. You do so by setting oreka.rtserver to chandigit and then entering the live streaming port for each member of the cluster, as follows:

oreka.rtserver=chandigit
oreka.rtserver.1=http://ork_aleph:59120/?type=stream&localparty=#AGENTEXT#
oreka.rtserver.2=http://ork_beth:59120/?type=stream&localparty=#AGENTEXT#

In this example, all calls which UniqueID starts wilth "1" will be handled by the "ork_aleph" server, and all calls which UniqueID start with "2" will be queries on the "ork_beth" server.

21.2.3.4. Expanded properties

The following properties are expanded in the Oreka live listening URL:

  • AGENTEXT is the numeric extension an agent is logged on from
  • AGENTCODE is the code of the agent