rails_mini_profiler 0 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +29 -111
  3. data/Rakefile +18 -0
  4. data/app/{javascript/images → assets/images/rails_mini_profiler}/bookmark.svg +0 -0
  5. data/app/{javascript/images → assets/images/rails_mini_profiler}/chart.svg +0 -0
  6. data/app/{javascript/images → assets/images/rails_mini_profiler}/delete.svg +0 -0
  7. data/app/{javascript/images → assets/images/rails_mini_profiler}/graph.svg +0 -0
  8. data/app/{javascript/images → assets/images/rails_mini_profiler}/logo.svg +0 -0
  9. data/app/{javascript/images → assets/images/rails_mini_profiler}/logo_variant.svg +2 -2
  10. data/app/assets/images/rails_mini_profiler/search.svg +10 -0
  11. data/app/{javascript/images → assets/images/rails_mini_profiler}/setting.svg +0 -0
  12. data/app/{javascript/images → assets/images/rails_mini_profiler}/show.svg +0 -0
  13. data/app/assets/javascripts/rails_mini_profiler.js +76 -1
  14. data/app/assets/stylesheets/rails_mini_profiler/application.css +149 -1
  15. data/app/assets/stylesheets/rails_mini_profiler/flamegraph.css +14 -0
  16. data/app/{javascript/stylesheets/flashes.scss → assets/stylesheets/rails_mini_profiler/flashes.css} +5 -3
  17. data/app/{javascript/stylesheets/navbar.scss → assets/stylesheets/rails_mini_profiler/navbar.css} +14 -8
  18. data/app/assets/stylesheets/rails_mini_profiler/profiled_requests.css +180 -0
  19. data/app/{javascript/stylesheets/traces.scss → assets/stylesheets/rails_mini_profiler/traces.css} +22 -17
  20. data/app/controllers/rails_mini_profiler/application_controller.rb +4 -9
  21. data/app/controllers/rails_mini_profiler/profiled_requests_controller.rb +10 -23
  22. data/app/helpers/rails_mini_profiler/application_helper.rb +0 -11
  23. data/app/models/rails_mini_profiler/application_record.rb +1 -1
  24. data/app/models/rails_mini_profiler/controller_trace.rb +3 -7
  25. data/app/models/rails_mini_profiler/flamegraph.rb +0 -4
  26. data/app/models/rails_mini_profiler/instantiation_trace.rb +3 -7
  27. data/app/models/rails_mini_profiler/profiled_request.rb +15 -21
  28. data/app/models/rails_mini_profiler/render_partial_trace.rb +3 -7
  29. data/app/models/rails_mini_profiler/render_template_trace.rb +3 -7
  30. data/app/models/rails_mini_profiler/rmp_trace.rb +3 -7
  31. data/app/models/rails_mini_profiler/sequel_trace.rb +3 -7
  32. data/app/models/rails_mini_profiler/trace.rb +3 -7
  33. data/app/presenters/rails_mini_profiler/profiled_request_presenter.rb +15 -8
  34. data/app/views/layouts/rails_mini_profiler/application.html.erb +12 -1
  35. data/app/views/layouts/rails_mini_profiler/flamegraph.html.erb +8 -1
  36. data/app/views/rails_mini_profiler/badge.html.erb +2 -2
  37. data/app/views/rails_mini_profiler/profiled_requests/index.html.erb +58 -8
  38. data/app/views/rails_mini_profiler/profiled_requests/show.html.erb +1 -1
  39. data/app/views/rails_mini_profiler/shared/_navbar.html.erb +1 -1
  40. data/db/migrate/20210621185018_create_rmp.rb +6 -8
  41. data/lib/generators/rails_mini_profiler/install_generator.rb +0 -24
  42. data/lib/generators/rails_mini_profiler/templates/rails_mini_profiler.rb.erb +7 -23
  43. data/lib/rails_mini_profiler/badge.rb +1 -23
  44. data/lib/rails_mini_profiler/configuration.rb +4 -28
  45. data/lib/rails_mini_profiler/engine.rb +4 -15
  46. data/lib/rails_mini_profiler/errors.rb +8 -0
  47. data/lib/rails_mini_profiler/guard.rb +7 -18
  48. data/lib/rails_mini_profiler/logger.rb +0 -5
  49. data/lib/rails_mini_profiler/middleware.rb +4 -4
  50. data/lib/rails_mini_profiler/models/base_model.rb +0 -5
  51. data/lib/rails_mini_profiler/models/trace.rb +9 -0
  52. data/lib/rails_mini_profiler/redirect.rb +1 -9
  53. data/lib/rails_mini_profiler/request_context.rb +7 -31
  54. data/lib/rails_mini_profiler/request_wrapper.rb +8 -44
  55. data/lib/rails_mini_profiler/storage.rb +29 -0
  56. data/lib/rails_mini_profiler/tracers.rb +85 -0
  57. data/lib/rails_mini_profiler/version.rb +1 -1
  58. data/lib/rails_mini_profiler.rb +9 -33
  59. metadata +30 -127
  60. data/LICENSE +0 -20
  61. data/app/javascript/images/check.svg +0 -3
  62. data/app/javascript/images/chevron.svg +0 -3
  63. data/app/javascript/images/filter.svg +0 -1
  64. data/app/javascript/images/search.svg +0 -9
  65. data/app/javascript/js/checklist_controller.js +0 -48
  66. data/app/javascript/js/enable_controller.js +0 -24
  67. data/app/javascript/js/filter_controller.js +0 -44
  68. data/app/javascript/js/search_controller.js +0 -18
  69. data/app/javascript/js/select_controller.js +0 -47
  70. data/app/javascript/packs/rails-mini-profiler.js +0 -88
  71. data/app/javascript/stylesheets/components/page_header/page_header.scss +0 -3
  72. data/app/javascript/stylesheets/components/pagination.scss +0 -55
  73. data/app/javascript/stylesheets/components/profiled_request_table/placeholder.scss +0 -33
  74. data/app/javascript/stylesheets/components/profiled_request_table/profiled_request_table.scss +0 -179
  75. data/app/javascript/stylesheets/flamegraph.scss +0 -10
  76. data/app/javascript/stylesheets/profiled_requests.scss +0 -89
  77. data/app/javascript/stylesheets/rails-mini-profiler.scss +0 -205
  78. data/app/search/rails_mini_profiler/base_search.rb +0 -67
  79. data/app/search/rails_mini_profiler/profiled_request_search.rb +0 -34
  80. data/app/views/models/_flamegraph.json.jb +0 -3
  81. data/app/views/models/_profiled_request.jb +0 -3
  82. data/app/views/models/_trace.jb +0 -3
  83. data/app/views/rails_mini_profiler/flamegraphs/show.json.jb +0 -3
  84. data/app/views/rails_mini_profiler/profiled_requests/index.json.jb +0 -3
  85. data/app/views/rails_mini_profiler/profiled_requests/shared/header/_header.erb +0 -20
  86. data/app/views/rails_mini_profiler/profiled_requests/shared/table/_placeholder.erb +0 -12
  87. data/app/views/rails_mini_profiler/profiled_requests/shared/table/_table.erb +0 -14
  88. data/app/views/rails_mini_profiler/profiled_requests/shared/table/_table_head.erb +0 -125
  89. data/app/views/rails_mini_profiler/profiled_requests/shared/table/_table_row.erb +0 -21
  90. data/app/views/rails_mini_profiler/profiled_requests/show.json.jb +0 -5
  91. data/app/views/rails_mini_profiler/shared/_head.erb +0 -13
  92. data/lib/generators/rails_mini_profiler/templates/rails_mini_profiler.js.erb +0 -13
  93. data/lib/rails_mini_profiler/configuration/storage.rb +0 -47
  94. data/lib/rails_mini_profiler/configuration/user_interface.rb +0 -48
  95. data/lib/rails_mini_profiler/tracing/controller_tracer.rb +0 -15
  96. data/lib/rails_mini_profiler/tracing/null_trace.rb +0 -7
  97. data/lib/rails_mini_profiler/tracing/sequel_tracer.rb +0 -37
  98. data/lib/rails_mini_profiler/tracing/sequel_tracker.rb +0 -37
  99. data/lib/rails_mini_profiler/tracing/subscriptions.rb +0 -34
  100. data/lib/rails_mini_profiler/tracing/trace.rb +0 -45
  101. data/lib/rails_mini_profiler/tracing/trace_factory.rb +0 -37
  102. data/lib/rails_mini_profiler/tracing/tracer.rb +0 -31
  103. data/lib/rails_mini_profiler/tracing/view_tracer.rb +0 -12
  104. data/lib/rails_mini_profiler/tracing.rb +0 -11
  105. data/public/rails_mini_profiler/speedscope/LICENSE +0 -21
  106. data/public/rails_mini_profiler/speedscope/demangle-cpp.1768f4cc.js +0 -4
  107. data/public/rails_mini_profiler/speedscope/demangle-cpp.1768f4cc.js.map +0 -1
  108. data/public/rails_mini_profiler/speedscope/favicon-16x16.f74b3187.png +0 -0
  109. data/public/rails_mini_profiler/speedscope/favicon-32x32.bc503437.png +0 -0
  110. data/public/rails_mini_profiler/speedscope/file-format-schema.json +0 -324
  111. data/public/rails_mini_profiler/speedscope/import.e3a73ef4.js +0 -117
  112. data/public/rails_mini_profiler/speedscope/import.e3a73ef4.js.map +0 -1
  113. data/public/rails_mini_profiler/speedscope/index.html +0 -2
  114. data/public/rails_mini_profiler/speedscope/release.txt +0 -3
  115. data/public/rails_mini_profiler/speedscope/reset.8c46b7a1.css +0 -2
  116. data/public/rails_mini_profiler/speedscope/reset.8c46b7a1.css.map +0 -1
  117. data/public/rails_mini_profiler/speedscope/source-map.438fa06b.js +0 -24
  118. data/public/rails_mini_profiler/speedscope/source-map.438fa06b.js.map +0 -1
  119. data/public/rails_mini_profiler/speedscope/speedscope.026f36b0.js +0 -200
  120. data/public/rails_mini_profiler/speedscope/speedscope.026f36b0.js.map +0 -1
  121. data/vendor/assets/images/bookmark.svg +0 -10
  122. data/vendor/assets/images/chart.svg +0 -12
  123. data/vendor/assets/images/check.svg +0 -3
  124. data/vendor/assets/images/chevron.svg +0 -3
  125. data/vendor/assets/images/delete.svg +0 -9
  126. data/vendor/assets/images/filter.svg +0 -1
  127. data/vendor/assets/images/graph.svg +0 -11
  128. data/vendor/assets/images/logo.svg +0 -18
  129. data/vendor/assets/images/logo_variant.svg +0 -32
  130. data/vendor/assets/images/search.svg +0 -9
  131. data/vendor/assets/images/setting.svg +0 -10
  132. data/vendor/assets/images/show.svg +0 -11
  133. data/vendor/assets/javascripts/rails-mini-profiler.css +0 -1
  134. data/vendor/assets/javascripts/rails-mini-profiler.js +0 -1
@@ -25,13 +25,13 @@
25
25
  transition: opacity 0.3s;
26
26
  }
27
27
 
28
- #logo-variant {
28
+ #rails-mini-profiler-badge-icon {
29
29
  height: 18px;
30
30
  width: 18px;
31
31
  padding-bottom: 2px;
32
32
  }
33
33
  </style>
34
34
  <a id="rails-mini-profiler-badge" href="<%= profiled_request_path(@profiled_request.id) %>" data-turbolinks="false" title="View performance data">
35
- <%= inline_svg('logo_variant.svg') %>
35
+ <%= inline_svg_tag('rails_mini_profiler/logo_variant', id: "rails-mini-profiler-badge-icon") %>
36
36
  <%= (@profiled_request.duration.to_f / 100).round %>ms
37
37
  </a>
@@ -1,9 +1,59 @@
1
+ <% if @profiled_requests.empty? %>
2
+ <section class="placeholder">
3
+ <%= inline_svg_tag('rails_mini_profiler/logo_variant', class: 'placeholder-image') %>
4
+ <div class="placeholder-text">
5
+ <h2> There is nothing here yet! </h2>
6
+ <p>Send some requests to your app for them to show up here</p>
7
+ </div>
8
+ </section>
9
+ <% else %>
10
+ <h1>Profiled Requests</h1>
11
+ <div class="profiled-requests-actions">
12
+ <%= form_with id: 'profiled-request-search-form', url: profiled_requests_url, method: :get do |form| %>
13
+ <%= form.search_field :path, id: 'profiled-request-search', placeholder: 'Search Path...', class: 'search-field' %>
14
+ <% end %>
15
+ <%= link_to(destroy_all_profiled_requests_url,
16
+ method: :delete,
17
+ class: 'clear-action',
18
+ data: { confirm: "This will delete all requests. Are you sure?" }) do %>
19
+ <button>Clear Requests</button>
20
+ <% end %>
21
+ </div>
22
+ <table id="profiled-requests-table" class="table">
23
+ <thead>
24
+ <tr>
25
+ <th class="text-left">Path</th>
26
+ <th class="text-left">Method</th>
27
+ <th class="text-left">Status</th>
28
+ <th class="text-left">Media Type</th>
29
+ <th class="text-right">Duration</th>
30
+ <th class="text-left"></th>
31
+ <th class="text-left"></th>
32
+ </tr>
33
+ </thead>
1
34
 
2
- <div
3
- data-controller="filters selectable"
4
- data-action="search-controller:submit@window->filters#apply">
5
- <%= render "rails_mini_profiler/profiled_requests/shared/header/header" %>
6
- <%= render "rails_mini_profiler/profiled_requests/shared/table/table" %>
7
- </div>
8
- <%== pagy_nav(@pagy) if @pagy.pages > 1 %>
9
- <br>
35
+ <tbody>
36
+ <% @profiled_requests.each do |profiled_request| %>
37
+ <tr data-link="<%= profiled_request_path(profiled_request.id)%>">
38
+ <td class="request-path"><%= profiled_request.request_name %></td>
39
+ <td> <%= profiled_request.request_method %> </td>
40
+ <td> <%= profiled_request.response_status %> </td>
41
+ <td> <%= profiled_request.response_media_type %> </td>
42
+ <td class="text-right"><%= profiled_request.duration %> ms</td>
43
+ <td class=""><%= profiled_request.created_at %></td>
44
+ <td class="request-buttons">
45
+ <%= link_to(profiled_request_path(profiled_request.id), title: 'Show Details') do %>
46
+ <%= inline_svg_tag('rails_mini_profiler/show.svg', options = {}) %>
47
+ <% end %>
48
+ <%= profiled_request.flamegraph_icon %>
49
+ <%= link_to(profiled_request_path(profiled_request.id), title: 'Delete Request', method: :delete) do %>
50
+ <%= inline_svg_tag('rails_mini_profiler/delete.svg') %>
51
+ <% end %>
52
+ </td>
53
+ </tr>
54
+ <% end %>
55
+ </tbody>
56
+ </table>
57
+
58
+ <br>
59
+ <% end %>
@@ -1,4 +1,4 @@
1
- <section class="page-header">
1
+ <section class="request-details">
2
2
  <h1> <%= @profiled_request.request_path %> </h1>
3
3
 
4
4
  <ul class="request-details-data">
@@ -1,7 +1,7 @@
1
1
  <header class="header">
2
2
  <nav class="nav">
3
3
  <a class="home" href="<%= profiled_requests_path %>">
4
- <%= inline_svg('logo.svg', class: 'home-logo') %>
4
+ <%= inline_svg_tag('rails_mini_profiler/logo', class: 'home-logo') %>
5
5
  <h1 class="home-title">Rails Mini Profiler </h1>
6
6
  </a>
7
7
  <ul class="header-links">
@@ -4,10 +4,10 @@ class CreateRmp < ActiveRecord::Migration[6.0]
4
4
  def change
5
5
  create_table :rmp_profiled_requests do |t|
6
6
  t.string :user_id
7
- t.bigint :start
8
- t.bigint :finish
7
+ t.integer :start
8
+ t.integer :finish
9
9
  t.integer :duration
10
- t.bigint :allocations
10
+ t.integer :allocations
11
11
  t.string :request_path
12
12
  t.string :request_query_string
13
13
  t.string :request_method
@@ -19,17 +19,15 @@ class CreateRmp < ActiveRecord::Migration[6.0]
19
19
  t.string :response_media_type
20
20
 
21
21
  t.timestamps
22
-
23
- t.index :created_at
24
22
  end
25
23
 
26
24
  create_table :rmp_traces do |t|
27
25
  t.belongs_to :rmp_profiled_request, null: false, foreign_key: true
28
26
  t.string :name
29
- t.bigint :start
30
- t.bigint :finish
27
+ t.integer :start
28
+ t.integer :finish
31
29
  t.integer :duration
32
- t.bigint :allocations
30
+ t.integer :allocations
33
31
  t.json :payload
34
32
  t.json :backtrace
35
33
 
@@ -1,39 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsMiniProfiler
4
- # Generators for Rails Mini Profiler
5
4
  module Generators
6
- # A basic installation generator to help set up users apps
7
5
  class InstallGenerator < Rails::Generators::Base
8
6
  source_root File.expand_path('templates', __dir__)
9
7
 
10
- # Install Rails Mini Profiler to your Rails app
11
- #
12
- # Updates the routes file to mount the engine, adds an initializer and copies a migration.
13
8
  desc 'Install rails-mini-profiler'
14
-
15
9
  def install
16
10
  route("mount RailsMiniProfiler::Engine => '/rails_mini_profiler'")
17
11
  template 'rails_mini_profiler.rb.erb', 'config/initializers/rails_mini_profiler.rb'
18
12
  system('rails rails_mini_profiler:install:migrations')
19
- webpacker_install if defined?(Webpacker::Engine)
20
- end
21
-
22
- private
23
-
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
-
31
- run 'yarn add @rails-mini-profiler/assets'
32
- webpack_config = YAML.load_file(webpacker_config_file)[Rails.env]
33
- destination = Rails.root.join(webpack_config['source_path'],
34
- webpack_config['source_entry_path'],
35
- 'rails-mini-profiler.js')
36
- template('rails_mini_profiler.js.erb', destination)
37
13
  end
38
14
  end
39
15
  end
@@ -1,29 +1,13 @@
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
5
1
  RailsMiniProfiler.configure do |config|
6
2
  # Customize when Rails Mini Profiler should run
7
- config.enabled = proc { |env| Rails.env.development? || env['HTTP_RMP_ENABLED'].present? }
8
-
9
- # Configure Flamegraph generation
10
- config.flamegraph_enabled = true
11
- # config.flamegraph_sample_rate = 0.5
12
-
13
- # Configure endpoints to profile
14
- config.skip_paths = []
3
+ # config.enabled = proc { |env| Rails.env.development? || request.headers[RMP_ENABLED].present? }
15
4
 
16
- # Configure how Rails Mini Profiler stores profiling information
17
- # config.storage.database = :rmp_database
18
- # config.storage.profiled_requests_table = :rmp_profiled_requests
19
- # config.storage.traces_table = :rmp_traces
20
- # config.storage.flamegraphs_table = :rmp_flamegraphs
5
+ # Disable Flamegraph generation
6
+ # config.flamegraph_enabled = false
21
7
 
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
8
+ # Use RailsMiniProfiler::Storage::ActiveRecord to store profiles in your Database
9
+ config.storage = RailsMiniProfiler::Storage::Memory
26
10
 
27
- # Customize how users are detected
28
- config.user_provider = proc { |env| Rack::Request.new(env).ip }
11
+ # Uncomment to customize how users are detected
12
+ # config.user_provider = proc { |env| Rack::Request.new(env).ip }
29
13
  end
@@ -1,33 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../../app/helpers/rails_mini_profiler/application_helper'
4
-
5
3
  module RailsMiniProfiler
6
- # Wraps functionality to render an interactive badge on top of HTML responses
7
- #
8
- # @api private
9
4
  class Badge
10
5
  include InlineSvg::ActionView::Helpers
11
- include RailsMiniProfiler::ApplicationHelper
12
6
  include Engine.routes.url_helpers
13
7
 
14
- # @param request_context [RequestContext] The current request context
15
- # @param configuration [Configuration] The current configuration
16
8
  def initialize(request_context, configuration: RailsMiniProfiler.configuration)
17
9
  @configuration = configuration
18
10
  @profiled_request = request_context.profiled_request
19
11
  @original_response = request_context.response
20
12
  end
21
13
 
22
- # Inject the badge into the response
23
- #
24
- # @return [ResponseWrapper] The modified response
25
14
  def render
26
15
  content_type = @original_response.headers['Content-Type']
27
16
  return @original_response unless content_type =~ %r{text/html}
28
17
 
29
- return @original_response unless @configuration.ui.badge_enabled
30
-
31
18
  modified_response = Rack::Response.new([], @original_response.status, @original_response.headers)
32
19
  modified_response.write(modified_body)
33
20
  modified_response.finish
@@ -42,9 +29,6 @@ module RailsMiniProfiler
42
29
 
43
30
  private
44
31
 
45
- # Modify the body of the original response
46
- #
47
- # @return String The modified body
48
32
  def modified_body
49
33
  body = @original_response.response.body
50
34
  index = body.rindex(%r{</body>}i) || body.rindex(%r{</html>}i)
@@ -55,9 +39,6 @@ module RailsMiniProfiler
55
39
  end
56
40
  end
57
41
 
58
- # Render the badge template
59
- #
60
- # @return String The badge HTML content to be injected
61
42
  def badge_content
62
43
  html = IO.read(File.expand_path('../../app/views/rails_mini_profiler/badge.html.erb', __dir__))
63
44
  @position = css_position
@@ -65,11 +46,8 @@ module RailsMiniProfiler
65
46
  template.result(binding)
66
47
  end
67
48
 
68
- # Transform the configuration position into CSS style positions
69
- #
70
- # @return String The badge position as CSS style
71
49
  def css_position
72
- case @configuration.ui.badge_position
50
+ case RailsMiniProfiler.configuration.badge_position
73
51
  when 'top-right'
74
52
  'top: 5px; right: 5px;'
75
53
  when 'bottom-left'
@@ -1,36 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rails_mini_profiler/configuration/storage'
4
- require 'rails_mini_profiler/configuration/user_interface'
5
-
6
3
  module RailsMiniProfiler
7
- # The main Rails Mini Profiler configuration object
8
- #
9
- # @!attribute [r] logger
10
- # @return [Logger] the current logger
11
- # @!attribute enabled
12
- # @return [Boolean] if the profiler is enabled
13
- # @!attribute flamegraph_enabled
14
- # @return [Boolean] if Flamegraph recording is enabled
15
- # @!attribute flamegraph_sample_rate
16
- # @return [Float] the sample rate in samples per millisecond
17
- # @!attribute skip_paths
18
- # @return [Array<String>] a list of regex patterns for paths to skip
19
- # @!attribute storage
20
- # @return [Storage] the storage configuration
21
- # @!attribute ui
22
- # @return [UserInterface] the ui configuration
23
- # @!attribute user_provider
24
- # @return [Proc] a proc to identify a user based on a rack env
25
4
  class Configuration
26
5
  attr_reader :logger
27
6
 
28
7
  attr_accessor :enabled,
8
+ :badge_enabled,
9
+ :badge_position,
29
10
  :flamegraph_enabled,
30
11
  :flamegraph_sample_rate,
31
12
  :skip_paths,
32
13
  :storage,
33
- :ui,
34
14
  :user_provider
35
15
 
36
16
  def initialize(**kwargs)
@@ -38,22 +18,18 @@ module RailsMiniProfiler
38
18
  kwargs.each { |key, value| instance_variable_set("@#{key}", value) }
39
19
  end
40
20
 
41
- # Reset the configuration to default values
42
21
  def reset
43
22
  @enabled = proc { |_env| Rails.env.development? || Rails.env.test? }
23
+ @badge_enabled = true
24
+ @badge_position = 'top-left'
44
25
  @flamegraph_enabled = true
45
26
  @flamegraph_sample_rate = 0.5
46
27
  @logger = RailsMiniProfiler::Logger.new(Rails.logger)
47
28
  @skip_paths = []
48
29
  @storage = Storage.new
49
- @ui = UserInterface.new
50
30
  @user_provider = proc { |env| Rack::Request.new(env).ip }
51
31
  end
52
32
 
53
- # Set the logger
54
- #
55
- # @param logger [Logger]
56
- # The logger to be used. If set to nil, the Rails default logger is used and the log level set to fatal
57
33
  def logger=(logger)
58
34
  if logger.nil?
59
35
  @logger.level = Logger::FATAL
@@ -1,9 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsMiniProfiler
4
- # The Rails Mini Profiler engine
5
- #
6
- # Injects a a custom [Middleware] into an existing Rails app to record request profiling information.
7
4
  class Engine < ::Rails::Engine
8
5
  isolate_namespace RailsMiniProfiler
9
6
 
@@ -11,6 +8,10 @@ module RailsMiniProfiler
11
8
  app.middleware.use(RailsMiniProfiler::Middleware)
12
9
  end
13
10
 
11
+ initializer 'rails_mini_profiler.assets.precompile', group: :all do |app|
12
+ app.config.assets.precompile += %w[rails_mini_profiler.js rails_mini_profiler/application.css]
13
+ end
14
+
14
15
  config.generators do |g|
15
16
  g.test_framework :rspec
16
17
  end
@@ -18,17 +19,5 @@ module RailsMiniProfiler
18
19
  initializer 'rails_mini_profiler_add_static assets' do |app|
19
20
  app.middleware.insert_before(ActionDispatch::Static, ActionDispatch::Static, "#{root}/public")
20
21
  end
21
-
22
- # If sprockets is not being used then there is no need to hook into asset compilation. Calling config.assets
23
- # without Sprockets installed breaks compilation.
24
- if defined?(Sprockets::Rails)
25
- initializer 'rails_mini_profiler.assets.precompile', group: :all do |app|
26
- app.config.assets.precompile += %w[
27
- rails_mini_profiler.js
28
- rails_mini_profiler/application.css
29
- vendor/assets/images
30
- ]
31
- end
32
- end
33
22
  end
34
23
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsMiniProfiler
4
+ RailsMiniProfilerError = Class.new(StandardError)
5
+
6
+ # Storage errors
7
+ StorageError = Class.new(RailsMiniProfilerError)
8
+ end
@@ -1,22 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsMiniProfiler
4
- # Encapsulates guard conditions on whether or not to run certain parts of the profiler.
5
4
  class Guard
6
- # @param request_context [RequestContext] the current request context
7
- # @param configuration [Configuration] the current configuration
8
5
  def initialize(request_context, configuration: RailsMiniProfiler.configuration)
9
6
  @request_context = request_context
10
7
  @request = request_context.request
11
8
  @configuration = configuration
12
9
  end
13
10
 
14
- # Whether or not to profile
15
- #
16
- # Profiling is disabled the profiler has been flat out disabled in the configuration or if the current request path
17
- # matches on of the ignored paths.
18
- #
19
- # @return [Boolean] false if no profiling should be done
20
11
  def profile?
21
12
  return false unless enabled?
22
13
 
@@ -25,28 +16,26 @@ module RailsMiniProfiler
25
16
  true
26
17
  end
27
18
 
19
+ def store?
20
+ return false unless @request_context.user
21
+
22
+ true
23
+ end
24
+
28
25
  private
29
26
 
30
- # Is the path of the current request an ignored one?
31
- #
32
- # @return [Boolean] true if the path is ignored. Per default, paths going to the engine itself are ignored, as are
33
- # asset requests, and the paths the user has configured.
34
27
  def ignored_path?
35
28
  return true if /#{Engine.routes.find_script_name({})}/.match?(@request.path)
36
29
 
37
30
  return true if /assets/.match?(@request.path)
38
31
 
39
32
  ignored_paths = @configuration.skip_paths
33
+
40
34
  return true if Regexp.union(ignored_paths).match?(@request.path)
41
35
 
42
36
  false
43
37
  end
44
38
 
45
- # Is the profiler enabled?
46
- #
47
- # Takes into account the current request env to decide if the profiler is enabled.
48
- #
49
- # @return [Boolean] false if the profiler is disabled
50
39
  def enabled?
51
40
  enabled = @configuration.enabled
52
41
  return enabled unless enabled.respond_to?(:call)
@@ -1,11 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsMiniProfiler
4
- # Construct a new custom logger to log from within the engine
5
4
  module Logger
6
- # Extends a logger with additional formatting
7
- #
8
- # @return [Logger] a customized logger
9
5
  def self.new(logger)
10
6
  logger = logger.dup
11
7
 
@@ -15,7 +11,6 @@ module RailsMiniProfiler
15
11
  logger.extend(self)
16
12
  end
17
13
 
18
- # Custom formatter to add a RailsMiniProfiler tag to log messages
19
14
  module Formatter
20
15
  def call(severity, timestamp, progname, msg)
21
16
  super(severity, timestamp, progname, "[RailsMiniProfiler] #{msg}")
@@ -5,11 +5,11 @@ module RailsMiniProfiler
5
5
  def initialize(app)
6
6
  @app = app
7
7
  @config = RailsMiniProfiler.configuration
8
- Tracing::Subscriptions.setup! { |trace| track_trace(trace) }
8
+ Tracers.setup! { |trace| track_trace(trace) }
9
9
  end
10
10
 
11
11
  def call(env)
12
- request = RequestWrapper.new(env: env)
12
+ request = RequestWrapper.new(env)
13
13
  request_context = RequestContext.new(request)
14
14
  return @app.call(env) unless Guard.new(request_context).profile?
15
15
 
@@ -33,8 +33,8 @@ module RailsMiniProfiler
33
33
  def track_trace(event)
34
34
  return if traces.nil?
35
35
 
36
- trace = RailsMiniProfiler::Tracing::TraceFactory.create(event)
37
- traces.append(trace) unless trace.is_a?(RailsMiniProfiler::Tracing::NullTrace)
36
+ trace = Tracers.build_trace(event)
37
+ traces.append(trace)
38
38
  end
39
39
 
40
40
  private
@@ -1,12 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsMiniProfiler
4
- # Thin wrappers around request/response classes
5
- #
6
- # @api private
7
4
  module Models
8
- # A pseudo model to be used to wrap profiling information. We can't use regular models, as their connecting
9
- # to the database results in problems when profiling.
10
5
  class BaseModel
11
6
  include ActiveModel::Model
12
7
 
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsMiniProfiler
4
+ module Models
5
+ class Trace < BaseModel
6
+ attr_accessor :id, :name, :start, :finish, :duration, :payload, :backtrace, :allocations, :created_at, :updated_at
7
+ end
8
+ end
9
+ end
@@ -1,25 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsMiniProfiler
4
- # Renders a redirect response if the user should be redirected from the original request
5
4
  class Redirect
6
5
  include Engine.routes.url_helpers
7
6
 
8
- # @param request_context [RequestContext] the current request context
9
7
  def initialize(request_context)
10
8
  @request = request_context.request
11
9
  @profiled_request = request_context.profiled_request
12
10
  end
13
11
 
14
- # Renders a redirect to a specific resource under certain conditions
15
- #
16
- # When the user requests a Flamegraph using a parameter for a specific request, they are being served a redirect.
17
- #
18
- # @return [Boolean] false if no redirect happens
19
- # @return [Array] response with status 302 and the new location to redirect to
20
12
  def render
21
13
  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].present?
14
+ return redirect_to(flamegraph_path(@profiled_request.id)) if params[:rmp_flamegraph]
23
15
 
24
16
  false
25
17
  end
@@ -1,27 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsMiniProfiler
4
- # A working context for the duration of a request, as it runs through Rails Mini Profiler's middleware
5
- #
6
- # Contains all information that is being gathered while profiling is active. At the end of the request processing,
7
- # the request context is converted into a models which are then stored in the host apps database.
8
- #
9
- # @!attribute [r] request
10
- # @return [RequestWrapper] the request as sent to the application
11
- # @!attribute response
12
- # @return [ResponseWrapper] the response as rendered by the application
13
- # @!attribute profiled_request
14
- # @return [ProfiledRequest] the profiling data as gathered during profiling
15
- # @!attribute traces
16
- # @return [Array<Models::Trace>] trace wrappers gathered during profiling
17
- # @!attribute flamegraph
18
- # @return [Flamegraph] a Flamegraph, if recorded
19
4
  class RequestContext
20
5
  attr_reader :request
21
6
 
22
7
  attr_accessor :response, :profiled_request, :traces, :flamegraph
23
8
 
24
- # @param request [RequestWrapper] the request as sent to the application
25
9
  def initialize(request)
26
10
  @request = request
27
11
  @env = request.env
@@ -29,16 +13,16 @@ module RailsMiniProfiler
29
13
  @complete = false
30
14
  end
31
15
 
32
- # If a user is currently authorized
33
- #
34
- # @return [Boolean] true if the user is authorized
16
+ def user_id
17
+ @user_id ||= User.current_user
18
+ end
19
+
35
20
  def authorized?
36
21
  @authorized ||= User.get(@env).present?
37
22
  end
38
23
 
39
- # Completes profiling, setting all data and preparing for saving it.
40
24
  def complete_profiling!
41
- profiled_request.user_id = User.current_user
25
+ profiled_request.user_id = user_id
42
26
  profiled_request.request = @request
43
27
  profiled_request.response = @response
44
28
  total_time = traces.find { |trace| trace.name == 'rails_mini_profiler.total_time' }
@@ -46,12 +30,9 @@ module RailsMiniProfiler
46
30
  @complete = true
47
31
  end
48
32
 
49
- # Save profiling data in the database.
50
- #
51
- # This will store the profiled request, as well as any attached traces and Flamgraph.
52
33
  def save_results!
53
34
  ActiveRecord::Base.transaction do
54
- profiled_request.flamegraph = RailsMiniProfiler::Flamegraph.new(data: flamegraph) if flamegraph.present?
35
+ profiled_request.flamegraph = Flamegraph.new(data: flamegraph) if flamegraph.present?
55
36
  profiled_request.save
56
37
  insert_traces unless traces.empty?
57
38
  end
@@ -73,12 +54,7 @@ module RailsMiniProfiler
73
54
 
74
55
  timestamp = Time.zone.now
75
56
  inserts = traces.map do |trace|
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
- }
57
+ { rmp_profiled_request_id: profiled_request.id, **trace.to_h, created_at: timestamp, updated_at: timestamp }
82
58
  end
83
59
  RailsMiniProfiler::Trace.insert_all(inserts)
84
60
  end