rails_mini_profiler 0.7.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/app/controllers/rails_mini_profiler/application_controller.rb +0 -9
- data/app/controllers/rails_mini_profiler/profiled_requests_controller.rb +16 -0
- data/app/models/rails_mini_profiler/profiled_request.rb +1 -1
- data/app/models/rails_mini_profiler/trace.rb +0 -15
- data/app/presenters/rails_mini_profiler/controller_trace_presenter.rb +10 -2
- data/app/presenters/rails_mini_profiler/instantiation_trace_presenter.rb +15 -3
- data/app/presenters/rails_mini_profiler/render_partial_trace_presenter.rb +6 -2
- data/app/presenters/rails_mini_profiler/render_template_trace_presenter.rb +6 -2
- data/app/presenters/rails_mini_profiler/sequel_trace_presenter.rb +16 -4
- data/app/presenters/rails_mini_profiler/trace_presenter.rb +1 -1
- data/app/views/rails_mini_profiler/profiled_requests/show/_trace.html.erb +1 -1
- data/lib/generators/rails_mini_profiler/templates/rails_mini_profiler.rb.erb +1 -1
- data/lib/rails_mini_profiler/badge.rb +20 -11
- data/lib/rails_mini_profiler/configuration/user_interface.rb +10 -2
- data/lib/rails_mini_profiler/configuration.rb +4 -0
- data/lib/rails_mini_profiler/middleware.rb +10 -10
- data/lib/rails_mini_profiler/request_context.rb +22 -18
- data/lib/rails_mini_profiler/request_wrapper.rb +12 -55
- data/lib/rails_mini_profiler/response_wrapper.rb +21 -17
- data/lib/rails_mini_profiler/{tracing → tracers}/controller_tracer.rb +15 -1
- data/lib/rails_mini_profiler/tracers/instantiation_tracer.rb +17 -0
- data/lib/rails_mini_profiler/{tracing → tracers}/null_trace.rb +1 -1
- data/lib/rails_mini_profiler/tracers/registry.rb +76 -0
- data/lib/rails_mini_profiler/tracers/rmp_tracer.rb +17 -0
- data/lib/rails_mini_profiler/{tracing → tracers}/sequel_tracer.rb +15 -1
- data/lib/rails_mini_profiler/{tracing → tracers}/sequel_tracker.rb +4 -1
- data/lib/rails_mini_profiler/{tracing → tracers}/subscriptions.rb +6 -12
- data/lib/rails_mini_profiler/{tracing → tracers}/trace.rb +2 -2
- data/lib/rails_mini_profiler/tracers/trace_factory.rb +27 -0
- data/lib/rails_mini_profiler/{tracing → tracers}/tracer.rb +15 -1
- data/lib/rails_mini_profiler/tracers/view_tracer.rb +29 -0
- data/lib/rails_mini_profiler/tracers.rb +14 -0
- data/lib/rails_mini_profiler/version.rb +1 -1
- data/lib/rails_mini_profiler.rb +1 -1
- metadata +15 -18
- data/app/models/rails_mini_profiler/controller_trace.rb +0 -37
- data/app/models/rails_mini_profiler/instantiation_trace.rb +0 -37
- data/app/models/rails_mini_profiler/render_partial_trace.rb +0 -37
- data/app/models/rails_mini_profiler/render_template_trace.rb +0 -37
- data/app/models/rails_mini_profiler/rmp_trace.rb +0 -35
- data/app/models/rails_mini_profiler/sequel_trace.rb +0 -37
- data/lib/rails_mini_profiler/tracing/trace_factory.rb +0 -37
- data/lib/rails_mini_profiler/tracing/view_tracer.rb +0 -12
- data/lib/rails_mini_profiler/tracing.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '08b93a903a5bb3b16310b3a918a1a52555a9ce5fc2a60624d0f2bb8158e3ddb5'
|
4
|
+
data.tar.gz: 88af5220a54c4f91e4506cd0423a853512dcc67235c65a22990d1c4fc1d92c25
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a41fec13f04188e895769fcb17004fdd6436aaddd8942ff4657beaffb7c0f4b63ca64d60f9877d119c1e363194ebd3c97e629216d0bf675fceb82cd49b6dcda
|
7
|
+
data.tar.gz: f5c81dbc3b627e48a0d9097fb587b37c2c299476adb87d01ace6c697e234b32f8fceee942045656f82f8c4d6ef6c082e58ad2f5619ccf2b4114b32764dae8c8f
|
data/README.md
CHANGED
@@ -153,7 +153,7 @@ Rails Mini Profiler allows you to configure various UI features.
|
|
153
153
|
|---------------------|---------------------------|-------------------------------------------------------------------------------------------------|
|
154
154
|
| `badge_enabled` | `true` | Should the hedgehog 🦔 badge be injected into pages? |
|
155
155
|
| `badge_position` | `'top-left'` | Where to display the badge. Options are `'top-left', 'top-right', 'bottom-left, 'bottom-right'` |
|
156
|
-
| `base_controller` | `ApplicationController`
|
156
|
+
| `base_controller` | `ApplicationController` | Which controller UI controllers should inherit from. |
|
157
157
|
| `page_size` | `25` | The page size for lists shown in the UI. |
|
158
158
|
| `webpacker_enabled` | `true` | Use Webpacker if available? Disable to fall back to the asset pipeline. |
|
159
159
|
|
@@ -6,15 +6,6 @@ module RailsMiniProfiler
|
|
6
6
|
|
7
7
|
before_action :check_rmp_user
|
8
8
|
|
9
|
-
protected
|
10
|
-
|
11
|
-
def present(model, presenter_class = nil, **kwargs)
|
12
|
-
klass = presenter_class || "RailsMiniProfiler::#{model.class.to_s.demodulize}Presenter".constantize
|
13
|
-
presenter = klass.new(model, view_context, **kwargs)
|
14
|
-
yield(presenter) if block_given?
|
15
|
-
presenter
|
16
|
-
end
|
17
|
-
|
18
9
|
private
|
19
10
|
|
20
11
|
def handle(error, status = 500)
|
@@ -67,6 +67,22 @@ module RailsMiniProfiler
|
|
67
67
|
@configuration ||= RailsMiniProfiler.configuration
|
68
68
|
end
|
69
69
|
|
70
|
+
def registry
|
71
|
+
@registry ||= RailsMiniProfiler::Tracers::Registry.new(configuration)
|
72
|
+
end
|
73
|
+
|
74
|
+
def present(model, presenter_class = nil, **kwargs)
|
75
|
+
klass = presenter_class || presenter_class(model)
|
76
|
+
klass.new(model, view_context, **kwargs)
|
77
|
+
end
|
78
|
+
|
79
|
+
def presenter_class(model)
|
80
|
+
return ProfiledRequestPresenter if model.is_a?(ProfiledRequest)
|
81
|
+
|
82
|
+
presenters = registry.presenters
|
83
|
+
presenters[model.name] || TracePresenter
|
84
|
+
end
|
85
|
+
|
70
86
|
def payload_column
|
71
87
|
if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
|
72
88
|
# Cast json field to text to have access to the LIKE operator
|
@@ -43,7 +43,7 @@ module RailsMiniProfiler
|
|
43
43
|
def request=(request)
|
44
44
|
self.request_body = request.body
|
45
45
|
self.request_headers = request.headers
|
46
|
-
self.request_method = request.
|
46
|
+
self.request_method = request.request_method
|
47
47
|
self.request_path = request.path
|
48
48
|
self.request_query_string = request.query_string
|
49
49
|
end
|
@@ -23,24 +23,9 @@
|
|
23
23
|
module RailsMiniProfiler
|
24
24
|
class Trace < RailsMiniProfiler::ApplicationRecord
|
25
25
|
self.table_name = RailsMiniProfiler.storage_configuration.traces_table
|
26
|
-
self.inheritance_column = :name
|
27
26
|
|
28
27
|
belongs_to :profiled_request,
|
29
28
|
class_name: 'RailsMiniProfiler::ProfiledRequest',
|
30
29
|
foreign_key: :rmp_profiled_request_id
|
31
|
-
|
32
|
-
class << self
|
33
|
-
def find_sti_class(name)
|
34
|
-
subclasses = {
|
35
|
-
'process_action.action_controller' => RailsMiniProfiler::ControllerTrace,
|
36
|
-
'sql.active_record' => RailsMiniProfiler::SequelTrace,
|
37
|
-
'instantiation.active_record' => RailsMiniProfiler::InstantiationTrace,
|
38
|
-
'rails_mini_profiler.total_time' => RailsMiniProfiler::RmpTrace,
|
39
|
-
'render_template.action_view' => RailsMiniProfiler::RenderTemplateTrace,
|
40
|
-
'render_partial.action_view' => RailsMiniProfiler::RenderPartialTrace
|
41
|
-
}
|
42
|
-
subclasses[name] || self
|
43
|
-
end
|
44
|
-
end
|
45
30
|
end
|
46
31
|
end
|
@@ -6,10 +6,18 @@ module RailsMiniProfiler
|
|
6
6
|
'Action Controller'
|
7
7
|
end
|
8
8
|
|
9
|
-
def
|
9
|
+
def view_runtime
|
10
|
+
payload['view_runtime']
|
11
|
+
end
|
12
|
+
|
13
|
+
def db_runtime
|
14
|
+
payload['db_runtime']
|
15
|
+
end
|
16
|
+
|
17
|
+
def content
|
10
18
|
content_tag('div') do
|
11
19
|
content_tag('pre', class: 'trace-payload') do
|
12
|
-
content_tag(:div, "View Time: #{
|
20
|
+
content_tag(:div, "View Time: #{view_runtime} ms, DB Time: #{db_runtime} ms",
|
13
21
|
class: 'sequel-trace-query')
|
14
22
|
end
|
15
23
|
end
|
@@ -3,12 +3,24 @@
|
|
3
3
|
module RailsMiniProfiler
|
4
4
|
class InstantiationTracePresenter < TracePresenter
|
5
5
|
def label
|
6
|
-
"#{
|
6
|
+
"#{class_name} Instantiation"
|
7
|
+
end
|
8
|
+
|
9
|
+
def class_name
|
10
|
+
payload['class_name']
|
11
|
+
end
|
12
|
+
|
13
|
+
def record_count
|
14
|
+
payload['record_count']
|
15
|
+
end
|
16
|
+
|
17
|
+
def db_runtime
|
18
|
+
payload['db_runtime']
|
7
19
|
end
|
8
20
|
|
9
21
|
def description
|
10
|
-
record_string = 'Record'.pluralize(
|
11
|
-
"Instantiated #{
|
22
|
+
record_string = 'Record'.pluralize(record_count)
|
23
|
+
"Instantiated #{record_count} #{class_name} #{record_string}"
|
12
24
|
end
|
13
25
|
end
|
14
26
|
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
|
-
|
8
|
-
(root ^
|
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
|
-
|
8
|
-
(root ^
|
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
|
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,
|
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
|
72
|
+
return [] if binds.nil? || binds.empty?
|
61
73
|
|
62
|
-
|
74
|
+
binds.each_with_object({}) do |hash, object|
|
63
75
|
name = hash['name']
|
64
76
|
value = hash['value']
|
65
77
|
object[name] = value
|
@@ -22,7 +22,7 @@ RailsMiniProfiler.configure do |config|
|
|
22
22
|
# Configure the Rails Mini Profiler User Interface
|
23
23
|
# config.ui.badge_enabled = true
|
24
24
|
# config.ui.badge_position = 'top-left'
|
25
|
-
# config.ui.base_controller =
|
25
|
+
# config.ui.base_controller = ApplicationController
|
26
26
|
# config.ui.page_size = 25
|
27
27
|
# config.ui.webpacker_enabled = true
|
28
28
|
|
@@ -23,30 +23,39 @@ module RailsMiniProfiler
|
|
23
23
|
#
|
24
24
|
# @return [ResponseWrapper] The modified response
|
25
25
|
def render
|
26
|
-
|
27
|
-
return @original_response unless content_type =~ %r{text/html}
|
28
|
-
|
29
|
-
return @original_response unless @configuration.ui.badge_enabled
|
26
|
+
return @original_response unless render_badge?
|
30
27
|
|
31
|
-
modified_response =
|
28
|
+
modified_response = ResponseWrapper.new([], @original_response.status, @original_response.headers)
|
32
29
|
modified_response.write(modified_body)
|
33
30
|
modified_response.finish
|
34
31
|
|
35
|
-
|
36
|
-
response.close if response.respond_to?(:close)
|
32
|
+
@original_response.close if @original_response.respond_to?(:close)
|
37
33
|
|
38
|
-
|
39
|
-
@original_response.headers,
|
40
|
-
modified_response)
|
34
|
+
modified_response
|
41
35
|
end
|
42
36
|
|
43
37
|
private
|
44
38
|
|
39
|
+
def render_badge?
|
40
|
+
content_type = @original_response.headers['Content-Type']
|
41
|
+
unless content_type =~ %r{text/html}
|
42
|
+
RailsMiniProfiler.logger.debug("badge not rendered, response has content type #{content_type}")
|
43
|
+
return false
|
44
|
+
end
|
45
|
+
|
46
|
+
unless @configuration.ui.badge_enabled
|
47
|
+
RailsMiniProfiler.logger.debug('badge not rendered, disabled in configuration')
|
48
|
+
return false
|
49
|
+
end
|
50
|
+
|
51
|
+
true
|
52
|
+
end
|
53
|
+
|
45
54
|
# Modify the body of the original response
|
46
55
|
#
|
47
56
|
# @return String The modified body
|
48
57
|
def modified_body
|
49
|
-
body = @original_response.
|
58
|
+
body = @original_response.body
|
50
59
|
index = body.rindex(%r{</body>}i) || body.rindex(%r{</html>}i)
|
51
60
|
if index
|
52
61
|
body.dup.insert(index, badge_content)
|
@@ -35,10 +35,11 @@ module RailsMiniProfiler
|
|
35
35
|
|
36
36
|
attr_accessor :badge_enabled,
|
37
37
|
:badge_position,
|
38
|
-
:base_controller,
|
39
38
|
:page_size,
|
40
39
|
:webpacker_enabled
|
41
40
|
|
41
|
+
attr_writer :base_controller
|
42
|
+
|
42
43
|
def initialize(**kwargs)
|
43
44
|
defaults!
|
44
45
|
kwargs.each { |key, value| instance_variable_set("@#{key}", value) }
|
@@ -48,11 +49,18 @@ module RailsMiniProfiler
|
|
48
49
|
def defaults!
|
49
50
|
@badge_enabled = true
|
50
51
|
@badge_position = 'top-left'
|
51
|
-
|
52
|
+
# We must not set base controller during when the app loads, aka during autoload time, as we are loading
|
53
|
+
# constants. Rather, we only load the base controller constants when any engine controllers are first initialized
|
54
|
+
# and call #base_controller
|
55
|
+
@base_controller = nil
|
52
56
|
@page_size = 25
|
53
57
|
@webpacker_enabled = true
|
54
58
|
end
|
55
59
|
|
60
|
+
def base_controller
|
61
|
+
@base_controller ||= default_base_controller
|
62
|
+
end
|
63
|
+
|
56
64
|
def default_base_controller
|
57
65
|
app_controller_exists = class_exists?('::ApplicationController')
|
58
66
|
return ::ApplicationController if app_controller_exists && ::ApplicationController < ActionController::Base
|
@@ -18,6 +18,8 @@ module RailsMiniProfiler
|
|
18
18
|
# @return [Array<String>] a list of regex patterns for paths to skip
|
19
19
|
# @!attribute storage
|
20
20
|
# @return [Storage] the storage configuration
|
21
|
+
# @!attribute tracers
|
22
|
+
# @return [Array<Symbol>] the list of enabled tracers
|
21
23
|
# @!attribute ui
|
22
24
|
# @return [UserInterface] the ui configuration
|
23
25
|
# @!attribute user_provider
|
@@ -30,6 +32,7 @@ module RailsMiniProfiler
|
|
30
32
|
:flamegraph_sample_rate,
|
31
33
|
:skip_paths,
|
32
34
|
:storage,
|
35
|
+
:tracers,
|
33
36
|
:ui,
|
34
37
|
:user_provider
|
35
38
|
|
@@ -46,6 +49,7 @@ module RailsMiniProfiler
|
|
46
49
|
@logger = RailsMiniProfiler::Logger.new(Rails.logger)
|
47
50
|
@skip_paths = []
|
48
51
|
@storage = Storage.new
|
52
|
+
@tracers = %i[controller instantiation sequel view rmp]
|
49
53
|
@ui = UserInterface.new
|
50
54
|
@user_provider = proc { |env| Rack::Request.new(env).ip }
|
51
55
|
end
|
@@ -5,21 +5,23 @@ module RailsMiniProfiler
|
|
5
5
|
def initialize(app)
|
6
6
|
@app = app
|
7
7
|
@config = RailsMiniProfiler.configuration
|
8
|
-
|
8
|
+
@registry = Tracers::Registry.setup!(@config)
|
9
|
+
Tracers::Subscriptions.setup!(@registry.tracers.keys) { |trace| track_trace(trace) }
|
10
|
+
@trace_factory = Tracers::TraceFactory.new(@registry)
|
9
11
|
end
|
10
12
|
|
11
13
|
def call(env)
|
12
|
-
request = RequestWrapper.new(env
|
14
|
+
request = RequestWrapper.new(env)
|
13
15
|
request_context = RequestContext.new(request)
|
14
16
|
return @app.call(env) unless Guard.new(request_context).profile?
|
15
17
|
|
16
|
-
request_context.profiled_request = ProfiledRequest.new
|
17
18
|
result = with_tracing(request_context) { profile(request_context) }
|
18
19
|
return result unless request_context.authorized?
|
19
20
|
|
20
|
-
|
21
|
+
status, headers, body = result
|
22
|
+
request_context.response = ResponseWrapper.new(body, status, headers)
|
21
23
|
complete!(request_context)
|
22
|
-
request_context.saved? ? render_response(request_context) : result
|
24
|
+
request_context.saved? ? render_response(request_context).to_a : result
|
23
25
|
ensure
|
24
26
|
User.current_user = nil
|
25
27
|
end
|
@@ -35,14 +37,13 @@ module RailsMiniProfiler
|
|
35
37
|
def track_trace(event)
|
36
38
|
return if traces.nil?
|
37
39
|
|
38
|
-
trace =
|
39
|
-
traces.append(trace) unless trace.is_a?(RailsMiniProfiler::
|
40
|
+
trace = @trace_factory.create(event)
|
41
|
+
traces.append(trace) unless trace.is_a?(RailsMiniProfiler::Tracers::NullTrace)
|
40
42
|
end
|
41
43
|
|
42
44
|
private
|
43
45
|
|
44
46
|
def complete!(request_context)
|
45
|
-
request_context.complete_profiling!
|
46
47
|
request_context.save_results!
|
47
48
|
true
|
48
49
|
rescue ActiveRecord::ActiveRecordError => e
|
@@ -54,8 +55,7 @@ module RailsMiniProfiler
|
|
54
55
|
redirect = Redirect.new(request_context).render
|
55
56
|
return redirect if redirect
|
56
57
|
|
57
|
-
|
58
|
-
[modified_response.status, modified_response.headers, modified_response.response]
|
58
|
+
Badge.new(request_context).render
|
59
59
|
end
|
60
60
|
|
61
61
|
def profile(request_context)
|
@@ -10,7 +10,7 @@ module RailsMiniProfiler
|
|
10
10
|
# @return [RequestWrapper] the request as sent to the application
|
11
11
|
# @!attribute response
|
12
12
|
# @return [ResponseWrapper] the response as rendered by the application
|
13
|
-
# @!attribute profiled_request
|
13
|
+
# # @!attribute profiled_request
|
14
14
|
# @return [ProfiledRequest] the profiling data as gathered during profiling
|
15
15
|
# @!attribute traces
|
16
16
|
# @return [Array<Models::Trace>] trace wrappers gathered during profiling
|
@@ -19,8 +19,10 @@ module RailsMiniProfiler
|
|
19
19
|
class RequestContext
|
20
20
|
attr_reader :request
|
21
21
|
|
22
|
-
attr_accessor :response, :
|
22
|
+
attr_accessor :response, :traces, :flamegraph, :profiled_request
|
23
23
|
|
24
|
+
# Create a new request context
|
25
|
+
#
|
24
26
|
# @param request [RequestWrapper] the request as sent to the application
|
25
27
|
def initialize(request)
|
26
28
|
@request = request
|
@@ -36,39 +38,41 @@ module RailsMiniProfiler
|
|
36
38
|
@authorized ||= User.get(@env).present?
|
37
39
|
end
|
38
40
|
|
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
41
|
# Save profiling data in the database.
|
50
42
|
#
|
51
43
|
# This will store the profiled request, as well as any attached traces and Flamgraph.
|
52
44
|
def save_results!
|
53
45
|
ActiveRecord::Base.transaction do
|
46
|
+
profiled_request = build_profiled_request
|
54
47
|
profiled_request.flamegraph = RailsMiniProfiler::Flamegraph.new(data: flamegraph) if flamegraph.present?
|
55
48
|
profiled_request.save
|
56
|
-
insert_traces unless traces.empty?
|
49
|
+
insert_traces(profiled_request) unless traces.empty?
|
50
|
+
@profiled_request = profiled_request
|
57
51
|
end
|
58
52
|
@saved = true
|
59
53
|
end
|
60
54
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
55
|
+
# Check if profiling results have been saved
|
56
|
+
#
|
57
|
+
# @return [Boolean] true if profiling results have been saved
|
65
58
|
def saved?
|
66
59
|
@saved
|
67
60
|
end
|
68
61
|
|
69
62
|
private
|
70
63
|
|
71
|
-
def
|
64
|
+
def build_profiled_request
|
65
|
+
new_profiled_request = ProfiledRequest.new
|
66
|
+
new_profiled_request.user_id = User.current_user
|
67
|
+
new_profiled_request.request = @request
|
68
|
+
new_profiled_request.response = @response
|
69
|
+
total_time = traces.find { |trace| trace.name == 'rails_mini_profiler.total_time' }
|
70
|
+
new_profiled_request.total_time = total_time
|
71
|
+
new_profiled_request
|
72
|
+
end
|
73
|
+
|
74
|
+
# We insert multiple at once for performance reasons.
|
75
|
+
def insert_traces(profiled_request)
|
72
76
|
return if traces.empty?
|
73
77
|
|
74
78
|
timestamp = Time.zone.now
|
@@ -1,69 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module RailsMiniProfiler
|
4
|
-
# A convenience wrapper
|
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
|
4
|
+
# A convenience wrapper extending {Rack::Request}
|
16
5
|
#
|
17
6
|
# @api private
|
18
|
-
class RequestWrapper
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
7
|
+
class RequestWrapper < Rack::Request
|
8
|
+
# Convenience method to read the request body as String
|
9
|
+
#
|
10
|
+
# @return [String] the request body
|
11
|
+
def body
|
12
|
+
return '' unless super
|
24
13
|
|
25
|
-
|
26
|
-
|
27
|
-
|
14
|
+
body = super.read
|
15
|
+
super.rewind
|
16
|
+
body
|
28
17
|
end
|
29
18
|
|
30
19
|
# The request headers
|
31
20
|
#
|
32
|
-
# @return [Hash] the headers
|
21
|
+
# @return [Hash] the request headers
|
33
22
|
def headers
|
34
|
-
|
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
|
23
|
+
env.select { |k, _v| k.start_with? 'HTTP_' } || {}
|
67
24
|
end
|
68
25
|
end
|
69
26
|
end
|
@@ -1,24 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module RailsMiniProfiler
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
4
|
+
# A convenience wrapper extending {Rack::Response}
|
5
|
+
#
|
6
|
+
# @api private
|
7
|
+
class ResponseWrapper < Rack::Response
|
8
|
+
# Return the response body as String
|
9
|
+
#
|
10
|
+
# Depending on preceding middleware, response bodies may be Strings, Arrays or literally anything else. This method
|
11
|
+
# converts whatever it is to a string so we can store it later.
|
12
|
+
#
|
13
|
+
# @return [String] of the response body
|
14
14
|
def body
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
body = super
|
16
|
+
case body
|
17
|
+
when String
|
18
|
+
body
|
19
|
+
when Array
|
20
|
+
body.join
|
21
|
+
when ActionDispatch::Response::RackBody
|
22
|
+
body.body
|
23
|
+
else
|
24
|
+
''
|
25
|
+
end
|
22
26
|
end
|
23
27
|
|
24
28
|
def json?
|
@@ -1,8 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module RailsMiniProfiler
|
4
|
-
module
|
4
|
+
module Tracers
|
5
5
|
class ControllerTracer < Tracer
|
6
|
+
class << self
|
7
|
+
def subscribes_to
|
8
|
+
'process_action.action_controller'
|
9
|
+
end
|
10
|
+
|
11
|
+
def build_from(event)
|
12
|
+
new(event).trace
|
13
|
+
end
|
14
|
+
|
15
|
+
def presents
|
16
|
+
ControllerTracePresenter
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
6
20
|
def trace
|
7
21
|
@event[:payload] = @event[:payload]
|
8
22
|
.slice(:view_runtime, :db_runtime)
|