queues: service level counts callers who weren't answered
withinSlaPercent was "answered within sla_seconds / answered", so a queue where a caller timed out still showed 100%. It is now the usual service level: answered within sla_seconds out of every caller the queue is done with, leaving out those who hung up before sla_seconds (nobody could have answered them in time). Timed out and turned away count as missed; callers still waiting aren't counted. Written into 04; the page label says "Callers answered within N s". Real calls: m8-t1 now shows 50% (1 answered in time, 1 timed out, the early hang-up left out) and the milestone check 67% (2 of 3), and asserts it. The check moves to queue 552 (*45552) so it doesn't clash with m8-t1's 550 on a shared database. Task: M8-T1
This commit is contained in:
1 parent
088372bff8
commit
4742ed52ea
8 files changed
+28
-17
No files matched your search
@@ -122,6 +122,10 @@ export async function queueStats(
|
||||
number | null
|
||||
>`round(avg(${queueCalls.waitSeconds}) filter (where ${answered}))::int`,
|
||||
withinSla: sql<number>`count(*) filter (where ${answered} and ${queueCalls.waitSeconds} <= ${q.slaSeconds})::int`,
|
||||
// Service level: answered within the target out of every caller the queue is done with,
|
||||
// leaving out callers still waiting and those who hung up before the target (nobody could
|
||||
// have answered them in time). Timed out and turned away count as missed.
|
||||
slaBase: sql<number>`count(*) filter (where ${queueCalls.outcome} is not null and not (${queueCalls.outcome} = 'abandoned' and ${queueCalls.waitSeconds} <= ${q.slaSeconds}))::int`,
|
||||
})
|
||||
.from(queueCalls)
|
||||
.where(
|
||||
@@ -137,6 +141,6 @@ export async function queueStats(
|
||||
abandoned: r!.abandoned,
|
||||
timedOut: r!.timedOut,
|
||||
avgWaitSeconds: r!.avgWait,
|
||||
withinSlaPercent: r!.answered ? Math.round((100 * r!.withinSla) / r!.answered) : null,
|
||||
withinSlaPercent: r!.slaBase ? Math.round((100 * r!.withinSla) / r!.slaBase) : null,
|
||||
};
|
||||
}
|
||||
@@ -240,7 +240,9 @@ describe.skipIf(!hasTestDb)('/api/queues', () => {
|
||||
abandoned: 1,
|
||||
timedOut: 2,
|
||||
avgWaitSeconds: 24,
|
||||
withinSlaPercent: 50, // 3 s yes, 45 s no (sla 20 s)
|
||||
// sla 20 s: 3 s yes; 45 s, the timeout and the turned away no; the 4 s hang-up and the
|
||||
// caller still waiting don't count
|
||||
withinSlaPercent: 25,
|
||||
});
|
||||
const [taken] = await t.db.select().from(queueCalls).where(eq(queueCalls.uniqueid, '1.1'));
|
||||
expect(taken).toMatchObject({
|
||||
|
||||
@@ -241,7 +241,7 @@ function QueueDetail({ id }: { id: string }) {
|
||||
['Timed out', s?.timedOut],
|
||||
['Average wait', s && (s.avgWaitSeconds === null ? '—' : `${s.avgWaitSeconds} s`)],
|
||||
[
|
||||
`Answered within ${q.slaSeconds} s`,
|
||||
`Callers answered within ${q.slaSeconds} s`,
|
||||
s && (s.withinSlaPercent === null ? '—' : `${s.withinSlaPercent}%`),
|
||||
],
|
||||
] as const
|
||||
|
||||
Reference in new issue
Block a user