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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 569f89edd8e16a6577ec6e22ca4a889026678d288d9282114b8fdeaedc6be2bf
4
- data.tar.gz: 7ec71935c344ff9113d3b4b9dc70dfaf3430fa30796075391d7d65bc008cb390
3
+ metadata.gz: bc0d1c8641a30fc59950236e1761ac6a0f1c07cdbc73c5192e256c7bfd84a6af
4
+ data.tar.gz: 20d8e78c618c96da12676078fff49bb2bf71014e6c8ace339d1fcdc4cd73e8a4
5
5
  SHA512:
6
- metadata.gz: dcb3c67be45ee1b7dc7516f7ddef1f4f9b6fc1513db927009aac3ef11c504caa6d9b11f3d9a8b28028c7f35f2e6e450cdc0a6b124939d1901679129a758d4499
7
- data.tar.gz: 28b0c19d557485c1abf1e636bebe911e42c8f3706de174021af6e543c0c52c4a6fa0ecdef39518acb58d18d5284147c4b57c950186a8b630e9bd2e69acbc72c9
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
  }
@@ -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 && reqs > 1 && options.collapseResults && !expandedResults) {
223
+ if (!controls && options.collapseResults && !expandedResults) {
224
224
  if (!totalsControl) {
225
225
  toArray(container.querySelectorAll(".profiler-result")).forEach(
226
226
  function(el) {
@@ -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
  }
@@ -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
- rack_file = Rack::File.new(resources_root, 'Cache-Control' => "max-age=#{cache_control_value}")
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
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module Rack
3
3
  class MiniProfiler
4
- ASSET_VERSION = 'c336b1303a50b21f5222bc23262ca7bf'
4
+ ASSET_VERSION = '116e2a6fd81c286e004e2a0afb03baa1'
5
5
  end
6
6
  end
@@ -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
@@ -91,8 +91,6 @@ module Rack
91
91
  end
92
92
 
93
93
  at_exit { t[:should_exit] = true }
94
-
95
- t
96
94
  end
97
95
 
98
96
  def save(page_struct)
@@ -22,7 +22,6 @@ module Rack
22
22
 
23
23
  def []=(name, val)
24
24
  attributes[name] = val
25
- self
26
25
  end
27
26
 
28
27
  def to_json(*a)
@@ -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['PATH_INFO']}"
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
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Rack
4
4
  class MiniProfiler
5
- VERSION = '3.3.0'
6
- SOURCE_CODE_URI = 'https://github.com/MiniProfiler/rack-mini-profiler'
5
+ VERSION = "3.3.1"
6
+ SOURCE_CODE_URI = "https://github.com/MiniProfiler/rack-mini-profiler"
7
7
  end
8
8
  end
@@ -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
- content_security_policy_nonce = @config.content_security_policy_nonce ||
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.to_s}\\}")
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.0
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: 2023-12-07 00:00:00.000000000 Z
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.10
363
+ rubygems_version: 3.5.4
364
364
  signing_key:
365
365
  specification_version: 4
366
366
  summary: Profiles loading speed for rack applications.