rack-mini-profiler 0.1.20 → 0.1.25

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.

Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/Ruby/CHANGELOG +130 -0
  3. data/{README.md → Ruby/README.md} +40 -9
  4. data/Ruby/lib/html/flamegraph.html +325 -0
  5. data/Ruby/lib/html/includes.css +451 -0
  6. data/{lib → Ruby/lib}/html/includes.js +135 -24
  7. data/{lib → Ruby/lib}/html/includes.less +38 -35
  8. data/{lib → Ruby/lib}/html/includes.tmpl +40 -15
  9. data/{lib → Ruby/lib}/html/jquery.1.7.1.js +1 -1
  10. data/{lib → Ruby/lib}/html/jquery.tmpl.js +1 -1
  11. data/{lib → Ruby/lib}/html/list.css +0 -0
  12. data/{lib → Ruby/lib}/html/list.js +7 -6
  13. data/{lib → Ruby/lib}/html/list.tmpl +0 -0
  14. data/Ruby/lib/html/profile_handler.js +1 -0
  15. data/{lib → Ruby/lib}/html/share.html +0 -0
  16. data/{lib → Ruby/lib}/mini_profiler/client_settings.rb +0 -0
  17. data/{lib → Ruby/lib}/mini_profiler/client_timer_struct.rb +1 -1
  18. data/{lib → Ruby/lib}/mini_profiler/config.rb +57 -52
  19. data/{lib → Ruby/lib}/mini_profiler/context.rb +11 -10
  20. data/Ruby/lib/mini_profiler/custom_timer_struct.rb +22 -0
  21. data/Ruby/lib/mini_profiler/flame_graph.rb +54 -0
  22. data/Ruby/lib/mini_profiler/gc_profiler.rb +107 -0
  23. data/{lib → Ruby/lib}/mini_profiler/page_timer_struct.rb +7 -2
  24. data/{lib → Ruby/lib}/mini_profiler/profiler.rb +206 -196
  25. data/{lib → Ruby/lib}/mini_profiler/profiling_methods.rb +131 -100
  26. data/{lib → Ruby/lib}/mini_profiler/request_timer_struct.rb +20 -1
  27. data/{lib → Ruby/lib}/mini_profiler/sql_timer_struct.rb +0 -0
  28. data/{lib → Ruby/lib}/mini_profiler/storage/abstract_store.rb +31 -27
  29. data/{lib → Ruby/lib}/mini_profiler/storage/file_store.rb +111 -109
  30. data/Ruby/lib/mini_profiler/storage/memcache_store.rb +53 -0
  31. data/{lib → Ruby/lib}/mini_profiler/storage/memory_store.rb +65 -63
  32. data/Ruby/lib/mini_profiler/storage/redis_store.rb +54 -0
  33. data/{lib → Ruby/lib}/mini_profiler/timer_struct.rb +0 -0
  34. data/Ruby/lib/mini_profiler/version.rb +5 -0
  35. data/{lib → Ruby/lib}/mini_profiler_rails/railtie.rb +3 -2
  36. data/Ruby/lib/patches/net_patches.rb +14 -0
  37. data/{lib → Ruby/lib}/patches/sql_patches.rb +89 -48
  38. data/{lib → Ruby/lib}/rack-mini-profiler.rb +2 -1
  39. data/rack-mini-profiler.gemspec +8 -6
  40. metadata +56 -65
  41. data/CHANGELOG +0 -93
  42. data/lib/html/includes.css +0 -75
  43. data/lib/html/profile_handler.js +0 -62
  44. data/lib/mini_profiler/storage/redis_store.rb +0 -44
@@ -1,100 +1,131 @@
1
- module Rack
2
- class MiniProfiler
3
- module ProfilingMethods
4
-
5
- def record_sql(query, elapsed_ms)
6
- c = current
7
- return unless c
8
- c.current_timer.add_sql(query, elapsed_ms, c.page_struct, c.skip_backtrace, c.full_backtrace) if (c && c.current_timer)
9
- end
10
-
11
- def start_step(name)
12
- if current
13
- parent_timer = current.current_timer
14
- current.current_timer = current_timer = current.current_timer.add_child(name)
15
- [current_timer,parent_timer]
16
- end
17
- end
18
-
19
- def finish_step(obj)
20
- if obj && current
21
- current_timer, parent_timer = obj
22
- current_timer.record_time
23
- current.current_timer = parent_timer
24
- end
25
- end
26
-
27
- # perform a profiling step on given block
28
- def step(name, opts = nil)
29
- if current
30
- parent_timer = current.current_timer
31
- result = nil
32
- current.current_timer = current_timer = current.current_timer.add_child(name)
33
- begin
34
- result = yield if block_given?
35
- ensure
36
- current_timer.record_time
37
- current.current_timer = parent_timer
38
- end
39
- else
40
- yield if block_given?
41
- end
42
- end
43
-
44
- def unprofile_method(klass, method)
45
-
46
- clean = clean_method_name(method)
47
-
48
- with_profiling = ("#{clean}_with_mini_profiler").intern
49
- without_profiling = ("#{clean}_without_mini_profiler").intern
50
-
51
- if klass.send :method_defined?, with_profiling
52
- klass.send :alias_method, method, without_profiling
53
- klass.send :remove_method, with_profiling
54
- klass.send :remove_method, without_profiling
55
- end
56
- end
57
-
58
- def profile_method(klass, method, &blk)
59
- default_name = klass.to_s + " " + method.to_s
60
- clean = clean_method_name(method)
61
-
62
- with_profiling = ("#{clean}_with_mini_profiler").intern
63
- without_profiling = ("#{clean}_without_mini_profiler").intern
64
-
65
- if klass.send :method_defined?, with_profiling
66
- return # dont double profile
67
- end
68
-
69
- klass.send :alias_method, without_profiling, method
70
- klass.send :define_method, with_profiling do |*args, &orig|
71
- return self.send without_profiling, *args, &orig unless Rack::MiniProfiler.current
72
-
73
- name = default_name
74
- name = blk.bind(self).call(*args) if blk
75
-
76
- parent_timer = Rack::MiniProfiler.current.current_timer
77
- page_struct = Rack::MiniProfiler.current.page_struct
78
- result = nil
79
-
80
- Rack::MiniProfiler.current.current_timer = current_timer = parent_timer.add_child(name)
81
- begin
82
- result = self.send without_profiling, *args, &orig
83
- ensure
84
- current_timer.record_time
85
- Rack::MiniProfiler.current.current_timer = parent_timer
86
- end
87
- result
88
- end
89
- klass.send :alias_method, method, with_profiling
90
- end
91
-
92
- private
93
-
94
- def clean_method_name(method)
95
- method.to_s.gsub(/[\?\!]/, "")
96
- end
97
-
98
- end
99
- end
100
- end
1
+ module Rack
2
+ class MiniProfiler
3
+ module ProfilingMethods
4
+
5
+ def record_sql(query, elapsed_ms)
6
+ c = current
7
+ return unless c
8
+ c.current_timer.add_sql(query, elapsed_ms, c.page_struct, c.skip_backtrace, c.full_backtrace) if (c && c.current_timer)
9
+ end
10
+
11
+ def start_step(name)
12
+ if current
13
+ parent_timer = current.current_timer
14
+ current.current_timer = current_timer = current.current_timer.add_child(name)
15
+ [current_timer,parent_timer]
16
+ end
17
+ end
18
+
19
+ def finish_step(obj)
20
+ if obj && current
21
+ current_timer, parent_timer = obj
22
+ current_timer.record_time
23
+ current.current_timer = parent_timer
24
+ end
25
+ end
26
+
27
+ # perform a profiling step on given block
28
+ def step(name, opts = nil)
29
+ if current
30
+ parent_timer = current.current_timer
31
+ result = nil
32
+ current.current_timer = current_timer = current.current_timer.add_child(name)
33
+ begin
34
+ result = yield if block_given?
35
+ ensure
36
+ current_timer.record_time
37
+ current.current_timer = parent_timer
38
+ end
39
+ else
40
+ yield if block_given?
41
+ end
42
+ end
43
+
44
+ def unprofile_method(klass, method)
45
+
46
+ clean = clean_method_name(method)
47
+
48
+ with_profiling = ("#{clean}_with_mini_profiler").intern
49
+ without_profiling = ("#{clean}_without_mini_profiler").intern
50
+
51
+ if klass.send :method_defined?, with_profiling
52
+ klass.send :alias_method, method, without_profiling
53
+ klass.send :remove_method, with_profiling
54
+ klass.send :remove_method, without_profiling
55
+ end
56
+ end
57
+
58
+ def profile_method(klass, method, &blk)
59
+ default_name = klass.to_s + " " + method.to_s
60
+ clean = clean_method_name(method)
61
+
62
+ with_profiling = ("#{clean}_with_mini_profiler").intern
63
+ without_profiling = ("#{clean}_without_mini_profiler").intern
64
+
65
+ if klass.send :method_defined?, with_profiling
66
+ return # dont double profile
67
+ end
68
+
69
+ klass.send :alias_method, without_profiling, method
70
+ klass.send :define_method, with_profiling do |*args, &orig|
71
+ return self.send without_profiling, *args, &orig unless Rack::MiniProfiler.current
72
+
73
+ name = default_name
74
+ if blk
75
+ name =
76
+ if respond_to?(:instance_exec)
77
+ instance_exec(*args, &blk)
78
+ else
79
+ # deprecated in Rails 4.x
80
+ blk.bind(self).call(*args)
81
+ end
82
+ end
83
+
84
+ parent_timer = Rack::MiniProfiler.current.current_timer
85
+ page_struct = Rack::MiniProfiler.current.page_struct
86
+ result = nil
87
+
88
+ Rack::MiniProfiler.current.current_timer = current_timer = parent_timer.add_child(name)
89
+ begin
90
+ result = self.send without_profiling, *args, &orig
91
+ ensure
92
+ current_timer.record_time
93
+ Rack::MiniProfiler.current.current_timer = parent_timer
94
+ end
95
+ result
96
+ end
97
+ klass.send :alias_method, method, with_profiling
98
+ end
99
+
100
+ # Add a custom timing. These are displayed similar to SQL/query time in
101
+ # columns expanding to the right.
102
+ #
103
+ # type - String counter type. Each distinct type gets its own column.
104
+ # duration_ms - Duration of the call in ms. Either this or a block must be
105
+ # given but not both.
106
+ #
107
+ # When a block is given, calculate the duration by yielding to the block
108
+ # and keeping a record of its run time.
109
+ #
110
+ # Returns the result of the block, or nil when no block is given.
111
+ def counter(type, duration_ms=nil)
112
+ result = nil
113
+ if block_given?
114
+ start = Time.now
115
+ result = yield
116
+ duration_ms = (Time.now - start).to_f * 1000
117
+ end
118
+ return result if current.nil? || !request_authorized?
119
+ current.current_timer.add_custom(type, duration_ms, current.page_struct)
120
+ result
121
+ end
122
+
123
+ private
124
+
125
+ def clean_method_name(method)
126
+ method.to_s.gsub(/[\?\!]/, "")
127
+ end
128
+
129
+ end
130
+ end
131
+ end
@@ -33,7 +33,9 @@ module Rack
33
33
  "Depth"=> parent ? parent.depth + 1 : 0,
34
34
  "ExecutedReaders"=> 0,
35
35
  "ExecutedScalars"=> 0,
36
- "ExecutedNonQueries"=> 0)
36
+ "ExecutedNonQueries"=> 0,
37
+ "CustomTimingStats" => {},
38
+ "CustomTimings" => {})
37
39
  @children_duration = 0
38
40
  @start = Time.now
39
41
  @parent = parent
@@ -79,6 +81,23 @@ module Rack
79
81
  timer
80
82
  end
81
83
 
84
+ def add_custom(type, elapsed_ms, page)
85
+ timer = CustomTimerStruct.new(type, elapsed_ms, page, self)
86
+ timer['ParentTimingId'] = self['Id']
87
+ self['CustomTimings'][type] ||= []
88
+ self['CustomTimings'][type].push(timer)
89
+
90
+ self['CustomTimingStats'][type] ||= {"Count" => 0, "Duration" => 0.0}
91
+ self['CustomTimingStats'][type]['Count'] += 1
92
+ self['CustomTimingStats'][type]['Duration'] += elapsed_ms
93
+
94
+ page['CustomTimingStats'][type] ||= {"Count" => 0, "Duration" => 0.0}
95
+ page['CustomTimingStats'][type]['Count'] += 1
96
+ page['CustomTimingStats'][type]['Duration'] += elapsed_ms
97
+
98
+ timer
99
+ end
100
+
82
101
  def record_time(milliseconds = nil)
83
102
  milliseconds ||= (Time.now - @start) * 1000
84
103
  self['DurationMilliseconds'] = milliseconds
@@ -1,27 +1,31 @@
1
- module Rack
2
- class MiniProfiler
3
- class AbstractStore
4
-
5
- def save(page_struct)
6
- raise NotImplementedError.new("save is not implemented")
7
- end
8
-
9
- def load(id)
10
- raise NotImplementedError.new("load is not implemented")
11
- end
12
-
13
- def set_unviewed(user, id)
14
- raise NotImplementedError.new("set_unviewed is not implemented")
15
- end
16
-
17
- def set_viewed(user, id)
18
- raise NotImplementedError.new("set_viewed is not implemented")
19
- end
20
-
21
- def get_unviewed_ids(user)
22
- raise NotImplementedError.new("get_unviewed_ids is not implemented")
23
- end
24
-
25
- end
26
- end
27
- end
1
+ module Rack
2
+ class MiniProfiler
3
+ class AbstractStore
4
+
5
+ def save(page_struct)
6
+ raise NotImplementedError.new("save is not implemented")
7
+ end
8
+
9
+ def load(id)
10
+ raise NotImplementedError.new("load is not implemented")
11
+ end
12
+
13
+ def set_unviewed(user, id)
14
+ raise NotImplementedError.new("set_unviewed is not implemented")
15
+ end
16
+
17
+ def set_viewed(user, id)
18
+ raise NotImplementedError.new("set_viewed is not implemented")
19
+ end
20
+
21
+ def get_unviewed_ids(user)
22
+ raise NotImplementedError.new("get_unviewed_ids is not implemented")
23
+ end
24
+
25
+ def diagnostics(user)
26
+ raise NotImplementedError.new("diagnostics not implemented")
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -1,109 +1,111 @@
1
- module Rack
2
- class MiniProfiler
3
- class FileStore < AbstractStore
4
-
5
- class FileCache
6
- def initialize(path, prefix)
7
- @path = path
8
- @prefix = prefix
9
- end
10
-
11
- def [](key)
12
- begin
13
- data = ::File.open(path(key),"rb") {|f| f.read}
14
- return Marshal.load data
15
- rescue => e
16
- return nil
17
- end
18
- end
19
-
20
- def []=(key,val)
21
- ::File.open(path(key), "wb+") {|f| f.write Marshal.dump(val)}
22
- end
23
-
24
- private
25
- def path(key)
26
- @path + "/" + @prefix + "_" + key
27
- end
28
- end
29
-
30
- EXPIRE_TIMER_CACHE = 3600 * 24
31
-
32
- def initialize(args)
33
- @path = args[:path]
34
- raise ArgumentError.new :path unless @path
35
- @timer_struct_cache = FileCache.new(@path, "mp_timers")
36
- @timer_struct_lock = Mutex.new
37
- @user_view_cache = FileCache.new(@path, "mp_views")
38
- @user_view_lock = Mutex.new
39
-
40
- me = self
41
- Thread.new do
42
- begin
43
- while true do
44
- # TODO: a sane retry count before bailing
45
- me.cleanup_cache
46
- sleep(3600)
47
- end
48
- rescue
49
- # don't crash the thread, we can clean up next time
50
- end
51
- end
52
- end
53
-
54
- def save(page_struct)
55
- @timer_struct_lock.synchronize {
56
- @timer_struct_cache[page_struct['Id']] = page_struct
57
- }
58
- end
59
-
60
- def load(id)
61
- @timer_struct_lock.synchronize {
62
- @timer_struct_cache[id]
63
- }
64
- end
65
-
66
- def set_unviewed(user, id)
67
- @user_view_lock.synchronize {
68
- current = @user_view_cache[user]
69
- current = [] unless Array === current
70
- current << id
71
- @user_view_cache[user] = current.uniq
72
- }
73
- end
74
-
75
- def set_viewed(user, id)
76
- @user_view_lock.synchronize {
77
- @user_view_cache[user] ||= []
78
- current = @user_view_cache[user]
79
- current = [] unless Array === current
80
- current.delete(id)
81
- @user_view_cache[user] = current.uniq
82
- }
83
- end
84
-
85
- def get_unviewed_ids(user)
86
- @user_view_lock.synchronize {
87
- @user_view_cache[user]
88
- }
89
- end
90
-
91
- def cleanup_cache
92
- files = Dir.entries(@path)
93
- @timer_struct_lock.synchronize {
94
- files.each do |f|
95
- f = @path + '/' + f
96
- File.delete f if f =~ /^mp_timers/ and (Time.now - File.mtime(f)) > EXPIRE_TIMER_CACHE
97
- end
98
- }
99
- @user_view_lock.synchronize {
100
- files.each do |f|
101
- f = @path + '/' + f
102
- File.delete f if f =~ /^mp_views/ and (Time.now - File.mtime(f)) > EXPIRE_TIMER_CACHE
103
- end
104
- }
105
- end
106
-
107
- end
108
- end
109
- end
1
+ module Rack
2
+ class MiniProfiler
3
+ class FileStore < AbstractStore
4
+
5
+ class FileCache
6
+ def initialize(path, prefix)
7
+ @path = path
8
+ @prefix = prefix
9
+ end
10
+
11
+ def [](key)
12
+ begin
13
+ data = ::File.open(path(key),"rb") {|f| f.read}
14
+ return Marshal.load data
15
+ rescue => e
16
+ return nil
17
+ end
18
+ end
19
+
20
+ def []=(key,val)
21
+ ::File.open(path(key), "wb+") {|f| f.write Marshal.dump(val)}
22
+ end
23
+
24
+ private
25
+ def path(key)
26
+ @path + "/" + @prefix + "_" + key
27
+ end
28
+ end
29
+
30
+ EXPIRES_IN_SECONDS = 60 * 60 * 24
31
+
32
+ def initialize(args = nil)
33
+ args ||= {}
34
+ @path = args[:path]
35
+ @expires_in_seconds = args[:expires_in] || EXPIRES_IN_SECONDS
36
+ raise ArgumentError.new :path unless @path
37
+ @timer_struct_cache = FileCache.new(@path, "mp_timers")
38
+ @timer_struct_lock = Mutex.new
39
+ @user_view_cache = FileCache.new(@path, "mp_views")
40
+ @user_view_lock = Mutex.new
41
+
42
+ me = self
43
+ Thread.new do
44
+ begin
45
+ while true do
46
+ # TODO: a sane retry count before bailing
47
+ me.cleanup_cache
48
+ sleep(3600)
49
+ end
50
+ rescue
51
+ # don't crash the thread, we can clean up next time
52
+ end
53
+ end
54
+ end
55
+
56
+ def save(page_struct)
57
+ @timer_struct_lock.synchronize {
58
+ @timer_struct_cache[page_struct['Id']] = page_struct
59
+ }
60
+ end
61
+
62
+ def load(id)
63
+ @timer_struct_lock.synchronize {
64
+ @timer_struct_cache[id]
65
+ }
66
+ end
67
+
68
+ def set_unviewed(user, id)
69
+ @user_view_lock.synchronize {
70
+ current = @user_view_cache[user]
71
+ current = [] unless Array === current
72
+ current << id
73
+ @user_view_cache[user] = current.uniq
74
+ }
75
+ end
76
+
77
+ def set_viewed(user, id)
78
+ @user_view_lock.synchronize {
79
+ @user_view_cache[user] ||= []
80
+ current = @user_view_cache[user]
81
+ current = [] unless Array === current
82
+ current.delete(id)
83
+ @user_view_cache[user] = current.uniq
84
+ }
85
+ end
86
+
87
+ def get_unviewed_ids(user)
88
+ @user_view_lock.synchronize {
89
+ @user_view_cache[user]
90
+ }
91
+ end
92
+
93
+ def cleanup_cache
94
+ files = Dir.entries(@path)
95
+ @timer_struct_lock.synchronize {
96
+ files.each do |f|
97
+ f = @path + '/' + f
98
+ ::File.delete f if ::File.basename(f) =~ /^mp_timers/ and (Time.now - ::File.mtime(f)) > @expires_in_seconds
99
+ end
100
+ }
101
+ @user_view_lock.synchronize {
102
+ files.each do |f|
103
+ f = @path + '/' + f
104
+ ::File.delete f if ::File.basename(f) =~ /^mp_views/ and (Time.now - ::File.mtime(f)) > @expires_in_seconds
105
+ end
106
+ }
107
+ end
108
+
109
+ end
110
+ end
111
+ end