rack-mini-profiler 3.3.0 → 3.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +3 -3
- data/lib/html/includes.css +18 -2
- data/lib/html/includes.js +1 -1
- data/lib/html/includes.scss +31 -1
- data/lib/html/includes.tmpl +9 -2
- data/lib/html/vendor.js +1 -1
- data/lib/mini_profiler/actions.rb +6 -1
- data/lib/mini_profiler/asset_version.rb +1 -1
- data/lib/mini_profiler/config.rb +2 -0
- data/lib/mini_profiler/snapshots_transporter.rb +2 -0
- data/lib/mini_profiler/storage/file_store.rb +0 -2
- data/lib/mini_profiler/timer_struct/base.rb +0 -1
- data/lib/mini_profiler/timer_struct/page.rb +10 -3
- data/lib/mini_profiler/version.rb +2 -2
- data/lib/mini_profiler/views.rb +8 -3
- data/lib/mini_profiler.rb +6 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc0d1c8641a30fc59950236e1761ac6a0f1c07cdbc73c5192e256c7bfd84a6af
|
4
|
+
data.tar.gz: 20d8e78c618c96da12676078fff49bb2bf71014e6c8ace339d1fcdc4cd73e8a4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 534f1a6ea263d6e9aaea85e14d0aa09ac893081ad350530c8122c241f1cb0f3397cd7fdf1ca5a65e96bca92384e0b38a6ebbcec8b9e94a4cafb4565198cbd743
|
7
|
+
data.tar.gz: 9114e796825cbaa2b88b71c5bfb0a2b5aa0ea6453a4bf4364d6666d37b42fbcdf12991b0df95ceffaefca47907b9d5c36932ada2c77b4d4120889b4f093b2c23
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 3.3.1 - 2024-02-15
|
4
|
+
- [FEATURE] Support dynamic `config.content_security_policy_nonce` [#609](https://github.com/MiniProfiler/rack-mini-profiler/pull/609)
|
5
|
+
- [FEATURE] Add flamgraph path to response header: [#601](https://github.com/MiniProfiler/rack-mini-profiler/pull/601)
|
6
|
+
|
3
7
|
## 3.3.0 - 2023-12-07
|
4
8
|
- [FEATURE] Use `?pp=flamegraph?ignore_gc=true` or `config.flamegraph_ignore_gc` to ignore gc in flamegraphs. [#599](https://github.com/MiniProfiler/rack-mini-profiler/pull/599)
|
5
9
|
|
data/README.md
CHANGED
@@ -180,7 +180,7 @@ To generate [flamegraphs](http://samsaffron.com/archive/2013/03/19/flame-graphs-
|
|
180
180
|
|
181
181
|
Then, to view the flamegraph as a direct HTML response from your request, just visit any page in your app with `?pp=flamegraph` appended to the URL, or add the header `X-Rack-Mini-Profiler` to the request with the value `flamegraph`.
|
182
182
|
|
183
|
-
Conversely, if you want your regular response instead (which is specially useful for JSON and/or XHR requests), just append the `?pp=async-flamegraph` parameter to your request/fetch URL; the request will then return as normal, and the flamegraph data will be stored for later *async* viewing, both for this request and for all subsequent requests made by this page (based on the `REFERER` header). For viewing these async flamegraphs, use the 'flamegraph' link that will appear inside the MiniProfiler UI for these requests.
|
183
|
+
Conversely, if you want your regular response instead (which is specially useful for JSON and/or XHR requests), just append the `?pp=async-flamegraph` parameter to your request/fetch URL; the request will then return as normal, and the flamegraph data will be stored for later *async* viewing, both for this request and for all subsequent requests made by this page (based on the `REFERER` header). For viewing these async flamegraphs, use the 'flamegraph' link that will appear inside the MiniProfiler UI for these requests or path returned in the `X-MiniProfiler-Flamegraph-Path` header.
|
184
184
|
|
185
185
|
Note: Mini Profiler will not record SQL timings for a request if it asks for a flamegraph. The rationale behind this is to keep
|
186
186
|
Mini Profiler's methods that are responsible for generating the timings data out of the flamegraph.
|
@@ -448,7 +448,7 @@ snapshots_transport_destination_url | `nil`
|
|
448
448
|
snapshots_transport_auth_key | `nil` | `POST` requests made by the snapshots transporter to the destination URL will have a `Mini-Profiler-Transport-Auth` header with the value of this config. Make sure you use a secure and random key for this config.
|
449
449
|
snapshots_redact_sql_queries | `true` | When this is true, SQL queries will be redacted from sampling snapshots, but the backtrace and duration of each SQL query will be saved with the snapshot to keep debugging performance issues possible.
|
450
450
|
snapshots_transport_gzip_requests | `false` | Make the snapshots transporter gzip the requests it makes to `snapshots_transport_destination_url`.
|
451
|
-
content_security_policy_nonce | Rails: Current nonce<br>Rack: nil | Set the content security policy nonce to use when inserting MiniProfiler's script block.
|
451
|
+
content_security_policy_nonce | Rails: Current nonce<br>Rack: nil | Set the content security policy nonce to use when inserting MiniProfiler's script block. Can be set to a static string, or a Proc which receives `env` and `response_headers` as arguments and returns the nonce.
|
452
452
|
enable_hotwire_turbo_drive_support | `false` | Enable support for Hotwire TurboDrive page transitions.
|
453
453
|
profile_parameter | `'pp'` | The query parameter used to interact with this gem.
|
454
454
|
|
@@ -466,7 +466,7 @@ If you are using Heroku Redis, you may need to add the following to your `config
|
|
466
466
|
|
467
467
|
```ruby
|
468
468
|
if Rails.env.production?
|
469
|
-
Rack::MiniProfiler.config.storage_options = {
|
469
|
+
Rack::MiniProfiler.config.storage_options = {
|
470
470
|
url: ENV["REDIS_URL"],
|
471
471
|
ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE }
|
472
472
|
}
|
data/lib/html/includes.css
CHANGED
@@ -105,7 +105,8 @@
|
|
105
105
|
.profiler-result .profiler-unit {
|
106
106
|
font-family: Consolas, monospace, serif; }
|
107
107
|
.profiler-result .profiler-number {
|
108
|
-
color: #111;
|
108
|
+
color: #111;
|
109
|
+
display: inline-block; }
|
109
110
|
.profiler-result .profiler-info {
|
110
111
|
text-align: right; }
|
111
112
|
.profiler-result .profiler-info .profiler-name {
|
@@ -235,6 +236,19 @@
|
|
235
236
|
.profiler-results {
|
236
237
|
z-index: 2147483643;
|
237
238
|
position: fixed; }
|
239
|
+
.profiler-results.profiler-left .profiler-button {
|
240
|
+
text-align: left; }
|
241
|
+
.profiler-results.profiler-right .profiler-button {
|
242
|
+
text-align: right; }
|
243
|
+
.profiler-results .profiler-button > .profiler-duration-milliseconds {
|
244
|
+
min-width: 70px; }
|
245
|
+
.profiler-results .profiler-button > .profiler-sql-count {
|
246
|
+
min-width: 55px; }
|
247
|
+
.profiler-results .profiler-button > .profiler-name {
|
248
|
+
min-width: 190px;
|
249
|
+
margin-left: 3px; }
|
250
|
+
.profiler-results .profiler-button > .profiler-number {
|
251
|
+
text-align: right; }
|
238
252
|
.profiler-results.profiler-top {
|
239
253
|
top: 0px; }
|
240
254
|
.profiler-results.profiler-top.profiler-left {
|
@@ -285,8 +299,10 @@
|
|
285
299
|
background-color: maroon; }
|
286
300
|
.profiler-results .profiler-button.profiler-button-active .profiler-number,
|
287
301
|
.profiler-results .profiler-button.profiler-button-active .profiler-nuclear,
|
302
|
+
.profiler-results .profiler-button.profiler-button-active .profiler-name,
|
288
303
|
.profiler-results .profiler-controls.profiler-button-active .profiler-number,
|
289
|
-
.profiler-results .profiler-controls.profiler-button-active .profiler-nuclear
|
304
|
+
.profiler-results .profiler-controls.profiler-button-active .profiler-nuclear,
|
305
|
+
.profiler-results .profiler-controls.profiler-button-active .profiler-name {
|
290
306
|
color: #fff;
|
291
307
|
font-weight: bold; }
|
292
308
|
.profiler-results .profiler-button.profiler-button-active .profiler-unit,
|
data/lib/html/includes.js
CHANGED
@@ -220,7 +220,7 @@ var _MiniProfiler = (function() {
|
|
220
220
|
totalSqlCount += parseInt(json.sql_count);
|
221
221
|
reqs++;
|
222
222
|
|
223
|
-
if (!controls &&
|
223
|
+
if (!controls && options.collapseResults && !expandedResults) {
|
224
224
|
if (!totalsControl) {
|
225
225
|
toArray(container.querySelectorAll(".profiler-result")).forEach(
|
226
226
|
function(el) {
|
data/lib/html/includes.scss
CHANGED
@@ -103,6 +103,7 @@ $zindex: 2147483640; // near 32bit max 2147483647
|
|
103
103
|
|
104
104
|
.profiler-number {
|
105
105
|
color: $numberColor;
|
106
|
+
display: inline-block;
|
106
107
|
}
|
107
108
|
|
108
109
|
.profiler-info {
|
@@ -317,6 +318,34 @@ $zindex: 2147483640; // near 32bit max 2147483647
|
|
317
318
|
|
318
319
|
$radius: 10px;
|
319
320
|
|
321
|
+
&.profiler-left {
|
322
|
+
.profiler-button {
|
323
|
+
text-align: left;
|
324
|
+
}
|
325
|
+
}
|
326
|
+
|
327
|
+
&.profiler-right {
|
328
|
+
.profiler-button {
|
329
|
+
text-align: right;
|
330
|
+
}
|
331
|
+
}
|
332
|
+
|
333
|
+
.profiler-button {
|
334
|
+
> .profiler-duration-milliseconds {
|
335
|
+
min-width: 70px;
|
336
|
+
}
|
337
|
+
> .profiler-sql-count {
|
338
|
+
min-width: 55px;
|
339
|
+
}
|
340
|
+
> .profiler-name {
|
341
|
+
min-width: 190px;
|
342
|
+
margin-left: 3px;
|
343
|
+
}
|
344
|
+
> .profiler-number {
|
345
|
+
text-align: right;
|
346
|
+
}
|
347
|
+
}
|
348
|
+
|
320
349
|
&.profiler-top {
|
321
350
|
top: 0px;
|
322
351
|
|
@@ -399,7 +428,8 @@ $zindex: 2147483640; // near 32bit max 2147483647
|
|
399
428
|
background-color: maroon;
|
400
429
|
|
401
430
|
.profiler-number,
|
402
|
-
.profiler-nuclear
|
431
|
+
.profiler-nuclear,
|
432
|
+
.profiler-name {
|
403
433
|
color: #fff;
|
404
434
|
font-weight: bold;
|
405
435
|
}
|
data/lib/html/includes.tmpl
CHANGED
@@ -2,14 +2,21 @@
|
|
2
2
|
<div class="profiler-result">
|
3
3
|
<div class="profiler-button {{? it.has_duplicate_sql_timings}}profiler-warning{{?}}">
|
4
4
|
{{? it.has_duplicate_sql_timings}}<span class="profiler-nuclear">!</span>{{?}}
|
5
|
-
<span class="profiler-number">
|
5
|
+
<span class="profiler-number profiler-duration-milliseconds">
|
6
6
|
{{= MiniProfiler.formatDuration(it.duration_milliseconds)}} <span class="profiler-unit">ms</span>
|
7
7
|
</span>
|
8
8
|
{{? MiniProfiler.showTotalSqlCount()}}
|
9
|
-
<span class="profiler-number">
|
9
|
+
<span class="profiler-number profiler-sql-count">
|
10
10
|
{{= it.sql_count}} <span class="profiler-unit">sql</span>
|
11
11
|
</span>
|
12
12
|
{{?}}
|
13
|
+
<span class="profiler-name">
|
14
|
+
{{? it.name.length >= 30 }}
|
15
|
+
{{= it.name.substring(0,15) + "..." + it.name.slice(-15) }}
|
16
|
+
{{??}}
|
17
|
+
{{= it.name}}
|
18
|
+
{{?}}
|
19
|
+
</span>
|
13
20
|
</div>
|
14
21
|
|
15
22
|
<div class="profiler-popup">
|
data/lib/html/vendor.js
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
MiniProfiler.templates = {};
|
8
8
|
MiniProfiler.templates["profilerTemplate"] = function anonymous(it
|
9
9
|
) {
|
10
|
-
var out=' <div class="profiler-result"> <div class="profiler-button ';if(it.has_duplicate_sql_timings){out+='profiler-warning';}out+='"> ';if(it.has_duplicate_sql_timings){out+='<span class="profiler-nuclear">!</span>';}out+=' <span class="profiler-number"> '+( MiniProfiler.formatDuration(it.duration_milliseconds))+' <span class="profiler-unit">ms</span> </span> ';if(MiniProfiler.showTotalSqlCount()){out+=' <span class="profiler-number"> '+( it.sql_count)+' <span class="profiler-unit">sql</span> </span> ';}out+=' </div> <div class="profiler-popup"> <div class="profiler-info"> <span class="profiler-name"> '+( it.name)+' <span class="profiler-overall-duration">('+( MiniProfiler.formatDuration(it.duration_milliseconds))+' ms)</span> </span> <span class="profiler-server-time">'+( it.machine_name)+' on '+( MiniProfiler.renderDate(it.started_formatted))+'</span> </div> <div class="profiler-output"> <table class="profiler-timings"> <thead> <tr> <th>event</th> <th>duration (ms)</th> <th class="profiler-duration-with-children">with children (ms)</th> <th class="time-from-start">from start (ms)</th> ';if(it.has_sql_timings){out+=' <th colspan="2">query time (ms)</th> ';}out+=' ';var arr1=it.custom_timing_names;if(arr1){var value,i1=-1,l1=arr1.length-1;while(i1<l1){value=arr1[i1+=1];out+=' <th colspan="2">'+( value.toLowerCase() )+' (ms)</th> ';} } out+=' </tr> </thead> <tbody> '+( MiniProfiler.templates.timingTemplate({timing: it.root, page: it}) )+' </tbody> <tfoot> <tr> <td colspan="3"> ';if(!it.client_timings){out+=' '+( MiniProfiler.templates.linksTemplate({timing: it.root, page: it}) )+' ';}out+=' <a class="profiler-toggle-duration-with-children" title="toggles column with aggregate child durations">show time with children</a> <a class="profiler-snapshots-page-link" title="Go to snapshots page" href="'+( MiniProfiler.options.path )+'snapshots">snapshots</a> </td> ';if(it.has_sql_timings){out+=' <td colspan="2" class="profiler-number profiler-percent-in-sql" title="'+( MiniProfiler.getSqlTimingsCount(it.root) )+' queries spent '+( MiniProfiler.formatDuration(it.duration_milliseconds_in_sql) )+' ms of total request time"> '+( MiniProfiler.formatDuration(it.duration_milliseconds_in_sql / it.duration_milliseconds * 100) )+' <span class="profiler-unit">% in sql</span> </td> ';}out+=' ';var arr2=it.custom_timing_names;if(arr2){var value,i2=-1,l2=arr2.length-1;while(i2<l2){value=arr2[i2+=1];out+=' <td colspan="2" class="profiler-number profiler-percentage-in-sql" title="'+( it.custom_timing_stats[value].count )+' '+( value.toLowerCase() )+' invocations spent '+( MiniProfiler.formatDuration(it.custom_timing_stats[value].duration) )+' ms of total request time"> '+( MiniProfiler.formatDuration(it.custom_timing_stats[value].duration / it.duration_milliseconds * 100) )+' <span class="profiler-unit">% in '+( value.toLowerCase() )+'</span> </td> ';} } out+=' </tr> </tfoot> </table> ';if(it.client_timings){out+=' <table class="profiler-timings profiler-client-timings"> <thead> <tr> <th>client event</th> <th>duration (ms)</th> <th>from start (ms)</th> </tr> </thead> <tbody> ';var arr3=MiniProfiler.getClientTimings(it.client_timings);if(arr3){var value,i3=-1,l3=arr3.length-1;while(i3<l3){value=arr3[i3+=1];out+=' <tr class="';if(value.isTrivial){out+='profiler-trivial';}out+='"> <td class="profiler-label">'+( value.name )+'</td> <td class="profiler-duration"> ';if(value.duration >= 0){out+=' <span class="profiler-unit"></span>'+( MiniProfiler.formatDuration(value.duration) )+' ';}out+=' </td> <td class="profiler-duration time-from-start"> <span class="profiler-unit">+</span>'+( MiniProfiler.formatDuration(value.start) )+' </td> </tr> ';} } out+=' </tbody> <tfoot> <td colspan="3"> '+( MiniProfiler.templates.linksTemplate({timing: it.root, page: it}) )+' </td> </tfoot> </table> ';}out+=' ';if(it.custom_fields && Object.keys(it.custom_fields).length > 0){out+=' <p class="custom-fields-title">Snapshot custom fields</p> <table class="profiler-timings"> <tbody> ';var arr4=Object.keys(it.custom_fields);if(arr4){var key,i4=-1,l4=arr4.length-1;while(i4<l4){key=arr4[i4+=1];out+=' <tr> <td class="profiler-label">'+( key )+'</td> <td class="profiler-label">'+( it.custom_fields[key] )+'</td> </tr> ';} } out+=' </tbody> </table> ';}out+=' </div> </div> ';if(it.has_sql_timings){out+=' <div class="profiler-queries"> <table> <thead> <tr> <th class="ta-right">step<br />time from start<br />query type<br />duration</th> <th class="ta-left">call stack<br />query</th> </tr> </thead> <tbody> ';var arr5=MiniProfiler.getSqlTimings(it.root);if(arr5){var value,index=-1,l5=arr5.length-1;while(index<l5){value=arr5[index+=1];out+=' '+( MiniProfiler.templates.sqlGapTemplate({g: value.prevGap}) )+' '+( MiniProfiler.templates.sqlTimingTemplate({i: index, s: value}) )+' ';if(value.nextGap){out+=' '+( MiniProfiler.templates.sqlGapTemplate({g: value.nextGap}) )+' ';}out+=' ';} } out+=' </tbody> </table> <p class="profiler-trivial-gap-container"> <a class="profiler-toggle-trivial-gaps">show trivial gaps</a> </p> </div> ';}out+=' </div>';return out;
|
10
|
+
var out=' <div class="profiler-result"> <div class="profiler-button ';if(it.has_duplicate_sql_timings){out+='profiler-warning';}out+='"> ';if(it.has_duplicate_sql_timings){out+='<span class="profiler-nuclear">!</span>';}out+=' <span class="profiler-number profiler-duration-milliseconds"> '+( MiniProfiler.formatDuration(it.duration_milliseconds))+' <span class="profiler-unit">ms</span> </span> ';if(MiniProfiler.showTotalSqlCount()){out+=' <span class="profiler-number profiler-sql-count"> '+( it.sql_count)+' <span class="profiler-unit">sql</span> </span> ';}out+=' <span class="profiler-name"> ';if(it.name.length >= 30){out+=' '+( it.name.substring(0,15) + "..." + it.name.slice(-15) )+' ';}else{out+=' '+( it.name)+' ';}out+=' </span> </div> <div class="profiler-popup"> <div class="profiler-info"> <span class="profiler-name"> '+( it.name)+' <span class="profiler-overall-duration">('+( MiniProfiler.formatDuration(it.duration_milliseconds))+' ms)</span> </span> <span class="profiler-server-time">'+( it.machine_name)+' on '+( MiniProfiler.renderDate(it.started_formatted))+'</span> </div> <div class="profiler-output"> <table class="profiler-timings"> <thead> <tr> <th>event</th> <th>duration (ms)</th> <th class="profiler-duration-with-children">with children (ms)</th> <th class="time-from-start">from start (ms)</th> ';if(it.has_sql_timings){out+=' <th colspan="2">query time (ms)</th> ';}out+=' ';var arr1=it.custom_timing_names;if(arr1){var value,i1=-1,l1=arr1.length-1;while(i1<l1){value=arr1[i1+=1];out+=' <th colspan="2">'+( value.toLowerCase() )+' (ms)</th> ';} } out+=' </tr> </thead> <tbody> '+( MiniProfiler.templates.timingTemplate({timing: it.root, page: it}) )+' </tbody> <tfoot> <tr> <td colspan="3"> ';if(!it.client_timings){out+=' '+( MiniProfiler.templates.linksTemplate({timing: it.root, page: it}) )+' ';}out+=' <a class="profiler-toggle-duration-with-children" title="toggles column with aggregate child durations">show time with children</a> <a class="profiler-snapshots-page-link" title="Go to snapshots page" href="'+( MiniProfiler.options.path )+'snapshots">snapshots</a> </td> ';if(it.has_sql_timings){out+=' <td colspan="2" class="profiler-number profiler-percent-in-sql" title="'+( MiniProfiler.getSqlTimingsCount(it.root) )+' queries spent '+( MiniProfiler.formatDuration(it.duration_milliseconds_in_sql) )+' ms of total request time"> '+( MiniProfiler.formatDuration(it.duration_milliseconds_in_sql / it.duration_milliseconds * 100) )+' <span class="profiler-unit">% in sql</span> </td> ';}out+=' ';var arr2=it.custom_timing_names;if(arr2){var value,i2=-1,l2=arr2.length-1;while(i2<l2){value=arr2[i2+=1];out+=' <td colspan="2" class="profiler-number profiler-percentage-in-sql" title="'+( it.custom_timing_stats[value].count )+' '+( value.toLowerCase() )+' invocations spent '+( MiniProfiler.formatDuration(it.custom_timing_stats[value].duration) )+' ms of total request time"> '+( MiniProfiler.formatDuration(it.custom_timing_stats[value].duration / it.duration_milliseconds * 100) )+' <span class="profiler-unit">% in '+( value.toLowerCase() )+'</span> </td> ';} } out+=' </tr> </tfoot> </table> ';if(it.client_timings){out+=' <table class="profiler-timings profiler-client-timings"> <thead> <tr> <th>client event</th> <th>duration (ms)</th> <th>from start (ms)</th> </tr> </thead> <tbody> ';var arr3=MiniProfiler.getClientTimings(it.client_timings);if(arr3){var value,i3=-1,l3=arr3.length-1;while(i3<l3){value=arr3[i3+=1];out+=' <tr class="';if(value.isTrivial){out+='profiler-trivial';}out+='"> <td class="profiler-label">'+( value.name )+'</td> <td class="profiler-duration"> ';if(value.duration >= 0){out+=' <span class="profiler-unit"></span>'+( MiniProfiler.formatDuration(value.duration) )+' ';}out+=' </td> <td class="profiler-duration time-from-start"> <span class="profiler-unit">+</span>'+( MiniProfiler.formatDuration(value.start) )+' </td> </tr> ';} } out+=' </tbody> <tfoot> <td colspan="3"> '+( MiniProfiler.templates.linksTemplate({timing: it.root, page: it}) )+' </td> </tfoot> </table> ';}out+=' ';if(it.custom_fields && Object.keys(it.custom_fields).length > 0){out+=' <p class="custom-fields-title">Snapshot custom fields</p> <table class="profiler-timings"> <tbody> ';var arr4=Object.keys(it.custom_fields);if(arr4){var key,i4=-1,l4=arr4.length-1;while(i4<l4){key=arr4[i4+=1];out+=' <tr> <td class="profiler-label">'+( key )+'</td> <td class="profiler-label">'+( it.custom_fields[key] )+'</td> </tr> ';} } out+=' </tbody> </table> ';}out+=' </div> </div> ';if(it.has_sql_timings){out+=' <div class="profiler-queries"> <table> <thead> <tr> <th class="ta-right">step<br />time from start<br />query type<br />duration</th> <th class="ta-left">call stack<br />query</th> </tr> </thead> <tbody> ';var arr5=MiniProfiler.getSqlTimings(it.root);if(arr5){var value,index=-1,l5=arr5.length-1;while(index<l5){value=arr5[index+=1];out+=' '+( MiniProfiler.templates.sqlGapTemplate({g: value.prevGap}) )+' '+( MiniProfiler.templates.sqlTimingTemplate({i: index, s: value}) )+' ';if(value.nextGap){out+=' '+( MiniProfiler.templates.sqlGapTemplate({g: value.nextGap}) )+' ';}out+=' ';} } out+=' </tbody> </table> <p class="profiler-trivial-gap-container"> <a class="profiler-toggle-trivial-gaps">show trivial gaps</a> </p> </div> ';}out+=' </div>';return out;
|
11
11
|
}
|
12
12
|
MiniProfiler.templates["linksTemplate"] = function anonymous(it
|
13
13
|
) {
|
@@ -55,7 +55,12 @@ module Rack
|
|
55
55
|
resources_env = env.dup
|
56
56
|
resources_env['PATH_INFO'] = file_name
|
57
57
|
|
58
|
-
|
58
|
+
if Gem::Version.new(Rack.release) >= Gem::Version.new("2.1.0")
|
59
|
+
rack_file = Rack::Files.new(resources_root, 'Cache-Control' => "max-age=#{cache_control_value}")
|
60
|
+
else
|
61
|
+
rack_file = Rack::File.new(resources_root, 'Cache-Control' => "max-age=#{cache_control_value}")
|
62
|
+
end
|
63
|
+
|
59
64
|
rack_file.call(resources_env)
|
60
65
|
end
|
61
66
|
|
data/lib/mini_profiler/config.rb
CHANGED
@@ -97,7 +97,9 @@ module Rack
|
|
97
97
|
|
98
98
|
# redefined - since the accessor defines it first
|
99
99
|
undef :authorization_mode=
|
100
|
+
# rubocop:disable Lint/DuplicateMethods
|
100
101
|
def authorization_mode=(mode)
|
102
|
+
# rubocop:enable Lint/DuplicateMethods
|
101
103
|
if mode == :whitelist
|
102
104
|
warn "[DEPRECATION] `:whitelist` authorization mode is deprecated. Please use `:allow_authorized` instead."
|
103
105
|
|
@@ -9,9 +9,11 @@ class ::Rack::MiniProfiler::SnapshotsTransporter
|
|
9
9
|
def transported_snapshots_count
|
10
10
|
@@transported_snapshots_count
|
11
11
|
end
|
12
|
+
|
12
13
|
def successful_http_requests_count
|
13
14
|
@@successful_http_requests_count
|
14
15
|
end
|
16
|
+
|
15
17
|
def failed_http_requests_count
|
16
18
|
@@failed_http_requests_count
|
17
19
|
end
|
@@ -59,13 +59,12 @@ module Rack
|
|
59
59
|
|
60
60
|
def initialize(env)
|
61
61
|
timer_id = MiniProfiler.generate_id
|
62
|
-
page_name = env['PATH_INFO']
|
63
62
|
started_at = (Time.now.to_f * 1000).to_i
|
64
63
|
started = (Process.clock_gettime(Process::CLOCK_MONOTONIC) * 1000).to_i
|
65
64
|
machine_name = env['SERVER_NAME']
|
66
65
|
super(
|
67
66
|
id: timer_id,
|
68
|
-
name: page_name,
|
67
|
+
name: page_name(env),
|
69
68
|
started: started,
|
70
69
|
started_at: started_at,
|
71
70
|
machine_name: machine_name,
|
@@ -93,7 +92,7 @@ module Rack
|
|
93
92
|
)
|
94
93
|
self[:request_method] = env['REQUEST_METHOD']
|
95
94
|
self[:request_path] = env['PATH_INFO']
|
96
|
-
name = "#{env['REQUEST_METHOD']} http://#{env['SERVER_NAME']}:#{env['SERVER_PORT']}#{env['SCRIPT_NAME']}#{env
|
95
|
+
name = "#{env['REQUEST_METHOD']} http://#{env['SERVER_NAME']}:#{env['SERVER_PORT']}#{env['SCRIPT_NAME']}#{page_name(env)}"
|
97
96
|
self[:root] = TimerStruct::Request.createRoot(name, self)
|
98
97
|
end
|
99
98
|
|
@@ -101,6 +100,14 @@ module Rack
|
|
101
100
|
@attributes[:name]
|
102
101
|
end
|
103
102
|
|
103
|
+
def page_name(env)
|
104
|
+
if env['QUERY_STRING'] && env['QUERY_STRING'] != ""
|
105
|
+
env['PATH_INFO'] + "?" + env['QUERY_STRING']
|
106
|
+
else
|
107
|
+
env['PATH_INFO']
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
104
111
|
def duration_ms
|
105
112
|
@attributes[:root][:duration_milliseconds]
|
106
113
|
end
|
data/lib/mini_profiler/views.rb
CHANGED
@@ -28,7 +28,7 @@ module Rack
|
|
28
28
|
# Use it when:
|
29
29
|
# * you have disabled auto append behaviour throught :auto_inject => false flag
|
30
30
|
# * you do not want script to be automatically appended for the current page. You can also call cancel_auto_inject
|
31
|
-
def get_profile_script(env)
|
31
|
+
def get_profile_script(env, response_headers = {})
|
32
32
|
path = public_base_path(env)
|
33
33
|
version = MiniProfiler::ASSET_VERSION
|
34
34
|
if @config.assets_url
|
@@ -39,7 +39,12 @@ module Rack
|
|
39
39
|
url = "#{path}includes.js?v=#{version}" if !url
|
40
40
|
css_url = "#{path}includes.css?v=#{version}" if !css_url
|
41
41
|
|
42
|
-
|
42
|
+
configured_nonce = @config.content_security_policy_nonce
|
43
|
+
if configured_nonce && !configured_nonce.is_a?(String)
|
44
|
+
configured_nonce = configured_nonce.call(env, response_headers)
|
45
|
+
end
|
46
|
+
|
47
|
+
content_security_policy_nonce = configured_nonce ||
|
43
48
|
env["action_dispatch.content_security_policy_nonce"] ||
|
44
49
|
env["secure_headers_content_security_policy_nonce"]
|
45
50
|
|
@@ -77,7 +82,7 @@ module Rack
|
|
77
82
|
script = ::File.read(::File.expand_path('../html/profile_handler.js', ::File.dirname(__FILE__)))
|
78
83
|
# replace the variables
|
79
84
|
settings.each do |k, v|
|
80
|
-
regex = Regexp.new("\\{#{k
|
85
|
+
regex = Regexp.new("\\{#{k}\\}")
|
81
86
|
script.gsub!(regex, v.to_s)
|
82
87
|
end
|
83
88
|
|
data/lib/mini_profiler.rb
CHANGED
@@ -436,11 +436,12 @@ module Rack
|
|
436
436
|
# inject header
|
437
437
|
if headers.is_a? Hash
|
438
438
|
headers['X-MiniProfiler-Ids'] = ids_comma_separated(env)
|
439
|
+
headers['X-MiniProfiler-Flamegraph-Path'] = flamegraph_path(env) if current.page_struct[:has_flamegraph]
|
439
440
|
end
|
440
441
|
|
441
442
|
if current.inject_js && content_type =~ /text\/html/
|
442
443
|
response = Rack::Response.new([], status, headers)
|
443
|
-
script = self.get_profile_script(env)
|
444
|
+
script = self.get_profile_script(env, headers)
|
444
445
|
|
445
446
|
if String === body
|
446
447
|
response.write inject(body, script)
|
@@ -605,6 +606,10 @@ module Rack
|
|
605
606
|
ids(env).join(",")
|
606
607
|
end
|
607
608
|
|
609
|
+
def flamegraph_path(env)
|
610
|
+
@config.base_url_path + 'flamegraph?id=' + current.page_struct[:id]
|
611
|
+
end
|
612
|
+
|
608
613
|
# cancels automatic injection of profile script for the current page
|
609
614
|
def cancel_auto_inject(env)
|
610
615
|
current.inject_js = false
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-mini-profiler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.3.
|
4
|
+
version: 3.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Saffron
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2024-02-14 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rack
|
@@ -360,7 +360,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
360
360
|
- !ruby/object:Gem::Version
|
361
361
|
version: '0'
|
362
362
|
requirements: []
|
363
|
-
rubygems_version: 3.4
|
363
|
+
rubygems_version: 3.5.4
|
364
364
|
signing_key:
|
365
365
|
specification_version: 4
|
366
366
|
summary: Profiles loading speed for rack applications.
|