rshade 0.1.3 → 0.1.8
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 +4 -4
- data/README.md +1 -2
- data/html/template.html.erb +72 -0
- data/lib/rshade.rb +26 -4
- data/lib/rshade/base.rb +13 -0
- data/lib/rshade/configuration.rb +43 -0
- data/lib/rshade/event.rb +35 -0
- data/lib/rshade/event_serializer.rb +41 -0
- data/lib/rshade/event_store.rb +23 -0
- data/lib/rshade/filter/app_filter.rb +20 -0
- data/lib/rshade/formatter/file.rb +28 -0
- data/lib/rshade/formatter/html.rb +31 -0
- data/lib/rshade/formatter/json.rb +60 -0
- data/lib/rshade/formatter/stdout.rb +10 -0
- data/lib/rshade/formatter/string.rb +30 -0
- data/lib/rshade/rails/rails.rb +0 -0
- data/lib/rshade/{rspec.rb → rspec/rspec.rb} +4 -6
- data/lib/rshade/storage.rb +4 -0
- data/lib/rshade/trace.rb +26 -41
- data/lib/rshade/version.rb +1 -1
- data/rshade.gemspec +1 -1
- data/todo.md +8 -0
- metadata +23 -12
- data/lib/rshade/source.rb +0 -57
- data/lib/rshade/source_node.rb +0 -23
- data/lib/rshade/tree.rb +0 -30
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f10cfe61e925b1882ff42ea7580a2a6d72b5eadd4f18831a7e52813e22d1daea
|
|
4
|
+
data.tar.gz: cfe32fccff6bd61114bb86d0fd0d790d66c61ca41ce7bda0fc39e03af73ddb46
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 34222d8c0982a0af1ccbd37a2436f3dfa58d164ad4614a51db4c2074aff55f5adc873aa89008b173a065ec83975b3e67f9266437931efc1725baf50d04638bd5
|
|
7
|
+
data.tar.gz: 231f085edc963e287f1e8ae1b0843567ff5857cbfd50d80e240548e143148609c44d02d76204a6dd021765785c7ce347e6d7dcdeb49a388ff08197ce52074f45
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
rshade (0.1.
|
|
4
|
+
rshade (0.1.7)
|
|
5
5
|
colorize
|
|
6
6
|
|
|
7
7
|
GEM
|
|
@@ -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 (
|
|
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 (
|
|
38
|
+
rake (>= 12.3.3)
|
|
39
39
|
rshade!
|
|
40
40
|
rspec (~> 3.0)
|
|
41
41
|
|
|
42
42
|
BUNDLED WITH
|
|
43
|
-
1.
|
|
43
|
+
1.17.3
|
data/README.md
CHANGED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
|
|
3
|
+
<html lang="en">
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<title>RShade call trace viewer</title>
|
|
7
|
+
<meta name="description" content="The HTML5 Herald">
|
|
8
|
+
<meta name="author" content="me">
|
|
9
|
+
<style>
|
|
10
|
+
body {
|
|
11
|
+
overflow-x: scroll;
|
|
12
|
+
}
|
|
13
|
+
.stacktrace-line {
|
|
14
|
+
color: #1c1c1c;
|
|
15
|
+
font-family: monospace;
|
|
16
|
+
border: 1px solid hsla(210,50%, 50%, 1);
|
|
17
|
+
margin-bottom: 10px;
|
|
18
|
+
width: fit-content;
|
|
19
|
+
}
|
|
20
|
+
.method-line {
|
|
21
|
+
font-size: 1.2rem;
|
|
22
|
+
padding: 10px;
|
|
23
|
+
background: hsla(210,50%, 50%, 0.1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.path-line {
|
|
27
|
+
padding: 10px;
|
|
28
|
+
font-size: 0.9rem;
|
|
29
|
+
background: hsla(110,50%, 50%, 0.1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.vars-line {
|
|
33
|
+
font-size: 0.7rem;
|
|
34
|
+
padding: 10px;
|
|
35
|
+
background: hsla(60,50%, 50%, 0.1);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
</style>
|
|
39
|
+
</head>
|
|
40
|
+
<body>
|
|
41
|
+
<div class="stacktrace"></div>
|
|
42
|
+
<script>
|
|
43
|
+
var data = <%=json %>;
|
|
44
|
+
var el = document.querySelector(".stacktrace");
|
|
45
|
+
for(i=0; i < data.length; i++) {
|
|
46
|
+
var value = data[i];
|
|
47
|
+
var newEl = document.createElement('div');
|
|
48
|
+
newEl.setAttribute("class", "stacktrace-line");
|
|
49
|
+
newEl.style.marginLeft = `${value.depth * 10}px`
|
|
50
|
+
|
|
51
|
+
line1 = document.createElement('div');
|
|
52
|
+
line1.setAttribute("class", "method-line");
|
|
53
|
+
line1.innerText = `${value.class}#${value.method_name}`;
|
|
54
|
+
|
|
55
|
+
var line2 = document.createElement('div');
|
|
56
|
+
line2.setAttribute("class", "path-line");
|
|
57
|
+
line2.innerText = `${value.class}#${value.full_path}`;
|
|
58
|
+
|
|
59
|
+
var line3 = document.createElement('div');
|
|
60
|
+
line3.setAttribute("class", "vars-line");
|
|
61
|
+
line3.innerText = JSON.stringify(value.vars)
|
|
62
|
+
|
|
63
|
+
newEl.appendChild(line1);
|
|
64
|
+
newEl.appendChild(line2);
|
|
65
|
+
newEl.appendChild(line3);
|
|
66
|
+
el.appendChild(newEl)
|
|
67
|
+
}
|
|
68
|
+
console.log(data);
|
|
69
|
+
</script>
|
|
70
|
+
|
|
71
|
+
</body>
|
|
72
|
+
</html>
|
data/lib/rshade.rb
CHANGED
|
@@ -1,12 +1,34 @@
|
|
|
1
1
|
require 'colorize'
|
|
2
|
-
require '
|
|
3
|
-
require 'rshade/
|
|
4
|
-
require 'rshade/
|
|
2
|
+
require 'erb'
|
|
3
|
+
require 'rshade/configuration'
|
|
4
|
+
require 'rshade/base'
|
|
5
|
+
require 'rshade/event_serializer'
|
|
6
|
+
require 'rshade/filter/app_filter'
|
|
7
|
+
require 'rshade/formatter/string'
|
|
8
|
+
require 'rshade/formatter/json'
|
|
9
|
+
require 'rshade/formatter/file'
|
|
10
|
+
require 'rshade/formatter/html'
|
|
11
|
+
require 'rshade/formatter/stdout'
|
|
12
|
+
require 'rshade/event'
|
|
13
|
+
require 'rshade/event_store'
|
|
5
14
|
require 'rshade/trace'
|
|
6
|
-
require 'rshade/rspec'
|
|
15
|
+
require 'rshade/rspec/rspec'
|
|
7
16
|
require 'rshade/version'
|
|
8
17
|
|
|
18
|
+
|
|
9
19
|
module RShade
|
|
10
20
|
APP_TRACE = :app_trace
|
|
11
21
|
FULL_TRACE = :full_trace
|
|
22
|
+
|
|
23
|
+
class << self
|
|
24
|
+
attr_writer :config
|
|
25
|
+
|
|
26
|
+
def config
|
|
27
|
+
@config ||= Configuration.new
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def configure
|
|
31
|
+
yield configuration
|
|
32
|
+
end
|
|
33
|
+
end
|
|
12
34
|
end
|
data/lib/rshade/base.rb
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module RShade
|
|
2
|
+
class Configuration
|
|
3
|
+
RUBY_VERSION_PATTERN = /ruby-[0-9.]*/
|
|
4
|
+
|
|
5
|
+
attr_accessor :track_gems, :filter, :formatter
|
|
6
|
+
|
|
7
|
+
def initialize
|
|
8
|
+
@track_gems = Set.new
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def excluded_paths
|
|
12
|
+
@excluded_paths ||= begin
|
|
13
|
+
paths = [ENV['GEM_PATH'].split(':'), parse_ruby_version].flatten.compact
|
|
14
|
+
paths.reject do |v|
|
|
15
|
+
track_gems.any? { |gem_name| v.include? gem_name }
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def parse_ruby_version
|
|
21
|
+
val = RUBY_VERSION_PATTERN.match(ENV['GEM_PATH'])
|
|
22
|
+
return nil unless val
|
|
23
|
+
|
|
24
|
+
val[0]
|
|
25
|
+
end
|
|
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
|
|
38
|
+
|
|
39
|
+
def root_dir
|
|
40
|
+
@root_dir ||= File.expand_path('../../', __dir__)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
data/lib/rshade/event.rb
ADDED
|
@@ -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,41 @@
|
|
|
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]
|
|
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
|
+
elsif local_var.is_a?(Hash)
|
|
22
|
+
vars[var] = shallow_copy_of_hash(local_var)
|
|
23
|
+
else
|
|
24
|
+
class_name = local_var.is_a?(Class) ? local_var.to_s : local_var.class.to_s
|
|
25
|
+
vars[var] = "FILTERED[#{class_name}]"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
vars
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
#TODO: work on more efficient way to serialize hash
|
|
32
|
+
def shallow_copy_of_hash(hash)
|
|
33
|
+
{}.tap do |new_hash|
|
|
34
|
+
hash.each do |k,v|
|
|
35
|
+
new_hash[k] = v.to_s
|
|
36
|
+
end
|
|
37
|
+
new_hash
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
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,28 @@
|
|
|
1
|
+
module RShade
|
|
2
|
+
module Formatter
|
|
3
|
+
class File < ::RShade::Base
|
|
4
|
+
attr_reader :formatter, :event_store
|
|
5
|
+
FILE_NAME = 'stacktrace.json'.freeze
|
|
6
|
+
|
|
7
|
+
def initialize(event_store, args={})
|
|
8
|
+
@event_store = event_store
|
|
9
|
+
@formatter = args.fetch(:format, Json)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def call
|
|
13
|
+
data = formatter.call(event_store)
|
|
14
|
+
if formatter == Json
|
|
15
|
+
write_to_file(JSON.pretty_generate(data))
|
|
16
|
+
else
|
|
17
|
+
write_to_file(data.to_s)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def write_to_file(data)
|
|
22
|
+
::File.open(::File.join(RShade.config.store_dir, FILE_NAME), "w+") do |f|
|
|
23
|
+
f.write data
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module RShade
|
|
2
|
+
module Formatter
|
|
3
|
+
class Html < ::RShade::Base
|
|
4
|
+
attr_reader :formatter, :event_store
|
|
5
|
+
FILE_NAME = 'stacktrace.html'.freeze
|
|
6
|
+
TEMPLATE = 'html/template.html.erb'
|
|
7
|
+
|
|
8
|
+
def initialize(event_store, args={})
|
|
9
|
+
@event_store = event_store
|
|
10
|
+
@formatter = args.fetch(:formatter, Json)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def call
|
|
14
|
+
data = formatter.call(event_store)
|
|
15
|
+
erb_template = ERB.new(template)
|
|
16
|
+
content = erb_template.result_with_hash({json: data.to_json})
|
|
17
|
+
write_to_file(content)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def write_to_file(data)
|
|
21
|
+
::File.open(::File.join(RShade.config.store_dir, FILE_NAME), "w+") do |f|
|
|
22
|
+
f.write data
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def template
|
|
27
|
+
@template ||=::File.read(::File.join(::RShade.config.root_dir, TEMPLATE))
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module RShade
|
|
2
|
+
module Formatter
|
|
3
|
+
class Json < ::RShade::Base
|
|
4
|
+
attr_reader :event_store
|
|
5
|
+
|
|
6
|
+
def initialize(event_store)
|
|
7
|
+
@event_store = event_store
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def call
|
|
11
|
+
flat
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def flat
|
|
15
|
+
arr = []
|
|
16
|
+
event_store.iterate do |node, depth|
|
|
17
|
+
arr << item(node)
|
|
18
|
+
end
|
|
19
|
+
arr.sort_by { |item| item[:depth]}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def hierarchical
|
|
23
|
+
hash = {}
|
|
24
|
+
event_store.iterate do |node, depth|
|
|
25
|
+
ref = hash_iterate(hash, depth)
|
|
26
|
+
ref[:data] = item(node)
|
|
27
|
+
end
|
|
28
|
+
sort_hash(hash)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def sort_hash(h)
|
|
32
|
+
{}.tap do |h2|
|
|
33
|
+
h.sort.each do |k,v|
|
|
34
|
+
h2[k] = v.is_a?(Hash) ? sort_hash(v) : v
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def hash_iterate(hash, depth)
|
|
40
|
+
(0..depth).each do |lvl|
|
|
41
|
+
unless hash[:inner]
|
|
42
|
+
hash[:inner] = {}
|
|
43
|
+
end
|
|
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
|
+
depth: value.depth,
|
|
55
|
+
vars: value.vars
|
|
56
|
+
}
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
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(
|
|
5
|
+
def rshade_reveal(options = {})
|
|
6
6
|
raise 'No block given' unless block_given?
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
trace.reveal 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
|
data/lib/rshade/trace.rb
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
module RShade
|
|
2
2
|
class Trace
|
|
3
|
-
attr_accessor :
|
|
3
|
+
attr_accessor :event_store, :formatter, :filter
|
|
4
4
|
EVENTS = %i[call return].freeze
|
|
5
5
|
|
|
6
|
-
def initialize
|
|
7
|
-
@
|
|
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
|
-
@
|
|
11
|
+
@level = 1
|
|
12
|
+
@stat = {}
|
|
13
|
+
@calls = 0
|
|
14
|
+
@returns = 0
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.reveal(options={}, &block)
|
|
18
|
+
new(options).reveal(&block)
|
|
10
19
|
end
|
|
11
20
|
|
|
12
21
|
def reveal
|
|
@@ -14,55 +23,31 @@ module RShade
|
|
|
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
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
show_full_trace
|
|
31
|
+
def show
|
|
32
|
+
formatter.call(event_store)
|
|
25
33
|
end
|
|
26
34
|
|
|
27
|
-
def
|
|
28
|
-
|
|
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
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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 && @
|
|
65
|
-
@
|
|
48
|
+
if tp.event == :return && @level > 0
|
|
49
|
+
@returns += 1
|
|
50
|
+
@level -=1
|
|
66
51
|
end
|
|
67
52
|
end
|
|
68
53
|
end
|
data/lib/rshade/version.rb
CHANGED
data/rshade.gemspec
CHANGED
|
@@ -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", "
|
|
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.
|
|
4
|
+
version: 0.1.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ivan Lopatin
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2020-06-25 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:
|
|
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:
|
|
54
|
+
version: 12.3.3
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: rspec
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -83,15 +83,27 @@ files:
|
|
|
83
83
|
- Rakefile
|
|
84
84
|
- bin/console
|
|
85
85
|
- bin/setup
|
|
86
|
+
- html/template.html.erb
|
|
86
87
|
- lib/rshade.rb
|
|
87
|
-
- lib/rshade/
|
|
88
|
-
- lib/rshade/
|
|
89
|
-
- lib/rshade/
|
|
88
|
+
- lib/rshade/base.rb
|
|
89
|
+
- lib/rshade/configuration.rb
|
|
90
|
+
- lib/rshade/event.rb
|
|
91
|
+
- lib/rshade/event_serializer.rb
|
|
92
|
+
- lib/rshade/event_store.rb
|
|
93
|
+
- lib/rshade/filter/app_filter.rb
|
|
94
|
+
- lib/rshade/formatter/file.rb
|
|
95
|
+
- lib/rshade/formatter/html.rb
|
|
96
|
+
- lib/rshade/formatter/json.rb
|
|
97
|
+
- lib/rshade/formatter/stdout.rb
|
|
98
|
+
- lib/rshade/formatter/string.rb
|
|
99
|
+
- lib/rshade/rails/rails.rb
|
|
100
|
+
- lib/rshade/rspec/rspec.rb
|
|
101
|
+
- lib/rshade/storage.rb
|
|
90
102
|
- lib/rshade/trace.rb
|
|
91
|
-
- lib/rshade/tree.rb
|
|
92
103
|
- lib/rshade/version.rb
|
|
93
104
|
- rshade.gemspec
|
|
94
105
|
- shade.jpg
|
|
106
|
+
- todo.md
|
|
95
107
|
homepage: https://github.com/gingray/rshade
|
|
96
108
|
licenses:
|
|
97
109
|
- MIT
|
|
@@ -115,8 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
115
127
|
- !ruby/object:Gem::Version
|
|
116
128
|
version: '0'
|
|
117
129
|
requirements: []
|
|
118
|
-
|
|
119
|
-
rubygems_version: 2.7.8
|
|
130
|
+
rubygems_version: 3.0.8
|
|
120
131
|
signing_key:
|
|
121
132
|
specification_version: 4
|
|
122
133
|
summary: https://github.com/gingray/rshade
|
data/lib/rshade/source.rb
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
module RShade
|
|
2
|
-
# nodoc
|
|
3
|
-
class Source
|
|
4
|
-
RUBY_VERSION_PATTERN = /ruby-[0-9.]*/
|
|
5
|
-
|
|
6
|
-
def initialize(hash)
|
|
7
|
-
@hash = hash
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def klass
|
|
11
|
-
@hash[:klass]
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def lib_code?
|
|
15
|
-
!app_code?
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def app_code?
|
|
19
|
-
@app_code ||= exclude_path.none? { |item| path.include? item }
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def path
|
|
23
|
-
@hash[:path]
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def lineno
|
|
27
|
-
@hash[:lineno]
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def method_name
|
|
31
|
-
@hash[:method_name]
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def vars
|
|
35
|
-
@hash[:vars]
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def exclude_path
|
|
39
|
-
@path_arr ||= begin
|
|
40
|
-
[ENV['GEM_PATH'].split(':'), parse_ruby_version].flatten.compact
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def parse_ruby_version
|
|
45
|
-
val = RUBY_VERSION_PATTERN.match(ENV['GEM_PATH'])
|
|
46
|
-
return nil unless val
|
|
47
|
-
|
|
48
|
-
val[0]
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def pretty
|
|
52
|
-
class_method = "#{klass}##{method_name}".colorize(:green)
|
|
53
|
-
full_path = "#{path}:#{lineno}".colorize(:blue)
|
|
54
|
-
"#{class_method}(#{vars.to_json}) -> #{full_path}"
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
data/lib/rshade/source_node.rb
DELETED
|
@@ -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
|
data/lib/rshade/tree.rb
DELETED
|
@@ -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
|