# Metrics

yslow measures three things about your network connection. Each is collected by sending a series of probes (currently 5) to each target.

## RTT (round-trip time)

The time for a single probe to reach a target and get a response, in milliseconds.

We measure RTT using TCP handshakes (SYN → SYN-ACK) on port 443 for internet targets, and TCP or ICMP ping for the gateway. TCP handshake is preferred because it works without elevated privileges and isn't blocked by most firewalls.

We report the **average RTT** across all successful probes in a run.

### Thresholds

| Target | Elevated | High |
|--------|----------|------|
| Gateway (LAN) | > 3 ms | > 10 ms |
| ISP (internet avg minus gateway avg) | > 50 ms | > 150 ms |
| Internet (when no gateway data) | > 50 ms | > 150 ms |

"Elevated" is a warning; "high" is an error.

The ISP threshold uses the difference between internet RTT and gateway RTT to isolate how much latency is added beyond your local network.

## Packet loss

The percentage of probes that received no response within the timeout (3 seconds).

Any packet loss is flagged as an error. When both gateway and internet loss are measured, we compare them to determine the source:

- Internet loss > gateway loss → problem is beyond your local network (ISP/routing)
- Internet loss ≤ gateway loss → problem is likely your local network (wifi/router)

## Jitter

The sample standard deviation of RTTs within a single probe run, in milliseconds. It measures how **consistent** the connection is — a low average RTT with high jitter means some packets are fast and some are slow.

High jitter degrades real-time applications (video calls, gaming, VoIP) even when average latency looks acceptable, because individual packets arrive with unpredictable timing.

### How it's calculated

Given RTTs `[r1, r2, ..., rn]` with mean `m`:

    jitter = sqrt(sum((ri - m)^2) / (n - 1))

This is the standard sample standard deviation (using Bessel's correction with `n-1`).

### Thresholds

| Target | High |
|--------|------|
| Gateway (LAN) | > 5 ms |
| Internet (beyond LAN) | > 20 ms above gateway jitter |

Internet jitter subtracts gateway jitter before comparing to the threshold, so local network jitter isn't double-counted. If your gateway has 15 ms jitter and your internet targets have 18 ms jitter, the ISP is only adding ~3 ms of jitter — the local network is the problem, not the ISP.

## DNS resolution timing

Measures how fast DNS resolvers respond, for both cached and uncached lookups. We detect the system's configured resolver (via resolvectl, nmcli, or /etc/resolv.conf) and compare it against three public resolvers (Google 8.8.8.8, Cloudflare 1.1.1.1, OpenDNS 208.67.222.222).

### How it's measured

**Configured resolver detection**: The primary nameserver is found by trying resolvectl (systemd-resolved), nmcli (NetworkManager/DHCP), then /etc/resolv.conf. Local stub addresses (127.0.0.53) are filtered out. Only the first (primary) resolver is tested.

**All resolvers**: Tested the same way — direct UDP DNS queries via dnspython. If the configured resolver is already in the public list (e.g. DHCP provides 8.8.8.8), it appears once marked as configured.

**Cached lookups**: Query `google.com` twice; discard the first (cache warm), keep the second. Measures resolver cache hit performance — essentially network RTT plus the resolver's internal lookup time.

**Uncached lookups**: Query 3 random subdomains like `<hex>.google.com` per resolver, take the median. These return NXDOMAIN but force full recursive resolution (root → .com → google.com nameservers). Random subdomains guarantee cache misses. Median is used instead of mean for robustness to outliers.

### Thresholds

Only uncached time is checked against thresholds. Cached time for remote resolvers is dominated by network RTT and isn't actionable — it's shown for context.

| Metric | Warning | Error |
|--------|---------|-------|
| Uncached lookup | > 100 ms | > 250 ms |
| Configured vs best public | > 2× slower | — |

The comparison warning is suppressed when the configured resolver is already flagged as slow on its own (avoids redundant noise).

### Why these thresholds

**Uncached (100 / 250 ms)**: Uncached requires full recursive resolution (root → TLD → authoritative). < 100 ms is normal for well-connected resolvers. > 250 ms adds perceptible delay to every first-visit domain.
