Wave ring: a week of cluster load cycles
Which cluster departs from its normal weekly load pattern?
Wave ring
How to read this example
- Wave lanes
- Hourly CPU load per cluster, arranged in seven day sectors.
- Bands & markers
- Normal ranges, hatched forecasts, and marked anomalies or deployments.
- Outside & centre
- Requests per hour outside; daily cost per cluster in the inner donut.
Try thisHover a wave at one hour to compare all clusters at the same time. Dashed, hatched portions are forecasts, not observed measurements.
Open the chart without page chrome ↗Drawing width at least 760 px. Scroll within the chart on smaller screens.
const options = {
"chart": {
"type": "radialColumn",
"height": 680,
"toolbar": {
"show": false
}
},
"series": [
{
"name": "Requests (k / h)",
"data": [
322,
322,
313,
304,
304,
282,
273,
298,
344,
369,
400,
425,
415,
415,
391,
381,
391,
428,
440,
474,
450,
425,
381,
344,
335,
341,
335,
319,
298,
276,
291,
322,
341,
375,
428,
437,
437,
425,
397,
381,
397,
440,
468,
487,
474,
431,
384,
350,
341,
332,
326,
310,
307,
291,
288,
295,
335,
394,
419,
440,
434,
400,
384,
409,
428,
456,
589,
583,
471,
422,
384,
341,
301,
322,
332,
338,
322,
313,
298,
310,
338,
400,
434,
431,
437,
400,
391,
378,
397,
459,
493,
508,
474,
453,
409,
357,
338,
329,
332,
310,
295,
276,
270,
298,
316,
369,
412,
397,
391,
366,
347,
357,
363,
384,
446,
459,
456,
428,
391,
344,
236,
223,
236,
211,
214,
202,
217,
223,
254,
267,
291,
307,
301,
273,
264,
279,
298,
313,
338,
344,
313,
363,
257,
242,
195,
189,
183,
186,
171,
164,
158,
174,
192,
233,
251,
264,
251,
236,
233,
null,
null,
null,
null,
null,
null,
null,
null,
null
]
}
],
"xaxis": {
"categories": [
"Mon 00:00",
"Mon 01:00",
"Mon 02:00",
"Mon 03:00",
"Mon 04:00",
"Mon 05:00",
"Mon 06:00",
"Mon 07:00",
"Mon 08:00",
"Mon 09:00",
"Mon 10:00",
"Mon 11:00",
"Mon 12:00",
"Mon 13:00",
"Mon 14:00",
"Mon 15:00",
"Mon 16:00",
"Mon 17:00",
"Mon 18:00",
"Mon 19:00",
"Mon 20:00",
"Mon 21:00",
"Mon 22:00",
"Mon 23:00",
"Tue 00:00",
"Tue 01:00",
"Tue 02:00",
"Tue 03:00",
"Tue 04:00",
"Tue 05:00",
"Tue 06:00",
"Tue 07:00",
"Tue 08:00",
"Tue 09:00",
"Tue 10:00",
"Tue 11:00",
"Tue 12:00",
"Tue 13:00",
"Tue 14:00",
"Tue 15:00",
"Tue 16:00",
"Tue 17:00",
"Tue 18:00",
"Tue 19:00",
"Tue 20:00",
"Tue 21:00",
"Tue 22:00",
"Tue 23:00",
"Wed 00:00",
"Wed 01:00",
"Wed 02:00",
"Wed 03:00",
"Wed 04:00",
"Wed 05:00",
"Wed 06:00",
"Wed 07:00",
"Wed 08:00",
"Wed 09:00",
"Wed 10:00",
"Wed 11:00",
"Wed 12:00",
"Wed 13:00",
"Wed 14:00",
"Wed 15:00",
"Wed 16:00",
"Wed 17:00",
"Wed 18:00",
"Wed 19:00",
"Wed 20:00",
"Wed 21:00",
"Wed 22:00",
"Wed 23:00",
"Thu 00:00",
"Thu 01:00",
"Thu 02:00",
"Thu 03:00",
"Thu 04:00",
"Thu 05:00",
"Thu 06:00",
"Thu 07:00",
"Thu 08:00",
"Thu 09:00",
"Thu 10:00",
"Thu 11:00",
"Thu 12:00",
"Thu 13:00",
"Thu 14:00",
"Thu 15:00",
"Thu 16:00",
"Thu 17:00",
"Thu 18:00",
"Thu 19:00",
"Thu 20:00",
"Thu 21:00",
"Thu 22:00",
"Thu 23:00",
"Fri 00:00",
"Fri 01:00",
"Fri 02:00",
"Fri 03:00",
"Fri 04:00",
"Fri 05:00",
"Fri 06:00",
"Fri 07:00",
"Fri 08:00",
"Fri 09:00",
"Fri 10:00",
"Fri 11:00",
"Fri 12:00",
"Fri 13:00",
"Fri 14:00",
"Fri 15:00",
"Fri 16:00",
"Fri 17:00",
"Fri 18:00",
"Fri 19:00",
"Fri 20:00",
"Fri 21:00",
"Fri 22:00",
"Fri 23:00",
"Sat 00:00",
"Sat 01:00",
"Sat 02:00",
"Sat 03:00",
"Sat 04:00",
"Sat 05:00",
"Sat 06:00",
"Sat 07:00",
"Sat 08:00",
"Sat 09:00",
"Sat 10:00",
"Sat 11:00",
"Sat 12:00",
"Sat 13:00",
"Sat 14:00",
"Sat 15:00",
"Sat 16:00",
"Sat 17:00",
"Sat 18:00",
"Sat 19:00",
"Sat 20:00",
"Sat 21:00",
"Sat 22:00",
"Sat 23:00",
"Sun 00:00",
"Sun 01:00",
"Sun 02:00",
"Sun 03:00",
"Sun 04:00",
"Sun 05:00",
"Sun 06:00",
"Sun 07:00",
"Sun 08:00",
"Sun 09:00",
"Sun 10:00",
"Sun 11:00",
"Sun 12:00",
"Sun 13:00",
"Sun 14:00",
"Sun 15:00",
"Sun 16:00",
"Sun 17:00",
"Sun 18:00",
"Sun 19:00",
"Sun 20:00",
"Sun 21:00",
"Sun 22:00",
"Sun 23:00"
]
},
"plotOptions": {
"radialColumn": {
"innerRadius": 0.74,
"hole": "30%",
"center": {
"label": "Requests (week)"
},
"fill": {
"type": "value",
"stops": [
"#475569",
"#64748b",
"#cbd5e1"
]
},
"categoryLabels": {
"step": 1,
"orientation": "horizontal",
"formatter": function (c) { return / 12:00$/.test(c) ? c.slice(0, 3) : '' }
},
"link": {
"mode": "angle",
"unit": "hours"
},
"markers": [
{
"at": "Wed 17:00",
"kind": "Deploy",
"label": "checkout v2.41",
"color": "#f472b6"
},
{
"at": "Thu 02:00",
"kind": "Deploy",
"label": "model server 0.9 (batch)",
"color": "#f472b6"
}
],
"layers": [
{
"type": "donut",
"name": "Cost per cluster (€ / day)",
"data": [
{
"x": "eu-k8s-1",
"y": 410,
"color": "#38bdf8",
"keys": [
"eu-k8s-1"
]
},
{
"x": "eu-k8s-2",
"y": 380,
"color": "#818cf8",
"keys": [
"eu-k8s-2"
]
},
{
"x": "us-k8s-1",
"y": 330,
"color": "#34d399",
"keys": [
"us-k8s-1"
]
},
{
"x": "gpu-inf",
"y": 690,
"color": "#f59e0b",
"keys": [
"gpu-inf"
]
}
],
"thickness": "16%",
"padding": 2,
"link": false,
"legend": false
},
{
"type": "wave",
"name": "CPU load (%)",
"data": [
{
"name": "eu-k8s-1",
"color": "#38bdf8",
"keys": [
"eu-k8s-1"
],
"data": [
29,
25,
22,
20,
23,
25,
30,
37,
47,
51,
56,
59,
50,
45,
36,
33,
33,
42,
47,
58,
57,
59,
49,
40,
32,
28,
23,
20,
22,
22,
28,
38,
43,
52,
59,
58,
56,
49,
39,
36,
35,
39,
47,
59,
62,
58,
50,
39,
33,
28,
25,
23,
23,
24,
28,
34,
41,
53,
57,
61,
52,
43,
40,
35,
35,
42,
55,
60,
60,
56,
50,
39,
28,
26,
25,
24,
26,
29,
31,
35,
45,
56,
62,
57,
52,
46,
38,
32,
32,
42,
52,
57,
59,
60,
51,
43,
34,
28,
25,
23,
25,
24,
29,
36,
44,
49,
56,
53,
48,
40,
32,
31,
32,
36,
48,
53,
55,
56,
49,
40,
22,
17,
16,
15,
17,
19,
24,
26,
33,
35,
41,
41,
37,
29,
23,
22,
24,
28,
34,
40,
39,
35,
29,
25,
17,
13,
11,
14,
17,
17,
19,
21,
26,
33,
35,
36,
33,
26,
22,
null,
null,
null,
null,
null,
null,
null,
null,
null
],
"envelope": {
"lo": [
23,
19,
16,
16,
16,
18,
22,
27,
34,
41,
45,
45,
41,
35,
29,
26,
27,
32,
39,
46,
49,
46,
39,
30,
24,
19,
17,
16,
17,
19,
22,
28,
35,
42,
46,
46,
42,
36,
30,
26,
28,
33,
41,
48,
51,
48,
40,
32,
25,
20,
18,
17,
18,
19,
23,
29,
36,
43,
48,
48,
44,
37,
31,
27,
28,
34,
42,
49,
52,
49,
42,
33,
24,
20,
17,
17,
17,
19,
23,
28,
36,
43,
47,
47,
43,
36,
30,
27,
28,
33,
41,
48,
51,
48,
41,
32,
22,
18,
16,
15,
16,
17,
21,
26,
33,
39,
43,
43,
39,
33,
28,
25,
26,
31,
38,
45,
47,
45,
38,
29,
15,
12,
10,
10,
10,
11,
14,
// Full configuration available through Raw or Copy.
const chart = new WestCoastCharts(document.querySelector('#chart'), options)
chart.render()import WestCoastCharts from 'west-coast-charts'
import premium from 'west-coast-charts/premium'
import waveRing from 'west-coast-charts/layers/wave-ring'
WestCoastCharts.use(premium).use(waveRing)
const WestCoastChartsPremium = premium
const WestCoastChartsLayer_waveRing = waveRing
WestCoastCharts.setLicenseKey(LICENCE_KEY) // paid production licence; localhost evaluation needs no key
const options = {
"chart": {
"type": "radialColumn",
"height": 680,
"toolbar": {
"show": false
}
},
"series": [
{
"name": "Requests (k / h)",
"data": [
322,
322,
313,
304,
304,
282,
273,
298,
344,
369,
400,
425,
415,
415,
391,
381,
391,
428,
440,
474,
450,
425,
381,
344,
335,
341,
335,
319,
298,
276,
291,
322,
341,
375,
428,
437,
437,
425,
397,
381,
397,
440,
468,
487,
474,
431,
384,
350,
341,
332,
326,
310,
307,
291,
288,
295,
335,
394,
419,
440,
434,
400,
384,
409,
428,
456,
589,
583,
471,
422,
384,
341,
301,
322,
332,
338,
322,
313,
298,
310,
338,
400,
434,
431,
437,
400,
391,
378,
397,
459,
493,
508,
474,
453,
409,
357,
338,
329,
332,
310,
295,
276,
270,
298,
316,
369,
412,
397,
391,
366,
347,
357,
363,
384,
446,
459,
456,
428,
391,
344,
236,
223,
236,
211,
214,
202,
217,
223,
254,
267,
291,
307,
301,
273,
264,
279,
298,
313,
338,
344,
313,
363,
257,
242,
195,
189,
183,
186,
171,
164,
158,
174,
192,
233,
251,
264,
251,
236,
233,
null,
null,
null,
null,
null,
null,
null,
null,
null
]
}
],
"xaxis": {
"categories": [
"Mon 00:00",
"Mon 01:00",
"Mon 02:00",
"Mon 03:00",
"Mon 04:00",
"Mon 05:00",
"Mon 06:00",
"Mon 07:00",
"Mon 08:00",
"Mon 09:00",
"Mon 10:00",
"Mon 11:00",
"Mon 12:00",
"Mon 13:00",
"Mon 14:00",
"Mon 15:00",
"Mon 16:00",
"Mon 17:00",
"Mon 18:00",
"Mon 19:00",
"Mon 20:00",
"Mon 21:00",
"Mon 22:00",
"Mon 23:00",
"Tue 00:00",
"Tue 01:00",
"Tue 02:00",
"Tue 03:00",
"Tue 04:00",
"Tue 05:00",
"Tue 06:00",
"Tue 07:00",
"Tue 08:00",
"Tue 09:00",
"Tue 10:00",
"Tue 11:00",
"Tue 12:00",
"Tue 13:00",
"Tue 14:00",
"Tue 15:00",
"Tue 16:00",
"Tue 17:00",
"Tue 18:00",
"Tue 19:00",
"Tue 20:00",
"Tue 21:00",
"Tue 22:00",
"Tue 23:00",
"Wed 00:00",
"Wed 01:00",
"Wed 02:00",
"Wed 03:00",
"Wed 04:00",
"Wed 05:00",
"Wed 06:00",
"Wed 07:00",
"Wed 08:00",
"Wed 09:00",
"Wed 10:00",
"Wed 11:00",
"Wed 12:00",
"Wed 13:00",
"Wed 14:00",
"Wed 15:00",
"Wed 16:00",
"Wed 17:00",
"Wed 18:00",
"Wed 19:00",
"Wed 20:00",
"Wed 21:00",
"Wed 22:00",
"Wed 23:00",
"Thu 00:00",
"Thu 01:00",
"Thu 02:00",
"Thu 03:00",
"Thu 04:00",
"Thu 05:00",
"Thu 06:00",
"Thu 07:00",
"Thu 08:00",
"Thu 09:00",
"Thu 10:00",
"Thu 11:00",
"Thu 12:00",
"Thu 13:00",
"Thu 14:00",
"Thu 15:00",
"Thu 16:00",
"Thu 17:00",
"Thu 18:00",
"Thu 19:00",
"Thu 20:00",
"Thu 21:00",
"Thu 22:00",
"Thu 23:00",
"Fri 00:00",
"Fri 01:00",
"Fri 02:00",
"Fri 03:00",
"Fri 04:00",
"Fri 05:00",
"Fri 06:00",
"Fri 07:00",
"Fri 08:00",
"Fri 09:00",
"Fri 10:00",
"Fri 11:00",
"Fri 12:00",
"Fri 13:00",
"Fri 14:00",
"Fri 15:00",
"Fri 16:00",
"Fri 17:00",
"Fri 18:00",
"Fri 19:00",
"Fri 20:00",
"Fri 21:00",
"Fri 22:00",
"Fri 23:00",
"Sat 00:00",
"Sat 01:00",
"Sat 02:00",
"Sat 03:00",
"Sat 04:00",
"Sat 05:00",
"Sat 06:00",
"Sat 07:00",
"Sat 08:00",
"Sat 09:00",
"Sat 10:00",
"Sat 11:00",
"Sat 12:00",
"Sat 13:00",
"Sat 14:00",
"Sat 15:00",
"Sat 16:00",
"Sat 17:00",
"Sat 18:00",
"Sat 19:00",
"Sat 20:00",
"Sat 21:00",
"Sat 22:00",
"Sat 23:00",
"Sun 00:00",
"Sun 01:00",
"Sun 02:00",
"Sun 03:00",
"Sun 04:00",
"Sun 05:00",
"Sun 06:00",
"Sun 07:00",
"Sun 08:00",
"Sun 09:00",
"Sun 10:00",
"Sun 11:00",
"Sun 12:00",
"Sun 13:00",
"Sun 14:00",
"Sun 15:00",
"Sun 16:00",
"Sun 17:00",
"Sun 18:00",
"Sun 19:00",
"Sun 20:00",
"Sun 21:00",
"Sun 22:00",
"Sun 23:00"
]
},
"plotOptions": {
"radialColumn": {
"innerRadius": 0.74,
"hole": "30%",
"center": {
"label": "Requests (week)"
},
"fill": {
"type": "value",
"stops": [
"#475569",
"#64748b",
"#cbd5e1"
]
},
"categoryLabels": {
"step": 1,
"orientation": "horizontal",
"formatter": function (c) { return / 12:00$/.test(c) ? c.slice(0, 3) : '' }
},
"link": {
"mode": "angle",
"unit": "hours"
},
"markers": [
{
"at": "Wed 17:00",
"kind": "Deploy",
"label": "checkout v2.41",
"color": "#f472b6"
},
{
"at": "Thu 02:00",
"kind": "Deploy",
"label": "model server 0.9 (batch)",
"color": "#f472b6"
}
],
"layers": [
{
"type": "donut",
"name": "Cost per cluster (€ / day)",
"data": [
{
"x": "eu-k8s-1",
"y": 410,
"color": "#38bdf8",
"keys": [
"eu-k8s-1"
]
},
{
"x": "eu-k8s-2",
"y": 380,
"color": "#818cf8",
"keys": [
"eu-k8s-2"
]
},
{
"x": "us-k8s-1",
"y": 330,
"color": "#34d399",
"keys": [
"us-k8s-1"
]
},
{
"x": "gpu-inf",
"y": 690,
"color": "#f59e0b",
"keys": [
"gpu-inf"
]
}
],
"thickness": "16%",
"padding": 2,
"link": false,
"legend": false
},
{
"type": "wave",
"name": "CPU load (%)",
"data": [
{
"name": "eu-k8s-1",
"color": "#38bdf8",
"keys": [
"eu-k8s-1"
],
"data": [
29,
25,
22,
20,
23,
25,
30,
37,
47,
51,
56,
59,
50,
45,
36,
33,
33,
42,
47,
58,
57,
59,
49,
40,
32,
28,
23,
20,
22,
22,
28,
38,
43,
52,
59,
58,
56,
49,
39,
36,
35,
39,
47,
59,
62,
58,
50,
39,
33,
28,
25,
23,
23,
24,
28,
34,
41,
53,
57,
61,
52,
43,
40,
35,
35,
42,
55,
60,
60,
56,
50,
39,
28,
26,
25,
24,
26,
29,
31,
35,
45,
56,
62,
57,
52,
46,
38,
32,
32,
42,
52,
57,
59,
60,
51,
43,
34,
28,
25,
23,
25,
24,
29,
36,
44,
49,
56,
53,
48,
40,
32,
31,
32,
36,
48,
53,
55,
56,
49,
40,
22,
17,
16,
15,
17,
19,
24,
26,
33,
35,
41,
41,
37,
29,
23,
22,
24,
28,
34,
40,
39,
35,
29,
25,
17,
13,
11,
14,
17,
17,
19,
21,
26,
33,
35,
36,
33,
26,
22,
null,
null,
null,
null,
null,
null,
null,
null,
null
],
"envelope": {
"lo": [
23,
19,
16,
16,
16,
18,
22,
27,
34,
41,
45,
45,
41,
35,
29,
26,
27,
32,
39,
46,
49,
46,
39,
30,
24,
19,
17,
16,
17,
19,
22,
28,
35,
42,
46,
46,
42,
36,
30,
26,
28,
33,
41,
48,
51,
48,
40,
32,
25,
20,
18,
17,
18,
19,
23,
29,
36,
43,
48,
48,
44,
37,
31,
27,
28,
34,
42,
49,
52,
49,
42,
33,
24,
20,
17,
17,
17,
19,
23,
28,
36,
43,
47,
47,
43,
36,
30,
27,
28,
33,
41,
48,
51,
48,
41,
32,
22,
18,
16,
15,
16,
17,
21,
26,
33,
39,
43,
43,
39,
33,
28,
25,
26,
31,
38,
45,
47,
45,
38,
29,
15,
12,
10,
10,
10,
11,
14,
// Full configuration available through Raw or Copy.
const chart = new WestCoastCharts(document.querySelector('#chart'), options)
await chart.render() Waiting for the chart.
Open Data & agent view to read this chart through chart.describe().
Read from the running library through its optional agent/describe module. Text, table and JSON share the same snapshot. Demo data only.
$ wcc chart export radial-column-wave-clusters.json --out radial-column-wave-clusters.svg --with-table Public agent tools 0.2.3, tested with Library 1.1.5; available from the versioned GitHub release and npm. Save a JSON spec first and check the loaded runtime and supported modules before rendering. Command reference
Loading /gallery/radial-column/wave-clusters/index.md … This example uses Premium modules. Compare licences · Embedding in a distributed product?