← Back to Blog
NEWS

Building a Real-Time SIP Dashboard with dSIPRouter and Grafana

Building a Real-Time SIP Dashboard with dSIPRouter and Grafana

Monitoring your SIP infrastructure in real-time isn't a luxury—it's a necessity. When calls drop or quality degrades, you need to know immediately, not when customers start complaining. This tutorial walks you through building a production-ready monitoring stack using dSIPRouter's Prometheus metrics, Grafana dashboards, and intelligent alerting.

What We're Building

By the end of this tutorial, you'll have:

  • Prometheus scraping metrics from dSIPRouter every 15 seconds
  • Grafana displaying real-time dashboards for call volume, registration status, and trunk health
  • Alerts that notify you via Slack/email when things go wrong

Prerequisites

  • dSIPRouter installed and running (v0.74+)
  • Docker and Docker Compose (for Prometheus/Grafana)
  • Basic familiarity with SIP concepts
  • 15-20 minutes of focused time

Part 1: Enabling Prometheus Metrics in dSIPRouter

Step 1: Configure the Metrics Endpoint

dSIPRouter exposes Prometheus-compatible metrics on a dedicated endpoint. First, enable it in your configuration:

# Edit dSIPRouter settings
cd /etc/dsiprouter/gui
nano settings.py

Find and update these settings:

# Prometheus metrics configuration
PROMETHEUS_ENABLED = True
PROMETHEUS_PORT = 9090
PROMETHEUS_METRICS_PATH = '/metrics'

Restart dSIPRouter to apply changes:

dsiprouter restart

Step 2: Verify Metrics Are Exposed

Test that metrics are accessible:

curl http://localhost:9090/metrics

You should see output like:

# HELP dsip_active_calls Current number of active calls
# TYPE dsip_active_calls gauge
dsip_active_calls 12

# HELP dsip_registrations_total Total SIP registrations
# TYPE dsip_registrations_total counter
dsip_registrations_total{status="success"} 1547
dsip_registrations_total{status="failed"} 23

# HELP dsip_trunk_utilization Percentage of trunk capacity in use
# TYPE dsip_trunk_utilization gauge
dsip_trunk_utilization{trunk="carrier_a"} 0.45
dsip_trunk_utilization{trunk="carrier_b"} 0.72

Part 2: Setting Up Prometheus

Step 1: Create the Docker Compose Stack

Create a directory for your monitoring stack:

mkdir -p ~/dsip-monitoring && cd ~/dsip-monitoring

Create docker-compose.yml:

version: '3.8'

services:
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    ports:
      - "9091:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - ./alert-rules.yml:/etc/prometheus/alert-rules.yml
      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.retention.time=30d'
    restart: unless-stopped

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=your_secure_password
      - GF_USERS_ALLOW_SIGN_UP=false
    volumes:
      - grafana_data:/var/lib/grafana
    depends_on:
      - prometheus
    restart: unless-stopped

  alertmanager:
    image: prom/alertmanager:latest
    container_name: alertmanager
    ports:
      - "9093:9093"
    volumes:
      - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
    restart: unless-stopped

volumes:
  prometheus_data:
  grafana_data:

Step 2: Configure Prometheus Scraping

Create prometheus.yml:

global:
  scrape_interval: 15s
  evaluation_interval: 15s

alerting:
  alertmanagers:
    - static_configs:
        - targets:
          - alertmanager:9093

rule_files:
  - "alert-rules.yml"

scrape_configs:
  - job_name: 'dsiprouter'
    static_configs:
      - targets: ['host.docker.internal:9090']  # Use your dSIPRouter IP
    metrics_path: /metrics
    scrape_interval: 15s

  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

Note: Replace host.docker.internal with your dSIPRouter server's IP if running on a different host.

Step 3: Launch the Stack

docker-compose up -d

Verify everything is running:

docker-compose ps

Part 3: Building Grafana Dashboards

Step 1: Access Grafana

Open http://your-server:3000 in your browser. Log in with:
- Username: admin
- Password: (the one you set in docker-compose.yml)

Step 2: Add Prometheus Data Source

  1. Navigate to Configuration → Data Sources
  2. Click Add data source
  3. Select Prometheus
  4. Set URL to http://prometheus:9091
  5. Click Save & Test

Step 3: Create the SIP Dashboard

Click Create → Dashboard, then add these panels:

Panel 1: Active Calls (Stat)

dsip_active_calls

Settings:
- Visualization: Stat
- Color mode: Value
- Thresholds: 0 (green), 50 (yellow), 100 (red)

Panel 2: Call Volume Over Time (Time Series)

rate(dsip_calls_total[5m]) * 60

This shows calls per minute, smoothed over 5-minute windows.

Panel 3: Registration Success Rate (Gauge)

sum(rate(dsip_registrations_total{status="success"}[5m])) / 
sum(rate(dsip_registrations_total[5m])) * 100

Settings:
- Visualization: Gauge
- Min: 0, Max: 100
- Thresholds: 95 (green), 90 (yellow), below (red)

Panel 4: Trunk Utilization (Bar Gauge)

dsip_trunk_utilization * 100

Settings:
- Visualization: Bar gauge
- Orientation: Horizontal
- Thresholds: 70 (green), 85 (yellow), 95 (red)

Panel 5: Call Quality (MOS Score)

avg(dsip_call_quality_mos)

Settings:
- Visualization: Gauge
- Min: 1, Max: 5
- Thresholds: 4.0 (green), 3.5 (yellow), below (red)

Panel 6: Failed Registrations (Time Series)

rate(dsip_registrations_total{status="failed"}[5m]) * 60

Settings:
- Visualization: Time series
- Color: Red
- Fill opacity: 20

Step 4: Save Your Dashboard

Click Save dashboard (disk icon), name it "dSIPRouter SIP Monitoring", and save.


Part 4: Creating Intelligent Alerts

Alert Rules Configuration

Create alert-rules.yml in your monitoring directory:

groups:
  - name: dsiprouter_alerts
    interval: 30s
    rules:
      # Call Quality Degradation
      - alert: CallQualityDegraded
        expr: avg(dsip_call_quality_mos) < 3.5
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "Call quality below acceptable threshold"
          description: "Average MOS score is {{ $value | printf \"%.2f\" }} (threshold: 3.5)"

      - alert: CallQualityCritical
        expr: avg(dsip_call_quality_mos) < 3.0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "CRITICAL: Severe call quality degradation"
          description: "Average MOS score dropped to {{ $value | printf \"%.2f\" }}"

      # Registration Failures
      - alert: HighRegistrationFailures
        expr: |
          sum(rate(dsip_registrations_total{status="failed"}[5m])) /
          sum(rate(dsip_registrations_total[5m])) * 100 > 5
        for: 3m
        labels:
          severity: warning
        annotations:
          summary: "Registration failure rate elevated"
          description: "{{ $value | printf \"%.1f\" }}% of registrations failing"

      - alert: RegistrationFailureSpike
        expr: |
          sum(rate(dsip_registrations_total{status="failed"}[5m])) /
          sum(rate(dsip_registrations_total[5m])) * 100 > 15
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "CRITICAL: Registration failure spike detected"
          description: "{{ $value | printf \"%.1f\" }}% of registrations failing"

      # Trunk Utilization
      - alert: TrunkHighUtilization
        expr: dsip_trunk_utilization > 0.85
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Trunk utilization high on {{ $labels.trunk }}"
          description: "Trunk {{ $labels.trunk }} at {{ $value | printf \"%.0f\" }}% capacity"

      - alert: TrunkNearCapacity
        expr: dsip_trunk_utilization > 0.95
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "CRITICAL: Trunk {{ $labels.trunk }} near capacity"
          description: "Trunk at {{ $value | printf \"%.0f\" }}% - calls may be rejected"

      # System Health
      - alert: dSIPRouterDown
        expr: up{job="dsiprouter"} == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "CRITICAL: dSIPRouter is unreachable"
          description: "Prometheus cannot scrape dSIPRouter metrics"

Configure Alert Notifications

Create alertmanager.yml for Slack notifications:

global:
  slack_api_url: 'https://hooks.slack.com/services/YOUR/WEBHOOK/URL'

route:
  group_by: ['alertname']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  receiver: 'slack-notifications'

  routes:
    - match:
        severity: critical
      receiver: 'slack-critical'
      repeat_interval: 30m

receivers:
  - name: 'slack-notifications'
    slack_configs:
      - channel: '#sip-monitoring'
        title: '{{ .GroupLabels.alertname }}'
        text: '{{ range .Alerts }}{{ .Annotations.description }}\n{{ end }}'
        send_resolved: true

  - name: 'slack-critical'
    slack_configs:
      - channel: '#sip-critical'
        title: '🚨 {{ .GroupLabels.alertname }}'
        text: '{{ range .Alerts }}{{ .Annotations.description }}\n{{ end }}'
        send_resolved: true

Restart the stack to apply alert configuration:

docker-compose restart

Part 5: Production Considerations

Security Hardening

  1. Secure the metrics endpoint with authentication:
# In dSIPRouter settings.py
PROMETHEUS_AUTH_ENABLED = True
PROMETHEUS_AUTH_USER = 'metrics'
PROMETHEUS_AUTH_PASSWORD = 'your_secure_password'

Update prometheus.yml:

scrape_configs:
  - job_name: 'dsiprouter'
    basic_auth:
      username: 'metrics'
      password: 'your_secure_password'
  1. Use HTTPS for Grafana in production (configure reverse proxy with SSL)

  2. Restrict network access to monitoring ports using firewall rules

High Availability

For production deployments, consider:

  • Running Prometheus with remote storage (Thanos, Cortex)
  • Setting up Grafana with a PostgreSQL backend for dashboard persistence
  • Using Alertmanager in cluster mode for HA alerting

Useful Additional Metrics

Extend your monitoring with these queries:

# Calls per carrier
sum by (carrier) (rate(dsip_calls_total[5m]))

# Average call duration
avg(dsip_call_duration_seconds)

# SIP response codes
sum by (code) (rate(dsip_sip_responses_total[5m]))

# Endpoint registration count
count(dsip_endpoint_registered == 1)

Wrapping Up

You now have a production-grade monitoring stack that:

✅ Scrapes real-time metrics from dSIPRouter every 15 seconds
✅ Visualizes call volume, quality, and trunk utilization
✅ Alerts you immediately when problems occur
✅ Stores 30 days of historical data for trend analysis

This setup transforms reactive firefighting into proactive monitoring. You'll catch registration storms before they cascade, spot quality degradation as it starts, and know exactly when it's time to add trunk capacity.

Next steps:
- Customize alert thresholds based on your traffic patterns
- Add business-hours-aware alerting
- Create executive dashboards showing daily/weekly call statistics
- Integrate with your incident management platform (PagerDuty, Opsgenie)

Questions or running into issues? Drop by the dSIPRouter community—we're happy to help you fine-tune your monitoring setup.