Skip to content
DocsStart free

Queue Metrics & CDR

Every queue call writes one row to a durable CDR timing layer in the PresenceDO, and the standard contact-center KPIs (ASA, service level, abandon rate, and AHT) are derived from those four timestamps. As with agent KPIs, there’s no separate aggregation job: the metrics are a pure read over the CDR within a time window.

CREATE TABLE queue_cdr(
call_id TEXT PRIMARY KEY,
queue_id TEXT,
agent_id TEXT, -- who answered (NULL until answered)
enqueued_at INTEGER, -- entered the queue (epoch ms)
connected_at INTEGER, -- answered by an agent (NULL until answered)
ended_at INTEGER, -- talk ended (NULL until the call ends)
disposition TEXT -- offered | answered | abandoned | timeout
);

One row per offered call, written and updated across the call’s life by the same single-threaded brain that runs the ACD fence:

Lifecycle eventEffect on the row
EnqueueInsert with enqueued_at and disposition = offered.
Answer (agent confirms)Set connected_at, agent_id, disposition = answered.
Abandon / timeout (before answer)Set disposition = abandoned or timeout and ended_at.
Hang-up (after answer)Set ended_at (the talk-end).

The three timestamps enqueued_at → connected_at → ended_at are all you need to derive every KPI below.

All metrics report over [since, now] and share a service-level threshold parameter, slSec (default 20 seconds).

offered = rows for the queue in the window
answered = rows where disposition = answered
abandoned = rows where disposition ∈ { abandoned, timeout }
abandonRatePct = round( 100 × abandoned / offered ) // 0 if offered = 0

The mean wait before an agent answered, over answered calls:

wait = connected_at − enqueued_at
asaMs = round( mean(wait over answered calls) ) // 0 if none answered

The share of all offered calls answered within slSec:

slMet = answered calls where (connected_at − enqueued_at) ≤ slSec×1000
serviceLevelPct = round( 100 × slMet / offered ) // 0 if offered = 0

Note the denominator is offered, not answered: an abandoned call counts against service level, which is the stricter (and standard contact-center) definition.

The mean talk time over calls that have ended:

ahtMs = round( mean(ended_at − connected_at over answered calls with ended_at) )

AHT here is talk time. It does not yet fold in the agent’s post-call wrap_up; that’s tracked separately in agent state-time and is a planned addition to AHT.

Queue KPIs are read from the public API at GET /v1/queues (the queues scope):

{
"queues": [
{
"queue": "q_support",
"offered": 120,
"answered": 108,
"abandoned": 12,
"abandonRatePct": 10,
"asaMs": 8200,
"serviceLevelPct": 84,
"ahtMs": 254000
}
]
}
  • Configurable service-level target per queue (today slSec defaults to 20s at the report layer).
  • Wrap-up in AHT: folding post-call work into handle time.
  • Interval reporting: half-hourly buckets for the classic SL/ASA-over-time grid.
  • Full call CDR + the edge SQL database/Iceberg export for long-term retention and cross-call analysis.