wtf-tools 1.0.3 → 1.0.4
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/LICENSE +22 -22
- data/README.md +165 -164
- data/Rakefile +8 -8
- data/example/dump.rb +30 -30
- data/example/timing.rb +20 -20
- data/example/tracking.rb +32 -32
- data/lib/wtf-tools.rb +69 -69
- data/lib/wtf/dumper.rb +144 -113
- data/lib/wtf/method_tracker.rb +90 -90
- data/lib/wtf/query_tracker.rb +48 -48
- data/wtf-tools.gemspec +24 -24
- metadata +1 -1
data/lib/wtf/method_tracker.rb
CHANGED
@@ -1,90 +1,90 @@
|
|
1
|
-
module WTF
|
2
|
-
module MethodTracker
|
3
|
-
class << self
|
4
|
-
def start_tracking(*objects)
|
5
|
-
require 'absolute_time'
|
6
|
-
|
7
|
-
objects.each do |object|
|
8
|
-
klass = object.is_a?(Module) ? object : object.class
|
9
|
-
prepare(klass)
|
10
|
-
end
|
11
|
-
reset_state
|
12
|
-
end
|
13
|
-
|
14
|
-
def prepare(base)
|
15
|
-
methods = base.instance_methods(false) + base.private_instance_methods(false)
|
16
|
-
compiled = methods.map do |name|
|
17
|
-
override_method(base, name)
|
18
|
-
end
|
19
|
-
base.module_eval %{
|
20
|
-
module Tracking
|
21
|
-
#{compiled.join}
|
22
|
-
end
|
23
|
-
prepend Tracking
|
24
|
-
}
|
25
|
-
end
|
26
|
-
|
27
|
-
def override_method(base, name)
|
28
|
-
%{
|
29
|
-
def #{name}(*args)
|
30
|
-
WTF::MethodTracker.on_start(#{base}, :#{name})
|
31
|
-
return_value = super
|
32
|
-
WTF::MethodTracker.on_end
|
33
|
-
return_value
|
34
|
-
end
|
35
|
-
}
|
36
|
-
end
|
37
|
-
|
38
|
-
attr_accessor :stats, :stack, :last_time, :last_heap
|
39
|
-
|
40
|
-
def reset_state
|
41
|
-
self.stats = Hash.new { |h,k| h[k] = { freq: 0, time: 0.0, heap: 0 } }
|
42
|
-
self.stack = [[nil, :top]]
|
43
|
-
self.last_time = AbsoluteTime.now
|
44
|
-
self.last_heap = GC.stat[:heap_length]
|
45
|
-
end
|
46
|
-
|
47
|
-
def on_start(*full_name)
|
48
|
-
add_stats(full_name)
|
49
|
-
stack.push(full_name)
|
50
|
-
end
|
51
|
-
|
52
|
-
def on_end
|
53
|
-
add_stats
|
54
|
-
stack.pop
|
55
|
-
end
|
56
|
-
|
57
|
-
def finish
|
58
|
-
add_stats
|
59
|
-
dump_stats
|
60
|
-
reset_state
|
61
|
-
end
|
62
|
-
|
63
|
-
def add_stats(at_start = nil)
|
64
|
-
stat = stats[stack.last]
|
65
|
-
|
66
|
-
this_time = AbsoluteTime.now
|
67
|
-
stat[:time] += this_time - last_time
|
68
|
-
self.last_time = this_time
|
69
|
-
|
70
|
-
this_heap = GC.stat[:heap_length]
|
71
|
-
stat[:heap] += this_heap - last_heap
|
72
|
-
self.last_heap = this_heap
|
73
|
-
|
74
|
-
stats[at_start][:freq] += 1 if at_start
|
75
|
-
end
|
76
|
-
|
77
|
-
def dump_stats
|
78
|
-
data = stats.map do |key, val|
|
79
|
-
[*key, val[:freq].to_i, val[:time].to_f.round(3), (val[:heap].to_f / 64).round(3)]
|
80
|
-
end
|
81
|
-
data = data.sort_by {|it| it[3] }.reverse
|
82
|
-
data.unshift(%w(class method count time heap_mb))
|
83
|
-
|
84
|
-
time = Time.now.strftime('%m%d_%H%M%S')
|
85
|
-
file = File.join(WTF.files_path, "track_#{time}_#{rand(10000)}.csv")
|
86
|
-
File.write(file, data.map(&:to_csv).join)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
1
|
+
module WTF
|
2
|
+
module MethodTracker
|
3
|
+
class << self
|
4
|
+
def start_tracking(*objects)
|
5
|
+
require 'absolute_time'
|
6
|
+
|
7
|
+
objects.each do |object|
|
8
|
+
klass = object.is_a?(Module) ? object : object.class
|
9
|
+
prepare(klass)
|
10
|
+
end
|
11
|
+
reset_state
|
12
|
+
end
|
13
|
+
|
14
|
+
def prepare(base)
|
15
|
+
methods = base.instance_methods(false) + base.private_instance_methods(false)
|
16
|
+
compiled = methods.map do |name|
|
17
|
+
override_method(base, name)
|
18
|
+
end
|
19
|
+
base.module_eval %{
|
20
|
+
module Tracking
|
21
|
+
#{compiled.join}
|
22
|
+
end
|
23
|
+
prepend Tracking
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def override_method(base, name)
|
28
|
+
%{
|
29
|
+
def #{name}(*args)
|
30
|
+
WTF::MethodTracker.on_start(#{base}, :#{name})
|
31
|
+
return_value = super
|
32
|
+
WTF::MethodTracker.on_end
|
33
|
+
return_value
|
34
|
+
end
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
attr_accessor :stats, :stack, :last_time, :last_heap
|
39
|
+
|
40
|
+
def reset_state
|
41
|
+
self.stats = Hash.new { |h,k| h[k] = { freq: 0, time: 0.0, heap: 0 } }
|
42
|
+
self.stack = [[nil, :top]]
|
43
|
+
self.last_time = AbsoluteTime.now
|
44
|
+
self.last_heap = GC.stat[:heap_length]
|
45
|
+
end
|
46
|
+
|
47
|
+
def on_start(*full_name)
|
48
|
+
add_stats(full_name)
|
49
|
+
stack.push(full_name)
|
50
|
+
end
|
51
|
+
|
52
|
+
def on_end
|
53
|
+
add_stats
|
54
|
+
stack.pop
|
55
|
+
end
|
56
|
+
|
57
|
+
def finish
|
58
|
+
add_stats
|
59
|
+
dump_stats
|
60
|
+
reset_state
|
61
|
+
end
|
62
|
+
|
63
|
+
def add_stats(at_start = nil)
|
64
|
+
stat = stats[stack.last]
|
65
|
+
|
66
|
+
this_time = AbsoluteTime.now
|
67
|
+
stat[:time] += this_time - last_time
|
68
|
+
self.last_time = this_time
|
69
|
+
|
70
|
+
this_heap = GC.stat[:heap_length]
|
71
|
+
stat[:heap] += this_heap - last_heap
|
72
|
+
self.last_heap = this_heap
|
73
|
+
|
74
|
+
stats[at_start][:freq] += 1 if at_start
|
75
|
+
end
|
76
|
+
|
77
|
+
def dump_stats
|
78
|
+
data = stats.map do |key, val|
|
79
|
+
[*key, val[:freq].to_i, val[:time].to_f.round(3), (val[:heap].to_f / 64).round(3)]
|
80
|
+
end
|
81
|
+
data = data.sort_by {|it| it[3] }.reverse
|
82
|
+
data.unshift(%w(class method count time heap_mb))
|
83
|
+
|
84
|
+
time = Time.now.strftime('%m%d_%H%M%S')
|
85
|
+
file = File.join(WTF.files_path, "track_#{time}_#{rand(10000)}.csv")
|
86
|
+
File.write(file, data.map(&:to_csv).join)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
data/lib/wtf/query_tracker.rb
CHANGED
@@ -1,48 +1,48 @@
|
|
1
|
-
module WTF
|
2
|
-
module QueryTracker
|
3
|
-
Trackable = Struct.new(:pattern, :options)
|
4
|
-
|
5
|
-
class << self
|
6
|
-
attr_reader :trackables
|
7
|
-
|
8
|
-
def start_tracking(pattern, options = {})
|
9
|
-
if @trackables.nil?
|
10
|
-
prepare_hook
|
11
|
-
@trackables = []
|
12
|
-
end
|
13
|
-
@trackables << Trackable.new(pattern, options)
|
14
|
-
end
|
15
|
-
|
16
|
-
def prepare_hook
|
17
|
-
ActiveRecord::ConnectionAdapters::AbstractAdapter.module_eval %{
|
18
|
-
module TrackingSQL
|
19
|
-
def log(sql, *args, &block)
|
20
|
-
WTF::QueryTracker.on_sql(sql)
|
21
|
-
super(sql, *args, &block)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
prepend TrackingSQL
|
25
|
-
}
|
26
|
-
end
|
27
|
-
|
28
|
-
def on_sql(sql)
|
29
|
-
trackables.each do |it|
|
30
|
-
if match(it.pattern, sql)
|
31
|
-
WTF::Dumper.new(:sql, sql, *caller.take(it.options[:size] || 30), :line).call
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def match(pattern, sql)
|
37
|
-
case pattern
|
38
|
-
when Regexp
|
39
|
-
pattern.match(sql)
|
40
|
-
when String
|
41
|
-
pattern == sql
|
42
|
-
when Proc
|
43
|
-
pattern.call(sql)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
1
|
+
module WTF
|
2
|
+
module QueryTracker
|
3
|
+
Trackable = Struct.new(:pattern, :options)
|
4
|
+
|
5
|
+
class << self
|
6
|
+
attr_reader :trackables
|
7
|
+
|
8
|
+
def start_tracking(pattern, options = {})
|
9
|
+
if @trackables.nil?
|
10
|
+
prepare_hook
|
11
|
+
@trackables = []
|
12
|
+
end
|
13
|
+
@trackables << Trackable.new(pattern, options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def prepare_hook
|
17
|
+
ActiveRecord::ConnectionAdapters::AbstractAdapter.module_eval %{
|
18
|
+
module TrackingSQL
|
19
|
+
def log(sql, *args, &block)
|
20
|
+
WTF::QueryTracker.on_sql(sql)
|
21
|
+
super(sql, *args, &block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
prepend TrackingSQL
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
def on_sql(sql)
|
29
|
+
trackables.each do |it|
|
30
|
+
if match(it.pattern, sql)
|
31
|
+
WTF::Dumper.new(:sql, sql, *caller.take(it.options[:size] || 30), :line).call
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def match(pattern, sql)
|
37
|
+
case pattern
|
38
|
+
when Regexp
|
39
|
+
pattern.match(sql)
|
40
|
+
when String
|
41
|
+
pattern == sql
|
42
|
+
when Proc
|
43
|
+
pattern.call(sql)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/wtf-tools.gemspec
CHANGED
@@ -1,24 +1,24 @@
|
|
1
|
-
Gem::Specification.new do |s|
|
2
|
-
s.name = 'wtf-tools'
|
3
|
-
s.version = '1.0.
|
4
|
-
s.date = '2016-07-01'
|
5
|
-
s.platform = Gem::Platform::RUBY
|
6
|
-
s.required_ruby_version = Gem::Requirement.new(">= 2.0.0")
|
7
|
-
s.summary = 'tools for debugging and profiling Ruby on Rails projects'
|
8
|
-
s.license = 'MIT'
|
9
|
-
|
10
|
-
s.description = <<-EOF
|
11
|
-
WTF-tools offers some flexible options for your puts-style Ruby debugging needs,
|
12
|
-
and method-level profiling for Ruby on Rails projects.
|
13
|
-
EOF
|
14
|
-
|
15
|
-
s.files = Dir['{lib/**/*,example/*,test/*}'] + %w(LICENSE Rakefile README.md wtf-tools.gemspec)
|
16
|
-
s.require_path = 'lib'
|
17
|
-
s.test_files = Dir['test/*.rb']
|
18
|
-
|
19
|
-
s.author = 'Remigijus Jodelis'
|
20
|
-
s.email = 'remigijus.jodelis@gmail.com'
|
21
|
-
s.homepage = 'http://github.com/remigijusj/wtf-tools'
|
22
|
-
|
23
|
-
s.add_runtime_dependency 'absolute_time', '~> 1.0'
|
24
|
-
end
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'wtf-tools'
|
3
|
+
s.version = '1.0.4'
|
4
|
+
s.date = '2016-07-01'
|
5
|
+
s.platform = Gem::Platform::RUBY
|
6
|
+
s.required_ruby_version = Gem::Requirement.new(">= 2.0.0")
|
7
|
+
s.summary = 'tools for debugging and profiling Ruby on Rails projects'
|
8
|
+
s.license = 'MIT'
|
9
|
+
|
10
|
+
s.description = <<-EOF
|
11
|
+
WTF-tools offers some flexible options for your puts-style Ruby debugging needs,
|
12
|
+
and method-level profiling for Ruby on Rails projects.
|
13
|
+
EOF
|
14
|
+
|
15
|
+
s.files = Dir['{lib/**/*,example/*,test/*}'] + %w(LICENSE Rakefile README.md wtf-tools.gemspec)
|
16
|
+
s.require_path = 'lib'
|
17
|
+
s.test_files = Dir['test/*.rb']
|
18
|
+
|
19
|
+
s.author = 'Remigijus Jodelis'
|
20
|
+
s.email = 'remigijus.jodelis@gmail.com'
|
21
|
+
s.homepage = 'http://github.com/remigijusj/wtf-tools'
|
22
|
+
|
23
|
+
s.add_runtime_dependency 'absolute_time', '~> 1.0'
|
24
|
+
end
|