rack-mini-profiler 1.0.2 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +138 -21
  3. data/README.md +201 -94
  4. data/lib/enable_rails_patches.rb +5 -0
  5. data/lib/generators/rack_mini_profiler/USAGE +9 -0
  6. data/lib/generators/rack_mini_profiler/install_generator.rb +13 -0
  7. data/lib/generators/{rack_profiler/templates/rack_profiler.rb → rack_mini_profiler/templates/rack_mini_profiler.rb} +1 -1
  8. data/lib/generators/rack_profiler/install_generator.rb +6 -3
  9. data/lib/html/dot.1.1.2.min.js +2 -0
  10. data/lib/html/includes.css +144 -45
  11. data/lib/html/includes.js +1423 -1009
  12. data/lib/html/includes.scss +538 -441
  13. data/lib/html/includes.tmpl +231 -148
  14. data/lib/html/pretty-print.js +810 -0
  15. data/lib/html/profile_handler.js +1 -1
  16. data/lib/html/rack-mini-profiler.css +3 -0
  17. data/lib/html/rack-mini-profiler.js +2 -0
  18. data/lib/html/share.html +0 -1
  19. data/lib/html/speedscope/LICENSE +21 -0
  20. data/lib/html/speedscope/README.md +3 -0
  21. data/lib/html/speedscope/demangle-cpp.1768f4cc.js +4 -0
  22. data/lib/html/speedscope/favicon-16x16.f74b3187.png +0 -0
  23. data/lib/html/speedscope/favicon-32x32.bc503437.png +0 -0
  24. data/lib/html/speedscope/file-format-schema.json +324 -0
  25. data/lib/html/speedscope/fonts/source-code-pro-regular.css +8 -0
  26. data/lib/html/speedscope/fonts/source-code-pro-v13-regular.woff +0 -0
  27. data/lib/html/speedscope/fonts/source-code-pro-v13-regular.woff2 +0 -0
  28. data/lib/html/speedscope/import.cf0fa83f.js +115 -0
  29. data/lib/html/speedscope/index.html +2 -0
  30. data/lib/html/speedscope/release.txt +3 -0
  31. data/lib/html/speedscope/reset.8c46b7a1.css +2 -0
  32. data/lib/html/speedscope/source-map.438fa06b.js +24 -0
  33. data/lib/html/speedscope/speedscope.44364064.js +200 -0
  34. data/lib/html/vendor.js +848 -0
  35. data/lib/mini_profiler/asset_version.rb +3 -2
  36. data/lib/mini_profiler/client_settings.rb +15 -7
  37. data/lib/mini_profiler/config.rb +51 -5
  38. data/lib/mini_profiler/gc_profiler.rb +1 -1
  39. data/lib/mini_profiler/profiling_methods.rb +13 -8
  40. data/lib/mini_profiler/snapshots_transporter.rb +109 -0
  41. data/lib/mini_profiler/storage/abstract_store.rb +52 -1
  42. data/lib/mini_profiler/storage/file_store.rb +7 -3
  43. data/lib/mini_profiler/storage/memcache_store.rb +13 -7
  44. data/lib/mini_profiler/storage/memory_store.rb +98 -5
  45. data/lib/mini_profiler/storage/redis_store.rb +226 -3
  46. data/lib/mini_profiler/storage.rb +7 -0
  47. data/lib/mini_profiler/timer_struct/base.rb +2 -0
  48. data/lib/mini_profiler/timer_struct/custom.rb +1 -0
  49. data/lib/mini_profiler/timer_struct/page.rb +60 -4
  50. data/lib/mini_profiler/timer_struct/request.rb +53 -11
  51. data/lib/mini_profiler/timer_struct/sql.rb +6 -2
  52. data/lib/mini_profiler/timer_struct.rb +8 -0
  53. data/lib/mini_profiler/version.rb +2 -1
  54. data/lib/{mini_profiler/profiler.rb → mini_profiler.rb} +394 -82
  55. data/lib/mini_profiler_rails/railtie.rb +88 -7
  56. data/lib/mini_profiler_rails/railtie_methods.rb +61 -0
  57. data/lib/patches/db/activerecord.rb +1 -12
  58. data/lib/patches/db/mongo.rb +1 -1
  59. data/lib/patches/db/moped.rb +1 -1
  60. data/lib/patches/db/mysql2/alias_method.rb +30 -0
  61. data/lib/patches/db/mysql2/prepend.rb +34 -0
  62. data/lib/patches/db/mysql2.rb +4 -27
  63. data/lib/patches/db/plucky.rb +4 -4
  64. data/lib/patches/db/riak.rb +1 -1
  65. data/lib/patches/net_patches.rb +21 -10
  66. data/lib/patches/sql_patches.rb +13 -5
  67. data/lib/prepend_mysql2_patch.rb +5 -0
  68. data/lib/prepend_net_http_patch.rb +5 -0
  69. data/lib/rack-mini-profiler.rb +1 -24
  70. data/rack-mini-profiler.gemspec +17 -8
  71. metadata +156 -32
  72. data/lib/html/jquery.1.7.1.js +0 -4
  73. data/lib/html/jquery.tmpl.js +0 -486
  74. data/lib/html/list.css +0 -9
  75. data/lib/html/list.js +0 -38
  76. data/lib/html/list.tmpl +0 -34
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # rack-mini-profiler
2
2
 
3
- [![Code Climate](https://codeclimate.com/github/MiniProfiler/rack-mini-profiler/badges/gpa.svg)](https://codeclimate.com/github/MiniProfiler/rack-mini-profiler) [![Build Status](https://travis-ci.org/MiniProfiler/rack-mini-profiler.svg)](https://travis-ci.org/MiniProfiler/rack-mini-profiler)
3
+ Middleware that displays speed badge for every HTML page, along with (optional) flamegraphs and memory profiling. Designed to work both in production and in development.
4
4
 
5
- Middleware that displays speed badge for every html page. Designed to work both in production and in development.
5
+ ![Screenshot 2023-04-05 at 3 13 52 PM](https://user-images.githubusercontent.com/845662/229996538-0f2d9c48-23d9-4d53-a1de-8b4c84c87fbd.png)
6
6
 
7
7
  #### Features
8
8
 
@@ -19,18 +19,17 @@ Middleware that displays speed badge for every html page. Designed to work both
19
19
 
20
20
  ## rack-mini-profiler needs your help
21
21
 
22
- We have decided to restructure our repository so there is a central UI repo and the various language implementation have their own.
22
+ We have decided to restructure our repository so there is a central UI repo and the various language implementations have their own.
23
23
 
24
24
  **WE NEED HELP.**
25
25
 
26
- - Setting up a build that reuses https://github.com/MiniProfiler/ui
27
- - Migrating the internal data structures [per the spec](https://github.com/MiniProfiler/ui)
26
+ - Help [triage issues](https://www.codetriage.com/miniprofiler/rack-mini-profiler) [![Open Source Helpers](https://www.codetriage.com/miniprofiler/rack-mini-profiler/badges/users.svg)](https://www.codetriage.com/miniprofiler/rack-mini-profiler)
28
27
 
29
28
  If you feel like taking on any of this start an issue and update us on your progress.
30
29
 
31
30
  ## Installation
32
31
 
33
- Install/add to Gemfile in Ruby 2.3+
32
+ Install/add to Gemfile in Ruby 2.6+
34
33
 
35
34
  ```ruby
36
35
  gem 'rack-mini-profiler'
@@ -44,7 +43,6 @@ You can also include optional libraries to enable additional features.
44
43
  gem 'memory_profiler'
45
44
 
46
45
  # For call-stack profiling flamegraphs
47
- gem 'flamegraph'
48
46
  gem 'stackprof'
49
47
  ```
50
48
 
@@ -52,9 +50,49 @@ gem 'stackprof'
52
50
 
53
51
  All you have to do is to include the Gem and you're good to go in development. See notes below for use in production.
54
52
 
53
+ #### Upgrading to version 2.0.0
54
+
55
+ Prior to version 2.0.0, Mini Profiler patched various Rails methods to get the information it needed such as template rendering time. Starting from version 2.0.0, Mini Profiler doesn't patch any Rails methods by default and relies on `ActiveSupport::Notifications` to get the information it needs from Rails. If you want Mini Profiler to keep using its patches in version 2.0.0 and later, change the gem line in your `Gemfile` to the following:
56
+
57
+ If you want to manually require Mini Profiler:
58
+ ```ruby
59
+ gem 'rack-mini-profiler', require: ['enable_rails_patches']
60
+ ```
61
+
62
+ If you don't want to manually require Mini Profiler:
63
+ ```ruby
64
+ gem 'rack-mini-profiler', require: ['enable_rails_patches', 'rack-mini-profiler']
65
+ ```
66
+
67
+ #### `Net::HTTP` stack level too deep errors
68
+
69
+ If you start seeing `SystemStackError: stack level too deep` errors from `Net::HTTP` after installing Mini Profiler, this means there is another patch for `Net::HTTP#request` that conflicts with Mini Profiler's patch in your application. To fix this, change `rack-mini-profiler` gem line in your `Gemfile` to the following:
70
+
71
+ ```ruby
72
+ gem 'rack-mini-profiler', require: ['prepend_net_http_patch', 'rack-mini-profiler']
73
+ ```
74
+
75
+ If you currently have `require: false`, remove the `'rack-mini-profiler'` string from the `require` array above so the gem line becomes like this:
76
+
77
+ ```ruby
78
+ gem 'rack-mini-profiler', require: ['prepend_net_http_patch']
79
+ ```
80
+
81
+ This conflict happens when a ruby method is patched twice, once using module prepend, and once using method aliasing. See this [ruby issue](https://bugs.ruby-lang.org/issues/11120) for details. The fix is to apply all patches the same way. Mini Profiler by default will apply its patch using method aliasing, but you can change that to module prepend by adding `require: ['prepend_net_http_patch']` to the gem line as shown above.
82
+
83
+ #### `peek-mysql2` stack level too deep errors
84
+
85
+ If you use peek-mysql2 with Rails >= 5, you'll need to use this gem spec in your Gemfile:
86
+
87
+ ```ruby
88
+ gem 'rack-mini-profiler', require: ['prepend_mysql2_patch', 'rack-mini-profiler']
89
+ ```
90
+
91
+ This should not be necessary with Rails < 5 because peek-mysql2 hooks into mysql2 gem in different ways depending on your Rails version.
92
+
55
93
  #### Rails and manual initialization
56
94
 
57
- In case you need to make sure rack_mini_profiler initialized is after all other gems, or you want to execute some code before rack_mini_profiler required:
95
+ In case you need to make sure rack_mini_profiler is initialized after all other gems, or you want to execute some code before rack_mini_profiler required:
58
96
 
59
97
  ```ruby
60
98
  gem 'rack-mini-profiler', require: false
@@ -65,7 +103,7 @@ be loaded outright, and an attempt to re-initialize it manually will raise an ex
65
103
  Then run the generator which will set up rack-mini-profiler in development:
66
104
 
67
105
  ```bash
68
- bundle exec rails g rack_profiler:install
106
+ bundle exec rails g rack_mini_profiler:install
69
107
  ```
70
108
 
71
109
  #### Rack Builder
@@ -128,12 +166,24 @@ export RACK_MINI_PROFILER_PATCH="false"
128
166
  # initializers/rack_profiler.rb: SqlPatches.patch %w(mongo)
129
167
  ```
130
168
 
169
+ #### Patching Net::HTTP
170
+
171
+ Other than databases, `rack-mini-profiler` applies a patch to `Net::HTTP`. You may want to disable this patch:
172
+
173
+ ```bash
174
+ export RACK_MINI_PROFILER_PATCH_NET_HTTP="false"
175
+ ```
176
+
131
177
  ### Flamegraphs
132
178
 
133
- To generate [flamegraphs](http://samsaffron.com/archive/2013/03/19/flame-graphs-in-ruby-miniprofiler):
179
+ To generate [flamegraphs](http://samsaffron.com/archive/2013/03/19/flame-graphs-in-ruby-miniprofiler), add the [**stackprof**](https://rubygems.org/gems/stackprof) gem to your Gemfile.
180
+
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.
134
182
 
135
- * add the [**flamegraph**](https://github.com/SamSaffron/flamegraph) gem to your Gemfile
136
- * visit a page in your app with `?pp=flamegraph`
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.
184
+
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
+ Mini Profiler's methods that are responsible for generating the timings data out of the flamegraph.
137
187
 
138
188
  ### Memory Profiling
139
189
 
@@ -157,6 +207,30 @@ There are two additional `pp` options that can be used to analyze memory which d
157
207
  * Use `?pp=profile-gc` to report on Garbage Collection statistics
158
208
  * Use `?pp=analyze-memory` to report on ObjectSpace statistics
159
209
 
210
+ ### Snapshots Sampling
211
+
212
+ In a complex web application, it's possible for a request to trigger rare conditions that result in poor performance. Mini Profiler ships with a feature to help detect those rare conditions and fix them. It works by enabling invisible profiling on one request every N requests, and saving the performance metrics that are collected during the request (a.k.a snapshot of the request) so that they can be viewed later. To turn this feature on, set the `snapshot_every_n_requests` config to a value larger than 0. The larger the value is, the less frequently requests are profiled.
213
+
214
+ Mini Profiler will exclude requests that are made to skipped paths (see `skip_paths` config below) from being sampled. Additionally, if profiling is enabled for a request that later finishes with a non-2xx status code, Mini Profiler will discard the snapshot and not save it (this behavior may change in the future).
215
+
216
+ After enabling snapshots sampling, you can see the snapshots that have been collected at `/mini-profiler-resources/snapshots` (or if you changed the `base_url_path` config, substitute `mini-profiler-resources` with your value of the config). You'll see on that page a table where each row represents a group of snapshots with the duration of the worst snapshot in that group. The worst snapshot in a group is defined as the snapshot whose request took longer than all of the snapshots in the same group. Snapshots grouped by HTTP method and path of the request, and if your application is a Rails app, Mini Profiler will try to convert the path to `controller#action` and group by that instead of request path. Clicking on a group will display the snapshots of that group sorted from worst to best. From there, you can click on a snapshot's ID to see the snapshot with all the performance metrics that were collected.
217
+
218
+ Access to the snapshots page is restricted to only those who can see the speed badge on their own requests, see the section below this one about access control.
219
+
220
+ Mini Profiler will keep a maximum of 50 snapshot groups and a maximum of 15 snapshots per group making the default maximum number of snapshots in the system 750. The default group and per group limits can be changed via the `max_snapshot_groups` and `max_snapshots_per_group` configuration options, see the configurations table below.
221
+
222
+ #### Snapshots Transporter
223
+
224
+ Mini Profiler can be configured so that it sends snapshots over HTTP using the snapshots transporter. The main use-case of the transporter is to allow the aggregation of snapshots from multiple applications/sources in a single place. To enable the snapshots transporter, you need to provide a destination URL to the `snapshots_transport_destination_url` config, and a secure key to the `snapshots_transport_auth_key` config (will be used for authorization). Both of these configs are required for the transporter to be enabled.
225
+
226
+ The transporter uses a buffer to temporarily hold snapshots in memory with a limit of 100 snapshots. Every 30 seconds, *if* the buffer is not empty, the transporter will make a `POST` request with the buffer content to the destination URL. Requests made by the transporter will have a `Mini-Profiler-Transport-Auth` header with the value of the `snapshots_transport_auth_key` config. The destination should only accept requests that include this header AND the header's value matches the key you set to the `snapshots_transport_auth_key` config.
227
+
228
+ If the specified destination responds with a non-200 status code, the transporter will increase the interval between requests by `2^n` seconds where `n` is the number of failed requests since the last successful request. The base interval between requests is 30 seconds. So if a request fails, the next request will be `30 + 2^1 = 32` seconds later. If the next request fails too, the next one will be `30 + 2^2 = 34` seconds later and so on until a request succeeds at which point the interval will return to 30 seconds. The interval will not go beyond 1 hour.
229
+
230
+ Requests made by the transporter can be optionally gzip-compressed by setting the `snapshots_transport_gzip_requests` config to true. The body of the requests (after decompression, if you opt for compression) is a JSON string with a single top-level key called `snapshots` and it has an array of snapshots. The structure of a snapshot is too complex to be explained here, but it has the same structure that Mini Profiler client expects. So if your use-case is to simply be able to view snapshots from multiple sources in one place, you should simply store the snapshots as-is, and then serve them to Mini Profiler client to consume. If the destination application also has Mini Profiler, you can simply use the API of the storage backends to store the incoming snapshots and Mini Profiler will treat them the same as local snapshots (e.g. they'll be grouped and displayed in the same manner described in the previous section).
231
+
232
+ Mini Profiler offers an API to add extra fields (a.k.a custom fields) to snapshots. For example, you may want to add whether the request was made by a logged-in or anonymous user, the version of your application or any other things that are specific to your application. To add custom fields to a snapshot, call the `Rack::MiniProfiler.add_snapshot_custom_field(<key>, <value>)` method anywhere during the lifetime of a request, and the snapshot of that request will include the fields you added. If you have a Rails app, you can call that method in an `after_action` callback. Custom fields are cleared between requests.
233
+
160
234
  ## Access control in non-development environments
161
235
 
162
236
  rack-mini-profiler is designed with production profiling in mind. To enable that run `Rack::MiniProfiler.authorize_request` once you know a request is allowed to profile.
@@ -175,18 +249,25 @@ rack-mini-profiler is designed with production profiling in mind. To enable that
175
249
 
176
250
  Note:
177
251
 
178
- Out-of-the-box we will initialize the `authorization_mode` to `:whitelist` in production. However, in some cases we may not be able to do it:
252
+ Out-of-the-box we will initialize the `authorization_mode` to `:allow_authorized` in production. However, in some cases we may not be able to do it:
179
253
 
180
- - If you are running in development or test we will not enable whitelist mode
254
+ - If you are running in development or test we will not enable the explicit authorization mode
181
255
  - If you use `require: false` on rack_mini_profiler we are unlikely to be able to run the railtie
182
256
  - If you are running outside of rails we will not run the railtie
183
257
 
184
258
  In those cases use:
185
259
 
186
260
  ```ruby
187
- Rack::MiniProfiler.config.authorization_mode = :whitelist
261
+ Rack::MiniProfiler.config.authorization_mode = :allow_authorized
188
262
  ```
189
263
 
264
+ When deciding to fully profile a page mini profiler consults with the `authorization_mode`
265
+
266
+ By default in production we attempt to set the authorization mode to `:allow_authorized` meaning that end user will only be able to see requests where somewhere `Rack::MiniProfiler.authorize_request` is invoked.
267
+
268
+ In development we run in the `:allow_all` authorization mode meaning every request is profiled and displayed to the end user.
269
+
270
+
190
271
  ## Configuration
191
272
 
192
273
  Various aspects of rack-mini-profiler's behavior can be configured when your app boots.
@@ -221,8 +302,7 @@ Rack::MiniProfiler.config.storage = Rack::MiniProfiler::MemoryStore
221
302
 
222
303
  # set RedisStore
223
304
  if Rails.env.production?
224
- uri = URI.parse(ENV["REDIS_SERVER_URL"])
225
- Rack::MiniProfiler.config.storage_options = { :host => uri.host, :port => uri.port, :password => uri.password }
305
+ Rack::MiniProfiler.config.storage_options = { url: ENV["REDIS_SERVER_URL"] }
226
306
  Rack::MiniProfiler.config.storage = Rack::MiniProfiler::RedisStore
227
307
  end
228
308
  ```
@@ -277,19 +357,53 @@ Single page applications built using Ember, Angular or other frameworks need som
277
357
  On route transition always call:
278
358
 
279
359
  ```
280
- window.MiniProfiler.pageTransition();
360
+ if (window.MiniProfiler !== undefined) {
361
+ window.MiniProfiler.pageTransition();
362
+ }
281
363
  ```
282
364
 
283
365
  This method will remove profiling information that was related to previous page and clear aggregate statistics.
284
366
 
285
367
  #### MiniProfiler's speed badge on pages that are not generated via Rails
286
- You need to inject the following in your SPA to load MiniProfiler's speed badge ([extra details surrounding this script](https://github.com/MiniProfiler/rack-mini-profiler/issues/139#issuecomment-192880706)):
368
+ You need to inject the following in your SPA to load MiniProfiler's speed badge ([extra details surrounding this script](https://github.com/MiniProfiler/rack-mini-profiler/issues/139#issuecomment-192880706) and [credit for the script tag](https://github.com/MiniProfiler/rack-mini-profiler/issues/479#issue-782488320) to [@ivanyv](https://github.com/ivanyv)):
287
369
 
288
370
  ```html
289
- <script async type="text/javascript" id="mini-profiler" src="/mini-profiler-resources/includes.js?v=12b4b45a3c42e6e15503d7a03810ff33" data-version="12b4b45a3c42e6e15503d7a03810ff33" data-path="/mini-profiler-resources/" data-current-id="redo66j4g1077kto8uh3" data-ids="redo66j4g1077kto8uh3" data-horizontal-position="left" data-vertical-position="top" data-trivial="false" data-children="false" data-max-traces="10" data-controls="false" data-authorized="true" data-toggle-shortcut="Alt+P" data-start-hidden="false" data-collapse-results="true"></script>
371
+ <script type="text/javascript" id="mini-profiler"
372
+ src="/mini-profiler-resources/includes.js?v=12b4b45a3c42e6e15503d7a03810ff33"
373
+ data-css-url="/mini-profiler-resources/includes.css?v=12b4b45a3c42e6e15503d7a03810ff33"
374
+ data-version="12b4b45a3c42e6e15503d7a03810ff33"
375
+ data-path="/mini-profiler-resources/"
376
+ data-horizontal-position="left"
377
+ data-vertical-position="top"
378
+ data-ids=""
379
+ data-trivial="false"
380
+ data-children="false"
381
+ data-max-traces="20"
382
+ data-controls="false"
383
+ data-total-sql-count="false"
384
+ data-authorized="true"
385
+ data-toggle-shortcut="alt+p"
386
+ data-start-hidden="false"
387
+ data-collapse-results="true"
388
+ data-html-container="body"
389
+ data-hidden-custom-fields></script>
290
390
  ```
291
391
 
292
- _Note:_ The GUID (`data-version` and the `?v=` parameter on the `src`) will change with each release of `rack_mini_profiler`. The MiniProfiler's speed badge will continue to work, although you will have to change the GUID to expire the script to fetch the most recent version.
392
+ See an [example of how to do this in a React useEffect](https://gist.github.com/katelovescode/01cfc2b962c165193b160fd10af6c4d5).
393
+
394
+ _Note:_ The GUID (`data-version` and the `?v=` parameter on the `src` and `data-css-url`) will change with each release of `rack_mini_profiler`. The MiniProfiler's speed badge will continue to work, although you will have to change the GUID to expire the script to fetch the most recent version.
395
+
396
+ #### Using MiniProfiler's built in route for apps without HTML responses
397
+ MiniProfiler also ships with a `/rack-mini-profiler/requests` route that displays the speed badge on a blank HTML page. This can be useful when profiling an application that does not render HTML.
398
+
399
+ #### Register MiniProfiler's assets in the Rails assets pipeline
400
+ MiniProfiler can be configured so it registers its assets in the assets pipeline. To do that, you'll need to provide a lambda (or proc) to the `assets_url` config (see the below section). The callback will receive 3 arguments which are: `name` represents asset name (currently it's either `rack-mini-profiling.js` or `rack-mini-profiling.css`), `assets_version` is a 32 characters long hash of MiniProfiler's assets, and `env` which is the `env` object of the request. MiniProfiler expects the `assets_url` callback to return a URL from which the asset can be loaded (the return value will be used as a `href`/`src` attribute in the DOM). If the `assets_url` callback is not set (the default) or it returns a non-truthy value, MiniProfiler will fallback to loading assets from its own middleware (`/mini-profiler-resources/*`). The following callback should work for most applications:
401
+
402
+ ```ruby
403
+ Rack::MiniProfiler.config.assets_url = ->(name, version, env) {
404
+ ActionController::Base.helpers.asset_path(name)
405
+ }
406
+ ```
293
407
 
294
408
  ### Configuration Options
295
409
 
@@ -302,98 +416,91 @@ Rack::MiniProfiler.config.start_hidden = true
302
416
  ```
303
417
  The available configuration options are:
304
418
 
305
- Option|Default|Description
306
- -------|---|--------
307
- pre_authorize_cb|Rails: dev only<br>Rack: always on|A lambda callback that returns true to make mini_profiler visible on a given request.
308
- position|`'top-left'`|Display mini_profiler on `'top-right'`, `'top-left'`, `'bottom-right'` or `'bottom-left'`.
309
- skip_paths|`[]`|Paths that skip profiling.
310
- skip_schema_queries|Rails dev: `'true'`<br>Othwerwise: `'false'`|`'true'` to log schema queries.
311
- auto_inject|`true`|`true` to inject the miniprofiler script in the page.
312
- backtrace_ignores|`[]`|Regexes of lines to be removed from backtraces.
313
- backtrace_includes|Rails: `[/^\/?(app|config|lib|test)/]`<br>Rack: `[]`|Regexes of lines to keep in backtraces.
314
- backtrace_remove|rails: `Rails.root`<br>Rack: `nil`|A string or regex to remove part of each line in the backtrace.
315
- toggle_shortcut|Alt+P|Keyboard shortcut to toggle the mini_profiler's visibility. See [jquery.hotkeys](https://github.com/jeresig/jquery.hotkeys).
316
- start_hidden|`false`|`false` to make mini_profiler visible on page load.
317
- backtrace_threshold_ms|`0`|Minimum SQL query elapsed time before a backtrace is recorded.
318
- flamegraph_sample_rate|`0.5`|How often to capture stack traces for flamegraphs in milliseconds.
319
- disable_env_dump|`false`|`true` disables `?pp=env`, which prevents sending ENV vars over HTTP.
320
- base_url_path|`'/mini-profiler-resources/'`|Path for assets; added as a prefix when naming assets and sought when responding to requests.
321
- collapse_results|`true`|If multiple timing results exist in a single page, collapse them till clicked.
322
- max_traces_to_show|20|Maximum number of mini profiler timing blocks to show on one page
323
- html_container|`body`|The HTML container (as a jQuery selector) to inject the mini_profiler UI into
324
- show_total_sql_count|`false`|Displays the total number of SQL executions.
325
-
326
- ### Custom middleware ordering (required if using `Rack::Deflate` with Rails)
327
-
328
- If you are using `Rack::Deflate` with rails and rack-mini-profiler in its default configuration,
329
- `Rack::MiniProfiler` will be injected (as always) at position 0 in the middleware stack. This
330
- will result in it attempting to inject html into the already-compressed response body. To fix this,
331
- the middleware ordering must be overriden.
332
-
333
- To do this, first add `, require: false` to the gemfile entry for rack-mini-profiler.
334
- This will prevent the railtie from running. Then, customize the initialization
335
- in the initializer like so:
419
+ Option | Default | Description
420
+ ------------------------------------|---------------------------------------------------------|------------------------
421
+ pre_authorize_cb | Rails: dev only<br>Rack: always on | A lambda callback that returns true to make mini_profiler visible on a given request.
422
+ position | `'top-left'` | Display mini_profiler on `'top-right'`, `'top-left'`, `'bottom-right'` or `'bottom-left'`.
423
+ skip_paths | `[]` | An array of paths that skip profiling. Both `String` and `Regexp` are acceptable in the array.
424
+ skip_schema_queries | Rails dev: `true`<br>Othwerwise: `false` | `true` to skip schema queries.
425
+ auto_inject | `true` | `true` to inject the miniprofiler script in the page.
426
+ backtrace_ignores | `[]` | Regexes of lines to be removed from backtraces.
427
+ backtrace_includes | Rails: `[/^\/?(app\|config\|lib\|test)/]`<br>Rack: `[]` | Regexes of lines to keep in backtraces.
428
+ backtrace_remove | rails: `Rails.root`<br>Rack: `nil` | A string or regex to remove part of each line in the backtrace.
429
+ toggle_shortcut | Alt+P | Keyboard shortcut to toggle the mini_profiler's visibility. See [jquery.hotkeys](https://github.com/jeresig/jquery.hotkeys).
430
+ start_hidden | `false` | `false` to make mini_profiler visible on page load.
431
+ backtrace_threshold_ms | `0` | Minimum SQL query elapsed time before a backtrace is recorded.
432
+ flamegraph_sample_rate | `0.5` | How often to capture stack traces for flamegraphs in milliseconds.
433
+ flamegraph_mode | `:wall` | The [StackProf mode](https://github.com/tmm1/stackprof#all-options) to pass to `StackProf.run`.
434
+ base_url_path | `'/mini-profiler-resources/'` | Path for assets; added as a prefix when naming assets and sought when responding to requests.
435
+ cookie_path | `'/'` | Set-Cookie header path for profile cookie
436
+ collapse_results | `true` | If multiple timing results exist in a single page, collapse them till clicked.
437
+ max_traces_to_show | 20 | Maximum number of mini profiler timing blocks to show on one page
438
+ html_container | `body` | The HTML container (as a jQuery selector) to inject the mini_profiler UI into
439
+ show_total_sql_count | `false` | Displays the total number of SQL executions.
440
+ enable_advanced_debugging_tools | `false` | Enables sensitive debugging tools that can be used via the UI. In production we recommend keeping this disabled as memory and environment debugging tools can expose contents of memory that may contain passwords. Defaults to `true` in development.
441
+ assets_url | `nil` | See the "Register MiniProfiler's assets in the Rails assets pipeline" section above.
442
+ snapshot_every_n_requests | `-1` | Determines how frequently snapshots are taken. See the "Snapshots Sampling" above for more details.
443
+ max_snapshot_groups | `50` | Determines how many snapshot groups Mini Profiler is allowed to keep.
444
+ max_snapshots_per_group | `15` | Determines how many snapshots per group Mini Profiler is allowed to keep.
445
+ snapshot_hidden_custom_fields | `[]` | Each snapshot custom field will have a dedicated column in the UI by default. Use this config to exclude certain custom fields from having their own columns.
446
+ snapshots_transport_destination_url | `nil` | Set this config to a valid URL to enable snapshots transporter which will `POST` snapshots to the given URL. The transporter requires `snapshots_transport_auth_key` config to be set as well.
447
+ 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.
448
+ 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.
449
+ snapshots_transport_gzip_requests | `false` | Make the snapshots transporter gzip the requests it makes to `snapshots_transport_destination_url`.
450
+ 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
+ enable_hotwire_turbo_drive_support | `false` | Enable support for Hotwire TurboDrive page transitions.
452
+ profile_parameter | `'pp'` | The query parameter used to interact with this gem.
453
+
454
+ ### Using MiniProfiler with `Rack::Deflate` middleware
455
+
456
+ If you are using `Rack::Deflate` with Rails and `rack-mini-profiler` in its default configuration,
457
+ `Rack::MiniProfiler` will be injected (as always) at position 0 in the middleware stack,
458
+ which means it will run after `Rack::Deflate` on response processing. To prevent attempting to inject
459
+ HTML in already compressed response body MiniProfiler will suppress compression by setting
460
+ `identity` encoding in `Accept-Encoding` request header.
461
+
462
+ ### Using MiniProfiler with Heroku Redis
463
+
464
+ If you are using Heroku Redis, you may need to add the following to your `config/initializers/mini_profiler.rb`, in order to get Mini Profiler to work:
336
465
 
337
466
  ```ruby
338
- require 'rack-mini-profiler'
339
-
340
- Rack::MiniProfilerRails.initialize!(Rails.application)
341
-
342
- Rails.application.middleware.delete(Rack::MiniProfiler)
343
- Rails.application.middleware.insert_after(Rack::Deflater, Rack::MiniProfiler)
467
+ if Rails.env.production?
468
+ Rack::MiniProfiler.config.storage_options = {
469
+ url: ENV["REDIS_URL"],
470
+ ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE }
471
+ }
472
+ Rack::MiniProfiler.config.storage = Rack::MiniProfiler::RedisStore
473
+ end
344
474
  ```
345
475
 
346
- Deleting the middleware and then reinserting it is a bit inelegant, but
347
- a sufficient and costless solution. It is possible that rack-mini-profiler might
348
- support this scenario more directly if it is found that
349
- there is significant need for this confriguration or that
350
- the above recipe causes problems.
351
-
476
+ The above code snippet is [Heroku's officially suggested workaround](https://help.heroku.com/HC0F8CUS/redis-connection-issues).
352
477
 
353
478
  ## Special query strings
354
479
 
355
480
  If you include the query string `pp=help` at the end of your request you will see the various options available. You can use these options to extend or contract the amount of diagnostics rack-mini-profiler gathers.
356
481
 
482
+ ## Development
357
483
 
358
- ## Rails 2.X support
484
+ If you want to contribute to this project, that's great, thank you! You can run the following rake task:
359
485
 
360
- To get MiniProfiler working with Rails 2.3.X you need to do the initialization manually as well as monkey patch away an incompatibility between activesupport and json_pure.
486
+ ```
487
+ $ BUNDLE_GEMFILE=website/Gemfile bundle install
488
+ $ bundle exec rake client_dev
489
+ ```
361
490
 
362
- Add the following code to your environment.rb (or just in a specific environment such as development.rb) for initialization and configuration of MiniProfiler.
491
+ This will start a local Sinatra server at `http://localhost:9292` where you'll be able to preview your changes. Refreshing the page should be enough to see any changes you make to files in the `lib/html` directory.
363
492
 
364
- ```ruby
365
- # configure and initialize MiniProfiler
366
- require 'rack-mini-profiler'
367
- c = ::Rack::MiniProfiler.config
368
- c.pre_authorize_cb = lambda { |env|
369
- Rails.env.development? || Rails.env.production?
370
- }
371
- tmp = Rails.root.to_s + "/tmp/miniprofiler"
372
- FileUtils.mkdir_p(tmp) unless File.exist?(tmp)
373
- c.storage_options = {:path => tmp}
374
- c.storage = ::Rack::MiniProfiler::FileStore
375
- config.middleware.use(::Rack::MiniProfiler)
376
- ::Rack::MiniProfiler.profile_method(ActionController::Base, :process) {|action| "Executing action: #{action}"}
377
- ::Rack::MiniProfiler.profile_method(ActionView::Template, :render) {|x,y| "Rendering: #{path_without_format_and_extension}"}
378
-
379
- # monkey patch away an activesupport and json_pure incompatability
380
- # http://pivotallabs.com/users/alex/blog/articles/1332-monkey-patch-of-the-day-activesupport-vs-json-pure-vs-ruby-1-8
381
- if JSON.const_defined?(:Pure)
382
- class JSON::Pure::Generator::State
383
- include ActiveSupport::CoreExtensions::Hash::Except
384
- end
385
- end
386
- ```
493
+ Make sure to prepend `bundle exec` before any Rake tasks you run.
387
494
 
388
495
  ## Running the Specs
389
496
 
497
+ You need Memcached and Redis services running for the specs.
498
+
390
499
  ```
391
- $ rake build
392
- $ rake spec
500
+ $ bundle exec rake build
501
+ $ bundle exec rake spec
393
502
  ```
394
503
 
395
- Additionally you can also run `autotest` if you like.
396
-
397
504
  ## Licence
398
505
 
399
506
  The MIT License (MIT)
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ MINI_PROFILER_ENABLE_RAILS_PATCHES = true
5
+ end
@@ -0,0 +1,9 @@
1
+ Description:
2
+ Generates an initializer for rack-mini-profiler. Use an initializer when manually
3
+ requiring rack-mini-profiler in your application (using require: false in your Gemfile).
4
+
5
+ Example:
6
+ `bin/rails generate rack_mini_profiler:install`
7
+
8
+ This generates a an initializer that requires and initializes
9
+ rack-mini-profiler in development mode.
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RackMiniProfiler
4
+ module Generators
5
+ class InstallGenerator < ::Rails::Generators::Base
6
+ source_root File.expand_path("templates", __dir__)
7
+
8
+ def create_initializer_file
9
+ copy_file "rack_mini_profiler.rb", "config/initializers/rack_mini_profiler.rb"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -3,6 +3,6 @@
3
3
  if Rails.env.development?
4
4
  require "rack-mini-profiler"
5
5
 
6
- # initialization is skipped so trigger it
6
+ # The initializer was required late, so initialize it manually.
7
7
  Rack::MiniProfilerRails.initialize!(Rails.application)
8
8
  end
@@ -1,12 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "generators/rack_mini_profiler/install_generator"
4
+
3
5
  module RackProfiler
4
6
  module Generators
5
- class InstallGenerator < ::Rails::Generators::Base
6
- source_root File.expand_path("templates", __dir__)
7
+ class InstallGenerator < RackMiniProfiler::Generators::InstallGenerator
8
+ source_root File.expand_path("../rack_mini_profiler/templates", __dir__)
7
9
 
8
10
  def create_initializer_file
9
- copy_file "rack_profiler.rb", "config/initializers/rack_profiler.rb"
11
+ warn("bin/rails generate rack_profiler:install is deprecated. Please use rack_mini_profiler:install instead.")
12
+ super
10
13
  end
11
14
  end
12
15
  end
@@ -0,0 +1,2 @@
1
+ /* Laura Doktorova https://github.com/olado/doT */
2
+ !function(){"use strict";function e(n,t,r){return("string"==typeof t?t:t.toString()).replace(n.define||a,function(e,t,o,a){return 0===t.indexOf("def.")&&(t=t.substring(4)),t in r||(":"===o?(n.defineParams&&a.replace(n.defineParams,function(e,n,o){r[t]={arg:n,text:o}}),t in r||(r[t]=a)):new Function("def","def['"+t+"']="+a)(r)),""}).replace(n.use||a,function(t,o){n.useParams&&(o=o.replace(n.useParams,function(e,n,t,o){if(r[t]&&r[t].arg&&o){var a=(t+":"+o).replace(/'|\\/g,"_");return r.__exp=r.__exp||{},r.__exp[a]=r[t].text.replace(new RegExp("(^|[^\\w$])"+r[t].arg+"([^\\w$])","g"),"$1"+o+"$2"),n+"def.__exp['"+a+"']"}}));var a=new Function("def","return "+o)(r);return a?e(n,a,r):a})}function n(e){return e.replace(/\\('|\\)/g,"$1").replace(/[\r\t\n]/g," ")}var t,r={engine:"doT",version:"1.1.1",templateSettings:{evaluate:/\{\{([\s\S]+?(\}?)+)\}\}/g,interpolate:/\{\{=([\s\S]+?)\}\}/g,encode:/\{\{!([\s\S]+?)\}\}/g,use:/\{\{#([\s\S]+?)\}\}/g,useParams:/(^|[^\w$])def(?:\.|\[[\'\"])([\w$\.]+)(?:[\'\"]\])?\s*\:\s*([\w$\.]+|\"[^\"]+\"|\'[^\']+\'|\{[^\}]+\})/g,define:/\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g,defineParams:/^\s*([\w$]+):([\s\S]+)/,conditional:/\{\{\?(\?)?\s*([\s\S]*?)\s*\}\}/g,iterate:/\{\{~\s*(?:\}\}|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\}\})/g,varname:"it",strip:!0,append:!0,selfcontained:!1,doNotSkipEncoded:!1},template:void 0,compile:void 0,log:!0};r.encodeHTMLSource=function(e){var n={"&":"&#38;","<":"&#60;",">":"&#62;",'"':"&#34;","'":"&#39;","/":"&#47;"},t=e?/[&<>"'\/]/g:/&(?!#?\w+;)|<|>|"|'|\//g;return function(e){return e?e.toString().replace(t,function(e){return n[e]||e}):""}},t=function(){return this||(0,eval)("this")}(),"undefined"!=typeof module&&module.exports?module.exports=r:"function"==typeof define&&define.amd?define(function(){return r}):t.doT=r;var o={append:{start:"'+(",end:")+'",startencode:"'+encodeHTML("},split:{start:"';out+=(",end:");out+='",startencode:"';out+=encodeHTML("}},a=/$^/;r.template=function(c,i,u){i=i||r.templateSettings;var d,s,p=i.append?o.append:o.split,l=0,f=i.use||i.define?e(i,c,u||{}):c;f=("var out='"+(i.strip?f.replace(/(^|\r|\n)\t* +| +\t*(\r|\n|$)/g," ").replace(/\r|\n|\t|\/\*[\s\S]*?\*\//g,""):f).replace(/'|\\/g,"\\$&").replace(i.interpolate||a,function(e,t){return p.start+n(t)+p.end}).replace(i.encode||a,function(e,t){return d=!0,p.startencode+n(t)+p.end}).replace(i.conditional||a,function(e,t,r){return t?r?"';}else if("+n(r)+"){out+='":"';}else{out+='":r?"';if("+n(r)+"){out+='":"';}out+='"}).replace(i.iterate||a,function(e,t,r,o){return t?(l+=1,s=o||"i"+l,t=n(t),"';var arr"+l+"="+t+";if(arr"+l+"){var "+r+","+s+"=-1,l"+l+"=arr"+l+".length-1;while("+s+"<l"+l+"){"+r+"=arr"+l+"["+s+"+=1];out+='"):"';} } out+='"}).replace(i.evaluate||a,function(e,t){return"';"+n(t)+"out+='"})+"';return out;").replace(/\n/g,"\\n").replace(/\t/g,"\\t").replace(/\r/g,"\\r").replace(/(\s|;|\}|^|\{)out\+='';/g,"$1").replace(/\+''/g,""),d&&(i.selfcontained||!t||t._encodeHTML||(t._encodeHTML=r.encodeHTMLSource(i.doNotSkipEncoded)),f="var encodeHTML = typeof _encodeHTML !== 'undefined' ? _encodeHTML : ("+r.encodeHTMLSource.toString()+"("+(i.doNotSkipEncoded||"")+"));"+f);try{return new Function(i.varname,f)}catch(e){throw"undefined"!=typeof console&&console.log("Could not create a template function: "+f),e}},r.compile=function(e,n){return r.template(e,null,n)}}();