power_trace 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +3 -6
- data/README.md +46 -5
- data/images/normal_rspec_error.png +0 -0
- data/images/power_trace_rspec_error.png +0 -0
- data/lib/power_trace.rb +15 -0
- data/lib/power_trace/entries/block_entry.rb +0 -3
- data/lib/power_trace/entries/method_entry.rb +11 -1
- data/lib/power_trace/entry.rb +31 -21
- data/lib/power_trace/exception_patch.rb +33 -6
- data/lib/power_trace/helpers/colorize_helper.rb +0 -7
- data/lib/power_trace/rspec_patch.rb +17 -0
- data/lib/power_trace/stack.rb +6 -7
- data/lib/power_trace/version.rb +1 -1
- data/power_trace.gemspec +3 -2
- metadata +12 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 489aca17c7b57c040a81bcb25149149c616f3c822c23f65b20f94fc630178eaa
|
4
|
+
data.tar.gz: 0bcc29315b7c6c5399b840340ecec4f8e628b463e90e2288515c020d849deb26
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 91826f382a2687ca209f52498789410eb712fa371ba2f5205b20fb6c1831e75637874c593e8b98520368deed3ad19c6a047389921066bb7686b69b9f2ec666b8
|
7
|
+
data.tar.gz: d62169e40fbdb3fe21b209ce788eab7cfa8426bc776b0d336da9544389ac0590b98b93fc7f8ce260521bfccb237c6312ed79c1f885667296737e015fb514a1a0
|
data/Gemfile.lock
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
power_trace (0.
|
4
|
+
power_trace (0.2.0)
|
5
5
|
activesupport
|
6
|
-
|
7
|
-
pry-stack_explorer
|
6
|
+
binding_of_caller (~> 0.8.0)
|
8
7
|
|
9
8
|
GEM
|
10
9
|
remote: https://rubygems.org/
|
@@ -28,9 +27,6 @@ GEM
|
|
28
27
|
pry (0.13.1)
|
29
28
|
coderay (~> 1.1)
|
30
29
|
method_source (~> 1.0)
|
31
|
-
pry-stack_explorer (0.5.1)
|
32
|
-
binding_of_caller (~> 0.7)
|
33
|
-
pry (~> 0.13)
|
34
30
|
rake (12.3.3)
|
35
31
|
rspec (3.9.0)
|
36
32
|
rspec-core (~> 3.9.0)
|
@@ -55,6 +51,7 @@ PLATFORMS
|
|
55
51
|
|
56
52
|
DEPENDENCIES
|
57
53
|
power_trace!
|
54
|
+
pry
|
58
55
|
rake (~> 12.0)
|
59
56
|
rspec (~> 3.0)
|
60
57
|
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# power_trace
|
2
2
|
|
3
|
-
![Ruby](https://github.com/st0012/power_trace/workflows/Ruby/badge.svg)
|
3
|
+
![Ruby](https://github.com/st0012/power_trace/workflows/Ruby/badge.svg) [![Gem Version](https://badge.fury.io/rb/power_trace.svg)](https://badge.fury.io/rb/power_trace)
|
4
4
|
|
5
5
|
Backtrace (Stack traces) are essential information for debugging our applications. However, they only tell us what the program did, but don't tell us what it had (the arguments, local variables...etc.). So it's very often that we'd need to visit each call site, rerun the program, and try to print out the variables. To me, It's like the Google map's navigation only tells us the name of the roads, but not showing us the map along with them.
|
6
6
|
|
@@ -82,10 +82,34 @@ I don't recommend using it like this for other purposes, though. Because by defa
|
|
82
82
|
|
83
83
|
- `colorize` - to decide whether to colorize each entry in their string format. Default is `true`.
|
84
84
|
- `line_limit` - `power_trace` truncates every argument/local variable's value to avoid creating too much noise. Default is `100`
|
85
|
+
- `extra_info_indent` -
|
85
86
|
|
86
|
-
|
87
|
+
By default, extra info sections (locals/arguments) are indented with `4` spaces. Like:
|
87
88
|
|
88
|
-
|
89
|
+
```
|
90
|
+
/Users/st0012/projects/power_trace/spec/fixtures.rb:23:in `forth_call'
|
91
|
+
(Arguments)
|
92
|
+
num1: 20
|
93
|
+
num2: 10
|
94
|
+
```
|
95
|
+
|
96
|
+
You can change this indentation with the `extra_info_indent: Int` option. It's useful when you need to adjust the output from some formatting tools (like `RSpec` formatters).
|
97
|
+
|
98
|
+
### Use It With StandardError (Experimental)
|
99
|
+
|
100
|
+
If you set
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
PowerTrace.replace_backtrace = true
|
104
|
+
```
|
105
|
+
|
106
|
+
it will replace every `StandardError` exception's backtrace with the `power_trace.to_backtrace`. So most of the error traces you see will also contain the colorized environment information!
|
107
|
+
|
108
|
+
This is still an experimental feature for now, as it has a very wide impact on all the libraries and your own code. **Don't try this on production!!!!**
|
109
|
+
|
110
|
+
#### Get `power_trace` Manually From A StandardError Exception
|
111
|
+
|
112
|
+
If you think the above feature is too aggressive. You can access an exception object's enhanced backtrace manually with the `power_trace` method:
|
89
113
|
|
90
114
|
```ruby
|
91
115
|
begin
|
@@ -95,7 +119,24 @@ rescue => e
|
|
95
119
|
end
|
96
120
|
```
|
97
121
|
|
98
|
-
|
122
|
+
This feature doesn't require any flag to enable, as the information is added as an extra field and doesn't override anything.
|
123
|
+
|
124
|
+
### Use It With RSpec
|
125
|
+
|
126
|
+
You can also prettify RSpec's error messages with `power_trace`, just use the below config:
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
PowerTrace.power_rspec_trace = true
|
130
|
+
```
|
131
|
+
|
132
|
+
Result:
|
133
|
+
|
134
|
+
**Before**
|
135
|
+
![normal rspec error message](https://github.com/st0012/power_trace/blob/master/images/normal_rspec_error.png)
|
136
|
+
|
137
|
+
**After**
|
138
|
+
![rspec error message with config set to true](https://github.com/st0012/power_trace/blob/master/images/power_trace_rspec_error.png)
|
139
|
+
|
99
140
|
|
100
141
|
## Inspirations & Helpful Tools
|
101
142
|
|
@@ -111,7 +152,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
111
152
|
|
112
153
|
## Contributing
|
113
154
|
|
114
|
-
Bug reports and pull requests are welcome on GitHub at [https://github.com/
|
155
|
+
Bug reports and pull requests are welcome on GitHub at [https://github.com/st0012/power_trace](https://github.com/st0012/power_trace). This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/%5BUSERNAME%5D/power_trace/blob/master/CODE_OF_CONDUCT.md).
|
115
156
|
|
116
157
|
## License
|
117
158
|
|
Binary file
|
Binary file
|
data/lib/power_trace.rb
CHANGED
@@ -2,6 +2,15 @@ require "power_trace/version"
|
|
2
2
|
require "power_trace/stack"
|
3
3
|
|
4
4
|
module PowerTrace
|
5
|
+
cattr_accessor :colorize_backtrace, instance_accessor: false
|
6
|
+
self.colorize_backtrace = true
|
7
|
+
|
8
|
+
cattr_accessor :replace_backtrace, instance_accessor: false
|
9
|
+
self.replace_backtrace = false
|
10
|
+
|
11
|
+
cattr_accessor :power_rspec_trace, instance_accessor: false
|
12
|
+
self.power_rspec_trace = false
|
13
|
+
|
5
14
|
def power_trace(options = {})
|
6
15
|
PowerTrace::Stack.new(options)
|
7
16
|
end
|
@@ -10,3 +19,9 @@ end
|
|
10
19
|
include PowerTrace
|
11
20
|
|
12
21
|
require "power_trace/exception_patch"
|
22
|
+
|
23
|
+
require "rspec" rescue LoadError
|
24
|
+
|
25
|
+
if defined?(RSpec)
|
26
|
+
require "power_trace/rspec_patch"
|
27
|
+
end
|
@@ -2,10 +2,20 @@ module PowerTrace
|
|
2
2
|
class MethodEntry < Entry
|
3
3
|
def method
|
4
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
|
5
9
|
end
|
6
10
|
|
11
|
+
private
|
12
|
+
|
7
13
|
def method_parameters
|
8
|
-
method
|
14
|
+
if method
|
15
|
+
method.parameters.map { |parameter| parameter[1] }
|
16
|
+
else
|
17
|
+
[]
|
18
|
+
end
|
9
19
|
end
|
10
20
|
|
11
21
|
def defined_class
|
data/lib/power_trace/entry.rb
CHANGED
@@ -6,8 +6,6 @@ module PowerTrace
|
|
6
6
|
include ColorizeHelper
|
7
7
|
UNDEFINED = "[undefined]"
|
8
8
|
|
9
|
-
INDENT = "\s" * 4
|
10
|
-
|
11
9
|
attr_reader :frame, :filepath, :line_number, :receiver, :locals, :arguments
|
12
10
|
|
13
11
|
def initialize(frame)
|
@@ -27,11 +25,17 @@ module PowerTrace
|
|
27
25
|
end
|
28
26
|
|
29
27
|
def arguments_string(options = {})
|
30
|
-
|
28
|
+
<<~STR.chomp
|
29
|
+
#{options[:indentation]}(Arguments)
|
30
|
+
#{hash_to_string(arguments, false, options)}
|
31
|
+
STR
|
31
32
|
end
|
32
33
|
|
33
34
|
def locals_string(options = {})
|
34
|
-
|
35
|
+
<<~STR.chomp
|
36
|
+
#{options[:indentation]}(Locals)
|
37
|
+
#{hash_to_string(locals, false, options)}
|
38
|
+
STR
|
35
39
|
end
|
36
40
|
|
37
41
|
def call_trace(options = {})
|
@@ -39,10 +43,10 @@ module PowerTrace
|
|
39
43
|
end
|
40
44
|
|
41
45
|
ATTRIBUTE_COLORS = {
|
42
|
-
name:
|
43
|
-
location:
|
44
|
-
arguments_string:
|
45
|
-
locals_string:
|
46
|
+
name: :blue,
|
47
|
+
location: :green,
|
48
|
+
arguments_string: :orange,
|
49
|
+
locals_string: :megenta
|
46
50
|
}
|
47
51
|
|
48
52
|
ATTRIBUTE_COLORS.each do |attribute, color|
|
@@ -53,7 +57,7 @@ module PowerTrace
|
|
53
57
|
call_result = send("original_#{attribute}", options)
|
54
58
|
|
55
59
|
if options[:colorize]
|
56
|
-
"#{color}
|
60
|
+
send("#{color}_color", call_result)
|
57
61
|
else
|
58
62
|
call_result
|
59
63
|
end
|
@@ -61,37 +65,43 @@ module PowerTrace
|
|
61
65
|
end
|
62
66
|
|
63
67
|
def to_s(options = {})
|
64
|
-
|
68
|
+
# this is to prevent entries from polluting each other's options
|
69
|
+
# of course, that'd only happen if I did something stupid ;)
|
70
|
+
assemble_string(options.dup)
|
65
71
|
end
|
66
72
|
|
67
73
|
private
|
68
74
|
|
75
|
+
def method_parameters
|
76
|
+
[]
|
77
|
+
end
|
78
|
+
|
69
79
|
def assemble_string(options)
|
70
80
|
strings = [call_trace(options)]
|
71
81
|
|
82
|
+
indentation = "\s" * options[:extra_info_indent]
|
83
|
+
options[:indentation] = indentation
|
84
|
+
|
72
85
|
if arguments.present?
|
73
|
-
strings <<
|
74
|
-
(Arguments)
|
75
|
-
#{arguments_string(options)}
|
76
|
-
STR
|
86
|
+
strings << arguments_string(options)
|
77
87
|
end
|
78
88
|
|
79
89
|
if locals.present?
|
80
|
-
strings <<
|
81
|
-
(Locals)
|
82
|
-
#{locals_string(options)}
|
83
|
-
STR
|
90
|
+
strings << locals_string(options)
|
84
91
|
end
|
85
92
|
|
86
93
|
strings.join("\n")
|
87
94
|
end
|
88
95
|
|
89
|
-
def hash_to_string(hash, inspect,
|
96
|
+
def hash_to_string(hash, inspect, options)
|
97
|
+
truncation = options[:line_limit]
|
98
|
+
indentation = options[:indentation] + "\s" * 2
|
99
|
+
|
90
100
|
elements_string = hash.map do |key, value|
|
91
101
|
value_string = value_to_string(value, truncation)
|
92
102
|
"#{key.to_s}: #{value_string}"
|
93
|
-
end.join("\n#{
|
94
|
-
"#{
|
103
|
+
end.join("\n#{indentation}")
|
104
|
+
"#{indentation}#{elements_string}"
|
95
105
|
end
|
96
106
|
|
97
107
|
def value_to_string(value, truncation)
|
@@ -1,14 +1,41 @@
|
|
1
|
-
class
|
2
|
-
attr_accessor :
|
1
|
+
class StandardError
|
2
|
+
attr_accessor :stored_power_trace
|
3
3
|
end
|
4
4
|
|
5
|
+
# the purposes of this section are:
|
6
|
+
# 1. capture and store a power_trace when the exception is firstly raised (will skip re-raising conditions)
|
7
|
+
# 2. if `replace_backtrace` is set to `true, it'll use the captured power_trace to replace the exception's original backtrace
|
5
8
|
TracePoint.trace(:raise) do |tp|
|
6
9
|
begin
|
7
10
|
e = tp.raised_exception
|
8
|
-
|
11
|
+
|
12
|
+
# it's too risky to deal with non-StandardError exceptions
|
13
|
+
next unless e.is_a?(StandardError)
|
14
|
+
|
15
|
+
# ignore re-raised exceptions
|
16
|
+
next if e.stored_power_trace
|
17
|
+
|
18
|
+
# these errors are commonly used as flow control so working with them can be error-prone and slow
|
19
|
+
# we can revisit them once the gem gets more stable
|
20
|
+
next if e.is_a?(LoadError)
|
21
|
+
next if e.is_a?(NameError)
|
22
|
+
next if e.is_a?(SystemCallError)
|
23
|
+
|
24
|
+
if defined?(Bootsnap)
|
25
|
+
next if e.is_a?(Bootsnap::LoadPathCache::FallbackScan)
|
26
|
+
next if e.is_a?(Bootsnap::LoadPathCache::ReturnFalse)
|
27
|
+
end
|
28
|
+
|
29
|
+
e.stored_power_trace = power_trace(exception: true)
|
30
|
+
|
31
|
+
if PowerTrace.replace_backtrace
|
32
|
+
e.set_backtrace(
|
33
|
+
e.stored_power_trace.to_backtrace(colorize: PowerTrace.colorize_backtrace)
|
34
|
+
)
|
35
|
+
end
|
9
36
|
rescue => e
|
10
|
-
puts
|
11
|
-
puts
|
12
|
-
|
37
|
+
puts(e)
|
38
|
+
puts(e.backtrace)
|
39
|
+
puts("power_trace's BUG")
|
13
40
|
end
|
14
41
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
RSpec::Core::Formatters::ExceptionPresenter.class_eval do
|
2
|
+
alias :original_formatted_backtrace :formatted_backtrace
|
3
|
+
|
4
|
+
def formatted_backtrace(exception=@exception)
|
5
|
+
if PowerTrace.power_rspec_trace || PowerTrace.replace_backtrace
|
6
|
+
backtrace_formatter.format_backtrace(exception.stored_power_trace.to_backtrace(extra_info_indent: 8), example.metadata) +
|
7
|
+
formatted_cause(exception)
|
8
|
+
else
|
9
|
+
original_formatted_backtrace
|
10
|
+
end
|
11
|
+
rescue => e
|
12
|
+
puts(e)
|
13
|
+
puts(e.backtrace)
|
14
|
+
puts("there's a bug in power_trace, please open an issue at https://github.com/st0012/power_trace")
|
15
|
+
original_formatted_backtrace
|
16
|
+
end
|
17
|
+
end
|
data/lib/power_trace/stack.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require "power_trace/entry"
|
2
|
-
require "
|
2
|
+
require "binding_of_caller"
|
3
3
|
|
4
4
|
module PowerTrace
|
5
5
|
class Stack
|
@@ -9,7 +9,8 @@ module PowerTrace
|
|
9
9
|
|
10
10
|
OUTPUT_OPTIONS_DEFAULT = {
|
11
11
|
colorize: true,
|
12
|
-
line_limit: 100
|
12
|
+
line_limit: 100,
|
13
|
+
extra_info_indent: 4
|
13
14
|
}
|
14
15
|
|
15
16
|
def initialize(options = {})
|
@@ -44,12 +45,8 @@ module PowerTrace
|
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
47
|
-
def frame_manager
|
48
|
-
PryStackExplorer.frame_manager(Pry.new)
|
49
|
-
end
|
50
|
-
|
51
48
|
def extract_entries
|
52
|
-
frames =
|
49
|
+
frames = binding.callers
|
53
50
|
# when using pry console, the power_trace_index will be `nil` and breaks EVERYTHING
|
54
51
|
# so we should fallback it to 0
|
55
52
|
power_trace_index = (frames.index { |b| b.frame_description&.to_sym == :power_trace } || 0) + 1
|
@@ -61,6 +58,8 @@ module PowerTrace
|
|
61
58
|
MethodEntry.new(b)
|
62
59
|
when :block
|
63
60
|
BlockEntry.new(b)
|
61
|
+
else
|
62
|
+
Entry.new(b)
|
64
63
|
end
|
65
64
|
end
|
66
65
|
end
|
data/lib/power_trace/version.rb
CHANGED
data/power_trace.gemspec
CHANGED
@@ -29,6 +29,7 @@ So I hope to solve this problem by adding some additional runtime info to the ba
|
|
29
29
|
spec.require_paths = ["lib"]
|
30
30
|
|
31
31
|
spec.add_dependency "activesupport"
|
32
|
-
spec.add_dependency "
|
33
|
-
|
32
|
+
spec.add_dependency "binding_of_caller", "~> 0.8.0"
|
33
|
+
|
34
|
+
spec.add_development_dependency "pry"
|
34
35
|
end
|
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.
|
4
|
+
version: 0.2.0
|
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-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -25,27 +25,27 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: binding_of_caller
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 0.8.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 0.8.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name: pry
|
42
|
+
name: pry
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
|
-
type: :
|
48
|
+
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
@@ -78,7 +78,9 @@ files:
|
|
78
78
|
- bin/setup
|
79
79
|
- images/entries.png
|
80
80
|
- images/normal_backtrace.png
|
81
|
+
- images/normal_rspec_error.png
|
81
82
|
- images/power_trace_backtrace.png
|
83
|
+
- images/power_trace_rspec_error.png
|
82
84
|
- images/print_directly.png
|
83
85
|
- lib/power_trace.rb
|
84
86
|
- lib/power_trace/entries/block_entry.rb
|
@@ -86,6 +88,7 @@ files:
|
|
86
88
|
- lib/power_trace/entry.rb
|
87
89
|
- lib/power_trace/exception_patch.rb
|
88
90
|
- lib/power_trace/helpers/colorize_helper.rb
|
91
|
+
- lib/power_trace/rspec_patch.rb
|
89
92
|
- lib/power_trace/stack.rb
|
90
93
|
- lib/power_trace/version.rb
|
91
94
|
- power_trace.gemspec
|