HTTP/DNS/ICMP/TCP/TLS latency tool with SLO validation, jitter, packet loss, MOS score (ITU-T G.107), CDN detection, Prometheus export and webhook alerting
Project description
ltiprobe
HTTP/DNS/ICMP/TCP/TLS latency measurement tool with SLO validation, jitter, packet loss, MOS score (ITU-T G.107), CDN detection, Prometheus export and webhook alerting. Displays a complete latency distribution (P50 to P99.9) from the terminal.
Installation
macOS
# Option 1 — Homebrew (recommended, no Python required)
brew tap bglatence/ltiprobe
brew install ltiprobe
# Option 2 — pip
pip install ltiprobe
Linux
On Linux, use pipx — it installs CLI tools in an isolated environment and configures PATH automatically:
# Install pipx (once)
sudo apt install pipx # Debian / Ubuntu
pipx ensurepath # adds ~/.local/bin to PATH
source ~/.bashrc
# Install ltiprobe
pipx install ltiprobe
ltiprobe --version
Why not plain
pip install? Without a virtual environment,pipinstalls scripts in~/.local/binwhich is often not in PATH on Linux. Usingpipxavoids this entirely.
If you prefer pip, add ~/.local/bin to your PATH first:
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc && source ~/.bashrc
pip install ltiprobe
Windows
pip install ltiprobe
ltiprobe --version
Usage
# Sites defined in ltiprobe.yaml (default)
ltiprobe
# DNS name or IP address as argument
ltiprobe https://apple.com https://amazon.com
ltiprobe http://192.168.1.100
ltiprobe https://10.0.0.5
# Number of measurements per site
ltiprobe -n 20
# Save results to CSV
ltiprobe --csv
# Show network hop count (traceroute)
ltiprobe --traceroute
# Continuous monitoring — re-run every 60 seconds
ltiprobe --interval 60
# Compare against a baseline CSV
ltiprobe --baseline resultats_20260420_143200.csv
# Export metrics in Prometheus text format
ltiprobe --prometheus-out metrics.prom
# Show advanced TLS certificate information
ltiprobe --tls-info
# Use an alternate config file
ltiprobe --config-file staging.yaml
# Disable TLS certificate validation (self-signed cert or direct IP)
ltiprobe --no-verify-tls https://10.0.0.5
# Help
ltiprobe --help
DNS name or IP address: ltiprobe accepts both. When using an IP address directly, DNS measurement is skipped (shown as N/A) and reachability is verified before starting. Use
--no-verify-tlswhen the server uses a self-signed certificate.
Sample output
ltiprobe (1.0.0):
* measuring response times of web sites (10 attempts)
* using config file: ltiprobe.yaml
https://google.com
HTTP distribution (10 measurements)
average : 45.3 ms min: 28.1 max: 145.2
p50 : 38.0 ms
p75 : 45.0 ms
p90 : 62.0 ms
p95 : 89.0 ms
p99 : 145.0 ms
p99.9 : 145.0 ms
HTTP timing (p50)
TTFB : 29.1 ms ← server processing
Transfer : 8.9 ms ← content download
Total p50 : 38.0 ms
Stability : stable (p99/p50 = 3.8x)
DNS -> average: 8.2 ms min: 6.1 max: 11.4
--- Protocol comparison (cold connection) ---
ICMP (network) : 12.3 ms min: 11.1 max: 13.5 jitter: 1.2 ms loss: 0% (10 packets)
TCP (port 443) : 18.7 ms min: 17.2 max: 21.0 jitter: 0.8 ms (+6.4 ms)
TLS (handshake, ×1) : 31.2 ms min: 28.4 max: 35.1 jitter: 1.5 ms (+12.5 ms)
HTTP (p50, cold) : 38.0 ms (+6.8 ms)
HTTP (p50, keep-alive) : 19.3 ms ← no TCP/TLS
── Scoring Standards ────────────────────────────────
ITU-T G.107 (E-Model)
R-factor : 88.1 / 100
MOS : 4.3 / 4.5 ✓ excellent
── Cache / CDN ──────────────────────────────────────
Cache → HIT Cloudflare PoP: YYZ Age: 42s
── TLS Certificate ──────────────────────────────────
Version : TLSv1.3
Cipher : TLS_AES_128_GCM_SHA256
Issuer : Google Trust Services
Subject (CN): *.google.com
Expires on : 2025-08-18 (in 113 days) ✓
HSTS : max-age=31536000
── HTTP Validation ──────────────────────────────────
status_code 200 → 200 ✓ OK
body_contains "google" → found ✓ OK
── SLO Analysis ─────────────────────────────────────
http_p50_ms 38.0 ms <= 300 ms ✓ OK
http_p95_ms 89.0 ms <= 400 ms ✓ OK
dns_ms 8.2 ms <= 50 ms ✓ OK
────────────────────────────────────────────────────
Summary: 3/3 objectives met
Configuration
Create a ltiprobe.yaml file at the root of your project:
nb_mesures: 10
timeout: 10
langue: EN # EN or FR
sites:
- url: https://api.example.com/health
slo:
http_p50_ms: 200 # max median HTTP latency
http_p95_ms: 400 # max HTTP P95 latency
dns_ms: 50 # max average DNS latency
tls_ms: 80 # max TLS handshake
icmp_ms: 30 # max network (ICMP) latency
tcp_ms: 40 # max TCP handshake
http_chaud_ms: 150 # max keep-alive HTTP (no TCP/TLS)
stabilite_ratio: 5 # max P99/P50 ratio
nb_hops_max: 25 # max network hops (--traceroute)
assert:
status_code: 200
body_contains: "ok"
header: "Content-Type: application/json"
webhook:
url: https://hooks.slack.com/services/xxx/yyy/zzz
on: slo_violation # slo_violation | degradation | all
If the file is absent, ltiprobe starts with default sites and values.
Available SLO keys
| Key | Description |
|---|---|
http_p50_ms |
Median HTTP latency (P50) |
http_p75_ms |
HTTP P75 latency |
http_p90_ms |
HTTP P90 latency |
http_p95_ms |
HTTP P95 latency |
http_p99_ms |
HTTP P99 latency |
http_p999_ms |
HTTP P99.9 latency |
dns_ms |
Average DNS latency |
tls_ms |
TLS handshake duration |
icmp_ms |
Average ICMP network latency |
tcp_ms |
TCP handshake duration |
http_chaud_ms |
Estimated keep-alive HTTP (no TCP/TLS) |
stabilite_ratio |
P99/P50 ratio (e.g. 5 means P99 ≤ 5× P50) |
nb_hops_max |
Max network hops (requires --traceroute) |
HTTP response validation (assert)
| Key | Description |
|---|---|
status_code |
Expected HTTP status code (e.g. 200) |
body_contains |
String expected in the first 4 KB of the body |
header |
"Key: Value" (partial match) or "Key" (presence check) |
TTFB / Transfer decomposition
ltiprobe splits each HTTP measurement into two phases with no extra request:
| Phase | What it measures |
|---|---|
| TTFB (Time To First Byte) | Time until the server sends the first response byte — reflects server processing and network round-trip |
| Transfer | Time to download the response body — reflects content size and bandwidth |
Both values are reported at P50 across all measurements.
Protocol layer comparison
ltiprobe measures all layers in parallel and shows deltas:
| Layer | What is measured |
|---|---|
| ICMP | Pure network latency (ping) |
| TCP | TCP handshake overhead (connect) |
| TLS | SSL/TLS handshake — paid once per connection |
| HTTP cold | Full request (new connection: includes TCP + TLS) |
| HTTP keep-alive | Estimated without TCP/TLS — represents server processing + transfer |
Note: Comparison is done on a cold connection. In production with HTTP keep-alive or HTTP/2, only the keep-alive HTTP cost applies per request.
Jitter and packet loss
ltiprobe reports jitter and packet loss for each protocol layer:
| Metric | Description |
|---|---|
| Jitter | Standard deviation of round-trip times — reflects latency consistency |
| Packet loss | Percentage of ICMP packets lost — displayed in green (0%) or orange (> 0%) |
Jitter is available on ICMP, TCP and TLS. Packet loss is available on ICMP only (TCP handles retransmission transparently).
New SLO keys: icmp_jitter_ms, icmp_loss_pct, tcp_jitter_ms.
Scoring Standards
ltiprobe includes a Scoring Standards section that applies industry-standard quality models to the measured network metrics. It appears automatically when ICMP data is available.
ITU-T G.107 (E-Model)
The E-Model is the ITU-T standard for estimating voice and real-time communication quality from three network metrics: latency, jitter, and packet loss.
Inputs (all already measured by ltiprobe):
| Input | Source |
|---|---|
| Latency | ICMP mean RTT |
| Jitter | ICMP RTT standard deviation |
| Packet loss | ICMP loss % |
Output:
- R-factor (0–100): raw quality score — higher is better
- MOS (1.0–4.5): Mean Opinion Score — perceptual quality as experienced by end users
| MOS | R-factor | Quality | User experience |
|---|---|---|---|
| ≥ 4.3 | ≥ 90 | Excellent | Indistinguishable from face-to-face |
| ≥ 4.0 | ≥ 80 | Good | Minor imperceptible imperfections |
| ≥ 3.6 | ≥ 70 | Acceptable | Noticeable but tolerable |
| ≥ 3.1 | ≥ 60 | Poor | Significant effort required |
| < 3.1 | < 60 | Bad | Communication breakdown |
Reference codec: G.711 (standard telephone quality, widely used for VoIP). The section is designed to accommodate additional standards (G.1051, QoE models) in future releases.
Stability indicator
ltiprobe computes the P99/P50 ratio to assess latency consistency:
| Ratio | Interpretation |
|---|---|
| < 2x | Very stable — all users have a similar experience |
| 2x – 5x | Stable — some acceptable variation |
| 5x – 10x | Variable — noticeable latency spikes |
| > 10x | Unstable — some users experience very high latency |
Network hop indicator (--traceroute)
| Hops | Indicator |
|---|---|
| ≤ 15 | Excellent — very direct route |
| ≤ 25 | Good — normal routing |
| ≤ 35 | High — long route (typically intercontinental) |
| > 35 | Critical — suboptimal route or routing issue |
Hidden hops (* * *) are counted but reported separately.
CDN / cache detection
ltiprobe automatically sends a HEAD request in parallel and reads response headers to detect whether the response comes from a CDN cache or the origin server.
| CDN detected | Header analysed |
|---|---|
| Cloudflare | CF-Ray |
| CloudFront (AWS) | X-Amz-Cf-Pop |
| Fastly | X-Served-By |
| Akamai | X-Check-Cacheable |
| Varnish | Via |
Advanced TLS information (--tls-info)
With --tls-info, ltiprobe inspects the TLS certificate and security configuration of each HTTPS site:
- TLS version and cipher suite negotiated
- Certificate issuer and subject (CN)
- Expiry date — with an orange warning if fewer than 30 days remain, red if expired
- HSTS header presence and value
The inspection reuses the existing TLS handshake thread — no extra network connection.
Continuous monitoring (--interval)
ltiprobe --interval 60 # re-run every 60 seconds
ltiprobe --interval 30 --csv # accumulate results across all scans into one CSV
Each scan is timestamped with local time + UTC:
── Scan #3 14:32 EDT / 18:32 UTC ────────────────────────
A degradation alert fires when a metric increases by ≥ 50% vs the previous scan:
⚠ p50 : 38ms → 72ms (+89%) since 14:28 EDT
Baseline comparison (--baseline)
Compare current results against a previously saved CSV:
# Save a baseline
ltiprobe --csv
# Compare later
ltiprobe --baseline resultats_20260420_143200.csv
# Compare and export a diff CSV
ltiprobe --baseline resultats_20260420_143200.csv --csv
When --baseline and --csv are combined, a second file comparaison_*.csv is generated
with columns {metric}_avant, {metric}_apres, {metric}_delta_pct, {metric}_statut
for each site.
Baselines generated by --interval (multiple rows per URL) are automatically aggregated
by median, making the reference robust to transient spikes.
Regression threshold: +10% or more on HTTP P50, P95, P99, DNS, or TTFB.
Prometheus export (--prometheus-out)
ltiprobe --prometheus-out metrics.prom
Generates a Prometheus text format file compatible with node_exporter textfile collector and Pushgateway.
Exported metrics:
| Metric | Description |
|---|---|
ltiprobe_http_p50_ms |
HTTP P50 latency |
ltiprobe_http_p95_ms |
HTTP P95 latency |
ltiprobe_http_p99_ms |
HTTP P99 latency |
ltiprobe_http_moyenne_ms |
HTTP mean latency |
ltiprobe_ttfb_p50_ms |
TTFB P50 |
ltiprobe_transfert_p50_ms |
Transfer time P50 |
ltiprobe_dns_moyenne_ms |
DNS mean latency |
ltiprobe_icmp_ms |
ICMP mean RTT |
ltiprobe_tcp_ms |
TCP handshake mean |
ltiprobe_tls_ms |
TLS handshake mean |
ltiprobe_stabilite_ratio |
P99/P50 stability ratio |
ltiprobe_slo_ok |
SLO check result — 1.0 = met, 0.0 = violated (labels: url, slo) |
Webhook alerting
Configure a webhook in ltiprobe.yaml to receive HTTP POST notifications:
webhook:
url: https://hooks.slack.com/services/xxx/yyy/zzz
on: slo_violation # slo_violation | degradation | all
on value |
When it fires |
|---|---|
slo_violation |
When at least one SLO check fails (default) |
degradation |
When a metric degrades ≥ 50% vs previous scan (--interval) |
all |
Both of the above |
Payload sent (JSON):
{
"source": "ltiprobe",
"event": "slo_violation",
"url": "https://apple.com",
"heure": "14:32 EDT",
"violations": [
{"slo": "http_p50_ms", "valeur": 312.5, "seuil": 200}
]
}
The webhook call is non-blocking (daemon thread) and does not affect measurement timing. Compatible with Slack, Microsoft Teams, PagerDuty, Discord, and any HTTP endpoint.
Multi-environment profiles (--config-file)
ltiprobe --config-file prod.yaml
ltiprobe --config-file staging.yaml
Multilingual support
Set langue: EN or langue: FR in ltiprobe.yaml.
CSV export (--csv)
Generates a timestamped file resultats_YYYYMMDD_HHMMSS.csv with columns:
url, average, min, max, p50 through p999, dns_moyenne, ttfb_p50,
transfert_p50, and hdr_encode (compressed histogram replayable with the
HdrHistogram library).
License
MIT
Français
Outil de mesure de latence HTTP/DNS/ICMP/TCP/TLS avec validation de SLOs, détection CDN, export Prometheus et alertes webhook. Affiche une distribution complète des latences (P50 à P99.9) depuis le terminal.
Installation
macOS
brew tap bglatence/ltiprobe && brew install ltiprobe
# ou
pip install ltiprobe
Linux — utiliser pipx pour éviter les problèmes de PATH :
sudo apt install pipx && pipx ensurepath && source ~/.bashrc
pipx install ltiprobe
Windows
pip install ltiprobe
Utilisation
ltiprobe # Sites définis dans ltiprobe.yaml
ltiprobe https://apple.com # Nom DNS
ltiprobe http://192.168.1.100 # Adresse IP directe
ltiprobe --no-verify-tls https://10.0.0.5 # IP avec cert auto-signé
ltiprobe -n 20 # 20 mesures par site
ltiprobe --csv # Export CSV
ltiprobe --traceroute # Afficher les hops réseau
ltiprobe --interval 60 # Monitoring continu toutes les 60s
ltiprobe --baseline resultats_20260420_143200.csv # Comparer à une baseline
ltiprobe --prometheus-out metrics.prom # Export Prometheus
ltiprobe --tls-info # Informations TLS avancées
ltiprobe --config-file staging.yaml # Fichier de config alternatif
Nom DNS ou adresse IP : les deux sont acceptés. En mode IP, la mesure DNS est ignorée (affiché N/A) et la joignabilité est vérifiée avant le démarrage.
Configuration (ltiprobe.yaml)
nb_mesures: 10
timeout: 10
langue: FR # FR ou EN
sites:
- url: https://api.exemple.com/health
slo:
http_p50_ms: 200
http_p95_ms: 400
dns_ms: 50
assert:
status_code: 200
body_contains: "ok"
webhook:
url: https://hooks.slack.com/services/xxx/yyy/zzz
on: slo_violation # slo_violation | degradation | all
Clés SLO disponibles
| Clé | Description |
|---|---|
http_p50_ms |
Latence HTTP médiane (P50) |
http_p75_ms |
Latence HTTP P75 |
http_p90_ms |
Latence HTTP P90 |
http_p95_ms |
Latence HTTP P95 |
http_p99_ms |
Latence HTTP P99 |
http_p999_ms |
Latence HTTP P99.9 |
dns_ms |
Latence DNS moyenne |
tls_ms |
Durée du handshake TLS |
icmp_ms |
Latence réseau ICMP |
tcp_ms |
Durée du handshake TCP |
http_chaud_ms |
HTTP keep-alive estimé (sans TCP/TLS) |
stabilite_ratio |
Ratio P99/P50 |
nb_hops_max |
Hops réseau max (requiert --traceroute) |
TTFB / décomposition du transfert
ltiprobe décompose chaque mesure HTTP en deux phases sans requête supplémentaire :
| Phase | Ce qui est mesuré |
|---|---|
| TTFB (Time To First Byte) | Temps jusqu'au premier octet de réponse — reflète le traitement serveur |
| Transfert | Temps de téléchargement du corps — reflète la taille et la bande passante |
Monitoring continu (--interval)
ltiprobe --interval 60 # relancer toutes les 60 secondes
ltiprobe --interval 30 --csv # accumuler les résultats dans un seul CSV
Une alerte de dégradation se déclenche quand une métrique augmente de ≥ 50 % par rapport au scan précédent.
Comparaison avec une baseline (--baseline)
ltiprobe --csv # sauvegarder une baseline
ltiprobe --baseline resultats_20260420_143200.csv # comparer plus tard
ltiprobe --baseline resultats_20260420_143200.csv --csv # + rapport CSV de comparaison
Seuil de régression : +10 % sur HTTP P50, P95, P99, DNS ou TTFB.
Les baselines issues de --interval (plusieurs lignes par URL) sont agrégées par médiane.
Export Prometheus (--prometheus-out)
ltiprobe --prometheus-out metrics.prom
Compatible avec le textfile collector de node_exporter et Pushgateway.
Métriques exportées : latences HTTP (P50/P95/P99/moyenne), TTFB, transfert, DNS, ICMP, TCP, TLS, ratio de stabilité, et résultats SLO (ltiprobe_slo_ok).
Informations TLS avancées (--tls-info)
Affiche la version TLS, le cipher négocié, l'émetteur, le sujet (CN), la date d'expiration (alerte orange < 30 jours, rouge si expiré) et la présence du header HSTS.
Alertes webhook
webhook:
url: https://hooks.slack.com/services/xxx/yyy/zzz
on: slo_violation # slo_violation | degradation | all
Envoi non-bloquant (thread daemon). Compatible Slack, Teams, PagerDuty, Discord et tout endpoint HTTP.
Jitter et packet loss
ltiprobe rapporte le jitter et le packet loss pour chaque couche protocolaire :
- Jitter : écart-type des RTT — mesure la consistance de la latence (ICMP, TCP, TLS)
- Packet loss : % de paquets perdus — affiché en vert (0%) ou orange (> 0%) — ICMP uniquement
Nouvelles clés SLO : icmp_jitter_ms, icmp_loss_pct, tcp_jitter_ms.
Scoring Standards
Quand les données ICMP sont disponibles, ltiprobe affiche une section Scoring Standards appliquant des modèles de qualité normalisés aux métriques mesurées.
ITU-T G.107 (E-Model)
Norme ITU-T d'estimation de la qualité vocale et temps-réel à partir de la latence, du jitter et du taux de perte. Zéro mesure réseau supplémentaire — tout est calculé depuis l'ICMP.
| MOS | Qualité | Ressenti |
|---|---|---|
| ≥ 4.3 | Excellente | Comme en face-à-face |
| ≥ 4.0 | Bonne | Imperceptible |
| ≥ 3.6 | Acceptable | Tolerable |
| ≥ 3.1 | Médiocre | Effort notable |
| < 3.1 | Mauvaise | Incompréhension |
Codec de référence : G.711. La section est extensible pour accueillir G.1051 ou d'autres normes QoE.
Licence
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ltiprobe-1.5.0.tar.gz.
File metadata
- Download URL: ltiprobe-1.5.0.tar.gz
- Upload date:
- Size: 51.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a773e540190df699f603d100d46dcb5f093db96e30d3e2329cce971805b67cb2
|
|
| MD5 |
8f18594af05b770319473e8f426cd54a
|
|
| BLAKE2b-256 |
b6e24031df77e98b4f267c07cb8990d3b01bb621d088377ef9437b035cc1ff7e
|
File details
Details for the file ltiprobe-1.5.0-py3-none-any.whl.
File metadata
- Download URL: ltiprobe-1.5.0-py3-none-any.whl
- Upload date:
- Size: 36.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8d9818d5bb5b990e0e4b9ce3b990e32ed0a96a7d7150fbc9506102b25bbae8cd
|
|
| MD5 |
96b43fbff780b2cd87e7fd8b618a2114
|
|
| BLAKE2b-256 |
65440019f5cef2982750efc4a8f0467daf4527628dfd41f568266f241263bb4c
|