rshade 0.1.6 → 0.1.7

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
  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