rack-mini-profiler 0.9.4 → 0.9.9

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.

Potentially problematic release.


This version of rack-mini-profiler might be problematic. Click here for more details.

@@ -3,9 +3,9 @@ module Rack
3
3
  module ProfilingMethods
4
4
 
5
5
  def record_sql(query, elapsed_ms)
6
- return unless current
6
+ return unless current && current.current_timer
7
7
  c = current
8
- c.current_timer.add_sql(query, elapsed_ms, c.page_struct, c.skip_backtrace, c.full_backtrace) if (c && c.current_timer)
8
+ c.current_timer.add_sql(query, elapsed_ms, c.page_struct, c.skip_backtrace, c.full_backtrace)
9
9
  end
10
10
 
11
11
  def start_step(name)
@@ -26,10 +26,9 @@ module Rack
26
26
  def step(name, opts = nil)
27
27
  if current
28
28
  parent_timer = current.current_timer
29
- result = nil
30
29
  current.current_timer = current_timer = current.current_timer.add_child(name)
31
30
  begin
32
- result = yield if block_given?
31
+ yield if block_given?
33
32
  ensure
34
33
  current_timer.record_time
35
34
  current.current_timer = parent_timer
@@ -87,34 +86,37 @@ module Rack
87
86
  end
88
87
  end
89
88
 
90
- result = nil
91
89
  parent_timer = Rack::MiniProfiler.current.current_timer
92
90
 
93
91
  if type == :counter
94
92
  start = Time.now
95
93
  begin
96
- result = self.send without_profiling, *args, &orig
94
+ self.send without_profiling, *args, &orig
97
95
  ensure
98
96
  duration_ms = (Time.now - start).to_f * 1000
99
97
  parent_timer.add_custom(name, duration_ms, Rack::MiniProfiler.current.page_struct )
100
98
  end
101
99
  else
102
- page_struct = Rack::MiniProfiler.current.page_struct
103
-
104
100
  Rack::MiniProfiler.current.current_timer = current_timer = parent_timer.add_child(name)
105
101
  begin
106
- result = self.send without_profiling, *args, &orig
102
+ self.send without_profiling, *args, &orig
107
103
  ensure
108
104
  current_timer.record_time
109
105
  Rack::MiniProfiler.current.current_timer = parent_timer
110
106
  end
111
107
  end
112
-
113
- result
114
108
  end
115
109
  klass.send :alias_method, method, with_profiling
116
110
  end
117
111
 
112
+ def profile_singleton_method(klass, method, type = :profile, &blk)
113
+ profile_method(singleton_class(klass), method, type, &blk)
114
+ end
115
+
116
+ def unprofile_singleton_method(klass, method)
117
+ unprofile_method(singleton_class(klass), method)
118
+ end
119
+
118
120
  # Add a custom timing. These are displayed similar to SQL/query time in
119
121
  # columns expanding to the right.
120
122
  #
@@ -140,6 +142,10 @@ module Rack
140
142
 
141
143
  private
142
144
 
145
+ def singleton_class(klass)
146
+ class << klass; self; end
147
+ end
148
+
143
149
  def clean_method_name(method)
144
150
  method.to_s.gsub(/[\?\!]/, "")
145
151
  end
@@ -26,8 +26,14 @@ module Rack
26
26
  end
27
27
 
28
28
  private
29
- def path(key)
30
- @path + "/" + @prefix + "_" + key
29
+ if RUBY_PLATFORM =~ /mswin(?!ce)|mingw|cygwin|bccwin/
30
+ def path(key)
31
+ @path + "/" + @prefix + "_" + key.gsub(/:/, '_')
32
+ end
33
+ else
34
+ def path(key)
35
+ @path + "/" + @prefix + "_" + key
36
+ end
31
37
  end
32
38
  end
33
39
 
@@ -38,6 +44,8 @@ module Rack
38
44
  @path = args[:path]
39
45
  @expires_in_seconds = args[:expires_in] || EXPIRES_IN_SECONDS
40
46
  raise ArgumentError.new :path unless @path
47
+ FileUtils.mkdir_p(@path) unless ::File.exists?(@path)
48
+
41
49
  @timer_struct_cache = FileCache.new(@path, "mp_timers")
42
50
  @timer_struct_lock = Mutex.new
43
51
  @user_view_cache = FileCache.new(@path, "mp_views")
@@ -40,10 +40,18 @@ module Rack
40
40
  self[:root] = TimerStruct::Request.createRoot(name, self)
41
41
  end
42
42
 
43
+ def name
44
+ @attributes[:name]
45
+ end
46
+
43
47
  def duration_ms
44
48
  @attributes[:root][:duration_milliseconds]
45
49
  end
46
50
 
51
+ def duration_ms_in_sql
52
+ @attributes[:duration_milliseconds_in_sql]
53
+ end
54
+
47
55
  def root
48
56
  @attributes[:root]
49
57
  end
@@ -44,10 +44,18 @@ module Rack
44
44
  @page = page
45
45
  end
46
46
 
47
+ def name
48
+ @attributes[:name]
49
+ end
50
+
47
51
  def duration_ms
48
52
  self[:duration_milliseconds]
49
53
  end
50
54
 
55
+ def duration_ms_in_sql
56
+ @attributes[:duration_milliseconds_in_sql]
57
+ end
58
+
51
59
  def start_ms
52
60
  self[:start_milliseconds]
53
61
  end
@@ -17,11 +17,11 @@ module Rack
17
17
  (
18
18
  (
19
19
  Rack::MiniProfiler.config.backtrace_includes.nil? or
20
- Rack::MiniProfiler.config.backtrace_includes.all?{|regex| ln =~ regex}
20
+ Rack::MiniProfiler.config.backtrace_includes.any?{|regex| ln =~ regex}
21
21
  ) and
22
22
  (
23
23
  Rack::MiniProfiler.config.backtrace_ignores.nil? or
24
- Rack::MiniProfiler.config.backtrace_ignores.all?{|regex| !(ln =~ regex)}
24
+ Rack::MiniProfiler.config.backtrace_ignores.none?{|regex| ln =~ regex}
25
25
  )
26
26
  )
27
27
  stack_trace << ln << "\n"
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  class MiniProfiler
3
- VERSION = '0.9.4'
3
+ VERSION = '0.9.9'
4
4
  end
5
5
  end
@@ -4,9 +4,9 @@ module Rack::MiniProfilerRails
4
4
 
5
5
  # call direct if needed to do a defer init
6
6
  def self.initialize!(app)
7
-
7
+
8
8
  raise "MiniProfilerRails initialized twice. Set `require: false' for rack-mini-profiler in your Gemfile" if @already_initialized
9
-
9
+
10
10
  c = Rack::MiniProfiler.config
11
11
 
12
12
  # By default, only show the MiniProfiler in development mode.
@@ -24,8 +24,11 @@ module Rack::MiniProfilerRails
24
24
 
25
25
  c.skip_paths ||= []
26
26
 
27
+ if serves_static_assets?(app)
28
+ c.skip_paths << app.config.assets.prefix
29
+ end
30
+
27
31
  if Rails.env.development?
28
- c.skip_paths << app.config.assets.prefix if app.respond_to? :assets
29
32
  c.skip_schema_queries = true
30
33
  end
31
34
 
@@ -40,7 +43,6 @@ module Rack::MiniProfilerRails
40
43
  # The file store is just so much less flaky
41
44
  base_path = Rails.application.config.paths['tmp'].first rescue "#{Rails.root}/tmp"
42
45
  tmp = base_path + '/miniprofiler'
43
- FileUtils.mkdir_p(tmp) unless File.exists?(tmp)
44
46
 
45
47
  c.storage_options = {:path => tmp}
46
48
  c.storage = Rack::MiniProfiler::FileStore
@@ -60,10 +62,26 @@ module Rack::MiniProfilerRails
60
62
  ActiveSupport.on_load(:action_view) do
61
63
  ::Rack::MiniProfiler.profile_method(ActionView::Template, :render) {|x,y| "Rendering: #{@virtual_path}"}
62
64
  end
63
-
65
+
64
66
  @already_initialized = true
65
67
  end
66
68
 
69
+ def self.serves_static_assets?(app)
70
+ config = app.config
71
+
72
+ if !config.respond_to?(:assets) || !config.assets.respond_to?(:prefix)
73
+ return false
74
+ end
75
+
76
+ if ::Rails.version >= "5.0.0"
77
+ ::Rails.configuration.public_file_server.enabled
78
+ elsif ::Rails.version >= "4.2.0"
79
+ ::Rails.configuration.serve_static_files
80
+ else
81
+ ::Rails.configuration.serve_static_assets
82
+ end
83
+ end
84
+
67
85
  class Railtie < ::Rails::Railtie
68
86
 
69
87
  initializer "rack_mini_profiler.configure_rails_initialization" do |app|
@@ -21,6 +21,8 @@ module Rack
21
21
  rval = log_without_miniprofiler(*args, &block)
22
22
 
23
23
  # Don't log schema queries if the option is set
24
+ # return rval unless sql =~ /\"vms\"/
25
+ # return rval unless sql =~ /\"(vms|ext_management_systems)\"/
24
26
  return rval if Rack::MiniProfiler.config.skip_schema_queries and name =~ /SCHEMA/
25
27
 
26
28
  elapsed_time = SqlPatches.elapsed_time(start)
@@ -0,0 +1,16 @@
1
+ # Mongo/Mongoid 5 patches
2
+ class Mongo::Server::Connection
3
+ def dispatch_with_timing(*args, &blk)
4
+ return dispatch_without_timing(*args, &blk) unless SqlPatches.should_measure?
5
+
6
+ result, _record = SqlPatches.record_sql(args[0][0].payload.inspect) do
7
+ dispatch_without_timing(*args, &blk)
8
+ end
9
+ return result
10
+ end
11
+
12
+ # TODO: change to Module#prepend as soon as Ruby 1.9.3 support is dropped
13
+ alias_method :dispatch_without_timing, :dispatch
14
+ alias_method :dispatch, :dispatch_with_timing
15
+
16
+ end
@@ -0,0 +1,14 @@
1
+ class Neo4j::Core::Query
2
+ alias_method :response_without_miniprofiler, :response
3
+
4
+ def response
5
+ return @response if @response
6
+ start = Time.now
7
+ rval = response_without_miniprofiler
8
+ elapsed_time = SqlPatches.elapsed_time(start)
9
+ Rack::MiniProfiler.record_sql(to_cypher, elapsed_time)
10
+ rval
11
+ end
12
+
13
+ alias_method :response_with_miniprofiler, :response
14
+ end
@@ -0,0 +1,29 @@
1
+ class Rack::MiniProfiler::NoBrainerProfiler
2
+
3
+ def on_query(env)
4
+ if SqlPatches.should_measure?
5
+ not_indexed = env[:criteria] && env[:criteria].where_present? &&
6
+ !env[:criteria].where_indexed? &&
7
+ !env[:criteria].model.try(:perf_warnings_disabled)
8
+
9
+ query = ""
10
+
11
+ # per-model/query database overrides
12
+ query << "[#{env[:options][:db]}] " if env[:options][:db]
13
+
14
+ # "read", "write" prefix
15
+ # query << "(#{NoBrainer::RQL.type_of(env[:query]).to_s}) "
16
+
17
+ query << "NOT USING INDEX: " if not_indexed
18
+ query << env[:query].inspect.gsub(/\n/, '').gsub(/ +/, ' ') + " "
19
+
20
+ if env[:exception]
21
+ query << "exception: #{env[:exception].class} #{env[:exception].message.split("\n").first} "
22
+ end
23
+
24
+ ::Rack::MiniProfiler.record_sql query.strip, env[:duration] * 1000.0
25
+ end
26
+ end
27
+
28
+ NoBrainer::Profiler.register self.new
29
+ end
@@ -0,0 +1,70 @@
1
+ class ActiveRecord::Result
2
+ alias_method :each_without_profiling, :each
3
+ def each(&blk)
4
+ return each_without_profiling(&blk) unless @miniprofiler_sql_id
5
+
6
+ start = Time.now
7
+ result = each_without_profiling(&blk)
8
+ elapsed_time = SqlPatches.elapsed_time(start)
9
+ @miniprofiler_sql_id.report_reader_duration(elapsed_time)
10
+
11
+ result
12
+ end
13
+ end
14
+
15
+ class ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter
16
+ SCHEMA_QUERY_TYPES = ["Sequence", "Primary Key", "Primary Key Trigger", nil].freeze
17
+
18
+ alias_method :execute_without_profiling, :execute
19
+ def execute(sql, name = nil)
20
+ mp_profile_sql(sql, name) { execute_without_profiling(sql, name) }
21
+ end
22
+
23
+ alias_method :exec_query_without_profiling, :exec_query
24
+ def exec_query(sql, name = 'SQL', binds = [])
25
+ mp_profile_sql(sql, name) { exec_query_without_profiling(sql, name, binds) }
26
+ end
27
+
28
+ alias_method :exec_insert_without_profiling, :exec_insert
29
+ def exec_insert(sql, name, binds, pk = nil, sequence_name = nil)
30
+ mp_profile_sql(sql, name) { exec_insert_without_profiling(sql, name, binds, pk, sequence_name) }
31
+ end
32
+
33
+ alias_method :exec_update_without_profiling, :exec_update
34
+ def exec_update(sql, name, binds)
35
+ mp_profile_sql(sql, name) { exec_update_without_profiling(sql, name, binds) }
36
+ end
37
+
38
+ # See oracle-enhanced/lib/active_record/connection_adapters/oracle_enhanced_database_statements.rb:183
39
+ # where the exec delete method is aliased in the same way. We just have to do it again here to make sure
40
+ # the new exec_delete alias is linked to our profiling-enabled version.
41
+ alias :exec_delete :exec_update
42
+
43
+ private
44
+
45
+ def mp_profile_sql(sql, name, &blk)
46
+ return yield unless mp_should_measure?(name)
47
+
48
+ start = Time.now
49
+ result = yield
50
+ elapsed_time = SqlPatches.elapsed_time(start)
51
+ record = ::Rack::MiniProfiler.record_sql(sql, elapsed_time)
52
+
53
+ # Some queries return the row count as a Fixnum and will be frozen, don't save a record
54
+ # for those.
55
+ result.instance_variable_set("@miniprofiler_sql_id", record) if (result && !result.frozen?)
56
+
57
+ result
58
+ end
59
+
60
+ # Only measure when profiling is enabled
61
+ # When skip_schema_queries is set to true, it will ignore any query of the types
62
+ # in the schema_query_types array
63
+ def mp_should_measure?(name)
64
+ return false unless SqlPatches.should_measure?
65
+
66
+ !(Rack::MiniProfiler.config.skip_schema_queries && SCHEMA_QUERY_TYPES.include?(name))
67
+ end
68
+ end
69
+
70
+ SqlPatches.patched = true
@@ -0,0 +1,103 @@
1
+ # riak-client 2.2.2 patches
2
+ class Riak::Multiget
3
+ class <<self
4
+ alias_method :get_all_without_profiling, :get_all
5
+ def get_all(client, fetch_list)
6
+ return get_all_without_profiling(client, fetch_list) unless SqlPatches.should_measure?
7
+
8
+ start = Time.now
9
+ result = get_all_without_profiling(client, fetch_list)
10
+ elapsed_time = SqlPatches.elapsed_time(start)
11
+ record = ::Rack::MiniProfiler.record_sql("get_all size=#{fetch_list.size}", elapsed_time)
12
+
13
+ result
14
+ end
15
+ end
16
+ end
17
+
18
+ class Riak::Client
19
+
20
+ alias_method :buckets_without_profiling, :buckets
21
+ def buckets(options={}, &blk)
22
+ profile("buckets #{options}") { buckets_without_profiling(options, &blk) }
23
+ end
24
+
25
+ alias_method :client_id_without_profiling, :client_id
26
+ def client_id
27
+ profile("client_id") { client_id_without_profiling }
28
+ end
29
+
30
+ alias_method :delete_object_without_profiling, :delete_object
31
+ def delete_object(bucket, key, options={})
32
+ profile("delete_object bucket=#{bucket.name} key=#{key} options=#{options}") { delete_object_without_profiling(bucket, key, options) }
33
+ end
34
+
35
+ alias_method :get_bucket_props_without_profiling, :get_bucket_props
36
+ def get_bucket_props(bucket, options={})
37
+ profile("get_bucket_props bucket=#{bucket.name} options=#{options}") { get_bucket_props_without_profiling(bucket, options) }
38
+ end
39
+
40
+ alias_method :get_index_without_profiling, :get_index
41
+ def get_index(bucket, index, query, options={})
42
+ profile("get_index bucket=#{bucket.name} index=#{index} query=#{query} options=#{options}") { get_index_without_profiling(bucket, index, query, options) }
43
+ end
44
+
45
+ alias_method :get_preflist_without_profiling, :get_preflist
46
+ def get_preflist(bucket, key, type=nil, options={})
47
+ profile("get_preflist bucket=#{bucket.name} key=#{key} type=#{type} options=#{options}") { get_preflist_without_profiling(bucket, key, type, options) }
48
+ end
49
+
50
+ alias_method :get_object_without_profiling, :get_object
51
+ def get_object(bucket, key, options={})
52
+ profile("get_object bucket=#{bucket.name} key=#{key} options=#{options}") { get_object_without_profiling(bucket, key, options) }
53
+ end
54
+
55
+ alias_method :list_keys_without_profiling, :list_keys
56
+ def list_keys(bucket, options={}, &block)
57
+ profile("list_keys bucket=#{bucket.name} options=#{options}") { list_keys_without_profiling(bucket, options, &block) }
58
+ end
59
+
60
+ alias_method :mapred_without_profiling, :mapred
61
+ def mapred(mr, &block)
62
+ profile("mapred") { mapred_without_profiling(mr, &block) }
63
+ end
64
+
65
+ alias_method :ping_without_profiling, :ping
66
+ def ping
67
+ profile("ping") { ping_without_profiling }
68
+ end
69
+
70
+ alias_method :reload_object_without_profiling, :reload_object
71
+ def reload_object(object, options={})
72
+ profile("reload_object bucket=#{object.bucket.name} key=#{object.key} vclock=#{object.vclock} options=#{options}") { reload_object_without_profiling(object, options) }
73
+ end
74
+
75
+ alias_method :set_bucket_props_without_profiling, :set_bucket_props
76
+ def set_bucket_props(bucket, properties, type=nil)
77
+ profile("set_bucket_props bucket=#{bucket.name} type=#{type}") { set_bucket_props_without_profiling(bucket, properties, type) }
78
+ end
79
+
80
+ alias_method :clear_bucket_props_without_profiling, :clear_bucket_props
81
+ def clear_bucket_props(bucket, options={})
82
+ profile("clear_bucket_props bucket=#{bucket.name} options=#{options}") { clear_bucket_props_without_profiling(bucket, options) }
83
+ end
84
+
85
+ alias_method :store_object_without_profiling, :store_object
86
+ def store_object(object, options={})
87
+ profile("store_object bucket=#{object.bucket.name} key=#{object.key} vclock=#{object.vclock} options=#{options}") { store_object_without_profiling(object, options) }
88
+ end
89
+
90
+ private
91
+
92
+ def profile(request, &blk)
93
+ return yield unless SqlPatches.should_measure?
94
+
95
+ start = Time.now
96
+ result = yield
97
+ elapsed_time = SqlPatches.elapsed_time(start)
98
+ record = ::Rack::MiniProfiler.record_sql(request, elapsed_time)
99
+
100
+ result
101
+ end
102
+
103
+ end