rails_mini_profiler 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 +7 -0
- data/LICENSE +20 -0
- data/README.md +302 -0
- data/app/assets/config/rails_mini_profiler_manifest.js +1 -0
- data/app/assets/javascripts/rails_mini_profiler.js +15 -0
- data/app/assets/stylesheets/rails_mini_profiler/application.css +16 -0
- data/app/controllers/rails_mini_profiler/application_controller.rb +33 -0
- data/app/controllers/rails_mini_profiler/flamegraphs_controller.rb +23 -0
- data/app/controllers/rails_mini_profiler/profiled_requests_controller.rb +68 -0
- data/app/helpers/rails_mini_profiler/application_helper.rb +23 -0
- data/app/helpers/rails_mini_profiler/profiled_requests_helper.rb +16 -0
- data/app/javascript/images/bookmark.svg +10 -0
- data/app/javascript/images/chart.svg +12 -0
- data/app/javascript/images/check.svg +3 -0
- data/app/javascript/images/chevron.svg +3 -0
- data/app/javascript/images/delete.svg +9 -0
- data/app/javascript/images/filter.svg +1 -0
- data/app/javascript/images/graph.svg +11 -0
- data/app/javascript/images/logo.svg +18 -0
- data/app/javascript/images/logo_variant.svg +32 -0
- data/app/javascript/images/search.svg +9 -0
- data/app/javascript/images/setting.svg +10 -0
- data/app/javascript/images/show.svg +11 -0
- 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 +88 -0
- data/app/javascript/stylesheets/components/page_header/page_header.scss +3 -0
- data/app/javascript/stylesheets/components/pagination.scss +55 -0
- 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 +10 -0
- data/app/javascript/stylesheets/flashes.scss +15 -0
- data/app/javascript/stylesheets/navbar.scss +44 -0
- data/app/javascript/stylesheets/profiled_requests.scss +89 -0
- data/app/javascript/stylesheets/rails-mini-profiler.scss +205 -0
- data/app/javascript/stylesheets/traces.scss +82 -0
- data/app/models/rails_mini_profiler/application_record.rb +17 -0
- data/app/models/rails_mini_profiler/controller_trace.rb +37 -0
- data/app/models/rails_mini_profiler/flamegraph.rb +37 -0
- data/app/models/rails_mini_profiler/instantiation_trace.rb +37 -0
- data/app/models/rails_mini_profiler/profiled_request.rb +65 -0
- data/app/models/rails_mini_profiler/render_partial_trace.rb +37 -0
- data/app/models/rails_mini_profiler/render_template_trace.rb +37 -0
- data/app/models/rails_mini_profiler/rmp_trace.rb +35 -0
- data/app/models/rails_mini_profiler/sequel_trace.rb +37 -0
- data/app/models/rails_mini_profiler/trace.rb +46 -0
- data/app/presenters/rails_mini_profiler/base_presenter.rb +25 -0
- data/app/presenters/rails_mini_profiler/controller_trace_presenter.rb +18 -0
- data/app/presenters/rails_mini_profiler/instantiation_trace_presenter.rb +14 -0
- data/app/presenters/rails_mini_profiler/profiled_request_presenter.rb +38 -0
- data/app/presenters/rails_mini_profiler/render_partial_trace_presenter.rb +11 -0
- data/app/presenters/rails_mini_profiler/render_template_trace_presenter.rb +15 -0
- data/app/presenters/rails_mini_profiler/rmp_trace_presenter.rb +9 -0
- data/app/presenters/rails_mini_profiler/sequel_trace_presenter.rb +69 -0
- data/app/presenters/rails_mini_profiler/trace_presenter.rb +61 -0
- 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/layouts/rails_mini_profiler/application.html.erb +15 -0
- data/app/views/layouts/rails_mini_profiler/flamegraph.html.erb +11 -0
- data/app/views/models/_flamegraph.json.jb +3 -0
- data/app/views/models/_profiled_request.jb +3 -0
- data/app/views/models/_trace.jb +3 -0
- data/app/views/rails_mini_profiler/badge.html.erb +37 -0
- data/app/views/rails_mini_profiler/flamegraphs/show.html.erb +13 -0
- data/app/views/rails_mini_profiler/flamegraphs/show.json.jb +3 -0
- data/app/views/rails_mini_profiler/profiled_requests/index.html.erb +9 -0
- data/app/views/rails_mini_profiler/profiled_requests/index.json.jb +3 -0
- data/app/views/rails_mini_profiler/profiled_requests/shared/_trace.html.erb +40 -0
- 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 +40 -0
- data/app/views/rails_mini_profiler/profiled_requests/show.json.jb +5 -0
- data/app/views/rails_mini_profiler/shared/_flashes.html.erb +8 -0
- data/app/views/rails_mini_profiler/shared/_head.erb +13 -0
- data/app/views/rails_mini_profiler/shared/_navbar.html.erb +15 -0
- data/config/routes.rb +11 -0
- data/db/migrate/20210621185018_create_rmp.rb +46 -0
- data/lib/generators/rails_mini_profiler/USAGE +2 -0
- data/lib/generators/rails_mini_profiler/install_generator.rb +40 -0
- data/lib/generators/rails_mini_profiler/templates/rails_mini_profiler.js.erb +13 -0
- data/lib/generators/rails_mini_profiler/templates/rails_mini_profiler.rb.erb +29 -0
- data/lib/rails_mini_profiler/badge.rb +84 -0
- data/lib/rails_mini_profiler/configuration/storage.rb +47 -0
- data/lib/rails_mini_profiler/configuration/user_interface.rb +48 -0
- data/lib/rails_mini_profiler/configuration.rb +65 -0
- data/lib/rails_mini_profiler/engine.rb +34 -0
- data/lib/rails_mini_profiler/flamegraph_guard.rb +47 -0
- data/lib/rails_mini_profiler/guard.rb +57 -0
- data/lib/rails_mini_profiler/logger.rb +25 -0
- data/lib/rails_mini_profiler/middleware.rb +74 -0
- data/lib/rails_mini_profiler/models/base_model.rb +23 -0
- data/lib/rails_mini_profiler/redirect.rb +33 -0
- data/lib/rails_mini_profiler/request_context.rb +86 -0
- data/lib/rails_mini_profiler/request_wrapper.rb +69 -0
- data/lib/rails_mini_profiler/response_wrapper.rb +32 -0
- 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/tracing/trace.rb +45 -0
- 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/user.rb +40 -0
- data/lib/rails_mini_profiler/version.rb +5 -0
- data/lib/rails_mini_profiler.rb +79 -0
- data/lib/tasks/rails_mini_profiler_tasks.rake +8 -0
- data/public/rails_mini_profiler/speedscope/LICENSE +21 -0
- data/public/rails_mini_profiler/speedscope/demangle-cpp.1768f4cc.js +4 -0
- data/public/rails_mini_profiler/speedscope/demangle-cpp.1768f4cc.js.map +1 -0
- data/public/rails_mini_profiler/speedscope/favicon-16x16.f74b3187.png +0 -0
- data/public/rails_mini_profiler/speedscope/favicon-32x32.bc503437.png +0 -0
- data/public/rails_mini_profiler/speedscope/file-format-schema.json +324 -0
- data/public/rails_mini_profiler/speedscope/import.e3a73ef4.js +117 -0
- data/public/rails_mini_profiler/speedscope/import.e3a73ef4.js.map +1 -0
- data/public/rails_mini_profiler/speedscope/index.html +2 -0
- data/public/rails_mini_profiler/speedscope/release.txt +3 -0
- data/public/rails_mini_profiler/speedscope/reset.8c46b7a1.css +2 -0
- data/public/rails_mini_profiler/speedscope/reset.8c46b7a1.css.map +1 -0
- data/public/rails_mini_profiler/speedscope/source-map.438fa06b.js +24 -0
- data/public/rails_mini_profiler/speedscope/source-map.438fa06b.js.map +1 -0
- data/public/rails_mini_profiler/speedscope/speedscope.026f36b0.js +200 -0
- data/public/rails_mini_profiler/speedscope/speedscope.026f36b0.js.map +1 -0
- data/vendor/assets/images/bookmark.svg +10 -0
- data/vendor/assets/images/chart.svg +12 -0
- data/vendor/assets/images/check.svg +3 -0
- data/vendor/assets/images/chevron.svg +3 -0
- data/vendor/assets/images/delete.svg +9 -0
- data/vendor/assets/images/filter.svg +1 -0
- data/vendor/assets/images/graph.svg +11 -0
- data/vendor/assets/images/logo.svg +18 -0
- data/vendor/assets/images/logo_variant.svg +32 -0
- data/vendor/assets/images/search.svg +9 -0
- data/vendor/assets/images/setting.svg +10 -0
- data/vendor/assets/images/show.svg +11 -0
- data/vendor/assets/javascripts/rails-mini-profiler.css +1 -0
- data/vendor/assets/javascripts/rails-mini-profiler.js +1 -0
- metadata +248 -0
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsMiniProfiler
|
4
|
+
class Middleware
|
5
|
+
def initialize(app)
|
6
|
+
@app = app
|
7
|
+
@config = RailsMiniProfiler.configuration
|
8
|
+
Tracing::Subscriptions.setup! { |trace| track_trace(trace) }
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
request = RequestWrapper.new(env: env)
|
13
|
+
request_context = RequestContext.new(request)
|
14
|
+
return @app.call(env) unless Guard.new(request_context).profile?
|
15
|
+
|
16
|
+
request_context.profiled_request = ProfiledRequest.new
|
17
|
+
result = with_tracing(request_context) { profile(request_context) }
|
18
|
+
return result unless request_context.authorized?
|
19
|
+
|
20
|
+
request_context.response = ResponseWrapper.new(*result)
|
21
|
+
complete!(request_context)
|
22
|
+
request_context.saved? ? render_response(request_context) : result
|
23
|
+
end
|
24
|
+
|
25
|
+
def traces
|
26
|
+
Thread.current[:rails_mini_profiler_traces]
|
27
|
+
end
|
28
|
+
|
29
|
+
def traces=(traces)
|
30
|
+
Thread.current[:rails_mini_profiler_traces] = traces
|
31
|
+
end
|
32
|
+
|
33
|
+
def track_trace(event)
|
34
|
+
return if traces.nil?
|
35
|
+
|
36
|
+
trace = RailsMiniProfiler::Tracing::TraceFactory.create(event)
|
37
|
+
traces.append(trace) unless trace.is_a?(RailsMiniProfiler::Tracing::NullTrace)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def complete!(request_context)
|
43
|
+
request_context.complete_profiling!
|
44
|
+
request_context.save_results!
|
45
|
+
true
|
46
|
+
rescue ActiveRecord::ActiveRecordError => e
|
47
|
+
RailsMiniProfiler.logger.error("Could not save profile: #{e}")
|
48
|
+
false
|
49
|
+
end
|
50
|
+
|
51
|
+
def render_response(request_context)
|
52
|
+
redirect = Redirect.new(request_context).render
|
53
|
+
return redirect if redirect
|
54
|
+
|
55
|
+
modified_response = Badge.new(request_context).render
|
56
|
+
[modified_response.status, modified_response.headers, modified_response.response]
|
57
|
+
end
|
58
|
+
|
59
|
+
def profile(request_context)
|
60
|
+
ActiveSupport::Notifications.instrument('rails_mini_profiler.total_time') do
|
61
|
+
request = request_context.request
|
62
|
+
FlamegraphGuard.new(request_context).record { @app.call(request.env) }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def with_tracing(request_context)
|
67
|
+
self.traces = []
|
68
|
+
result = yield
|
69
|
+
request_context.traces = traces
|
70
|
+
self.traces = nil
|
71
|
+
result
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsMiniProfiler
|
4
|
+
# Thin wrappers around request/response classes
|
5
|
+
#
|
6
|
+
# @api private
|
7
|
+
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
|
+
class BaseModel
|
11
|
+
include ActiveModel::Model
|
12
|
+
|
13
|
+
def initialize(*_args, **attributes)
|
14
|
+
super(attributes)
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_h
|
18
|
+
instance_variables
|
19
|
+
.each_with_object({}) { |var, hash| hash[var.to_s.delete('@')] = instance_variable_get(var) }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsMiniProfiler
|
4
|
+
# Renders a redirect response if the user should be redirected from the original request
|
5
|
+
class Redirect
|
6
|
+
include Engine.routes.url_helpers
|
7
|
+
|
8
|
+
# @param request_context [RequestContext] the current request context
|
9
|
+
def initialize(request_context)
|
10
|
+
@request = request_context.request
|
11
|
+
@profiled_request = request_context.profiled_request
|
12
|
+
end
|
13
|
+
|
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
|
+
def render
|
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].present?
|
23
|
+
|
24
|
+
false
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def redirect_to(location)
|
30
|
+
[302, { 'Location' => location, 'Content-Type' => 'text/html' }, ['Moved Temporarily']]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
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
|
+
class RequestContext
|
20
|
+
attr_reader :request
|
21
|
+
|
22
|
+
attr_accessor :response, :profiled_request, :traces, :flamegraph
|
23
|
+
|
24
|
+
# @param request [RequestWrapper] the request as sent to the application
|
25
|
+
def initialize(request)
|
26
|
+
@request = request
|
27
|
+
@env = request.env
|
28
|
+
@saved = false
|
29
|
+
@complete = false
|
30
|
+
end
|
31
|
+
|
32
|
+
# If a user is currently authorized
|
33
|
+
#
|
34
|
+
# @return [Boolean] true if the user is authorized
|
35
|
+
def authorized?
|
36
|
+
@authorized ||= User.get(@env).present?
|
37
|
+
end
|
38
|
+
|
39
|
+
# Completes profiling, setting all data and preparing for saving it.
|
40
|
+
def complete_profiling!
|
41
|
+
profiled_request.user_id = User.current_user
|
42
|
+
profiled_request.request = @request
|
43
|
+
profiled_request.response = @response
|
44
|
+
total_time = traces.find { |trace| trace.name == 'rails_mini_profiler.total_time' }
|
45
|
+
profiled_request.total_time = total_time
|
46
|
+
@complete = true
|
47
|
+
end
|
48
|
+
|
49
|
+
# Save profiling data in the database.
|
50
|
+
#
|
51
|
+
# This will store the profiled request, as well as any attached traces and Flamgraph.
|
52
|
+
def save_results!
|
53
|
+
ActiveRecord::Base.transaction do
|
54
|
+
profiled_request.flamegraph = RailsMiniProfiler::Flamegraph.new(data: flamegraph) if flamegraph.present?
|
55
|
+
profiled_request.save
|
56
|
+
insert_traces unless traces.empty?
|
57
|
+
end
|
58
|
+
@saved = true
|
59
|
+
end
|
60
|
+
|
61
|
+
def complete?
|
62
|
+
@complete
|
63
|
+
end
|
64
|
+
|
65
|
+
def saved?
|
66
|
+
@saved
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def insert_traces
|
72
|
+
return if traces.empty?
|
73
|
+
|
74
|
+
timestamp = Time.zone.now
|
75
|
+
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
|
+
}
|
82
|
+
end
|
83
|
+
RailsMiniProfiler::Trace.insert_all(inserts)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
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
|
18
|
+
class RequestWrapper
|
19
|
+
attr_reader :body,
|
20
|
+
:method,
|
21
|
+
:path,
|
22
|
+
:query_string,
|
23
|
+
:env
|
24
|
+
|
25
|
+
def initialize(*_args, **attributes)
|
26
|
+
@attributes = attributes
|
27
|
+
setup
|
28
|
+
end
|
29
|
+
|
30
|
+
# The request headers
|
31
|
+
#
|
32
|
+
# @return [Hash] the headers
|
33
|
+
def headers
|
34
|
+
@attributes[:headers] || @env.select { |k, _v| k.start_with? 'HTTP_' } || {}
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
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
|
+
|
62
|
+
return '' unless @env['rack.input']
|
63
|
+
|
64
|
+
body = @env['rack.input'].read
|
65
|
+
@env['rack.input'].rewind
|
66
|
+
body
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsMiniProfiler
|
4
|
+
class ResponseWrapper
|
5
|
+
attr_reader :response, :rack_response
|
6
|
+
|
7
|
+
delegate :status, :headers, to: :rack_response
|
8
|
+
|
9
|
+
def initialize(status, headers, response)
|
10
|
+
@rack_response = Rack::Response.new(response, status, headers)
|
11
|
+
@response = response
|
12
|
+
end
|
13
|
+
|
14
|
+
def body
|
15
|
+
return '' unless json? || xml?
|
16
|
+
|
17
|
+
response&.body || ''
|
18
|
+
end
|
19
|
+
|
20
|
+
def media_type
|
21
|
+
@media_type ||= @rack_response.media_type
|
22
|
+
end
|
23
|
+
|
24
|
+
def json?
|
25
|
+
media_type =~ %r{application/json}
|
26
|
+
end
|
27
|
+
|
28
|
+
def xml?
|
29
|
+
media_type =~ %r{application/xml}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -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
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsMiniProfiler
|
4
|
+
module Tracing
|
5
|
+
class Subscriptions
|
6
|
+
DEFAULT_SUBSCRIPTIONS = %w[
|
7
|
+
sql.active_record
|
8
|
+
instantiation.active_record
|
9
|
+
render_template.action_view
|
10
|
+
render_partial.action_view
|
11
|
+
process_action.action_controller
|
12
|
+
rails_mini_profiler.total_time
|
13
|
+
].freeze
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def setup!(&callback)
|
17
|
+
DEFAULT_SUBSCRIPTIONS.each do |event|
|
18
|
+
subscribe(event, &callback)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def subscribe(*subscriptions, &callback)
|
25
|
+
subscriptions.each do |subscription|
|
26
|
+
ActiveSupport::Notifications.subscribe(subscription) do |event|
|
27
|
+
callback.call(event)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|