Every call that passes through your Asterisk PBX generates a Call Detail Record (CDR). These records contain a wealth of information — who called, when, how long they talked, whether the call was answered. But for most Asterisk administrators, CDR data sits unused in a MySQL table or flat file, invisible and unactionable.
This guide transforms your CDR data from raw database rows into meaningful reports that drive real business decisions. You'll learn how CDR works, how to query it effectively, and how to build (or choose) a reporting system that actually helps you manage your call center.
What's in an Asterisk CDR?
A CDR record is created for every call processed by Asterisk. Each record contains standardized fields:
| Field | Description | Example |
|---|---|---|
accountcode | Account code assigned to call | sales-team |
src | Source (caller) number | +15551234567 |
dst | Destination (dialed) number | 200 |
dcontext | Destination context | from-internal |
clid | Full Caller ID string | "John Smith" <+15551234567> |
channel | Originating channel | PJSIP/trunk-0000001a |
dstchannel | Destination channel | PJSIP/1001-0000001b |
lastapp | Last application executed | Dial, Queue, Voicemail |
lastdata | Data passed to last app | PJSIP/1001,30 |
start | Call start timestamp | 2026-03-18 09:15:22 |
answer | Answer timestamp | 2026-03-18 09:15:28 |
end | Call end timestamp | 2026-03-18 09:18:45 |
duration | Total call duration (seconds) | 203 |
billsec | Billable seconds (talk time) | 197 |
disposition | Call outcome | ANSWERED, NO ANSWER, BUSY, FAILED |
amaflags | AMA flags | DOCUMENTATION |
uniqueid | Unique call identifier | 1710752122.456 |
userfield | Custom user field | (varies) |
CDR vs. CEL: Understanding the Difference
CDR gives you one record per call — a summary. Think of it as the receipt.
CEL (Channel Event Logging) gives you every event during a call — channel creation, ringing, answer, bridge, transfer, hangup. Think of it as the full transaction log.
For basic reporting (call volume, duration, disposition), CDR is sufficient. For complex analytics (transfer chains, conference participants, queue interactions), you need CEL.
| Need | Use CDR | Use CEL |
|---|---|---|
| Total calls per day | ✅ | ✅ |
| Average call duration | ✅ | ✅ |
| Call disposition breakdown | ✅ | ✅ |
| Transfer path tracking | ❌ | ✅ |
| Queue hold time per caller | Limited | ✅ |
| Conference participant tracking | ❌ | ✅ |
| Agent ring time before answer | ❌ | ✅ |
| Precise billing calculations | ❌ | ✅ |
Setting Up CDR Storage
Option 1: CSV (Default)
By default, Asterisk writes CDR to /var/log/asterisk/cdr-csv/Master.csv. This is fine for small installations but becomes unwieldy fast.
# Check if CSV CDR is active
asterisk -rx "cdr show status"Option 2: MySQL/MariaDB
The most common backend for CDR reporting. Configure in /etc/asterisk/cdr_mysql.conf:
[global]
hostname = localhost
dbname = asteriskcdrdb
table = cdr
password = your_db_password
user = asterisk_cdr
port = 3306Create the CDR table:
CREATE TABLE cdr (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
calldate DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
clid VARCHAR(80) NOT NULL DEFAULT '',
src VARCHAR(80) NOT NULL DEFAULT '',
dst VARCHAR(80) NOT NULL DEFAULT '',
dcontext VARCHAR(80) NOT NULL DEFAULT '',
channel VARCHAR(80) NOT NULL DEFAULT '',
dstchannel VARCHAR(80) NOT NULL DEFAULT '',
lastapp VARCHAR(80) NOT NULL DEFAULT '',
lastdata VARCHAR(80) NOT NULL DEFAULT '',
duration INT(11) NOT NULL DEFAULT 0,
billsec INT(11) NOT NULL DEFAULT 0,
disposition VARCHAR(45) NOT NULL DEFAULT '',
amaflags INT(11) NOT NULL DEFAULT 0,
accountcode VARCHAR(20) NOT NULL DEFAULT '',
uniqueid VARCHAR(150) NOT NULL DEFAULT '',
userfield VARCHAR(255) NOT NULL DEFAULT '',
INDEX idx_calldate (calldate),
INDEX idx_src (src),
INDEX idx_dst (dst),
INDEX idx_disposition (disposition),
INDEX idx_accountcode (accountcode)
);Option 3: PostgreSQL
For larger installations. Configure in /etc/asterisk/cdr_pgsql.conf:
[global]
hostname = localhost
dbname = asteriskcdrdb
table = cdr
password = your_db_password
user = asterisk_cdr
port = 5432Option 4: ODBC (Universal)
ODBC works with any supported database. Configure via /etc/asterisk/cdr_adaptive_odbc.conf:
[asterisk_cdr]
connection = asterisk
table = cdr
alias start => calldate
alias clid => srcAfter configuring, reload CDR:
asterisk -rx "module reload cdr"
asterisk -rx "cdr show status"Essential CDR Queries
Once your CDR is in a database, here are the queries every administrator needs:
Daily Call Volume
SELECT
DATE(calldate) AS call_date,
COUNT(*) AS total_calls,
SUM(CASE WHEN disposition = 'ANSWERED' THEN 1 ELSE 0 END) AS answered,
SUM(CASE WHEN disposition = 'NO ANSWER' THEN 1 ELSE 0 END) AS no_answer,
SUM(CASE WHEN disposition = 'BUSY' THEN 1 ELSE 0 END) AS busy,
SUM(CASE WHEN disposition = 'FAILED' THEN 1 ELSE 0 END) AS failed
FROM cdr
WHERE calldate >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
GROUP BY DATE(calldate)
ORDER BY call_date DESC;Hourly Call Distribution (Heatmap Data)
SELECT
DAYOFWEEK(calldate) AS day_of_week,
HOUR(calldate) AS hour_of_day,
COUNT(*) AS call_count
FROM cdr
WHERE calldate >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
GROUP BY DAYOFWEEK(calldate), HOUR(calldate)
ORDER BY day_of_week, hour_of_day;This query gives you the data for a heatmap — one of the most powerful visualizations for staffing decisions.
Average Call Duration by Destination
SELECT
dst AS extension,
COUNT(*) AS total_calls,
ROUND(AVG(billsec), 1) AS avg_talk_seconds,
ROUND(AVG(duration), 1) AS avg_total_seconds,
ROUND(AVG(duration - billsec), 1) AS avg_ring_seconds,
SUM(CASE WHEN disposition = 'ANSWERED' THEN 1 ELSE 0 END) / COUNT(*) * 100 AS answer_rate_pct
FROM cdr
WHERE calldate >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
AND disposition IN ('ANSWERED', 'NO ANSWER')
GROUP BY dst
HAVING total_calls >= 5
ORDER BY total_calls DESC
LIMIT 20;Top Callers (Inbound)
SELECT
src AS caller_number,
COUNT(*) AS call_count,
SUM(billsec) AS total_talk_seconds,
ROUND(AVG(billsec), 1) AS avg_talk_seconds,
MIN(calldate) AS first_call,
MAX(calldate) AS last_call
FROM cdr
WHERE calldate >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
AND src != ''
AND LENGTH(src) > 5 -- Filter internal extensions
GROUP BY src
ORDER BY call_count DESC
LIMIT 25;Unanswered Call Analysis
SELECT
src AS caller_number,
dst AS called_extension,
calldate,
duration AS ring_seconds,
disposition
FROM cdr
WHERE calldate >= DATE_SUB(CURDATE(), INTERVAL 1 DAY)
AND disposition != 'ANSWERED'
AND LENGTH(src) > 5
ORDER BY calldate DESC;Trunk Utilization
SELECT
SUBSTRING_INDEX(channel, '-', 1) AS trunk,
COUNT(*) AS total_calls,
SUM(billsec) AS total_seconds,
ROUND(AVG(billsec), 1) AS avg_seconds,
SUM(CASE WHEN disposition = 'ANSWERED' THEN 1 ELSE 0 END) AS answered,
SUM(CASE WHEN disposition = 'FAILED' THEN 1 ELSE 0 END) AS failed
FROM cdr
WHERE calldate >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
GROUP BY SUBSTRING_INDEX(channel, '-', 1)
ORDER BY total_calls DESC;Peak Concurrent Calls (Advanced)
SELECT
DATE(calldate) AS call_date,
HOUR(calldate) AS call_hour,
MAX(concurrent) AS peak_concurrent
FROM (
SELECT
calldate,
(SELECT COUNT(*) FROM cdr c2
WHERE c2.calldate <= c1.calldate
AND ADDTIME(c2.calldate, SEC_TO_TIME(c2.duration)) >= c1.calldate) AS concurrent
FROM cdr c1
WHERE calldate >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
) AS concurrent_data
GROUP BY DATE(calldate), HOUR(calldate)
ORDER BY call_date DESC, call_hour;CDR Reporting Tools Compared
Manual SQL Queries
Pros: Full control, no extra software Cons: Requires SQL knowledge, no visualization, no automation, time-consuming
Asternic CDR Reports
A PHP-based CDR viewer for Asterisk.
Pros: Direct CDR table integration, basic charts Cons: PHP legacy code, limited customization, no real-time, dated interface
CDR-Stats (Abandoned)
A Django-based CDR analytics platform.
Pros: Was comprehensive with fraud detection Cons: Project is abandoned. Last real updates were years ago. Python 2 era. Don't start new installations with this.
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.
Grafana + SQL Datasource
Connect Grafana directly to your CDR database.
Pros: Powerful visualization, free, highly customizable Cons: You write every query yourself. No queue-specific intelligence. 20-40 hours to build a decent dashboard set. Ongoing maintenance.
Astervis
Purpose-built analytics platform that goes beyond raw CDR reporting.
Pros:
- —Automatic CDR ingestion: No manual database configuration needed. Astervis reads CDR data via AMI and its own collection pipeline.
- —30+ pre-built charts: Heatmaps, trend lines, comparison views — all ready out of the box
- —Queue + CDR combined: Unlike pure CDR tools, Astervis correlates CDR data with queue events for complete call lifecycle visibility
- —Operator performance: Individual agent KPIs derived from CDR + queue data
- —One-command install: No PHP, no Java, no custom SQL
Cons: Paid after 14-day trial (from $49/month)
Beyond Basic CDR: Advanced Analytics
Raw CDR data answers "what happened." Advanced analytics answers "why it happened" and "what to do about it."
Call Outcome Classification
CDR disposition tells you ANSWERED or NO ANSWER, but not the business outcome. Did the answered call result in a sale? A resolved issue? A callback request?
Advanced platforms combine CDR with:
- —Queue data: Hold time, queue name, agent who handled it
- —CRM data: Customer record, ticket status, deal stage
- —Call recording: What was actually discussed
This correlation is where CDR stops being a log and starts being intelligence.
Trend Detection
Single-day CDR reports are noise. Meaningful insights come from trends:
- —Is average handle time increasing week-over-week? (Training issue)
- —Are failed calls concentrating on specific trunks? (Provider issue)
- —Is call volume shifting to different hours? (Market change)
- —Are specific extensions seeing abandonment spikes? (Staffing issue)
Predictive Staffing
Historical CDR data, combined with queue analytics, enables predictive staffing models:
- —Analyze call volume patterns by hour, day, week, and month
- —Factor in seasonality and known events
- —Calculate required agents per time slot based on SLA targets
- —Generate staffing schedules automatically
This is the holy grail of CDR analytics — turning historical data into forward-looking operational decisions.
Setting Up CDR Reporting with Astervis
If you want to skip the DIY SQL queries and get production-ready CDR reporting in minutes:
Step 1: Install Astervis
curl -fsSL https://get.astervis.io | bashAstervis automatically connects to your Asterisk instance via AMI and begins ingesting call data — CDR, queue events, and channel events — into its TimescaleDB backend.
Step 2: Explore Pre-Built Reports
Open your dashboard at http://your-server:3000. CDR-derived reports available immediately:
- —Call Volume Trends: Daily, weekly, monthly — with comparison overlays
- —Heatmap: Call distribution by hour and day of week
- —Disposition Breakdown: Answered, missed, busy, failed — with trends
- —Agent Performance: Calls handled, average duration, availability
- —Trunk Analytics: Utilization per trunk, failure rates, concurrent calls
- —Top Callers/Destinations: Highest volume numbers with drill-down
Step 3: Integrate with Your CRM
Connect Bitrix24 or AmoCRM to see customer context alongside CDR data. When reviewing a call record, see the customer's history, open deals, and support tickets — all in one view.
CDR Data Retention Best Practices
How Long to Keep CDR Data
| Use Case | Retention | Rationale |
|---|---|---|
| Operational reporting | 90 days | Recent patterns for staffing |
| Compliance (GDPR) | As required | Varies by jurisdiction |
| Billing disputes | 12 months | Standard dispute window |
| Trend analysis | 24 months | Seasonal pattern detection |
| Regulatory (telecom) | 1-7 years | Jurisdiction-dependent |
Performance Optimization
For MySQL/MariaDB CDR tables:
-- Partition by month for faster queries
ALTER TABLE cdr PARTITION BY RANGE (TO_DAYS(calldate)) (
PARTITION p202601 VALUES LESS THAN (TO_DAYS('2026-02-01')),
PARTITION p202602 VALUES LESS THAN (TO_DAYS('2026-03-01')),
PARTITION p202603 VALUES LESS THAN (TO_DAYS('2026-04-01')),
PARTITION p_future VALUES LESS THAN MAXVALUE
);
-- Archive old data
CREATE TABLE cdr_archive LIKE cdr;
INSERT INTO cdr_archive SELECT * FROM cdr WHERE calldate < DATE_SUB(CURDATE(), INTERVAL 1 YEAR);
DELETE FROM cdr WHERE calldate < DATE_SUB(CURDATE(), INTERVAL 1 YEAR);For high-volume installations (10,000+ calls/day), consider TimescaleDB — a PostgreSQL extension purpose-built for time-series data. It's what Astervis uses internally, and it handles CDR queries orders of magnitude faster than standard MySQL at scale.
Common CDR Pitfalls
1. Missing Records
CDR records are generated by Asterisk, not the network. If Asterisk crashes mid-call, that CDR may be incomplete or missing. Always monitor CDR record counts against expected call volumes.
2. Duration vs. Billsec Confusion
- —
duration= total time from call start to hangup (includes ringing) - —
billsec= time from answer to hangup (talk time only)
Using duration for agent performance metrics inflates numbers. Always use billsec for talk time calculations.
3. Transferred Call Double-Counting
Blind transfers create multiple CDR records for a single caller experience. A call that's transferred twice generates 3 CDR records. Your reporting must account for this by grouping on linkedid (Asterisk 12+) or the original uniqueid.
4. Time Zone Mismatches
If your Asterisk server runs in UTC but your team works in EST, CDR timestamps will be 5 hours off from "business time." Either configure Asterisk's timezone or handle conversion in your reporting layer.
5. Queue Calls Lack Context
A CDR for a queue call shows the last agent who handled it, but not:
- —How long the caller waited in queue
- —How many agents were tried first (RINGNOANSWER events)
- —Whether the caller abandoned and called back
This is why CDR alone is insufficient for call center analytics. You need queue_log or AMI event data alongside CDR.
Conclusion
CDR data is the foundation of Asterisk reporting, but raw CDR records are just the starting point. The gap between "data in a database" and "actionable insights" is where most teams get stuck — spending weeks writing SQL queries and building dashboards instead of improving their call center operations.
If you need basic call logs, manual SQL queries work. If you need production-ready analytics with heatmaps, agent KPIs, trunk monitoring, and CRM integration — Astervis gives you all of that in a 5-minute install, with 30+ charts ready from day one.
Start your free 14-day trial and see what your CDR data has been trying to tell you.
Need real-time monitoring too? Read: How to Monitor Asterisk Queues in Real-Time
Comparing solutions? Check: Best Asterisk Monitoring Tools in 2026
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.
