source_route 0.1.2 → 0.1.3
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/README.md +8 -5
- data/lib/source_route/formats/html.rb +2 -1
- data/lib/source_route/formats/html_template.slim +28 -16
- data/lib/source_route/generate_result.rb +11 -1
- data/lib/source_route/json_overrides/activerecord_associations_association.rb +20 -0
- data/lib/source_route/tp_result_chain.rb +9 -7
- data/lib/source_route/version.rb +1 -1
- data/lib/source_route/wrapper.rb +44 -6
- data/lib/source_route.rb +5 -0
- data/test/source_route_test.rb +24 -5
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1a153562bb55ebdbeed1c374089561c69be101a5
|
4
|
+
data.tar.gz: 326bc1d36580221a021630ddd59ce66ea2cedfc2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1265a2077f7420311560c804169c50c369639c5c0882453549bee819ceb429bfa4713d3e545fca2c079076bce45911b7fe3db03547811dfb28f1a4acee3255ee
|
7
|
+
data.tar.gz: 381f9a950f6b582edded7df76c30934f123c14fcbf51b4853b6062333d48c42a40d393543ec20b5c3c63682d4d0d65fe296f0ecb8e1ffe11d706c62fd5a9989f
|
data/README.md
CHANGED
@@ -44,8 +44,9 @@ you will get a different trace file.
|
|
44
44
|
SourceRoute.enable :wanted_method_name
|
45
45
|
.... # here is your code
|
46
46
|
....
|
47
|
-
|
48
|
-
|
47
|
+
....
|
48
|
+
# add it after your tracked code, it will output the trace into a html file
|
49
|
+
SourceRoute.output_html
|
49
50
|
|
50
51
|
Same as the previous example, you will get a html file showing the code trace.
|
51
52
|
|
@@ -91,12 +92,14 @@ Finally, I expect my working style can change from searching workaround from int
|
|
91
92
|
|
92
93
|
### TODO
|
93
94
|
|
94
|
-
|
95
|
+
Add debug option to provider more verbose messages of what has happened
|
96
|
+
|
97
|
+
Open File directly from browser(chrome) by plugin?
|
95
98
|
|
96
99
|
Apply https://github.com/a5hik/ng-sortable
|
97
100
|
|
98
|
-
|
101
|
+
Add vertical timeline.
|
99
102
|
(see http://tympanus.net/codrops/2013/05/02/vertical-timeline/
|
100
103
|
http://stackoverflow.com/questions/20896240/responsive-timeline-ui-with-bootstrap3)
|
101
104
|
|
102
|
-
|
105
|
+
Hide defined class filter.
|
@@ -14,8 +14,9 @@ module SourceRoute
|
|
14
14
|
|
15
15
|
if result_config.import_return_to_call and wrapper.condition.has_call_and_return_event
|
16
16
|
wrapper.import_return_value_to_call_chain
|
17
|
-
wrapper.
|
17
|
+
wrapper.treeize_call_chain
|
18
18
|
end
|
19
|
+
# TODO: any exception triggered in render method will be absorb totally, how to fix it?
|
19
20
|
html_output_str = slim_template.render(wrapper)
|
20
21
|
File.open(filename, 'w') do |f|
|
21
22
|
f << html_output_str
|
@@ -7,10 +7,14 @@ html
|
|
7
7
|
script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"
|
8
8
|
|
9
9
|
css:
|
10
|
-
.call-level-
|
11
|
-
.call-level-
|
12
|
-
.call-level-
|
13
|
-
.call-level-
|
10
|
+
.call-level-0 {}
|
11
|
+
.call-level-1 { margin-left: 50px }
|
12
|
+
.call-level-2 { margin-left: 100px }
|
13
|
+
.call-level-3 { margin-left: 150px }
|
14
|
+
.call-level-4 { margin-left: 200px }
|
15
|
+
.call-level-5 { margin-left: 250px }
|
16
|
+
.call-level-6 { margin-left: 300px }
|
17
|
+
.call-level-7 { margin-left: 300px }
|
14
18
|
body(ng-app="SourceRoute" ng-controller="MainCtrl")
|
15
19
|
|
16
20
|
nav.navbar.navbar-default.navbar-static-top
|
@@ -30,6 +34,14 @@ html
|
|
30
34
|
.clearfix
|
31
35
|
|
32
36
|
.container
|
37
|
+
.level-header(ng-if="parentLengthList" style="padding-bottom: 10px")
|
38
|
+
.btn-group>
|
39
|
+
button.btn.btn-default>(ng-click="traceFilter.parent_length = length" ng-repeat="length in parentLengthList")
|
40
|
+
span> Level
|
41
|
+
span(ng-bind="::length")
|
42
|
+
span
|
43
|
+
button.btn.btn-primary(ng-click="traceFilter.parent_length = undefined") Clear
|
44
|
+
|
33
45
|
.trace-flow
|
34
46
|
.row
|
35
47
|
.left-info.col-sm-4(ng-if="false")
|
@@ -67,6 +79,10 @@ html
|
|
67
79
|
span<>
|
68
80
|
| =>
|
69
81
|
span<>(ng-bind="value | json")
|
82
|
+
.self-obj.well.well-sm(ng-if="trace.hasOwnProperty('tp_self')" style="color: red; margin-bottom: 0")
|
83
|
+
span Self
|
84
|
+
div
|
85
|
+
span(ng-bind="tpSelfList[trace.tp_self] | json")
|
70
86
|
.path-value.well.well-sm(ng-if="trace.path")
|
71
87
|
span Path
|
72
88
|
div
|
@@ -82,7 +98,9 @@ html
|
|
82
98
|
sourceRoute = angular.module('SourceRoute', ['ui.bootstrap'])
|
83
99
|
sourceRoute.controller('MainCtrl', function($scope, $filter) {
|
84
100
|
$scope.traces = angular.element("#trace-data").data('trace')
|
101
|
+
$scope.tpSelfList = angular.element("#trace-data").data('tp-self-caches')
|
85
102
|
$scope.tpEvents = angular.element("#trace-data").data('tp-events')
|
103
|
+
$scope.parentLengthList = angular.element("#trace-data").data('tp-parent-length-list')
|
86
104
|
|
87
105
|
$scope.traceFilter = {event: $scope.tpEvents[0]}
|
88
106
|
if ($scope.tpEvents.length == 1 && angular.isUndefined($scope.traces[0].event)) {
|
@@ -94,8 +112,8 @@ html
|
|
94
112
|
$scope.definedClasses = _.uniq(_.map($scope.traces, 'defined_class'))
|
95
113
|
|
96
114
|
$scope.callLevelClass = function(trace) {
|
97
|
-
if (trace.parent_length >
|
98
|
-
return 'call-level-
|
115
|
+
if (trace.parent_length > 7) {
|
116
|
+
return 'call-level-7'
|
99
117
|
} else {
|
100
118
|
return 'call-level-' + trace.parent_length
|
101
119
|
}
|
@@ -110,15 +128,9 @@ html
|
|
110
128
|
|
111
129
|
})
|
112
130
|
|
113
|
-
ruby:
|
114
|
-
local_trace_data = @tp_result_chain.map do |tp_result|
|
115
|
-
if tp_result.key?(:defined_class)
|
116
|
-
tp_result[:defined_class] = tp_result[:defined_class].to_s
|
117
|
-
tp_result[:return_value] = tp_result[:return_value].inspect if tp_result.key?(:return_value)
|
118
|
-
end
|
119
|
-
tp_result
|
120
|
-
end
|
121
|
-
|
122
131
|
.data-collect
|
123
132
|
/ dont use local_trace_data.to_json, because ActiveSupport override it and can introduce unexpected crash for some data
|
124
|
-
#trace-data(data-trace="#{
|
133
|
+
#trace-data(data-trace="#{jsonify_tp_result_chain}"
|
134
|
+
data-tp-events="#{jsonify_events}"
|
135
|
+
data-tp-self-caches="#{jsonify_tp_self_caches}"
|
136
|
+
data-tp-parent-length-list="#{JSON.dump(parent_length_list)}")
|
@@ -44,7 +44,7 @@ module SourceRoute
|
|
44
44
|
def build(trace_point_instance)
|
45
45
|
@tp = trace_point_instance
|
46
46
|
collect_tp_data
|
47
|
-
|
47
|
+
collect_tp_self if @config[:include_tp_self]
|
48
48
|
collect_local_var_data if @config[:include_local_var]
|
49
49
|
collect_instance_var_data if @config[:include_instance_var]
|
50
50
|
@collect_data
|
@@ -77,6 +77,15 @@ module SourceRoute
|
|
77
77
|
|
78
78
|
private
|
79
79
|
|
80
|
+
# include? will evaluate @tp.self, if @tp.self is AR::Relation, it could cause problems
|
81
|
+
# So that's why I use object_id as replace
|
82
|
+
def collect_tp_self
|
83
|
+
unless @wrapper.tp_self_caches.find { |tp_cache| tp_cache.equal? @tp.self }
|
84
|
+
@wrapper.tp_self_caches.push @tp.self
|
85
|
+
end
|
86
|
+
@collect_data[:tp_self] = @wrapper.tp_self_caches.map(&:__id__).index(@tp.self.__id__)
|
87
|
+
end
|
88
|
+
|
80
89
|
def collect_tp_data
|
81
90
|
@collect_data = output_attributes(@tp.event).inject({}) do |memo, key|
|
82
91
|
memo[key.to_sym] = @tp.send(key) if @tp.respond_to?(key)
|
@@ -87,6 +96,7 @@ module SourceRoute
|
|
87
96
|
def collect_local_var_data
|
88
97
|
local_var_hash = {}
|
89
98
|
|
99
|
+
# Warn: @tp.binding.eval('local_variables') =! @tp.binding.send('local_variables')
|
90
100
|
@tp.binding.eval('local_variables').each do |v|
|
91
101
|
local_var_hash[v] = @tp.binding.local_variable_get v
|
92
102
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
if defined? ActiveRecord
|
2
|
+
class ActiveRecord::Associations::Association
|
3
|
+
|
4
|
+
# dump association can trigger ActiveSupport::JSON::Encoding::CircularReferenceError when use rails ~> 4.0.1
|
5
|
+
# I try other json gems to fix it, but all failed. That's why I override it here.
|
6
|
+
def to_json(options = nil)
|
7
|
+
JSON.dump(to_s)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class ActiveRecord::Base
|
12
|
+
|
13
|
+
# dump association can trigger ActiveSupport::JSON::Encoding::CircularReferenceError when use rails ~> 4.0.1
|
14
|
+
# I try other json gems to fix it, but all failed. That's why I override it here.
|
15
|
+
def to_json(options = nil)
|
16
|
+
JSON.dump(to_s)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -21,17 +21,15 @@ module SourceRoute
|
|
21
21
|
def import_return_value_to_call_chain
|
22
22
|
call_chain.each do |ctp|
|
23
23
|
matched_return_tp = return_chain.detect do |rtp|
|
24
|
-
rtp[:
|
25
|
-
rtp[:tp_self] == ctp[:tp_self]
|
26
|
-
|
24
|
+
rtp[:tp_self] == ctp[:tp_self] and rtp[:method_id] == ctp[:method_id] and rtp[:defined_class] == ctp[:defined_class]
|
27
25
|
end
|
28
26
|
ctp[:return_value] = matched_return_tp[:return_value]
|
29
|
-
ctp[:local_var] = matched_return_tp[:local_var]
|
30
|
-
ctp[:instance_var] = matched_return_tp[:instance_var]
|
27
|
+
ctp[:local_var] = matched_return_tp[:local_var] if matched_return_tp.key? :local_var
|
28
|
+
ctp[:instance_var] = matched_return_tp[:instance_var] if matched_return_tp.key? :instance_var
|
31
29
|
end
|
32
30
|
end
|
33
31
|
|
34
|
-
def
|
32
|
+
def treeize_call_chain
|
35
33
|
init_order_id_and_parent_ids
|
36
34
|
call_chain.each do |tpr|
|
37
35
|
return_tpr = return_chain.find do |rtpr|
|
@@ -49,10 +47,14 @@ module SourceRoute
|
|
49
47
|
cal_parent_length
|
50
48
|
end
|
51
49
|
|
50
|
+
def parent_length_list
|
51
|
+
call_chain.map { |tp| tp[:parent_length] }.uniq.sort
|
52
|
+
end
|
53
|
+
|
52
54
|
private
|
53
55
|
def init_order_id_and_parent_ids
|
54
56
|
each_with_index do |tpr, index|
|
55
|
-
tpr[:order_id], tpr[:parent_ids] = index, [
|
57
|
+
tpr[:order_id], tpr[:parent_ids] = index, []
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
data/lib/source_route/version.rb
CHANGED
data/lib/source_route/wrapper.rb
CHANGED
@@ -6,10 +6,10 @@ module SourceRoute
|
|
6
6
|
TRACE_POINT_METHODS = [:defined_class, :method_id, :path, :lineno]
|
7
7
|
|
8
8
|
attr_accessor :condition, :tp
|
9
|
-
attr_reader :tp_result_chain
|
9
|
+
attr_reader :tp_result_chain, :tp_self_caches
|
10
10
|
|
11
11
|
extend Forwardable
|
12
|
-
def_delegators :@tp_result_chain, :import_return_value_to_call_chain, :
|
12
|
+
def_delegators :@tp_result_chain, :import_return_value_to_call_chain, :treeize_call_chain, :call_chain, :return_chain, :parent_length_list
|
13
13
|
|
14
14
|
Condition = Struct.new(:events, :negatives, :positive, :result_config) do
|
15
15
|
def initialize(e=[:call], n={}, p={}, r=GenerateResult::Config.new)
|
@@ -46,9 +46,12 @@ module SourceRoute
|
|
46
46
|
|
47
47
|
self.events = [:call, :return]
|
48
48
|
result_config.import_return_to_call = true
|
49
|
-
result_config.include_instance_var = true
|
50
|
-
result_config.include_local_var = true
|
51
49
|
result_config.include_tp_self = true
|
50
|
+
|
51
|
+
result_config.show_additional_attrs = [:path, :lineno]
|
52
|
+
# JSON serialize trigger many problems when handle complicated object
|
53
|
+
# result_config.include_instance_var = true
|
54
|
+
# result_config.include_local_var = true
|
52
55
|
end
|
53
56
|
end
|
54
57
|
|
@@ -57,9 +60,10 @@ module SourceRoute
|
|
57
60
|
end
|
58
61
|
|
59
62
|
def reset
|
60
|
-
@tp.disable if @tp
|
63
|
+
@tp.disable if defined? @tp
|
61
64
|
@condition = Condition.new
|
62
65
|
@tp_result_chain = TpResultChain.new
|
66
|
+
@tp_self_caches = []
|
63
67
|
self
|
64
68
|
end
|
65
69
|
|
@@ -81,9 +85,43 @@ module SourceRoute
|
|
81
85
|
end
|
82
86
|
track.enable
|
83
87
|
self.tp = track
|
84
|
-
track
|
85
88
|
end
|
86
89
|
|
90
|
+
# TODO: move this into chain self
|
91
|
+
def stringify_tp_self_caches
|
92
|
+
tp_self_caches.clone.map(&:to_s)
|
93
|
+
end
|
94
|
+
|
95
|
+
def stringify_tp_result_chain
|
96
|
+
deep_cloned = tp_result_chain.map do |tp_result|
|
97
|
+
tp_result.clone
|
98
|
+
end
|
99
|
+
deep_cloned.map do |tr|
|
100
|
+
# to_s is safer than inspect
|
101
|
+
# ex: inspect on ActiveRecord_Relation may crash
|
102
|
+
tr[:defined_class] = tr[:defined_class].to_s if tr.key?(:defined_class)
|
103
|
+
if tr.key?(:return_value)
|
104
|
+
if tr[:return_value].nil? or tr[:return_value] == ''
|
105
|
+
tr[:return_value] = tr[:return_value].inspect
|
106
|
+
else
|
107
|
+
tr[:return_value] = tr[:return_value].to_s
|
108
|
+
end
|
109
|
+
end
|
110
|
+
tr
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def jsonify_events
|
115
|
+
JSON.dump(@condition.events.map(&:to_s))
|
116
|
+
end
|
117
|
+
|
118
|
+
def jsonify_tp_result_chain
|
119
|
+
JSON.dump(stringify_tp_result_chain)
|
120
|
+
end
|
121
|
+
|
122
|
+
def jsonify_tp_self_caches
|
123
|
+
JSON.dump(stringify_tp_self_caches)
|
124
|
+
end
|
87
125
|
end # END Wrapper
|
88
126
|
|
89
127
|
end
|
data/lib/source_route.rb
CHANGED
@@ -10,6 +10,7 @@ require "source_route/wrapper"
|
|
10
10
|
require "source_route/generate_result"
|
11
11
|
require "source_route/tp_result_chain"
|
12
12
|
require "source_route/tp_filter"
|
13
|
+
require 'source_route/json_overrides/activerecord_associations_association'
|
13
14
|
|
14
15
|
module SourceRoute
|
15
16
|
extend self
|
@@ -58,6 +59,10 @@ module SourceRoute
|
|
58
59
|
SourceRoute::Formats::Html.slim_render(wrapper)
|
59
60
|
end
|
60
61
|
|
62
|
+
def output_html
|
63
|
+
build_html_output
|
64
|
+
end
|
65
|
+
|
61
66
|
# Not implement yet
|
62
67
|
class Logger < Logger
|
63
68
|
end
|
data/test/source_route_test.rb
CHANGED
@@ -110,7 +110,25 @@ class SourceRouteTest < Minitest::Test
|
|
110
110
|
end
|
111
111
|
assert @wrapper.condition.result_config.include_tp_self
|
112
112
|
first_result = @wrapper.tp_result_chain.first
|
113
|
-
|
113
|
+
assert_equal first_result[:tp_self], 0
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_trace_include_tp_self
|
117
|
+
SourceRoute.trace method_id: 'nonsense', full_feature: true do
|
118
|
+
SampleApp.new.nonsense
|
119
|
+
end
|
120
|
+
assert_equal 1, @wrapper.tp_self_caches.size
|
121
|
+
assert @wrapper.stringify_tp_self_caches.first.is_a? String
|
122
|
+
assert @wrapper.tp_self_caches.first.is_a? SampleApp
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_stringify_tp_result_chain
|
126
|
+
SourceRoute.trace method_id: 'nonsense', full_feature: true do
|
127
|
+
SampleApp.new.nonsense
|
128
|
+
end
|
129
|
+
origin_tp_result_chain = @wrapper.tp_result_chain
|
130
|
+
assert @wrapper.stringify_tp_result_chain.first[:defined_class].is_a? String
|
131
|
+
assert_equal origin_tp_result_chain, @wrapper.tp_result_chain
|
114
132
|
end
|
115
133
|
|
116
134
|
def test_trace_without_first_hash_option
|
@@ -188,15 +206,16 @@ class SourceRouteTest < Minitest::Test
|
|
188
206
|
event :call, :return
|
189
207
|
end
|
190
208
|
SampleApp.new.nonsense_with_instance_var
|
191
|
-
@wrapper.
|
192
|
-
@wrapper.
|
209
|
+
@wrapper.treeize_call_chain
|
210
|
+
@wrapper.treeize_call_chain
|
193
211
|
call_results = @wrapper.call_chain
|
194
212
|
|
195
213
|
nonsense_call_tp = call_results.find { |tp| tp[:method_id] == :nonsense }
|
196
214
|
nonsense_with_instance_var_call_tp = call_results.find { |tp| tp[:method_id] == :nonsense_with_instance_var }
|
197
215
|
|
198
|
-
assert_equal [
|
199
|
-
assert_equal
|
216
|
+
assert_equal [nonsense_with_instance_var_call_tp[:order_id]], nonsense_call_tp[:parent_ids]
|
217
|
+
assert_equal 1, nonsense_call_tp[:parent_length]
|
218
|
+
assert_equal [0, 1], @wrapper.parent_length_list
|
200
219
|
end
|
201
220
|
|
202
221
|
# Nothing has tested really when run rake cause ENV['ignore_html_generation'] was set to true
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: source_route
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- raykin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: awesome_print
|
@@ -128,6 +128,7 @@ files:
|
|
128
128
|
- lib/source_route/formats/html.rb
|
129
129
|
- lib/source_route/formats/html_template.slim
|
130
130
|
- lib/source_route/generate_result.rb
|
131
|
+
- lib/source_route/json_overrides/activerecord_associations_association.rb
|
131
132
|
- lib/source_route/tp_filter.rb
|
132
133
|
- lib/source_route/tp_result_chain.rb
|
133
134
|
- lib/source_route/version.rb
|