appmap 0.83.5 → 0.85.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: 324aa913dbeb7c955fb624faf0ac6294694c9ea11e066c741d7e69313b194d91
4
- data.tar.gz: bbbc92d307315e5bb520dd769b2f90ab81d542e0243fc5d000172d2df2451dbb
3
+ metadata.gz: 002b026a3ee8b2e89a073906212e694f296dcc0666db8450c9051bab372550b2
4
+ data.tar.gz: 743adc87f3f3ae044c7da5d3040be48f79db21bf5d9861b60ec32f84ba39bc19
5
5
  SHA512:
6
- metadata.gz: 80ab785186c5d48d1b34422728f73883c7a152022e67276c64076df636449ecd5711411e32ba8150a0b3a58bad0897111dc63b7036cbb329a1f4030a83d1e102
7
- data.tar.gz: 54d432b3a78da40759e8b3bd43ae68fc718db7b2796c569898dc9181aabdde40546d582ebd756c76efab325ed275815ff06d15f2b2d745bffc6108f5586057a3
6
+ metadata.gz: 6af49c4b8155df95b38edf948217eedfa785151c7d3b6997cee8f0ba5971444c755a1e189a12fffdd640e1ec7e12316bd3a5e70d82e047d1dba4c2873040e5a1
7
+ data.tar.gz: e5af21dd5198c5291cdcd8da036b54c31c59178c17ccda863e4653aab7efb9a5392325226f90ef973f99107d8a44d24870dab3417d6b50c001ae4d325f50f30a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,36 @@
1
+ # [0.85.0](https://github.com/applandinc/appmap-ruby/compare/v0.84.0...v0.85.0) (2022-08-08)
2
+
3
+
4
+ ### Features
5
+
6
+ * Tune method parameters ([4a7b575](https://github.com/applandinc/appmap-ruby/commit/4a7b575e6f9684adaac4b592adc1ad2c832e900d))
7
+
8
+ # [0.84.0](https://github.com/applandinc/appmap-ruby/compare/v0.83.6...v0.84.0) (2022-08-04)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * Address stack overflow error with tracing? ([f426210](https://github.com/applandinc/appmap-ruby/commit/f426210b8dfb48987f2b6c1b5e57e80e3a2c921d))
14
+ * Handle nil class names ([263f2fc](https://github.com/applandinc/appmap-ruby/commit/263f2fc97b716f1a8205a3e85292c59ee19bc6bc))
15
+
16
+
17
+ ### Features
18
+
19
+ * Label ActiveSupport::MessageEncryptor ([38a7aeb](https://github.com/applandinc/appmap-ruby/commit/38a7aeb446a2baa63f6724eea8dcf36276d336c9))
20
+ * Label crypto function with algorithm name ([a7a9c61](https://github.com/applandinc/appmap-ruby/commit/a7a9c6145790fc5bc425e413d56984ef777f9fd1))
21
+ * Label EncryptedKeyRotatingCookieJar.commit ([8e1d015](https://github.com/applandinc/appmap-ruby/commit/8e1d0158d25f2cc386c32ba899085fd21fadafcb))
22
+ * Label OpenSSL::Random ([5c947a9](https://github.com/applandinc/appmap-ruby/commit/5c947a90037300639a94ab89d9e1a4dca26265bc))
23
+ * Label Random ([7572803](https://github.com/applandinc/appmap-ruby/commit/7572803991693ad80f8526c44056133cca13d4b8))
24
+ * Label the rest of OpenSSL::Cipher ([7863b7b](https://github.com/applandinc/appmap-ruby/commit/7863b7b3fcf2ecccda16b80e637e216c06a95108))
25
+ * Make activesupport a runtime dependency ([140a674](https://github.com/applandinc/appmap-ruby/commit/140a6744be2abf47d01e880a98f1dd06c8a505b1))
26
+
27
+ ## [0.83.6](https://github.com/applandinc/appmap-ruby/compare/v0.83.5...v0.83.6) (2022-08-01)
28
+
29
+
30
+ ### Bug Fixes
31
+
32
+ * Catch an uncaught EINVAL on Windows when attempting to parse source code ([9a152d8](https://github.com/applandinc/appmap-ruby/commit/9a152d8e48846b46572a3e7061bcdb35942b8993))
33
+
1
34
  ## [0.83.5](https://github.com/applandinc/appmap-ruby/compare/v0.83.4...v0.83.5) (2022-06-30)
2
35
 
3
36
 
data/appmap.gemspec CHANGED
@@ -27,11 +27,12 @@ Gem::Specification.new do |spec|
27
27
  spec.extensions << "ext/appmap/extconf.rb"
28
28
  spec.require_paths = ['lib']
29
29
 
30
- spec.add_dependency 'activesupport'
31
30
  spec.add_dependency 'method_source'
32
31
  spec.add_dependency 'rack'
33
32
  spec.add_dependency 'reverse_markdown'
34
33
 
34
+ spec.add_runtime_dependency 'activesupport'
35
+
35
36
  spec.add_development_dependency 'bundler', '>= 1.16'
36
37
  spec.add_development_dependency 'minitest', '~> 5.15'
37
38
  spec.add_development_dependency 'pry-byebug'
data/lib/appmap/agent.rb CHANGED
@@ -57,6 +57,12 @@ module AppMap
57
57
  end
58
58
  end
59
59
 
60
+ def tracing_enabled?
61
+ return false unless @tracing
62
+
63
+ @tracing.enabled?
64
+ end
65
+
60
66
  # Used to start tracing, stop tracing, and record events.
61
67
  def tracing
62
68
  @tracing ||= Trace::Tracing.new
@@ -11,6 +11,14 @@
11
11
  require_name: active_support/security_utils
12
12
  force: true
13
13
  - method: ActiveSupport.run_load_hooks
14
- label: deserialize.safe
14
+ labels:
15
+ - deserialize.safe
16
+ - lang.eval.safe
15
17
  require_name: active_support/lazy_load_hooks
16
18
  force: true
19
+ - method: ActiveSupport::MessageEncryptor#encrypt_and_sign
20
+ require_name: active_support/message_encryptor
21
+ force: true
22
+ - method: ActiveSupport::MessageEncryptor#decrypt_and_verifdy
23
+ require_name: active_support/message_encryptor
24
+ force: true
@@ -1,3 +1,3 @@
1
1
  - method: Net::HTTP#request
2
2
  label: protocol.http
3
- handler_class: AppMap::Handler::NetHTTP
3
+ handler_class: AppMap::Handler::NetHTTPHandler
@@ -12,5 +12,39 @@
12
12
  label: crypto.pkcs5
13
13
  - method: OpenSSL::Cipher#encrypt
14
14
  label: crypto.encrypt
15
+ handler_class: AppMap::Handler::OpenSSLHandler
15
16
  - method: OpenSSL::Cipher#decrypt
16
17
  label: crypto.decrypt
18
+ handler_class: AppMap::Handler::OpenSSLHandler
19
+ - method: OpenSSL::Cipher#auth_data=
20
+ label: crypto.set_auth_data
21
+ - method: OpenSSL::Cipher#auth_tag=
22
+ label: crypto.set_auth_tag
23
+ - method: OpenSSL::Cipher#auth_tag_len=
24
+ label: crypto.set_auth_tag_len
25
+ - method: OpenSSL::Cipher#ccm_data_len=
26
+ label: crypto.set_ccm_data_len
27
+ - method: OpenSSL::Cipher#iv=
28
+ label: crypto.set_iv
29
+ - method: OpenSSL::Cipher#iv_len=
30
+ label: crypto.set_iv_len
31
+ - method: OpenSSL::Cipher#key=
32
+ label: crypto.set_key
33
+ - method: OpenSSL::Cipher#key_len=
34
+ label: crypto.set_key_len
35
+ - method: OpenSSL::Cipher#padding=
36
+ label: crypto.set_padding
37
+ - method: OpenSSL::Cipher#final
38
+ label: crypto.final
39
+ - methods:
40
+ - OpenSSL::Cipher#random_iv
41
+ - OpenSSL::Cipher#random_key
42
+ - OpenSSL::Cipher#reset
43
+ - OpenSSL::Cipher#update
44
+ - methods:
45
+ - OpenSSL::Random.random_bytes
46
+ label: random.secure
47
+ - methods:
48
+ - OpenSSL::Random#add
49
+ - OpenSSL::Random#seed
50
+ label: pseudorandom.seed
@@ -2,6 +2,7 @@
2
2
  - Marshal#load
3
3
  - Marshal#restore
4
4
  require_name: ruby
5
+ handler_class: AppMap::Handler::MarshalLoadHandler
5
6
  label: deserialize.unsafe
6
7
  - method: Marshal#dump
7
8
  require_name: ruby
@@ -18,7 +19,7 @@
18
19
  - Kernel#eval
19
20
  require_name: ruby
20
21
  label: lang.eval
21
- handler_class: AppMap::Handler::Eval
22
+ handler_class: AppMap::Handler::EvalHandler
22
23
  - methods:
23
24
  - IO#popen
24
25
  - Kernel#exec
@@ -29,3 +30,6 @@
29
30
  - Process#spawn
30
31
  require_name: ruby
31
32
  label: system.exec
33
+ - methods:
34
+ - ERB#result
35
+ require_name: ruby
data/lib/appmap/config.rb CHANGED
@@ -32,8 +32,8 @@ module AppMap
32
32
  attr_writer :handler_class
33
33
 
34
34
  def handler_class
35
- require 'appmap/handler/function'
36
- @handler_class || AppMap::Handler::Function
35
+ require 'appmap/handler/function_handler'
36
+ @handler_class || AppMap::Handler::FunctionHandler
37
37
  end
38
38
 
39
39
  # Indicates that only the entry points to a package will be recorded.
@@ -72,7 +72,7 @@ module AppMap
72
72
  # Builds a package for gem. Generally corresponds to a `gem:` entry in appmap.yml. Also used when mapping
73
73
  # a builtin.
74
74
  def build_from_gem(gem, shallow: true, require_name: nil, exclude: [], labels: [], optional: false, force: false)
75
- if !force && %w[method_source activesupport].member?(gem)
75
+ if !force && %w[method_source].member?(gem)
76
76
  warn "WARNING: #{gem} cannot be AppMapped because it is a dependency of the appmap gem"
77
77
  return
78
78
  end
data/lib/appmap/event.rb CHANGED
@@ -84,10 +84,10 @@ module AppMap
84
84
  # Heuristic for dynamically defined class whose name can be nil
85
85
  def best_class_name(value)
86
86
  value_cls = value.class
87
- while value_cls.name.nil?
87
+ while value_cls && value_cls.name.nil?
88
88
  value_cls = value_cls.superclass
89
89
  end
90
- value_cls.name
90
+ value_cls&.name || 'unknown'
91
91
  end
92
92
 
93
93
  def encode_display_string(value)
@@ -193,7 +193,7 @@ module AppMap
193
193
 
194
194
  public
195
195
 
196
- def build_from_invocation(defined_class, method, receiver, arguments, event: MethodCall.new)
196
+ def build_from_invocation(defined_class, method, receiver, arguments, parameters: method.parameters, event: MethodCall.new)
197
197
  event ||= MethodCall.new
198
198
  defined_class ||= 'Class'
199
199
 
@@ -208,10 +208,10 @@ module AppMap
208
208
 
209
209
  # Check if the method has key parameters. If there are any they'll always be last.
210
210
  # If yes, then extract it from arguments.
211
- has_key = [[:dummy], *method.parameters].last.first.to_s.start_with?('key') && arguments[-1].is_a?(Hash)
211
+ has_key = [[:dummy], *parameters].last.first.to_s.start_with?('key') && arguments[-1].is_a?(Hash)
212
212
  kwargs = has_key && arguments[-1].dup || {}
213
213
 
214
- event.parameters = method.parameters.map.with_index do |method_param, idx|
214
+ event.parameters = parameters.map.with_index do |method_param, idx|
215
215
  param_type, param_name = method_param
216
216
  param_name ||= 'arg'
217
217
  value = case param_type
@@ -53,3 +53,5 @@
53
53
  labels:
54
54
  - deserialize.safe
55
55
  - lang.eval.safe
56
+ - methods: ActionDispatch::Cookies::EncryptedKeyRotatingCookieJar.commit
57
+ require_name: action_dispatch
@@ -0,0 +1,12 @@
1
+ - methods:
2
+ - Random.new_seed
3
+ - Random.rand
4
+ - Random.raw_seed
5
+ - Random.srand
6
+ - Random#bytes
7
+ - Random#rand
8
+ labels:
9
+ - pseudorandom
10
+ - random.insecure
11
+ - method: Random#seed
12
+ label: pseudorandom.seed
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'appmap/handler/function'
3
+ require 'appmap/handler/function_handler'
4
4
 
5
5
  module AppMap
6
6
  module Handler
@@ -14,15 +14,30 @@ module AppMap
14
14
  #
15
15
  # If the binding is not provided, by default eval will run in the
16
16
  # current frame. Since we call it here, this will mean the #do_call
17
- # frame, which would make AppMap::Handler::Eval the lexical scope
17
+ # frame, which would make AppMap::Handler::EvalHandler the lexical scope
18
18
  # for constant lookup and definition; as a consequence
19
19
  # eg. `eval "class Foo; end"` would define
20
- # AppMap::Handler::Eval::Foo instead of defining it in
20
+ # AppMap::Handler::EvalHandler::Foo instead of defining it in
21
21
  # the module where the original call was made.
22
22
  #
23
23
  # To avoid this, we explicitly substitute the correct execution
24
24
  # context, up several stack frames.
25
- class Eval < Function
25
+ class EvalHandler < FunctionHandler
26
+ # Kernel#eval reports the method parameters as :rest, instead of what you might expect from
27
+ # the documented signature: eval(string [, binding [, filename [,lineno]]])
28
+ # In the C code, it's defined as rb_f_eval(int argc, const VALUE *argv, VALUE self),
29
+ # so maybe that's why the parameters are reported as :rest.
30
+ #
31
+ # In any case, reporting the parameters as :rest means that the code string, binding, etc
32
+ # are reported in the AppMap as members of an Array, without individual object ids or types.
33
+ #
34
+ # To make eval easier to analyze, fake the hook_method parameters to better match
35
+ # the documentation.
36
+ PARAMETERS= [
37
+ [ :req, :string ],
38
+ [ :rest ],
39
+ ]
40
+
26
41
  # The depth of the frame we need to pluck out:
27
42
  # 1. Hook::Method#do_call
28
43
  # 2. Hook::Method#trace_call
@@ -31,6 +46,10 @@ module AppMap
31
46
  # 5. the (intended) frame of the original eval that we hooked
32
47
  # Note it needs to be adjusted if this call sequence changes.
33
48
  FRAME_DEPTH = 5
49
+
50
+ def handle_call(receiver, args)
51
+ AppMap::Event::MethodCall.build_from_invocation(defined_class, hook_method, receiver, args, parameters: PARAMETERS)
52
+ end
34
53
 
35
54
  def do_call(receiver, src = nil, context = nil, *rest)
36
55
  context ||= AppMap.caller_binding FRAME_DEPTH
@@ -6,7 +6,7 @@ require 'appmap/hook/method'
6
6
  module AppMap
7
7
  module Handler
8
8
  # Base handler class, will emit method call and return events.
9
- class Function < Hook::Method
9
+ class FunctionHandler < Hook::Method
10
10
  def handle_call(receiver, args)
11
11
  AppMap::Event::MethodCall.build_from_invocation(defined_class, hook_method, receiver, args)
12
12
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'appmap/handler/function_handler'
4
+
5
+ module AppMap
6
+ module Handler
7
+ class MarshalLoadHandler < FunctionHandler
8
+ PARAMETERS= [
9
+ [ :req, :source ],
10
+ [ :rest ],
11
+ ]
12
+
13
+ def handle_call(receiver, args)
14
+ AppMap::Event::MethodCall.build_from_invocation(defined_class, hook_method, receiver, args, parameters: PARAMETERS)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -29,7 +29,7 @@ module AppMap
29
29
 
30
30
  self.request_method = request.method
31
31
  self.url = url
32
- self.headers = NetHTTP.copy_headers(request)
32
+ self.headers = NetHTTPHandler.copy_headers(request)
33
33
  self.params = Rack::Utils.parse_nested_query(query)
34
34
  end
35
35
 
@@ -64,7 +64,7 @@ module AppMap
64
64
 
65
65
  if response
66
66
  self.status = response.code.to_i
67
- self.headers = NetHTTP.copy_headers(response)
67
+ self.headers = NetHTTPHandler.copy_headers(response)
68
68
  else
69
69
  self.headers = {}
70
70
  end
@@ -84,7 +84,7 @@ module AppMap
84
84
 
85
85
  # Handler class for HTTP requests.
86
86
  # Emits HTTP request events instead of method calls.
87
- class NetHTTP < Hook::Method
87
+ class NetHTTPHandler < Hook::Method
88
88
  def self.copy_headers(obj)
89
89
  {}.tap do |headers|
90
90
  obj.each_header do |key, value|
@@ -0,0 +1,16 @@
1
+ require 'appmap/handler/function_handler'
2
+
3
+ module AppMap
4
+ module Handler
5
+ class OpenSSLHandler < FunctionHandler
6
+ def handle_call(receiver, args)
7
+ super.tap do |event|
8
+ algorithm = receiver.name
9
+ event.receiver[:labels] ||= []
10
+ label = [ 'crypto.algorithm', algorithm ].join('.')
11
+ event.receiver[:labels] << label unless event.receiver[:labels].include?(label)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,9 +1,9 @@
1
- require 'appmap/handler/function'
1
+ require 'appmap/handler/function_handler'
2
2
 
3
3
  module AppMap
4
4
  module Handler
5
5
  module Rails
6
- class RenderHandler < AppMap::Handler::Function
6
+ class RenderHandler < AppMap::Handler::FunctionHandler
7
7
  def handle_call(receiver, args)
8
8
  options, _ = args
9
9
  # TODO: :file, :xml
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'appmap/handler/function'
3
+ require 'appmap/handler/function_handler'
4
4
  require 'appmap/event'
5
5
 
6
6
  module AppMap
@@ -110,7 +110,7 @@ module AppMap
110
110
  # Hooks the ActionView::Resolver methods +find_all+, +find_all_anywhere+. The resolver is used
111
111
  # during template rendering to lookup the template file path from parameters such as the
112
112
  # template name, prefix, and partial (boolean).
113
- class ResolverHandler < AppMap::Handler::Function
113
+ class ResolverHandler < AppMap::Handler::FunctionHandler
114
114
  def handle_call(receiver, args)
115
115
  name, prefix, partial = args
116
116
  warn "Resolver: #{{ name: name, prefix: prefix, partial: partial }}" if LOG
@@ -83,7 +83,7 @@ module AppMap
83
83
  end
84
84
 
85
85
  def trace?
86
- return false unless AppMap.tracing.enabled?
86
+ return false unless AppMap.tracing_enabled?
87
87
  return false if Thread.current[HOOK_DISABLE_KEY]
88
88
  return false if hook_package&.shallow? && AppMap.tracing.last_package_for_current_thread == hook_package
89
89
 
data/lib/appmap/trace.rb CHANGED
@@ -22,7 +22,7 @@ module AppMap
22
22
 
23
23
  def comment
24
24
  @method.comment
25
- rescue MethodSource::SourceNotFoundError
25
+ rescue MethodSource::SourceNotFoundError, Errno::EINVAL
26
26
  nil
27
27
  end
28
28
 
data/lib/appmap/util.rb CHANGED
@@ -193,6 +193,7 @@ module AppMap
193
193
  end
194
194
 
195
195
  def deep_dup(hash)
196
+ require 'active_support/core_ext'
196
197
  hash.deep_dup
197
198
  end
198
199
 
@@ -3,7 +3,7 @@
3
3
  module AppMap
4
4
  URL = 'https://github.com/applandinc/appmap-ruby'
5
5
 
6
- VERSION = '0.83.5'
6
+ VERSION = '0.85.0'
7
7
 
8
8
  APPMAP_FORMAT_VERSION = '1.7.0'
9
9
 
data/lib/appmap.rb CHANGED
@@ -20,13 +20,6 @@
20
20
  # - appmap/swagger (Rake task)
21
21
  # - appmap/depends (Rake task)
22
22
 
23
- begin
24
- require 'active_support'
25
- require 'active_support/core_ext'
26
- rescue NameError
27
- warn 'active_support is not available. AppMap execution will continue optimistically without it...'
28
- end
29
-
30
23
  require 'appmap/version'
31
24
  require 'appmap/agent'
32
25
 
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appmap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.83.5
4
+ version: 0.85.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-06-30 00:00:00.000000000 Z
11
+ date: 2022-08-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: activesupport
14
+ name: method_source
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: method_source
28
+ name: rack
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rack
42
+ name: reverse_markdown
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: reverse_markdown
56
+ name: activesupport
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -353,6 +353,7 @@ files:
353
353
  - ext/appmap/extconf.rb
354
354
  - lib/appmap.rb
355
355
  - lib/appmap/agent.rb
356
+ - lib/appmap/builtin_hooks/activesupport.yml
356
357
  - lib/appmap/builtin_hooks/json.yml
357
358
  - lib/appmap/builtin_hooks/logger.yml
358
359
  - lib/appmap/builtin_hooks/net/http.yml
@@ -383,19 +384,21 @@ files:
383
384
  - lib/appmap/gem_hooks/activejob-cancel.yml
384
385
  - lib/appmap/gem_hooks/activejob.yml
385
386
  - lib/appmap/gem_hooks/activerecord.yml
386
- - lib/appmap/gem_hooks/activesupport.yml
387
387
  - lib/appmap/gem_hooks/cancancan.yml
388
388
  - lib/appmap/gem_hooks/devise.yml
389
389
  - lib/appmap/gem_hooks/pandoc-ruby.yml
390
390
  - lib/appmap/gem_hooks/rails.yml
391
391
  - lib/appmap/gem_hooks/railties.yml
392
+ - lib/appmap/gem_hooks/random.yml
392
393
  - lib/appmap/gem_hooks/resque.yml
393
394
  - lib/appmap/gem_hooks/sidekiq.yml
394
395
  - lib/appmap/gem_hooks/sprockets.yml
395
396
  - lib/appmap/handler.rb
396
- - lib/appmap/handler/eval.rb
397
- - lib/appmap/handler/function.rb
398
- - lib/appmap/handler/net_http.rb
397
+ - lib/appmap/handler/eval_handler.rb
398
+ - lib/appmap/handler/function_handler.rb
399
+ - lib/appmap/handler/marshal_load_handler.rb
400
+ - lib/appmap/handler/net_http_handler.rb
401
+ - lib/appmap/handler/open_ssl_handler.rb
399
402
  - lib/appmap/handler/rails/render_handler.rb
400
403
  - lib/appmap/handler/rails/request_handler.rb
401
404
  - lib/appmap/handler/rails/sql_handler.rb