trace_tree 0.2.8 → 0.2.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e6a33c823c7c9a9edef43b4a0a9a6131cb5088cf
4
- data.tar.gz: 8fc50067cb0975e582b1450f0f5b4056aae86b1b
3
+ metadata.gz: 2acc2e68551caee98c0c8b0245646acea04bce6d
4
+ data.tar.gz: f7b038d0a709e7dc15f9225179177b1948168a54
5
5
  SHA512:
6
- metadata.gz: 0ed48c6ec0f6b579f8e823c0d03bfb34c511b9f9c86d508f624ad313830313c24ffd9dbae30a52c4b0410453763a0d93224fbe47616d781d51c63f25bb2ffc3d
7
- data.tar.gz: d54d68166144f9bbcc60498fe189ffbdb27d47516ddce71cf8ed5fd2bc77ac8ecb06153c9aa6f95f02b6204b9658a59c5fde30f4c5b025c829467f642cce0944
6
+ metadata.gz: f8c8e186db907601748d81fcd7c325c35084cb9cd504599337fc95fc0d81d59a2c5dc5cf5a4d4171ecf16b3e4660ace8e1c44f51c71a7e97a330917622f6066c
7
+ data.tar.gz: 9e650c794990c69ce8154fcaca17bef4c4c3684295eaa49c84218df412b2a5d1768de8fef6e5c78319f879dc366f45e24f66f99c29a8b3fd406ca684ab37e25a
data/README.md CHANGED
@@ -45,7 +45,10 @@ end
45
45
  * `:gem => true` by default. Replace the gem paths in source_location with $GemPathN, can make the lines shorter. To see what are replaced, inspect `TraceTree::GemPaths`.
46
46
  * `:html => nil` by default. Set it true to generate a html in which a tree constructed with `<ul>`, `<li>`. (No need to set `color`).
47
47
  * `:tmp => nil` by default. Set it true or a string or an array of string to specify a tmp file under the default tmp dir of your system. (No need to provide `file` argument. It makes parent directories as needed)
48
+ * `:htmp => nil` by default. It is combination of `:html` and `:tmp`.
49
+ * `:in => //, :out => nil` by default. Give them regexp(s) to include/exclude methods defined in files match that regexp(s). Notice thread-calls and methods defined by `define_method` are always included. Also, once you set any of these two options, the code to trace should not be in same line with `binding.trace_tree() do`.
48
50
  * `:timer => nil` by default. Set it true if you want to know how much time spent in tracing and drawing tree. Notice the `file` should be appendable, otherwise the time will overwrite the tree.
51
+ * `:debug =>` by default. Give it somthing like what for `:tmp` to output a whole list of TracePoints in file for debug.
49
52
 
50
53
  ### Example
51
54
 
@@ -7,7 +7,7 @@ class TraceTree
7
7
  include TreeGraphable
8
8
  include TreeHtmlable
9
9
 
10
- attr_reader :current, :thread
10
+ attr_reader :current, :thread, :frame_env
11
11
  attr_accessor :terminal
12
12
 
13
13
  Interfaces = [:event, :defined_class, :method_id, :path, :lineno]
@@ -27,16 +27,21 @@ class TraceTree
27
27
  end
28
28
 
29
29
  def hashify point
30
- attrs = Interfaces.each_with_object({}) do |attr, hash|
31
- hash[attr] = point.send attr
32
- end
33
- attrs.merge!({return_value: point.return_value}) if point.event =~ /return/
34
- attrs.merge!({thread: point.thread}) if point.respond_to? :thread
35
- attrs
30
+ h = {}
31
+ h[:event] = point.event
32
+ h[:defined_class] = point.defined_class
33
+ h[:method_id] = point.method_id
34
+ h[:frame_env] = point.frame_env unless point.thread?
35
+ h[:path] = point.path
36
+ h[:lineno] = point.lineno
37
+ h[:thread] = point.thread
38
+ h[:return_value] = point.return_value if point.event =~ /return/
39
+ h
36
40
  end
37
41
 
38
42
  def class_of? point
39
- [point.event, point.defined_class, point.method_id] == event_class_method
43
+ e, c, m = event_class_method
44
+ point.method_id == m && point.event == e && point.defined_class == c
40
45
  end
41
46
 
42
47
  def initialize_clone proto
@@ -46,6 +51,19 @@ class TraceTree
46
51
  end
47
52
 
48
53
  attr_reader :proto
54
+
55
+ def cache_event_class_method!
56
+ bases.each do |base|
57
+ base.class_eval <<-EOM
58
+ class << self
59
+ alias_method :_event_class_method, :event_class_method
60
+ def self.event_class_method
61
+ @ecm ||= _event_class_method.freeze
62
+ end
63
+ end
64
+ EOM
65
+ end
66
+ end
49
67
  end
50
68
 
51
69
  def method_missing method_id, *args, &blk
@@ -56,17 +74,33 @@ class TraceTree
56
74
  Interfaces.each do |i|
57
75
  instance_variable_set "@#{i}", trace_point.send(i)
58
76
  end
77
+
59
78
  @return_value = trace_point.return_value if x_return?
60
- @current = BindingOfCallers::Revealed.new trace_point.binding.of_caller(3) unless thread?
61
- @thread = thread? ? trace_point.self : current.send(:eval, 'Thread.current')
79
+
80
+ if thread?
81
+ @thread = trace_point.self
82
+ else
83
+ there = trace_point.binding.of_caller(3)
84
+ @current = BindingOfCallers::Revealed.new there
85
+ @frame_env = current.frame_env.to_sym
86
+ @thread = current.send(:eval, 'Thread.current')
87
+ end
62
88
  rescue => e
63
89
  puts e
64
90
  end
65
91
 
92
+ def b_call?
93
+ event == :b_call
94
+ end
95
+
66
96
  def c_call?
67
97
  event == :c_call
68
98
  end
69
99
 
100
+ def class?
101
+ event == :class
102
+ end
103
+
70
104
  def x_return?
71
105
  event =~ /return/
72
106
  end
@@ -75,6 +109,13 @@ class TraceTree
75
109
  event =~ /thread/
76
110
  end
77
111
 
112
+ def end_of_trace?
113
+ MainFile == path && (
114
+ (:c_return == event && :instance_eval == method_id) ||
115
+ (:c_call == event && :disable == method_id)
116
+ )
117
+ end
118
+
78
119
  def return_value
79
120
  raise RuntimeError.new('RuntimeError: not supported by this event') unless x_return?
80
121
  @return_value
@@ -127,7 +168,9 @@ class TraceTree
127
168
  end
128
169
 
129
170
  def method_name
130
- c_call? ? method_id : current.frame_env
171
+ return method_id if c_call?
172
+ return frame_env if b_call? || class?
173
+ (method_id == frame_env) ? method_id : "#{method_id} -> #{frame_env}"
131
174
  end
132
175
 
133
176
  def call_symbol
@@ -162,7 +205,32 @@ class TraceTree
162
205
  end
163
206
  end
164
207
 
165
- Dir.glob(File.expand_path('../point/*', __FILE__)).each do |concreate_point_path|
166
- load concreate_point_path
167
- #puts "---->#{concreate_point_path}"
208
+ Dir.glob(File.expand_path('../point/*', __FILE__)).each do |concrete_point_path|
209
+ load concrete_point_path
210
+ #puts "---->#{concrete_point_path}"
211
+ end
212
+
213
+ class TraceTree
214
+ class Point
215
+
216
+ cache_event_class_method!
217
+
218
+ NativeThreadCall = [CcallClassthreadNew,
219
+ CreturnClassthreadNew,
220
+ CcallThreadInitialize,
221
+ CreturnThreadInitialize,
222
+ Threadbegin,
223
+ Threadend]
224
+
225
+ def thread_relative?
226
+ NativeThreadCall.any?{ |k| k.class_of? self } ||
227
+ Thread == defined_class
228
+ end
229
+
230
+ def method_defined_by_define_method?
231
+ (event == :call || event == :return) &&
232
+ method_id != frame_env
233
+ end
234
+
235
+ end
168
236
  end
@@ -1,3 +1,3 @@
1
1
  class TraceTree
2
- VERSION = "0.2.8"
2
+ VERSION = "0.2.9"
3
3
  end
data/lib/trace_tree.rb CHANGED
@@ -16,6 +16,8 @@ end
16
16
 
17
17
  class TraceTree
18
18
 
19
+ MainFile = __FILE__
20
+
19
21
  Events = [:b_call, :b_return,
20
22
  :c_call, :c_return,
21
23
  :call, :return,
@@ -31,19 +33,18 @@ class TraceTree
31
33
  def generate *log, **opt, &to_do
32
34
  @opt = opt
33
35
  @log = dump_location *log
34
- enhance_point **opt
35
- @build_command = opt[:html] ? :tree_html_full : :tree_graph
36
- @ignore = opt[:ignore] || {}
37
- here = bi.eval('self')
36
+ @debug = TmpFile.new opt[:debug] if opt[:debug]
37
+ enhance_point
38
+ @build_command = (opt[:html] || opt[:htmp]) ? :tree_html_full : :tree_graph
39
+ make_filter
40
+ @__file__, @__line__, there = bi.eval('[__FILE__, __LINE__, self]')
38
41
 
39
42
  #start_trace
40
43
  timer[:trace]
41
- @tp = TracePoint.new(*Events) do |point|
42
- trace_points << point_loader.create(point) if wanted? point
43
- end
44
+ @tp = TracePoint.new *Events, &@deal
44
45
  @tp.enable
45
46
 
46
- here.instance_eval &to_do
47
+ there.instance_eval &to_do
47
48
  ensure
48
49
  #stop_trace
49
50
  return unless @tp
@@ -58,10 +59,11 @@ class TraceTree
58
59
 
59
60
  def dump_location *log
60
61
  return TmpFile.new opt[:tmp] if opt[:tmp]
62
+ return TmpFile.new(opt[:htmp] + '.html') if opt[:htmp]
61
63
  log.empty? ? STDOUT : log[0]
62
64
  end
63
65
 
64
- def enhance_point opt
66
+ def enhance_point
65
67
  enhancement = []
66
68
  enhancement << TraceTree::Color unless opt[:color] == false
67
69
  enhancement << TraceTree::ShortGemPath unless opt[:gem] == false
@@ -72,18 +74,40 @@ class TraceTree
72
74
  timer[:tree]
73
75
  tree = sort(trace_points_array).send build_command
74
76
  timer[:tree]
77
+ @debug.puts table_of_points if defined? @debug
75
78
  log.puts tree
76
79
  log.puts timer.to_s if opt[:timer]
77
80
  rescue => e
78
81
  log.puts timer.to_s
79
82
  log.puts e
80
- log.puts Terminal::Table.from_hashes trace_points_array.map(&:to_h)
83
+ log.puts table_of_points
84
+ end
85
+
86
+ def table_of_points
87
+ Terminal::Table.from_hashes trace_points_array.map(&:to_h)
81
88
  end
82
89
 
83
- def wanted? trace_point
84
- @ignore.any? do |attr, pattern|
85
- pattern =~ trace_point.send(attr)
86
- end ? false : true
90
+ def make_filter
91
+ if !opt.key?(:in) && !opt.key?(:out)
92
+ return @deal = -> point { trace_points << point_loader.create(point) }
93
+ end
94
+ @in, @out = Array(opt[:in] || //), Array(opt[:out])
95
+ @deal = -> point do
96
+ po = point_loader.create(point)
97
+ trace_points << po if wanted? po
98
+ end
99
+ end
100
+
101
+ def wanted? point
102
+ return false if point.end_of_trace?
103
+ return true if native?(point) || point.thread_relative? || point.method_defined_by_define_method?
104
+ @in.any?{ |pattern| pattern =~ point.path } &&
105
+ @out.all?{ |pattern| pattern !~ point.path }
106
+ end
107
+
108
+ def native? point
109
+ MainFile == point.path ||
110
+ (:b_call == point.event && @__file__ == point.path && @__line__ == point.lineno)
87
111
  end
88
112
 
89
113
  def sort trace_points
@@ -111,6 +135,8 @@ class TraceTree
111
135
  point.thread_begin = began_threads[thread]
112
136
  end
113
137
 
138
+ #binding.pry
139
+
114
140
  stacks[trace_points.first.thread][0].
115
141
  callees[0].
116
142
  callees[0]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trace_tree
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.8
4
+ version: 0.2.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - ken
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-06-10 00:00:00.000000000 Z
11
+ date: 2017-07-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler