Skip to main content

Documentation

Complete guide to setting up website monitoring with PingZen. API documentation, code examples, and best practices.

PingZen monitors report latency for PING and HTTP/HTTPS checks. Below is exactly how we measure, what each metric means, and how our numbers compare to industry-standard tools (Linux ping, curl, icmplib, fping).

PING (ICMP) — Kernel-Accurate RTT

For Ping monitors we shell out to the system ping binary (same as Datadog and most probes) and parse its statistics line. All reported RTT values come directly from the kernel — not from any Python timestamp — so they are identical to what you would see running ping on the probe host yourself.

How we measure (step by step)

  1. Run ping -c N -i 0.2 <host> as an asyncio subprocess (N = configurable packet count, default 4).
  2. iputils ping uses gettimeofday() for send-side timestamp + kernel SO_TIMESTAMP control message (cmsg) for receive-side — see iputils source.
  3. Parse the rtt min/avg/max/mdev line from stdout (Linux) or round-trip min/avg/max/stddev (macOS).
  4. Store min_rtt, avg_rtt, max_rtt, jitter (mdev), and packet_loss as floats in the check_results table.
  5. The integer response_time_ms column is set to round(avg_rtt) with a 1 ms floor — sub-ms RTTs round to 1 ms instead of 0, which reads as “no response”.
  6. Subprocess fork+exec overhead (~10 ms wall-clock) is discarded — it never enters the RTT figures.

Stored fields

ping_avg_rtt

Average RTT in milliseconds (float, 3 decimals). Kernel-measured. Use this for power-user precision — e.g. sub-ms in-datacenter targets show as 0.260 ms.

ping_min_rtt / ping_max_rtt

Minimum and maximum RTT across all echo packets in one check (float).

ping_jitter

Mean deviation of RTTs from their average (mdev) as reported by Linux ping. Note: this is classical mdev, not the RFC 3550 inter-arrival jitter used by some RTP tools — the two formulas differ.

ping_packet_loss

Fraction of packets that did not receive a reply within timeout (0.0–100.0 %).

response_time_ms

Integer ms — equals round(ping_avg_rtt), floored at 1 ms. Primary UI metric; for sub-ms precision inspect ping_avg_rtt directly.

Sub-millisecond targets (in-datacenter)

If your probe is in the same datacenter as the target (typical for bare-metal setups), real RTT is 0.2–0.9 ms. The integer response_time_ms is floored at 1 ms to avoid displaying "0ms" (which reads as a failed check). The true sub-ms value is always preserved in the float ping_avg_rtt field — visible in check_results API and the chart tooltip.

HTTP / HTTPS — Time to First Byte with Breakdown

For HTTP/HTTPS monitors we use httpx.AsyncClient with the trace extension hook to capture individual phase timestamps. We record wall-clock total plus four sub-event durations. Convention matches curl time_total and time_starttransfer.

Per-check timing fields

response_time_ms (total)

Full wall-clock from before request-build until httpx await response returns. Matches curl time_total without body read. Includes TCP + TLS + TTFB plus ~5–15 ms of Python / httpx / asyncio overhead (pool lookup, response object construction, event-loop scheduling). This is the "what the client saw" figure.

timing_tcp_ms

TCP handshake duration: connection.connect_tcp.startedconnection.connect_tcp.complete. Equivalent to curl time_connect - time_namelookup. One RTT under typical conditions.

timing_tls_ms

TLS handshake duration: connection.start_tls.startedconnection.start_tls.complete. Equivalent to curl time_appconnect - time_connect. One RTT for TLS 1.3, ~2 RTTs for TLS 1.2.

timing_ttfb_ms

Request-send → first response byte: http11.send_request_headers.startedhttp11.receive_response_headers.started. Pure server processing + one RTT. Equivalent to curl time_starttransfer - time_pretransfer.

(not stored) DNS, body-read

DNS is usually cached by the httpx pool and not emitted as a separate trace event. Response body read is not included in total — we break before response.content. Add either as Server-Timing header custom metric if needed.

Why total > tcp + tls + ttfb

On warm connection-pool reuse the sub-events may not fire at all (connection already open) yet total still reports 5–20 ms. The difference is real Python / httpx / asyncio overhead: auth and header construction before the first trace event, response object build and close after the last event, plus event-loop scheduling under concurrent load. This is normal for all Python-based HTTP monitors — curl shows the same 2–8 ms gap between sum-of-phases and total. The separate timing_* fields give you the pure network / server picture.

Industry Standards We Follow

PingZen measurements are RFC-compliant and align with major tools:

  • RFC 2681 — Round-trip Delay Metric for IPPM: our ICMP path via system ping qualifies as a Type-P-Round-trip-Delay measurement.
  • Datadog Synthetic ICMP tests use ping subprocess + stdout parse — identical to PingZen.
  • Prometheus blackbox_exporter uses Go time.Now() userspace timestamps, no SO_TIMESTAMPING — PingZen has the same precision class via kernel recv-side cmsg.
  • SmokePing / fping: batched C raw sockets for efficiency. Same metric semantics (min/avg/max/jitter/loss), different implementation.
  • RIPE Atlas: ICMP echo with internal firmware timestamping. Precision not publicly documented.
  • icmplib (Python): pure-Python raw socket. Validated against PingZen subprocess — RTT matches within 0.1 ms.
  • SO_TIMESTAMPING kernel hardware timestamps exist for nanosecond precision but are overkill for application-level uptime monitoring (and unsupported in containerized environments).

Common Questions

My router shows sub-millisecond ping but PingZen shows 30+ ms. Why?

Most likely different targets on different paths. Run ping <target_ip> on the same host that runs the PingZen probe — you will almost always get the same number we report. If not, paste the shell output and we will investigate routing.

HTTP response_time is 24 ms but my server reports 6 ms processing. Where are the missing 18 ms?

Total is wall-clock from client init; your server-side 6 ms is pure processing. The delta includes TCP ACK propagation, httpx pool lookup, Python object construction, and asyncio scheduling. For pure server latency use timing_ttfb_ms (which already excludes TCP and TLS).

Can I export the raw float ping_avg_rtt?

Yes — the check_results API returns ping_avg_rtt as a float. UI charts tooltip shows it with 3 decimals. For sub-ms in-DC pings this is the value to watch.

Why is jitter (mdev) sometimes higher than expected?

We report Linux ping mdev (mean deviation of RTTs from their average), not RFC 3550 inter-arrival jitter used by some RTP tools. Both are valid, they measure different things. On stable in-DC links mdev is typically 0.01–0.5 ms.

Common Questions

What protocols can I monitor?

PingZen supports 23 protocols: HTTP/HTTPS, WebSocket (WS/WSS), TCP, UDP, ICMP Ping, gRPC, DNS, WHOIS, SSL certificates, Email (SMTP/IMAP/POP3), FTP/FTPS, DNSBL, PageSpeed, SOCKS5, MTProxy, API Check, and Transaction. You can monitor websites, APIs, servers, databases, and any network service.

How fast can I get alerts?

Telegram alerts are delivered within 1-2 seconds of detection. Slack and Discord notifications arrive almost instantly. You can configure multiple alert channels for redundancy.

Can I organize monitors by project?

Yes! PingZen supports workspaces, which let you organize monitors by project, environment, or team. Each workspace can have its own alert configurations and team members.

Is there an API for automation?

Absolutely. PingZen provides a full REST API with OpenAPI documentation. You can create, update, and delete monitors programmatically.

How do status pages work?

Status pages are public, branded pages showing your services' uptime. You can display real-time status and allow customers to subscribe for updates.

What happens if I reach my monitor limit?

We'll notify you when approaching your limit. You can pause some monitors or contact us for increased capacity. We never stop monitoring without warning, ensuring your critical services stay protected.

Ready to stop missing downtime?

Join thousands of teams who trust PingZen. Setup takes 30 seconds.