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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e359db40f93fb8aa3973ed198e521e29c21aa2ab
4
- data.tar.gz: b0f07e1dce0010f430d54b81b993c0bd7dcb73e4
3
+ metadata.gz: 1a153562bb55ebdbeed1c374089561c69be101a5
4
+ data.tar.gz: 326bc1d36580221a021630ddd59ce66ea2cedfc2
5
5
  SHA512:
6
- metadata.gz: b418b380f34fe5ed9aa794eab4950b6c9936f9f019408047de068412c1986f49d17c0d84cb05e80d302d30af3f27b3d404797d8d2d7077feb7f143bc728437ec
7
- data.tar.gz: 02fd9a36fbb122ebadfd660baf1fe19328f272ba0260a5620becdd310bb69b34d68af85655f1355353b9ac375b38f4819f9feb61690c17d4f4358924e8f16ff1
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
- # may be code this in another file
48
- SourceRoute.build_html_output
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
- Open Method directly from browser
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
- Hide defined class filter. Add vertical timeline.
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
- Add debug option to provider more verbose messages of what has happened
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.order_call_chain
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-1 {}
11
- .call-level-2 { margin-left: 50px }
12
- .call-level-3 { margin-left: 100px }
13
- .call-level-4 { margin-left: 150px }
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 > 4) {
98
- return 'call-level-4'
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="#{JSON.dump(local_trace_data)}" data-tp-events="#{JSON.dump(@condition.events)}")
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
- @collect_data[:tp_self] = @tp.self if @config[:include_tp_self]
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[:defined_class] == ctp[:defined_class] and rtp[:method_id] == ctp[:method_id] and
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 order_call_chain
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, [-1]
57
+ tpr[:order_id], tpr[:parent_ids] = index, []
56
58
  end
57
59
  end
58
60
 
@@ -1,3 +1,3 @@
1
1
  module SourceRoute
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
@@ -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, :order_call_chain, :call_chain, :return_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
@@ -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
- assert first_result[:tp_self]
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.order_call_chain
192
- @wrapper.order_call_chain
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 [-1, nonsense_with_instance_var_call_tp[:order_id]], nonsense_call_tp[:parent_ids]
199
- assert_equal 2, nonsense_call_tp[:parent_length]
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.2
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-14 00:00:00.000000000 Z
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