power_trace 0.2.1 → 0.2.2
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/Gemfile.lock +2 -2
- data/README.md +2 -9
- data/benchmarks/raise_with_power_trace.rb +110 -0
- data/lib/power_trace.rb +11 -0
- data/lib/power_trace/entry.rb +18 -3
- data/lib/power_trace/exception_patch.rb +2 -4
- data/lib/power_trace/rspec_patch.rb +3 -5
- data/lib/power_trace/stack.rb +7 -8
- data/lib/power_trace/version.rb +1 -1
- metadata +3 -4
- data/lib/power_trace/entries/block_entry.rb +0 -4
- data/lib/power_trace/entries/method_entry.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 75a503a2bc8b1ee1123f7b37cf6a1e8ce7873256cf85b0c9cb00371fb17239d2
|
4
|
+
data.tar.gz: 41aaddfe26306041d6a580c7a212018eae7df3b3f289b0ed02dbba6ccf59d5a7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b19155914a1f24eca4f1e71731ed1f2128190e9399f14b10e6a5eeaa715aa69effbb7760ec303e26d6bb2241ee7a9ec215b08f132aa1753e6813f74a9b528a0e
|
7
|
+
data.tar.gz: cfd37781a60288fd72a2cab5ff052eee371a5f0b4bae99bb5ce503aa59180a197b3911b22ce9b99c82f71a1e68e375deb2add39ec0fd83524c2d1413532162d8
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
power_trace (0.2.
|
4
|
+
power_trace (0.2.2)
|
5
5
|
activesupport
|
6
6
|
binding_of_caller (~> 0.8.0)
|
7
7
|
|
@@ -44,7 +44,7 @@ GEM
|
|
44
44
|
thread_safe (0.3.6)
|
45
45
|
tzinfo (1.2.7)
|
46
46
|
thread_safe (~> 0.1)
|
47
|
-
zeitwerk (2.
|
47
|
+
zeitwerk (2.4.0)
|
48
48
|
|
49
49
|
PLATFORMS
|
50
50
|
ruby
|
data/README.md
CHANGED
@@ -50,12 +50,7 @@ It should look just like the normal `puts(caller)`, just colorized and with more
|
|
50
50
|
|
51
51
|
Except for the call site, each entry also contains rich information about the runtime context. You can build your own debugging tool with that information easily.
|
52
52
|
|
53
|
-
|
54
|
-
|
55
|
-
- `MethodEntry`- a method call's trace
|
56
|
-
- `BlockEntry` - a block evaluation's trace
|
57
|
-
|
58
|
-
They both have these attributes:
|
53
|
+
Every entry has these attributes:
|
59
54
|
|
60
55
|
- `filepath`
|
61
56
|
- `line_number`
|
@@ -64,9 +59,7 @@ They both have these attributes:
|
|
64
59
|
- `locals` - local variables in that frame
|
65
60
|
- `arguments`
|
66
61
|
- the method call's arguments
|
67
|
-
- will
|
68
|
-
|
69
|
-

|
62
|
+
- will be empty for `block` entries
|
70
63
|
|
71
64
|
#### Convert It Into Backtraces
|
72
65
|
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
lib = File.expand_path("../lib", __dir__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
|
5
|
+
n = 1_000
|
6
|
+
|
7
|
+
class Foo
|
8
|
+
def first_call
|
9
|
+
second_call(20)
|
10
|
+
end
|
11
|
+
|
12
|
+
def second_call(num)
|
13
|
+
third_call_with_block do |ten|
|
14
|
+
forth_call(num, ten)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def third_call_with_block(&block)
|
19
|
+
yield(10)
|
20
|
+
end
|
21
|
+
|
22
|
+
def forth_call(num1, num2)
|
23
|
+
raise "Foo Error"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
foo = Foo.new
|
28
|
+
|
29
|
+
Benchmark.benchmark do |bm|
|
30
|
+
bench_proc = proc do
|
31
|
+
3.times do
|
32
|
+
bm.report do
|
33
|
+
n.times do
|
34
|
+
foo.first_call rescue nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
puts "#{n} times - ruby #{RUBY_VERSION}"
|
41
|
+
puts("Normal raise")
|
42
|
+
|
43
|
+
bench_proc.call
|
44
|
+
|
45
|
+
puts("====================================")
|
46
|
+
puts("======= power_trace required =======")
|
47
|
+
puts("====================================")
|
48
|
+
|
49
|
+
require "power_trace"
|
50
|
+
|
51
|
+
cases = [
|
52
|
+
{
|
53
|
+
replace_backtrace: false,
|
54
|
+
trace_limit: 10
|
55
|
+
},
|
56
|
+
{
|
57
|
+
replace_backtrace: false,
|
58
|
+
trace_limit: 50
|
59
|
+
},
|
60
|
+
{
|
61
|
+
replace_backtrace: true,
|
62
|
+
trace_limit: 10
|
63
|
+
},
|
64
|
+
{
|
65
|
+
replace_backtrace: true,
|
66
|
+
trace_limit: 50
|
67
|
+
}
|
68
|
+
]
|
69
|
+
|
70
|
+
cases.each do |setup|
|
71
|
+
PowerTrace.replace_backtrace = setup[:replace_backtrace]
|
72
|
+
PowerTrace.trace_limit = setup[:trace_limit]
|
73
|
+
|
74
|
+
message =
|
75
|
+
if setup[:replace_backtrace]
|
76
|
+
"Raise and replace backtrace (trace_limit: #{PowerTrace.trace_limit})"
|
77
|
+
else
|
78
|
+
"Raise and store power_trace (trace_limit: #{PowerTrace.trace_limit})"
|
79
|
+
end
|
80
|
+
|
81
|
+
puts(message)
|
82
|
+
bench_proc.call
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# 1000 times - ruby 2.7.1
|
87
|
+
# Normal raise
|
88
|
+
# 0.002032 0.000093 0.002125 ( 0.002119)
|
89
|
+
# 0.001131 0.000107 0.001238 ( 0.001239)
|
90
|
+
# 0.001092 0.000100 0.001192 ( 0.001192)
|
91
|
+
# ====================================
|
92
|
+
# ======= power_trace required =======
|
93
|
+
# ====================================
|
94
|
+
# Raise and store power_trace (trace_limit: 10)
|
95
|
+
# 0.157296 0.001807 0.159103 ( 0.159504)
|
96
|
+
# 0.159911 0.000668 0.160579 ( 0.160961)
|
97
|
+
# 0.152814 0.000493 0.153307 ( 0.153658)
|
98
|
+
# Raise and store power_trace (trace_limit: 50)
|
99
|
+
# 0.228311 0.000649 0.228960 ( 0.229264)
|
100
|
+
# 0.248271 0.001956 0.250227 ( 0.257272)
|
101
|
+
# 0.229469 0.000923 0.230392 ( 0.230822)
|
102
|
+
# Raise and replace backtrace (trace_limit: 10)
|
103
|
+
# 0.331577 0.000360 0.331937 ( 0.332203)
|
104
|
+
# 0.354934 0.001634 0.356568 ( 0.356939)
|
105
|
+
# 0.334688 0.001201 0.335889 ( 0.336682)
|
106
|
+
# Raise and replace backtrace (trace_limit: 50)
|
107
|
+
# 0.557920 0.002530 0.560450 ( 0.561101)
|
108
|
+
# 0.553058 0.001767 0.554825 ( 0.555651)
|
109
|
+
# 0.560771 0.002160 0.562931 ( 0.563613)
|
110
|
+
|
data/lib/power_trace.rb
CHANGED
@@ -11,9 +11,20 @@ module PowerTrace
|
|
11
11
|
cattr_accessor :power_rspec_trace, instance_accessor: false
|
12
12
|
self.power_rspec_trace = false
|
13
13
|
|
14
|
+
cattr_accessor :trace_limit, instance_accessor: false
|
15
|
+
self.trace_limit = 50
|
16
|
+
|
14
17
|
def power_trace(options = {})
|
15
18
|
PowerTrace::Stack.new(options)
|
16
19
|
end
|
20
|
+
|
21
|
+
class << self
|
22
|
+
def print_power_trace_error(exception)
|
23
|
+
puts(exception)
|
24
|
+
puts(exception.backtrace)
|
25
|
+
puts("there's a bug in power_trace, please open an issue at https://github.com/st0012/power_trace")
|
26
|
+
end
|
27
|
+
end
|
17
28
|
end
|
18
29
|
|
19
30
|
include PowerTrace
|
data/lib/power_trace/entry.rb
CHANGED
@@ -132,8 +132,23 @@ module PowerTrace
|
|
132
132
|
|
133
133
|
[locals, arguments]
|
134
134
|
end
|
135
|
+
|
136
|
+
def method
|
137
|
+
@method ||= Object.instance_method(:method).bind(@receiver).call(name)
|
138
|
+
rescue NameError
|
139
|
+
# if any part of the program uses Refinement to extend its methods
|
140
|
+
# we might still get NoMethodError when trying to get that method outside the scope
|
141
|
+
nil
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def method_parameters
|
147
|
+
if method
|
148
|
+
method.parameters.map { |parameter| parameter[1] }
|
149
|
+
else
|
150
|
+
[]
|
151
|
+
end
|
152
|
+
end
|
135
153
|
end
|
136
154
|
end
|
137
|
-
|
138
|
-
require "power_trace/entries/method_entry"
|
139
|
-
require "power_trace/entries/block_entry"
|
@@ -30,12 +30,10 @@ TracePoint.trace(:raise) do |tp|
|
|
30
30
|
|
31
31
|
if PowerTrace.replace_backtrace
|
32
32
|
e.set_backtrace(
|
33
|
-
e.stored_power_trace.to_backtrace
|
33
|
+
e.stored_power_trace.to_backtrace
|
34
34
|
)
|
35
35
|
end
|
36
36
|
rescue => e
|
37
|
-
|
38
|
-
puts(e.backtrace)
|
39
|
-
puts("power_trace's BUG")
|
37
|
+
PowerTrace.print_power_trace_error(e)
|
40
38
|
end
|
41
39
|
end
|
@@ -3,15 +3,13 @@ RSpec::Core::Formatters::ExceptionPresenter.class_eval do
|
|
3
3
|
|
4
4
|
def formatted_backtrace(exception=@exception)
|
5
5
|
if PowerTrace.power_rspec_trace || PowerTrace.replace_backtrace
|
6
|
-
|
7
|
-
|
6
|
+
backtrace = exception.stored_power_trace.to_backtrace(extra_info_indent: 8)
|
7
|
+
backtrace_formatter.format_backtrace(backtrace, example.metadata) + formatted_cause(exception)
|
8
8
|
else
|
9
9
|
original_formatted_backtrace
|
10
10
|
end
|
11
11
|
rescue => e
|
12
|
-
|
13
|
-
puts(e.backtrace)
|
14
|
-
puts("there's a bug in power_trace, please open an issue at https://github.com/st0012/power_trace")
|
12
|
+
PowerTrace.print_power_trace_error(e)
|
15
13
|
original_formatted_backtrace
|
16
14
|
end
|
17
15
|
end
|
data/lib/power_trace/stack.rb
CHANGED
@@ -24,6 +24,7 @@ module PowerTrace
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def to_backtrace(output_options = {})
|
27
|
+
output_options[:colorize] = output_options.fetch(:colorize, PowerTrace.colorize_backtrace) if @exception
|
27
28
|
output_options = extract_output_options(output_options)
|
28
29
|
@entries.map { |e| e.to_s(output_options) }
|
29
30
|
end
|
@@ -52,16 +53,14 @@ module PowerTrace
|
|
52
53
|
power_trace_index = (frames.index { |b| b.frame_description&.to_sym == :power_trace } || 0) + 1
|
53
54
|
power_trace_index += 1 if @exception
|
54
55
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
MethodEntry.new(b)
|
59
|
-
when :block
|
60
|
-
BlockEntry.new(b)
|
56
|
+
end_index =
|
57
|
+
if @exception
|
58
|
+
power_trace_index + PowerTrace.trace_limit - 1
|
61
59
|
else
|
62
|
-
|
60
|
+
-1
|
63
61
|
end
|
64
|
-
|
62
|
+
|
63
|
+
frames[power_trace_index..end_index].map { |b| Entry.new(b) }
|
65
64
|
end
|
66
65
|
end
|
67
66
|
end
|
data/lib/power_trace/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: power_trace
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- st0012
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-07-
|
11
|
+
date: 2020-07-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -75,6 +75,7 @@ files:
|
|
75
75
|
- LICENSE.txt
|
76
76
|
- README.md
|
77
77
|
- Rakefile
|
78
|
+
- benchmarks/raise_with_power_trace.rb
|
78
79
|
- bin/console
|
79
80
|
- bin/setup
|
80
81
|
- images/entries.png
|
@@ -84,8 +85,6 @@ files:
|
|
84
85
|
- images/power_trace_rspec_error.png
|
85
86
|
- images/print_directly.png
|
86
87
|
- lib/power_trace.rb
|
87
|
-
- lib/power_trace/entries/block_entry.rb
|
88
|
-
- lib/power_trace/entries/method_entry.rb
|
89
88
|
- lib/power_trace/entry.rb
|
90
89
|
- lib/power_trace/exception_patch.rb
|
91
90
|
- lib/power_trace/helpers/colorize_helper.rb
|
@@ -1,25 +0,0 @@
|
|
1
|
-
module PowerTrace
|
2
|
-
class MethodEntry < Entry
|
3
|
-
def method
|
4
|
-
@method ||= Object.instance_method(:method).bind(@receiver).call(name)
|
5
|
-
rescue NameError
|
6
|
-
# if any part of the program uses Refinement to extend its methods
|
7
|
-
# we might still get NoMethodError when trying to get that method outside the scope
|
8
|
-
nil
|
9
|
-
end
|
10
|
-
|
11
|
-
private
|
12
|
-
|
13
|
-
def method_parameters
|
14
|
-
if method
|
15
|
-
method.parameters.map { |parameter| parameter[1] }
|
16
|
-
else
|
17
|
-
[]
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def defined_class
|
22
|
-
method.owner
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|