blob: 1a9e99483c6ce486dd26a8fa4624fd21d6148fd4 [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;
Alexbdc72742021-12-23 13:26:05 -060046 width: 100%;
47 border-style: dashed;
48 border-width: 1px;
Alexb2129542021-11-23 15:49:42 -060049 }
50 .collapsable.in {
51 visibility: visible;
52 display: inline-block;
53 }
54
55 .row_button {
56 background-color: #468;
57 color: #fff;
58 cursor: pointer;
59 padding: 5px;
60 width: 100%;
61 border: none;
62 text-align: left;
63 outline: none;
64 font-size: 13px;
65 }
66 .row_button:after {
67 content: '\02795'; /* Unicode character for "plus" sign (+) */
68 font-size: 13px;
69 color: white;
70 float: left;
71 margin-left: 5px;
72 }
73
74 .row_active:after {
75 content: "\2796"; /* Unicode character for "minus" sign (-) */
76 color: white
77 }
78
79 .row_active, .row_button:hover {
80 background-color: #68a;
81 color: white
82 }
83
84 .cell_button {
85 color: darkgreen;
86 cursor: pointer;
87 padding: 5px;
88 width: 100%;
89 border: none;
90 text-align: center;
91 outline: none;
92 }
93 .cell_button:hover {
94 background-color: gray;
95 }
96
97 .row_content {
98 padding: 0 18px;
99 background-color: white;
100 max-height: 0;
101 overflow: hidden;
102 transition: max-height 0.2s ease-out;
103 border-width: 1px;
104 border-color: #68a;
105 border-style: solid;
106 }
107
108 div.services > .collapsable.in {
109 display: table-row;
110 }
Alex30380a42021-12-20 16:11:20 -0600111 .agents:nth-child(even) {
Alexb2129542021-11-23 15:49:42 -0600112 background-color: #eee;
113 }
Alex30380a42021-12-20 16:11:20 -0600114 .agents:nth-child(odd) {
Alexb2129542021-11-23 15:49:42 -0600115 background-color: #fff;
116 }
117
118 tr.node > td, tr.collapsable > td {
119 display: block;
120 float: left;
121 padding: 1px;
122 margin: 2px;
123 }
124 td > .osd_group {
125 display: grid;
126 grid-template-columns: 40px 25px 25px 70px;
127 padding-left: 0px;
128 padding-right: 0px;
129 margin: 1px;
130 }
131 td > .props_group {
132 display: grid;
Alex0989ecf2022-03-29 13:43:21 -0500133 grid-template-columns: 60px 80px 35px 45px 95px 110px;;
Alexb2129542021-11-23 15:49:42 -0600134 padding-left: 0px;
135 padding-right: 0px;
136 margin: 1px;
137 }
Alex30380a42021-12-20 16:11:20 -0600138 td > .osd_props_group {
139 display: grid;
140 grid-template-columns: 50px 50px 50px 50px;
141 padding-left: 0px;
142 padding-right: 0px;
143 margin: 1px;
144 }
145 td > .osd_stats_group {
146 display: grid;
147 grid-template-columns: 80px 110px 110px 110px 100px 100px 110px 140px;
148 padding-left: 0px;
149 padding-right: 0px;
150 margin: 1px;
151
152 }
Alexb2129542021-11-23 15:49:42 -0600153 td > .pg_group {
154 display: grid;
155 grid-template-columns: 50px 40px 60px 65px 60px 65px 65px;;
156 padding-left: 0px;
157 padding-right: 0px;
158 margin: 1px;
159 }
160 td > .bench_run_group {
161 display: grid;
Alex0989ecf2022-03-29 13:43:21 -0500162 grid-template-columns: 80px 110px 80px 80px 110px 80px;;
Alexb2129542021-11-23 15:49:42 -0600163 padding-left: 0px;
164 padding-right: 0px;
165 margin: 1px;
166 }
167 td > .bench_group {
168 display: grid;
169 grid-template-columns: 80px 80px 75px 75px;
170 padding-left: 0px;
171 padding-right: 0px;
172 margin: 1px;
173 }
174 td > .meta_group {
175 display: inline-block;
176 grid-template-columns: repeat(4, auto);
177 padding-left: 0px;
178 padding-right: 0px;
179 margin: 1px;
180 }
181 .item {
Alexb2129542021-11-23 15:49:42 -0600182 border-width: 1px;
183 border-style: solid;
184 margin: 1px 1px 1px 1px;
185 padding: 0px 1px 0px 1px;
186 }
187
Alexbdc72742021-12-23 13:26:05 -0600188 .details-wrap { margin-left: 20px;}
Alexb2129542021-11-23 15:49:42 -0600189 .spacer { border-radius: 2px; width: 20px;}
Alexbdc72742021-12-23 13:26:05 -0600190 .bench_id { border-radius: 10px; width: 50px; text-align: center;}
191 .time { border-radius: 10px; width: 160px; text-align: center;}
Alexb2129542021-11-23 15:49:42 -0600192 .status { border-radius: 10px; width: 120px; text-align: center;}
193 .health_ok { background-color: #393; color: white;}
194 .health_error { background-color: #933; color: white;}
195 .health_warn { background-color: #eb3; color: #333;}
196 .checks_code { border-radius: 2px; width: 20%; background-color: transparent; color: darkred;}
197
198 .head { height: 18px; background-color: transparent; border-color: transparent; border: 0px;}
199 .centered { text-align: center;}
200 .right { text-align: right;}
201 .col_shortmessage { min-width: 300px; }
202 .col_longmessage { width: auto; }
Alexbdc72742021-12-23 13:26:05 -0600203 .col_properties { width: auto; border-radius: 10px;}
204 .col_bench { width: auto; border-radius: 10px;}
Alexb2129542021-11-23 15:49:42 -0600205
206 .srv_name { width: 300px }
207 .srv_path { width: 250px }
208 .srv_timestamp { width: 250px }
209 .srv_addr { width: 450px }
210
211 .id { width: 30px }
212 .bucket_name { width: 365px }
213 .bucket_type { width: 50px }
214 .bucket_params { width: 200px }
215 .bucket_items { width: 630px }
216
217 .df_name { width: 300px }
218 .df_total { width: 150px }
219 .df_avail { width: 150px }
220 .df_used { width: 150px }
221 .df_used_raw { width: 150px }
222 .df_used_raw_rate { width: 150px }
223
224 .rdf_name { width: 200px; }
225 .rdf_obj { width: 75px; }
226 .rdf_total { width: 100px; }
227 .rdf_used { width: 100px; }
228 .rdf_bench { width: 100px; }
229
230 .dev_name { width: 300px; }
231 .dev_param { width: 100px; }
232
233 .mon_name { width: 100px }
234 .mon_url { width: 500px }
235
236 .meters {
237 display: inline-block;
238 margin: 1px;
239 }
240 .meters > .meter {
241 display: block;
242 float: left;
243 border-width: 1px;
244 border-style: solid;
245 margin: 0px 1px 0px 1px;
246 padding: 0px 1px 0px 1px;
247
248 }
249 .meters > .warn {
250 border-color: #d3a200;
251 background-color: rgb(255, 216, 133);
252 }
253 .meters > .fail {
254 border-color: #bb0000;
255 background-color: rgb(250, 135, 135);
256 }
257 .osd { border-color: #a0c0a0; background-color: rgb(252, 248, 248); text-align: center;}
258 .prop { border-color: #74c28b; background-color: rgb(252, 248, 248); text-align: center;}
259 .pg { border-color: #c0c0a0; background-color: rgb(255, 255, 251); text-align: right; }
260 .bench { border-color: #a0c0c0; background-color: rgb(255, 250, 250); text-align: right; }
261 .lat_commit { border-color: #a0c0c0; background-color: rgb(255, 250, 250); text-align: right; width: 45px}
262 .lat_apply { border-color: #a0c0c0; background-color: rgb(255, 250, 250); text-align: left; width: 35px}
263 .meta_name { border-color: #c4b890; background-color: #e7dbb6; text-align: left; width: 150px;}
264 .meta_value { border-color: #c6c3ba;background-color: #d4d4d4; text-align: left; width: 480px;}
265
266 .map_grid {
267 display: grid;
268 grid-template-columns: auto auto auto auto auto auto auto auto auto auto;
269 grid-column-gap: 20px;
270 padding-left: 0px;
271 padding-right: 0px;
272 margin: 1px;
273 margin-left: 20px;
274
275 }
276 .map_item {
277 display: inline-grid;
278 border-width: 0px;
279 border-style: solid;
280 margin: 1px 1px 1px 1px;
281 padding: 0px 1px 0px 1px;
282 }
283
284 .map_grid > .ok {
285 color: #80a080;
286 }
287 .map_grid > .warn {
288 color: #d3a200;
289 }
290 .map_grid > .fail {
291 color: #bb0000;
292 }
293
294 .modules {
295 font-family: "LaoSangamMN", Monaco, monospace;
296 font-size: 0.8em;
297 background-color: white;
298 }
299 .module_node {
300 margin-bottom: 2px;
301 display: flex;
302 }
303 .module_name, .node_name {
304 text-align: center;
305 border-width: 0px;
306 border-style: solid;
307 margin: 1px 1px 1px 1px;
308 padding: 0px 1px 0px 1px;
309 min-width: 250px;
310 border-radius: 10px;
311 }
312 .node_name {
313 background-color: #ddd;
314 }
315 .module_grid {
316 display: grid;
317 grid-template-columns: repeat(8, 100px);
318 grid-template-rows: repeat(6, auto);
319 grid-auto-flow: column;
320 grid-column-gap: 10px;
321 padding-left: 0px;
322 padding-right: 0px;
323 margin: 1px;
324 margin-left: 20px;
325 }
326 .module {
327 display: inline-grid;
328 text-align: center;
329 border-width: 0px;
330 border-style: solid;
331 margin: 1px 1px 1px 1px;
332 padding: 0px 1px 0px 1px;
333 min-width: 100px;
334 border-radius: 10px;
335 }
336
337 .module_grid > .on, .service_node > .ok {
338 background-color: #8c8;
339 }
340 .module_grid > .off, .service_node > .off{
341 background-color: #9aa;
342 }
343 .module_grid > .fail, .service_node > .fail {
344 background-color: #a33;
345 }
346 .module_grid > .always, .service_node > .fail {
347 background-color: #282;
348 }
349
Alexbdc72742021-12-23 13:26:05 -0600350 .tooltip { border-bottom: 0px dotted black;}
351 .tooltip .tooltiptext {
352 font-size: 0.9em;
353 width: 200px;
354
355 }
Alexb2129542021-11-23 15:49:42 -0600356 .tooltiptext {
Alexbdc72742021-12-23 13:26:05 -0600357 transform: translate(0px, 2px);
Alexb2129542021-11-23 15:49:42 -0600358 }
359
360 .console {
361 background-color: black;
362 font-family: "Lucida Console", Monaco, monospace;
363 font-size: 0.5em;
364 width: auto;
365 color: #fff;
366 border-radius: 6px;
367 padding: 5px 5px;
368 }
369
370 </style>
371</head>
Alex30380a42021-12-20 16:11:20 -0600372
373{% macro put_osd_prop(prop, b, a, p) %}
374 {% if prop in p %}
375 <div class="item bench">{{ a[prop] | to_mb }} ({{ "%0.4f" | format(p[prop]|float) }})</div>
376 {% else %}
377 <div class="item bench">{{ a[prop] | to_mb }}</div>
378 {% endif %}
379{% endmacro %}
380
381{% macro put_osd_perc(prop, b, a, p) %}
382 {% if prop in p %}
383 <div class="item bench">{{ "%0.4f"|format(a[prop]|float) }} ({{ "%0.4f" | format(p[prop]|float) }})</div>
384 {% else %}
385 <div class="item bench">{{ "%0.4f"|format(a[prop]|float) }}</div>
386 {% endif %}
387{% endmacro %}
388
389{% macro summary_value(prop, s) %}
390 {% if prop in s %}
391 <div class="item bench">{{ s[prop] }} nodes</div>
392 {% else %}
393 <div class="item bench">0</div>
394 {% endif %}
395{% endmacro %}
396
397
398
Alexb2129542021-11-23 15:49:42 -0600399<body onload="init()">
400
401<div class="header">
402 <div class="label">Ceph version:</div>
403 <div class="text">{{ ceph_version }}</div>
404 <div class="label">Image:</div>
405 <div class="text">{{ cluster.image }}</div>
406 <div class="label date">generated on: {{ gen_date }}</div>
407</div>
408
409<div class="bar">
410 <div class="bar-centered">
411 <button class="bar-item" onclick="openBar(event, 'bench')">Benchmark Results</button>
Alex30380a42021-12-20 16:11:20 -0600412 <button class="bar-item" onclick="openBar(event, 'osdstats')">OSD Stats</button>
Alexb2129542021-11-23 15:49:42 -0600413 <button class="bar-item" onclick="openBar(event, 'status')">Status</button>
414 <!-- <button class="bar-item" onclick="openBar(event, 'latency')">Latency</button> -->
415 </div>
416</div>
417
418<!-- Benchmarks -->
419{% macro bench_page(results, id_label) %}
420<div id="{{ id_label }}" class="barcontent">
421 <h5>{{ caller() }}</h5>
Alexbdc72742021-12-23 13:26:05 -0600422 <div class="note">Graphs in detailed section shows value measured by internal Ceph profiler</div>
423 <div class="note">'All agents' value shows theoretical load calculated client-side</div>
Alexb2129542021-11-23 15:49:42 -0600424 <hr>
425 <table class="ceph_status">
426 <tr class="node">
Alexbdc72742021-12-23 13:26:05 -0600427 <td class="bench_id">N</td>
428 <td class="time">Time started</td>
Alexb2129542021-11-23 15:49:42 -0600429 <td class="status">Data point</td>
430 <td class="col_properties">
431 <div class="props_group">
Alexb2129542021-11-23 15:49:42 -0600432 <div class="item prop">Run Time</div>
433 <div class="item prop">Storage class</div>
434 <div class="item pg">PGs</div>
435 <div class="item prop">Engine</div>
436 <div class="item prop">Mode</div>
Alex0989ecf2022-03-29 13:43:21 -0500437 <div class="item prop">BS / IODepth / Size</div>
Alexb2129542021-11-23 15:49:42 -0600438 </div>
439 </td>
440 <td class="col_bench">
441 <div class="bench_run_group">
442 <div class="item bench">Read, MB/s</div>
Alex0989ecf2022-03-29 13:43:21 -0500443 <div class="item bench">Avg/cLat 95p, usec</div>
Alexb2129542021-11-23 15:49:42 -0600444 <div class="item bench">Read, op/s</div>
445 <div class="item bench">Write, MB/s</div>
Alex0989ecf2022-03-29 13:43:21 -0500446 <div class="item bench">Avg/cLat 95p, usec</div>
Alexb2129542021-11-23 15:49:42 -0600447 <div class="item bench">Write, op/s</div>
448 </div>
449 </td>
450 </tr>
451 {% for time,dt in results.items() %}
452 {% set t = dt["totals"] %}
453 {% set o = dt["input_options"] %}
454 {% set tstripped = time | tstrip %}
455 <tr class="node" onclick="toggleClassByID('timing_{{ tstripped }}_data')" id="timing_{{ tstripped }}_button">
Alexbdc72742021-12-23 13:26:05 -0600456 <td class="bench_id">{{ dt["id"] }}</td>
457 <td class="time">{{ time }}</td>
Alexb2129542021-11-23 15:49:42 -0600458 <td class="status">All agents</td>
459 <td class="col_properties">
460 <div class="props_group">
Alex0989ecf2022-03-29 13:43:21 -0500461 <div class="item prop">{{ o["ramp_time"] }}/{{ o["runtime"] }}</div>
Alexb2129542021-11-23 15:49:42 -0600462 <div class="item prop">{{ t["storage_class"] }}</div>
463 <div class="item pg">{{ t["storage_class_stats"]["num_pg"] }}</div>
464 <div class="item prop">{{ o["ioengine"] }}</div>
Alex30380a42021-12-20 16:11:20 -0600465 <div class="item prop">{{ o["readwrite"] }} ({{ o["rwmixread"] }}/{{ 100 - (o["rwmixread"]|int) }})</div>
Alex0989ecf2022-03-29 13:43:21 -0500466 <div class="item prop">{{ o["bs"] }}/{{ o["iodepth"] }}/{{ o["size"] }}</div>
Alexb2129542021-11-23 15:49:42 -0600467 </div>
468 </td>
469 <td class="col_bench">
470 <div class="bench_run_group">
471 <div class="item bench">{{ t["read_bw_bytes"] | to_mb }}</div>
Alex0989ecf2022-03-29 13:43:21 -0500472 <div class="item bench">{{ "%0.2f" | format(t["read_avg_lat_us"]|float) }} / {{ "%0.2f" | format(t["read_95p_clat_us"]|float) }}</div>
Alexb2129542021-11-23 15:49:42 -0600473 <div class="item bench">{{ "%0.2f" | format(t["read_iops"]|float) }}</div>
474 <div class="item bench">{{ t["write_bw_bytes"] | to_mb }}</div>
Alex0989ecf2022-03-29 13:43:21 -0500475 <div class="item bench">{{ "%0.2f" | format(t["write_avg_lat_us"]|float) }} / {{ "%0.2f" | format(t["write_95p_clat_us"]|float) }}</div>
Alexb2129542021-11-23 15:49:42 -0600476 <div class="item bench">{{ "%0.2f" | format(t["write_iops"]|float) }}</div>
477 </div>
478 </td>
479 </tr>
Alex30380a42021-12-20 16:11:20 -0600480 {% set c = dt["ceph"] %}
Alexb2129542021-11-23 15:49:42 -0600481 <tr class="collapsable" id="timing_{{ tstripped }}_data"><td colspan=3>
Alexbdc72742021-12-23 13:26:05 -0600482 <div class="details-wrap">
Alex30380a42021-12-20 16:11:20 -0600483 <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 -0600484 <div class="bc-wrap">
485 <div class="bctimecol">
Alex30380a42021-12-20 16:11:20 -0600486 <div class="bctime"><span class="bctimetext">{{ c["max_rbl"][1] | to_mb }}</span></div>
487 <div class="bctime"><span class="bctimetext">{{ c["max_rbl"][2] | to_mb }}</span></div>
488 <div class="bctime"><span class="bctimetext">{{ c["max_rbl"][3] | to_mb }}</span></div>
489 <div class="bctime"><span class="bctimetext">{{ c["max_rbl"][4] | to_mb }}</span></div>
Alexb2129542021-11-23 15:49:42 -0600490 </div>
491
492 <div class="bc-container">
493 <div class="bc">
Alex30380a42021-12-20 16:11:20 -0600494 {% for sec, c_data in c["stats"].items() %}
495 {% set elapsed = sec | float %}
496 <div class="bccol">
497 {% if sec == c["max_rbl_time"] %}
498 <div class="bcheader">{{ c_data["read_bytes_sec"] | to_mb }}</div>
499 <div class="bcbar green-bar" style="height: {{ c_data["read_bytes_sec_perc"] }};"></div>
500 {% else %}
501 <div class="bcbar" style="height: {{ c_data["read_bytes_sec_perc"] }};"></div>
502 {% endif%}
503 <div class="bcfooter">{{ "%0.1f" | format(elapsed) }}</div>
504 </div>
505 {% endfor %}
Alexb2129542021-11-23 15:49:42 -0600506 </div>
507 </div>
508 </div>
Alex30380a42021-12-20 16:11:20 -0600509 <div class="inlineheader">Global READ stats, IOPS vs seconds. Measured maximum is <b>{{ c["max_ril"][0] }}</b> op/sec</div>
510 <div class="bc-wrap">
511 <div class="bctimecol">
512 <div class="bctime"><span class="bctimetext">{{ c["max_ril"][1] }}</span></div>
513 <div class="bctime"><span class="bctimetext">{{ c["max_ril"][2] }}</span></div>
514 <div class="bctime"><span class="bctimetext">{{ c["max_ril"][3] }}</span></div>
515 <div class="bctime"><span class="bctimetext">{{ c["max_ril"][4] }}</span></div>
516 </div>
517
518 <div class="bc-container">
519 <div class="bc">
520 {% for sec, c_data in c["stats"].items() %}
521 {% set elapsed = sec | float %}
522 <div class="bccol">
523 {% if sec == c["max_ril_time"] %}
524 <div class="bcheader">{{ c_data["read_op_per_sec"] }}</div>
525 <div class="bcbar green-bar" style="height: {{ c_data["read_op_per_sec_perc"] }};"></div>
526 {% else %}
527 <div class="bcbar" style="height: {{ c_data["read_op_per_sec_perc"] }};"></div>
528 {% endif%}
529 <div class="bcfooter">{{ "%0.1f" | format(elapsed) }}</div>
530 </div>
531 {% endfor %}
532 </div>
533 </div>
534 </div>
535 <div class="inlineheader">Global WRITE stats, MB/s vs seconds. Measured maximum is <b>{{ c["max_wbl"][0] | to_mb }}</b> MB/sec</div>
536 <div class="bc-wrap">
537 <div class="bctimecol">
538 <div class="bctime"><span class="bctimetext">{{ c["max_wbl"][1] | to_mb }}</span></div>
539 <div class="bctime"><span class="bctimetext">{{ c["max_wbl"][2] | to_mb }}</span></div>
540 <div class="bctime"><span class="bctimetext">{{ c["max_wbl"][3] | to_mb }}</span></div>
541 <div class="bctime"><span class="bctimetext">{{ c["max_wbl"][4] | to_mb }}</span></div>
542 </div>
543
544 <div class="bc-container">
545 <div class="bc">
546 {% for sec, c_data in c["stats"].items() %}
547 {% set elapsed = sec | float %}
548 <div class="bccol">
549 {% if sec == c["max_wbl_time"] %}
550 <div class="bcheader">{{ c_data["write_bytes_sec"] | to_mb }}</div>
551 <div class="bcbar green-bar" style="height: {{ c_data["write_bytes_sec_perc"] }};"></div>
552 {% else %}
553 <div class="bcbar" style="height: {{ c_data["write_bytes_sec_perc"] }};"></div>
554 {% endif%}
555 <div class="bcfooter">{{ "%0.1f" | format(elapsed) }}</div>
556 </div>
557 {% endfor %}
558 </div>
559 </div>
560 </div>
561
562 <div class="inlineheader">Global WRITE stats, IOPS vs seconds. Measured maximum is <b>{{ c["max_wil"][0] }}</b> op/sec</div>
563 <div class="bc-wrap">
564 <div class="bctimecol">
565 <div class="bctime"><span class="bctimetext">{{ c["max_wil"][1] }}</span></div>
566 <div class="bctime"><span class="bctimetext">{{ c["max_wil"][2] }}</span></div>
567 <div class="bctime"><span class="bctimetext">{{ c["max_wil"][3] }}</span></div>
568 <div class="bctime"><span class="bctimetext">{{ c["max_wil"][4] }}</span></div>
569 </div>
570
571 <div class="bc-container">
572 <div class="bc">
573 {% for sec, c_data in c["stats"].items() %}
574 {% set elapsed = sec | float %}
575 <div class="bccol">
576 {% if sec == c["max_wil_time"] %}
577 <div class="bcheader">{{ c_data["write_op_per_sec"] }}</div>
578 <div class="bcbar green-bar" style="height: {{ c_data["write_op_per_sec_perc"] }};"></div>
579 {% else %}
580 <div class="bcbar" style="height: {{ c_data["write_op_per_sec_perc"] }};"></div>
581 {% endif%}
582 <div class="bcfooter">{{ "%0.1f" | format(elapsed) }}</div>
583 </div>
584 {% endfor %}
585 </div>
586 </div>
587 </div>
588 <div class="inlineheader">Per Agent stats</div>
Alexb2129542021-11-23 15:49:42 -0600589 <table style="table-layout: auto;"><tbody>
590 {% for agent,ag_result in dt["agents"].items() %}
Alex90ac1532021-12-09 11:13:14 -0600591 {% set j = ag_result["jobs"][0] %}
Alex30380a42021-12-20 16:11:20 -0600592 <tr class="agents">
Alexbdc72742021-12-23 13:26:05 -0600593 <td class="time">{{ time }}</td>
Alexb2129542021-11-23 15:49:42 -0600594 <td class="status">{{ agent }}</td>
595 <td class="col_properties">
596 <div class="props_group">
Alex0989ecf2022-03-29 13:43:21 -0500597 <div class="item prop">{{ j["job options"]["ramp_time"] }}/{{ j["job options"]["runtime"] }}</div>
Alexb2129542021-11-23 15:49:42 -0600598 <div class="item prop">{{ t["storage_class"] }}</div>
599 <div class="item pg">{{ t["storage_class_stats"]["num_pg"] }}</div>
600 <div class="item prop">{{ o["ioengine"] }}</div>
Alex30380a42021-12-20 16:11:20 -0600601 <div class="item prop">{{ o["readwrite"] }} ({{ o["rwmixread"] }}/{{ 100 - (o["rwmixread"]|int) }})</div>
Alex0989ecf2022-03-29 13:43:21 -0500602 <div class="item prop">{{ j["job options"]["bs"] }}/{{ o["iodepth"] }}/{{ j["job options"]["size"] }}</div>
Alexb2129542021-11-23 15:49:42 -0600603 </div>
604 </td>
605 <td class="col_bench">
606 <div class="bench_run_group">
607 <div class="item bench">{{ j["read"]["bw_bytes"] | to_mb }}</div>
Alex0989ecf2022-03-29 13:43:21 -0500608 <div class="item bench">{{ "%0.2f" | format(j["read"]["lat_ns"]["mean"]|float / 1000) }} / {{ "%0.2f" | format(j["read"]["clat_ns"]["percentile"]["95.000000"]|float / 1000) }}</div>
Alexb2129542021-11-23 15:49:42 -0600609 <div class="item bench">{{ "%0.2f" | format(j["read"]["iops"]|float) }}</div>
610 <div class="item bench">{{ j["write"]["bw_bytes"] | to_mb }}</div>
Alex0989ecf2022-03-29 13:43:21 -0500611 <div class="item bench">{{ "%0.2f" | format(j["write"]["lat_ns"]["mean"]|float / 1000) }} / {{ "%0.2f" | format(j["write"]["clat_ns"]["percentile"]["95.000000"]|float / 1000) }}</div>
Alexb2129542021-11-23 15:49:42 -0600612 <div class="item bench">{{ "%0.2f" | format(j["write"]["iops"]|float) }}</div>
613 </div>
614 </td>
615 </tr>
616 </tr>
617 {% endfor %}
618 </tbody></table>
Alexbdc72742021-12-23 13:26:05 -0600619 </div>
Alexb2129542021-11-23 15:49:42 -0600620 </td></tr>
621 {% endfor %}
622 </table>
623</div>
624{% endmacro %}
625
Alex30380a42021-12-20 16:11:20 -0600626<!-- OSD stats -->
627{% macro osds_page(results, id_label) %}
628<div id="{{ id_label }}" class="barcontent">
629 <h5>{{ caller() }}</h5>
Alexbdc72742021-12-23 13:26:05 -0600630 <div class="note">Node counts is the number of nodes with parameter changed at the end of the testrun comparing to start of the testrun</div>
631 <div class="note">Hover over column title for description</div>
Alex30380a42021-12-20 16:11:20 -0600632 <hr>
633 <table class="ceph_status">
634 <tr class="node">
Alexbdc72742021-12-23 13:26:05 -0600635 <td class="bench_id">N</td>
636 <td class="time">Time started</td>
Alex30380a42021-12-20 16:11:20 -0600637 <td class="status">Data point</td>
638 <td class="col_properties">
639 <div class="osd_props_group">
Alexbdc72742021-12-23 13:26:05 -0600640 <div class="tooltip">
641 <div class="item prop">Status</div>
642 <div class="tooltiptext">OSD nodes with 'up' status</div>
643 </div>
644 <div class="tooltip">
645 <div class="item prop">Class</div>
646 <div class="tooltiptext">OSD device class: 'hdd', 'ssd', 'nvme', etc</div>
647 </div>
648 <div class="tooltip">
649 <div class="item prop">Weight</div>
650 <div class="tooltiptext">The weight of the OSD in the CRUSH map</div>
651 </div>
652 <div class="tooltip">
653 <div class="item pg">PGs</div>
654 <div class="tooltiptext">The number of placement groups in the OSD</div>
655 </div>
Alex30380a42021-12-20 16:11:20 -0600656 </div>
657 </td>
658 <td class="col_bench">
659 <div class="osd_stats_group">
Alexbdc72742021-12-23 13:26:05 -0600660 <div class="tooltip">
661 <div class="item bench">Total, GB</div>
662 <div class="tooltiptext">The total storage capacity of the OSD</div>
663 </div>
664 <div class="tooltip">
665 <div class="item bench">Avail., GB</div>
666 <div class="tooltiptext">The amount of free space available on the OSD.</div>
667 </div>
668 <div class="tooltip">
669 <div class="item bench">Used, GB</div>
670 <div class="tooltiptext">The OSD capacity used</div>
671 </div>
672 <div class="tooltip">
673 <div class="item bench">Data, GB</div>
674 <div class="tooltiptext">The amount of OSD capacity that is used by user data</div>
675 </div>
676 <div class="tooltip">
677 <div class="item bench">OMAP, GB</div>
678 <div class="tooltiptext">An estimate value of the bluefs storage that is being used to store object map (omap) data (key value pairs stored in rocksdb)</div>
679 </div>
680 <div class="tooltip">
681 <div class="item bench">Meta, GB</div>
682 <div class="tooltiptext">The bluefs space allocated, or the value set in the bluestore_bluefs_min parameter, whichever is larger, for internal metadata which is calculated as the total space allocated in bluefs minus the estimated omap data size</div>
683 </div>
684 <div class="tooltip">
685 <div class="item bench">Utilized, %</div>
686 <div class="tooltiptext">The notional percentage of storage used by the OSD</div>
687 </div>
688 <div class="tooltip">
689 <div class="item bench">Variance, %</div>
690 <div class="tooltiptext">The variation above or below average utilization</div>
691 </div>
Alex30380a42021-12-20 16:11:20 -0600692 </div>
693 </td>
694 </tr>
695 {% for time,dt in results.items() %}
696 {% set b = dt["osd_summary"]["before"] %}
697 {% set a = dt["osd_summary"]["after"] %}
698 {% set s = dt["osd_summary"]["active"] %}
699 {% set tstripped = time | tstrip %}
700 <tr class="node" onclick="toggleClassByID('timing_{{ tstripped }}_osds')" id="timing_{{ tstripped }}_button">
Alexbdc72742021-12-23 13:26:05 -0600701 <td class="bench_id">{{ dt["id"] }}</td>
702 <td class="time">{{ time }}</td>
Alex30380a42021-12-20 16:11:20 -0600703 <td class="status">Active nodes</td>
704 <td class="col_properties">
705 <div class="osd_props_group">
706 <div class="item prop">{{ s["status"] }}</div>
707 <div class="item prop">{{ s["device_class"] }}</div>
708 <div class="item prop">&minus;</div>
709 <div class="item pg">{{ s["pgs"] }}</div>
710 </div>
711 </td>
712 <td class="col_bench">
713 <div class="osd_stats_group">
714 <div class="item bench">{{ a["total_kb"] | to_mb }}</div>
715 {{ summary_value("kb_avail", s) }}
716 {{ summary_value("kb_used", s) }}
717 {{ summary_value("kb_used_data", s) }}
718 {{ summary_value("kb_used_omap", s) }}
719 {{ summary_value("kb_used_meta", s) }}
720 {{ summary_value("utilization", s) }}
721 <div class="item bench">{{ s["var_down"] }}&darr; / {{ s["var_up"] }}&uarr;</div>
722 </div>
723 </td>
724 </tr>
725 <tr class="collapsable" id="timing_{{ tstripped }}_osds"><td colspan=3>
726 <table style="table-layout: auto;"><tbody>
727 {% for osd in dt["osds"].keys() | sort %}
728 {% set n = dt["osds"][osd] %}
729 {% set b = n["before"] %}
730 {% set a = n["after"] %}
731 {% set p = n["percent"] %}
732 <tr class="agents">
Alexbdc72742021-12-23 13:26:05 -0600733 <td class="time">{{ time }}</td>
Alex30380a42021-12-20 16:11:20 -0600734 <td class="status">{{ osd }}</td>
735 <td class="col_properties">
736 <div class="osd_props_group">
737 <div class="item prop">{{ a["status"] }}</div>
738 <div class="item prop">{{ a["device_class"] }}</div>
739 <div class="item prop">{{ "%0.4f" | format(a["crush_weight"]|float) }}</div>
740 <div class="item pg">{{ a["pgs"] }}</div>
741 </div>
742 </td>
743 <td class="col_bench">
744 <div class="osd_stats_group">
745 <div class="item bench">{{ a["kb"] | to_mb }}</div>
746 {{ put_osd_prop("kb_avail", b, a, p) }}
747 {{ put_osd_prop("kb_used", b, a, p) }}
748 {{ put_osd_prop("kb_used_data", b, a, p) }}
749 {{ put_osd_prop("kb_used_omap", b, a, p) }}
750 {{ put_osd_prop("kb_used_meta", b, a, p) }}
751 {{ put_osd_perc("utilization", b, a, p) }}
752 {{ put_osd_perc("var", b, a, p) }}
753 </div>
754 </td>
755 </tr>
756 {% endfor %}
757 </tbody></table>
758 </td></tr>
759 {% endfor %}
760 </table>
761</div>
762{% endmacro %}
763
764
Alexb2129542021-11-23 15:49:42 -0600765<!-- Status page -->
766{% macro status_page(info, id_label) %}
767<div id="{{ id_label }}" class="barcontent">
768 <h5>{{ caller() }}</h5>
769 <hr>
770 <table class="ceph_status">
771 <tr class="node">
772 <td class="status">Cluster status</td>
773 <td class="col_shortmessage">Status summary</td>
774 <td class="col_osd">
775 <div class="osd_group">
776 <div class="item osd">OSDs</div>
777 <div class="item osd">Up</div>
778 <div class="item osd">In</div>
779 <div class="item osd">Remap PGs</div>
780 </div>
781 </td>
782 <td class="col_pgs">
783 <div class="pg_group">
784 <div class="item pg">PGs</div>
785 <div class="item pg">Pools</div>
786 <div class="item pg">Objects</div>
787 <div class="item pg">Data, GB</div>
788 <div class="item pg">Used, GB</div>
789 <div class="item pg">Avail, GB</div>
790 <div class="item pg">Total, GB</div>
791 </div>
792 </td>
793 <td class="col_bench">
794 <div class="bench_group">
795 <div class="item bench">Read, MB/sec</div>
796 <div class="item bench">Write, MB/sec</div>
797 <div class="item bench">Read, op/sec</div>
798 <div class="item bench">Write, op/sec</div>
799 </div>
800 </td>
801 </tr>
802 {% set cs = idle_status %}
803 {% set osdmap = cs | get_osdmap %}
804 <tr class="node" onclick="toggleClassByID('health_data')" id="health_data_button">
805 <td class="status {{ health_detail["status"] | lower }}">{{ health_detail["status"] }}</td>
806 <td class="col_shortmessage">
807 {% for code,dt in health_detail["checks"].items() %}
808 {{ dt["summary"]["message"] }}<br>
809 {% endfor %}
810 </td>
811 <!-- background: linear-gradient(to right, gray 0% 20%, transparent 20% 100%); -->
812 <td class="col_osd">
813 <div class="osd_group">
814 <div class="item osd">{{ osdmap["num_osds"] }}</div>
815 <div class="item osd">{{ osdmap["num_up_osds"] }}</div>
816 <div class="item osd">{{ osdmap["num_in_osds"] }}</div>
817 <div class="item osd">{{ osdmap["num_remapped_pgs"] }}</div>
818 </div>
819 </td>
820 {% set pgmap = cs["pgmap"] %}
821 <td class="col_pgs">
822 <div class="pg_group">
823 <div class="item pg">{{ pgmap["num_pgs"] }}</div>
824 <div class="item pg">{{ pgmap["num_pools"] }}</div>
825 <div class="item pg">{{ pgmap["num_objects"] }}</div>
826 <div class="item pg">{{ pgmap["data_bytes"] | to_gb }}</div>
827 <div class="item pg">{{ pgmap["bytes_used"] | to_gb }}</div>
828 <div class="item pg">{{ pgmap["bytes_avail"] | to_gb }}</div>
829 <div class="item pg">{{ pgmap["bytes_total"] | to_gb }}</div>
830 </div>
831 </td>
832 <td class="col_bench">
833 <div class="bench_group">
834 {% if "read_bytes_sec" in pgmap %}
835 <div class="item bench">{{ pgmap["read_bytes_sec"] | to_mb }}</div>
836 {% else %}
837 <div class="item bench">0</div>
838 {% endif %}
839 {% if "write_bytes_sec" in pgmap %}
840 <div class="item bench">{{ pgmap["write_bytes_sec"] | to_mb }}</div>
841 {% else %}
842 <div class="item bench">0</div>
843 {% endif %}
844 {% if "read_op_per_sec" in pgmap %}
845 <div class="item bench">{{ pgmap["read_op_per_sec"] }}</div>
846 {% else %}
847 <div class="item bench">0</div>
848 {% endif %}
849 {% if "write_op_per_sec" in pgmap %}
850 <div class="item bench">{{ pgmap["write_op_per_sec"] }}</div>
851 {% else %}
852 <div class="item bench">0</div>
853 {% endif %}
854 </div>
855 </td>
856 </tr>
857 <tr class="collapsable in" id="health_data"><td colspan=3>
858 <table><tbody>
859 {% for code,dt in health_detail["checks"].items() %}
860 <tr>
861 <td class="spacer"></td>
862 <td class="status {{ dt["severity"] | lower }}">{{ dt["severity"] }}</td>
863 <td class="checks_code">{{ code }}</td>
864 <td class="col_longmessage">
865 <table><tbody>
866 {% for detail in dt["detail"] %}
867 <tr><td>{{ detail["message"] }}</td></tr>
868 {% endfor %}
869 </tbody></table>
870 </td>
871 </tr>
872 {% endfor %}
873 </tbody></table>
874 </td></tr>
875 </table>
876 <hr>
877 <!-- Services -->
878 {% set sm = idle_status["servicemap"] %}
879 <h5>Services: {{ sm["services"] | count }} running. Last modification: {{ sm["modified"] }}</h5>
880 <table class="ceph_status">
881 <tr class="node">
882 <td class="srv_name">Name</td>
883 <td class="srv_path">Subpath</td>
884 <td class="srv_timestamp">Start time</td>
885 <td class="srv_addr">Address</td>
886 </tr>
887 {% for name, d1 in sm["services"].items() %}
888 {% if "daemons" in d1 %}
889 {% set d2 = d1["daemons"] %}
890 {% for key, d3 in d2.items() %}
891 {% if key.startswith("rgw.store") %}
892 <tr class="node" onclick="toggleClassByID('{{ name }}_service_data')" id="{{ name }}_service_data_button">
893 <td class="srv_name">{{ name }} ({{ d3["gid"] }})</td>
894 <td class="srv_path">daemons:{{ key }}</td>
895 <td class="srv_timestamp">{{ d3["start_stamp"] }}</td>
896 <td class="srv_addr">{{ d3["addr"] }}</td>
897 </tr>
898 <tr class="collapsable in" id="{{ name}}_service_data"><td colspan=4>
899 <table><tbody>
900 <tr><td class="metadata">
901 {% for mname, mvalue in d3["metadata"].items() %}
902 <div class="meta_group">
903 <div class="item meta_name">{{ mname }}</div>
904 <div class="item meta_value">{{ mvalue }}</div>
905 </div>
906 {% endfor %}
907 </td></tr>
908 </tbody></table>
909 </td></tr>
910 {% endif %}
911 {% endfor %}
912 {% endif %}
913 {% endfor %}
914 </table>
915 <hr>
916 <!-- Modules -->
917 {% set mgrmap = idle_status["mgrmap"] %}
918 {% set mods = mgrmap["modules"] %}
919 {% set avail = mgrmap["available_modules"] %}
920 {% if "always_on_modules" in mgrmap %}
921 {% set always_on = mgrmap["always_on_modules"].values() | list %}
922 {% set always_on = always_on[0] %}
923 {% else %}
924 {% set always_on = [] %}
925 {% endif %}
926 <h5>Modules: {{ mods | count}} active. {{ always_on | count }} always on. {{ avail | count }} available.</h5>
927 <div class="modules">
928 <div class="module_grid">
929 {% for mod in avail %}
930 {% if mod["name"] in always_on %}
931 <div class="module always">{{ mod["name"] }}</div>
932 {% elif mod["name"] in mods %}
933 <div class="module on">{{ mod["name"] }}</div>
934 {% elif not mod["can_run"] %}
935 <div class="module fail tooltip">
936 <div class="module fail">{{ mod["name"] }}</div>
937 <pre class="tooltiptext">{{ mod["error_string"] | linebreaks }}</pre>
938 </div>
939 {% else %}
940 <div class="module">{{ mod["name"] }}</div>
941 {% endif %}
942 {% endfor %}
943 </div>
944 </div>
945 <hr>
946</div>
947{% endmacro %}
948
949<!-- ================================= -->
950<!-- Cluster nodes page -->
951{% call bench_page(results, "bench") %}
952 Benchmark results
953{% endcall %}
954
Alex30380a42021-12-20 16:11:20 -0600955{% call osds_page(results, "osdstats") %}
956 OSD nodes stats collected before and after each step
957{% endcall %}
958
Alexb2129542021-11-23 15:49:42 -0600959{% call status_page(info, "status") %}
960 Cluster status
961{% endcall %}
962
963</body>
964</html>