rails_mini_profiler 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +20 -0
  3. data/README.md +23 -8
  4. data/app/controllers/rails_mini_profiler/application_controller.rb +8 -3
  5. data/app/controllers/rails_mini_profiler/profiled_requests_controller.rb +1 -0
  6. data/app/helpers/rails_mini_profiler/application_helper.rb +2 -0
  7. data/app/javascript/stylesheets/components/pagination.scss +54 -0
  8. data/app/javascript/stylesheets/rails-mini-profiler.scss +1 -0
  9. data/app/views/models/_flamegraph.json.jb +3 -0
  10. data/app/views/models/_profiled_request.jb +3 -0
  11. data/app/views/models/_trace.jb +3 -0
  12. data/app/views/rails_mini_profiler/flamegraphs/show.json.jb +3 -0
  13. data/app/views/rails_mini_profiler/profiled_requests/index.html.erb +1 -1
  14. data/app/views/rails_mini_profiler/profiled_requests/index.json.jb +3 -0
  15. data/app/views/rails_mini_profiler/profiled_requests/show.json.jb +5 -0
  16. data/lib/generators/rails_mini_profiler/install_generator.rb +7 -1
  17. data/lib/generators/rails_mini_profiler/templates/rails_mini_profiler.rb.erb +9 -4
  18. data/lib/rails_mini_profiler/badge.rb +3 -1
  19. data/lib/rails_mini_profiler/{storage.rb → configuration/storage.rb} +0 -0
  20. data/lib/rails_mini_profiler/configuration/user_interface.rb +48 -0
  21. data/lib/rails_mini_profiler/configuration.rb +4 -7
  22. data/lib/rails_mini_profiler/middleware.rb +1 -1
  23. data/lib/rails_mini_profiler/redirect.rb +1 -1
  24. data/lib/rails_mini_profiler/request_context.rb +6 -1
  25. data/lib/rails_mini_profiler/request_wrapper.rb +44 -8
  26. data/lib/rails_mini_profiler/version.rb +1 -4
  27. data/lib/rails_mini_profiler.rb +3 -1
  28. data/vendor/assets/javascripts/rails-mini-profiler.css +1 -1
  29. metadata +45 -9
  30. data/Rakefile +0 -18
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c0dfb74da2ecab593753e57b0b23c131ffb7857d5c22ce167185a8ba29aa013b
4
- data.tar.gz: cc0d40ee213af658df6475062054814be1dcbec8471e894dd7fc13c8633dd734
3
+ metadata.gz: 33db210bbcb4b8ee82f80aa2f88023a478ec4852e9bbcc60cf9f70baf2a0145f
4
+ data.tar.gz: aed097f8f0e418feea8ce2670f173271bea7dd1f8803e542c2f50b82b953932d
5
5
  SHA512:
6
- metadata.gz: f21f840089c68cd189c75bd00428d3f9f23a9b84a9c3e48de1fe2236d798ece02e7869a0bc4b265a6bb26018c347cc73d0e089d64d96bcf163ecf5bcda157f7e
7
- data.tar.gz: 8185fec8a94783a448f7340e395e3278d3eecc4b801acfd3b321a1ff2255c5d902037ecff71001b78e74371f94eabb76efed986d15a9decc307feec0a45779f2
6
+ metadata.gz: a6cc1c0d0e05949bb360d4e5d04091bcfb16419a80ca31361d617a1a34571d28dfc33f31820075646143b9a359b12aa66c9ec67bb859bbdc25feaca062b5adb8
7
+ data.tar.gz: c6673b79dc6b8aacd205b5b368c1e044fb8b0e595fbb41371cf6f2c667fe31875cea9376ea551cb0e39a6c13c57cd654f41342b09bc4f41a1084a03092804fe9
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2021 hschne
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -106,22 +106,21 @@ Flamegraphs are rendered using [Speedscope](https://github.com/jlfwong/speedscop
106
106
 
107
107
  Rails Mini Profiler provides a wide array of configuration options. You can find details below. For an example configuration check `initializers/rails_mini_profiler.rb` (or [the template file](https://github.com/hschne/rails-mini-profiler/blob/main/lib/generators/rails_mini_profiler/templates/rails_mini_profiler.rb.erb)).
108
108
 
109
- | Option | Default | Description |
110
- | ------------------------ | ---------------------------- | ----------------------------------------------------------------------------------------------- |
109
+ | Name | Default | Description |
110
+ |--------------------------|------------------------------|-------------------------------------------------------------------------------------------------|
111
111
  | `enabled` | `true` (dev)/ `false` (prod) | Whether or not RMP is enabled |
112
- | `badge_enabled` | `true` | Should the hedgehog 🦔 badge be injected into pages? |
113
- | `badge_position` | `'top-left'` | Where to display the badge. Options are `'top-left', 'top-right', 'bottom-left, 'bottom-right'` |
114
112
  | `flamegraph_enabled` | `true` | Should flamegraphs be recorded automatically? |
115
113
  | `flamegraph_sample_rate` | `0.5` | The flamegraph sample rate. How many snapshots per millisecond are created. |
116
114
  | `skip_paths` | `[]` | An array of request paths that should not be profiled. Regex allowed. |
117
- | `storage` | `Storage` | Storage configuration. See [Storage](#Storage) |
115
+ | `storage` | `Storage.new` | Storage configuration. See [Storage](#Storage). |
116
+ | `ui` | `UserInterface.new` | UI configuration. See [UI](#UI). |
118
117
  | `user_provider` | `Rack::Request.new(env).ip` | How to identify users. See [Users](#Users) |
119
118
 
120
119
  ### Request Configuration
121
120
 
122
121
  You may override the configuration by sending request parameters. The following parameters are available:
123
122
 
124
- | Option | Description |
123
+ | Name | Description |
125
124
  | ---------------- | ------------------------------------------------------------------------------------------- |
126
125
  | `rmp_flamegraph` | Overrides `flamegraph_enabled` If set to `true` will redirect to the flamegraph immediatly. |
127
126
 
@@ -130,7 +129,7 @@ You may override the configuration by sending request parameters. The following
130
129
  Rails Mini Profiler stores profiling information in your database per default. You can configure various details of how
131
130
  traces and requests are stored.
132
131
 
133
- | Configuration | Default | Description |
132
+ | Name | Default | Description |
134
133
  | ------------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------- |
135
134
  | `database` | `nil` | Set a custom database to be used for storing profiler information. Uses `connect_to` for profiler records |
136
135
  | `profiled_requests_table` | `rmp_profiled_requests` | The table to be used to store profiled requests. |
@@ -155,6 +154,16 @@ class ProfiledRequestCleanupJob < ApplicationJob
155
154
  end
156
155
  ```
157
156
 
157
+ ### UI
158
+
159
+ Rails Mini Profiler allows you to configure various UI features.
160
+
161
+ | Name | Default | Description |
162
+ |------------------|--------------|-------------------------------------------------------------------------------------------------|
163
+ | `badge_enabled` | `true` | Should the hedgehog 🦔 badge be injected into pages? |
164
+ | `badge_position` | `'top-left'` | Where to display the badge. Options are `'top-left', 'top-right', 'bottom-left, 'bottom-right'` |
165
+ | `page_size` | `25` | The page size for lists shown in the UI. |
166
+
158
167
  ### Users
159
168
 
160
169
  Profiling information is segregated by user ID. That means users cannot see each other's profiled requests.
@@ -215,7 +224,13 @@ As such, compared to `rack-mini-profiler`, it does not support non-Rails apps (e
215
224
 
216
225
  Rails Mini Profiler is in early development. As such, breaking changes may still be introduced on a regular basis. While Rails Mini Profiler is in pre-release we do not offer upgrade migrations.
217
226
 
218
- If an upgrade to Rails Mini Profiler breaks your application, we recommend that you drop the offending tables and re-run migrations for the latest version:
227
+ If an upgrade to Rails Mini Profiler breaks your application, we recommend that you clean house and start over. Re-run the initializer and overwrite existing files:
228
+
229
+ ```bash
230
+ rails rails_mini_profiler:install
231
+ ```
232
+
233
+ If only the DB schema is out of date, drop the offending tables and re-run migrations for the latest version:
219
234
 
220
235
  ```
221
236
  rails rails_mini_profiler:install:migrations
@@ -2,7 +2,9 @@
2
2
 
3
3
  module RailsMiniProfiler
4
4
  class ApplicationController < ActionController::Base
5
- rescue_from ActiveRecord::RecordNotFound, with: :not_found
5
+ include Pagy::Backend
6
+
7
+ rescue_from ActiveRecord::RecordNotFound, with: ->(error) { handle(error, 404) }
6
8
 
7
9
  before_action :check_current_user
8
10
 
@@ -17,8 +19,11 @@ module RailsMiniProfiler
17
19
 
18
20
  private
19
21
 
20
- def not_found(error)
21
- redirect_back(fallback_location: profiled_requests_path, alert: error.to_s)
22
+ def handle(error, status = 500)
23
+ respond_to do |format|
24
+ format.html { redirect_back(fallback_location: profiled_requests_path, alert: error.to_s) }
25
+ format.json { render status: status, json: { message: error.to_s } }
26
+ end
22
27
  end
23
28
 
24
29
  def check_current_user
@@ -11,6 +11,7 @@ module RailsMiniProfiler
11
11
  .includes(:flamegraph)
12
12
  .where(user_id: user_id).order(id: :desc)
13
13
  @profiled_requests = @profiled_requests.where('request_path LIKE ?', "%#{params[:path]}%") if params[:path]
14
+ @pagy, @profiled_requests = pagy(@profiled_requests, items: configuration.ui.page_size)
14
15
  @profiled_requests = @profiled_requests.map { |request| present(request) }
15
16
  end
16
17
 
@@ -2,6 +2,8 @@
2
2
 
3
3
  module RailsMiniProfiler
4
4
  module ApplicationHelper
5
+ include Pagy::Frontend
6
+
5
7
  def present(model, presenter_class = nil, **kwargs)
6
8
  klass = presenter_class || "#{model.class}Presenter".constantize
7
9
  presenter = klass.new(model, self, **kwargs)
@@ -0,0 +1,54 @@
1
+ .pagy-nav {
2
+ display: flex;
3
+ align-items: center;
4
+ justify-content: center;
5
+ padding: 1em 0;
6
+ }
7
+
8
+ .pagy-nav > .page.disabled,
9
+ .pagy-nav > .page.active,
10
+ .pagy-nav > .page > a {
11
+ padding: 0.5rem 1rem;
12
+
13
+ color: var(--grey-900);
14
+
15
+ background: white;
16
+ border: 1px solid var(--border-color);
17
+ border-right: none;
18
+ text-decoration: none;
19
+ cursor: pointer;
20
+
21
+ &:hover {
22
+ background: var(--grey-100);
23
+ }
24
+ }
25
+
26
+ .pagy-nav > .page.prev a,
27
+ .pagy-nav > .page.prev.disabled {
28
+ border-radius: 5px 0 0 5px;
29
+ }
30
+
31
+ .pagy-nav > .page.next a,
32
+ .pagy-nav > .page.next.disabled {
33
+ border-radius: 0 5px 5px 0;
34
+ border-right: 1px solid var(--border-color);
35
+ }
36
+
37
+ .pagy-nav > .page.active {
38
+ cursor: default;
39
+ background: var(--red-500);
40
+ border-color: var(--red-500);
41
+ color: white;
42
+
43
+ &:hover {
44
+ background: var(--red-500);
45
+ }
46
+ }
47
+
48
+ .pagy-nav > .page.disabled {
49
+ cursor: default;
50
+ color: var(--grey-500);
51
+ &:hover {
52
+ background: white;
53
+ }
54
+ }
@@ -3,6 +3,7 @@
3
3
  @import 'navbar';
4
4
  @import 'profiled_requests';
5
5
  @import 'traces';
6
+ @import 'components/pagination';
6
7
 
7
8
  @import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600;700&display=swap');
8
9
 
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ flamegraph
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ profiled_request.attributes
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ trace.attributes
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ render 'models/flamegraph', flamegraph: @flamegraph
@@ -54,6 +54,6 @@
54
54
  <% end %>
55
55
  </tbody>
56
56
  </table>
57
-
57
+ <%== pagy_nav(@pagy) %>
58
58
  <br>
59
59
  <% end %>
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ render partial: 'models/profiled_request', collection: @profiled_requests, as: :profiled_request
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ request = render 'models/profiled_request', profiled_request: @profiled_request
4
+ request[:traces] = render partial: 'models/trace', collection: @traces, as: :trace
5
+ request
@@ -22,8 +22,14 @@ module RailsMiniProfiler
22
22
  private
23
23
 
24
24
  def webpacker_install
25
+ webpacker_config_file = Rails.root.join('config', 'webpacker.yml')
26
+ unless File.exist?(webpacker_config_file)
27
+ say "Webpacker is not installed. Run 'rails webpacker:install' and rerun installation to complete setup"
28
+ return
29
+ end
30
+
25
31
  run 'yarn add @rails-mini-profiler/assets'
26
- webpack_config = YAML.load_file(Rails.root.join('config', 'webpacker.yml'))[Rails.env]
32
+ webpack_config = YAML.load_file(webpacker_config_file)[Rails.env]
27
33
  destination = Rails.root.join(webpack_config['source_path'],
28
34
  webpack_config['source_entry_path'],
29
35
  'rails-mini-profiler.js')
@@ -1,11 +1,11 @@
1
+ # Rails Mini Profiler Initializer (<%= RailsMiniProfiler::VERSION %>)
2
+
3
+ # Customize to your hearts content. If you remove this file, Rails Mini Profiler will use sensible defaults.
4
+ # For more information see https://github.com/hschne/rails-mini-profiler#configuration
1
5
  RailsMiniProfiler.configure do |config|
2
6
  # Customize when Rails Mini Profiler should run
3
7
  config.enabled = proc { |env| Rails.env.development? || env['HTTP_RMP_ENABLED'].present? }
4
8
 
5
- # Configure how hedgehog badge is rendered
6
- config.badge_enabled = true
7
- # config.badge_position = 'top-left'
8
-
9
9
  # Configure Flamegraph generation
10
10
  config.flamegraph_enabled = true
11
11
  # config.flamegraph_sample_rate = 0.5
@@ -19,6 +19,11 @@ RailsMiniProfiler.configure do |config|
19
19
  # config.storage.traces_table = :rmp_traces
20
20
  # config.storage.flamegraphs_table = :rmp_flamegraphs
21
21
 
22
+ # Configure the Rails Mini Profiler User Interface
23
+ # config.ui.badge_enabled = true
24
+ # config.ui.badge_position = 'top-left'
25
+ # config.ui.page_size = 25
26
+
22
27
  # Customize how users are detected
23
28
  config.user_provider = proc { |env| Rack::Request.new(env).ip }
24
29
  end
@@ -26,6 +26,8 @@ module RailsMiniProfiler
26
26
  content_type = @original_response.headers['Content-Type']
27
27
  return @original_response unless content_type =~ %r{text/html}
28
28
 
29
+ return @original_response unless @configuration.ui.badge_enabled
30
+
29
31
  modified_response = Rack::Response.new([], @original_response.status, @original_response.headers)
30
32
  modified_response.write(modified_body)
31
33
  modified_response.finish
@@ -67,7 +69,7 @@ module RailsMiniProfiler
67
69
  #
68
70
  # @return String The badge position as CSS style
69
71
  def css_position
70
- case @configuration.badge_position
72
+ case @configuration.ui.badge_position
71
73
  when 'top-right'
72
74
  'top: 5px; right: 5px;'
73
75
  when 'bottom-left'
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsMiniProfiler
4
+ # Configure various aspects about Rails Mini Profilers UI.
5
+ #
6
+ # @!attribute badge_enabled
7
+ # @see Badge
8
+ # @return [Boolean] if the badge should be enabled
9
+ # @!attribute badge_position
10
+ # @see Badge
11
+ # @return [String] the position of the interactive HTML badge
12
+ # @!attribute page_size
13
+ # @return [Integer] how many items to render per page in list views
14
+ class UserInterface
15
+ class << self
16
+ # Construct a new UI configuration instance
17
+ #
18
+ # @return [UserInterface] a new storage configuration
19
+ def configuration
20
+ @configuration ||= new
21
+ end
22
+
23
+ # Configure how profiling data is shown to the user
24
+ #
25
+ # @yieldreturn [UserInterface] a new UI configuration object
26
+ def configure
27
+ yield(configuration)
28
+ configuration
29
+ end
30
+ end
31
+
32
+ attr_accessor :badge_enabled,
33
+ :badge_position,
34
+ :page_size
35
+
36
+ def initialize(**kwargs)
37
+ defaults!
38
+ kwargs.each { |key, value| instance_variable_set("@#{key}", value) }
39
+ end
40
+
41
+ # Reset the configuration to default values
42
+ def defaults!
43
+ @badge_enabled = true
44
+ @badge_position = 'top-left'
45
+ @page_size = 25
46
+ end
47
+ end
48
+ end
@@ -7,9 +7,6 @@ module RailsMiniProfiler
7
7
  # @return [Logger] the current logger
8
8
  # @!attribute enabled
9
9
  # @return [Boolean] if the profiler is enabled
10
- # @!attribute badge_position
11
- # @see Badge
12
- # @return [String] the position of the interactive HTML badge.
13
10
  # @!attribute flamegraph_enabled
14
11
  # @return [Boolean] if Flamegraph recording is enabled
15
12
  # @!attribute flamegraph_sample_rate
@@ -18,18 +15,19 @@ module RailsMiniProfiler
18
15
  # @return [Array<String>] a list of regex patterns for paths to skip
19
16
  # @!attribute storage
20
17
  # @return [Storage] the storage configuration
18
+ # @!attribute ui
19
+ # @return [UserInterface] the ui configuration
21
20
  # @!attribute user_provider
22
21
  # @return [Proc] a proc to identify a user based on a rack env
23
22
  class Configuration
24
23
  attr_reader :logger
25
24
 
26
25
  attr_accessor :enabled,
27
- :badge_enabled,
28
- :badge_position,
29
26
  :flamegraph_enabled,
30
27
  :flamegraph_sample_rate,
31
28
  :skip_paths,
32
29
  :storage,
30
+ :ui,
33
31
  :user_provider
34
32
 
35
33
  def initialize(**kwargs)
@@ -40,13 +38,12 @@ module RailsMiniProfiler
40
38
  # Reset the configuration to default values
41
39
  def reset
42
40
  @enabled = proc { |_env| Rails.env.development? || Rails.env.test? }
43
- @badge_enabled = true
44
- @badge_position = 'top-left'
45
41
  @flamegraph_enabled = true
46
42
  @flamegraph_sample_rate = 0.5
47
43
  @logger = RailsMiniProfiler::Logger.new(Rails.logger)
48
44
  @skip_paths = []
49
45
  @storage = Storage.new
46
+ @ui = UserInterface.new
50
47
  @user_provider = proc { |env| Rack::Request.new(env).ip }
51
48
  end
52
49
 
@@ -9,7 +9,7 @@ module RailsMiniProfiler
9
9
  end
10
10
 
11
11
  def call(env)
12
- request = RequestWrapper.new(env)
12
+ request = RequestWrapper.new(env: env)
13
13
  request_context = RequestContext.new(request)
14
14
  return @app.call(env) unless Guard.new(request_context).profile?
15
15
 
@@ -19,7 +19,7 @@ module RailsMiniProfiler
19
19
  # @return [Array] response with status 302 and the new location to redirect to
20
20
  def render
21
21
  params = CGI.parse(@request.query_string).transform_values(&:first).with_indifferent_access
22
- return redirect_to(flamegraph_path(@profiled_request.id)) if params[:rmp_flamegraph]
22
+ return redirect_to(flamegraph_path(@profiled_request.id)) if params[:rmp_flamegraph].present?
23
23
 
24
24
  false
25
25
  end
@@ -73,7 +73,12 @@ module RailsMiniProfiler
73
73
 
74
74
  timestamp = Time.zone.now
75
75
  inserts = traces.map do |trace|
76
- { rmp_profiled_request_id: profiled_request.id, **trace.to_h, created_at: timestamp, updated_at: timestamp }
76
+ {
77
+ rmp_profiled_request_id: profiled_request.id,
78
+ created_at: timestamp,
79
+ updated_at: timestamp,
80
+ **trace.to_h.symbolize_keys # Symbolize keys needed for Ruby 2.6
81
+ }
77
82
  end
78
83
  RailsMiniProfiler::Trace.insert_all(inserts)
79
84
  end
@@ -1,6 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsMiniProfiler
4
+ # A convenience wrapper around [Rack::Env]
5
+ #
6
+ # @!attribute body
7
+ # @return [String] the request body
8
+ # @!attribute method
9
+ # @return [String] the request method
10
+ # @!attribute path
11
+ # @return [String] the request path
12
+ # @!attribute query_string
13
+ # @return [String] the request query string
14
+ # @!attribute env
15
+ # @return [Rack::Env] the original env
16
+ #
17
+ # @api private
4
18
  class RequestWrapper
5
19
  attr_reader :body,
6
20
  :method,
@@ -8,21 +22,43 @@ module RailsMiniProfiler
8
22
  :query_string,
9
23
  :env
10
24
 
11
- def initialize(env = {})
12
- @env = env
13
- @method = @env['REQUEST_METHOD'] || 'GET'
14
- @query_string = @env['QUERY_STRING'] || ''
15
- @path = @env['PATH_INFO'] || '/'
16
- @body = read_body
25
+ def initialize(*_args, **attributes)
26
+ @attributes = attributes
27
+ setup
17
28
  end
18
29
 
30
+ # The request headers
31
+ #
32
+ # @return [Hash] the headers
19
33
  def headers
20
- @env.select { |k, _v| k.start_with? 'HTTP_' } || []
34
+ @attributes[:headers] || @env.select { |k, _v| k.start_with? 'HTTP_' } || {}
21
35
  end
22
36
 
23
37
  private
24
38
 
25
- def read_body
39
+ def setup
40
+ @env = @attributes[:env] || {}
41
+ @method = setup_method
42
+ @query_string = setup_query_string
43
+ @path = setup_path
44
+ @body = setup_body
45
+ end
46
+
47
+ def setup_method
48
+ @attributes[:method] || @env['REQUEST_METHOD'] || 'GET'
49
+ end
50
+
51
+ def setup_query_string
52
+ @attributes[:query_string] || @env['QUERY_STRING'] || ''
53
+ end
54
+
55
+ def setup_path
56
+ @attributes[:path] || @env['PATH_INFO'] || '/'
57
+ end
58
+
59
+ def setup_body
60
+ return @attributes[:body] if @attributes[:body]
61
+
26
62
  return '' unless @env['rack.input']
27
63
 
28
64
  body = @env['rack.input'].read
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsMiniProfiler
4
- # This needs to be double quoted for release-please
5
- #
6
- # See https://github.com/googleapis/release-please/issues/1018
7
- VERSION = "0.3.0" # rubocop:disable Style/StringLiterals
4
+ VERSION = '0.4.0'
8
5
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'forwardable'
4
4
  require 'inline_svg'
5
+ require 'pagy'
5
6
 
6
7
  require 'rails_mini_profiler/version'
7
8
  require 'rails_mini_profiler/engine'
@@ -14,7 +15,8 @@ require 'rails_mini_profiler/models/trace'
14
15
 
15
16
  require 'rails_mini_profiler/logger'
16
17
  require 'rails_mini_profiler/configuration'
17
- require 'rails_mini_profiler/storage'
18
+ require 'rails_mini_profiler/configuration/storage'
19
+ require 'rails_mini_profiler/configuration/user_interface'
18
20
  require 'rails_mini_profiler/request_wrapper'
19
21
  require 'rails_mini_profiler/response_wrapper'
20
22
  require 'rails_mini_profiler/guard'
@@ -1 +1 @@
1
- @import url("https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600;700&display=swap");.flash{margin-top:1rem;padding:1rem;border-radius:5px}.flash-error{color:#fff;background:var(--red-500)}.flash-notice{color:#fff;background:var(--green-400)}#wrapper{height:100vh;width:100%}#speedscope-iframe{width:100%;height:100%;border:none}.header{margin:0;padding:1.5rem 0;display:flex;justify-content:center;box-shadow:0 0 20px 0 rgba(0,0,0,.2);background:var(--primary)}.header a{color:#fff;text-decoration:none}.nav{width:var(--main-width);justify-content:space-between}.home,.nav{display:flex}.home{align-items:center;text-decoration:none}.home-logo{width:64px;height:64px}.home-title{padding:0 0 0 1rem;margin:0}.header-links{margin:0;padding:0;list-style:none;display:flex;align-items:center;font-weight:700}main{width:100%;display:flex;justify-content:center}.main-section{width:var(--main-width)}.placeholder{display:flex;flex-direction:column;justify-content:center;align-items:center;width:100%;height:450px}.placeholder-image{height:30%;width:30%;-webkit-filter:grayscale(1) brightness(2.5)}.placeholder-text{text-align:center;color:var(--grey-400)}.profiled-requests-actions{display:flex;padding:1rem 0;justify-content:space-between;align-items:center}.search-field{padding:.5rem;border-radius:.25em;border:1px solid var(--grey-400);color:var(--grey-700)}.clear-action button{background:var(--red-500);color:#fff}.table{width:100%;border-collapse:collapse;border-radius:5px;border:1px hidden var(--border-color);box-shadow:0 0 0 1px var(--border-color)}.table thead tr{color:var(--grey-400)}.table thead th{font-weight:400}.table tr{border:1px solid var(--border-color);color:var(--grey-700);cursor:pointer}.table tr:nth-child(2n){background:var(--grey-50)}.table tbody tr:hover{background:var(--grey-100)}.table td,.table th{padding:.5rem 1rem}.request-path{max-width:300px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.request-buttons{z-index:1;text-align:right}.request-buttons a{text-decoration:none;padding:0 .25rem;color:var(--grey-700)}.request-buttons a:active,.request-buttons a:focus-visible,.request-buttons a:hover{color:var(--blue-500)}.request-buttons a.link-disabled{cursor:default;pointer-events:none;text-decoration:none;color:var(--grey-200)}.request-details-data{display:flex;margin:0;padding:0}.data-item{display:flex;flex-direction:column;align-items:flex-start;list-style:none;margin-right:3rem;padding:0}.data-item small{color:var(--grey-400)}.data-item span{margin:.25rem 0}[class*=request-method-get],[class*=request-status-2]{color:#fff;background:var(--green-400)!important}[class*=request-method-patch],[class*=request-method-put],[class*=request-status-4]{color:#fff;background:var(--yellow-400)!important}[class*=request-method-delete],[class*=request-status-5]{color:#fff;background:var(--red-500)!important}.request-details-actions{margin:0;padding:2em 0;display:flex;align-items:center;justify-content:space-between}.flamegraph-button button{background:var(--grey-200)}.trace-list{margin:0;padding:0}.trace{list-style:none;display:flex;padding:.25em 0;align-items:center;justify-content:flex-start}.trace:nth-child(odd){background:var(--grey-100)}.trace .trace-bar{position:relative;margin:0;height:16px;padding:0;cursor:pointer;background:linear-gradient(to top right,var(--grey-500),var(--grey-400))}.instantiation-trace .trace-bar{background:linear-gradient(to top right,var(--green-400),var(--green-300))}.sequel-trace .trace-bar{background:linear-gradient(to top right,var(--green-500),var(--green-400))}.controller-trace .trace-bar{background:linear-gradient(to top right,var(--yellow-500),var(--yellow-400))}.render-partial-trace .trace-bar,.render-template-trace .trace-bar{background:linear-gradient(to top right,var(--blue-500),var(--blue-400))}.trace-name{margin:0;box-sizing:border-box;padding:0 .5em;overflow:hidden;font-size:14px;text-align:right;text-overflow:ellipsis;color:var(--grey-400)}.trace-payload{margin:0}.sequel-trace-query{padding:1em;background:var(--grey-100)}.sequel-trace-binds,.sequel-trace-query{overflow:auto;max-height:100px;white-space:pre-wrap}.sequel-trace-binds{margin:0 0 1em;padding:.5em 1em;font-size:12px;background:var(--grey-50)}.trace-table{margin-top:1em;width:100%;border-collapse:collapse;border:1px hidden var(--border-color)}@font-face{font-family:Open Sans;font-weight:400;font-style:normal}@font-face{font-family:Open Sans;font-weight:600;font-style:normal}@font-face{font-family:Open Sans;font-weight:700;font-style:normal}html{--grey-50:#f9fafb;--grey-100:#f3f4f6;--grey-200:#e5e7eb;--grey-400:#9ca3af;--grey-500:#6b7280;--grey-700:#374151;--grey-900:#111827;--red-400:#f87171;--red-500:#ef4444;--red-600:#dc2626;--yellow-400:#fbbf24;--yellow-500:#f59e0b;--green-300:#6ee7b7;--green-400:#34d399;--green-500:#10b981;--blue-400:#60a5fa;--blue-500:#3b82f6;--main-width:1056px;--primary:var(--red-600);--border-color:var(--grey-200);--text-color:var(--grey-900);font-family:Open Sans,monospace}body,html{width:100%;height:100%;margin:0;padding:0}body{color:var(--text-color)}h1{padding:2rem 0 1rem}button{border:none;border-radius:.25rem;padding:.5em;text-align:center;text-decoration:none;display:inline-block;font-size:1rem;cursor:pointer}button:hover{box-shadow:0 .25rem .25rem 0 var(--grey-50)}.text-left{text-align:left}.text-right{text-align:right}.pill{margin:.2rem 0;padding:.1rem .4rem;border-radius:5px;font-size:.9rem;font-weight:600;letter-spacing:.1rem;background:var(--grey-200)}.popover{display:flex;flex-direction:column;width:600px;padding:1em;color:#000}.popover-header{display:flex;padding-bottom:1em;flex-direction:row;justify-content:space-between;align-items:center}.popover-description{margin:0;padding:0}.popover-close{background:transparent;padding:0;font-weight:700;font-size:20px;color:var(--grey-400)}.popover-body{padding:1em 0}.popover-footer{border-top:1px solid var(--grey-50)}.tippy-box[data-theme~=rmp]{background:#fff;box-shadow:8px 0 30px 4px rgba(0,0,0,.2),8px 4px 10px 0 rgba(0,0,0,.05);border-radius:3px;transition:all .2s cubic-bezier(.19,1,.22,1)}.tippy-box[data-theme~=rmp][data-placement^=top]>.tippy-arrow:before{border-top-color:#fff}.tippy-box[data-theme~=rmp][data-placement^=bottom]>.tippy-arrow:before{border-bottom-color:#fff}.tippy-box[data-theme~=rmp][data-placement^=left]>.tippy-arrow:before{border-left-color:#fff}.tippy-box[data-theme~=rmp][data-placement^=right]>.tippy-arrow:before{border-right-color:#fff}
1
+ @import url("https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600;700&display=swap");.flash{margin-top:1rem;padding:1rem;border-radius:5px}.flash-error{color:#fff;background:var(--red-500)}.flash-notice{color:#fff;background:var(--green-400)}#wrapper{height:100vh;width:100%}#speedscope-iframe{width:100%;height:100%;border:none}.header{margin:0;padding:1.5rem 0;display:flex;justify-content:center;box-shadow:0 0 20px 0 rgba(0,0,0,.2);background:var(--primary)}.header a{color:#fff;text-decoration:none}.nav{width:var(--main-width);justify-content:space-between}.home,.nav{display:flex}.home{align-items:center;text-decoration:none}.home-logo{width:64px;height:64px}.home-title{padding:0 0 0 1rem;margin:0}.header-links{margin:0;padding:0;list-style:none;display:flex;align-items:center;font-weight:700}main{width:100%;display:flex;justify-content:center}.main-section{width:var(--main-width)}.placeholder{display:flex;flex-direction:column;justify-content:center;align-items:center;width:100%;height:450px}.placeholder-image{height:30%;width:30%;-webkit-filter:grayscale(1) brightness(2.5)}.placeholder-text{text-align:center;color:var(--grey-400)}.profiled-requests-actions{display:flex;padding:1rem 0;justify-content:space-between;align-items:center}.search-field{padding:.5rem;border-radius:.25em;border:1px solid var(--grey-400);color:var(--grey-700)}.clear-action button{background:var(--red-500);color:#fff}.table{width:100%;border-collapse:collapse;border-radius:5px;border:1px hidden var(--border-color);box-shadow:0 0 0 1px var(--border-color)}.table thead tr{color:var(--grey-400)}.table thead th{font-weight:400}.table tr{border:1px solid var(--border-color);color:var(--grey-700);cursor:pointer}.table tr:nth-child(2n){background:var(--grey-50)}.table tbody tr:hover{background:var(--grey-100)}.table td,.table th{padding:.5rem 1rem}.request-path{max-width:300px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.request-buttons{z-index:1;text-align:right}.request-buttons a{text-decoration:none;padding:0 .25rem;color:var(--grey-700)}.request-buttons a:active,.request-buttons a:focus-visible,.request-buttons a:hover{color:var(--blue-500)}.request-buttons a.link-disabled{cursor:default;pointer-events:none;text-decoration:none;color:var(--grey-200)}.request-details-data{display:flex;margin:0;padding:0}.data-item{display:flex;flex-direction:column;align-items:flex-start;list-style:none;margin-right:3rem;padding:0}.data-item small{color:var(--grey-400)}.data-item span{margin:.25rem 0}[class*=request-method-get],[class*=request-status-2]{color:#fff;background:var(--green-400)!important}[class*=request-method-patch],[class*=request-method-put],[class*=request-status-4]{color:#fff;background:var(--yellow-400)!important}[class*=request-method-delete],[class*=request-status-5]{color:#fff;background:var(--red-500)!important}.request-details-actions{margin:0;padding:2em 0;display:flex;align-items:center;justify-content:space-between}.flamegraph-button button{background:var(--grey-200)}.trace-list{margin:0;padding:0}.trace{list-style:none;display:flex;padding:.25em 0;align-items:center;justify-content:flex-start}.trace:nth-child(odd){background:var(--grey-100)}.trace .trace-bar{position:relative;margin:0;height:16px;padding:0;cursor:pointer;background:linear-gradient(to top right,var(--grey-500),var(--grey-400))}.instantiation-trace .trace-bar{background:linear-gradient(to top right,var(--green-400),var(--green-300))}.sequel-trace .trace-bar{background:linear-gradient(to top right,var(--green-500),var(--green-400))}.controller-trace .trace-bar{background:linear-gradient(to top right,var(--yellow-500),var(--yellow-400))}.render-partial-trace .trace-bar,.render-template-trace .trace-bar{background:linear-gradient(to top right,var(--blue-500),var(--blue-400))}.trace-name{margin:0;box-sizing:border-box;padding:0 .5em;overflow:hidden;font-size:14px;text-align:right;text-overflow:ellipsis;color:var(--grey-400)}.trace-payload{margin:0}.sequel-trace-query{padding:1em;background:var(--grey-100)}.sequel-trace-binds,.sequel-trace-query{overflow:auto;max-height:100px;white-space:pre-wrap}.sequel-trace-binds{margin:0 0 1em;padding:.5em 1em;font-size:12px;background:var(--grey-50)}.trace-table{margin-top:1em;width:100%;border-collapse:collapse;border:1px hidden var(--border-color)}.pagy-nav{display:flex;align-items:center;justify-content:center;padding:1em 0}.pagy-nav>.page.active,.pagy-nav>.page.disabled,.pagy-nav>.page>a{padding:.5rem 1rem;color:var(--grey-900);background:#fff;border:1px solid var(--border-color);border-right:none;text-decoration:none;cursor:pointer}.pagy-nav>.page.active:hover,.pagy-nav>.page.disabled:hover,.pagy-nav>.page>a:hover{background:var(--grey-100)}.pagy-nav>.page.prev.disabled,.pagy-nav>.page.prev a{border-radius:5px 0 0 5px}.pagy-nav>.page.next.disabled,.pagy-nav>.page.next a{border-radius:0 5px 5px 0;border-right:1px solid var(--border-color)}.pagy-nav>.page.active{cursor:default;border-color:var(--red-500);color:#fff}.pagy-nav>.page.active,.pagy-nav>.page.active:hover{background:var(--red-500)}.pagy-nav>.page.disabled{cursor:default;color:var(--grey-500)}.pagy-nav>.page.disabled:hover{background:#fff}@font-face{font-family:Open Sans;font-weight:400;font-style:normal}@font-face{font-family:Open Sans;font-weight:600;font-style:normal}@font-face{font-family:Open Sans;font-weight:700;font-style:normal}html{--grey-50:#f9fafb;--grey-100:#f3f4f6;--grey-200:#e5e7eb;--grey-400:#9ca3af;--grey-500:#6b7280;--grey-700:#374151;--grey-900:#111827;--red-400:#f87171;--red-500:#ef4444;--red-600:#dc2626;--yellow-400:#fbbf24;--yellow-500:#f59e0b;--green-300:#6ee7b7;--green-400:#34d399;--green-500:#10b981;--blue-400:#60a5fa;--blue-500:#3b82f6;--main-width:1056px;--primary:var(--red-600);--border-color:var(--grey-200);--text-color:var(--grey-900);font-family:Open Sans,monospace}body,html{width:100%;height:100%;margin:0;padding:0}body{color:var(--text-color)}h1{padding:2rem 0 1rem}button{border:none;border-radius:.25rem;padding:.5em;text-align:center;text-decoration:none;display:inline-block;font-size:1rem;cursor:pointer}button:hover{box-shadow:0 .25rem .25rem 0 var(--grey-50)}.text-left{text-align:left}.text-right{text-align:right}.pill{margin:.2rem 0;padding:.1rem .4rem;border-radius:5px;font-size:.9rem;font-weight:600;letter-spacing:.1rem;background:var(--grey-200)}.popover{display:flex;flex-direction:column;width:600px;padding:1em;color:#000}.popover-header{display:flex;padding-bottom:1em;flex-direction:row;justify-content:space-between;align-items:center}.popover-description{margin:0;padding:0}.popover-close{background:transparent;padding:0;font-weight:700;font-size:20px;color:var(--grey-400)}.popover-body{padding:1em 0}.popover-footer{border-top:1px solid var(--grey-50)}.tippy-box[data-theme~=rmp]{background:#fff;box-shadow:8px 0 30px 4px rgba(0,0,0,.2),8px 4px 10px 0 rgba(0,0,0,.05);border-radius:3px;transition:all .2s cubic-bezier(.19,1,.22,1)}.tippy-box[data-theme~=rmp][data-placement^=top]>.tippy-arrow:before{border-top-color:#fff}.tippy-box[data-theme~=rmp][data-placement^=bottom]>.tippy-arrow:before{border-bottom-color:#fff}.tippy-box[data-theme~=rmp][data-placement^=left]>.tippy-arrow:before{border-left-color:#fff}.tippy-box[data-theme~=rmp][data-placement^=right]>.tippy-arrow:before{border-right-color:#fff}
metadata CHANGED
@@ -1,29 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_mini_profiler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - hschne
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-21 00:00:00.000000000 Z
11
+ date: 2021-08-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: inline_svg
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '1.7'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: jb
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.8'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pagy
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '4.11'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
25
53
  - !ruby/object:Gem::Version
26
- version: '0'
54
+ version: '4.11'
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: rails
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -45,8 +73,8 @@ executables: []
45
73
  extensions: []
46
74
  extra_rdoc_files: []
47
75
  files:
76
+ - LICENSE
48
77
  - README.md
49
- - Rakefile
50
78
  - app/assets/config/rails_mini_profiler_manifest.js
51
79
  - app/assets/javascripts/rails_mini_profiler.js
52
80
  - app/assets/stylesheets/rails_mini_profiler/application.css
@@ -65,6 +93,7 @@ files:
65
93
  - app/javascript/images/setting.svg
66
94
  - app/javascript/images/show.svg
67
95
  - app/javascript/packs/rails-mini-profiler.js
96
+ - app/javascript/stylesheets/components/pagination.scss
68
97
  - app/javascript/stylesheets/flamegraph.scss
69
98
  - app/javascript/stylesheets/flashes.scss
70
99
  - app/javascript/stylesheets/navbar.scss
@@ -92,11 +121,17 @@ files:
92
121
  - app/presenters/rails_mini_profiler/trace_presenter.rb
93
122
  - app/views/layouts/rails_mini_profiler/application.html.erb
94
123
  - app/views/layouts/rails_mini_profiler/flamegraph.html.erb
124
+ - app/views/models/_flamegraph.json.jb
125
+ - app/views/models/_profiled_request.jb
126
+ - app/views/models/_trace.jb
95
127
  - app/views/rails_mini_profiler/badge.html.erb
96
128
  - app/views/rails_mini_profiler/flamegraphs/show.html.erb
129
+ - app/views/rails_mini_profiler/flamegraphs/show.json.jb
97
130
  - app/views/rails_mini_profiler/profiled_requests/index.html.erb
131
+ - app/views/rails_mini_profiler/profiled_requests/index.json.jb
98
132
  - app/views/rails_mini_profiler/profiled_requests/shared/_trace.html.erb
99
133
  - app/views/rails_mini_profiler/profiled_requests/show.html.erb
134
+ - app/views/rails_mini_profiler/profiled_requests/show.json.jb
100
135
  - app/views/rails_mini_profiler/shared/_flashes.html.erb
101
136
  - app/views/rails_mini_profiler/shared/_head.erb
102
137
  - app/views/rails_mini_profiler/shared/_navbar.html.erb
@@ -109,6 +144,8 @@ files:
109
144
  - lib/rails_mini_profiler.rb
110
145
  - lib/rails_mini_profiler/badge.rb
111
146
  - lib/rails_mini_profiler/configuration.rb
147
+ - lib/rails_mini_profiler/configuration/storage.rb
148
+ - lib/rails_mini_profiler/configuration/user_interface.rb
112
149
  - lib/rails_mini_profiler/engine.rb
113
150
  - lib/rails_mini_profiler/flamegraph_guard.rb
114
151
  - lib/rails_mini_profiler/guard.rb
@@ -120,7 +157,6 @@ files:
120
157
  - lib/rails_mini_profiler/request_context.rb
121
158
  - lib/rails_mini_profiler/request_wrapper.rb
122
159
  - lib/rails_mini_profiler/response_wrapper.rb
123
- - lib/rails_mini_profiler/storage.rb
124
160
  - lib/rails_mini_profiler/tracers.rb
125
161
  - lib/rails_mini_profiler/user.rb
126
162
  - lib/rails_mini_profiler/version.rb
@@ -169,7 +205,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
169
205
  requirements:
170
206
  - - ">="
171
207
  - !ruby/object:Gem::Version
172
- version: 2.7.0
208
+ version: 2.6.0
173
209
  required_rubygems_version: !ruby/object:Gem::Requirement
174
210
  requirements:
175
211
  - - ">="
data/Rakefile DELETED
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/setup'
4
-
5
- APP_RAKEFILE = File.expand_path('spec/dummy/Rakefile', __dir__)
6
- load 'rails/tasks/engine.rake'
7
- load 'rails/tasks/statistics.rake'
8
-
9
- require 'bundler/gem_tasks'
10
-
11
- require 'rspec/core/rake_task'
12
- rspec = RSpec::Core::RakeTask.new(:spec)
13
- rspec.verbose = false
14
-
15
- require 'rubocop/rake_task'
16
- RuboCop::RakeTask.new
17
-
18
- task default: %i[spec rubocop]