rack-mini-profiler 3.3.0 → 4.0.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/CHANGELOG.md +17 -0
- data/README.md +18 -3
- data/lib/html/includes.css +45 -11
- data/lib/html/includes.js +8 -3
- data/lib/html/includes.scss +73 -17
- data/lib/html/includes.tmpl +51 -29
- data/lib/html/vendor.js +2 -2
- data/lib/mini_profiler/actions.rb +10 -5
- data/lib/mini_profiler/asset_version.rb +1 -1
- data/lib/mini_profiler/config.rb +2 -0
- data/lib/mini_profiler/profiling_methods.rb +3 -2
- data/lib/mini_profiler/snapshots_transporter.rb +2 -0
- data/lib/mini_profiler/storage/file_store.rb +0 -2
- data/lib/mini_profiler/storage/memcache_store.rb +1 -1
- data/lib/mini_profiler/timer_struct/base.rb +0 -1
- data/lib/mini_profiler/timer_struct/page.rb +11 -3
- data/lib/mini_profiler/timer_struct/request.rb +3 -2
- data/lib/mini_profiler/timer_struct/sql.rb +4 -1
- data/lib/mini_profiler/version.rb +2 -2
- data/lib/mini_profiler/views.rb +10 -5
- data/lib/mini_profiler.rb +10 -5
- data/lib/mini_profiler_rails/railtie.rb +2 -1
- data/lib/patches/db/pg/alias_method.rb +121 -0
- data/lib/patches/db/pg/prepend.rb +115 -0
- data/lib/patches/db/pg.rb +4 -119
- data/lib/prepend_pg_patch.rb +5 -0
- data/rack-mini-profiler.gemspec +3 -3
- metadata +11 -11
@@ -4,7 +4,7 @@ module Rack
|
|
4
4
|
class MiniProfiler
|
5
5
|
module ProfilingMethods
|
6
6
|
|
7
|
-
def record_sql(query, elapsed_ms, params = nil)
|
7
|
+
def record_sql(query, elapsed_ms, params = nil, cached = nil)
|
8
8
|
return unless current && current.current_timer
|
9
9
|
c = current
|
10
10
|
c.current_timer.add_sql(
|
@@ -13,7 +13,8 @@ module Rack
|
|
13
13
|
c.page_struct,
|
14
14
|
redact_sql_queries? ? nil : params,
|
15
15
|
c.skip_backtrace,
|
16
|
-
c.full_backtrace
|
16
|
+
c.full_backtrace,
|
17
|
+
cached
|
17
18
|
)
|
18
19
|
end
|
19
20
|
|
@@ -9,9 +9,11 @@ class ::Rack::MiniProfiler::SnapshotsTransporter
|
|
9
9
|
def transported_snapshots_count
|
10
10
|
@@transported_snapshots_count
|
11
11
|
end
|
12
|
+
|
12
13
|
def successful_http_requests_count
|
13
14
|
@@successful_http_requests_count
|
14
15
|
end
|
16
|
+
|
15
17
|
def failed_http_requests_count
|
16
18
|
@@failed_http_requests_count
|
17
19
|
end
|
@@ -42,7 +42,7 @@ module Rack
|
|
42
42
|
@client.add("#{@prefix}-#{user}-v", [], @expires_in_seconds)
|
43
43
|
MAX_RETRIES.times do
|
44
44
|
break if @client.cas("#{@prefix}-#{user}-v", @expires_in_seconds) do |ids|
|
45
|
-
ids << id
|
45
|
+
ids << id if !ids.include?(id)
|
46
46
|
ids
|
47
47
|
end
|
48
48
|
end
|
@@ -59,13 +59,12 @@ module Rack
|
|
59
59
|
|
60
60
|
def initialize(env)
|
61
61
|
timer_id = MiniProfiler.generate_id
|
62
|
-
page_name = env['PATH_INFO']
|
63
62
|
started_at = (Time.now.to_f * 1000).to_i
|
64
63
|
started = (Process.clock_gettime(Process::CLOCK_MONOTONIC) * 1000).to_i
|
65
64
|
machine_name = env['SERVER_NAME']
|
66
65
|
super(
|
67
66
|
id: timer_id,
|
68
|
-
name: page_name,
|
67
|
+
name: page_name(env),
|
69
68
|
started: started,
|
70
69
|
started_at: started_at,
|
71
70
|
machine_name: machine_name,
|
@@ -79,6 +78,7 @@ module Rack
|
|
79
78
|
trivial_duration_threshold_milliseconds: 2,
|
80
79
|
head: nil,
|
81
80
|
sql_count: 0,
|
81
|
+
cached_sql_count: 0,
|
82
82
|
duration_milliseconds_in_sql: 0,
|
83
83
|
has_sql_timings: true,
|
84
84
|
has_duplicate_sql_timings: false,
|
@@ -93,7 +93,7 @@ module Rack
|
|
93
93
|
)
|
94
94
|
self[:request_method] = env['REQUEST_METHOD']
|
95
95
|
self[:request_path] = env['PATH_INFO']
|
96
|
-
name = "#{env['REQUEST_METHOD']} http://#{env['SERVER_NAME']}:#{env['SERVER_PORT']}#{env['SCRIPT_NAME']}#{env
|
96
|
+
name = "#{env['REQUEST_METHOD']} http://#{env['SERVER_NAME']}:#{env['SERVER_PORT']}#{env['SCRIPT_NAME']}#{page_name(env)}"
|
97
97
|
self[:root] = TimerStruct::Request.createRoot(name, self)
|
98
98
|
end
|
99
99
|
|
@@ -101,6 +101,14 @@ module Rack
|
|
101
101
|
@attributes[:name]
|
102
102
|
end
|
103
103
|
|
104
|
+
def page_name(env)
|
105
|
+
if env['QUERY_STRING'] && env['QUERY_STRING'] != ""
|
106
|
+
env['PATH_INFO'] + "?" + env['QUERY_STRING']
|
107
|
+
else
|
108
|
+
env['PATH_INFO']
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
104
112
|
def duration_ms
|
105
113
|
@attributes[:root][:duration_milliseconds]
|
106
114
|
end
|
@@ -101,14 +101,15 @@ module Rack
|
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
|
-
def add_sql(query, elapsed_ms, page, params = nil, skip_backtrace = false, full_backtrace = false)
|
105
|
-
TimerStruct::Sql.new(query, elapsed_ms, page, self, params, skip_backtrace, full_backtrace).tap do |timer|
|
104
|
+
def add_sql(query, elapsed_ms, page, params = nil, skip_backtrace = false, full_backtrace = false, cached = false)
|
105
|
+
TimerStruct::Sql.new(query, elapsed_ms, page, self, params, skip_backtrace, full_backtrace, cached).tap do |timer|
|
106
106
|
self[:sql_timings].push(timer)
|
107
107
|
timer[:parent_timing_id] = self[:id]
|
108
108
|
self[:has_sql_timings] = true
|
109
109
|
self[:sql_timings_duration_milliseconds] += elapsed_ms
|
110
110
|
page[:duration_milliseconds_in_sql] += elapsed_ms
|
111
111
|
page[:sql_count] += 1
|
112
|
+
page[:cached_sql_count] += 1 if cached
|
112
113
|
end
|
113
114
|
end
|
114
115
|
|
@@ -10,7 +10,7 @@ module Rack
|
|
10
10
|
class Sql < TimerStruct::Base
|
11
11
|
attr_accessor :parent
|
12
12
|
|
13
|
-
def initialize(query, duration_ms, page, parent, params = nil, skip_backtrace = false, full_backtrace = false)
|
13
|
+
def initialize(query, duration_ms, page, parent, params = nil, skip_backtrace = false, full_backtrace = false, cached = false)
|
14
14
|
|
15
15
|
stack_trace = nil
|
16
16
|
unless skip_backtrace || duration_ms < Rack::MiniProfiler.config.backtrace_threshold_ms
|
@@ -46,7 +46,10 @@ module Rack
|
|
46
46
|
duration_milliseconds: duration_ms,
|
47
47
|
first_fetch_duration_milliseconds: duration_ms,
|
48
48
|
parameters: query ? trim_binds(params) : nil,
|
49
|
+
row_count: 0,
|
50
|
+
class_name: nil,
|
49
51
|
parent_timing_id: nil,
|
52
|
+
cached: cached,
|
50
53
|
is_duplicate: false
|
51
54
|
)
|
52
55
|
end
|
data/lib/mini_profiler/views.rb
CHANGED
@@ -28,7 +28,7 @@ module Rack
|
|
28
28
|
# Use it when:
|
29
29
|
# * you have disabled auto append behaviour throught :auto_inject => false flag
|
30
30
|
# * you do not want script to be automatically appended for the current page. You can also call cancel_auto_inject
|
31
|
-
def get_profile_script(env)
|
31
|
+
def get_profile_script(env, response_headers = {})
|
32
32
|
path = public_base_path(env)
|
33
33
|
version = MiniProfiler::ASSET_VERSION
|
34
34
|
if @config.assets_url
|
@@ -39,7 +39,12 @@ module Rack
|
|
39
39
|
url = "#{path}includes.js?v=#{version}" if !url
|
40
40
|
css_url = "#{path}includes.css?v=#{version}" if !css_url
|
41
41
|
|
42
|
-
|
42
|
+
configured_nonce = @config.content_security_policy_nonce
|
43
|
+
if configured_nonce && !configured_nonce.is_a?(String)
|
44
|
+
configured_nonce = configured_nonce.call(env, response_headers)
|
45
|
+
end
|
46
|
+
|
47
|
+
content_security_policy_nonce = configured_nonce ||
|
43
48
|
env["action_dispatch.content_security_policy_nonce"] ||
|
44
49
|
env["secure_headers_content_security_policy_nonce"]
|
45
50
|
|
@@ -77,7 +82,7 @@ module Rack
|
|
77
82
|
script = ::File.read(::File.expand_path('../html/profile_handler.js', ::File.dirname(__FILE__)))
|
78
83
|
# replace the variables
|
79
84
|
settings.each do |k, v|
|
80
|
-
regex = Regexp.new("\\{#{k
|
85
|
+
regex = Regexp.new("\\{#{k}\\}")
|
81
86
|
script.gsub!(regex, v.to_s)
|
82
87
|
end
|
83
88
|
|
@@ -105,7 +110,7 @@ module Rack
|
|
105
110
|
end
|
106
111
|
|
107
112
|
def flamegraph(graph, path, env)
|
108
|
-
headers = { '
|
113
|
+
headers = { 'content-type' => 'text/html' }
|
109
114
|
iframe_src = "#{public_base_path(env)}speedscope/index.html"
|
110
115
|
html = <<~HTML
|
111
116
|
<!DOCTYPE html>
|
@@ -136,7 +141,7 @@ module Rack
|
|
136
141
|
end
|
137
142
|
|
138
143
|
def help(client_settings, env)
|
139
|
-
headers = { '
|
144
|
+
headers = { 'content-type' => 'text/html' }
|
140
145
|
html = <<~HTML
|
141
146
|
<!DOCTYPE html>
|
142
147
|
<html>
|
data/lib/mini_profiler.rb
CHANGED
@@ -296,8 +296,8 @@ module Rack
|
|
296
296
|
|
297
297
|
mode_match_data = action_parameters(env)['flamegraph_mode']
|
298
298
|
|
299
|
-
if mode_match_data && [:cpu, :wall, :object, :custom].include?(mode_match_data
|
300
|
-
mode = mode_match_data
|
299
|
+
if mode_match_data && [:cpu, :wall, :object, :custom].include?(mode_match_data.to_sym)
|
300
|
+
mode = mode_match_data.to_sym
|
301
301
|
else
|
302
302
|
mode = config.flamegraph_mode
|
303
303
|
end
|
@@ -329,7 +329,7 @@ module Rack
|
|
329
329
|
)
|
330
330
|
end
|
331
331
|
elsif path == '/rack-mini-profiler/requests'
|
332
|
-
status, headers, body = [200, { 'Content-Type' => 'text/html' }, [blank_page_html]]
|
332
|
+
status, headers, body = [200, { 'Content-Type' => 'text/html' }, [blank_page_html.dup]] # important to dup here!
|
333
333
|
else
|
334
334
|
status, headers, body = @app.call(env)
|
335
335
|
end
|
@@ -417,7 +417,7 @@ module Rack
|
|
417
417
|
end
|
418
418
|
|
419
419
|
def action_parameters(env)
|
420
|
-
|
420
|
+
Rack::Utils.parse_nested_query(env['QUERY_STRING'])
|
421
421
|
end
|
422
422
|
|
423
423
|
def inject_profiler(env, status, headers, body)
|
@@ -436,11 +436,12 @@ module Rack
|
|
436
436
|
# inject header
|
437
437
|
if headers.is_a? Hash
|
438
438
|
headers['X-MiniProfiler-Ids'] = ids_comma_separated(env)
|
439
|
+
headers['X-MiniProfiler-Flamegraph-Path'] = flamegraph_path(env) if current.page_struct[:has_flamegraph]
|
439
440
|
end
|
440
441
|
|
441
442
|
if current.inject_js && content_type =~ /text\/html/
|
442
443
|
response = Rack::Response.new([], status, headers)
|
443
|
-
script = self.get_profile_script(env)
|
444
|
+
script = self.get_profile_script(env, headers)
|
444
445
|
|
445
446
|
if String === body
|
446
447
|
response.write inject(body, script)
|
@@ -605,6 +606,10 @@ module Rack
|
|
605
606
|
ids(env).join(",")
|
606
607
|
end
|
607
608
|
|
609
|
+
def flamegraph_path(env)
|
610
|
+
@config.base_url_path + 'flamegraph?id=' + current.page_struct[:id]
|
611
|
+
end
|
612
|
+
|
608
613
|
# cancels automatic injection of profile script for the current page
|
609
614
|
def cancel_auto_inject(env)
|
610
615
|
current.inject_js = false
|
@@ -111,7 +111,8 @@ module Rack::MiniProfilerRails
|
|
111
111
|
Rack::MiniProfiler.record_sql(
|
112
112
|
payload[:sql],
|
113
113
|
(finish - start) * 1000,
|
114
|
-
Rack::MiniProfiler.binds_to_params(payload[:binds])
|
114
|
+
Rack::MiniProfiler.binds_to_params(payload[:binds]),
|
115
|
+
payload[:cached]
|
115
116
|
)
|
116
117
|
end
|
117
118
|
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class PG::Result
|
4
|
+
alias_method :each_without_profiling, :each
|
5
|
+
alias_method :values_without_profiling, :values
|
6
|
+
|
7
|
+
def values(*args, &blk)
|
8
|
+
return values_without_profiling(*args, &blk) unless defined?(@miniprofiler_sql_id)
|
9
|
+
mp_report_sql do
|
10
|
+
values_without_profiling(*args , &blk)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def each(*args, &blk)
|
15
|
+
return each_without_profiling(*args, &blk) unless defined?(@miniprofiler_sql_id)
|
16
|
+
mp_report_sql do
|
17
|
+
each_without_profiling(*args, &blk)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def mp_report_sql(&block)
|
22
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
23
|
+
result = yield
|
24
|
+
elapsed_time = SqlPatches.elapsed_time(start)
|
25
|
+
@miniprofiler_sql_id.report_reader_duration(elapsed_time)
|
26
|
+
result
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class PG::Connection
|
31
|
+
alias_method :exec_without_profiling, :exec
|
32
|
+
alias_method :async_exec_without_profiling, :async_exec
|
33
|
+
alias_method :exec_prepared_without_profiling, :exec_prepared
|
34
|
+
alias_method :send_query_prepared_without_profiling, :send_query_prepared
|
35
|
+
alias_method :prepare_without_profiling, :prepare
|
36
|
+
|
37
|
+
if Gem::Version.new(PG::VERSION) >= Gem::Version.new("1.1.0")
|
38
|
+
alias_method :exec_params_without_profiling, :exec_params
|
39
|
+
end
|
40
|
+
|
41
|
+
def prepare(*args, &blk)
|
42
|
+
# we have no choice but to do this here,
|
43
|
+
# if we do the check for profiling first, our cache may miss critical stuff
|
44
|
+
|
45
|
+
@prepare_map ||= {}
|
46
|
+
@prepare_map[args[0]] = args[1]
|
47
|
+
# dont leak more than 10k ever
|
48
|
+
@prepare_map = {} if @prepare_map.length > 1000
|
49
|
+
|
50
|
+
return prepare_without_profiling(*args, &blk) unless SqlPatches.should_measure?
|
51
|
+
prepare_without_profiling(*args, &blk)
|
52
|
+
end
|
53
|
+
|
54
|
+
def exec(*args, &blk)
|
55
|
+
return exec_without_profiling(*args, &blk) unless SqlPatches.should_measure?
|
56
|
+
|
57
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
58
|
+
result = exec_without_profiling(*args, &blk)
|
59
|
+
elapsed_time = SqlPatches.elapsed_time(start)
|
60
|
+
record = ::Rack::MiniProfiler.record_sql(args[0], elapsed_time)
|
61
|
+
result.instance_variable_set("@miniprofiler_sql_id", record) if result
|
62
|
+
|
63
|
+
result
|
64
|
+
end
|
65
|
+
|
66
|
+
if Gem::Version.new(PG::VERSION) >= Gem::Version.new("1.1.0")
|
67
|
+
def exec_params(*args, &blk)
|
68
|
+
return exec_params_without_profiling(*args, &blk) unless SqlPatches.should_measure?
|
69
|
+
|
70
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
71
|
+
result = exec_params_without_profiling(*args, &blk)
|
72
|
+
elapsed_time = SqlPatches.elapsed_time(start)
|
73
|
+
record = ::Rack::MiniProfiler.record_sql(args[0], elapsed_time)
|
74
|
+
result.instance_variable_set("@miniprofiler_sql_id", record) if result
|
75
|
+
|
76
|
+
result
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def exec_prepared(*args, &blk)
|
81
|
+
return exec_prepared_without_profiling(*args, &blk) unless SqlPatches.should_measure?
|
82
|
+
|
83
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
84
|
+
result = exec_prepared_without_profiling(*args, &blk)
|
85
|
+
elapsed_time = SqlPatches.elapsed_time(start)
|
86
|
+
mapped = args[0]
|
87
|
+
mapped = @prepare_map[mapped] || args[0] if @prepare_map
|
88
|
+
record = ::Rack::MiniProfiler.record_sql(mapped, elapsed_time)
|
89
|
+
result.instance_variable_set("@miniprofiler_sql_id", record) if result
|
90
|
+
|
91
|
+
result
|
92
|
+
end
|
93
|
+
|
94
|
+
def send_query_prepared(*args, &blk)
|
95
|
+
return send_query_prepared_without_profiling(*args, &blk) unless SqlPatches.should_measure?
|
96
|
+
|
97
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
98
|
+
result = send_query_prepared_without_profiling(*args, &blk)
|
99
|
+
elapsed_time = SqlPatches.elapsed_time(start)
|
100
|
+
mapped = args[0]
|
101
|
+
mapped = @prepare_map[mapped] || args[0] if @prepare_map
|
102
|
+
record = ::Rack::MiniProfiler.record_sql(mapped, elapsed_time)
|
103
|
+
result.instance_variable_set("@miniprofiler_sql_id", record) if result
|
104
|
+
|
105
|
+
result
|
106
|
+
end
|
107
|
+
|
108
|
+
def async_exec(*args, &blk)
|
109
|
+
return async_exec_without_profiling(*args, &blk) unless SqlPatches.should_measure?
|
110
|
+
|
111
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
112
|
+
result = exec_without_profiling(*args, &blk)
|
113
|
+
elapsed_time = SqlPatches.elapsed_time(start)
|
114
|
+
record = ::Rack::MiniProfiler.record_sql(args[0], elapsed_time)
|
115
|
+
result.instance_variable_set("@miniprofiler_sql_id", record) if result
|
116
|
+
|
117
|
+
result
|
118
|
+
end
|
119
|
+
|
120
|
+
alias_method :query, :exec
|
121
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class PG::Result
|
4
|
+
module MiniProfiler
|
5
|
+
def values(*args, &blk)
|
6
|
+
return super unless defined?(@miniprofiler_sql_id)
|
7
|
+
mp_report_sql do
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def each(*args, &blk)
|
13
|
+
return super unless defined?(@miniprofiler_sql_id)
|
14
|
+
mp_report_sql do
|
15
|
+
super
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def mp_report_sql(&block)
|
20
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
21
|
+
result = yield
|
22
|
+
elapsed_time = SqlPatches.elapsed_time(start)
|
23
|
+
@miniprofiler_sql_id.report_reader_duration(elapsed_time)
|
24
|
+
result
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
prepend MiniProfiler
|
29
|
+
end
|
30
|
+
|
31
|
+
class PG::Connection
|
32
|
+
module MiniProfiler
|
33
|
+
def prepare(*args, &blk)
|
34
|
+
# we have no choice but to do this here,
|
35
|
+
# if we do the check for profiling first, our cache may miss critical stuff
|
36
|
+
|
37
|
+
@prepare_map ||= {}
|
38
|
+
@prepare_map[args[0]] = args[1]
|
39
|
+
# dont leak more than 10k ever
|
40
|
+
@prepare_map = {} if @prepare_map.length > 1000
|
41
|
+
|
42
|
+
return super unless SqlPatches.should_measure?
|
43
|
+
super
|
44
|
+
end
|
45
|
+
|
46
|
+
def exec(*args, &blk)
|
47
|
+
return super unless SqlPatches.should_measure?
|
48
|
+
|
49
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
50
|
+
result = super
|
51
|
+
elapsed_time = SqlPatches.elapsed_time(start)
|
52
|
+
record = ::Rack::MiniProfiler.record_sql(args[0], elapsed_time)
|
53
|
+
result.instance_variable_set("@miniprofiler_sql_id", record) if result
|
54
|
+
|
55
|
+
result
|
56
|
+
end
|
57
|
+
|
58
|
+
if Gem::Version.new(PG::VERSION) >= Gem::Version.new("1.1.0")
|
59
|
+
def exec_params(*args, &blk)
|
60
|
+
return super unless SqlPatches.should_measure?
|
61
|
+
|
62
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
63
|
+
result = super
|
64
|
+
elapsed_time = SqlPatches.elapsed_time(start)
|
65
|
+
record = ::Rack::MiniProfiler.record_sql(args[0], elapsed_time)
|
66
|
+
result.instance_variable_set("@miniprofiler_sql_id", record) if result
|
67
|
+
|
68
|
+
result
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def exec_prepared(*args, &blk)
|
73
|
+
return super unless SqlPatches.should_measure?
|
74
|
+
|
75
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
76
|
+
result = super
|
77
|
+
elapsed_time = SqlPatches.elapsed_time(start)
|
78
|
+
mapped = args[0]
|
79
|
+
mapped = @prepare_map[mapped] || args[0] if @prepare_map
|
80
|
+
record = ::Rack::MiniProfiler.record_sql(mapped, elapsed_time)
|
81
|
+
result.instance_variable_set("@miniprofiler_sql_id", record) if result
|
82
|
+
|
83
|
+
result
|
84
|
+
end
|
85
|
+
|
86
|
+
def send_query_prepared(*args, &blk)
|
87
|
+
return super unless SqlPatches.should_measure?
|
88
|
+
|
89
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
90
|
+
result = super
|
91
|
+
elapsed_time = SqlPatches.elapsed_time(start)
|
92
|
+
mapped = args[0]
|
93
|
+
mapped = @prepare_map[mapped] || args[0] if @prepare_map
|
94
|
+
record = ::Rack::MiniProfiler.record_sql(mapped, elapsed_time)
|
95
|
+
result.instance_variable_set("@miniprofiler_sql_id", record) if result
|
96
|
+
|
97
|
+
result
|
98
|
+
end
|
99
|
+
|
100
|
+
def async_exec(*args, &blk)
|
101
|
+
return super unless SqlPatches.should_measure?
|
102
|
+
|
103
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
104
|
+
result = super
|
105
|
+
elapsed_time = SqlPatches.elapsed_time(start)
|
106
|
+
record = ::Rack::MiniProfiler.record_sql(args[0], elapsed_time)
|
107
|
+
result.instance_variable_set("@miniprofiler_sql_id", record) if result
|
108
|
+
|
109
|
+
result
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
prepend MiniProfiler
|
114
|
+
alias_method :query, :exec
|
115
|
+
end
|
data/lib/patches/db/pg.rb
CHANGED
@@ -1,122 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
alias_method
|
7
|
-
|
8
|
-
def values(*args, &blk)
|
9
|
-
return values_without_profiling(*args, &blk) unless defined?(@miniprofiler_sql_id)
|
10
|
-
mp_report_sql do
|
11
|
-
values_without_profiling(*args , &blk)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def each(*args, &blk)
|
16
|
-
return each_without_profiling(*args, &blk) unless defined?(@miniprofiler_sql_id)
|
17
|
-
mp_report_sql do
|
18
|
-
each_without_profiling(*args, &blk)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def mp_report_sql(&block)
|
23
|
-
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
24
|
-
result = yield
|
25
|
-
elapsed_time = SqlPatches.elapsed_time(start)
|
26
|
-
@miniprofiler_sql_id.report_reader_duration(elapsed_time)
|
27
|
-
result
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
class PG::Connection
|
32
|
-
alias_method :exec_without_profiling, :exec
|
33
|
-
alias_method :async_exec_without_profiling, :async_exec
|
34
|
-
alias_method :exec_prepared_without_profiling, :exec_prepared
|
35
|
-
alias_method :send_query_prepared_without_profiling, :send_query_prepared
|
36
|
-
alias_method :prepare_without_profiling, :prepare
|
37
|
-
|
38
|
-
if Gem::Version.new(PG::VERSION) >= Gem::Version.new("1.1.0")
|
39
|
-
alias_method :exec_params_without_profiling, :exec_params
|
40
|
-
end
|
41
|
-
|
42
|
-
def prepare(*args, &blk)
|
43
|
-
# we have no choice but to do this here,
|
44
|
-
# if we do the check for profiling first, our cache may miss critical stuff
|
45
|
-
|
46
|
-
@prepare_map ||= {}
|
47
|
-
@prepare_map[args[0]] = args[1]
|
48
|
-
# dont leak more than 10k ever
|
49
|
-
@prepare_map = {} if @prepare_map.length > 1000
|
50
|
-
|
51
|
-
return prepare_without_profiling(*args, &blk) unless SqlPatches.should_measure?
|
52
|
-
prepare_without_profiling(*args, &blk)
|
53
|
-
end
|
54
|
-
|
55
|
-
def exec(*args, &blk)
|
56
|
-
return exec_without_profiling(*args, &blk) unless SqlPatches.should_measure?
|
57
|
-
|
58
|
-
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
59
|
-
result = exec_without_profiling(*args, &blk)
|
60
|
-
elapsed_time = SqlPatches.elapsed_time(start)
|
61
|
-
record = ::Rack::MiniProfiler.record_sql(args[0], elapsed_time)
|
62
|
-
result.instance_variable_set("@miniprofiler_sql_id", record) if result
|
63
|
-
|
64
|
-
result
|
65
|
-
end
|
66
|
-
|
67
|
-
if Gem::Version.new(PG::VERSION) >= Gem::Version.new("1.1.0")
|
68
|
-
def exec_params(*args, &blk)
|
69
|
-
return exec_params_without_profiling(*args, &blk) unless SqlPatches.should_measure?
|
70
|
-
|
71
|
-
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
72
|
-
result = exec_params_without_profiling(*args, &blk)
|
73
|
-
elapsed_time = SqlPatches.elapsed_time(start)
|
74
|
-
record = ::Rack::MiniProfiler.record_sql(args[0], elapsed_time)
|
75
|
-
result.instance_variable_set("@miniprofiler_sql_id", record) if result
|
76
|
-
|
77
|
-
result
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def exec_prepared(*args, &blk)
|
82
|
-
return exec_prepared_without_profiling(*args, &blk) unless SqlPatches.should_measure?
|
83
|
-
|
84
|
-
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
85
|
-
result = exec_prepared_without_profiling(*args, &blk)
|
86
|
-
elapsed_time = SqlPatches.elapsed_time(start)
|
87
|
-
mapped = args[0]
|
88
|
-
mapped = @prepare_map[mapped] || args[0] if @prepare_map
|
89
|
-
record = ::Rack::MiniProfiler.record_sql(mapped, elapsed_time)
|
90
|
-
result.instance_variable_set("@miniprofiler_sql_id", record) if result
|
91
|
-
|
92
|
-
result
|
93
|
-
end
|
94
|
-
|
95
|
-
def send_query_prepared(*args, &blk)
|
96
|
-
return send_query_prepared_without_profiling(*args, &blk) unless SqlPatches.should_measure?
|
97
|
-
|
98
|
-
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
99
|
-
result = send_query_prepared_without_profiling(*args, &blk)
|
100
|
-
elapsed_time = SqlPatches.elapsed_time(start)
|
101
|
-
mapped = args[0]
|
102
|
-
mapped = @prepare_map[mapped] || args[0] if @prepare_map
|
103
|
-
record = ::Rack::MiniProfiler.record_sql(mapped, elapsed_time)
|
104
|
-
result.instance_variable_set("@miniprofiler_sql_id", record) if result
|
105
|
-
|
106
|
-
result
|
107
|
-
end
|
108
|
-
|
109
|
-
def async_exec(*args, &blk)
|
110
|
-
return async_exec_without_profiling(*args, &blk) unless SqlPatches.should_measure?
|
111
|
-
|
112
|
-
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
113
|
-
result = exec_without_profiling(*args, &blk)
|
114
|
-
elapsed_time = SqlPatches.elapsed_time(start)
|
115
|
-
record = ::Rack::MiniProfiler.record_sql(args[0], elapsed_time)
|
116
|
-
result.instance_variable_set("@miniprofiler_sql_id", record) if result
|
117
|
-
|
118
|
-
result
|
119
|
-
end
|
120
|
-
|
121
|
-
alias_method :query, :exec
|
3
|
+
if defined?(Rack::MINI_PROFILER_PREPEND_PG_PATCH)
|
4
|
+
require "patches/db/pg/prepend"
|
5
|
+
else
|
6
|
+
require "patches/db/pg/alias_method"
|
122
7
|
end
|
data/rack-mini-profiler.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
lib = File.expand_path('../lib', __FILE__)
|
4
|
-
$LOAD_PATH.unshift(lib)
|
4
|
+
$LOAD_PATH.unshift(lib) if !$LOAD_PATH.include?(lib)
|
5
5
|
require 'mini_profiler/version'
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
|
|
21
21
|
"CHANGELOG.md"
|
22
22
|
]
|
23
23
|
s.add_runtime_dependency 'rack', '>= 1.2.0'
|
24
|
-
s.required_ruby_version = '>=
|
24
|
+
s.required_ruby_version = '>= 3.1.0'
|
25
25
|
|
26
26
|
s.metadata = {
|
27
27
|
'source_code_uri' => Rack::MiniProfiler::SOURCE_CODE_URI,
|
@@ -41,7 +41,7 @@ Gem::Specification.new do |s|
|
|
41
41
|
s.add_development_dependency 'rubocop-discourse'
|
42
42
|
s.add_development_dependency 'listen'
|
43
43
|
s.add_development_dependency 'webpacker'
|
44
|
-
s.add_development_dependency 'rails', '
|
44
|
+
s.add_development_dependency 'rails', '>= 7.1'
|
45
45
|
s.add_development_dependency 'webmock', '3.9.1'
|
46
46
|
s.add_development_dependency 'rubyzip'
|
47
47
|
|