Skip to main content

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.

PyPI version

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, pip installs scripts in ~/.local/bin which is often not in PATH on Linux. Using pipx avoids 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-tls when 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ltiprobe-1.4.0.tar.gz (49.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ltiprobe-1.4.0-py3-none-any.whl (35.6 kB view details)

Uploaded Python 3

File details

Details for the file ltiprobe-1.4.0.tar.gz.

File metadata

  • Download URL: ltiprobe-1.4.0.tar.gz
  • Upload date:
  • Size: 49.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for ltiprobe-1.4.0.tar.gz
Algorithm Hash digest
SHA256 48b7cee125f2a4e2a2cf2db519b0a700ca401f06fda3155cdbfc72ced4739194
MD5 6616b098837d6716ffe86f83c57a616a
BLAKE2b-256 9b45e125560dee115a498f875fb48c83e111fe5f929d937b6f38de676737a51a

See more details on using hashes here.

File details

Details for the file ltiprobe-1.4.0-py3-none-any.whl.

File metadata

  • Download URL: ltiprobe-1.4.0-py3-none-any.whl
  • Upload date:
  • Size: 35.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for ltiprobe-1.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9507181d35bd53fd79f91dcbfae30b90c568f9e938b11f9e481e8ea20abce708
MD5 468a7ce3f15b27580d1d3d2b22a0ce9e
BLAKE2b-256 7bbf810c2d6fd0fdc667e6fa74701a376fb54c8451a73155e1c35544a5e23e5f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page