blob: 229a553d67045f61abd27e08e4314dcc8029021a [file] [log] [blame]
Alexb2129542021-11-23 15:49:42 -06001<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
Alex30380a42021-12-20 16:11:20 -06005 <title>Ceph cluster benchmark</title>
Alexb2129542021-11-23 15:49:42 -06006 {% include 'common_styles.j2' %}
7 {% include 'common_scripts.j2' %}
8 {% include 'bar_chart.j2' %}
9 <style>
10 table.cluster_nodes {
11 width: 100%;
12 margin-left: 1%;
13 margin-right: 1%;
14 }
15 .barcontent {
16 margin: auto;
17 width: 1350px;
18 padding: 10px;
19 }
20 .bar-centered {
21 float: none;
22 transform: translate(25%);
23 }
Alex30380a42021-12-20 16:11:20 -060024 .inlineheader {
25 background-color: lightgray;
26 padding-left: 40px;
27 margin-bottom: 10px;
28 }
Alexb2129542021-11-23 15:49:42 -060029 /* Node rows*/
30 .node {
31 font-family: "LaoSangamMN", Monaco, monospace;
32 font-size: 0.8em;
33 display: flex;
34 background-color: white;
35 align-items: center;
36 }
Alex30380a42021-12-20 16:11:20 -060037 .node:hover, .node:active {
38 background-color: #eda;
39 }
Alexb2129542021-11-23 15:49:42 -060040 .collapsable {
41 font-family: "LaoSangamMN", Monaco, monospace;
42 font-size: 0.8em;
43 display: none;
44 background-color: white;
45 visibility: hidden;
46 }
47 .collapsable.in {
48 visibility: visible;
49 display: inline-block;
50 }
51
52 .row_button {
53 background-color: #468;
54 color: #fff;
55 cursor: pointer;
56 padding: 5px;
57 width: 100%;
58 border: none;
59 text-align: left;
60 outline: none;
61 font-size: 13px;
62 }
63 .row_button:after {
64 content: '\02795'; /* Unicode character for "plus" sign (+) */
65 font-size: 13px;
66 color: white;
67 float: left;
68 margin-left: 5px;
69 }
70
71 .row_active:after {
72 content: "\2796"; /* Unicode character for "minus" sign (-) */
73 color: white
74 }
75
76 .row_active, .row_button:hover {
77 background-color: #68a;
78 color: white
79 }
80
81 .cell_button {
82 color: darkgreen;
83 cursor: pointer;
84 padding: 5px;
85 width: 100%;
86 border: none;
87 text-align: center;
88 outline: none;
89 }
90 .cell_button:hover {
91 background-color: gray;
92 }
93
94 .row_content {
95 padding: 0 18px;
96 background-color: white;
97 max-height: 0;
98 overflow: hidden;
99 transition: max-height 0.2s ease-out;
100 border-width: 1px;
101 border-color: #68a;
102 border-style: solid;
103 }
104
105 div.services > .collapsable.in {
106 display: table-row;
107 }
Alex30380a42021-12-20 16:11:20 -0600108 .agents:nth-child(even) {
Alexb2129542021-11-23 15:49:42 -0600109 background-color: #eee;
110 }
Alex30380a42021-12-20 16:11:20 -0600111 .agents:nth-child(odd) {
Alexb2129542021-11-23 15:49:42 -0600112 background-color: #fff;
113 }
114
115 tr.node > td, tr.collapsable > td {
116 display: block;
117 float: left;
118 padding: 1px;
119 margin: 2px;
120 }
121 td > .osd_group {
122 display: grid;
123 grid-template-columns: 40px 25px 25px 70px;
124 padding-left: 0px;
125 padding-right: 0px;
126 margin: 1px;
127 }
128 td > .props_group {
129 display: grid;
130 grid-template-columns: 60px 60px 80px 35px 45px 95px 50px 60px 45px;
131 padding-left: 0px;
132 padding-right: 0px;
133 margin: 1px;
134 }
Alex30380a42021-12-20 16:11:20 -0600135 td > .osd_props_group {
136 display: grid;
137 grid-template-columns: 50px 50px 50px 50px;
138 padding-left: 0px;
139 padding-right: 0px;
140 margin: 1px;
141 }
142 td > .osd_stats_group {
143 display: grid;
144 grid-template-columns: 80px 110px 110px 110px 100px 100px 110px 140px;
145 padding-left: 0px;
146 padding-right: 0px;
147 margin: 1px;
148
149 }
Alexb2129542021-11-23 15:49:42 -0600150 td > .pg_group {
151 display: grid;
152 grid-template-columns: 50px 40px 60px 65px 60px 65px 65px;;
153 padding-left: 0px;
154 padding-right: 0px;
155 margin: 1px;
156 }
157 td > .bench_run_group {
158 display: grid;
159 grid-template-columns: 80px 80px 80px 80px 75px 75px;
160 padding-left: 0px;
161 padding-right: 0px;
162 margin: 1px;
163 }
164 td > .bench_group {
165 display: grid;
166 grid-template-columns: 80px 80px 75px 75px;
167 padding-left: 0px;
168 padding-right: 0px;
169 margin: 1px;
170 }
171 td > .meta_group {
172 display: inline-block;
173 grid-template-columns: repeat(4, auto);
174 padding-left: 0px;
175 padding-right: 0px;
176 margin: 1px;
177 }
178 .item {
179 display: inline-grid;
180 border-width: 1px;
181 border-style: solid;
182 margin: 1px 1px 1px 1px;
183 padding: 0px 1px 0px 1px;
184 }
185
186 .spacer { border-radius: 2px; width: 20px;}
187 .status { border-radius: 10px; width: 120px; text-align: center;}
188 .health_ok { background-color: #393; color: white;}
189 .health_error { background-color: #933; color: white;}
190 .health_warn { background-color: #eb3; color: #333;}
191 .checks_code { border-radius: 2px; width: 20%; background-color: transparent; color: darkred;}
192
193 .head { height: 18px; background-color: transparent; border-color: transparent; border: 0px;}
194 .centered { text-align: center;}
195 .right { text-align: right;}
196 .col_shortmessage { min-width: 300px; }
197 .col_longmessage { width: auto; }
198 .col_properties { width: auto;}
199
200 .srv_name { width: 300px }
201 .srv_path { width: 250px }
202 .srv_timestamp { width: 250px }
203 .srv_addr { width: 450px }
204
205 .id { width: 30px }
206 .bucket_name { width: 365px }
207 .bucket_type { width: 50px }
208 .bucket_params { width: 200px }
209 .bucket_items { width: 630px }
210
211 .df_name { width: 300px }
212 .df_total { width: 150px }
213 .df_avail { width: 150px }
214 .df_used { width: 150px }
215 .df_used_raw { width: 150px }
216 .df_used_raw_rate { width: 150px }
217
218 .rdf_name { width: 200px; }
219 .rdf_obj { width: 75px; }
220 .rdf_total { width: 100px; }
221 .rdf_used { width: 100px; }
222 .rdf_bench { width: 100px; }
223
224 .dev_name { width: 300px; }
225 .dev_param { width: 100px; }
226
227 .mon_name { width: 100px }
228 .mon_url { width: 500px }
229
230 .meters {
231 display: inline-block;
232 margin: 1px;
233 }
234 .meters > .meter {
235 display: block;
236 float: left;
237 border-width: 1px;
238 border-style: solid;
239 margin: 0px 1px 0px 1px;
240 padding: 0px 1px 0px 1px;
241
242 }
243 .meters > .warn {
244 border-color: #d3a200;
245 background-color: rgb(255, 216, 133);
246 }
247 .meters > .fail {
248 border-color: #bb0000;
249 background-color: rgb(250, 135, 135);
250 }
251 .osd { border-color: #a0c0a0; background-color: rgb(252, 248, 248); text-align: center;}
252 .prop { border-color: #74c28b; background-color: rgb(252, 248, 248); text-align: center;}
253 .pg { border-color: #c0c0a0; background-color: rgb(255, 255, 251); text-align: right; }
254 .bench { border-color: #a0c0c0; background-color: rgb(255, 250, 250); text-align: right; }
255 .lat_commit { border-color: #a0c0c0; background-color: rgb(255, 250, 250); text-align: right; width: 45px}
256 .lat_apply { border-color: #a0c0c0; background-color: rgb(255, 250, 250); text-align: left; width: 35px}
257 .meta_name { border-color: #c4b890; background-color: #e7dbb6; text-align: left; width: 150px;}
258 .meta_value { border-color: #c6c3ba;background-color: #d4d4d4; text-align: left; width: 480px;}
259
260 .map_grid {
261 display: grid;
262 grid-template-columns: auto auto auto auto auto auto auto auto auto auto;
263 grid-column-gap: 20px;
264 padding-left: 0px;
265 padding-right: 0px;
266 margin: 1px;
267 margin-left: 20px;
268
269 }
270 .map_item {
271 display: inline-grid;
272 border-width: 0px;
273 border-style: solid;
274 margin: 1px 1px 1px 1px;
275 padding: 0px 1px 0px 1px;
276 }
277
278 .map_grid > .ok {
279 color: #80a080;
280 }
281 .map_grid > .warn {
282 color: #d3a200;
283 }
284 .map_grid > .fail {
285 color: #bb0000;
286 }
287
288 .modules {
289 font-family: "LaoSangamMN", Monaco, monospace;
290 font-size: 0.8em;
291 background-color: white;
292 }
293 .module_node {
294 margin-bottom: 2px;
295 display: flex;
296 }
297 .module_name, .node_name {
298 text-align: center;
299 border-width: 0px;
300 border-style: solid;
301 margin: 1px 1px 1px 1px;
302 padding: 0px 1px 0px 1px;
303 min-width: 250px;
304 border-radius: 10px;
305 }
306 .node_name {
307 background-color: #ddd;
308 }
309 .module_grid {
310 display: grid;
311 grid-template-columns: repeat(8, 100px);
312 grid-template-rows: repeat(6, auto);
313 grid-auto-flow: column;
314 grid-column-gap: 10px;
315 padding-left: 0px;
316 padding-right: 0px;
317 margin: 1px;
318 margin-left: 20px;
319 }
320 .module {
321 display: inline-grid;
322 text-align: center;
323 border-width: 0px;
324 border-style: solid;
325 margin: 1px 1px 1px 1px;
326 padding: 0px 1px 0px 1px;
327 min-width: 100px;
328 border-radius: 10px;
329 }
330
331 .module_grid > .on, .service_node > .ok {
332 background-color: #8c8;
333 }
334 .module_grid > .off, .service_node > .off{
335 background-color: #9aa;
336 }
337 .module_grid > .fail, .service_node > .fail {
338 background-color: #a33;
339 }
340 .module_grid > .always, .service_node > .fail {
341 background-color: #282;
342 }
343
344 .tooltiptext {
345 transform: translate(100px);
346 }
347
348 .console {
349 background-color: black;
350 font-family: "Lucida Console", Monaco, monospace;
351 font-size: 0.5em;
352 width: auto;
353 color: #fff;
354 border-radius: 6px;
355 padding: 5px 5px;
356 }
357
358 </style>
359</head>
Alex30380a42021-12-20 16:11:20 -0600360
361{% macro put_osd_prop(prop, b, a, p) %}
362 {% if prop in p %}
363 <div class="item bench">{{ a[prop] | to_mb }} ({{ "%0.4f" | format(p[prop]|float) }})</div>
364 {% else %}
365 <div class="item bench">{{ a[prop] | to_mb }}</div>
366 {% endif %}
367{% endmacro %}
368
369{% macro put_osd_perc(prop, b, a, p) %}
370 {% if prop in p %}
371 <div class="item bench">{{ "%0.4f"|format(a[prop]|float) }} ({{ "%0.4f" | format(p[prop]|float) }})</div>
372 {% else %}
373 <div class="item bench">{{ "%0.4f"|format(a[prop]|float) }}</div>
374 {% endif %}
375{% endmacro %}
376
377{% macro summary_value(prop, s) %}
378 {% if prop in s %}
379 <div class="item bench">{{ s[prop] }} nodes</div>
380 {% else %}
381 <div class="item bench">0</div>
382 {% endif %}
383{% endmacro %}
384
385
386
Alexb2129542021-11-23 15:49:42 -0600387<body onload="init()">
388
389<div class="header">
390 <div class="label">Ceph version:</div>
391 <div class="text">{{ ceph_version }}</div>
392 <div class="label">Image:</div>
393 <div class="text">{{ cluster.image }}</div>
394 <div class="label date">generated on: {{ gen_date }}</div>
395</div>
396
397<div class="bar">
398 <div class="bar-centered">
399 <button class="bar-item" onclick="openBar(event, 'bench')">Benchmark Results</button>
Alex30380a42021-12-20 16:11:20 -0600400 <button class="bar-item" onclick="openBar(event, 'osdstats')">OSD Stats</button>
Alexb2129542021-11-23 15:49:42 -0600401 <button class="bar-item" onclick="openBar(event, 'status')">Status</button>
402 <!-- <button class="bar-item" onclick="openBar(event, 'latency')">Latency</button> -->
403 </div>
404</div>
405
406<!-- Benchmarks -->
407{% macro bench_page(results, id_label) %}
408<div id="{{ id_label }}" class="barcontent">
409 <h5>{{ caller() }}</h5>
410 <hr>
411 <table class="ceph_status">
412 <tr class="node">
413 <td class="status">Time started</td>
414 <td class="status">Data point</td>
415 <td class="col_properties">
416 <div class="props_group">
417 <div class="item prop">Warmup</div>
418 <div class="item prop">Run Time</div>
419 <div class="item prop">Storage class</div>
420 <div class="item pg">PGs</div>
421 <div class="item prop">Engine</div>
422 <div class="item prop">Mode</div>
423 <div class="item prop">BS</div>
424 <div class="item prop">IOdepth</div>
425 <div class="item prop">Size</div>
426 </div>
427 </td>
428 <td class="col_bench">
429 <div class="bench_run_group">
430 <div class="item bench">Read, MB/s</div>
431 <div class="item bench">Avg lat, usec</div>
432 <div class="item bench">Read, op/s</div>
433 <div class="item bench">Write, MB/s</div>
434 <div class="item bench">Avg lat, usec</div>
435 <div class="item bench">Write, op/s</div>
436 </div>
437 </td>
438 </tr>
439 {% for time,dt in results.items() %}
440 {% set t = dt["totals"] %}
441 {% set o = dt["input_options"] %}
442 {% set tstripped = time | tstrip %}
443 <tr class="node" onclick="toggleClassByID('timing_{{ tstripped }}_data')" id="timing_{{ tstripped }}_button">
444 <td class="status">{{ time }}</td>
445 <td class="status">All agents</td>
446 <td class="col_properties">
447 <div class="props_group">
448 <div class="item prop">{{ o["ramp_time"] }}</div>
449 <div class="item prop">{{ o["runtime"] }}</div>
450 <div class="item prop">{{ t["storage_class"] }}</div>
451 <div class="item pg">{{ t["storage_class_stats"]["num_pg"] }}</div>
452 <div class="item prop">{{ o["ioengine"] }}</div>
Alex30380a42021-12-20 16:11:20 -0600453 <div class="item prop">{{ o["readwrite"] }} ({{ o["rwmixread"] }}/{{ 100 - (o["rwmixread"]|int) }})</div>
Alexb2129542021-11-23 15:49:42 -0600454 <div class="item prop">{{ o["bs"] }}</div>
455 <div class="item prop">{{ o["iodepth"] }}</div>
456 <div class="item prop">{{ o["size"] }}</div>
457 </div>
458 </td>
459 <td class="col_bench">
460 <div class="bench_run_group">
461 <div class="item bench">{{ t["read_bw_bytes"] | to_mb }}</div>
462 <div class="item bench">{{ "%0.2f" | format(t["read_avg_lat_us"]|float) }}</div>
463 <div class="item bench">{{ "%0.2f" | format(t["read_iops"]|float) }}</div>
464 <div class="item bench">{{ t["write_bw_bytes"] | to_mb }}</div>
465 <div class="item bench">{{ "%0.2f" | format(t["write_avg_lat_us"]|float) }}</div>
466 <div class="item bench">{{ "%0.2f" | format(t["write_iops"]|float) }}</div>
467 </div>
468 </td>
469 </tr>
Alex30380a42021-12-20 16:11:20 -0600470 {% set c = dt["ceph"] %}
Alexb2129542021-11-23 15:49:42 -0600471 <tr class="collapsable" id="timing_{{ tstripped }}_data"><td colspan=3>
Alex30380a42021-12-20 16:11:20 -0600472 <div class="inlineheader">Global READ stats, MB/s vs seconds. Measured maximum is <b>{{ c["max_rbl"][0] | to_mb }}</b> MB/sec</div>
Alexb2129542021-11-23 15:49:42 -0600473 <div class="bc-wrap">
474 <div class="bctimecol">
Alex30380a42021-12-20 16:11:20 -0600475 <div class="bctime"><span class="bctimetext">{{ c["max_rbl"][1] | to_mb }}</span></div>
476 <div class="bctime"><span class="bctimetext">{{ c["max_rbl"][2] | to_mb }}</span></div>
477 <div class="bctime"><span class="bctimetext">{{ c["max_rbl"][3] | to_mb }}</span></div>
478 <div class="bctime"><span class="bctimetext">{{ c["max_rbl"][4] | to_mb }}</span></div>
Alexb2129542021-11-23 15:49:42 -0600479 </div>
480
481 <div class="bc-container">
482 <div class="bc">
Alex30380a42021-12-20 16:11:20 -0600483 {% for sec, c_data in c["stats"].items() %}
484 {% set elapsed = sec | float %}
485 <div class="bccol">
486 {% if sec == c["max_rbl_time"] %}
487 <div class="bcheader">{{ c_data["read_bytes_sec"] | to_mb }}</div>
488 <div class="bcbar green-bar" style="height: {{ c_data["read_bytes_sec_perc"] }};"></div>
489 {% else %}
490 <div class="bcbar" style="height: {{ c_data["read_bytes_sec_perc"] }};"></div>
491 {% endif%}
492 <div class="bcfooter">{{ "%0.1f" | format(elapsed) }}</div>
493 </div>
494 {% endfor %}
Alexb2129542021-11-23 15:49:42 -0600495 </div>
496 </div>
497 </div>
Alex30380a42021-12-20 16:11:20 -0600498 <div class="inlineheader">Global READ stats, IOPS vs seconds. Measured maximum is <b>{{ c["max_ril"][0] }}</b> op/sec</div>
499 <div class="bc-wrap">
500 <div class="bctimecol">
501 <div class="bctime"><span class="bctimetext">{{ c["max_ril"][1] }}</span></div>
502 <div class="bctime"><span class="bctimetext">{{ c["max_ril"][2] }}</span></div>
503 <div class="bctime"><span class="bctimetext">{{ c["max_ril"][3] }}</span></div>
504 <div class="bctime"><span class="bctimetext">{{ c["max_ril"][4] }}</span></div>
505 </div>
506
507 <div class="bc-container">
508 <div class="bc">
509 {% for sec, c_data in c["stats"].items() %}
510 {% set elapsed = sec | float %}
511 <div class="bccol">
512 {% if sec == c["max_ril_time"] %}
513 <div class="bcheader">{{ c_data["read_op_per_sec"] }}</div>
514 <div class="bcbar green-bar" style="height: {{ c_data["read_op_per_sec_perc"] }};"></div>
515 {% else %}
516 <div class="bcbar" style="height: {{ c_data["read_op_per_sec_perc"] }};"></div>
517 {% endif%}
518 <div class="bcfooter">{{ "%0.1f" | format(elapsed) }}</div>
519 </div>
520 {% endfor %}
521 </div>
522 </div>
523 </div>
524 <div class="inlineheader">Global WRITE stats, MB/s vs seconds. Measured maximum is <b>{{ c["max_wbl"][0] | to_mb }}</b> MB/sec</div>
525 <div class="bc-wrap">
526 <div class="bctimecol">
527 <div class="bctime"><span class="bctimetext">{{ c["max_wbl"][1] | to_mb }}</span></div>
528 <div class="bctime"><span class="bctimetext">{{ c["max_wbl"][2] | to_mb }}</span></div>
529 <div class="bctime"><span class="bctimetext">{{ c["max_wbl"][3] | to_mb }}</span></div>
530 <div class="bctime"><span class="bctimetext">{{ c["max_wbl"][4] | to_mb }}</span></div>
531 </div>
532
533 <div class="bc-container">
534 <div class="bc">
535 {% for sec, c_data in c["stats"].items() %}
536 {% set elapsed = sec | float %}
537 <div class="bccol">
538 {% if sec == c["max_wbl_time"] %}
539 <div class="bcheader">{{ c_data["write_bytes_sec"] | to_mb }}</div>
540 <div class="bcbar green-bar" style="height: {{ c_data["write_bytes_sec_perc"] }};"></div>
541 {% else %}
542 <div class="bcbar" style="height: {{ c_data["write_bytes_sec_perc"] }};"></div>
543 {% endif%}
544 <div class="bcfooter">{{ "%0.1f" | format(elapsed) }}</div>
545 </div>
546 {% endfor %}
547 </div>
548 </div>
549 </div>
550
551 <div class="inlineheader">Global WRITE stats, IOPS vs seconds. Measured maximum is <b>{{ c["max_wil"][0] }}</b> op/sec</div>
552 <div class="bc-wrap">
553 <div class="bctimecol">
554 <div class="bctime"><span class="bctimetext">{{ c["max_wil"][1] }}</span></div>
555 <div class="bctime"><span class="bctimetext">{{ c["max_wil"][2] }}</span></div>
556 <div class="bctime"><span class="bctimetext">{{ c["max_wil"][3] }}</span></div>
557 <div class="bctime"><span class="bctimetext">{{ c["max_wil"][4] }}</span></div>
558 </div>
559
560 <div class="bc-container">
561 <div class="bc">
562 {% for sec, c_data in c["stats"].items() %}
563 {% set elapsed = sec | float %}
564 <div class="bccol">
565 {% if sec == c["max_wil_time"] %}
566 <div class="bcheader">{{ c_data["write_op_per_sec"] }}</div>
567 <div class="bcbar green-bar" style="height: {{ c_data["write_op_per_sec_perc"] }};"></div>
568 {% else %}
569 <div class="bcbar" style="height: {{ c_data["write_op_per_sec_perc"] }};"></div>
570 {% endif%}
571 <div class="bcfooter">{{ "%0.1f" | format(elapsed) }}</div>
572 </div>
573 {% endfor %}
574 </div>
575 </div>
576 </div>
577 <div class="inlineheader">Per Agent stats</div>
Alexb2129542021-11-23 15:49:42 -0600578 <table style="table-layout: auto;"><tbody>
579 {% for agent,ag_result in dt["agents"].items() %}
Alex90ac1532021-12-09 11:13:14 -0600580 {% set j = ag_result["jobs"][0] %}
Alex30380a42021-12-20 16:11:20 -0600581 <tr class="agents">
Alexb2129542021-11-23 15:49:42 -0600582 <td class="status">{{ time }}</td>
583 <td class="status">{{ agent }}</td>
584 <td class="col_properties">
585 <div class="props_group">
586 <div class="item prop">{{ j["job options"]["ramp_time"] }}</div>
587 <div class="item prop">{{ j["job options"]["runtime"] }}</div>
588 <div class="item prop">{{ t["storage_class"] }}</div>
589 <div class="item pg">{{ t["storage_class_stats"]["num_pg"] }}</div>
590 <div class="item prop">{{ o["ioengine"] }}</div>
Alex30380a42021-12-20 16:11:20 -0600591 <div class="item prop">{{ o["readwrite"] }} ({{ o["rwmixread"] }}/{{ 100 - (o["rwmixread"]|int) }})</div>
Alexb2129542021-11-23 15:49:42 -0600592 <div class="item prop">{{ j["job options"]["bs"] }}</div>
593 <div class="item prop">{{ o["iodepth"] }}</div>
594 <div class="item prop">{{ j["job options"]["size"] }}</div>
595 </div>
596 </td>
597 <td class="col_bench">
598 <div class="bench_run_group">
599 <div class="item bench">{{ j["read"]["bw_bytes"] | to_mb }}</div>
600 <div class="item bench">{{ "%0.2f" | format(j["read"]["lat_ns"]["mean"]|float / 1000) }}</div>
601 <div class="item bench">{{ "%0.2f" | format(j["read"]["iops"]|float) }}</div>
602 <div class="item bench">{{ j["write"]["bw_bytes"] | to_mb }}</div>
603 <div class="item bench">{{ "%0.2f" | format(j["write"]["lat_ns"]["mean"]|float / 1000) }}</div>
604 <div class="item bench">{{ "%0.2f" | format(j["write"]["iops"]|float) }}</div>
605 </div>
606 </td>
607 </tr>
608 </tr>
609 {% endfor %}
610 </tbody></table>
611 </td></tr>
612 {% endfor %}
613 </table>
614</div>
615{% endmacro %}
616
Alex30380a42021-12-20 16:11:20 -0600617<!-- OSD stats -->
618{% macro osds_page(results, id_label) %}
619<div id="{{ id_label }}" class="barcontent">
620 <h5>{{ caller() }}</h5>
621 <hr>
622 <table class="ceph_status">
623 <tr class="node">
624 <td class="status">Time started</td>
625 <td class="status">Data point</td>
626 <td class="col_properties">
627 <div class="osd_props_group">
628 <div class="item prop">Status</div>
629 <div class="item prop">Class</div>
630 <div class="item prop">Weight</div>
631 <div class="item pg">PGs</div>
632 </div>
633 </td>
634 <td class="col_bench">
635 <div class="osd_stats_group">
636 <div class="item bench">Total, GB</div>
637 <div class="item bench">Avail., GB</div>
638 <div class="item bench">Used, GB</div>
639 <div class="item bench">Data, GB</div>
640 <div class="item bench">OMAP, GB</div>
641 <div class="item bench">Meta, GB</div>
642 <div class="item bench">Utilized, %</div>
643 <div class="item bench">Variance, %</div>
644 </div>
645 </td>
646 </tr>
647 {% for time,dt in results.items() %}
648 {% set b = dt["osd_summary"]["before"] %}
649 {% set a = dt["osd_summary"]["after"] %}
650 {% set s = dt["osd_summary"]["active"] %}
651 {% set tstripped = time | tstrip %}
652 <tr class="node" onclick="toggleClassByID('timing_{{ tstripped }}_osds')" id="timing_{{ tstripped }}_button">
653 <td class="status">{{ time }}</td>
654 <td class="status">Active nodes</td>
655 <td class="col_properties">
656 <div class="osd_props_group">
657 <div class="item prop">{{ s["status"] }}</div>
658 <div class="item prop">{{ s["device_class"] }}</div>
659 <div class="item prop">&minus;</div>
660 <div class="item pg">{{ s["pgs"] }}</div>
661 </div>
662 </td>
663 <td class="col_bench">
664 <div class="osd_stats_group">
665 <div class="item bench">{{ a["total_kb"] | to_mb }}</div>
666 {{ summary_value("kb_avail", s) }}
667 {{ summary_value("kb_used", s) }}
668 {{ summary_value("kb_used_data", s) }}
669 {{ summary_value("kb_used_omap", s) }}
670 {{ summary_value("kb_used_meta", s) }}
671 {{ summary_value("utilization", s) }}
672 <div class="item bench">{{ s["var_down"] }}&darr; / {{ s["var_up"] }}&uarr;</div>
673 </div>
674 </td>
675 </tr>
676 <tr class="collapsable" id="timing_{{ tstripped }}_osds"><td colspan=3>
677 <table style="table-layout: auto;"><tbody>
678 {% for osd in dt["osds"].keys() | sort %}
679 {% set n = dt["osds"][osd] %}
680 {% set b = n["before"] %}
681 {% set a = n["after"] %}
682 {% set p = n["percent"] %}
683 <tr class="agents">
684 <td class="status">{{ time }}</td>
685 <td class="status">{{ osd }}</td>
686 <td class="col_properties">
687 <div class="osd_props_group">
688 <div class="item prop">{{ a["status"] }}</div>
689 <div class="item prop">{{ a["device_class"] }}</div>
690 <div class="item prop">{{ "%0.4f" | format(a["crush_weight"]|float) }}</div>
691 <div class="item pg">{{ a["pgs"] }}</div>
692 </div>
693 </td>
694 <td class="col_bench">
695 <div class="osd_stats_group">
696 <div class="item bench">{{ a["kb"] | to_mb }}</div>
697 {{ put_osd_prop("kb_avail", b, a, p) }}
698 {{ put_osd_prop("kb_used", b, a, p) }}
699 {{ put_osd_prop("kb_used_data", b, a, p) }}
700 {{ put_osd_prop("kb_used_omap", b, a, p) }}
701 {{ put_osd_prop("kb_used_meta", b, a, p) }}
702 {{ put_osd_perc("utilization", b, a, p) }}
703 {{ put_osd_perc("var", b, a, p) }}
704 </div>
705 </td>
706 </tr>
707 {% endfor %}
708 </tbody></table>
709 </td></tr>
710 {% endfor %}
711 </table>
712</div>
713{% endmacro %}
714
715
Alexb2129542021-11-23 15:49:42 -0600716<!-- Status page -->
717{% macro status_page(info, id_label) %}
718<div id="{{ id_label }}" class="barcontent">
719 <h5>{{ caller() }}</h5>
720 <hr>
721 <table class="ceph_status">
722 <tr class="node">
723 <td class="status">Cluster status</td>
724 <td class="col_shortmessage">Status summary</td>
725 <td class="col_osd">
726 <div class="osd_group">
727 <div class="item osd">OSDs</div>
728 <div class="item osd">Up</div>
729 <div class="item osd">In</div>
730 <div class="item osd">Remap PGs</div>
731 </div>
732 </td>
733 <td class="col_pgs">
734 <div class="pg_group">
735 <div class="item pg">PGs</div>
736 <div class="item pg">Pools</div>
737 <div class="item pg">Objects</div>
738 <div class="item pg">Data, GB</div>
739 <div class="item pg">Used, GB</div>
740 <div class="item pg">Avail, GB</div>
741 <div class="item pg">Total, GB</div>
742 </div>
743 </td>
744 <td class="col_bench">
745 <div class="bench_group">
746 <div class="item bench">Read, MB/sec</div>
747 <div class="item bench">Write, MB/sec</div>
748 <div class="item bench">Read, op/sec</div>
749 <div class="item bench">Write, op/sec</div>
750 </div>
751 </td>
752 </tr>
753 {% set cs = idle_status %}
754 {% set osdmap = cs | get_osdmap %}
755 <tr class="node" onclick="toggleClassByID('health_data')" id="health_data_button">
756 <td class="status {{ health_detail["status"] | lower }}">{{ health_detail["status"] }}</td>
757 <td class="col_shortmessage">
758 {% for code,dt in health_detail["checks"].items() %}
759 {{ dt["summary"]["message"] }}<br>
760 {% endfor %}
761 </td>
762 <!-- background: linear-gradient(to right, gray 0% 20%, transparent 20% 100%); -->
763 <td class="col_osd">
764 <div class="osd_group">
765 <div class="item osd">{{ osdmap["num_osds"] }}</div>
766 <div class="item osd">{{ osdmap["num_up_osds"] }}</div>
767 <div class="item osd">{{ osdmap["num_in_osds"] }}</div>
768 <div class="item osd">{{ osdmap["num_remapped_pgs"] }}</div>
769 </div>
770 </td>
771 {% set pgmap = cs["pgmap"] %}
772 <td class="col_pgs">
773 <div class="pg_group">
774 <div class="item pg">{{ pgmap["num_pgs"] }}</div>
775 <div class="item pg">{{ pgmap["num_pools"] }}</div>
776 <div class="item pg">{{ pgmap["num_objects"] }}</div>
777 <div class="item pg">{{ pgmap["data_bytes"] | to_gb }}</div>
778 <div class="item pg">{{ pgmap["bytes_used"] | to_gb }}</div>
779 <div class="item pg">{{ pgmap["bytes_avail"] | to_gb }}</div>
780 <div class="item pg">{{ pgmap["bytes_total"] | to_gb }}</div>
781 </div>
782 </td>
783 <td class="col_bench">
784 <div class="bench_group">
785 {% if "read_bytes_sec" in pgmap %}
786 <div class="item bench">{{ pgmap["read_bytes_sec"] | to_mb }}</div>
787 {% else %}
788 <div class="item bench">0</div>
789 {% endif %}
790 {% if "write_bytes_sec" in pgmap %}
791 <div class="item bench">{{ pgmap["write_bytes_sec"] | to_mb }}</div>
792 {% else %}
793 <div class="item bench">0</div>
794 {% endif %}
795 {% if "read_op_per_sec" in pgmap %}
796 <div class="item bench">{{ pgmap["read_op_per_sec"] }}</div>
797 {% else %}
798 <div class="item bench">0</div>
799 {% endif %}
800 {% if "write_op_per_sec" in pgmap %}
801 <div class="item bench">{{ pgmap["write_op_per_sec"] }}</div>
802 {% else %}
803 <div class="item bench">0</div>
804 {% endif %}
805 </div>
806 </td>
807 </tr>
808 <tr class="collapsable in" id="health_data"><td colspan=3>
809 <table><tbody>
810 {% for code,dt in health_detail["checks"].items() %}
811 <tr>
812 <td class="spacer"></td>
813 <td class="status {{ dt["severity"] | lower }}">{{ dt["severity"] }}</td>
814 <td class="checks_code">{{ code }}</td>
815 <td class="col_longmessage">
816 <table><tbody>
817 {% for detail in dt["detail"] %}
818 <tr><td>{{ detail["message"] }}</td></tr>
819 {% endfor %}
820 </tbody></table>
821 </td>
822 </tr>
823 {% endfor %}
824 </tbody></table>
825 </td></tr>
826 </table>
827 <hr>
828 <!-- Services -->
829 {% set sm = idle_status["servicemap"] %}
830 <h5>Services: {{ sm["services"] | count }} running. Last modification: {{ sm["modified"] }}</h5>
831 <table class="ceph_status">
832 <tr class="node">
833 <td class="srv_name">Name</td>
834 <td class="srv_path">Subpath</td>
835 <td class="srv_timestamp">Start time</td>
836 <td class="srv_addr">Address</td>
837 </tr>
838 {% for name, d1 in sm["services"].items() %}
839 {% if "daemons" in d1 %}
840 {% set d2 = d1["daemons"] %}
841 {% for key, d3 in d2.items() %}
842 {% if key.startswith("rgw.store") %}
843 <tr class="node" onclick="toggleClassByID('{{ name }}_service_data')" id="{{ name }}_service_data_button">
844 <td class="srv_name">{{ name }} ({{ d3["gid"] }})</td>
845 <td class="srv_path">daemons:{{ key }}</td>
846 <td class="srv_timestamp">{{ d3["start_stamp"] }}</td>
847 <td class="srv_addr">{{ d3["addr"] }}</td>
848 </tr>
849 <tr class="collapsable in" id="{{ name}}_service_data"><td colspan=4>
850 <table><tbody>
851 <tr><td class="metadata">
852 {% for mname, mvalue in d3["metadata"].items() %}
853 <div class="meta_group">
854 <div class="item meta_name">{{ mname }}</div>
855 <div class="item meta_value">{{ mvalue }}</div>
856 </div>
857 {% endfor %}
858 </td></tr>
859 </tbody></table>
860 </td></tr>
861 {% endif %}
862 {% endfor %}
863 {% endif %}
864 {% endfor %}
865 </table>
866 <hr>
867 <!-- Modules -->
868 {% set mgrmap = idle_status["mgrmap"] %}
869 {% set mods = mgrmap["modules"] %}
870 {% set avail = mgrmap["available_modules"] %}
871 {% if "always_on_modules" in mgrmap %}
872 {% set always_on = mgrmap["always_on_modules"].values() | list %}
873 {% set always_on = always_on[0] %}
874 {% else %}
875 {% set always_on = [] %}
876 {% endif %}
877 <h5>Modules: {{ mods | count}} active. {{ always_on | count }} always on. {{ avail | count }} available.</h5>
878 <div class="modules">
879 <div class="module_grid">
880 {% for mod in avail %}
881 {% if mod["name"] in always_on %}
882 <div class="module always">{{ mod["name"] }}</div>
883 {% elif mod["name"] in mods %}
884 <div class="module on">{{ mod["name"] }}</div>
885 {% elif not mod["can_run"] %}
886 <div class="module fail tooltip">
887 <div class="module fail">{{ mod["name"] }}</div>
888 <pre class="tooltiptext">{{ mod["error_string"] | linebreaks }}</pre>
889 </div>
890 {% else %}
891 <div class="module">{{ mod["name"] }}</div>
892 {% endif %}
893 {% endfor %}
894 </div>
895 </div>
896 <hr>
897</div>
898{% endmacro %}
899
900<!-- ================================= -->
901<!-- Cluster nodes page -->
902{% call bench_page(results, "bench") %}
903 Benchmark results
904{% endcall %}
905
Alex30380a42021-12-20 16:11:20 -0600906{% call osds_page(results, "osdstats") %}
907 OSD nodes stats collected before and after each step
908{% endcall %}
909
Alexb2129542021-11-23 15:49:42 -0600910{% call status_page(info, "status") %}
911 Cluster status
912{% endcall %}
913
914</body>
915</html>