Monitoring a (Cogeco) Sagemcom Modem with Prometheus

Monitoring a (Cogeco) Sagemcom Modem with Prometheus

Four consecutive days of unexplained connectivity loss. Each event took the whole path down. Restoring service meant walking to the modem and power-cycling it.

The LED was green between failures. The ISP app had nothing useful. Bridge-mode management at 192.168.100.1 is a GUI, not a monitoring surface so I had no history, no signal information, and no way to tell whether the line was noisy, if the modem was thermal-throttling, or if the firmware had simply wedged.

That is a diagnostic black box that I was determined to fix.


The gap

Consumer DOCSIS gear exposes a lot of state internally. Downstream SNR. Upstream transmit power. Correctable and uncorrectable codewords. Channel lock. Uptime. Temperature. CPU and memory. Almost none of that is available as a scrape target.

Off-the-shelf Sagemcom exporters exist for other ISPs. Cogeco's F3896 firmware does not speak the documented F3896 REST URLs. Those paths redirect back to the GUI. The working interface is the authenticated JSON-RPC endpoint the web UI already uses: POST /cgi/json-req.

Existing clients fail for a second reason that only shows up after login. Passing session-options.nss as the string "gtw:tr181" returns a session. Every subsequent getValue then fails with XMO_UNKNOWN_PATH_ERR. The GUI sends namespaces as a structured object list. The exporter has to do the same.


What gets scraped

The interesting questions map cleanly onto TR-181 paths under Device/Docsis/CableModem and Device/DeviceInfo:

QuestionSignal
Did the modem restart?Uptime decrease; reboot count
Is RF quality degrading?Downstream SNR, channel power, lock state
Is the modem screaming upstream?Upstream transmit power approaching ~51 dBmV
Is the coax corrupting frames?Rising uncorrectable codewords
Is the box itself unhealthy?Temperature, thermal throttle, CPU, free memory
Is the LAN handoff intact?Ethernet link up, negotiated speed, errors

Those are the series the exporter emits. GUI reachability and optional public TCP probes sit beside them so a dead modem, a failed API scrape, and a broader path failure are distinguishable.


Exporter shape

cogeco-sagemcom-exporter is a single Python file. Standard library only. Small Alpine image. Read-only container. No reboot, reset, or write methods — scrape and logout only.

Each scrape:

  1. Checks whether the management GUI answers.
  2. Opens one JSON-RPC session with the SHA-512 challenge-response the GUI uses.
  3. Batches every TR-181 path into a single getValue request.
  4. Logs out in a finally block so orphan sessions do not exhaust the modem's concurrent login limit.
  5. Exposes Prometheus text on :9488/metrics.

Batching matters for these boxes. They have weak CPUs and tight session pools. One round-trip per scrape is the difference between a quiet collector and a device that locks you out of your own admin UI.

Configuration is via environment variables: modem address,  MODEM_USERNAME / PASSWORD, optional toggles for Ethernet and system sensors, and a list of TCP probe targets. Use MODEM_USERNAME rather than USERNAME — shells on macOS already export USERNAME as the local account name.


Dashboards and alerts

The repo ships a Grafana dashboard and a rule group aimed at the failures that actually matter:

  • Modem GUI unreachable
  • DOCSIS scrape failed while the GUI is still up
  • Internet path probes down
  • Modem restarted (uptime delta)
  • Downstream SNR below 33 dB
  • Upstream power above 51 dBmV
  • Uncorrectable codewords rising
  • Channel unlocked

SNR and upstream power are the early warning pair. Uncorrectables are the packet-loss confirmation. Uptime resets give you a timestamp to align with WAN loss. Path probes without a modem-side signal usually mean something upstream of the coax — treat them as a symptom, not a ticket text for the ISP.


What this doesn't do

A healthy scrape does not prove Cogeco's plant is fine. Public TCP probes can fail because a single destination is filtering you. Channel tables can look clean while something else in the path is broken.

What the exporter does give you is history. When the next silent failure happens, you can answer whether SNR collapsed, upstream power climbed, codewords spiked, the box rebooted, or the API simply stopped answering.

Code, OpenAPI/OpenRPC notes for the HTTP and JSON-RPC layers, dashboard, and alerts:

https://github.com/colinedwardwood/cogeco-sagemcom-exporter