Your Asterisk PBX generates thousands of data points every hour — call detail records, queue events, agent state changes, SIP channel metrics, and trunk utilization statistics. Yet most call centers running Asterisk have no way to see this data in real time. Managers rely on end-of-day spreadsheets, or worse, gut feelings.
This guide shows you how to build a complete KPI dashboard for your Asterisk call center. We'll cover which metrics to track, where the data lives, how to query it, and the fastest ways to go from zero visibility to full operational intelligence.
Why Your Asterisk Call Center Needs a KPI Dashboard
Before diving into implementation, let's be honest about what happens without proper visibility:
Without a dashboard:
- —Supervisors discover queue overflows hours after they happen
- —Managers can't answer "how are we doing today?" without pulling CDR exports
- —Agent performance reviews rely on subjective impressions rather than data
- —SLA breaches go unnoticed until the client complains
- —Staffing decisions are based on averages, not peak-hour patterns
With a well-built dashboard:
- —Real-time queue wallboards let supervisors react in seconds, not hours
- —Daily performance is visible at a glance to every stakeholder
- —Agent coaching becomes data-driven and fair
- —SLA compliance is tracked in real time with automatic alerts
- —Heatmaps reveal exactly when you need more agents (and when you're overstaffed)
According to industry benchmarks, call centers with real-time analytics dashboards reduce average wait times by 15-25% and improve first call resolution by 10-15% within the first quarter of deployment.
The 20 KPIs Every Asterisk Call Center Should Track
Not all metrics are created equal. Here's a comprehensive KPI framework organized by who needs them and how often they should be monitored.
Tier 1: Real-Time (Wallboard) — Update Every 5-10 Seconds
These are the metrics your supervisors need on a screen in front of them all day:
| KPI | Formula | Target | Data Source |
|---|---|---|---|
| Calls in Queue | Count of callers waiting | < 5 | AMI QueueStatus |
| Longest Wait Time | Max wait of current callers | < 60s | AMI QueueStatus |
| Available Agents | Agents in "Not In Use" state | > 20% of total | AMI QueueMember |
| Service Level (rolling) | (Answered within threshold / Total offered) × 100 | ≥ 80/20 | queue_log |
| Active Calls | Count of bridged channels | — | AMI CoreShowChannels |
| Abandoned (today) | Calls where caller hung up in queue | < 5% | queue_log ABANDON events |
Tier 2: Agent Performance — Update Every 30-60 Seconds
Track individual and team productivity in near-real-time:
| KPI | Formula | Target | Data Source |
|---|---|---|---|
| Average Handle Time (AHT) | (Talk Time + Hold Time + ACW) / Calls Handled | Industry: 4-6 min | CDR + queue_log |
| Agent Utilization | (Total Handle Time / Logged-In Time) × 100 | 75-85% | queue_log PAUSE/UNPAUSE |
| First Call Resolution (FCR) | (Calls resolved without callback / Total calls) × 100 | > 70% | CDR + CRM data |
| Calls per Hour | Total calls handled / Hours worked | 8-15 (varies) | queue_log CONNECT events |
| Hold Time Ratio | Total hold time / Total talk time | < 10% | CDR holdtime field |
| Transfer Rate | Transfers / Total calls × 100 | < 15% | queue_log TRANSFER events |
| After-Call Work (ACW) | Time in wrap-up after call ends | < 60s | queue_log PAUSE(ACW) |
Tier 3: Operational — Update Every 5-15 Minutes
These metrics drive tactical decisions throughout the day:
| KPI | Formula | Target | Data Source |
|---|---|---|---|
| Average Speed of Answer (ASA) | Total wait time / Calls answered | < 30s | queue_log CONNECT |
| Abandonment Rate | Abandoned / (Answered + Abandoned) × 100 | < 5% | queue_log |
| Queue Wait Time Distribution | Histogram of wait times (0-15s, 15-30s, etc.) | 80% under 30s | queue_log |
| Trunk Utilization | Active trunk channels / Total capacity × 100 | < 70% (headroom) | AMI |
| Callback Success Rate | Successful callbacks / Callback requests × 100 | > 85% | CDR + callback logs |
Tier 4: Strategic — Daily/Weekly Reports
These inform staffing, training, and business decisions:
| KPI | Formula | Target | Data Source |
|---|---|---|---|
| Cost per Call | Total operating cost / Total calls handled | Varies by industry | CDR + financials |
| Customer Satisfaction (CSAT) | Survey responses average | > 4.2/5 | Post-call survey |
| Agent Attrition Rate | Agents departed / Average headcount × 100 | < 3%/month | HR data |
Understanding Asterisk's Data Sources
Before you build anything, you need to know where the data lives. Asterisk stores call center data across several subsystems:
1. CDR (Call Detail Records)
The CDR table is your primary historical data source. Every completed call generates a record:
asterisk*CLI> cdr show status
Key CDR fields for dashboards:
-- PostgreSQL CDR table structure (typical)
CREATE TABLE cdr (
calldate TIMESTAMPTZ NOT NULL,
clid VARCHAR(80),
src VARCHAR(80), -- Caller number
dst VARCHAR(80), -- Dialed number/queue
dcontext VARCHAR(80), -- Dial context
channel VARCHAR(80), -- Originating channel
dstchannel VARCHAR(80), -- Destination channel
lastapp VARCHAR(80), -- Last application (Queue, Dial, etc.)
lastdata VARCHAR(80), -- App arguments
duration INTEGER, -- Total duration (ring + talk)
billsec INTEGER, -- Billable seconds (talk only)
disposition VARCHAR(45), -- ANSWERED, NO ANSWER, BUSY, FAILED
uniqueid VARCHAR(150), -- Unique call ID
linkedid VARCHAR(150) -- Linked ID (bridges related legs)
);
CREATE INDEX idx_cdr_calldate ON cdr (calldate);
CREATE INDEX idx_cdr_dst ON cdr (dst);
CREATE INDEX idx_cdr_disposition ON cdr (disposition);2. queue_log
This is the richest source of real-time queue data. Every queue event is logged:
-- queue_log format: time|callid|queuename|agent|event|data1|data2|data3|data4|data5
1711000000|1711000000.42|support|SIP/agent101|CONNECT|12|1711000000.42|5
1711000000|1711000000.43|sales|NONE|ABANDON|1|1|45
Key events to track:
| Event | Meaning | Dashboard Use |
|---|---|---|
| ENTERQUEUE | Caller entered queue | Queue depth, arrival rate |
| CONNECT | Agent answered | Wait time, ASA, service level |
| ABANDON | Caller hung up waiting | Abandonment rate |
| COMPLETECALLER | Caller ended call | AHT, call duration |
| COMPLETEAGENT | Agent ended call | AHT, call duration |
| RINGNOANSWER | Agent didn't answer ring | Missed calls per agent |
| TRANSFER | Call transferred | Transfer rate |
| PAUSE | Agent paused (break, ACW) | Utilization, availability |
| UNPAUSE | Agent unpaused | Utilization, availability |
| REMOVEMEMBER | Agent logged out | Staffing levels |
| ADDMEMBER | Agent logged in | Staffing levels |
Store queue_log in a database for efficient querying:
CREATE TABLE queue_log (
id BIGSERIAL PRIMARY KEY,
time TIMESTAMPTZ NOT NULL,
callid VARCHAR(80),
queuename VARCHAR(80),
agent VARCHAR(80),
event VARCHAR(32) NOT NULL,
data1 VARCHAR(100),
data2 VARCHAR(100),
data3 VARCHAR(100),
data4 VARCHAR(100),
data5 VARCHAR(100)
);
CREATE INDEX idx_qlog_time ON queue_log (time);
CREATE INDEX idx_qlog_queue_event ON queue_log (queuename, event);
CREATE INDEX idx_qlog_agent ON queue_log (agent);3. AMI (Asterisk Manager Interface)
AMI provides real-time state through a TCP socket:
Action: QueueStatus
Queue: support
Response: Success
...
Event: QueueParams
Queue: support
Calls: 3
Holdtime: 15
TalkTime: 245
Completed: 87
Abandoned: 4
ServiceLevel: 80.2
ServicelevelPerf: 85.1
...
Event: QueueMember
Queue: support
Name: Agent 101
StateInterface: SIP/agent101
Status: 1 -- 1=Not In Use, 2=In Use, 6=Ringing
Paused: 0
CallsTaken: 12
LastCall: 1711000000
4. CEL (Channel Event Logging)
For granular call-flow tracking (hold events, transfers, conferences):
CREATE TABLE cel (
id BIGSERIAL PRIMARY KEY,
eventtype VARCHAR(30), -- CHAN_START, ANSWER, HOLD, UNHOLD, BRIDGE_ENTER, etc.
eventtime TIMESTAMPTZ,
cid_name VARCHAR(80),
cid_num VARCHAR(80),
exten VARCHAR(80),
context VARCHAR(80),
channame VARCHAR(80),
linkedid VARCHAR(80),
uniqueid VARCHAR(80),
extra TEXT -- JSON with additional data
);Building Your Dashboard: Three Approaches Compared
Approach 1: DIY with Grafana + PostgreSQL
Time to build: 60-120 hours | Cost: Free (OSS) | Maintenance: 5-10 hrs/month
The most common approach. You configure Asterisk to write CDR and queue_log to PostgreSQL, then build Grafana dashboards with SQL queries.
Step 1: Configure CDR to PostgreSQL
Edit /etc/asterisk/cdr_pgsql.conf:
[global]
hostname=localhost
port=5432
dbname=asterisk
user=asterisk
password=your_secure_password
table=cdrStep 2: Configure queue_log to database
In /etc/asterisk/extconfig.conf:
[settings]
queue_log => pgsql,asterisk,queue_logStep 3: Write SQL queries for each KPI
Here's a real-time service level query for Grafana:
-- Service Level (80/20) for the last hour, by queue
WITH events AS (
SELECT
queuename,
event,
CAST(data1 AS INTEGER) AS wait_time
FROM queue_log
WHERE time >= NOW() - INTERVAL '1 hour'
AND event IN ('CONNECT', 'ABANDON')
)
SELECT
queuename AS "Queue",
COUNT(*) FILTER (WHERE event = 'CONNECT') AS answered,
COUNT(*) FILTER (WHERE event = 'ABANDON') AS abandoned,
ROUND(
100.0 * COUNT(*) FILTER (WHERE event = 'CONNECT' AND wait_time <= 20)
/ NULLIF(COUNT(*), 0), 1
) AS "Service Level %"
FROM events
GROUP BY queuename
ORDER BY queuename;Hourly call volume heatmap:
-- Heatmap: calls by hour and day of week (last 4 weeks)
SELECT
EXTRACT(DOW FROM calldate) AS day_of_week,
EXTRACT(HOUR FROM calldate) AS hour,
COUNT(*) AS call_count
FROM cdr
WHERE calldate >= NOW() - INTERVAL '28 days'
AND dst IN ('support', 'sales', 'billing')
GROUP BY 1, 2
ORDER BY 1, 2;Agent performance scorecard:
-- Agent performance: today
WITH agent_calls AS (
SELECT
agent,
COUNT(*) FILTER (WHERE event = 'CONNECT') AS calls_taken,
AVG(CAST(data2 AS INTEGER)) FILTER (WHERE event IN ('COMPLETECALLER','COMPLETEAGENT')) AS avg_talk_time,
AVG(CAST(data1 AS INTEGER)) FILTER (WHERE event = 'CONNECT') AS avg_wait_given,
COUNT(*) FILTER (WHERE event = 'RINGNOANSWER') AS missed_rings,
COUNT(*) FILTER (WHERE event = 'TRANSFER') AS transfers
FROM queue_log
WHERE time >= CURRENT_DATE
AND agent != 'NONE'
GROUP BY agent
),
agent_pauses AS (
SELECT
agent,
SUM(
EXTRACT(EPOCH FROM
LEAD(time) OVER (PARTITION BY agent ORDER BY time) - time
)
) FILTER (WHERE event = 'PAUSE') AS total_pause_seconds
FROM queue_log
WHERE time >= CURRENT_DATE
AND event IN ('PAUSE', 'UNPAUSE')
GROUP BY agent
)
SELECT
ac.agent AS "Agent",
ac.calls_taken AS "Calls",
ROUND(ac.avg_talk_time) || 's' AS "Avg Talk",
ROUND(ac.avg_wait_given) || 's' AS "Avg Wait Given",
ac.missed_rings AS "Missed",
ac.transfers AS "Transfers",
COALESCE(ROUND(ap.total_pause_seconds / 60), 0) || ' min' AS "Break Time"
FROM agent_calls ac
LEFT JOIN agent_pauses ap ON ac.agent = ap.agent
ORDER BY ac.calls_taken DESC;Pros: Free, highly customizable, you own everything Cons: Takes 60-120 hours to build, requires SQL expertise, no AMI real-time data in Grafana (needs custom middleware), dashboards break when Asterisk version changes, ongoing maintenance burden
Approach 2: QueueMetrics
Time to deploy: 2-4 hours | Cost: CHF 8/agent/month | Maintenance: 2-3 hrs/month
QueueMetrics is the legacy standard for Asterisk queue reporting. It reads queue_log and provides pre-built reports.
What you get:
- —Pre-built historical reports (30+ reports)
- —Basic real-time wallboard
- —Agent page with performance metrics
- —SLA tracking
Limitations:
- —Java-based (requires JVM, heavy resource usage)
- —UI looks dated (no modern data visualization)
- —No real-time AMI integration for live channel state
- —No heatmaps or advanced visualizations
- —No trunk monitoring
- —No CRM integration
- —Pricing scales per-agent (expensive at scale: 50 agents = $400/month)
- —Self-hosted only, manual updates
Approach 3: Astervis (Modern Purpose-Built Solution)
Time to deploy: 15 minutes | Cost: From $49/month | Maintenance: Zero (auto-updates)
Astervis connects directly to your Asterisk PBX via AMI and CDR, providing 30+ pre-built dashboards with real-time data:
What you get:
- —30+ charts including heatmaps, trend lines, and distribution graphs
- —Real-time wallboard (updates every 5 seconds via AMI)
- —Agent performance dashboards with KPI scoring
- —Queue analytics with SLA tracking
- —Trunk utilization monitoring
- —Call recording playback integration
- —CRM integration (Bitrix24, AmoCRM)
- —Operator scheduling and shift management
- —One-command installation:
curl -fsSL https://get.astervis.io | bash - —Self-hosted, your data stays on your server
Tired of guessing what's happening in your queues?
Astervis gives you 30+ real-time charts, operator KPIs, and CRM integration for your Asterisk PBX. Self-hosted. Install in 5 minutes. From $119/mo flat — unlimited operators.
Feature Comparison: All Three Approaches
| Feature | DIY Grafana | QueueMetrics | Astervis |
|---|---|---|---|
| Setup time | 60-120 hours | 2-4 hours | 15 minutes |
| Real-time data | Limited (no AMI) | Basic | Full AMI + CDR |
| Update frequency | Manual refresh | 30-60 seconds | 5 seconds |
| Pre-built dashboards | None (build all) | ~30 reports | 30+ charts |
| Heatmaps | Custom SQL needed | ❌ | ✅ Built-in |
| Agent scorecards | Custom SQL needed | Basic | ✅ Advanced |
| Trunk monitoring | Custom build | ❌ | ✅ |
| CRM integration | Custom build | ❌ | ✅ Bitrix24, AmoCRM |
| Call recordings | Separate tool | Basic | ✅ Integrated player |
| Mobile-friendly | Depends | ❌ | ✅ Responsive |
| Alerts | Grafana alerts | Email only | ✅ Multi-channel |
| Maintenance | 5-10 hrs/month | 2-3 hrs/month | Zero |
| Cost (50 agents) | Free (+ your time) | ~$400/month | $199/month |
| Modern UI | Depends on skill | ❌ | ✅ |
Designing Effective Dashboard Layouts
Regardless of which approach you choose, these design principles make dashboards actually useful:
The "Three-Screen" Model
Most effective call centers use three dashboard views, each designed for a different audience:
Screen 1: Operations Wallboard (for supervisors and agents)
Display on a large TV visible to the entire floor:
┌─────────────────────────────────────────────────────┐
│ SERVICE LEVEL: 87% │ CALLS IN QUEUE: 2 │
│ ████████████░░ 80/20 │ LONGEST WAIT: 0:23 │
├─────────────────────────────────────────────────────┤
│ AVAILABLE AGENTS │ TODAY'S STATS │
│ ● Agent 101 (idle) │ Answered: 234 │
│ ● Agent 102 (talking) │ Abandoned: 8 (3.3%) │
│ ● Agent 103 (ringing) │ Avg Wait: 18s │
│ ○ Agent 104 (break) │ Avg Talk: 4:22 │
│ ● Agent 105 (talking) │ ASA: 14s │
├─────────────────────────────────────────────────────┤
│ HOURLY VOLUME call volume by hour graph │
│ 8am ████████████ 45 │
│ 9am ██████████████████ 67 │
│ 10am ████████████████████████ 89 ← peak │
│ 11am ██████████████████ 65 │
└─────────────────────────────────────────────────────┘
Design rules for wallboards:
- —Maximum 6-8 metrics (cognitive overload kills usefulness)
- —Color coding: green (on target), yellow (warning), red (breach)
- —Font size readable from 15+ feet away
- —Auto-refresh every 5-10 seconds
- —No scrolling required — everything visible at once
Screen 2: Manager Dashboard (for team leads and managers)
This is where tactical decisions happen:
┌────────────────────────────────────────────────────────────┐
│ QUEUE PERFORMANCE (Today) │
│ ┌──────────┬─────────┬──────────┬──────┬──────┬─────────┐ │
│ │ Queue │ Offered │ Answered │ Abn% │ SL% │ ASA │ │
│ ├──────────┼─────────┼──────────┼──────┼──────┼─────────┤ │
│ │ Support │ 156 │ 148 │ 5.1% │ 82% │ 22s │ │
│ │ Sales │ 89 │ 87 │ 2.2% │ 91% │ 12s │ │
│ │ Billing │ 67 │ 61 │ 9.0% │ 71% │ 38s ⚠ │ │
│ └──────────┴─────────┴──────────┴──────┴──────┴─────────┘ │
├────────────────────────────────────────────────────────────┤
│ AGENT LEADERBOARD │ WAIT TIME DISTRIBUTION │
│ 1. Agent 103 — 34 calls, 92% │ 0-15s: ████████████ 45% │
│ 2. Agent 101 — 31 calls, 88% │ 15-30s: ████████ 28% │
│ 3. Agent 105 — 28 calls, 85% │ 30-60s: ████ 15% │
│ 4. Agent 102 — 26 calls, 79% │ 60-90s: ██ 8% │
│ 5. Agent 104 — 22 calls, 75% │ 90s+: █ 4% │
├────────────────────────────────────────────────────────────┤
│ HOURLY HEATMAP (Mon-Fri) │
│ 8am 9am 10am 11am 12pm 1pm 2pm 3pm 4pm 5pm │
│ Mon ░░ ██ ████ ████ ██ ░░ ██ ████ ████ ██ │
│ Tue ░░ ██ ████ ██ ██ ██ ██ ████ ██ ░░ │
│ Wed ██ ████ ████ ████ ██ ██ ████ ████ ████ ██ │
│ Thu ░░ ██ ████ ██ ██ ░░ ██ ██ ████ ██ │
│ Fri ░░ ██ ██ ██ ░░ ░░ ██ ██ ██ ░░ │
└────────────────────────────────────────────────────────────┘
Include:
- —Queue-by-queue comparison table
- —Agent leaderboard with key metrics
- —Wait time distribution histogram
- —Hourly heatmap for staffing optimization
- —SLA trend line (7-day and 30-day)
Screen 3: Executive Report (for directors and C-suite)
Weekly or monthly view focused on trends and business impact:
- —MoM call volume trend with forecast
- —Cost per call trend
- —Customer satisfaction scores over time
- —SLA compliance trend (should be improving)
- —Staffing efficiency metrics
- —Top call reasons (from IVR data or disposition codes)
Dashboard Design Best Practices
- —
Start with questions, not metrics. What decisions does each viewer need to make? Only show data that informs those decisions.
- —
Use progressive disclosure. Summary numbers on the main view, click through for detail. Don't cram everything onto one screen.
- —
Color means something. Green/yellow/red should map to target/warning/breach consistently. Don't use color decoratively.
- —
Real-time ≠ historical. Separate them. Real-time dashboards answer "what's happening now?" Historical dashboards answer "what happened and why?"
- —
Benchmark everything. Raw numbers without targets are meaningless. "ASA is 34 seconds" means nothing. "ASA is 34 seconds (target: 20s) — ⚠ 70% above target" drives action.
- —
Show trends, not just snapshots. A service level of 75% is bad. But if it was 60% last week, you're improving. Context matters.
- —
Test readability. If a supervisor can't understand the wallboard from their desk, it's not useful.
Essential SQL Queries for Your Asterisk Dashboard
Here are production-ready queries you can use regardless of your visualization tool:
Real-Time Service Level by Queue
WITH hourly_events AS (
SELECT
queuename,
event,
CAST(NULLIF(data1, '') AS INTEGER) AS wait_seconds
FROM queue_log
WHERE time >= NOW() - INTERVAL '1 hour'
AND event IN ('CONNECT', 'ABANDON')
)
SELECT
queuename,
COUNT(*) AS total_offered,
COUNT(*) FILTER (WHERE event = 'CONNECT') AS answered,
COUNT(*) FILTER (WHERE event = 'ABANDON') AS abandoned,
ROUND(
100.0 * COUNT(*) FILTER (
WHERE event = 'CONNECT' AND wait_seconds <= 20
) / NULLIF(COUNT(*), 0), 1
) AS service_level_pct,
ROUND(AVG(wait_seconds) FILTER (WHERE event = 'CONNECT'), 0) AS avg_speed_answer
FROM hourly_events
GROUP BY queuename;Agent Utilization (Today)
WITH agent_sessions AS (
SELECT
agent,
event,
time,
LEAD(time) OVER (PARTITION BY agent ORDER BY time) AS next_time,
LEAD(event) OVER (PARTITION BY agent ORDER BY time) AS next_event
FROM queue_log
WHERE time >= CURRENT_DATE
AND agent != 'NONE'
AND event IN ('ADDMEMBER', 'REMOVEMEMBER', 'CONNECT',
'COMPLETECALLER', 'COMPLETEAGENT', 'PAUSE', 'UNPAUSE')
),
talk_time AS (
SELECT
agent,
SUM(EXTRACT(EPOCH FROM next_time - time)) AS total_talk_seconds
FROM agent_sessions
WHERE event = 'CONNECT'
GROUP BY agent
),
login_time AS (
SELECT
agent,
SUM(EXTRACT(EPOCH FROM
COALESCE(next_time, NOW()) - time
)) AS total_login_seconds
FROM agent_sessions
WHERE event = 'ADDMEMBER'
GROUP BY agent
)
SELECT
t.agent,
ROUND(t.total_talk_seconds / 3600, 1) AS talk_hours,
ROUND(l.total_login_seconds / 3600, 1) AS login_hours,
ROUND(100.0 * t.total_talk_seconds /
NULLIF(l.total_login_seconds, 0), 1) AS utilization_pct
FROM talk_time t
JOIN login_time l ON t.agent = l.agent
ORDER BY utilization_pct DESC;Abandonment Analysis (Identifying Problem Hours)
SELECT
DATE_TRUNC('hour', time) AS hour,
COUNT(*) FILTER (WHERE event IN ('CONNECT', 'ABANDON')) AS total_offered,
COUNT(*) FILTER (WHERE event = 'ABANDON') AS abandoned,
ROUND(
100.0 * COUNT(*) FILTER (WHERE event = 'ABANDON')
/ NULLIF(COUNT(*) FILTER (WHERE event IN ('CONNECT', 'ABANDON')), 0), 1
) AS abandon_rate_pct,
ROUND(AVG(CAST(NULLIF(data1, '') AS INTEGER))
FILTER (WHERE event = 'ABANDON'), 0) AS avg_wait_before_abandon
FROM queue_log
WHERE time >= CURRENT_DATE
AND event IN ('CONNECT', 'ABANDON')
GROUP BY DATE_TRUNC('hour', time)
HAVING COUNT(*) FILTER (WHERE event = 'ABANDON') > 0
ORDER BY hour;Weekly Performance Trend
SELECT
DATE_TRUNC('week', time) AS week,
COUNT(*) FILTER (WHERE event = 'CONNECT') AS answered,
COUNT(*) FILTER (WHERE event = 'ABANDON') AS abandoned,
ROUND(
100.0 * COUNT(*) FILTER (WHERE event = 'CONNECT' AND CAST(NULLIF(data1,'') AS INTEGER) <= 20)
/ NULLIF(COUNT(*) FILTER (WHERE event IN ('CONNECT','ABANDON')), 0), 1
) AS service_level_pct,
ROUND(AVG(CAST(NULLIF(data1,'') AS INTEGER))
FILTER (WHERE event = 'CONNECT'), 0) AS avg_wait_seconds,
ROUND(AVG(CAST(NULLIF(data2,'') AS INTEGER))
FILTER (WHERE event IN ('COMPLETECALLER','COMPLETEAGENT')), 0) AS avg_talk_seconds
FROM queue_log
WHERE time >= NOW() - INTERVAL '12 weeks'
AND event IN ('CONNECT', 'ABANDON', 'COMPLETECALLER', 'COMPLETEAGENT')
GROUP BY DATE_TRUNC('week', time)
ORDER BY week;Setting Up Alerts That Actually Work
A dashboard without alerts is just a pretty picture. Here's how to set up meaningful notifications:
Alert Hierarchy
| Alert Level | Trigger | Response | Channel |
|---|---|---|---|
| Info | Queue depth > 3 for 2+ min | Supervisor awareness | Wallboard color change |
| Warning | Service level < 80% (rolling 30min) | Activate overflow agents | Slack/Teams notification |
| Critical | Abandonment rate > 10% (rolling 15min) | Emergency staffing action | SMS + Slack + email |
| Emergency | All agents unavailable | Management escalation | Phone call to duty manager |
Example: PostgreSQL Alert Query
Run this on a cron every 60 seconds:
-- Check for SLA breach in the last 15 minutes
WITH recent AS (
SELECT
queuename,
COUNT(*) AS total,
COUNT(*) FILTER (
WHERE event = 'CONNECT' AND CAST(data1 AS INTEGER) <= 20
) AS within_sla
FROM queue_log
WHERE time >= NOW() - INTERVAL '15 minutes'
AND event IN ('CONNECT', 'ABANDON')
GROUP BY queuename
)
SELECT
queuename,
total,
ROUND(100.0 * within_sla / NULLIF(total, 0), 1) AS sla_pct,
CASE
WHEN 100.0 * within_sla / NULLIF(total, 0) < 60 THEN 'CRITICAL'
WHEN 100.0 * within_sla / NULLIF(total, 0) < 80 THEN 'WARNING'
ELSE 'OK'
END AS status
FROM recent
WHERE 100.0 * within_sla / NULLIF(total, 0) < 80;Common Dashboard Mistakes to Avoid
1. Metric Overload Showing 50 metrics on one screen helps nobody. Start with 6-8 critical KPIs per dashboard view. You can always drill down for more detail.
2. No Baselines Metrics without targets are just numbers. Define what "good" looks like for each KPI before building the dashboard. Use the industry benchmarks in this guide as starting points, then calibrate to your operation.
3. Ignoring the "So What?" Test For every metric on your dashboard, ask: "If this number changes, what would I do differently?" If the answer is "nothing," remove the metric.
4. Historical-Only Dashboards End-of-day reports are useful for trends, but they can't prevent today's problems. Invest in real-time visibility first, then add historical analysis.
5. Not Segmenting by Queue Blended metrics across all queues hide problems. Your sales queue performing at 95% SLA can mask your support queue drowning at 60%. Always show per-queue metrics.
6. Forgetting Agent Privacy Performance dashboards should be coaching tools, not surveillance. Share individual metrics with agents privately; show team averages on the wallboard. Build a culture of improvement, not fear.
7. Set-and-Forget Dashboards need iteration. Review weekly: Are the metrics still relevant? Are the thresholds right? Has the operation changed? A dashboard that hasn't been updated in 6 months is probably lying to you.
Getting Started: Zero to Dashboard in 15 Minutes
If you want to skip the weeks of DIY setup and get a complete KPI dashboard today:
1. Install Astervis on your PBX server:
curl -fsSL https://get.astervis.io | bash2. Connect to your Asterisk instance:
The installer auto-detects your Asterisk configuration and connects via AMI and CDR.
3. Open your browser:
Navigate to your server's IP on port 3000. All 30+ dashboards are ready immediately — real-time wallboard, agent scorecards, queue analytics, trunk monitoring, heatmaps, and more.
4. Configure team access:
Set up operator accounts and assign queues. Agents see their own metrics. Supervisors see their team. Managers see everything.
No SQL queries to write. No Grafana panels to configure. No middleware to maintain. Start your 14-day free trial — no credit card required — and have full visibility into your call center in under 15 minutes.
Key Takeaways
- —
Track the right 20 KPIs organized by tier: real-time wallboard metrics, agent performance, operational efficiency, and strategic business metrics.
- —
Understand where data lives in Asterisk: CDR for historical records, queue_log for queue events, AMI for real-time state, and CEL for granular call flow tracking.
- —
Design dashboards for specific audiences: wallboards for the floor, tactical dashboards for managers, executive reports for leadership. Each serves a different purpose.
- —
Three approaches exist: DIY Grafana (free but 60-120 hours to build), QueueMetrics (legacy, per-agent pricing), or Astervis (modern, 15-minute setup, from $49/month).
- —
Set up alerts, not just dashboards. A metric nobody sees when it breaches is useless. Implement a tiered alert system that escalates automatically.
- —
Avoid common mistakes: metric overload, no baselines, blended queue metrics, and set-and-forget dashboards all reduce the value of your investment.
- —
Start simple, iterate fast. Get basic visibility running today, then refine over weeks. A simple dashboard you actually use beats a complex one that's perpetually "in progress."
Stop guessing. Start monitoring.
See your Asterisk call center's real performance — queue wait times, agent activity, trunk usage, and 30+ charts. Self-hosted on your server. Install in 5 minutes. No credit card required.
From $119/mo flat. Unlimited operators. 14-day free trial.
