Prometheus Metrics
ChannelWatch exposes a standard Prometheus metrics endpoint at /metrics. Every metric carries per-DVR labels so you can build dashboards that show individual server health alongside aggregate totals.
Scrape endpoint
Section titled “Scrape endpoint”GET /metricsThe endpoint is unauthenticated and returns text in the standard Prometheus exposition format. Point your Prometheus scrape config at it directly:
scrape_configs: - job_name: channelwatch static_configs: - targets: ['channelwatch-host:8501'] scrape_interval: 30sLabel schema
Section titled “Label schema”Every metric includes four labels that identify the DVR it came from:
| Label | Example value | Description |
|---|---|---|
dvr_id | a1b2c3d4 | Stable 8-character ID derived from md5(host:port)[:8] |
dvr_name | Living Room | User-editable display name |
host | 192.168.1.50 | DVR host as configured |
port | 8089 | DVR port as configured |
An additional scope label is set to "all" on aggregate series (see below).
Available metrics
Section titled “Available metrics”Connection and health
Section titled “Connection and health”| Metric | Type | Description |
|---|---|---|
channelwatch_dvr_connected | Gauge | 1 if the DVR task is alive and connected, 0 otherwise |
channelwatch_dvr_last_event_seconds_ago | Gauge | Seconds since the last SSE event or successful poll from this DVR |
channelwatch_dvr_task_restarts_total | Counter | Number of times the DVR’s asyncio task has been restarted |
channelwatch_dvr_last_event_seconds_ago is the key metric for the readiness probe. When it exceeds staleness_threshold_seconds (default 300), the watchdog marks the DVR unhealthy.
Streams and activity
Section titled “Streams and activity”| Metric | Type | Description |
|---|---|---|
channelwatch_active_streams | Gauge | Number of active streams on this DVR right now |
channelwatch_alerts_sent_total | Counter | Total alerts sent, labeled by dvr_id and alert_type |
channelwatch_notification_errors_total | Counter | Failed notification deliveries, labeled by dvr_id and provider |
Disk space
Section titled “Disk space”| Metric | Type | Description |
|---|---|---|
channelwatch_disk_free_bytes | Gauge | Free disk space reported by this DVR |
channelwatch_disk_total_bytes | Gauge | Total disk capacity reported by this DVR |
channelwatch_disk_free_percent | Gauge | Free disk space as a percentage |
System
Section titled “System”| Metric | Type | Description |
|---|---|---|
channelwatch_uptime_seconds | Gauge | Seconds since ChannelWatch started |
channelwatch_config_reloads_total | Counter | Number of hot-reload events since startup |
Aggregate series
Section titled “Aggregate series”All per-DVR metrics also have an aggregate counterpart with scope="all" and no dvr_id/dvr_name/host/port labels. These aggregate series are kept for backward compatibility with dashboards built before per-DVR labels were introduced.
For example, channelwatch_active_streams{scope="all"} gives the total active stream count across all DVRs. If you only have one DVR, the per-DVR and aggregate values are identical.
Example Grafana dashboard
Section titled “Example Grafana dashboard”ChannelWatch ships a Grafana dashboard JSON file at dev/dashboards/channelwatch-overview.json in the product repository. Import it into Grafana v10+ via Dashboards > Import > Upload JSON file.
The dashboard includes panels for:
- Per-DVR connection status (green/red status grid)
- Active streams per DVR (time series)
- Disk usage per DVR and aggregate (gauge + time series)
- Recent alert rate (counter delta)
- Notification delivery errors (counter delta)
Alerting rules (example)
Section titled “Alerting rules (example)”groups: - name: channelwatch rules: - alert: DVRStale expr: channelwatch_dvr_last_event_seconds_ago > 300 for: 2m labels: severity: warning annotations: summary: "DVR {{ $labels.dvr_name }} has not received events" description: "Last event was {{ $value | humanizeDuration }} ago"
- alert: DVRDisconnected expr: channelwatch_dvr_connected == 0 for: 1m labels: severity: critical annotations: summary: "DVR {{ $labels.dvr_name }} is disconnected"Related pages
Section titled “Related pages”- Health & Readiness Probes - how
channelwatch_dvr_last_event_seconds_agodrives readiness state - Per-DVR Health - the
/api/v1/dvrs/<id>/healthJSON endpoint - Debug Bundles - capture a snapshot for troubleshooting