appmap 0.73.0 → 0.76.0

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: df9ed913bb9ce4b945312ab2a50d8305b7c85c8f84a2004b9cf785362fcf2ad2
4
- data.tar.gz: 2f2a844c20263b62a1291b05396d883c205cdebf2ae32062206e7bf42c23e757
3
+ metadata.gz: 15371b6980bcc95640c4d579c323da11db85509c0f50110c318da0d9cc04f189
4
+ data.tar.gz: 03a4e889edcfaf15629a7e9662f230df18b3b1123c86ce463edf4ba03c9e7280
5
5
  SHA512:
6
- metadata.gz: 330bcbec5db0a2b92662898432b3cc4eb4e8ca98729f6cfc0577d6490a0f19a1908e19b6c58c512c9b5db7e98a9f90804c5f0fe4362f52b31a69849760cde6db
7
- data.tar.gz: 29544bb8ae0db136aad8a518511eb6723fe113e54bc4d585d9e06a857f9227f3e0fbf6daa2bcf1067df5092eef88b13034862d09b187e496cb6758eb8ec094eb
6
+ metadata.gz: a1bc1b230b3e946400acbc3d1bc8ee87508973ce594ca488c17f2d39d1280346959e2c5acb5c9d3f6cd62627b61764f5cd0d96ef60639c645337df2ac850409b
7
+ data.tar.gz: e0bb0223a99795cedc38470d49dae428a720f0638674dc4e04b26d15aa085286d51c42aacc1ee490ff713122711728af9df1064adcb66a6dff7ccb89292b72a5
data/CHANGELOG.md CHANGED
@@ -1,3 +1,34 @@
1
+ # [0.76.0](https://github.com/applandinc/appmap-ruby/compare/v0.75.0...v0.76.0) (2022-03-19)
2
+
3
+
4
+ ### Features
5
+
6
+ * Autoload hook handlers ([4cc0e70](https://github.com/applandinc/appmap-ruby/commit/4cc0e7003a8c37d3b6c8c8bbc68cffac0335b878))
7
+
8
+ # [0.75.0](https://github.com/applandinc/appmap-ruby/compare/v0.74.0...v0.75.0) (2022-03-17)
9
+
10
+
11
+ ### Features
12
+
13
+ * Apply label deserialize.safe to ActiveSupport.run_load_hooks ([1f67f9b](https://github.com/applandinc/appmap-ruby/commit/1f67f9b260503772cba6824ef746f903def14323))
14
+ * Print stacks if requested by env var ([72ef911](https://github.com/applandinc/appmap-ruby/commit/72ef9116d3248467632762ce63303a54bed998e9))
15
+
16
+ # [0.74.0](https://github.com/applandinc/appmap-ruby/compare/v0.73.0...v0.74.0) (2022-03-14)
17
+
18
+
19
+ ### Bug Fixes
20
+
21
+ * Apply special case hook handling to Kernel and instance_eval ([25823ff](https://github.com/applandinc/appmap-ruby/commit/25823ff0fb86beff3edc64da251a125ee198ef40))
22
+ * Only apply a method hook to a class that defines the method ([ede2236](https://github.com/applandinc/appmap-ruby/commit/ede22364bfcbf324e8db3aa6d64d5b032f36ace2))
23
+ * Optimize/improve string-ification of values ([c9b6cdb](https://github.com/applandinc/appmap-ruby/commit/c9b6cdb72dfc55cc3a166eda470eba19093e9090))
24
+
25
+
26
+ ### Features
27
+
28
+ * Improve hook performance by using bind_call ([e09fce9](https://github.com/applandinc/appmap-ruby/commit/e09fce9f5b3c0b18bc3b81083c1523df6a6932db))
29
+ * Label system.exec, string.pack, string.html_safe ([963c6dd](https://github.com/applandinc/appmap-ruby/commit/963c6ddfa0f607ad219ae8829cfb383b0d5988d0))
30
+ * Log initiation of each builtin hook ([902a736](https://github.com/applandinc/appmap-ruby/commit/902a7360d17c6b49de97f34643c733e8c47c294d))
31
+
1
32
  # [0.73.0](https://github.com/applandinc/appmap-ruby/compare/v0.72.5...v0.73.0) (2022-03-07)
2
33
 
3
34
 
@@ -0,0 +1,13 @@
1
+ - methods:
2
+ - Open3#capture2
3
+ - Open3#capture2e
4
+ - Open3#capture3
5
+ - Open3#pipeline
6
+ - Open3#pipeline_r
7
+ - Open3#pipeline_rw
8
+ - Open3#pipeline_start
9
+ - Open3#pipeline_w
10
+ - Open3#popen2
11
+ - Open3#popen2e
12
+ - Open3#popen3
13
+ label: system.exec
@@ -0,0 +1,39 @@
1
+ - methods:
2
+ - Marshal#load
3
+ - Marshal#restore
4
+ require_name: ruby
5
+ label: deserialize.unsafe
6
+ - method: Marshal#dump
7
+ require_name: ruby
8
+ label: serialize
9
+ - method: String#pack
10
+ require_name: ruby
11
+ label: string.pack
12
+ - methods:
13
+ - String#unpack
14
+ - String#unpack1
15
+ require_name: ruby
16
+ label: string.unpack
17
+ #- methods:
18
+ # TODO: eval does not happen in the right context, and therefore any new constants
19
+ # which are defined are placed on the wrong module/class.
20
+ # - Kernel#eval
21
+ # - Binding#eval
22
+ # - BasicObject#instance_eval
23
+ # These methods cannot be hooked as far as I can tell.
24
+ # Why? When calling one of these functions, the context at the point of
25
+ # definition is used. It's not possible to bind class_eval to a new context.
26
+ # - Module#class_eval
27
+ # - Module#module_eval
28
+ # require_name: ruby
29
+ # label: lang.eval
30
+ - methods:
31
+ - IO#popen
32
+ - Kernel#exec
33
+ - Kernel#spawn
34
+ - Kernel#syscall
35
+ - Kernel#system
36
+ - Process#exec
37
+ - Process#spawn
38
+ require_name: ruby
39
+ label: system.exec
data/lib/appmap/config.rb CHANGED
@@ -4,8 +4,7 @@ require 'pathname'
4
4
  require 'set'
5
5
  require 'yaml'
6
6
  require 'appmap/util'
7
- require 'appmap/handler/net_http'
8
- require 'appmap/handler/rails/template'
7
+ require 'appmap/handler'
9
8
  require 'appmap/service/guesser'
10
9
  require 'appmap/swagger/configuration'
11
10
  require 'appmap/depends/configuration'
@@ -206,8 +205,8 @@ module AppMap
206
205
  }.compact
207
206
 
208
207
  handler_class = hook_decl['handler_class']
209
- options[:handler_class] = Util.class_from_string(handler_class) if handler_class
210
-
208
+ options[:handler_class] = Handler.find(handler_class) if handler_class
209
+
211
210
  package_hooks(methods, **options)
212
211
  end
213
212
 
@@ -51,7 +51,7 @@ module AppMap
51
51
  appmap['metadata'] = update_metadata(scenario, appmap['metadata'])
52
52
  scenario_filename = AppMap::Util.scenario_filename(appmap['metadata']['name'])
53
53
 
54
- AppMap::Util.write_appmap(File.join(APPMAP_OUTPUT_DIR, scenario_filename), JSON.generate(appmap))
54
+ AppMap::Util.write_appmap(File.join(APPMAP_OUTPUT_DIR, scenario_filename), appmap)
55
55
  end
56
56
 
57
57
  def enabled?
data/lib/appmap/event.rb CHANGED
@@ -20,7 +20,9 @@ module AppMap
20
20
  MethodEventStruct = Struct.new(:id, :event, :thread_id)
21
21
 
22
22
  class MethodEvent < MethodEventStruct
23
- LIMIT = 100
23
+ MAX_ARRAY_ENUMERATION = 10
24
+ MAX_HASH_ENUMERATION = 10
25
+ MAX_STRING_LENGTH = 100
24
26
 
25
27
  class << self
26
28
  def build_from_invocation(event_type, event:)
@@ -48,14 +50,14 @@ module AppMap
48
50
  end
49
51
 
50
52
  start = Time.now
51
- value_string = custom_display_string(value) || default_display_string(value)
53
+ value_string, final = custom_display_string(value) || default_display_string(value)
52
54
 
53
55
  if @times
54
56
  elapsed = Time.now - start
55
57
  @times[best_class_name(value)] += elapsed
56
58
  end
57
59
 
58
- encode_display_string(value_string)
60
+ final ? value_string : encode_display_string(value_string)
59
61
  end
60
62
 
61
63
  def object_properties(hash_like)
@@ -80,21 +82,33 @@ module AppMap
80
82
  end
81
83
 
82
84
  def encode_display_string(value)
83
- (value||'')[0...LIMIT].encode('utf-8', invalid: :replace, undef: :replace, replace: '_')
85
+ (value||'')[0...MAX_STRING_LENGTH].encode('utf-8', invalid: :replace, undef: :replace, replace: '_')
84
86
  end
85
87
 
86
88
  def custom_display_string(value)
87
89
  case value
88
90
  when NilClass, TrueClass, FalseClass, Numeric, Time, Date
89
- value.to_s
91
+ [ value.to_s, true ]
92
+ when Symbol
93
+ [ ":#{value}", true ]
90
94
  when String
91
- value[0...LIMIT].encode('utf-8', invalid: :replace, undef: :replace, replace: '_')
95
+ result = value[0...MAX_STRING_LENGTH].encode('utf-8', invalid: :replace, undef: :replace, replace: '_')
96
+ result << " (...#{value.length - MAX_STRING_LENGTH} more characters)" if value.length > MAX_STRING_LENGTH
97
+ [ result, true ]
98
+ when Array
99
+ result = value[0...MAX_ARRAY_ENUMERATION].map{|v| display_string(v)}.join(', ')
100
+ result << " (...#{value.length - MAX_ARRAY_ENUMERATION} more items)" if value.length > MAX_ARRAY_ENUMERATION
101
+ [ [ '[', result, ']' ].join, true ]
102
+ when Hash
103
+ result = value.keys[0...MAX_HASH_ENUMERATION].map{|key| "#{display_string(key)}=>#{display_string(value[key])}"}.join(', ')
104
+ result << " (...#{value.size - MAX_HASH_ENUMERATION} more entries)" if value.size > MAX_HASH_ENUMERATION
105
+ [ [ '{', result, '}' ].join, true ]
92
106
  when File
93
- "#{value.class}[path=#{value.path}]"
107
+ [ "#{value.class}[path=#{value.path}]", true ]
94
108
  when Net::HTTP
95
- "#{value.class}[#{value.address}:#{value.port}]"
109
+ [ "#{value.class}[#{value.address}:#{value.port}]", true ]
96
110
  when Net::HTTPGenericRequest
97
- "#{value.class}[#{value.method} #{value.path}]"
111
+ [ "#{value.class}[#{value.method} #{value.path}]", true ]
98
112
  end
99
113
  rescue StandardError
100
114
  nil
@@ -11,3 +11,7 @@
11
11
  label: mvc.template.resolver
12
12
  handler_class: AppMap::Handler::Rails::Template::ResolverHandler
13
13
  require_name: action_view
14
+ - methods:
15
+ - ActionView::Helpers::SanitizeHelper#sanitize
16
+ label: string.html_safe
17
+ require_name: action_view
@@ -10,3 +10,7 @@
10
10
  label: crypto.secure_compare
11
11
  require_name: active_support/security_utils
12
12
  force: true
13
+ - method: ActiveSupport.run_load_hooks
14
+ label: deserialize.safe
15
+ require_name: active_support/lazy_load_hooks
16
+ force: true
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/inflector/methods'
4
+
5
+ module AppMap
6
+ # Specific hook handler classes and general related utilities.
7
+ module Handler
8
+ # Try to find handler module with a given name.
9
+ #
10
+ # If the module is not loaded, tries to require the appropriate file
11
+ # using the usual conventions, eg. `Acme::Handler::AppMap` will try
12
+ # to require `acme/handler/app_map`, then `acme/handler` and
13
+ # finally `acme`. Raises NameError if the module could not be loaded
14
+ # this way.
15
+ def self.find(name)
16
+ begin
17
+ return Object.const_get name
18
+ rescue NameError
19
+ try_load ActiveSupport::Inflector.underscore name
20
+ end
21
+ Object.const_get name
22
+ end
23
+
24
+ def self.try_load(fname)
25
+ fname = fname.sub %r{^app_map/}, 'appmap/'
26
+ fname = fname.split '/'
27
+ until fname.empty?
28
+ begin
29
+ require fname.join '/'
30
+ return
31
+ rescue LoadError
32
+ # pass
33
+ end
34
+ fname.pop
35
+ end
36
+ end
37
+ end
38
+ end
@@ -69,28 +69,24 @@ module AppMap
69
69
  after_hook = self.method(:after_hook)
70
70
  with_disabled_hook = self.method(:with_disabled_hook)
71
71
 
72
- hook_method_def = Proc.new do |*args, &block|
73
- is_array_containing_empty_hash = ->(obj) {
74
- obj.is_a?(Array) && obj.length == 1 && obj[0].is_a?(Hash) && obj[0].size == 0
75
- }
76
-
77
- call_instance_method = -> {
78
- # https://github.com/applandinc/appmap-ruby/issues/153
79
- if NEW_RUBY && is_array_containing_empty_hash.(args) && hook_method.arity == 1
80
- if NEW_RUBY
81
- hook_method.bind_call(self, {}, &block)
82
- else
83
- hook_method.bind(self).call({}, &block)
84
- end
72
+ is_array_containing_empty_hash = ->(obj) {
73
+ obj.is_a?(Array) && obj.length == 1 && obj[0].is_a?(Hash) && obj[0].size == 0
74
+ }
75
+
76
+ call_instance_method = lambda do |receiver, args, &block|
77
+ # https://github.com/applandinc/appmap-ruby/issues/153
78
+ if NEW_RUBY && is_array_containing_empty_hash.(args) && hook_method.arity == 1
79
+ hook_method.bind_call(receiver, {}, &block)
80
+ else
81
+ if NEW_RUBY
82
+ hook_method.bind_call(receiver, *args, &block)
85
83
  else
86
- if NEW_RUBY
87
- hook_method.bind_call(self, *args, &block)
88
- else
89
- hook_method.bind(self).call(*args, &block)
90
- end
84
+ hook_method.bind(receiver).call(*args, &block)
91
85
  end
92
- }
86
+ end
87
+ end
93
88
 
89
+ hook_method_def = Proc.new do |*args, &block|
94
90
  # We may not have gotten the class for the method during
95
91
  # initialization (e.g. for a singleton method on an embedded
96
92
  # struct), so make sure we have it now.
@@ -102,7 +98,9 @@ module AppMap
102
98
 
103
99
  enabled = true if AppMap.tracing.enabled? && !reentrant && !disabled_by_shallow_flag.call
104
100
 
105
- return call_instance_method.call unless enabled
101
+ enabled = false if %i[instance_eval instance_exec].member?(hook_method.name) && args.empty?
102
+
103
+ return call_instance_method.call(self, args, &block) unless enabled
106
104
 
107
105
  call_event, start_time = with_disabled_hook.call do
108
106
  before_hook.call(self, defined_class, args)
@@ -110,7 +108,7 @@ module AppMap
110
108
  return_value = nil
111
109
  exception = nil
112
110
  begin
113
- return_value = call_instance_method.call
111
+ return_value = call_instance_method.call(self, args, &block)
114
112
  rescue
115
113
  exception = $ERROR_INFO
116
114
  raise
@@ -125,8 +123,18 @@ module AppMap
125
123
  hook_method_parameters = hook_method.parameters.dup.freeze
126
124
  SIGNATURES[[ hook_class, hook_method.name ]] = hook_method_parameters
127
125
 
128
- hook_class.ancestors.first.tap do |cls|
129
- cls.define_method_with_arity(hook_method.name, hook_method.arity, hook_method_def)
126
+ # irb(main):001:0> Kernel.public_instance_method(:system)
127
+ # (irb):1:in `public_instance_method': method `system' for module `Kernel' is private (NameError)
128
+ if hook_class == Kernel
129
+ hook_class.define_method_with_arity(hook_method.name, hook_method.arity, hook_method_def)
130
+ else
131
+ hook_class.ancestors.find { |cls| cls.method_defined?(hook_method.name, false) }.tap do |cls|
132
+ if cls
133
+ cls.define_method_with_arity(hook_method.name, hook_method.arity, hook_method_def)
134
+ else
135
+ warn "#{hook_method.name} not found on #{hook_class}"
136
+ end
137
+ end
130
138
  end
131
139
  end
132
140
 
data/lib/appmap/hook.rb CHANGED
@@ -105,8 +105,14 @@ module AppMap
105
105
 
106
106
  Array(hook.method_names).each do |method_name|
107
107
  method_name = method_name.to_sym
108
- base_cls = Util.class_from_string(class_name, must: false)
109
- next unless base_cls
108
+
109
+ warn "AppMap: Initiating hook for builtin #{class_name} #{method_name}" if LOG
110
+
111
+ begin
112
+ base_cls = Object.const_get class_name
113
+ rescue NameError
114
+ next
115
+ end
110
116
 
111
117
  hook_method = lambda do |entry|
112
118
  cls, method = entry
@@ -116,6 +122,11 @@ module AppMap
116
122
  end
117
123
 
118
124
  methods = []
125
+ # irb(main):001:0> Kernel.public_instance_method(:system)
126
+ # (irb):1:in `public_instance_method': method `system' for module `Kernel' is private (NameError)
127
+ if base_cls == Kernel
128
+ methods << [ base_cls, base_cls.instance_method(method_name) ] rescue nil
129
+ end
119
130
  methods << [ base_cls, base_cls.public_instance_method(method_name) ] rescue nil
120
131
  methods << [ base_cls, base_cls.protected_instance_method(method_name) ] rescue nil
121
132
  if base_cls.respond_to?(:singleton_class)
@@ -120,7 +120,7 @@ module AppMap
120
120
  }.compact
121
121
  fname = AppMap::Util.scenario_filename(name)
122
122
 
123
- AppMap::Util.write_appmap(File.join(APPMAP_OUTPUT_DIR, fname), JSON.generate(appmap))
123
+ AppMap::Util.write_appmap(File.join(APPMAP_OUTPUT_DIR, fname), appmap)
124
124
  end
125
125
 
126
126
  def enabled?
data/lib/appmap/record.rb CHANGED
@@ -23,5 +23,5 @@ at_exit do
23
23
  'classMap' => AppMap.class_map(tracer.event_methods),
24
24
  'events' => events
25
25
  }
26
- AppMap::Util.write_appmap('appmap.json', JSON.generate(appmap))
26
+ AppMap::Util.write_appmap('appmap.json', appmap)
27
27
  end
data/lib/appmap/rspec.rb CHANGED
@@ -205,7 +205,7 @@ module AppMap
205
205
  }.compact
206
206
  fname = AppMap::Util.scenario_filename(name)
207
207
 
208
- AppMap::Util.write_appmap(File.join(APPMAP_OUTPUT_DIR, fname), JSON.generate(appmap))
208
+ AppMap::Util.write_appmap(File.join(APPMAP_OUTPUT_DIR, fname), appmap)
209
209
  end
210
210
 
211
211
  def enabled?
data/lib/appmap/trace.rb CHANGED
@@ -84,12 +84,43 @@ module AppMap
84
84
  end
85
85
  end
86
86
 
87
+ class StackPrinter
88
+ class << self
89
+ def enabled?
90
+ ENV['APPMAP_PRINT_STACKS'] == 'true'
91
+ end
92
+
93
+ def depth
94
+ (ENV['APPMAP_STACK_DEPTH'] || 20).to_i
95
+ end
96
+ end
97
+
98
+ def initialize
99
+ @@stacks ||= Hash.new
100
+ end
101
+
102
+ def record(event)
103
+ stack = caller.select { |line| !line.index('/lib/appmap/') }[0...StackPrinter.depth].join("\n ")
104
+ stack_hash = Digest::SHA256.hexdigest(stack)
105
+ unless @@stacks[stack_hash]
106
+ @@stacks[stack_hash] = stack
107
+ puts
108
+ puts 'Event: ' + event.to_h.map { |k, v| [ "#{k}: #{v}" ] }.join(", ")
109
+ puts ' ' + stack
110
+ puts
111
+ end
112
+ end
113
+ end
114
+
87
115
  class Tracer
116
+ attr_accessor :stacks
117
+
88
118
  # Records the events which happen in a program.
89
119
  def initialize
90
120
  @events = []
91
121
  @last_package_for_thread = {}
92
122
  @methods = Set.new
123
+ @stack_printer = StackPrinter.new if StackPrinter.enabled?
93
124
  @enabled = false
94
125
  end
95
126
 
@@ -112,6 +143,7 @@ module AppMap
112
143
  def record_event(event, package: nil, defined_class: nil, method: nil)
113
144
  return unless @enabled
114
145
 
146
+ @stack_printer.record(event) if @stack_printer
115
147
  @last_package_for_thread[Thread.current.object_id] = package if package
116
148
  @events << event
117
149
  static = event.static if event.respond_to?(:static)
data/lib/appmap/util.rb CHANGED
@@ -21,14 +21,6 @@ module AppMap
21
21
  WHITE = "\e[37m"
22
22
 
23
23
  class << self
24
- def class_from_string(fq_class, must: true)
25
- fq_class.split('::').inject(Object) do |mod, class_name|
26
- mod.const_get(class_name)
27
- end
28
- rescue NameError
29
- raise if must
30
- end
31
-
32
24
  def parse_function_name(name)
33
25
  package_tokens = name.split('/')
34
26
 
@@ -171,7 +163,7 @@ module AppMap
171
163
  mode = File::RDWR | File::CREAT | File::EXCL
172
164
  ::Dir::Tmpname.create([ 'appmap_', '.json' ]) do |tmpname|
173
165
  tempfile = File.open(tmpname, mode)
174
- tempfile.write(appmap)
166
+ tempfile.write(JSON.generate(appmap))
175
167
  tempfile.close
176
168
  # Atomically move the tempfile into place.
177
169
  FileUtils.mv tempfile.path, filename
@@ -3,7 +3,7 @@
3
3
  module AppMap
4
4
  URL = 'https://github.com/applandinc/appmap-ruby'
5
5
 
6
- VERSION = '0.73.0'
6
+ VERSION = '0.76.0'
7
7
 
8
8
  APPMAP_FORMAT_VERSION = '1.5.1'
9
9
 
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'appmap/event'
5
+
6
+ include AppMap
7
+
8
+ describe 'display_string' do
9
+ def display_string(value)
10
+ Event::MethodEvent.display_string value
11
+ end
12
+
13
+ def compare_display_string(value, expected)
14
+ expect(display_string(value)).to eq(expected)
15
+ end
16
+
17
+ context 'for a' do
18
+ it 'String' do
19
+ compare_display_string 'foo', 'foo'
20
+ end
21
+ it 'long String' do
22
+ compare_display_string 'foo' * 100, 'foo' * 33 + 'f (...200 more characters)'
23
+ end
24
+ it 'Array' do
25
+ compare_display_string([ 1, 'my', :bar, [ 2, 3 ], { 4 => 5 } ], '[1, my, :bar, [2, 3], {4=>5}]')
26
+ end
27
+ it 'large Array' do
28
+ compare_display_string 50.times.map { |i| i }, '[0, 1, 2, 3, 4, 5, 6, 7, 8, 9 (...40 more items)]'
29
+ end
30
+ it 'large Hash' do
31
+ compare_display_string(50.times.map { |i| [ i*2, i*2+1] }.to_h, '{0=>1, 2=>3, 4=>5, 6=>7, 8=>9, 10=>11, 12=>13, 14=>15, 16=>17, 18=>19 (...40 more entries)}')
32
+ end
33
+ it 'Hash' do
34
+ compare_display_string({ 1 => 2, 'my' => 'neighbor', bar: :baz, ary: [ 1, 2 ]}, '{1=>2, my=>neighbor, :bar=>:baz, :ary=>[1, 2]}')
35
+ end
36
+ it 'big Hash' do
37
+ compare_display_string(50.times.map { |i| [ i*2, i*2+1] }.to_h, '{0=>1, 2=>3, 4=>5, 6=>7, 8=>9, 10=>11, 12=>13, 14=>15, 16=>17, 18=>19 (...40 more entries)}')
38
+ end
39
+ end
40
+ end
data/spec/hook_spec.rb CHANGED
@@ -1136,7 +1136,7 @@ describe 'AppMap class Hooking', docker: false do
1136
1136
  :parameters:
1137
1137
  - :name: :args
1138
1138
  :class: Array
1139
- :value: '["foo"]'
1139
+ :value: "[foo]"
1140
1140
  :kind: :rest
1141
1141
  - :name: :kw1
1142
1142
  :class: String
@@ -78,7 +78,7 @@ describe 'Rails' do
78
78
  'name' => 'params',
79
79
  'class' => 'ActiveSupport::HashWithIndifferentAccess',
80
80
  'object_id' => Integer,
81
- 'value' => '{"login"=>"alice"}',
81
+ 'value' => '{login=>alice}',
82
82
  'kind' => 'req'
83
83
  ),
84
84
  'receiver' => anything
@@ -127,7 +127,7 @@ describe 'Net::HTTP handler' do
127
127
  :message:
128
128
  - :name: ary
129
129
  :class: Array
130
- :value: '["1", "2"]'
130
+ :value: "[1, 2]"
131
131
  EVENT
132
132
  end
133
133
 
data/test/gem_test.rb CHANGED
@@ -24,7 +24,7 @@ class GemTest < Minitest::Test
24
24
  appmap_file = 'tmp/appmap/minitest/Parser_parser.appmap.json'
25
25
  appmap = JSON.parse(File.read(appmap_file))
26
26
  events = appmap['events']
27
- assert_equal 2, events.size
27
+ assert_equal 6, events.size
28
28
  assert_equal 'call', events.first['event']
29
29
  assert_equal 'default_parser', events.first['method_id']
30
30
  assert_match /\lib\/parser\/base\.rb$/, events.first['path']
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appmap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.73.0
4
+ version: 0.76.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Gilpin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-03-07 00:00:00.000000000 Z
11
+ date: 2022-03-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -339,10 +339,11 @@ files:
339
339
  - lib/appmap/agent.rb
340
340
  - lib/appmap/builtin_hooks/json.yml
341
341
  - lib/appmap/builtin_hooks/logger.yml
342
- - lib/appmap/builtin_hooks/marshal.yml
343
342
  - lib/appmap/builtin_hooks/net/http.yml
343
+ - lib/appmap/builtin_hooks/open3.yml
344
344
  - lib/appmap/builtin_hooks/openssl.yml
345
345
  - lib/appmap/builtin_hooks/psych.yml
346
+ - lib/appmap/builtin_hooks/ruby.yml
346
347
  - lib/appmap/class_map.rb
347
348
  - lib/appmap/command/agent_setup/init.rb
348
349
  - lib/appmap/command/agent_setup/status.rb
@@ -373,6 +374,7 @@ files:
373
374
  - lib/appmap/gem_hooks/resque.yml
374
375
  - lib/appmap/gem_hooks/sidekiq.yml
375
376
  - lib/appmap/gem_hooks/sprockets.yml
377
+ - lib/appmap/handler.rb
376
378
  - lib/appmap/handler/function.rb
377
379
  - lib/appmap/handler/net_http.rb
378
380
  - lib/appmap/handler/rails/request_handler.rb
@@ -409,6 +411,7 @@ files:
409
411
  - spec/config_spec.rb
410
412
  - spec/depends/api_spec.rb
411
413
  - spec/depends/spec_helper.rb
414
+ - spec/display_string_spec.rb
412
415
  - spec/fixtures/config/incomplete_config.yml
413
416
  - spec/fixtures/config/invalid_config.yml
414
417
  - spec/fixtures/config/invalid_yaml_config.yml
@@ -1,8 +0,0 @@
1
- - methods:
2
- - Marshal#load
3
- - Marshal#restore
4
- require_name: ruby
5
- label: deserialize.unsafe
6
- - method: Marshal#dump
7
- require_name: ruby
8
- label: serialize