rshade 0.1.6 → 0.1.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6df1b60bffc16ead7fcebdeb882136144baa8e1fa33b2f4bad417dd3dfe68d92
4
- data.tar.gz: 072dcf363cfb6e9ac2112970fe133c8551fb9c3be7e02ad826ae8b19ca39a5f5
3
+ metadata.gz: 5594d3ba4348f6f4c4b73a74c223a7b30f3b7eda7216c72d0d122079cae63bf7
4
+ data.tar.gz: b071916008465bed00ff107b8b88fe778235a333e1a24c74af5ea62631ec4b75
5
5
  SHA512:
6
- metadata.gz: 9a4fec3f4b69197d872ff150aaf31e8202ada46b5a44d3b0d63ee8f831807f2db20db3e1a403e490ca3605e7d026099c51e4fdd55a8603e343a08b84fcb873ca
7
- data.tar.gz: a27714bfafda9b4d26adb96c135ea596d37a212586ede2a0df7cab2c751998cae205c16dfdb7d32fb903f2f343dfbf04dce73105f50e30ed98bea927083f8f5b
6
+ metadata.gz: b4a81694ecce4e7063a8a8d4cd5ed758ea93ca151aa0b09cd785e281d206c4cdcdfa389237523fe05f57441c6f4ad648f5cd60e1abb46793162b2ff182965555
7
+ data.tar.gz: 756a618370faa424864563640ac0389124201bc5c49eb47fdb6cae0fe8f535dadc7c97c366b6c5dfaa330700a39d9e2eaa6e9caad9538209319a7da9587c142f
@@ -14,7 +14,7 @@ GEM
14
14
  pry (0.12.2)
15
15
  coderay (~> 1.1.0)
16
16
  method_source (~> 0.9.0)
17
- rake (10.5.0)
17
+ rake (13.0.1)
18
18
  rspec (3.8.0)
19
19
  rspec-core (~> 3.8.0)
20
20
  rspec-expectations (~> 3.8.0)
@@ -35,9 +35,9 @@ PLATFORMS
35
35
  DEPENDENCIES
36
36
  bundler (~> 1.16)
37
37
  pry
38
- rake (~> 10.0)
38
+ rake (>= 12.3.3)
39
39
  rshade!
40
40
  rspec (~> 3.0)
41
41
 
42
42
  BUNDLED WITH
43
- 1.16.6
43
+ 1.17.3
data/README.md CHANGED
@@ -5,8 +5,7 @@
5
5
  Ruby Shade or RShade gem to help you to reveal what lines of code are used in program execution.
6
6
 
7
7
  ```ruby
8
- trace = RShade::Trace.new
9
- trace.reveal do
8
+ trace = RShade::Trace.reveal do
10
9
  #your code here
11
10
  end
12
11
  trace.show
@@ -1,10 +1,16 @@
1
1
  require 'colorize'
2
2
  require 'rshade/configuration'
3
- require 'rshade/source'
4
- require 'rshade/tree'
5
- require 'rshade/source_node'
3
+ require 'rshade/base'
4
+ require 'rshade/event_serializer'
5
+ require 'rshade/filter/app_filter'
6
+ require 'rshade/formatter/string'
7
+ require 'rshade/formatter/json'
8
+ require 'rshade/formatter/stdout'
9
+ require 'rshade/formatter/http'
10
+ require 'rshade/event'
11
+ require 'rshade/event_store'
6
12
  require 'rshade/trace'
7
- require 'rshade/rspec'
13
+ require 'rshade/rspec/rspec'
8
14
  require 'rshade/version'
9
15
 
10
16
 
@@ -15,7 +21,7 @@ module RShade
15
21
  class << self
16
22
  attr_writer :config
17
23
 
18
- def configuration
24
+ def config
19
25
  @config ||= Configuration.new
20
26
  end
21
27
 
@@ -0,0 +1,13 @@
1
+ module RShade
2
+ class Base
3
+ def initialize(*args); end
4
+
5
+ def self.call(*args)
6
+ new(*args).call
7
+ end
8
+
9
+ def call
10
+ raise NotImplementedError
11
+ end
12
+ end
13
+ end
@@ -2,21 +2,17 @@ module RShade
2
2
  class Configuration
3
3
  RUBY_VERSION_PATTERN = /ruby-[0-9.]*/
4
4
 
5
- attr_accessor :custom_arg_print, :included_gems
5
+ attr_accessor :track_gems, :filter, :formatter
6
6
 
7
7
  def initialize
8
- @included_gems = []
9
- end
10
-
11
- def default_arg_print(args)
12
-
8
+ @track_gems = Set.new
13
9
  end
14
10
 
15
11
  def excluded_paths
16
12
  @excluded_paths ||= begin
17
13
  paths = [ENV['GEM_PATH'].split(':'), parse_ruby_version].flatten.compact
18
14
  paths.reject do |v|
19
- included_gems.any? { |gem_name| v.include? gem_name }
15
+ track_gems.any? { |gem_name| v.include? gem_name }
20
16
  end
21
17
  end
22
18
  end
@@ -28,5 +24,16 @@ module RShade
28
24
  val[0]
29
25
  end
30
26
 
27
+ def filter
28
+ @filter ||= ::RShade::Filter::AppFilter
29
+ end
30
+
31
+ def formatter
32
+ @formatter ||= ::RShade::Formatter::Stdout
33
+ end
34
+
35
+ def store_dir
36
+ File.expand_path('../../tmp', __dir__)
37
+ end
31
38
  end
32
39
  end
@@ -0,0 +1,35 @@
1
+ module RShade
2
+ # nodoc
3
+ class Event
4
+ attr_reader :hash
5
+ attr_accessor :depth
6
+
7
+ def initialize(hash)
8
+ @hash = hash
9
+ end
10
+
11
+ def level
12
+ @hash[:level]
13
+ end
14
+
15
+ def klass
16
+ @hash[:klass]
17
+ end
18
+
19
+ def path
20
+ @hash[:path]
21
+ end
22
+
23
+ def lineno
24
+ @hash[:lineno]
25
+ end
26
+
27
+ def method_name
28
+ @hash[:method_name]
29
+ end
30
+
31
+ def vars
32
+ @hash[:vars]
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,29 @@
1
+ require 'date'
2
+ module RShade
3
+ class EventSerializer < Base
4
+ attr_reader :evt, :level
5
+ SERIALIZE_CLASSES = [NilClass, TrueClass, FalseClass, Numeric, Time, Date, String, Symbol, Array, Hash]
6
+ def initialize(evt, level)
7
+ @evt = evt
8
+ @level = level
9
+ end
10
+
11
+ def call
12
+ { level: @level, path: evt.path, lineno: evt.lineno, klass: evt.defined_class, method_name: evt.method_id, vars: process_locals(evt) }
13
+ end
14
+
15
+ def process_locals(evt)
16
+ vars = {}
17
+ evt.binding.local_variables.each do |var|
18
+ local_var = evt.binding.local_variable_get var
19
+ if SERIALIZE_CLASSES.any? { |klass| local_var.is_a?(klass) }
20
+ vars[var] = local_var
21
+ else
22
+ class_name = local_var.is_a?(Class) ? local_var.to_s : local_var.class.to_s
23
+ vars[var] = "FILTERED[#{class_name}]"
24
+ end
25
+ end
26
+ vars
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,23 @@
1
+ module RShade
2
+ # nodoc
3
+ class EventStore
4
+ attr_reader :events
5
+
6
+ def initialize
7
+ @events = []
8
+ end
9
+
10
+ def <<(event)
11
+ events << event
12
+ end
13
+
14
+ def iterate(&block)
15
+ pos_map = {}
16
+ @events.map {|item| item.level }.uniq.sort.each_with_index { |item, index| pos_map[item] = index}
17
+ @events.uniq{|item| [item.level, "#{item.klass}##{item.method_name}"]}.sort_by { |item| item.depth }.each do |item|
18
+ item.depth = pos_map[item.level]
19
+ yield(item, item.depth)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,20 @@
1
+ module RShade
2
+ module Filter
3
+ class AppFilter < ::RShade::Base
4
+ attr_reader :data
5
+
6
+ def initialize(data)
7
+ @data = data
8
+ end
9
+
10
+ def call
11
+ valid?(data[:path])
12
+ end
13
+
14
+ def valid?(path)
15
+ return true if RShade.config.track_gems.any? { |item| path.include? item }
16
+ RShade.config.excluded_paths.none? { |item| path.include? item }
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,8 @@
1
+ module RShade
2
+ module Formatter
3
+ class Http < ::RShade::Base
4
+ def call
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,70 @@
1
+ module RShade
2
+ module Formatter
3
+ class Json < ::RShade::Base
4
+ attr_reader :event_store
5
+ FILE_NAME = 'stacktrace.json'.freeze
6
+
7
+ def initialize(event_store)
8
+ @event_store = event_store
9
+ end
10
+
11
+ def call
12
+ flat
13
+ end
14
+
15
+ def flat
16
+ arr = []
17
+ event_store.iterate do |node, depth|
18
+ arr << item(node)
19
+ end
20
+ write_to_file(JSON.pretty_generate(arr.sort_by { |item| item[:depth]}))
21
+ arr
22
+ end
23
+
24
+ def hierarchical
25
+ hash = {}
26
+ event_store.iterate do |node, depth|
27
+ ref = hash_iterate(hash, depth)
28
+ ref[:data] = item(node)
29
+ end
30
+ hash = sort_hash(hash)
31
+ write_to_file(JSON.pretty_generate(hash))
32
+ hash
33
+ end
34
+
35
+ def write_to_file(data)
36
+ File.open(File.join(RShade.config.store_dir, FILE_NAME), "w+") do |f|
37
+ f.write data
38
+ end
39
+ end
40
+
41
+ def sort_hash(h)
42
+ {}.tap do |h2|
43
+ h.sort.each do |k,v|
44
+ h2[k] = v.is_a?(Hash) ? sort_hash(v) : v
45
+ end
46
+ end
47
+ end
48
+
49
+ def hash_iterate(hash, depth)
50
+ (0..depth).each do |lvl|
51
+ unless hash[:inner]
52
+ hash[:inner] = {}
53
+ end
54
+ hash = hash[:inner]
55
+ end
56
+ hash
57
+ end
58
+
59
+ def item(value)
60
+ {
61
+ class: value.klass.to_s,
62
+ method_name: value.method_name,
63
+ full_path: "#{value.path}:#{value.lineno}",
64
+ depth: value.depth,
65
+ vars: value.vars
66
+ }
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,10 @@
1
+ module RShade
2
+ module Formatter
3
+ class Stdout < String
4
+ def call
5
+ buffer = super
6
+ puts buffer
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,30 @@
1
+ module RShade
2
+ module Formatter
3
+ class String < ::RShade::Base
4
+ attr_reader :event_store
5
+ ROOT_SEP = "---\n"
6
+
7
+ def initialize(event_store)
8
+ @event_store = event_store
9
+ end
10
+
11
+ def call
12
+ buffer = StringIO.new
13
+ event_store.iterate do |node, depth|
14
+ if depth == 1
15
+ buffer << ROOT_SEP
16
+ next
17
+ end
18
+ puts line(node, depth)
19
+ end
20
+ buffer.string
21
+ end
22
+
23
+ def line(value, depth)
24
+ class_method = "#{value.klass}##{value.method_name}".colorize(:green)
25
+ full_path = "#{value.path}:#{value.lineno}".colorize(:blue)
26
+ "#{' ' * depth}#{class_method}(#{value.vars}) -> #{full_path}\n"
27
+ end
28
+ end
29
+ end
30
+ end
File without changes
@@ -2,15 +2,13 @@ module RShade
2
2
  REPORTS = []
3
3
 
4
4
  module RSpecHelper
5
- def rshade_reveal(type = ::RShade::APP_TRACE, options = {})
5
+ def rshade_reveal(options = {})
6
6
  raise 'No block given' unless block_given?
7
-
8
- trace = Trace.new
9
- trace.reveal(options) do
7
+ options.merge!(formatter: Formatter::String) { |_key,v1, _v2| v1 }
8
+ result = Trace.reveal(options) do
10
9
  yield
11
10
  end
12
-
13
- REPORTS.push trace.show(type)
11
+ REPORTS.push result.show
14
12
  end
15
13
  end
16
14
  end
@@ -0,0 +1,4 @@
1
+ module RShade
2
+ class Storage
3
+ end
4
+ end
@@ -1,68 +1,53 @@
1
1
  module RShade
2
2
  class Trace
3
- attr_accessor :source_tree, :options
3
+ attr_accessor :event_store, :formatter, :filter
4
4
  EVENTS = %i[call return].freeze
5
5
 
6
- def initialize
7
- @source_tree = SourceNode.new(nil)
6
+ def initialize(options={})
7
+ @event_store = EventStore.new
8
+ @formatter = options.fetch(:formatter, RShade.config.formatter)
9
+ @filter = options.fetch(:filter, RShade.config.filter)
8
10
  @tp = TracePoint.new(*EVENTS, &method(:process_trace))
9
- @stack = [@source_tree]
11
+ @level = 1
12
+ @stat = {}
13
+ @calls = 0
14
+ @returns = 0
10
15
  end
11
16
 
12
- def reveal(options = {})
17
+ def self.reveal(options={}, &block)
18
+ new(options).reveal(&block)
19
+ end
20
+
21
+ def reveal
13
22
  return unless block_given?
14
23
 
15
24
  @tp.enable
16
25
  yield
26
+ self
17
27
  ensure
18
28
  @tp.disable
19
29
  end
20
30
 
21
- def show(type = ::RShade::APP_TRACE)
22
- return show_app_trace if type == ::RShade::APP_TRACE
23
-
24
- show_full_trace
31
+ def show
32
+ formatter.call(event_store)
25
33
  end
26
34
 
27
- def show_full_trace(tree = nil)
28
- buffer = StringIO.new
29
- tree ||= source_tree
30
- tree.pre_order_traverse do |node, depth|
31
- if node.root?
32
- buffer << "---\n"
33
- next
34
- end
35
-
36
- buffer << "#{' ' * depth} #{node.value.pretty}\n" if node.value
37
- end
38
- puts buffer.string
39
- end
40
-
41
- def show_app_trace
42
- clone = source_tree.clone_by do |node|
43
- next true if node.root?
44
-
45
- node.value.app_code?
46
- end
47
- show_full_trace(clone)
35
+ def stat
36
+ { calls: @calls, returns: @returns }
48
37
  end
49
38
 
50
39
  def process_trace(tp)
51
40
  if tp.event == :call
52
- parent = @stack.last
53
- vars = {}
54
- tp.binding.local_variables.each do |var|
55
- vars[var] = tp.binding.local_variable_get var
56
- end
57
- hash = { level: @stack.size, path: tp.path, lineno: tp.lineno, klass: tp.defined_class, method_name: tp.method_id, vars: vars }
58
- node = SourceNode.new(Source.new(hash))
59
- node.parent = parent
60
- parent << node
61
- @stack.push node
41
+ @level +=1
42
+ hash = EventSerializer.call(tp, @level)
43
+ return unless filter.call(hash)
44
+ @calls += 1
45
+ event_store << Event.new(hash)
62
46
  end
63
47
 
64
- if tp.event == :return && @stack.size > 1
65
- @stack.pop
48
+ if tp.event == :return && @level > 0
49
+ @returns += 1
50
+ @level -=1
66
51
  end
67
52
  end
68
53
  end
@@ -1,3 +1,3 @@
1
1
  module RShade
2
- VERSION = "0.1.6"
2
+ VERSION = "0.1.7"
3
3
  end
@@ -39,6 +39,6 @@ Gem::Specification.new do |spec|
39
39
  spec.add_runtime_dependency 'colorize'
40
40
 
41
41
  spec.add_development_dependency "bundler", "~> 1.16"
42
- spec.add_development_dependency "rake", "~> 10.0"
42
+ spec.add_development_dependency "rake", ">= 12.3.3"
43
43
  spec.add_development_dependency "rspec", "~> 3.0"
44
44
  end
data/todo.md ADDED
@@ -0,0 +1,8 @@
1
+ 1. Should I use rails way organizing module/file naming or not?
2
+ 2. Reduce global state usage
3
+ 3. Problem with stack deep
4
+ 4. Problem when have binary values error in serialization (Encoding problems)
5
+ 5. Make filter while tracing that will be more efficient
6
+ 6. sort depth and than replace values
7
+ 7. tree not working bcz of vars serialization
8
+ 8. Some classes in Rails can't serialize safely produce StackTraceTooDeep
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rshade
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Lopatin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-11-13 00:00:00.000000000 Z
11
+ date: 2020-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -42,16 +42,16 @@ dependencies:
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '10.0'
47
+ version: 12.3.3
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '10.0'
54
+ version: 12.3.3
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -84,15 +84,24 @@ files:
84
84
  - bin/console
85
85
  - bin/setup
86
86
  - lib/rshade.rb
87
+ - lib/rshade/base.rb
87
88
  - lib/rshade/configuration.rb
88
- - lib/rshade/rspec.rb
89
- - lib/rshade/source.rb
90
- - lib/rshade/source_node.rb
89
+ - lib/rshade/event.rb
90
+ - lib/rshade/event_serializer.rb
91
+ - lib/rshade/event_store.rb
92
+ - lib/rshade/filter/app_filter.rb
93
+ - lib/rshade/formatter/http.rb
94
+ - lib/rshade/formatter/json.rb
95
+ - lib/rshade/formatter/stdout.rb
96
+ - lib/rshade/formatter/string.rb
97
+ - lib/rshade/rails/rails.rb
98
+ - lib/rshade/rspec/rspec.rb
99
+ - lib/rshade/storage.rb
91
100
  - lib/rshade/trace.rb
92
- - lib/rshade/tree.rb
93
101
  - lib/rshade/version.rb
94
102
  - rshade.gemspec
95
103
  - shade.jpg
104
+ - todo.md
96
105
  homepage: https://github.com/gingray/rshade
97
106
  licenses:
98
107
  - MIT
@@ -116,8 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
125
  - !ruby/object:Gem::Version
117
126
  version: '0'
118
127
  requirements: []
119
- rubyforge_project:
120
- rubygems_version: 2.7.8
128
+ rubygems_version: 3.0.8
121
129
  signing_key:
122
130
  specification_version: 4
123
131
  summary: https://github.com/gingray/rshade
@@ -1,46 +0,0 @@
1
- module RShade
2
- # nodoc
3
- class Source
4
-
5
- def initialize(hash)
6
- @hash = hash
7
- end
8
-
9
- def klass
10
- @hash[:klass]
11
- end
12
-
13
- def lib_code?
14
- !app_code?
15
- end
16
-
17
- def app_code?
18
- return true if RShade.configuration.included_gems.any? { |item| path.include? item }
19
-
20
- @app_code ||= RShade.configuration.excluded_paths.none? { |item| path.include? item }
21
- end
22
-
23
- def path
24
- @hash[:path]
25
- end
26
-
27
- def lineno
28
- @hash[:lineno]
29
- end
30
-
31
- def method_name
32
- @hash[:method_name]
33
- end
34
-
35
- def vars
36
- @hash[:vars]
37
- end
38
-
39
-
40
- def pretty
41
- class_method = "#{klass}##{method_name}".colorize(:green)
42
- full_path = "#{path}:#{lineno}".colorize(:blue)
43
- "#{class_method}(#{vars.to_json}) -> #{full_path}"
44
- end
45
- end
46
- end
@@ -1,23 +0,0 @@
1
- module RShade
2
- # nodoc
3
- class SourceNode < Tree
4
- def initialize(value = nil)
5
- super(value)
6
- end
7
-
8
- def clone_by(new_tree = SourceNode.new(nil), &block)
9
- if yield(self)
10
- new_tree.value = value
11
- node = SourceNode.new(nil)
12
- node.parent = new_tree
13
- new_tree << node
14
- new_tree = node
15
- end
16
-
17
- nodes.each do |item|
18
- item.clone_by(new_tree, &block)
19
- end
20
- new_tree
21
- end
22
- end
23
- end
@@ -1,30 +0,0 @@
1
- module RShade
2
- # nodoc
3
- class Tree
4
- attr_accessor :parent, :value
5
- attr_reader :nodes
6
-
7
- def initialize(value = nil)
8
- @value = value
9
- @nodes = []
10
- @parent = nil
11
- end
12
-
13
- def root?
14
- !parent
15
- end
16
-
17
- def <<(node)
18
- @nodes << node
19
- end
20
-
21
- def pre_order_traverse(depth = 0, &block)
22
- return unless block_given?
23
-
24
- yield(self, depth)
25
- nodes.each do |item|
26
- item.pre_order_traverse(depth + 1, &block)
27
- end
28
- end
29
- end
30
- end