Networking  

How to Visualize Network Latency Across Global CDN Nodes Using Python

Table of Contents

  • Introduction

  • Why Global Latency Visualization Matters

  • Real-World Scenario: Live Streaming During a Global Esports Tournament

  • Core Concepts: Measuring and Mapping Latency

  • Step-by-Step Implementation

  • Complete Working Code with Real-Time Simulation

  • Best Practices for Production Use

  • Conclusion

Introduction

In today’s hyper-connected digital world, milliseconds matter. Whether you're streaming a live concert, delivering financial data, or hosting a global multiplayer game, understanding how your content performs across continents is non-negotiable. Content Delivery Networks (CDNs) promise speed—but how do you see that speed in action?

This article shows you how to build a real-time visualization of network latency across global CDN nodes using Python, GeoIP, and interactive maps—no complex infrastructure required.

Why Global Latency Visualization Matters

Latency isn’t just a number—it’s user experience. High latency in Tokyo while your servers blaze in Frankfurt means frustrated viewers, dropped connections, and lost revenue. Visualizing latency geographically helps you:

  • Identify underperforming regions

  • Validate CDN provider claims

  • Trigger failover mechanisms proactively

  • Communicate performance to stakeholders

But raw ping data is useless without context. You need a map—not a spreadsheet.

Real-World Scenario: Live Streaming During a Global Esports Tournament

Imagine you’re the infrastructure lead for "Global Clash 2024", a live esports championship broadcast to 5 million concurrent viewers across 120 countries. Your video streams are served via a multi-CDN strategy (Cloudflare, AWS CloudFront, and Akamai). Midway through the finals, chat explodes: “Stream is buffering in São Paulo!” But your monitoring dashboard shows “average latency: 87ms.” That’s misleading—your users in Brazil are suffering 420ms delays while users in Berlin enjoy 45ms.

PlantUML Diagram

You need a live, geographic heatmap of latency—not averages. Let’s build one.

Core Concepts: Measuring and Mapping Latency

We’ll simulate real-world behavior using:

  • Public CDN endpoints (e.g., speedtest-sfo2.digitalocean.com)

  • GeoIP lookup to map IPs to countries

  • ICMP ping (or HTTP round-trip time) for latency measurement

  • Plotly + Mapbox for interactive, real-time visualization

Note: In production, use HTTP-based timing (not ICMP) since many CDNs block ping. We’ll use requests with timing for realism.

Step-by-Step Implementation

  1. Define global CDN test points (real endpoints from major providers)

  2. Measure round-trip time (RTT) to each endpoint

  3. Resolve each endpoint’s geolocation

  4. Plot latencies on an interactive world map

We’ll simulate live updates every 10 seconds—just like during a real tournament.

Complete Working Code with Real-Time Simulation

PlantUML Diagram
import requests
import time
import plotly.graph_objects as go
from datetime import datetime
import json
from IPython.display import display, clear_output, HTML

# --- Configuration ---
CDN_NODES = [
    {"name": "DigitalOcean SFO", "url": "https://speedtest-sfo2.digitalocean.com", "lat": 37.7749, "lon": -122.4194},
    {"name": "Cloudflare LHR", "url": "https://speed.cloudflare.com", "lat": 51.5074, "lon": -0.1278},
    {"name": "AWS Tokyo", "url": "https://d36cz9buwru1tt.cloudfront.net", "lat": 35.6895, "lon": 139.6917},
    {"name": "Google Singapore", "url": "https://storage.googleapis.com", "lat": 1.3521, "lon": 103.8198},
    {"name": "Azure São Paulo", "url": "https://azure.microsoft.com", "lat": -23.5505, "lon": -46.6333},
    {"name": "Fastly Sydney", "url": "https://fastly.com", "lat": -33.8688, "lon": 151.2093},
]

# --- Core Functions ---
def measure_latency(url: str, timeout: int = 5) -> float:
    """Measure HTTP round-trip time in milliseconds."""
    try:
        start = time.time()
        # Fetch a small resource (like the root page)
        requests.get(url, timeout=timeout)
        return (time.time() - start) * 1000
    except Exception:
        return float('inf')  # Mark as unreachable

def generate_figure() -> go.Figure:
    """Generates the Plotly figure with the latest latency data."""
    lats, lons, texts, sizes, colors = [], [], [], [], []

    for node in CDN_NODES:
        # Measure latency for each node
        latency = measure_latency(node["url"])
        status = f"{latency:.0f} ms" if latency != float('inf') else "Timeout"

        lats.append(node["lat"])
        lons.append(node["lon"])
        texts.append(f"<b>{node['name']}</b><br>{status}") # HTML for bold text
        sizes.append(20)

        # Color scheme: Green (<100ms), Orange (100-300ms), Red (>300ms)
        if latency == float('inf'):
            color = "gray"
        elif latency < 100:
            color = "green"
        elif latency < 300:
            color = "orange"
        else:
            color = "red"
        colors.append(color)

    fig = go.Figure(go.Scattermapbox(
        lat=lats,
        lon=lons,
        mode='markers+text',
        marker=go.scattermapbox.Marker(
            size=sizes,
            color=colors,
            opacity=0.8,
            symbol='circle'
        ),
        text=texts,
        textposition="bottom right",
        hoverinfo='text' # Use the text field for hover data
    ))

    fig.update_layout(
        title={
            'text': f" Global CDN Latency Map – Live Update: {datetime.now().strftime('%H:%M:%S')}",
            'y':0.95,
            'x':0.5,
            'xanchor': 'center',
            'yanchor': 'top'},
        mapbox=dict(
            style="carto-darkmatter", # Better visual contrast for a map
            zoom=1.5,
            center=dict(lat=20, lon=0),
            # Optional: Add Mapbox token if using a private style
            # accesstoken='<YOUR_MAPBOX_TOKEN_IF_NEEDED>' 
        ),
        margin={"r":0,"t":50,"l":0,"b":0},
        height=600
    )

    # Return the HTML representation for the update() method
    return HTML(fig.to_html(include_plotlyjs='cdn', full_html=False))


def live_monitor(interval_seconds: int = 10, num_updates: int = 5):
    """
    Simulates continuous monitoring by updating the map periodically.
    NOTE: Must be run in a Jupyter or Colab Notebook.
    """
    print(f"Starting live monitoring. Refreshing map every {interval_seconds} seconds for {num_updates} updates...")

    # Create a placeholder (DisplayHandle) for the output
    output_container = display(HTML("<h2>Loading...</h2>"), display_id=True)

    for i in range(num_updates):
        # 1. Generate the new figure (as HTML)
        new_content = generate_figure()

        # 2. Update the output container
        # This replaces the content in the original placeholder without a new cell output.
        output_container.update(new_content)

        if i < num_updates - 1:
            time.sleep(interval_seconds)
            
    # Final message after the loop
    output_container.update(HTML(f"<h3>Live monitoring simulation complete! ({num_updates} updates)</h3>"))

# --- Execution ---
if __name__ == "__main__":
    # To run this, execute the function call in a Jupyter/Colab cell.
    # We will run a short simulation (e.g., 3 updates, 10 seconds apart)
    live_monitor(interval_seconds=10, num_updates=3)

# IMPORTANT NOTE: This code must be executed in a Jupyter or Google Colab Notebook environment.
e
  • No external API keys needed – uses public endpoints and open-source map tiles.

  • Error-resilient – handles timeouts gracefully.

  • Production-ready structure – easy to containerize or integrate into dashboards.

Best Practices for Production Use

  • Use HTTP HEAD requests instead of GET to reduce bandwidth

  • Cache GeoIP data—don’t resolve coordinates on every check

  • Aggregate data over time to avoid noise (e.g., 5-second rolling average)

  • Add alerting: trigger Slack/email if latency > 300ms in any region

  • Rotate endpoints: test multiple nodes per region for accuracy

For live events, run this script on a cloud instance near your origin server to simulate real user conditions.

Conclusion

During the Global Clash 2024 finals, your team spots the São Paulo latency spike instantly on the map. You reroute Brazilian traffic to a local edge partner within 90 seconds—saving the stream and earning a shoutout from the tournament host.

That’s the power of visualizing what matters. Latency isn’t abstract—it’s geographic, emotional, and urgent. With this approach, you don’t just monitor your CDN—you feel it.