CDN Cache Hit Ratio Widget — Free HTML CSS JS Snippet

CDN Cache Hit Ratio Widget · Dashboards · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Pure SVG stroke-dasharray/stroke-dashoffset progress ring, no canvas or charting library
Ring color shifts between green, amber, and red bands based on the current hit-rate percentage
Per-request simulation with randomized request volume and per-edge routing, not a single random percentage per tick
Independent per-edge-location hit ratio bars reveal regional regressions a global average can mask
Running hit and miss counters formatted with toLocaleString for readability at scale
Live pulsing "Live" indicator badge signals the data is actively updating
Smooth CSS transitions on the ring offset, ring color, and edge bar widths avoid abrupt jumps
Structured to swap the simulated tick function for a real CDN analytics API poll with minimal changes

About this UI Snippet

CDN Cache Hit Ratio Widget — Animated SVG Ring, Live Counters & Per-Edge Breakdown

Screenshot of the CDN Cache Hit Ratio Widget snippet rendered live

A CDN's entire value proposition comes down to one ratio: what fraction of requests get served from a nearby cache instead of round-tripping back to origin. This widget makes that ratio the visual centerpiece — a large animated ring shows the current overall hit rate, a running total of hits versus misses accumulates beside it, and a per-edge-location list breaks the same ratio down by region so a regression in one location doesn't hide inside a healthy global average.

The ring drawn with stroke-dasharray, not a chart library

The SVG has two overlapping circles of the same radius: a light gray track and a colored foreground circle whose stroke-dasharray is set to the circle's full circumference (CIRC = 2 * Math.PI * 48) and whose stroke-dashoffset is animated to represent the unfilled portion. Setting offset = CIRC - (pct / 100) * CIRC means at 0% the offset equals the full circumference (nothing visible) and at 100% the offset is 0 (the full circle drawn). The circle is rotated -90deg so the arc starts from 12 o'clock rather than the default 3 o'clock, matching how a progress ring is conventionally read. This is the standard pure-SVG technique for a progress ring with no canvas or charting dependency.

The ring's color itself carries meaning, not just its fill amount

setRing() sets the circle's stroke color based on threshold bands — green at 85%+, amber between 60-85%, red below 60% — recomputed on every tick. A cache hit ratio isn't just a number that goes up or down; it has industry-typical healthy ranges, and encoding that directly in the ring's color means a viewer doesn't need to know "is 72% good or bad" from memory, the amber color already answers that.

Per-request simulation, not a single random number per tick

simulateTick() doesn't just pick one random hit-rate percentage per second — it simulates a random *count* of individual requests (40 + Math.floor(Math.random() * 60)), routes each one to a randomly chosen edge location, and rolls a 90%-probability hit/miss outcome for each request individually before aggregating into both the global ring and each edge's own running total. This produces the same statistical texture real traffic has — some edges get more requests than others in a given tick purely by chance, and the overall ratio converges toward the underlying 90% probability over time rather than jumping around a single random value every second.

Per-edge bars reveal what the global ring average hides

The four .edge-row bars each compute their own hits / total percentage independently. Because every edge draws from the same 90% hit probability in this demo, they trend similarly, but in production this is exactly where regional cache configuration problems surface — an edge location with a stale cache-control policy or a recently added origin region can show a materially worse ratio than the global average while the ring alone stays reassuringly green.

Numbers formatted for scanability at scale

hitVal and missVal use .toLocaleString() rather than raw digit strings, so accumulated counts read as "12,480" instead of "12480" once the running totals grow past a few thousand over a long-running dashboard session.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly how the stroke-dasharray and stroke-dashoffset values combine to draw a partial circle, and why the SVG circle needs a -90 degree rotation for the ring to start filling from the top rather than the right side. The same assistant can help optimize it — for instance asking whether the per-request simulation loop would still perform well if the requests-per-second figure were scaled up by 100x for a much higher-traffic demo. It's also useful for extending the widget: ask it to add a historical sparkline of hit rate over the last few minutes, support configurable color thresholds passed as props, or add a tooltip on each edge bar showing raw hit and miss counts on hover. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a "CDN cache hit ratio" dashboard widget in HTML, CSS, and vanilla JavaScript — no charting or SVG library, hand-rolled SVG only.

Requirements:
- Draw an animated circular progress ring using two overlapping SVG circles (a static background track and a colored foreground arc) with the foreground arc's fill percentage controlled purely through stroke-dasharray and stroke-dashoffset math — no canvas, no external charting library — and display the current overall cache hit percentage as text in the ring's center.
- The ring's stroke color must switch between at least three distinct color bands (for example green, amber, red) based on which percentage range the current hit rate falls into, recalculated every time the value updates.
- Simulate live traffic on an interval (roughly every one to two seconds): generate a random number of individual simulated requests per tick, route each one to a randomly chosen edge location from a list of at least four named regions, and independently roll a hit-or-miss outcome for each individual request (do not just generate one random percentage per tick) — aggregate these into a running global hit/miss total and per-edge-location hit/miss totals.
- Display running total hit and miss counters (formatted with thousands separators) and a requests-per-second figure that update on each tick, plus a live-updating requests-per-second value.
- Render one horizontal bar per edge location showing that location's own independently computed hit-rate percentage, so a regional regression is visible even when the global ring stays in a healthy color band.
- All numeric transitions (ring fill, bar widths) should animate smoothly between values rather than jumping instantly.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Watch the ring and counters updateEvery 1.5 seconds a new batch of simulated requests updates the hit-rate ring, the running hit/miss totals, and the requests-per-second figure.
  2. 2
    Watch the ring change colorThe ring turns green at 85%+ hit rate, amber between 60-85%, and red below 60%, recalculated on every update.
  3. 3
    Watch per-edge barsEach of the four edge locations tracks its own independent hit ratio, useful for spotting a regional regression the global ring average might hide.
  4. 4
    Replace the simulation with real metricsSwap simulateTick() for a fetch call to your CDN provider's analytics API (Cloudflare, Fastly, CloudFront) polling real hit/miss counts per edge location.
  5. 5
    Adjust the color thresholdsChange the 85 and 60 percentage breakpoints in setRing() to match what counts as healthy for your specific CDN configuration and content mix.
  6. 6
    Export in your formatClick "HTML" for a standalone file, "JSX" for a React component, or "Tailwind" for a Tailwind CSS version.

Real-world uses

Common Use Cases

OPS
CDN and edge infrastructure dashboards
The core use case — give an infrastructure team a live view of cache effectiveness across edge locations without opening a separate CDN provider console.
Performance and reliability status boards
Pair with a Connection Pool Monitor Tile and similar infra widgets on a shared team status wall or ops dashboard.
ALERT
Cache configuration regression alerting
A sudden drop in one edge's bar while others stay steady is a strong signal to investigate that region's cache-control headers or recent origin changes.
Cost and origin-load capacity planning
A falling global hit rate directly predicts rising origin server load and CDN bandwidth cost, making this ring a useful early input to capacity discussions.
Learn SVG progress ring construction
A clean, dependency-free example of building an animated circular progress indicator from two overlapping SVG circles and stroke-dashoffset math.

Got questions?

Frequently Asked Questions

Two SVG circles of the same radius overlap — a static gray track and a colored foreground circle. The foreground circle's stroke-dasharray is set to its full circumference, and its stroke-dashoffset is set to circumference minus (percentage/100 times circumference), which visually reveals more of the stroke as the percentage rises. Rotating the circle -90 degrees makes the arc start from the top instead of the default right-hand starting point.

setRing() sets the stroke color to green at 85% or higher, amber between 60% and 85%, and red below 60%, recalculated on every update. This lets the color itself communicate whether the current hit rate is healthy without requiring the viewer to know what a "good" cache hit ratio number looks like.

simulateTick() picks a random request count per tick and rolls an individual hit/miss outcome (with a 90% hit probability) for each simulated request, aggregating them into per-edge and global totals. This produces the same statistical variability real traffic shows — some ticks and some edges naturally skew higher or lower by chance — rather than a single smoothly random percentage that would not resemble real request-level data.

Each edge tracks its own hits and total requests independently and computes its own percentage. In production this is exactly where a regional cache misconfiguration, a stale cache-control policy, or a newly added origin region would surface as a below-average bar even while the global ring stays in a healthy color band, since the ring only reflects the aggregate across all edges combined.

Replace simulateTick() with a periodic fetch() call to your CDN's analytics or logs API (for example Cloudflare Analytics, Fastly real-time stats, or CloudFront metrics), map the response into totalHits, totalMisses, and each EDGES entry's hits/total counts, and call the same setRing() and renderEdges() functions to update the display from real numbers instead of the random simulation.

toLocaleString() formats large numbers with thousands separators (for example "12,480" instead of "12480"), which keeps the running totals easy to scan at a glance once a long-running dashboard session accumulates counts into the thousands or more.