rails_mini_profiler 0.4.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +48 -34
  3. data/app/adapters/rails_mini_profiler/database_adapter.rb +16 -0
  4. data/app/controllers/rails_mini_profiler/application_controller.rb +9 -15
  5. data/app/controllers/rails_mini_profiler/profiled_requests_controller.rb +44 -14
  6. data/app/helpers/rails_mini_profiler/application_helper.rb +1 -1
  7. data/app/helpers/rails_mini_profiler/profiled_requests_helper.rb +10 -0
  8. data/app/javascript/images/check.svg +3 -0
  9. data/app/javascript/images/chevron.svg +3 -0
  10. data/app/javascript/images/copy.svg +6 -0
  11. data/app/javascript/images/filter.svg +1 -0
  12. data/app/javascript/images/logo_variant.svg +2 -2
  13. data/app/javascript/images/search.svg +4 -5
  14. data/app/javascript/js/checklist_controller.js +48 -0
  15. data/app/javascript/js/clipboard_controller.js +53 -0
  16. data/app/javascript/js/enable_controller.js +23 -0
  17. data/app/javascript/js/filter_controller.js +48 -0
  18. data/app/javascript/js/search_controller.js +18 -0
  19. data/app/javascript/js/select_controller.js +52 -0
  20. data/app/javascript/packs/rails-mini-profiler.js +69 -53
  21. data/app/javascript/stylesheets/components/buttons.scss +59 -0
  22. data/app/javascript/stylesheets/components/dropdown.scss +103 -0
  23. data/app/javascript/stylesheets/components/input.scss +10 -0
  24. data/app/javascript/stylesheets/{navbar.scss → components/navbar.scss} +7 -13
  25. data/app/javascript/stylesheets/components/page_header.scss +7 -0
  26. data/app/javascript/stylesheets/components/pagination.scss +14 -13
  27. data/app/javascript/stylesheets/components/placeholder.scss +36 -0
  28. data/app/javascript/stylesheets/components/profiled_request_table.scss +55 -0
  29. data/app/javascript/stylesheets/components/trace.scss +93 -0
  30. data/app/javascript/stylesheets/flamegraph.scss +3 -2
  31. data/app/javascript/stylesheets/flashes.scss +3 -5
  32. data/app/javascript/stylesheets/profiled_requests.scss +12 -161
  33. data/app/javascript/stylesheets/rails-mini-profiler.scss +81 -66
  34. data/app/javascript/stylesheets/traces.scss +52 -56
  35. data/app/models/rails_mini_profiler/profiled_request.rb +1 -1
  36. data/app/models/rails_mini_profiler/trace.rb +0 -15
  37. data/app/presenters/rails_mini_profiler/controller_trace_presenter.rb +10 -2
  38. data/app/presenters/rails_mini_profiler/instantiation_trace_presenter.rb +15 -3
  39. data/app/presenters/rails_mini_profiler/profiled_request_presenter.rb +10 -17
  40. data/app/presenters/rails_mini_profiler/render_partial_trace_presenter.rb +6 -2
  41. data/app/presenters/rails_mini_profiler/render_template_trace_presenter.rb +6 -2
  42. data/app/presenters/rails_mini_profiler/sequel_trace_presenter.rb +16 -4
  43. data/app/presenters/rails_mini_profiler/trace_presenter.rb +10 -8
  44. data/app/search/rails_mini_profiler/base_search.rb +67 -0
  45. data/app/search/rails_mini_profiler/profiled_request_search.rb +33 -0
  46. data/app/search/rails_mini_profiler/trace_search.rb +27 -0
  47. data/app/views/rails_mini_profiler/badge.html.erb +2 -2
  48. data/app/views/rails_mini_profiler/profiled_requests/index.html.erb +8 -58
  49. data/app/views/rails_mini_profiler/profiled_requests/shared/header/_header.erb +19 -0
  50. data/app/views/rails_mini_profiler/profiled_requests/shared/table/_placeholder.erb +12 -0
  51. data/app/views/rails_mini_profiler/profiled_requests/shared/table/_table.erb +14 -0
  52. data/app/views/rails_mini_profiler/profiled_requests/shared/table/_table_head.erb +125 -0
  53. data/app/views/rails_mini_profiler/profiled_requests/shared/table/_table_row.erb +21 -0
  54. data/app/views/rails_mini_profiler/profiled_requests/{shared → show}/_trace.html.erb +24 -7
  55. data/app/views/rails_mini_profiler/profiled_requests/show/_trace_list.erb +12 -0
  56. data/app/views/rails_mini_profiler/profiled_requests/show/_trace_list_header.erb +87 -0
  57. data/app/views/rails_mini_profiler/profiled_requests/show/_trace_list_placeholder.erb +12 -0
  58. data/app/views/rails_mini_profiler/profiled_requests/show.html.erb +5 -18
  59. data/app/views/rails_mini_profiler/shared/_head.erb +1 -1
  60. data/lib/generators/rails_mini_profiler/templates/rails_mini_profiler.rb.erb +2 -0
  61. data/lib/rails_mini_profiler/badge.rb +21 -12
  62. data/lib/rails_mini_profiler/configuration/user_interface.rb +31 -1
  63. data/lib/rails_mini_profiler/configuration.rb +7 -0
  64. data/lib/rails_mini_profiler/engine.rb +12 -8
  65. data/lib/rails_mini_profiler/flamegraph_guard.rb +10 -6
  66. data/lib/rails_mini_profiler/guard.rb +19 -1
  67. data/lib/rails_mini_profiler/middleware.rb +12 -10
  68. data/lib/rails_mini_profiler/request_context.rb +22 -18
  69. data/lib/rails_mini_profiler/request_wrapper.rb +12 -55
  70. data/lib/rails_mini_profiler/response_wrapper.rb +21 -17
  71. data/lib/rails_mini_profiler/tracers/controller_tracer.rb +29 -0
  72. data/lib/rails_mini_profiler/tracers/instantiation_tracer.rb +17 -0
  73. data/lib/rails_mini_profiler/tracers/null_trace.rb +7 -0
  74. data/lib/rails_mini_profiler/tracers/registry.rb +76 -0
  75. data/lib/rails_mini_profiler/tracers/rmp_tracer.rb +17 -0
  76. data/lib/rails_mini_profiler/tracers/sequel_tracer.rb +51 -0
  77. data/lib/rails_mini_profiler/tracers/sequel_tracker.rb +40 -0
  78. data/lib/rails_mini_profiler/tracers/subscriptions.rb +28 -0
  79. data/lib/rails_mini_profiler/{models → tracers}/trace.rb +11 -3
  80. data/lib/rails_mini_profiler/tracers/trace_factory.rb +27 -0
  81. data/lib/rails_mini_profiler/tracers/tracer.rb +45 -0
  82. data/lib/rails_mini_profiler/tracers/view_tracer.rb +29 -0
  83. data/lib/rails_mini_profiler/tracers.rb +12 -83
  84. data/lib/rails_mini_profiler/user.rb +1 -1
  85. data/lib/rails_mini_profiler/version.rb +1 -1
  86. data/lib/rails_mini_profiler.rb +4 -8
  87. data/vendor/assets/images/check.svg +3 -0
  88. data/vendor/assets/images/chevron.svg +3 -0
  89. data/vendor/assets/images/copy.svg +6 -0
  90. data/vendor/assets/images/filter.svg +1 -0
  91. data/vendor/assets/images/logo_variant.svg +2 -2
  92. data/vendor/assets/images/search.svg +4 -5
  93. data/vendor/assets/javascripts/rails-mini-profiler.css +1 -1
  94. data/vendor/assets/javascripts/rails-mini-profiler.js +1 -1
  95. metadata +58 -13
  96. data/app/models/rails_mini_profiler/controller_trace.rb +0 -37
  97. data/app/models/rails_mini_profiler/instantiation_trace.rb +0 -37
  98. data/app/models/rails_mini_profiler/render_partial_trace.rb +0 -37
  99. data/app/models/rails_mini_profiler/render_template_trace.rb +0 -37
  100. data/app/models/rails_mini_profiler/rmp_trace.rb +0 -35
  101. data/app/models/rails_mini_profiler/sequel_trace.rb +0 -37
@@ -15,21 +15,14 @@ module RailsMiniProfiler
15
15
  end
16
16
 
17
17
  def created_at
18
- time_tag(model.created_at.in_time_zone(Time.zone))
19
- end
20
-
21
- def flamegraph_icon
22
- return nil unless RailsMiniProfiler.configuration.flamegraph_enabled
23
-
24
- if model.flamegraph.present?
25
- link_to(flamegraph_path(model.id), title: 'Show Flamegraph') do
26
- inline_svg('graph.svg')
27
- end
28
- else
29
- link_to(flamegraph_path(model.id), title: 'No Flamegraph present for this request', class: 'link-disabled') do
30
- inline_svg('graph.svg')
31
- end
32
- end
18
+ from_time = Time.now
19
+ created_at = model.created_at.in_time_zone(Time.zone)
20
+ distance = if from_time - created_at < 5.minutes
21
+ 'Now'
22
+ else
23
+ "#{distance_of_time_in_words(from_time, created_at)} ago"
24
+ end
25
+ time_tag(created_at) { content_tag('span', distance) }
33
26
  end
34
27
 
35
28
  def flamegraph_button
@@ -37,8 +30,8 @@ module RailsMiniProfiler
37
30
 
38
31
  return nil unless model.flamegraph.present?
39
32
 
40
- link_to(flamegraph_path(model.id), title: 'Show Flamegraph', class: 'flamegraph-button') do
41
- content_tag('button', 'Flamegraph')
33
+ link_to(flamegraph_path(model.id), title: 'Show Flamegraph') do
34
+ content_tag('button', 'Flamegraph', class: 'btn-grey')
42
35
  end
43
36
  end
44
37
  end
@@ -2,10 +2,14 @@
2
2
 
3
3
  module RailsMiniProfiler
4
4
  class RenderPartialTracePresenter < TracePresenter
5
+ def identifier
6
+ payload['identifier']
7
+ end
8
+
5
9
  def label
6
10
  root = Rails.root.to_s.split('/').to_set
7
- identifier = model.identifier.split('/').to_set
8
- (root ^ identifier).drop(2).join('/').reverse.truncate(30).reverse
11
+ id = identifier.split('/').to_set
12
+ (root ^ id).drop(2).join('/').reverse.truncate(30).reverse
9
13
  end
10
14
  end
11
15
  end
@@ -2,10 +2,14 @@
2
2
 
3
3
  module RailsMiniProfiler
4
4
  class RenderTemplateTracePresenter < TracePresenter
5
+ def identifier
6
+ payload['identifier']
7
+ end
8
+
5
9
  def label
6
10
  root = Rails.root.to_s.split('/').to_set
7
- identifier = model.identifier.split('/').to_set
8
- (root ^ identifier).drop(2).join('/').reverse.truncate(30).reverse
11
+ id = identifier.split('/').to_set
12
+ (root ^ id).drop(2).join('/').reverse.truncate(30).reverse
9
13
  end
10
14
 
11
15
  def description
@@ -6,14 +6,26 @@ module RailsMiniProfiler
6
6
  sql_description
7
7
  end
8
8
 
9
+ def name
10
+ payload['name']
11
+ end
12
+
13
+ def sql
14
+ payload['sql']
15
+ end
16
+
17
+ def binds
18
+ payload['binds']
19
+ end
20
+
9
21
  alias description label
10
22
 
11
- def payload
23
+ def content
12
24
  return nil if transaction?
13
25
 
14
26
  content_tag('div') do
15
27
  content_tag('pre', class: 'trace-payload') do
16
- content_tag(:div, model.sql, class: 'sequel-trace-query')
28
+ content_tag(:div, sql, class: 'sequel-trace-query')
17
29
  end + binding_content
18
30
  end
19
31
  end
@@ -57,9 +69,9 @@ module RailsMiniProfiler
57
69
  end
58
70
 
59
71
  def simple_binds
60
- return [] if model.binds.nil? || model.binds.empty?
72
+ return [] if binds.nil? || binds.empty?
61
73
 
62
- model.binds.each_with_object({}) do |hash, object|
74
+ binds.each_with_object({}) do |hash, object|
63
75
  name = hash['name']
64
76
  value = hash['value']
65
77
  object[name] = value
@@ -2,9 +2,12 @@
2
2
 
3
3
  module RailsMiniProfiler
4
4
  class TracePresenter < BasePresenter
5
- def initialize(trace, view, profiled_request:)
5
+ def initialize(trace, view, context: {})
6
6
  super(trace, view)
7
- @profiled_request = profiled_request
7
+ @start = context[:start]
8
+ @finish = context[:finish]
9
+ @total_duration = context[:total_duration]
10
+ @total_allocations = context[:total_allocations]
8
11
  end
9
12
 
10
13
  def label
@@ -15,7 +18,7 @@ module RailsMiniProfiler
15
18
  label
16
19
  end
17
20
 
18
- def payload
21
+ def content
19
22
  nil
20
23
  end
21
24
 
@@ -38,7 +41,7 @@ module RailsMiniProfiler
38
41
  end
39
42
 
40
43
  def duration_percent
41
- (model.duration.to_f / @profiled_request.duration * 100).round
44
+ (model.duration.to_f / @total_duration * 100).round
42
45
  end
43
46
 
44
47
  def allocations
@@ -46,16 +49,15 @@ module RailsMiniProfiler
46
49
  end
47
50
 
48
51
  def allocations_percent
49
- (model.allocations.to_f / @profiled_request.allocations * 100).round
52
+ (model.allocations.to_f / @total_allocations * 100).round
50
53
  end
51
54
 
52
55
  def from_start
53
- (model.start - @profiled_request.start).to_f / 100
56
+ (model.start - @start).to_f / 100
54
57
  end
55
58
 
56
59
  def from_start_percent
57
- ((model.start - @profiled_request.start).to_f /
58
- (@profiled_request.finish - @profiled_request.start)).to_f * 100
60
+ ((model.start - @start).to_f / (@finish - @start)).to_f * 100
59
61
  end
60
62
  end
61
63
  end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsMiniProfiler
4
+ class BaseSearch
5
+ def initialize(params = nil, **kwargs)
6
+ config = self.class.config
7
+ options = params&.to_h || {}
8
+ options = options.merge(kwargs)
9
+ @scope = options.delete(:scope) || (config[:scope] && instance_eval(&config[:scope]))
10
+ @options = (options.delete(:options) || config[:options]).stringify_keys
11
+ @params = options.stringify_keys.slice(*@options.keys)
12
+ end
13
+
14
+ def results
15
+ @results ||= apply
16
+ end
17
+
18
+ def results?
19
+ results.any?
20
+ end
21
+
22
+ class << self
23
+ def scope(&block)
24
+ config[:scope] = block
25
+ end
26
+
27
+ def option(name, options = {}, &block)
28
+ name = name.to_s
29
+ handler = options[:with] || block
30
+
31
+ config[:options][name] = normalize_search_handler(handler, name)
32
+
33
+ define_method(name) { @search.param name }
34
+ end
35
+
36
+ def results(**kwargs)
37
+ new(**kwargs).results
38
+ end
39
+
40
+ def config
41
+ @config ||= { options: {} }
42
+ end
43
+
44
+ private
45
+
46
+ def normalize_search_handler(handler, name)
47
+ case handler
48
+ when Symbol
49
+ ->(scope, value) { method(handler).call scope, value }
50
+ when Proc
51
+ handler
52
+ else
53
+ ->(scope, value) { scope.where name => value unless value.blank? }
54
+ end
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def apply
61
+ @params.inject(@scope) do |scope, (name, value)|
62
+ new_scope = instance_exec scope, value, &@options[name]
63
+ new_scope || scope
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsMiniProfiler
4
+ class ProfiledRequestSearch < BaseSearch
5
+ option(:id) do |scope, value|
6
+ scope.where(id: value)
7
+ end
8
+
9
+ option(:path) do |scope, value|
10
+ scope.where('request_path LIKE ?', "%#{value}%")
11
+ end
12
+
13
+ option(:method) do |scope, value|
14
+ scope.where(request_method: value)
15
+ end
16
+
17
+ option(:media_type) do |scope, value|
18
+ scope.where(response_media_type: value)
19
+ end
20
+
21
+ option(:status) do |scope, value|
22
+ value = value.map(&:to_i)
23
+ min = value.min
24
+ max = value.max + 100
25
+ scope.where('response_status >= :lower', lower: min)
26
+ .where('response_status < :upper', upper: max)
27
+ end
28
+
29
+ option(:duration) do |scope, value|
30
+ scope.where('duration > :duration', duration: value)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsMiniProfiler
4
+ class TraceSearch < BaseSearch
5
+ option(:name) do |scope, value|
6
+ scope.where(name: value)
7
+ end
8
+
9
+ option(:duration) do |scope, value|
10
+ scope.where('duration > :duration', duration: value)
11
+ end
12
+
13
+ option(:allocations) do |scope, value|
14
+ scope.where('allocations > :allocations', allocations: value)
15
+ end
16
+
17
+ option(:payload) do |scope, value|
18
+ payload_column = DatabaseAdapter.cast_to_text(:payload)
19
+ scope.where("#{payload_column} LIKE ?", "%#{value}%")
20
+ end
21
+
22
+ option(:backtrace) do |scope, value|
23
+ backtrace_column = Adapters::DatabaseAdapter.cast_to_text(:backtrace)
24
+ scope.where("#{backtrace_column} LIKE ?", "%#{value}%")
25
+ end
26
+ end
27
+ end
@@ -25,13 +25,13 @@
25
25
  transition: opacity 0.3s;
26
26
  }
27
27
 
28
- #rails-mini-profiler-badge-icon {
28
+ #logo-variant {
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', id: "rails-mini-profiler-badge-icon") %>
35
+ <%= inline_svg('logo_variant.svg') %>
36
36
  <%= (@profiled_request.duration.to_f / 100).round %>ms
37
37
  </a>
@@ -1,59 +1,9 @@
1
- <% if @profiled_requests.empty? %>
2
- <section class="placeholder">
3
- <%= inline_svg('logo_variant.svg', 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>
34
1
 
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('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('delete.svg') %>
51
- <% end %>
52
- </td>
53
- </tr>
54
- <% end %>
55
- </tbody>
56
- </table>
57
- <%== pagy_nav(@pagy) %>
58
- <br>
59
- <% end %>
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>
@@ -0,0 +1,19 @@
1
+ <div class="page-header profiled-requests-header">
2
+ <div class="">
3
+ <h1>Profiled Requests</h1>
4
+ </div>
5
+ <div>
6
+ <%= button_tag('Delete Selected',
7
+ disabled: params[:id].blank?,
8
+ data: {
9
+ controller: 'enable',
10
+ 'enable-target': 'enable',
11
+ action: 'rmp:select:change@window->enable#change click->filters#post'
12
+ }) -%>
13
+ <%= link_to(destroy_all_profiled_requests_url,
14
+ method: :delete,
15
+ data: { confirm: "This will delete all requests. Are you sure?" }) do %>
16
+ <%= button_tag('Delete All', class: 'btn-red') %>
17
+ <% end %>
18
+ </div>
19
+ </div>
@@ -0,0 +1,12 @@
1
+ <tr class="no-row">
2
+ <td colspan="100%">
3
+ <div class="placeholder">
4
+ <%= inline_svg('logo_variant.svg', class: 'placeholder-image') %>
5
+ <div class="placeholder-text">
6
+ <h2>No Requests found!</h2>
7
+ <p>Send some requests to your app or modify your filters</p>
8
+ </div>
9
+ <%= link_to('Clear Filters', profiled_requests_path, class: 'placeholder-link') %>
10
+ </div>
11
+ </td>
12
+ </tr>
@@ -0,0 +1,14 @@
1
+ <table
2
+ id="profiled-requests-table"
3
+ class="table">
4
+ <%= render "rails_mini_profiler/profiled_requests/shared/table/table_head" %>
5
+ <tbody>
6
+ <% if @profiled_requests.empty? %>
7
+ <%= render "rails_mini_profiler/profiled_requests/shared/table/placeholder" %>
8
+ <% else %>
9
+ <% @profiled_requests.each do |profiled_request| %>
10
+ <%= render "rails_mini_profiler/profiled_requests/shared/table/table_row", profiled_request: profiled_request %>
11
+ <% end %>
12
+ <% end %>
13
+ </tbody>
14
+ </table>
@@ -0,0 +1,125 @@
1
+ <thead>
2
+ <tr>
3
+ <th style="width: 20px;" class="text-left">
4
+ <%= label_tag nil do %>
5
+ <%= check_box_tag 'selected[]', nil,
6
+ params.fetch(:selected, []).size == @pagy.items,
7
+ class: "request-checkbox",
8
+ data: {
9
+ action: 'click->selectable#selectAll',
10
+ 'selectable-target': 'all'
11
+ }
12
+ %>
13
+ <% end %>
14
+ </th>
15
+ <th style="width: 25%;" class="text-left" data-controller="dropdown">
16
+ <button data-action="click->dropdown#toggle click@window->dropdown#hide" data-dropdown-target="button" class="dropdown-toggle none">
17
+ Path <%= inline_svg('search.svg', class: 'table-filter-icon') %> </button>
18
+ <div data-controller="search" data-dropdown-target="menu" class="dropdown-container hidden">
19
+ <div class="dropdown-body">
20
+ <%= form_with url: profiled_requests_url, method: :get do |form| %>
21
+ <%= form.search_field :path,
22
+ value: params[:path],
23
+ placeholder: 'Search Path',
24
+ class: 'dropdown-search-field',
25
+ data: { 'filters-target': 'filter' } %>
26
+ <%= form.submit 'Search', class: 'btn-red', data: { action: 'click->search#submit' } -%>
27
+ <% end %>
28
+ </div>
29
+ </div>
30
+ </th>
31
+ <th style="width: 10%;" class="" data-controller="dropdown">
32
+ <button data-action="click->dropdown#toggle click@window->dropdown#hide" data-dropdown-target="button" class="dropdown-toggle none">
33
+ Method <%= inline_svg('filter.svg', class: 'table-filter-icon') %> </button>
34
+ <div data-controller="checklist" data-dropdown-target="menu" class="dropdown-container hidden">
35
+ <div class="dropdown-header">
36
+ Select Method...
37
+ <button class="clear-filters" data-action="checklist#checkNone">
38
+ Clear filter
39
+ </button>
40
+ </div>
41
+ <% %w[get put post delete].map(&:upcase).each do |method| %>
42
+ <%= label_tag nil, class: "dropdown-entry" do %>
43
+ <%= check_box_tag 'method[]', method, params.fetch(:method, []).include?(method),
44
+ class: "",
45
+ data: { 'filters-target': "filter" } %>
46
+ <%= method %>
47
+ <% end %>
48
+ <% end %>
49
+ <button class="dropdown-footer" data-action="filters#apply">
50
+ Apply
51
+ </button>
52
+ </div>
53
+ </th>
54
+ <th style="width: 10%;" class="" data-controller="dropdown">
55
+ <button data-action="click->dropdown#toggle click@window->dropdown#hide" data-dropdown-target="button" class="dropdown-toggle none">
56
+ Status <%= inline_svg('filter.svg', class: 'table-filter-icon') %> </button>
57
+ <div data-controller="checklist" data-dropdown-target="menu" class="dropdown-container hidden">
58
+ <div class="dropdown-header">
59
+ Select Status...
60
+ <button class="clear-filters" data-action="checklist#checkNone filters#apply">
61
+ Clear filter
62
+ </button>
63
+ </div>
64
+ <% %w[200 300 400 500].each do |status| %>
65
+ <%= label_tag nil, class: "dropdown-entry" do %>
66
+ <%= check_box_tag 'status[]', status, params.fetch(:status, []).include?(status),
67
+ class: "",
68
+ data: { 'filters-target': "filter" } %>
69
+ <%= status %>
70
+ <% end %>
71
+ <% end %>
72
+ <button class="dropdown-footer" data-action="filters#apply">
73
+ Apply
74
+ </button>
75
+ </div>
76
+ </th>
77
+ <th style="width: 15%;" class="" data-controller="dropdown">
78
+ <button data-action="click->dropdown#toggle click@window->dropdown#hide" data-dropdown-target="button" class="dropdown-toggle none">
79
+ Media Type <%= inline_svg('filter.svg', class: 'table-filter-icon') %> </button>
80
+ <div data-controller="checklist" data-dropdown-target="menu" class="dropdown-container hidden">
81
+ <div class="dropdown-header">
82
+ Select Media Type...
83
+ <button class="clear-filters" data-action="checklist#checkNone filters#apply">
84
+ Clear filter
85
+ </button>
86
+ </div>
87
+ <% %w[text/html application/json application/xml].each do |media_type| %>
88
+ <%= label_tag nil, class: "dropdown-entry" do %>
89
+ <%= check_box_tag 'media_type[]', media_type, params.fetch(:media_type, []).include?(media_type),
90
+ class: "",
91
+ data: { target: "filters.filter" } %>
92
+ <%= media_type %>
93
+ <% end %>
94
+ <% end %>
95
+ <button class="dropdown-footer" data-action="filters#apply">
96
+ Apply
97
+ </button>
98
+ </div>
99
+ </th>
100
+ <th style="width: 10%;" class="text-left" data-controller="dropdown">
101
+ <button data-action="click->dropdown#toggle click@window->dropdown#hide" data-dropdown-target="button" class="dropdown-toggle none">
102
+ Duration <%= inline_svg('filter.svg', class: 'table-filter-icon') %> </button>
103
+ <div data-controller="checklist" data-dropdown-target="menu" class="dropdown-container hidden">
104
+ <div class="dropdown-header">
105
+ Select Duration...
106
+ <button class="clear-filters" data-action="checklist#checkNone filters#apply">
107
+ Clear filter
108
+ </button>
109
+ </div>
110
+ <% [100_00, 250_00, 500_00].each do |duration| %>
111
+ <%= label_tag nil, class: "dropdown-entry" do %>
112
+ <%= radio_button_tag 'duration', duration.to_s , params.fetch(:duration, []).include?(duration.to_s),
113
+ class: "",
114
+ data: { target: "filters.filter" } %>
115
+ <%= "> #{duration / 100}ms" %>
116
+ <% end %>
117
+ <% end %>
118
+ <button class="dropdown-footer" data-action="filters#apply">
119
+ Apply
120
+ </button>
121
+ </div>
122
+ </th>
123
+ <th style="width: 15%;" class="text-left">Date</th>
124
+ </tr>
125
+ </thead>
@@ -0,0 +1,21 @@
1
+ <tr data-link="<%= profiled_request_path(profiled_request.id) %>">
2
+ <td class="">
3
+ <%= label_tag nil do %>
4
+ <%= check_box_tag 'id[]', profiled_request.id,
5
+ params.fetch(:selected, []).include?(profiled_request.id),
6
+ class: "request-checkbox",
7
+ data: {
8
+ 'selectable-target': 'selectable',
9
+ 'filters-target': 'filter',
10
+ action: 'click->selectable#onSelected'
11
+ },
12
+ onclick: "event.stopPropagation();" %>
13
+ <% end %>
14
+ </td>
15
+ <td class="request-path"><%= profiled_request.request_name %></td>
16
+ <td class="text-left"> <%= profiled_request.request_method %> </td>
17
+ <td class="text-left"> <%= profiled_request.response_status %> </td>
18
+ <td class="text-left"> <%= profiled_request.response_media_type %> </td>
19
+ <td class="text-left"><%= profiled_request.duration %> ms</td>
20
+ <td class="text-left"><%= profiled_request.created_at %></td>
21
+ </tr>
@@ -7,8 +7,29 @@
7
7
  <button class="popover-close">x</button>
8
8
  </section>
9
9
  <section class="popover-body">
10
- <%= trace.payload %>
11
- <table class="trace-table">
10
+ <%= trace.content %>
11
+
12
+ <% if trace.backtrace %>
13
+ <section class="popover-footer">
14
+ <div
15
+ class="backtrace"
16
+ data-controller="clipboard"
17
+ data-clipboard-filter=".+?(?=:in)"
18
+ data-clipboard-copied-message="Copied" >
19
+ <pre data-clipboard-target="source"><%= trace.backtrace %></pre>
20
+ <button
21
+ title="Copy to clipboard"
22
+ type="button"
23
+ data-action="clipboard#copy"
24
+ data-clipboard-target="button"
25
+ >
26
+ <%= inline_svg('copy.svg') %>
27
+ </button>
28
+ </div>
29
+ </section>
30
+ <% end %>
31
+
32
+ <table class="trace-details-table">
12
33
  <thead>
13
34
  <tr>
14
35
  <th class="text-left"></th>
@@ -30,11 +51,7 @@
30
51
  </table>
31
52
  </section>
32
53
 
33
- <% if trace.backtrace %>
34
- <section class="popover-footer">
35
- <pre><%= trace.backtrace %></pre>
36
- </section>
37
- <% end %>
54
+
38
55
  </div>
39
56
  </div>
40
57
  </li>
@@ -0,0 +1,12 @@
1
+ <section class="trace-list">
2
+ <%= render "rails_mini_profiler/profiled_requests/show/trace_list_header" %>
3
+ <% if @traces.empty? %>
4
+ <%= render "rails_mini_profiler/profiled_requests/show/trace_list_placeholder" %>
5
+ <% else %>
6
+ <ol>
7
+ <% @traces.each do |trace| %>
8
+ <%= render "rails_mini_profiler/profiled_requests/show/trace", trace: trace %>
9
+ <% end %>
10
+ </ol>
11
+ <% end %>
12
+ </section>