GrayWatch
Find the network device that's lying to you.
Every dashboard is green. Interfaces up, zero CRC errors, no syslog. And your payments team is screaming about timeouts. That's a gray failure — a device silently dropping traffic while its own counters read clean — and it's the most feared failure mode in modern fabrics, because every monitoring tool you own consumes telemetry from the liar itself.
Hyperscalers solved this internally a decade ago (Microsoft's Pingmesh, the 007 paper). GrayWatch brings the technique to everyone else: one file, zero dependencies, read-only.
⚠ GRAY FAILURE: spine1 (99.9% confidence, chance odds 1 in 16,807)
in 5 lossy paths, 0 clean paths; self-report clean=True
→ drain from ECMP, re-probe, service the hardware
✓ exonerated: gpufab1, leaf1, leaf2, leaf3, leaf4, spine2
Quick start
python graywatch.py demo # 30 seconds to a verdict
python graywatch.py analyze your-probes.json # your fabric
Output: a terminal verdict plus a board-ready HTML report with the full disagreement matrix, corroborating paths, and the recommended drain procedure.
How it works
Never ask a device about itself. Feed GrayWatch probe results that record the path each probe transited — from TWAMP, a ping-mesh cron job, SR-steered probes, whatever you already run:
[{"src": "leaf1", "dst": "leaf3", "path": ["leaf1", "spine2", "leaf3"], "loss_pct": 2.4}]
The conviction invariant: a device present in ≥ N lossy paths and zero clean paths, while self-reporting healthy, is convicted by the disagreement itself. In an ECMP fabric, innocent devices necessarily appear on clean paths via the healthy spine — so the same matrix that convicts the culprit explicitly exonerates everyone else. An exclusivity rule localizes multiple simultaneous gray devices without smearing blame.
Confidence is an exact binomial probability, not a heuristic: the chance an innocent device would show this lossy/clean split at the fabric's measured background loss rate. The demo's "1 in 16,807" is (1/7)⁵ — simple enough to check by hand, which is the point.
When loss is present but not localizable, GrayWatch says so (distinct exit code) and tells you what probe diversity to add. Refusing to guess is a feature.
Guarantees
- Read-only, structurally — there is no code path that writes to a device. ~400 lines; read it before you run it.
- Zero dependencies — Python 3.10+ standard library only.
- Deterministic — same input, same verdict, same odds.
Probe data requirements
Each record needs src, dst, path (ordered device names the probe
transited), loss_pct. Tunables: --threshold (lossy cutoff, default 0.5%)
and --min-lossy (corroboration minimum, default 3). More endpoint pairs
and per-path steering = stronger convictions; the statistics scale
automatically.
Roadmap
Per-interface conviction (same invariant, finer hops), probe-source integrations (TWAMP responders, SR-policy steering), probe diversity against flow-selective failures.
License
Apache-2.0 — see LICENSE.
Metadata
Release files for graywatch 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| graywatch-1.0.0.tar.gz | 13.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| graywatch-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 30.4 kB
Release files / graywatch-1.0.0.tar.gz
| Download URL | graywatch-1.0.0.tar.gz |
|---|---|
| Size | 13.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2555faa407a3f4f8c6650fd322bbdab979e94e3da0d5df9b8dd27475315263c5
|
|
BLAKE2b-256 checksum How to use checksums |
eb51a200214309d772181727cef6765dfeef901a327be7bc86961d234a96889b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 12, 2026.
Transparency logRelease files / graywatch-1.0.0-py3-none-any.whl
| Download URL | graywatch-1.0.0-py3-none-any.whl |
|---|---|
| Size | 16.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d6776b912777d9887b5421c2e10e101f88641149fd9a53e029ea2ad071faff76
|
|
BLAKE2b-256 checksum How to use checksums |
bf50a6d0884baa4ff5cdfe1c78acf9d831a6b44d059d32ca53fec58ffc747a55
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 12, 2026.
Transparency log