By this point, I understood more about how my home network fit together, but I still couldn’t explain the interruptions. A Zoom call would freeze for 30 seconds or an SSH connection would drop, and I had no measurements from that moment to help explain why. My wife was having similar problems while working in the top-floor office. I knew the interruptions were happening often; I needed a way to capture what the network was doing when they happened.

Starting small

My first idea was to put some unused Raspberry Pis to work, with a probe in every room reporting measurements back to a central node. I liked the idea of being able to see whether a problem affected one room or several at the same time.

That also meant setting up and coordinating several devices before I could start collecting data. For the sake of simplicity, I decided to start with a probe I could run on my laptop.

Building a probe

I wanted to record network performance over time, along with the details of the laptop’s connection. Pinging my home router and a public internet target seemed like a useful starting point.

The program runs continuously, taking measurements at a regular interval that defaults to one minute. At each interval, it pings two targets: my local gateway and 1.1.1.1, a public IP address operated by Cloudflare.

Those two targets give me a way to compare the local connection with a path that also goes out to the internet. If response times to both the gateway and the public target increased together, I’d have a reason to investigate the local connection first. If the gateway stayed responsive while the public target slowed down, I’d look farther along the path. Neither result would identify the cause on its own, but it would help narrow the next experiment.

Alongside the ping results, the probe captures details about the network connection:

  • SSID
  • BSSID
  • Signal
  • Noise
  • Band

Recording those details would let me check whether bad periods coincided with a particular access point, band, or weaker signal. That connection between performance and network characteristics is what I wanted to explore.

The probe writes its results to a JSONL file: each line is a JSON record, so I can keep appending measurements as it runs. Here’s one record, formatted across multiple lines for readability:

{
  "schemaVersion": 1,
  "timestamp": "2026-07-23T20:57:31.281125Z",
  "target": "1.1.1.1",
  "targetType": "internet",
  "sent": 0,
  "received": 0,
  "samples": [],
  "network": {
    "interface": "en0",
    "connectionLabel": "macbook-main-router",
    "ssid": "Verizon_76Y7HS",
    "bssid": "20:58:43:5d:1c:ea",
    "channelNumber": 1,
    "band": "2.4GHz",
    "channelWidthMHz": 20,
    "signalDBM": -60,
    "noiseDBM": -92
  },
  "error": "ping 1.1.1.1: context deadline exceeded"
}

This example records a failed probe attempt. The error field reports that the ping operation exceeded its deadline, and the record contains no timing samples. With both sent and received reported as zero, I can’t treat it as a packet-loss measurement. It does preserve the timestamp and connection details, so I can see the context in which the attempt failed.

Running the probe

The code is in my network-debugging repository. Feel free to use it if you’re investigating similar problems.

I designed it with macOS and Linux in mind, but the current implementation supports macOS only. I’ve only run it on my Mac, and I haven’t built the Linux adapter yet.

I start a named run with:

./experiment.sh <run-name>

Making sense of the data

Once I had a way to collect measurements, I needed a way to inspect them. A file full of individual records would only get me so far when I wanted to spot patterns across a run.

I vibe coded a Python app using Streamlit for this. The dashboard accepts a JSONL file from the probe and turns the measurements into charts, with options to group the data by the recorded properties. Its source is in the same network-debugging repository.

One comparison I wanted to make was performance by band: did the measurements look different when the laptop was connected over 2.4 GHz? Grouping the data gives me a starting point for that question. Any difference would still need investigation, since the band might change along with the laptop’s location or signal strength.

At this point, I had a way to collect measurements and look for patterns. The next step was to use it during deliberate experiments around the house. I’ll walk through those experiments and the dashboard in action in part 4, Experimentation.