appmap 0.54.4 → 0.55.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: 13450fa6c0ff3576dc48e27f35355e3eb4bd4ed70aac677af1235b8b8b8ce793
4
- data.tar.gz: 2c08a504d3e6a467d212630290205ecab9391c64a33831574df43cb8526ab0ad
3
+ metadata.gz: dfd518bd44a86f1270fe90e70c397e213763dd582260ace7c5a01898b94030d2
4
+ data.tar.gz: cf449bff5700a1bfd5efabda40ccd59c5281d595aa34ca551d6a3b4b1f89f5f8
5
5
  SHA512:
6
- metadata.gz: 49585b5fba1c9b7a0aabffd6dfc44fb051532fd9fe96d35a0176c6bcf382a51df948bfac8f1f0d3db474917f5587dbf07e90de9c9097d3de9a1650a1632f8fd6
7
- data.tar.gz: aa489a3dc598dfc2c16ee3a6167e53683e5564870c3b1ed0552e9e0ba0d758da2d1c442059bee3efbe57206f9088a98ca7c271d8550f52ed5d18d0aa2a039635
6
+ metadata.gz: 1824e49817ccceca6571fb2cb6f4a3033fb4873bb184577ec3989af3d74d09aecbf7685f9ce9f7efeb2a43e811f9477b0cfc5c6f6778ba3ec8d141c37560112c
7
+ data.tar.gz: da796d7072dab9b505f6fe1220ae3987e0577be458dfb1253b3d4b860df41d7a4856640629dd300ebcb6588f350f4f55af2b867bf730d0a65e90788c0f2eeb0d
data/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ # [0.55.0](https://github.com/applandinc/appmap-ruby/compare/v0.54.4...v0.55.0) (2021-06-28)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Avoid calling == ([f30ed9f](https://github.com/applandinc/appmap-ruby/commit/f30ed9f309753252df35e372d925db3b914260d4))
7
+ * Log dynamic loading of appmap helpers at info level ([15dcd3c](https://github.com/applandinc/appmap-ruby/commit/15dcd3c913fa1c32aea034b28ddae59668efa217))
8
+ * Remove dynamic loading of rake and rspec helpers ([6790970](https://github.com/applandinc/appmap-ruby/commit/67909702f3c8a52081ef1e23a87c292908883334))
9
+
10
+
11
+ ### Features
12
+
13
+ * APPMAP_PROFILE_DISPLAY_STRING and APPMAP_OBJECT_STRING ([3f5daa8](https://github.com/applandinc/appmap-ruby/commit/3f5daa890bfbfd39b7f825794d0c43da509b3201))
14
+ * Package name to require can be specified when hooking a gem ([fcc5eb6](https://github.com/applandinc/appmap-ruby/commit/fcc5eb691a0330444560eb4c2afe7fc3c4c8afa8))
15
+ * Profile packaging hooking ([c020a31](https://github.com/applandinc/appmap-ruby/commit/c020a312f4545348ec7cc302443269c57a7fc026))
16
+
1
17
  ## [0.54.4](https://github.com/applandinc/appmap-ruby/compare/v0.54.3...v0.54.4) (2021-06-27)
2
18
 
3
19
 
data/lib/appmap.rb CHANGED
@@ -28,11 +28,9 @@ lambda do
28
28
  INITIALIZERS = {
29
29
  # In a Rails app, Rails is always defined by the time the other gems are loaded. Therefore, we
30
30
  # don't try and trap the loading of Rails itself here.
31
- 'RSpec' => Initializer.new('AppMap::RSpec', 'appmap/rspec', 'rspec-core'),
31
+ # Emperically, Rake and RSpec are also defined before appmap is loaded whenever a Rake task or
32
+ # RSpec tests are being run. Therefore, the only hook we need here is Minitest.
32
33
  'Minitest::Unit::TestCase' => Initializer.new('AppMap::Minitest', 'appmap/minitest', 'minitest'),
33
- 'Rake' => [
34
- Initializer.new('AppMap::Swagger', 'appmap/swagger', 'rake')
35
- ]
36
34
  }
37
35
 
38
36
  TracePoint.new(:class) do |tp|
data/lib/appmap/config.rb CHANGED
@@ -343,7 +343,7 @@ module AppMap
343
343
  shallow = package['shallow']
344
344
  # shallow is true by default for gems
345
345
  shallow = true if shallow.nil?
346
- Package.build_from_gem(gem, exclude: package['exclude'] || [], shallow: shallow)
346
+ Package.build_from_gem(gem, package_name: package['package'], exclude: package['exclude'] || [], shallow: shallow)
347
347
  else
348
348
  Package.build_from_path(path, exclude: package['exclude'] || [], shallow: package['shallow'])
349
349
  end
data/lib/appmap/event.rb CHANGED
@@ -29,11 +29,31 @@ module AppMap
29
29
 
30
30
  # Gets a display string for a value. This is not meant to be a machine deserializable value.
31
31
  def display_string(value)
32
- return nil unless value
32
+ return nil if value.equal?(nil)
33
33
 
34
+ # With setting APPMAP_PROFILE_DISPLAY_STRING, stringifying this class is shown to take 9 seconds(!) of a 17 second test run.
35
+ return nil if best_class_name(value) == 'ActiveSupport::Callbacks::Filters::Environment'
36
+
37
+ if @times.nil? && ENV['APPMAP_PROFILE_DISPLAY_STRING'] == 'true'
38
+ @times = Hash.new {|memo,key| memo[key] = 0}
39
+ Thread.new do
40
+ sleep 0.5
41
+ while true
42
+ warn @times.to_a.sort{|a,b| b[1] <=> a[1]}[0..9].join("\n")
43
+ sleep 3
44
+ end
45
+ end
46
+ end
47
+
48
+ start = Time.now
34
49
  value_string = custom_display_string(value) || default_display_string(value)
35
50
 
36
- (value_string||'')[0...LIMIT].encode('utf-8', invalid: :replace, undef: :replace, replace: '_')
51
+ if @times
52
+ elapsed = Time.now - start
53
+ @times[best_class_name(value)] += elapsed
54
+ end
55
+
56
+ encode_dislay_string(value_string)
37
57
  end
38
58
 
39
59
  def object_properties(hash_like)
@@ -57,8 +77,16 @@ module AppMap
57
77
  value_cls.name
58
78
  end
59
79
 
80
+ def encode_dislay_string(value)
81
+ (value||'')[0...LIMIT].encode('utf-8', invalid: :replace, undef: :replace, replace: '_')
82
+ end
83
+
60
84
  def custom_display_string(value)
61
85
  case value
86
+ when NilClass, TrueClass, FalseClass, Numeric, Time, Date
87
+ value.to_s
88
+ when String
89
+ value[0...LIMIT].encode('utf-8', invalid: :replace, undef: :replace, replace: '_')
62
90
  when File
63
91
  "#{value.class}[path=#{value.path}]"
64
92
  when Net::HTTP
@@ -71,6 +99,8 @@ module AppMap
71
99
  end
72
100
 
73
101
  def default_display_string(value)
102
+ return nil if ENV['APPMAP_OBJECT_STRING'] == 'false'
103
+
74
104
  last_resort_string = lambda do
75
105
  warn "AppMap encountered an error inspecting a #{value.class.name}: #{$!.message}"
76
106
  '*Error inspecting variable*'
data/lib/appmap/hook.rb CHANGED
@@ -9,6 +9,7 @@ module AppMap
9
9
 
10
10
  OBJECT_INSTANCE_METHODS = %i[! != !~ <=> == === =~ __id__ __send__ class clone define_singleton_method display dup enum_for eql? equal? extend freeze frozen? hash inspect instance_eval instance_exec instance_of? instance_variable_defined? instance_variable_get instance_variable_set instance_variables is_a? itself kind_of? method methods nil? object_id private_methods protected_methods public_method public_methods public_send remove_instance_variable respond_to? send singleton_class singleton_method singleton_methods taint tainted? tap then to_enum to_s to_h to_a trust untaint untrust untrusted? yield_self].freeze
11
11
  OBJECT_STATIC_METHODS = %i[! != !~ < <= <=> == === =~ > >= __id__ __send__ alias_method allocate ancestors attr attr_accessor attr_reader attr_writer autoload autoload? class class_eval class_exec class_variable_defined? class_variable_get class_variable_set class_variables clone const_defined? const_get const_missing const_set constants define_method define_singleton_method deprecate_constant display dup enum_for eql? equal? extend freeze frozen? hash include include? included_modules inspect instance_eval instance_exec instance_method instance_methods instance_of? instance_variable_defined? instance_variable_get instance_variable_set instance_variables is_a? itself kind_of? method method_defined? methods module_eval module_exec name new nil? object_id prepend private_class_method private_constant private_instance_methods private_method_defined? private_methods protected_instance_methods protected_method_defined? protected_methods public_class_method public_constant public_instance_method public_instance_methods public_method public_method_defined? public_methods public_send remove_class_variable remove_instance_variable remove_method respond_to? send singleton_class singleton_class? singleton_method singleton_methods superclass taint tainted? tap then to_enum to_s trust undef_method untaint untrust untrusted? yield_self].freeze
12
+ SLOW_PACKAGE_THRESHOLD = 0.05
12
13
 
13
14
  @unbound_method_arity = ::UnboundMethod.instance_method(:arity)
14
15
  @method_arity = ::Method.instance_method(:arity)
@@ -49,6 +50,27 @@ module AppMap
49
50
  @notrace_paths = Set.new
50
51
  # Locations that have already been visited.
51
52
  @trace_locations = Set.new
53
+ @module_load_times = Hash.new {|memo,k| memo[k] = 0}
54
+ @slow_packages = Set.new
55
+
56
+ if ENV['APPMAP_PROFILE_HOOK'] == 'true'
57
+ Thread.new do
58
+ sleep 1
59
+ while true
60
+ @module_load_times
61
+ .keys
62
+ .select { |key| !@slow_packages.member?(key) }
63
+ .each do |key|
64
+ elapsed = @module_load_times[key]
65
+ if elapsed >= SLOW_PACKAGE_THRESHOLD
66
+ @slow_packages.add(key)
67
+ warn "AppMap: Package #{key} took #{@module_load_times[key]} seconds to hook"
68
+ end
69
+ end
70
+ sleep 5
71
+ end
72
+ end
73
+ end
52
74
 
53
75
  @trace_end = TracePoint.new(:end, &method(:trace_end))
54
76
  @trace_end.enable(&block)
@@ -157,6 +179,7 @@ module AppMap
157
179
  end
158
180
  end
159
181
 
182
+ start = Time.now
160
183
  instance_methods.each(&hook.(cls))
161
184
  begin
162
185
  # NoMethodError: private method `singleton_class' called for Rack::MiniProfiler:Class
@@ -166,6 +189,11 @@ module AppMap
166
189
  # uninitialized constant Faraday::Connection
167
190
  warn "NameError in #{__FILE__}: #{$!.message}"
168
191
  end
192
+ elapsed = Time.now - start
193
+ if location.index(Bundler.bundle_path.to_s) == 0
194
+ package_tokens = location[Bundler.bundle_path.to_s.length + 1..-1].split('/')
195
+ @module_load_times[package_tokens[1]] += elapsed
196
+ end
169
197
  end
170
198
  end
171
199
  end
@@ -49,9 +49,14 @@ module AppMap
49
49
 
50
50
  hook_method_def = Proc.new do |*args, &block|
51
51
  instance_method = hook_method.bind(self).to_proc
52
+
53
+ is_array_containing_empty_hash = ->(obj) {
54
+ obj.is_a?(Array) && obj.length == 1 && obj[0].is_a?(Hash) && obj[0].size == 0
55
+ }
56
+
52
57
  call_instance_method = -> {
53
58
  # https://github.com/applandinc/appmap-ruby/issues/153
54
- if Util.ruby_minor_version >= 2.7 && args == ARRAY_OF_EMPTY_HASH && hook_method.arity == 1
59
+ if Util.ruby_minor_version >= 2.7 && is_array_containing_empty_hash.(args) && hook_method.arity == 1
55
60
  instance_method.call({}, &block)
56
61
  else
57
62
  instance_method.call(*args, &block)
data/lib/appmap/util.rb CHANGED
@@ -185,7 +185,7 @@ module AppMap
185
185
 
186
186
  def startup_message(msg)
187
187
  if defined?(::Rails) && defined?(::Rails.logger) && ::Rails.logger
188
- ::Rails.logger.debug msg
188
+ ::Rails.logger.info msg
189
189
  elsif ENV['DEBUG'] == 'true'
190
190
  warn msg
191
191
  end
@@ -3,7 +3,7 @@
3
3
  module AppMap
4
4
  URL = 'https://github.com/applandinc/appmap-ruby'
5
5
 
6
- VERSION = '0.54.4'
6
+ VERSION = '0.55.0'
7
7
 
8
8
  APPMAP_FORMAT_VERSION = '1.5.1'
9
9
 
data/spec/hook_spec.rb CHANGED
@@ -970,7 +970,7 @@ describe 'AppMap class Hooking', docker: false do
970
970
  tz = ENV['TZ']
971
971
  ENV['TZ'] = 'UTC'
972
972
  Timecop.freeze(Time.utc('2020-01-01')) do
973
- expect(Time).to receive(:now).exactly(3).times.and_call_original
973
+ expect(Time).to receive(:now).at_least(3).times.and_call_original
974
974
  expect(InstanceMethod.new.say_the_time).to be
975
975
  end
976
976
  ensure
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.54.4
4
+ version: 0.55.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: 2021-06-27 00:00:00.000000000 Z
11
+ date: 2021-06-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport