rack-mini-profiler 0.1.21 → 0.1.26

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


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

Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/Ruby/CHANGELOG +135 -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/{lib → Ruby/lib}/mini_profiler/gc_profiler.rb +35 -12
  23. data/{lib → Ruby/lib}/mini_profiler/page_timer_struct.rb +7 -2
  24. data/{lib → Ruby/lib}/mini_profiler/profiler.rb +209 -144
  25. data/{lib → Ruby/lib}/mini_profiler/profiling_methods.rb +131 -108
  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/{lib → Ruby/lib}/mini_profiler/storage/memcache_store.rb +11 -9
  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/Ruby/lib/mini_profiler_rails/railtie.rb +89 -0
  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 +1 -0
  39. data/rack-mini-profiler.gemspec +6 -4
  40. metadata +53 -64
  41. data/CHANGELOG +0 -99
  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
  45. data/lib/mini_profiler_rails/railtie.rb +0 -85
@@ -1,108 +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
- 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
- private
101
-
102
- def clean_method_name(method)
103
- method.to_s.gsub(/[\?\!]/, "")
104
- end
105
-
106
- end
107
- end
108
- 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