|
| 1 | +- content_for :title, "Performance" |
| 2 | + |
| 3 | +.admin-merge-container |
| 4 | + h1 Performance |
| 5 | + |
| 6 | + / Date range form |
| 7 | + form.perf-date-form action=admin_page_load_stats_path method="get" |
| 8 | + .perf-date-fields |
| 9 | + label |
| 10 | + span From |
| 11 | + input type="date" name="from" value="#{@from.iso8601}" |
| 12 | + label |
| 13 | + span To |
| 14 | + input type="date" name="to" value="#{@to.iso8601}" |
| 15 | + button.button.button-secondary type="submit" Apply |
| 16 | + p.perf-date-summary |
| 17 | + strong> #{number_with_delimiter(@total_count)} |
| 18 | + | requests from #{@from.strftime('%b %d, %Y')} to #{@to.strftime('%b %d, %Y')} |
| 19 | + |
| 20 | + / Summary cards |
| 21 | + .perf-summary-cards |
| 22 | + - { false => "Normal", true => "Turbo" }.each do |turbo, label| |
| 23 | + - data = @overall[turbo] |
| 24 | + .perf-card |
| 25 | + .perf-card-header= label |
| 26 | + .perf-card-body |
| 27 | + .perf-stat-row |
| 28 | + .perf-stat |
| 29 | + .stat-value= data[:p95].positive? ? "#{data[:p95].round(1)}ms" : "—" |
| 30 | + .stat-label P95 |
| 31 | + .perf-stat |
| 32 | + .stat-value= data[:p99].positive? ? "#{data[:p99].round(1)}ms" : "—" |
| 33 | + .stat-label P99 |
| 34 | + .perf-stat |
| 35 | + .stat-value= number_with_delimiter(data[:count]) |
| 36 | + .stat-label Requests |
| 37 | + |
| 38 | + / Histograms |
| 39 | + .perf-histograms |
| 40 | + - bins = PageLoadStat::HISTOGRAM_BINS |
| 41 | + - { false => "normal", true => "turbo" }.each do |turbo, key| |
| 42 | + .perf-histogram-col |
| 43 | + h3= turbo ? "Turbo Requests" : "Normal Requests" |
| 44 | + - hist = @overall[turbo][:histogram] |
| 45 | + - chart_data = bins.map { |b| { label: b[:label], count: hist[b[:index]] } } |
| 46 | + div id="perf-histogram-#{key}" data-histogram=chart_data.to_json |
| 47 | + |
| 48 | + / Per-action table |
| 49 | + h2 Per-Action Breakdown |
| 50 | + .merge-log-table |
| 51 | + table |
| 52 | + thead |
| 53 | + tr |
| 54 | + th Controller |
| 55 | + th Action |
| 56 | + th Requests |
| 57 | + th P95 (ms) |
| 58 | + th P99 (ms) |
| 59 | + th StdDev (ms) |
| 60 | + tbody |
| 61 | + - if @per_action.empty? |
| 62 | + tr |
| 63 | + td colspan="6" .empty-state No data for this range. |
| 64 | + - else |
| 65 | + - @per_action.each do |row| |
| 66 | + tr |
| 67 | + td= row[:controller] |
| 68 | + td= row[:action] |
| 69 | + td= number_with_delimiter(row[:request_count].to_i) |
| 70 | + td= row[:p95].to_f.round(1) |
| 71 | + td= row[:p99].to_f.round(1) |
| 72 | + td= row[:stddev] ? row[:stddev].to_f.round(1) : "—" |
| 73 | + |
| 74 | + script[src="https://cdn.jsdelivr.net/npm/vega@5.25.0"] |
| 75 | + script[src="https://cdn.jsdelivr.net/npm/vega-embed@6.22.2"] |
| 76 | + script |
| 77 | + | |
| 78 | + (function() { |
| 79 | + var bins = document.querySelectorAll("[data-histogram]"); |
| 80 | + bins.forEach(function(el) { |
| 81 | + var data = JSON.parse(el.dataset.histogram); |
| 82 | + var spec = { |
| 83 | + "$schema": "https://vega.github.io/schema/vega/v5.json", |
| 84 | + width: Math.max(280, el.parentElement.getBoundingClientRect().width - 40), |
| 85 | + height: 200, |
| 86 | + padding: 10, |
| 87 | + autosize: { type: "fit", contains: "padding" }, |
| 88 | + data: [{ name: "hist", values: data }], |
| 89 | + scales: [ |
| 90 | + { |
| 91 | + name: "x", |
| 92 | + type: "band", |
| 93 | + domain: { data: "hist", field: "label" }, |
| 94 | + range: "width", |
| 95 | + padding: 0.2 |
| 96 | + }, |
| 97 | + { |
| 98 | + name: "y", |
| 99 | + type: "linear", |
| 100 | + domain: { data: "hist", field: "count" }, |
| 101 | + nice: true, |
| 102 | + range: "height" |
| 103 | + } |
| 104 | + ], |
| 105 | + axes: [ |
| 106 | + { orient: "bottom", scale: "x", labelAngle: -30, labelAlign: "right" }, |
| 107 | + { orient: "left", scale: "y" } |
| 108 | + ], |
| 109 | + marks: [ |
| 110 | + { |
| 111 | + type: "rect", |
| 112 | + from: { data: "hist" }, |
| 113 | + encode: { |
| 114 | + enter: { |
| 115 | + x: { scale: "x", field: "label" }, |
| 116 | + width: { scale: "x", band: 1 }, |
| 117 | + y: { scale: "y", field: "count" }, |
| 118 | + y2: { scale: "y", value: 0 }, |
| 119 | + fill: { value: "#4e79a7" }, |
| 120 | + tooltip: { signal: "datum.label + ': ' + datum.count + ' requests'" } |
| 121 | + } |
| 122 | + } |
| 123 | + } |
| 124 | + ] |
| 125 | + }; |
| 126 | + vegaEmbed(el, spec, { actions: false, tooltip: true }); |
| 127 | + }); |
| 128 | + })(); |
0 commit comments