source_route 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|