rails_mini_profiler 0.4.0 → 0.5.0
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.
- checksums.yaml +4 -4
- data/app/controllers/rails_mini_profiler/profiled_requests_controller.rb +13 -10
- data/app/javascript/images/check.svg +3 -0
- data/app/javascript/images/chevron.svg +3 -0
- data/app/javascript/images/filter.svg +1 -0
- data/app/javascript/images/logo_variant.svg +2 -2
- data/app/javascript/images/search.svg +4 -5
- data/app/javascript/js/checklist_controller.js +48 -0
- data/app/javascript/js/enable_controller.js +24 -0
- data/app/javascript/js/filter_controller.js +44 -0
- data/app/javascript/js/search_controller.js +18 -0
- data/app/javascript/js/select_controller.js +47 -0
- data/app/javascript/packs/rails-mini-profiler.js +23 -15
- data/app/javascript/stylesheets/components/page_header/page_header.scss +3 -0
- data/app/javascript/stylesheets/components/pagination.scss +14 -13
- data/app/javascript/stylesheets/components/profiled_request_table/placeholder.scss +33 -0
- data/app/javascript/stylesheets/components/profiled_request_table/profiled_request_table.scss +179 -0
- data/app/javascript/stylesheets/flamegraph.scss +3 -2
- data/app/javascript/stylesheets/flashes.scss +3 -5
- data/app/javascript/stylesheets/navbar.scss +7 -13
- data/app/javascript/stylesheets/profiled_requests.scss +35 -120
- data/app/javascript/stylesheets/rails-mini-profiler.scss +90 -61
- data/app/javascript/stylesheets/traces.scss +17 -17
- data/app/presenters/rails_mini_profiler/profiled_request_presenter.rb +8 -15
- data/app/search/rails_mini_profiler/base_search.rb +67 -0
- data/app/search/rails_mini_profiler/profiled_request_search.rb +34 -0
- data/app/views/rails_mini_profiler/badge.html.erb +2 -2
- data/app/views/rails_mini_profiler/profiled_requests/index.html.erb +8 -58
- data/app/views/rails_mini_profiler/profiled_requests/shared/header/_header.erb +20 -0
- data/app/views/rails_mini_profiler/profiled_requests/shared/table/_placeholder.erb +12 -0
- data/app/views/rails_mini_profiler/profiled_requests/shared/table/_table.erb +14 -0
- data/app/views/rails_mini_profiler/profiled_requests/shared/table/_table_head.erb +125 -0
- data/app/views/rails_mini_profiler/profiled_requests/shared/table/_table_row.erb +21 -0
- data/app/views/rails_mini_profiler/profiled_requests/show.html.erb +1 -1
- data/lib/rails_mini_profiler/configuration.rb +3 -0
- data/lib/rails_mini_profiler/engine.rb +12 -8
- data/lib/rails_mini_profiler/middleware.rb +3 -3
- data/lib/rails_mini_profiler/tracing/controller_tracer.rb +15 -0
- data/lib/rails_mini_profiler/tracing/null_trace.rb +7 -0
- data/lib/rails_mini_profiler/tracing/sequel_tracer.rb +37 -0
- data/lib/rails_mini_profiler/tracing/sequel_tracker.rb +37 -0
- data/lib/rails_mini_profiler/tracing/subscriptions.rb +34 -0
- data/lib/rails_mini_profiler/{models → tracing}/trace.rb +10 -2
- data/lib/rails_mini_profiler/tracing/trace_factory.rb +37 -0
- data/lib/rails_mini_profiler/tracing/tracer.rb +31 -0
- data/lib/rails_mini_profiler/tracing/view_tracer.rb +12 -0
- data/lib/rails_mini_profiler/tracing.rb +11 -0
- data/lib/rails_mini_profiler/version.rb +1 -1
- data/lib/rails_mini_profiler.rb +4 -8
- data/vendor/assets/images/check.svg +3 -0
- data/vendor/assets/images/chevron.svg +3 -0
- data/vendor/assets/images/filter.svg +1 -0
- data/vendor/assets/images/logo_variant.svg +2 -2
- data/vendor/assets/images/search.svg +4 -5
- data/vendor/assets/javascripts/rails-mini-profiler.css +1 -1
- data/vendor/assets/javascripts/rails-mini-profiler.js +1 -1
- metadata +33 -4
- data/lib/rails_mini_profiler/tracers.rb +0 -85
@@ -25,13 +25,13 @@
|
|
25
25
|
transition: opacity 0.3s;
|
26
26
|
}
|
27
27
|
|
28
|
-
#
|
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'
|
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
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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,20 @@
|
|
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
|
+
class: 'clear-action',
|
16
|
+
data: { confirm: "This will delete all requests. Are you sure?" }) do %>
|
17
|
+
<%= button_tag('Delete All') %>
|
18
|
+
<% end %>
|
19
|
+
</div>
|
20
|
+
</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: 'dropdown-search-button', 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
|
+
<% %w[>100ms >250ms].each do |duration| %>
|
111
|
+
<%= label_tag nil, class: "dropdown-entry" do %>
|
112
|
+
<%= radio_button_tag 'duration', duration, params.fetch(:duration, []).include?(duration),
|
113
|
+
class: "",
|
114
|
+
data: { target: "filters.filter" } %>
|
115
|
+
<%= duration %>
|
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>
|
@@ -11,14 +11,6 @@ module RailsMiniProfiler
|
|
11
11
|
app.middleware.use(RailsMiniProfiler::Middleware)
|
12
12
|
end
|
13
13
|
|
14
|
-
initializer 'rails_mini_profiler.assets.precompile', group: :all do |app|
|
15
|
-
app.config.assets.precompile += %w[
|
16
|
-
rails_mini_profiler.js
|
17
|
-
rails_mini_profiler/application.css
|
18
|
-
vendor/assets/images
|
19
|
-
]
|
20
|
-
end
|
21
|
-
|
22
14
|
config.generators do |g|
|
23
15
|
g.test_framework :rspec
|
24
16
|
end
|
@@ -26,5 +18,17 @@ module RailsMiniProfiler
|
|
26
18
|
initializer 'rails_mini_profiler_add_static assets' do |app|
|
27
19
|
app.middleware.insert_before(ActionDispatch::Static, ActionDispatch::Static, "#{root}/public")
|
28
20
|
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
|
29
33
|
end
|
30
34
|
end
|
@@ -5,7 +5,7 @@ module RailsMiniProfiler
|
|
5
5
|
def initialize(app)
|
6
6
|
@app = app
|
7
7
|
@config = RailsMiniProfiler.configuration
|
8
|
-
|
8
|
+
Tracing::Subscriptions.setup! { |trace| track_trace(trace) }
|
9
9
|
end
|
10
10
|
|
11
11
|
def call(env)
|
@@ -33,8 +33,8 @@ module RailsMiniProfiler
|
|
33
33
|
def track_trace(event)
|
34
34
|
return if traces.nil?
|
35
35
|
|
36
|
-
trace =
|
37
|
-
traces.append(trace)
|
36
|
+
trace = RailsMiniProfiler::Tracing::TraceFactory.create(event)
|
37
|
+
traces.append(trace) unless trace.is_a?(RailsMiniProfiler::Tracing::NullTrace)
|
38
38
|
end
|
39
39
|
|
40
40
|
private
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsMiniProfiler
|
4
|
+
module Tracing
|
5
|
+
class ControllerTracer < Tracer
|
6
|
+
def trace
|
7
|
+
@event[:payload] = @event[:payload]
|
8
|
+
.slice(:view_runtime, :db_runtime)
|
9
|
+
.reject { |_k, v| v.blank? }
|
10
|
+
.transform_values { |value| value&.round(2) }
|
11
|
+
super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsMiniProfiler
|
4
|
+
module Tracing
|
5
|
+
class SequelTracer < Tracer
|
6
|
+
def trace
|
7
|
+
return NullTrace.new if ignore?
|
8
|
+
|
9
|
+
payload = @event[:payload].slice(:name, :sql, :binds, :type_casted_binds)
|
10
|
+
typecasted_binds = payload[:type_casted_binds]
|
11
|
+
# Sometimes, typecasted binds are a proc. Not sure why. In those instances, we extract the typecasted
|
12
|
+
# values from the proc by executing call.
|
13
|
+
typecasted_binds = typecasted_binds.call if typecasted_binds.respond_to?(:call)
|
14
|
+
payload[:binds] = transform_binds(payload[:binds], typecasted_binds)
|
15
|
+
payload.delete(:type_casted_binds)
|
16
|
+
payload.reject { |_k, v| v.blank? }
|
17
|
+
@event[:payload] = payload
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def transform_binds(binds, type_casted_binds)
|
24
|
+
binds.each_with_object([]).with_index do |(binding, object), i|
|
25
|
+
name = binding.name
|
26
|
+
value = type_casted_binds[i]
|
27
|
+
object << { name: name, value: value }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def ignore?
|
32
|
+
payload = @event[:payload]
|
33
|
+
!SqlTracker.new(name: payload[:name], query: payload[:sql]).track?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsMiniProfiler
|
4
|
+
module Tracing
|
5
|
+
class SqlTracker
|
6
|
+
TRACKED_SQL_COMMANDS = %w[SELECT INSERT UPDATE DELETE].freeze
|
7
|
+
UNTRACKED_NAMES = %w[SCHEMA].freeze
|
8
|
+
UNTRACKED_TABLES = %w[
|
9
|
+
SCHEMA_MIGRATIONS
|
10
|
+
SQLITE_MASTER
|
11
|
+
ACTIVE_MONITORING_METRICS
|
12
|
+
SQLITE_TEMP_MASTER
|
13
|
+
SQLITE_VERSION
|
14
|
+
AR_INTERNAL_METADATA
|
15
|
+
].freeze
|
16
|
+
|
17
|
+
def initialize(query:, name:)
|
18
|
+
@query = query.to_s.upcase
|
19
|
+
@name = name.to_s.upcase
|
20
|
+
end
|
21
|
+
|
22
|
+
def track?
|
23
|
+
query.start_with?(*TRACKED_SQL_COMMANDS) &&
|
24
|
+
!name.start_with?(*UNTRACKED_NAMES) &&
|
25
|
+
!untracked_tables?
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
attr_reader :query, :name
|
31
|
+
|
32
|
+
def untracked_tables?
|
33
|
+
UNTRACKED_TABLES.any? { |table| query.include?(table) }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|