rack-mini-profiler 0.10.6 → 2.3.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.
Files changed (74) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +129 -16
  3. data/README.md +116 -63
  4. data/lib/enable_rails_patches.rb +5 -0
  5. data/lib/generators/rack_profiler/install_generator.rb +2 -0
  6. data/lib/generators/rack_profiler/templates/rack_profiler.rb +2 -0
  7. data/lib/html/dot.1.1.2.min.js +2 -0
  8. data/lib/html/includes.css +141 -40
  9. data/lib/html/includes.js +1398 -970
  10. data/lib/html/includes.scss +547 -442
  11. data/lib/html/includes.tmpl +227 -142
  12. data/lib/html/pretty-print.js +810 -0
  13. data/lib/html/profile_handler.js +1 -1
  14. data/lib/html/rack-mini-profiler.css +3 -0
  15. data/lib/html/rack-mini-profiler.js +2 -0
  16. data/lib/html/share.html +0 -1
  17. data/lib/html/speedscope/LICENSE +21 -0
  18. data/lib/html/speedscope/README.md +3 -0
  19. data/lib/html/speedscope/demangle-cpp.1768f4cc.js +4 -0
  20. data/lib/html/speedscope/favicon-16x16.f74b3187.png +0 -0
  21. data/lib/html/speedscope/favicon-32x32.bc503437.png +0 -0
  22. data/lib/html/speedscope/file-format-schema.json +324 -0
  23. data/lib/html/speedscope/import.cf0fa83f.js +115 -0
  24. data/lib/html/speedscope/index.html +2 -0
  25. data/lib/html/speedscope/release.txt +3 -0
  26. data/lib/html/speedscope/reset.8c46b7a1.css +2 -0
  27. data/lib/html/speedscope/source-map.438fa06b.js +24 -0
  28. data/lib/html/speedscope/speedscope.44364064.js +200 -0
  29. data/lib/html/vendor.js +848 -0
  30. data/lib/mini_profiler/asset_version.rb +3 -2
  31. data/lib/mini_profiler/client_settings.rb +27 -16
  32. data/lib/mini_profiler/config.rb +73 -46
  33. data/lib/mini_profiler/context.rb +5 -3
  34. data/lib/mini_profiler/gc_profiler.rb +17 -16
  35. data/lib/mini_profiler/profiler.rb +332 -94
  36. data/lib/mini_profiler/profiling_methods.rb +20 -15
  37. data/lib/mini_profiler/snapshots_transporter.rb +109 -0
  38. data/lib/mini_profiler/storage/abstract_store.rb +80 -0
  39. data/lib/mini_profiler/storage/file_store.rb +18 -13
  40. data/lib/mini_profiler/storage/memcache_store.rb +10 -7
  41. data/lib/mini_profiler/storage/memory_store.rb +63 -13
  42. data/lib/mini_profiler/storage/redis_store.rb +143 -7
  43. data/lib/mini_profiler/timer_struct/base.rb +4 -2
  44. data/lib/mini_profiler/timer_struct/client.rb +9 -8
  45. data/lib/mini_profiler/timer_struct/custom.rb +8 -5
  46. data/lib/mini_profiler/timer_struct/page.rb +79 -24
  47. data/lib/mini_profiler/timer_struct/request.rb +83 -38
  48. data/lib/mini_profiler/timer_struct/sql.rb +25 -22
  49. data/lib/mini_profiler/version.rb +3 -1
  50. data/lib/mini_profiler_rails/railtie.rb +91 -8
  51. data/lib/mini_profiler_rails/railtie_methods.rb +61 -0
  52. data/lib/patches/db/activerecord.rb +5 -14
  53. data/lib/patches/db/mongo.rb +3 -1
  54. data/lib/patches/db/moped.rb +5 -3
  55. data/lib/patches/db/mysql2.rb +8 -6
  56. data/lib/patches/db/neo4j.rb +3 -1
  57. data/lib/patches/db/nobrainer.rb +4 -2
  58. data/lib/patches/db/oracle_enhanced.rb +4 -2
  59. data/lib/patches/db/pg.rb +41 -21
  60. data/lib/patches/db/plucky.rb +7 -5
  61. data/lib/patches/db/riak.rb +15 -13
  62. data/lib/patches/db/rsolr.rb +6 -4
  63. data/lib/patches/db/sequel.rb +2 -0
  64. data/lib/patches/net_patches.rb +20 -8
  65. data/lib/patches/sql_patches.rb +17 -7
  66. data/lib/prepend_net_http_patch.rb +5 -0
  67. data/lib/rack-mini-profiler.rb +3 -3
  68. data/rack-mini-profiler.gemspec +23 -9
  69. metadata +146 -31
  70. data/lib/html/jquery.1.7.1.js +0 -4
  71. data/lib/html/jquery.tmpl.js +0 -486
  72. data/lib/html/list.css +0 -9
  73. data/lib/html/list.js +0 -38
  74. data/lib/html/list.tmpl +0 -34
@@ -1,28 +1,31 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Rack
3
4
  class MiniProfiler
4
5
 
5
6
  # Timing system for a SQL query
6
7
  module TimerStruct
7
8
  class Sql < TimerStruct::Base
9
+ attr_accessor :parent
10
+
8
11
  def initialize(query, duration_ms, page, parent, params = nil, skip_backtrace = false, full_backtrace = false)
9
12
 
10
13
  stack_trace = nil
11
14
  unless skip_backtrace || duration_ms < Rack::MiniProfiler.config.backtrace_threshold_ms
12
15
  # Allow us to filter the stack trace
13
- stack_trace = String.new
14
- # Clean up the stack trace if there are options to do so
16
+ stack_trace = "".dup
17
+ # Clean up the stack trace if there are options to do so
15
18
  Kernel.caller.each do |ln|
16
- ln.gsub!(Rack::MiniProfiler.config.backtrace_remove, '') if Rack::MiniProfiler.config.backtrace_remove and !full_backtrace
17
- if full_backtrace or
19
+ ln.gsub!(Rack::MiniProfiler.config.backtrace_remove, '') if Rack::MiniProfiler.config.backtrace_remove && !full_backtrace
20
+ if full_backtrace ||
18
21
  (
19
22
  (
20
- Rack::MiniProfiler.config.backtrace_includes.nil? or
21
- Rack::MiniProfiler.config.backtrace_includes.any?{|regex| ln =~ regex}
22
- ) and
23
+ Rack::MiniProfiler.config.backtrace_includes.nil? ||
24
+ Rack::MiniProfiler.config.backtrace_includes.any? { |regex| ln =~ regex }
25
+ ) &&
23
26
  (
24
- Rack::MiniProfiler.config.backtrace_ignores.nil? or
25
- Rack::MiniProfiler.config.backtrace_ignores.none?{|regex| ln =~ regex}
27
+ Rack::MiniProfiler.config.backtrace_ignores.nil? ||
28
+ Rack::MiniProfiler.config.backtrace_ignores.none? { |regex| ln =~ regex }
26
29
  )
27
30
  )
28
31
  stack_trace << ln << "\n"
@@ -32,17 +35,17 @@ module Rack
32
35
 
33
36
  @parent = parent
34
37
  @page = page
35
- start_millis = ((Time.now.to_f * 1000).to_i - page[:started]) - duration_ms
38
+ start_millis = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) * 1000).to_i - page[:started]) - duration_ms
36
39
  super(
37
- :execute_type => 3, # TODO
38
- :formatted_command_string => query,
39
- :stack_trace_snippet => stack_trace,
40
- :start_milliseconds => start_millis,
41
- :duration_milliseconds => duration_ms,
42
- :first_fetch_duration_milliseconds => duration_ms,
43
- :parameters => trim_binds(params),
44
- :parent_timing_id => nil,
45
- :is_duplicate => false
40
+ execute_type: 3, # TODO
41
+ formatted_command_string: query ? ERB::Util.html_escape(query) : nil,
42
+ stack_trace_snippet: stack_trace,
43
+ start_milliseconds: start_millis,
44
+ duration_milliseconds: duration_ms,
45
+ first_fetch_duration_milliseconds: duration_ms,
46
+ parameters: query ? trim_binds(params) : nil,
47
+ parent_timing_id: nil,
48
+ is_duplicate: false
46
49
  )
47
50
  end
48
51
 
@@ -57,18 +60,18 @@ module Rack
57
60
  def trim_binds(binds)
58
61
  max_len = Rack::MiniProfiler.config.max_sql_param_length
59
62
  return if binds.nil? || max_len == 0
60
- return binds.map{|(name, val)| [name, val]} if max_len.nil?
63
+ return binds.map { |(name, val)| [name, val] } if max_len.nil?
61
64
  binds.map do |(name, val)|
62
65
  val ||= name
63
66
  if val.nil? || val == true || val == false || val.kind_of?(Numeric)
64
67
  # keep these parameters as is
65
68
  elsif val.kind_of?(String)
66
- val = val[0...max_len]+(max_len < val.length ? '...' : '') if max_len
69
+ val = val[0...max_len] + (max_len < val.length ? '...' : '') if max_len
67
70
  else
68
71
  val = val.class.name
69
72
  end
70
73
  if name.kind_of?(String)
71
- name = name[0...max_len]+(max_len < name.length ? '...' : '') if max_len
74
+ name = name[0...max_len] + (max_len < name.length ? '...' : '') if max_len
72
75
  end
73
76
  [name, val]
74
77
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rack
2
4
  class MiniProfiler
3
- VERSION = '0.10.6'
5
+ VERSION = '2.3.0'
4
6
  end
5
7
  end
@@ -1,11 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'fileutils'
4
+ require_relative './railtie_methods'
2
5
 
3
6
  module Rack::MiniProfilerRails
7
+ extend Rack::MiniProfilerRailsMethods
4
8
 
5
9
  # call direct if needed to do a defer init
6
10
  def self.initialize!(app)
7
11
 
8
- raise "MiniProfilerRails initialized twice. Set `require: false' for rack-mini-profiler in your Gemfile" if @already_initialized
12
+ raise "MiniProfilerRails initialized twice. Set `require: false' for rack-mini-profiler in your Gemfile" if defined?(@already_initialized) && @already_initialized
9
13
 
10
14
  c = Rack::MiniProfiler.config
11
15
 
@@ -26,6 +30,8 @@ module Rack::MiniProfilerRails
26
30
 
27
31
  if serves_static_assets?(app)
28
32
  c.skip_paths << app.config.assets.prefix
33
+ wp_assets_path = get_webpacker_assets_path()
34
+ c.skip_paths << wp_assets_path if wp_assets_path
29
35
  end
30
36
 
31
37
  unless Rails.env.development? || Rails.env.test?
@@ -42,7 +48,7 @@ module Rack::MiniProfilerRails
42
48
  base_path = Rails.application.config.paths['tmp'].first rescue "#{Rails.root}/tmp"
43
49
  tmp = base_path + '/miniprofiler'
44
50
 
45
- c.storage_options = {:path => tmp}
51
+ c.storage_options = { path: tmp }
46
52
  c.storage = Rack::MiniProfiler::FileStore
47
53
  end
48
54
 
@@ -53,16 +59,92 @@ module Rack::MiniProfilerRails
53
59
 
54
60
  # Install the Middleware
55
61
  app.middleware.insert(0, Rack::MiniProfiler)
62
+ c.enable_advanced_debugging_tools = Rails.env.development?
63
+
64
+ if ::Rack::MiniProfiler.patch_rails?
65
+ # Attach to various Rails methods
66
+ ActiveSupport.on_load(:action_controller) do
67
+ ::Rack::MiniProfiler.profile_method(ActionController::Base, :process) { |action| "Executing action: #{action}" }
68
+ end
69
+
70
+ ActiveSupport.on_load(:action_view) do
71
+ ::Rack::MiniProfiler.profile_method(ActionView::Template, :render) { |x, y| "Rendering: #{@virtual_path}" }
72
+ end
73
+ else
74
+ subscribe("start_processing.action_controller") do |name, start, finish, id, payload|
75
+ next if !should_measure?
76
+
77
+ current = Rack::MiniProfiler.current
78
+ description = "Executing action: #{payload[:action]}"
79
+ Thread.current[get_key(payload)] = current.current_timer
80
+ Rack::MiniProfiler.current.current_timer = current.current_timer.add_child(description)
81
+ end
56
82
 
57
- # Attach to various Rails methods
58
- ActiveSupport.on_load(:action_controller) do
59
- ::Rack::MiniProfiler.profile_method(ActionController::Base, :process) {|action| "Executing action: #{action}"}
83
+ subscribe("process_action.action_controller") do |name, start, finish, id, payload|
84
+ next if !should_measure?
85
+
86
+ key = get_key(payload)
87
+ parent_timer = Thread.current[key]
88
+ next if !parent_timer
89
+
90
+ Thread.current[key] = nil
91
+ Rack::MiniProfiler.current.current_timer.record_time
92
+ Rack::MiniProfiler.current.current_timer = parent_timer
93
+ end
94
+
95
+ subscribe("render_partial.action_view") do |name, start, finish, id, payload|
96
+ render_notification_handler(shorten_identifier(payload[:identifier]), finish, start)
97
+ end
98
+
99
+ subscribe("render_template.action_view") do |name, start, finish, id, payload|
100
+ render_notification_handler(shorten_identifier(payload[:identifier]), finish, start)
101
+ end
102
+
103
+ if Rack::MiniProfiler.subscribe_sql_active_record
104
+ # we don't want to subscribe if we've already patched a DB driver
105
+ # otherwise we would end up with 2 records for every query
106
+ subscribe("sql.active_record") do |name, start, finish, id, payload|
107
+ next if !should_measure?
108
+ next if payload[:name] =~ /SCHEMA/ && Rack::MiniProfiler.config.skip_schema_queries
109
+
110
+ Rack::MiniProfiler.record_sql(
111
+ payload[:sql],
112
+ (finish - start) * 1000,
113
+ Rack::MiniProfiler.binds_to_params(payload[:binds])
114
+ )
115
+ end
116
+ end
60
117
  end
61
- ActiveSupport.on_load(:action_view) do
62
- ::Rack::MiniProfiler.profile_method(ActionView::Template, :render) {|x,y| "Rendering: #{@virtual_path}"}
118
+ @already_initialized = true
119
+ end
120
+
121
+ def self.create_engine
122
+ return if defined?(Rack::MiniProfilerRails::Engine)
123
+ klass = Class.new(::Rails::Engine) do
124
+ engine_name 'rack-mini-profiler'
125
+ config.assets.paths << File.expand_path('../../html', __FILE__)
126
+ config.assets.precompile << 'rack-mini-profiler.js'
127
+ config.assets.precompile << 'rack-mini-profiler.css'
63
128
  end
129
+ Rack::MiniProfilerRails.const_set("Engine", klass)
130
+ end
64
131
 
65
- @already_initialized = true
132
+ def self.subscribe(event, &blk)
133
+ if ActiveSupport::Notifications.respond_to?(:monotonic_subscribe)
134
+ ActiveSupport::Notifications.monotonic_subscribe(event) { |*args| blk.call(*args) }
135
+ else
136
+ ActiveSupport::Notifications.subscribe(event) do |name, start, finish, id, payload|
137
+ blk.call(name, start.to_f, finish.to_f, id, payload)
138
+ end
139
+ end
140
+ end
141
+
142
+ def self.get_key(payload)
143
+ "mini_profiler_parent_timer_#{payload[:controller]}_#{payload[:action]}".to_sym
144
+ end
145
+
146
+ def self.shorten_identifier(identifier)
147
+ identifier.split('/').last(2).join('/')
66
148
  end
67
149
 
68
150
  def self.serves_static_assets?(app)
@@ -93,6 +175,7 @@ module Rack::MiniProfilerRails
93
175
  middlewares = app.middleware.middlewares
94
176
  if Rack::MiniProfiler.config.suppress_encoding.nil? &&
95
177
  middlewares.include?(Rack::Deflater) &&
178
+ middlewares.include?(Rack::MiniProfiler) &&
96
179
  middlewares.index(Rack::Deflater) > middlewares.index(Rack::MiniProfiler)
97
180
  Rack::MiniProfiler.config.suppress_encoding = true
98
181
  end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack::MiniProfilerRailsMethods
4
+ def render_notification_handler(name, finish, start, name_as_description: false)
5
+ return if !should_measure?
6
+
7
+ description = name_as_description ? name : "Rendering: #{name}"
8
+ current = Rack::MiniProfiler.current.current_timer
9
+ node = current.add_child(description)
10
+ duration = finish - start
11
+ duration_ms = duration * 1000
12
+ node.start -= duration
13
+ node[:start_milliseconds] -= duration_ms
14
+ node.record_time(duration_ms)
15
+
16
+ children_duration = 0
17
+ to_be_moved = { requests: [], sql: [], custom: {} }
18
+ current.children.each do |child|
19
+ next if child == node
20
+ if should_move?(child, node)
21
+ to_be_moved[:requests] << child
22
+ children_duration += child[:duration_milliseconds]
23
+ end
24
+ end
25
+ node[:duration_without_children_milliseconds] = duration_ms - children_duration
26
+ to_be_moved[:requests].each { |req| current.move_child(req, node) }
27
+
28
+ current.sql_timings.each do |sql|
29
+ to_be_moved[:sql] << sql if should_move?(sql, node)
30
+ end
31
+ to_be_moved[:sql].each { |sql| current.move_sql(sql, node) }
32
+
33
+ current.custom_timings.each do |type, timings|
34
+ to_be_moved[:custom] = []
35
+ timings.each do |custom|
36
+ to_be_moved[:custom] << custom if should_move?(custom, node)
37
+ end
38
+ to_be_moved[:custom].each { |custom| current.move_custom(type, custom, node) }
39
+ end
40
+ end
41
+
42
+ def should_measure?
43
+ current = Rack::MiniProfiler.current
44
+ current && current.measure
45
+ end
46
+
47
+ def should_move?(child, node)
48
+ start = :start_milliseconds
49
+ duration = :duration_milliseconds
50
+ child[start] >= node[start] &&
51
+ child[start] + child[duration] <= node[start] + node[duration]
52
+ end
53
+
54
+ def get_webpacker_assets_path
55
+ if defined?(Webpacker) && Webpacker.config.config_path.exist?
56
+ Webpacker.config.public_output_path.to_s.gsub(Webpacker.config.public_path.to_s, "")
57
+ end
58
+ end
59
+
60
+ extend self
61
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ## based off https://github.com/newrelic/rpm/blob/master/lib/new_relic/agent/instrumentation/active_record.rb
2
4
  ## fallback for alls sorts of weird dbs
3
5
  module Rack
@@ -13,29 +15,18 @@ module Rack
13
15
  end
14
16
  end
15
17
 
16
- def binds_to_params(binds)
17
- return if binds.nil? || Rack::MiniProfiler.config.max_sql_param_length == 0
18
- # map ActiveRecord::Relation::QueryAttribute to [name, value]
19
- params = binds.map { |c| c.kind_of?(Array) ? [c.first, c.last] : [c.name, c.value] }
20
- if (skip = Rack::MiniProfiler.config.skip_sql_param_names)
21
- params.map { |(n,v)| n =~ skip ? [n, nil] : [n, v] }
22
- else
23
- params
24
- end
25
- end
26
-
27
18
  def log_with_miniprofiler(*args, &block)
28
19
  return log_without_miniprofiler(*args, &block) unless SqlPatches.should_measure?
29
20
 
30
21
  sql, name, binds = args
31
- start = Time.now
22
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
32
23
  rval = log_without_miniprofiler(*args, &block)
33
24
 
34
25
  # Don't log schema queries if the option is set
35
- return rval if Rack::MiniProfiler.config.skip_schema_queries and name =~ /SCHEMA/
26
+ return rval if Rack::MiniProfiler.config.skip_schema_queries && name =~ (/SCHEMA/)
36
27
 
37
28
  elapsed_time = SqlPatches.elapsed_time(start)
38
- Rack::MiniProfiler.record_sql(sql, elapsed_time, binds_to_params(binds))
29
+ Rack::MiniProfiler.record_sql(sql, elapsed_time, Rack::MiniProfiler.binds_to_params(binds))
39
30
  rval
40
31
  end
41
32
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Mongo/Mongoid 5 patches
2
4
  class Mongo::Server::Connection
3
5
  def dispatch_with_timing(*args, &blk)
@@ -6,7 +8,7 @@ class Mongo::Server::Connection
6
8
  result, _record = SqlPatches.record_sql(args[0][0].payload.inspect) do
7
9
  dispatch_without_timing(*args, &blk)
8
10
  end
9
- return result
11
+ result
10
12
  end
11
13
 
12
14
  # TODO: change to Module#prepend as soon as Ruby 1.9.3 support is dropped
@@ -1,12 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Mongoid 3 patches
2
4
  class Moped::Node
3
5
  alias_method :process_without_profiling, :process
4
- def process(*args,&blk)
5
- return process_without_profiling(*args,&blk) unless SqlPatches.should_measure?
6
+ def process(*args, &blk)
7
+ return process_without_profiling(*args, &blk) unless SqlPatches.should_measure?
6
8
 
7
9
  result, _record = SqlPatches.record_sql(args[0].log_inspect) do
8
10
  process_without_profiling(*args, &blk)
9
11
  end
10
- return result
12
+ result
11
13
  end
12
14
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # The best kind of instrumentation is in the actual db provider, however we don't want to double instrument
2
4
 
3
5
  class Mysql2::Result
@@ -5,8 +7,8 @@ class Mysql2::Result
5
7
  def each(*args, &blk)
6
8
  return each_without_profiling(*args, &blk) unless defined?(@miniprofiler_sql_id)
7
9
 
8
- start = Time.now
9
- result = each_without_profiling(*args,&blk)
10
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
11
+ result = each_without_profiling(*args, &blk)
10
12
  elapsed_time = SqlPatches.elapsed_time(start)
11
13
 
12
14
  @miniprofiler_sql_id.report_reader_duration(elapsed_time)
@@ -16,11 +18,11 @@ end
16
18
 
17
19
  class Mysql2::Client
18
20
  alias_method :query_without_profiling, :query
19
- def query(*args,&blk)
20
- return query_without_profiling(*args,&blk) unless SqlPatches.should_measure?
21
+ def query(*args, &blk)
22
+ return query_without_profiling(*args, &blk) unless SqlPatches.should_measure?
21
23
 
22
- result, record = SqlPatches.record_sql( args[0] ) do
23
- query_without_profiling(*args,&blk)
24
+ result, record = SqlPatches.record_sql(args[0]) do
25
+ query_without_profiling(*args, &blk)
24
26
  end
25
27
  result.instance_variable_set("@miniprofiler_sql_id", record) if result
26
28
  result
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Neo4j::Core::Query
2
4
  alias_method :response_without_miniprofiler, :response
3
5
 
4
6
  def response
5
7
  return @response if @response
6
- start = Time.now
8
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
7
9
  rval = response_without_miniprofiler
8
10
  elapsed_time = SqlPatches.elapsed_time(start)
9
11
  Rack::MiniProfiler.record_sql(to_cypher, elapsed_time)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Rack::MiniProfiler::NoBrainerProfiler
2
4
 
3
5
  def on_query(env)
@@ -6,7 +8,7 @@ class Rack::MiniProfiler::NoBrainerProfiler
6
8
  !env[:criteria].where_indexed? &&
7
9
  !env[:criteria].model.try(:perf_warnings_disabled)
8
10
 
9
- query = ""
11
+ query = "".dup
10
12
 
11
13
  # per-model/query database overrides
12
14
  query << "[#{env[:options][:db]}] " if env[:options][:db]
@@ -15,7 +17,7 @@ class Rack::MiniProfiler::NoBrainerProfiler
15
17
  # query << "(#{NoBrainer::RQL.type_of(env[:query]).to_s}) "
16
18
 
17
19
  query << "NOT USING INDEX: " if not_indexed
18
- query << env[:query].inspect.gsub(/\n/, '').gsub(/ +/, ' ') + " "
20
+ query << env[:query].inspect.delete("\n").gsub(/ +/, ' ') + " "
19
21
 
20
22
  if env[:exception]
21
23
  query << "exception: #{env[:exception].class} #{env[:exception].message.split("\n").first} "
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class ActiveRecord::Result
2
4
  alias_method :each_without_profiling, :each
3
5
  def each(&blk)
4
6
  return each_without_profiling(&blk) unless defined?(@miniprofiler_sql_id)
5
7
 
6
- start = Time.now
8
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
7
9
  result = each_without_profiling(&blk)
8
10
  elapsed_time = SqlPatches.elapsed_time(start)
9
11
  @miniprofiler_sql_id.report_reader_duration(elapsed_time)
@@ -45,7 +47,7 @@ class ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter
45
47
  def mp_profile_sql(sql, name, &blk)
46
48
  return yield unless mp_should_measure?(name)
47
49
 
48
- start = Time.now
50
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
49
51
  result = yield
50
52
  elapsed_time = SqlPatches.elapsed_time(start)
51
53
  record = ::Rack::MiniProfiler.record_sql(sql, elapsed_time)
data/lib/patches/db/pg.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # PG patches, keep in mind exec and async_exec have a exec{|r| } semantics that is yet to be implemented
2
4
  class PG::Result
3
5
  alias_method :each_without_profiling, :each
@@ -6,7 +8,7 @@ class PG::Result
6
8
  def values(*args, &blk)
7
9
  return values_without_profiling(*args, &blk) unless defined?(@miniprofiler_sql_id)
8
10
  mp_report_sql do
9
- values_without_profiling(*args ,&blk)
11
+ values_without_profiling(*args , &blk)
10
12
  end
11
13
  end
12
14
 
@@ -18,7 +20,7 @@ class PG::Result
18
20
  end
19
21
 
20
22
  def mp_report_sql(&block)
21
- start = Time.now
23
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
22
24
  result = yield
23
25
  elapsed_time = SqlPatches.elapsed_time(start)
24
26
  @miniprofiler_sql_id.report_reader_duration(elapsed_time)
@@ -33,7 +35,11 @@ class PG::Connection
33
35
  alias_method :send_query_prepared_without_profiling, :send_query_prepared
34
36
  alias_method :prepare_without_profiling, :prepare
35
37
 
36
- def prepare(*args,&blk)
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)
37
43
  # we have no choice but to do this here,
38
44
  # if we do the check for profiling first, our cache may miss critical stuff
39
45
 
@@ -42,15 +48,15 @@ class PG::Connection
42
48
  # dont leak more than 10k ever
43
49
  @prepare_map = {} if @prepare_map.length > 1000
44
50
 
45
- return prepare_without_profiling(*args,&blk) unless SqlPatches.should_measure?
46
- prepare_without_profiling(*args,&blk)
51
+ return prepare_without_profiling(*args, &blk) unless SqlPatches.should_measure?
52
+ prepare_without_profiling(*args, &blk)
47
53
  end
48
54
 
49
- def exec(*args,&blk)
50
- return exec_without_profiling(*args,&blk) unless SqlPatches.should_measure?
55
+ def exec(*args, &blk)
56
+ return exec_without_profiling(*args, &blk) unless SqlPatches.should_measure?
51
57
 
52
- start = Time.now
53
- result = exec_without_profiling(*args,&blk)
58
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
59
+ result = exec_without_profiling(*args, &blk)
54
60
  elapsed_time = SqlPatches.elapsed_time(start)
55
61
  record = ::Rack::MiniProfiler.record_sql(args[0], elapsed_time)
56
62
  result.instance_variable_set("@miniprofiler_sql_id", record) if result
@@ -58,11 +64,25 @@ class PG::Connection
58
64
  result
59
65
  end
60
66
 
61
- def exec_prepared(*args,&blk)
62
- return exec_prepared_without_profiling(*args,&blk) unless SqlPatches.should_measure?
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?
63
83
 
64
- start = Time.now
65
- result = exec_prepared_without_profiling(*args,&blk)
84
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
85
+ result = exec_prepared_without_profiling(*args, &blk)
66
86
  elapsed_time = SqlPatches.elapsed_time(start)
67
87
  mapped = args[0]
68
88
  mapped = @prepare_map[mapped] || args[0] if @prepare_map
@@ -72,11 +92,11 @@ class PG::Connection
72
92
  result
73
93
  end
74
94
 
75
- def send_query_prepared(*args,&blk)
76
- return send_query_prepared_without_profiling(*args,&blk) unless SqlPatches.should_measure?
95
+ def send_query_prepared(*args, &blk)
96
+ return send_query_prepared_without_profiling(*args, &blk) unless SqlPatches.should_measure?
77
97
 
78
- start = Time.now
79
- result = send_query_prepared_without_profiling(*args,&blk)
98
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
99
+ result = send_query_prepared_without_profiling(*args, &blk)
80
100
  elapsed_time = SqlPatches.elapsed_time(start)
81
101
  mapped = args[0]
82
102
  mapped = @prepare_map[mapped] || args[0] if @prepare_map
@@ -86,11 +106,11 @@ class PG::Connection
86
106
  result
87
107
  end
88
108
 
89
- def async_exec(*args,&blk)
90
- return async_exec_without_profiling(*args,&blk) unless SqlPatches.should_measure?
109
+ def async_exec(*args, &blk)
110
+ return async_exec_without_profiling(*args, &blk) unless SqlPatches.should_measure?
91
111
 
92
- start = Time.now
93
- result = exec_without_profiling(*args,&blk)
112
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
113
+ result = exec_without_profiling(*args, &blk)
94
114
  elapsed_time = SqlPatches.elapsed_time(start)
95
115
  record = ::Rack::MiniProfiler.record_sql(args[0], elapsed_time)
96
116
  result.instance_variable_set("@miniprofiler_sql_id", record) if result
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # mongo_mapper patches
2
4
  # TODO: Include overrides for distinct, update, cursor, and create
3
5
  class Plucky::Query
@@ -7,19 +9,19 @@ class Plucky::Query
7
9
  alias_method :remove_without_profiling, :remove
8
10
 
9
11
  def find_each(*args, &blk)
10
- return profile_database_operation(__callee__, filtered_inspect(), *args, &blk)
12
+ profile_database_operation(__callee__, filtered_inspect(), *args, &blk)
11
13
  end
12
14
 
13
15
  def find_one(*args, &blk)
14
- return profile_database_operation(__callee__, filtered_inspect(args[0]), *args, &blk)
16
+ profile_database_operation(__callee__, filtered_inspect(args[0]), *args, &blk)
15
17
  end
16
18
 
17
19
  def count(*args, &blk)
18
- return profile_database_operation(__callee__, filtered_inspect(), *args, &blk)
20
+ profile_database_operation(__callee__, filtered_inspect(), *args, &blk)
19
21
  end
20
22
 
21
23
  def remove(*args, &blk)
22
- return profile_database_operation(__callee__, filtered_inspect(), *args, &blk)
24
+ profile_database_operation(__callee__, filtered_inspect(), *args, &blk)
23
25
  end
24
26
 
25
27
  private
@@ -27,7 +29,7 @@ class Plucky::Query
27
29
  def profile_database_operation(method, message, *args, &blk)
28
30
  return self.send("#{method.id2name}_without_profiling", *args, &blk) unless SqlPatches.should_measure?
29
31
 
30
- start = Time.now
32
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
31
33
  result = self.send("#{method.id2name}_without_profiling", *args, &blk)
32
34
  elapsed_time = SqlPatches.elapsed_time(start)
33
35