rshade 0.1.9 → 0.2.0
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/.gitignore +2 -1
- data/Gemfile +6 -2
- data/Gemfile.lock +10 -1
- data/README.md +19 -3
- data/Rakefile +5 -3
- data/bin/console +4 -3
- data/lib/rshade/config/registry.rb +47 -0
- data/lib/rshade/config/stack_store.rb +58 -0
- data/lib/rshade/config/store.rb +14 -5
- data/lib/rshade/config.rb +9 -3
- data/lib/rshade/core_extensions/object/reveal.rb +34 -5
- data/lib/rshade/event.rb +15 -9
- data/lib/rshade/event_observer.rb +3 -1
- data/lib/rshade/event_processor.rb +14 -12
- data/lib/rshade/event_tree.rb +13 -15
- data/lib/rshade/filter/abstract_filter.rb +3 -1
- data/lib/rshade/filter/default.rb +3 -1
- data/lib/rshade/filter/exclude_path_filter.rb +10 -7
- data/lib/rshade/filter/filter_builder.rb +14 -3
- data/lib/rshade/filter/filter_composition.rb +26 -24
- data/lib/rshade/filter/include_path_filter.rb +5 -1
- data/lib/rshade/filter/variable_filter.rb +4 -1
- data/lib/rshade/formatter/stack/json.rb +51 -0
- data/lib/rshade/formatter/stack/stdout.rb +13 -0
- data/lib/rshade/formatter/stack/string.rb +41 -0
- data/lib/rshade/formatter/trace/file.rb +33 -0
- data/lib/rshade/formatter/trace/html.rb +38 -0
- data/lib/rshade/formatter/trace/json.rb +61 -0
- data/lib/rshade/formatter/trace/stdout.rb +14 -0
- data/lib/rshade/formatter/trace/string.rb +48 -0
- data/lib/rshade/rspec/rspec.rb +7 -6
- data/lib/rshade/serializer/traversal.rb +54 -0
- data/lib/rshade/stack.rb +26 -0
- data/lib/rshade/stack_frame.rb +60 -0
- data/lib/rshade/trace.rb +8 -5
- data/lib/rshade/trace_observable.rb +5 -0
- data/lib/rshade/version.rb +3 -1
- data/lib/rshade.rb +26 -10
- data/rshade.gemspec +24 -21
- metadata +44 -9
- data/lib/rshade/binding_serializer.rb +0 -35
- data/lib/rshade/formatter/file.rb +0 -28
- data/lib/rshade/formatter/html.rb +0 -33
- data/lib/rshade/formatter/json.rb +0 -59
- data/lib/rshade/formatter/stdout.rb +0 -10
- data/lib/rshade/formatter/string.rb +0 -36
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RShade
|
2
4
|
module Filter
|
3
5
|
class FilterComposition
|
@@ -5,53 +7,53 @@ module RShade
|
|
5
7
|
AND_OP = :and
|
6
8
|
OR_OP = :or
|
7
9
|
UNARY_OP = :unary
|
8
|
-
attr_reader :
|
10
|
+
attr_reader :value, :left, :right, :parent
|
9
11
|
attr_accessor :parent
|
10
12
|
|
11
13
|
# @param [#call, Enumerable] left
|
12
14
|
# @param [#call, Enumerable] right
|
13
|
-
def initialize(
|
14
|
-
@
|
15
|
+
def initialize(value, left = nil, right = nil)
|
16
|
+
@value = value
|
15
17
|
@left = left
|
16
18
|
@right = right
|
17
19
|
end
|
18
20
|
|
19
21
|
def call(event)
|
20
|
-
case
|
22
|
+
case value
|
21
23
|
when UNARY_OP
|
22
|
-
|
24
|
+
left&.call(event)
|
23
25
|
when AND_OP
|
24
|
-
|
26
|
+
left&.call(event) && right&.call(event)
|
25
27
|
when OR_OP
|
26
|
-
|
27
|
-
r = right&.call(event)
|
28
|
-
# puts "#{left} => #{l} OR #{right} => #{r}"
|
29
|
-
return l || r
|
28
|
+
left&.call(event) || right&.call(event)
|
30
29
|
else
|
31
|
-
|
30
|
+
value.call(event)
|
32
31
|
end
|
33
32
|
end
|
34
33
|
|
35
34
|
def each(&block)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
yield left
|
40
|
-
end
|
41
|
-
|
42
|
-
if right&.respond_to?(:each)
|
43
|
-
right&.each(&block)
|
44
|
-
else
|
45
|
-
yield right
|
46
|
-
end
|
35
|
+
yield value unless left && right
|
36
|
+
left&.each(&block)
|
37
|
+
right&.each(&block)
|
47
38
|
end
|
48
39
|
|
49
40
|
def config_filter(type, &block)
|
50
41
|
filter = find do |filter|
|
51
42
|
filter.is_a? type
|
52
43
|
end
|
53
|
-
filter
|
44
|
+
filter&.config(&block)
|
45
|
+
end
|
46
|
+
|
47
|
+
# for debug purposes, show each filter and result of evaluation
|
48
|
+
def filter_results(event)
|
49
|
+
each_with_object([]) do |filter, arr|
|
50
|
+
arr << [filter, filter.call(event)]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.build(arr)
|
55
|
+
::RShade::Filter::FilterBuilder.build(arr)
|
54
56
|
end
|
55
57
|
end
|
56
58
|
end
|
57
|
-
end
|
59
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RShade
|
2
4
|
module Filter
|
3
5
|
class IncludePathFilter < AbstractFilter
|
@@ -22,6 +24,7 @@ module RShade
|
|
22
24
|
paths.any? do |path|
|
23
25
|
next str?(path, event_path) if path.is_a? String
|
24
26
|
next regexp?(path, event_path) if path.is_a? Regexp
|
27
|
+
|
25
28
|
false
|
26
29
|
end
|
27
30
|
end
|
@@ -31,6 +34,7 @@ module RShade
|
|
31
34
|
end
|
32
35
|
|
33
36
|
private
|
37
|
+
|
34
38
|
def str?(str, event_path)
|
35
39
|
event_path.include?(str)
|
36
40
|
end
|
@@ -40,4 +44,4 @@ module RShade
|
|
40
44
|
end
|
41
45
|
end
|
42
46
|
end
|
43
|
-
end
|
47
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RShade
|
4
|
+
module Formatter
|
5
|
+
module Stack
|
6
|
+
class Json
|
7
|
+
attr_reader :filepath, :pretty
|
8
|
+
|
9
|
+
def initialize(filepath:, pretty: false)
|
10
|
+
@filepath = filepath
|
11
|
+
@pretty = pretty
|
12
|
+
end
|
13
|
+
|
14
|
+
# @param [Array<RShade::StackFrame>] stack_frames
|
15
|
+
def call(stack_frames)
|
16
|
+
payload = stack_frames.map.with_index do |frame, idx|
|
17
|
+
serialize(idx, frame)
|
18
|
+
end
|
19
|
+
|
20
|
+
File.open(filepath, 'a+') do |file|
|
21
|
+
record = {
|
22
|
+
time: Time.now.getutc,
|
23
|
+
thread_id: Thread.current,
|
24
|
+
thread_list: Thread.list,
|
25
|
+
frames: payload
|
26
|
+
}
|
27
|
+
file.puts(convert_to_json(record, pretty))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def convert_to_json(object, pretty)
|
34
|
+
return JSON.pretty_generate(object) if pretty
|
35
|
+
|
36
|
+
JSON.generate(object)
|
37
|
+
end
|
38
|
+
|
39
|
+
# @param [RShade::StackFrame] frame
|
40
|
+
def serialize(idx, frame)
|
41
|
+
{
|
42
|
+
frame: idx,
|
43
|
+
source_location: "#{frame.source_location[:path]}:#{frame.source_location[:line]}",
|
44
|
+
local_variables: frame.local_vars,
|
45
|
+
receiver_variables: frame.receiver_variables
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RShade
|
4
|
+
module Formatter
|
5
|
+
module Stack
|
6
|
+
class String
|
7
|
+
ROOT_SEP = "---\n"
|
8
|
+
|
9
|
+
def initialize(opts = {}); end
|
10
|
+
|
11
|
+
# @param [RShade::EventProcessor] stack
|
12
|
+
def call(stack)
|
13
|
+
buffer = StringIO.new
|
14
|
+
stack.each_with_index do |frame, idx|
|
15
|
+
if idx.zero?
|
16
|
+
buffer << ROOT_SEP
|
17
|
+
next
|
18
|
+
end
|
19
|
+
next unless frame
|
20
|
+
|
21
|
+
buffer.write line(idx, frame, idx)
|
22
|
+
end
|
23
|
+
buffer.string
|
24
|
+
end
|
25
|
+
|
26
|
+
# @param [RShade::StackFrame] frame
|
27
|
+
def line(line_idx, frame, depth)
|
28
|
+
source_location = ColorizedString["(#{frame.source_location[:path]}:#{frame.source_location[:line]})"].colorize(:green)
|
29
|
+
var_str = frame.local_vars.map do |_, val|
|
30
|
+
var_name = val[:name]
|
31
|
+
var_value = val[:value]
|
32
|
+
var_type = val[:type]
|
33
|
+
"#{var_type} #{var_name} => (#{var_value})"
|
34
|
+
end.join(', ')
|
35
|
+
colorized_var_str = ColorizedString[var_str].colorize(:blue)
|
36
|
+
"#{' ' * depth}[frame: #{line_idx}]#{source_location} => local vars: (#{colorized_var_str})\n"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RShade
|
4
|
+
module Formatter
|
5
|
+
module Trace
|
6
|
+
class File
|
7
|
+
attr_reader :formatter
|
8
|
+
|
9
|
+
FILE_NAME = 'stacktrace.json'
|
10
|
+
|
11
|
+
def initialize(args = {})
|
12
|
+
@formatter = args.fetch(:format, Json)
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param [RShade::EventProcessor] event_store
|
16
|
+
def call(event_store)
|
17
|
+
data = formatter.call(event_store)
|
18
|
+
if formatter == Json
|
19
|
+
write_to_file(JSON.pretty_generate(data))
|
20
|
+
else
|
21
|
+
write_to_file(data.to_s)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def write_to_file(data)
|
26
|
+
::File.open(::File.join(RShade::Config.store_dir, FILE_NAME), 'w+') do |f|
|
27
|
+
f.write data
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module RShade
|
6
|
+
module Formatter
|
7
|
+
module Trace
|
8
|
+
class Html
|
9
|
+
attr_reader :formatter
|
10
|
+
|
11
|
+
FILE_NAME = 'stacktrace.html'
|
12
|
+
TEMPLATE = 'html/template.html.erb'
|
13
|
+
|
14
|
+
def initialize(args = {})
|
15
|
+
@formatter = args.fetch(:formatter, Json)
|
16
|
+
end
|
17
|
+
|
18
|
+
# @param [RShade::EventProcessor] event_store
|
19
|
+
def call(event_store)
|
20
|
+
data = formatter.call(event_store)
|
21
|
+
erb_template = ERB.new(template)
|
22
|
+
content = erb_template.result_with_hash({ json: data.to_json })
|
23
|
+
write_to_file(content)
|
24
|
+
end
|
25
|
+
|
26
|
+
def write_to_file(data)
|
27
|
+
::File.open(::File.join(RShade::Config.store_dir, FILE_NAME), 'w+') do |f|
|
28
|
+
f.write data
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def template
|
33
|
+
@template ||= ::File.read(::File.join(::RShade::Config.root_dir, TEMPLATE))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RShade
|
4
|
+
module Formatter
|
5
|
+
module Trace
|
6
|
+
class Json
|
7
|
+
attr_reader :event_processor
|
8
|
+
|
9
|
+
# @param [RShade::EventProcessor] event_store
|
10
|
+
def call(event_store)
|
11
|
+
@event_store = event_store
|
12
|
+
flat
|
13
|
+
end
|
14
|
+
|
15
|
+
def flat
|
16
|
+
arr = []
|
17
|
+
event_store.each do |node|
|
18
|
+
arr << item(node.event)
|
19
|
+
end
|
20
|
+
arr.sort_by { |item| item[:level] }
|
21
|
+
end
|
22
|
+
|
23
|
+
def hierarchical
|
24
|
+
hash = {}
|
25
|
+
event_store.each do |node|
|
26
|
+
depth = node.level
|
27
|
+
ref = hash_iterate(hash, depth)
|
28
|
+
ref[:data] = item(node)
|
29
|
+
end
|
30
|
+
sort_hash(hash)
|
31
|
+
end
|
32
|
+
|
33
|
+
def sort_hash(h)
|
34
|
+
{}.tap do |h2|
|
35
|
+
h.sort.each do |k, v|
|
36
|
+
h2[k] = v.is_a?(Hash) ? sort_hash(v) : v
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def hash_iterate(hash, depth)
|
42
|
+
(0..depth).each do |_lvl|
|
43
|
+
hash[:inner] = {} unless hash[:inner]
|
44
|
+
hash = hash[:inner]
|
45
|
+
end
|
46
|
+
hash
|
47
|
+
end
|
48
|
+
|
49
|
+
def item(value)
|
50
|
+
{
|
51
|
+
class: value.klass.to_s,
|
52
|
+
method_name: value.method_name,
|
53
|
+
full_path: "#{value.path}:#{value.lineno}",
|
54
|
+
level: value.depth,
|
55
|
+
vars: value.vars
|
56
|
+
}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RShade
|
4
|
+
module Formatter
|
5
|
+
module Trace
|
6
|
+
class String
|
7
|
+
ROOT_SEP = "---\n"
|
8
|
+
|
9
|
+
def initialize(opts = {}); end
|
10
|
+
|
11
|
+
# @param [RShade::EventProcessor] event_store
|
12
|
+
def call(event_store)
|
13
|
+
buffer = StringIO.new
|
14
|
+
event_store.each_with_index do |node, idx|
|
15
|
+
depth = node.level
|
16
|
+
event = node.value
|
17
|
+
if depth == 1
|
18
|
+
buffer << ROOT_SEP
|
19
|
+
next
|
20
|
+
end
|
21
|
+
next unless event
|
22
|
+
|
23
|
+
buffer.write line(idx, event, node.vlevel)
|
24
|
+
end
|
25
|
+
buffer.string
|
26
|
+
end
|
27
|
+
|
28
|
+
def line(line_idx, value, depth)
|
29
|
+
vars = value.vars
|
30
|
+
returned_value = value.return_value || {}
|
31
|
+
returned_str = "#{returned_value[:type]} #{returned_value[:value]}"
|
32
|
+
returned = ColorizedString["=> |#{returned_str}|"].colorize(:magenta)
|
33
|
+
|
34
|
+
class_method = ColorizedString["#{value.klass}##{value.method_name}"].colorize(:green)
|
35
|
+
full_path = ColorizedString["#{value.path}:#{value.lineno}"].colorize(:blue)
|
36
|
+
line_idx = ColorizedString["[#{line_idx}] "].colorize(:red)
|
37
|
+
var_str = vars.map do |_, val|
|
38
|
+
var_name = val[:name]
|
39
|
+
var_value = val[:value]
|
40
|
+
var_type = val[:type]
|
41
|
+
"#{var_type} #{var_name} => (#{var_value})"
|
42
|
+
end.join(', ')
|
43
|
+
"#{' ' * depth}#{line_idx}#{class_method}(#{var_str}) #{returned} -> #{full_path}\n"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/rshade/rspec/rspec.rb
CHANGED
@@ -1,13 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RShade
|
2
|
-
REPORTS = []
|
4
|
+
REPORTS = [].freeze
|
3
5
|
|
4
6
|
module RSpecHelper
|
5
|
-
def rshade_reveal(options = {})
|
7
|
+
def rshade_reveal(options = {}, &block)
|
6
8
|
raise 'No block given' unless block_given?
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
9
|
+
|
10
|
+
options.merge!(formatter: Formatter::String) { |_key, v1, _v2| v1 }
|
11
|
+
result = Trace.reveal(options, &block)
|
11
12
|
REPORTS.push result.show
|
12
13
|
end
|
13
14
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RShade
|
4
|
+
module Serializer
|
5
|
+
class Traversal
|
6
|
+
attr_reader :types
|
7
|
+
|
8
|
+
def initialize(custom_types = {})
|
9
|
+
@types = default_types.merge(custom_types)
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(hash)
|
13
|
+
new_val = {}
|
14
|
+
hash.each do |name, value|
|
15
|
+
new_val[name] = traverse(value)
|
16
|
+
end
|
17
|
+
new_val
|
18
|
+
end
|
19
|
+
|
20
|
+
def default_types
|
21
|
+
{
|
22
|
+
default: lambda(&:to_s),
|
23
|
+
Integer => ->(value) { value },
|
24
|
+
Float => ->(value) { value },
|
25
|
+
Numeric => ->(value) { value },
|
26
|
+
String => ->(value) { value },
|
27
|
+
Hash => lambda do |value|
|
28
|
+
hash = {}
|
29
|
+
begin
|
30
|
+
value.each do |k, v|
|
31
|
+
hash[k] = traverse(v)
|
32
|
+
end
|
33
|
+
rescue Exception => e
|
34
|
+
binding.pry
|
35
|
+
end
|
36
|
+
|
37
|
+
hash
|
38
|
+
end,
|
39
|
+
Array => lambda do |value|
|
40
|
+
value.map { |item| traverse(item) }
|
41
|
+
end
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
def traverse(value)
|
46
|
+
klass = Class
|
47
|
+
klass = value.class unless value.is_a?(Class)
|
48
|
+
serializer = types[klass]
|
49
|
+
serializer ||= types[:default]
|
50
|
+
serializer.call(value)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/rshade/stack.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RShade
|
4
|
+
class Stack
|
5
|
+
attr_reader :config
|
6
|
+
|
7
|
+
def initialize(config: nil, registry: ::RShade::Config::Registry.instance)
|
8
|
+
@config = config || registry.default_stack_config
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.trace(config: nil)
|
12
|
+
new(config:).trace
|
13
|
+
end
|
14
|
+
|
15
|
+
def trace
|
16
|
+
config.exclude_gems!
|
17
|
+
result = binding.callers.drop(2).map do |bind|
|
18
|
+
frame = StackFrame.from_binding(bind)
|
19
|
+
next nil unless config.filter.call(frame)
|
20
|
+
|
21
|
+
frame
|
22
|
+
end.compact.reverse
|
23
|
+
config.formatter.call(result)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RShade
|
4
|
+
# nodoc
|
5
|
+
class StackFrame
|
6
|
+
attr_reader :hash
|
7
|
+
|
8
|
+
def initialize(hash)
|
9
|
+
@hash = hash
|
10
|
+
end
|
11
|
+
|
12
|
+
%i[source_location source local_vars receiver_variables].each do |method_name|
|
13
|
+
define_method method_name do
|
14
|
+
fetch method_name
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def path
|
19
|
+
source_location[:path]
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param [Binding] binding_frame
|
23
|
+
def self.from_binding(binding_frame)
|
24
|
+
source_location = {
|
25
|
+
path: binding_frame.source_location[0],
|
26
|
+
line: binding_frame.source_location[1]
|
27
|
+
}
|
28
|
+
local_vars = binding_frame.local_variables.each_with_object({}) do |var_name, memo|
|
29
|
+
value = binding_frame.local_variable_get(var_name)
|
30
|
+
type = value.is_a?(Class) ? value : value.class
|
31
|
+
memo[var_name] = {
|
32
|
+
name: var_name,
|
33
|
+
value:,
|
34
|
+
type: type.to_s
|
35
|
+
}
|
36
|
+
end
|
37
|
+
receiver_variables = binding_frame.receiver.instance_variables.each_with_object({}) do |var_name, memo|
|
38
|
+
value = binding_frame.receiver.instance_variable_get(var_name)
|
39
|
+
type = value.is_a?(Class) ? value : value.class
|
40
|
+
memo[var_name] = {
|
41
|
+
name: var_name,
|
42
|
+
value:,
|
43
|
+
type: type.to_s
|
44
|
+
}
|
45
|
+
end
|
46
|
+
hash = { source_location:, local_vars:, source: {}, receiver_variables: }
|
47
|
+
new(hash)
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_s
|
51
|
+
"#{source_location} - #{local_vars} - #{source}"
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def fetch(key)
|
57
|
+
@hash[key]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/rshade/trace.rb
CHANGED
@@ -1,22 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RShade
|
2
4
|
class Trace
|
3
5
|
attr_reader :config, :event_store
|
4
|
-
|
6
|
+
|
5
7
|
# @param [RShade::Config,RShade::Config::Store] config
|
6
8
|
def initialize(config)
|
7
9
|
@config = fetch_config(config)
|
8
10
|
@event_store = EventTree.new
|
9
11
|
end
|
10
12
|
|
11
|
-
def self.reveal(config=nil, &block)
|
13
|
+
def self.reveal(config = nil, &block)
|
12
14
|
new(config).reveal(&block)
|
13
15
|
end
|
14
16
|
|
15
17
|
def reveal(&block)
|
16
|
-
processor = EventProcessor.new(
|
18
|
+
processor = EventProcessor.new(event_store, config)
|
17
19
|
observer = EventObserver.new(config, processor)
|
18
20
|
observable = RShade::TraceObservable.new([observer], config)
|
19
|
-
observable.reveal
|
21
|
+
observable.reveal(&block)
|
20
22
|
self
|
21
23
|
end
|
22
24
|
|
@@ -25,8 +27,9 @@ module RShade
|
|
25
27
|
end
|
26
28
|
|
27
29
|
private
|
30
|
+
|
28
31
|
def fetch_config(config)
|
29
|
-
config
|
32
|
+
config ||= ::RShade::Config.default
|
30
33
|
config = config.value if config.is_a?(::RShade::Config)
|
31
34
|
config
|
32
35
|
end
|
@@ -1,7 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RShade
|
2
4
|
class TraceObservable
|
3
5
|
include Observable
|
4
6
|
attr_reader :trace_p
|
7
|
+
|
5
8
|
CALL_EVENTS = Set[:call, :c_call, :b_call]
|
6
9
|
RETURN_EVENTS = Set[:return, :c_return, :b_return]
|
7
10
|
|
@@ -27,6 +30,7 @@ module RShade
|
|
27
30
|
end
|
28
31
|
|
29
32
|
private
|
33
|
+
|
30
34
|
# more info https://rubyapi.org/3.1/o/tracepoint
|
31
35
|
# @param [TracePoint] tp
|
32
36
|
def process(tp)
|
@@ -34,6 +38,7 @@ module RShade
|
|
34
38
|
event = Event.from_trace_point(tp)
|
35
39
|
return notify_observers(event, :enter) if CALL_EVENTS.include?(tp.event)
|
36
40
|
return notify_observers(event, :leave) if RETURN_EVENTS.include?(tp.event)
|
41
|
+
|
37
42
|
notify_observers(event, :other)
|
38
43
|
end
|
39
44
|
end
|
data/lib/rshade/version.rb
CHANGED