appmap 0.34.4 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -0
- data/README.md +11 -0
- data/Rakefile +1 -1
- data/appmap.gemspec +1 -1
- data/appmap.yml +1 -7
- data/ext/appmap/appmap.c +63 -4
- data/lib/appmap.rb +1 -1
- data/lib/appmap/class_map.rb +6 -7
- data/lib/appmap/config.rb +55 -25
- data/lib/appmap/event.rb +28 -10
- data/lib/appmap/hook.rb +12 -8
- data/lib/appmap/hook/method.rb +35 -28
- data/lib/appmap/rails/request_handler.rb +88 -0
- data/lib/appmap/rails/sql_handler.rb +10 -2
- data/lib/appmap/railtie.rb +4 -6
- data/lib/appmap/rspec.rb +10 -0
- data/lib/appmap/trace.rb +9 -7
- data/lib/appmap/util.rb +1 -1
- data/lib/appmap/version.rb +1 -1
- data/spec/abstract_controller4_base_spec.rb +1 -1
- data/spec/abstract_controller_base_spec.rb +6 -0
- data/spec/fixtures/hook/exception_method.rb +44 -0
- data/spec/hook_spec.rb +135 -2
- data/test/cli_test.rb +0 -10
- data/test/fixtures/gem_test/Gemfile +6 -0
- data/test/fixtures/gem_test/appmap.yml +3 -0
- data/test/fixtures/gem_test/test/to_param_test.rb +14 -0
- data/test/gem_test.rb +34 -0
- data/test/minitest_test.rb +2 -2
- data/test/openssl_test.rb +1 -49
- metadata +13 -10
- data/.ruby-version +0 -1
- data/lib/appmap/rails/action_handler.rb +0 -91
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 102dab80f2d8cffd51fd1377583a1b063078cd77ab7ad4ffdcd20867a084b11b
|
4
|
+
data.tar.gz: cbb87144593416f84099cf8a9d8ac18f18d9763dce28277320ae6a99ff59ec58
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a24e2ecb22a654d11e91ef28a7fdd961c178144f474a36e26c70e8e243bac18c13e3c5ff606f5ed2a058ddf6d98f9dbd0678a0f986ddfae4f18ed7524c27d41d
|
7
|
+
data.tar.gz: 712cb7e18026aa80135af7ce54a7a8c412362355c0eb6b151a0f05354cf991ebe9402e298d9646b9fab2e5d673d3338a773a0b1b1d0e1846ec3ed970074a1f77
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,27 @@
|
|
1
|
+
# v0.36.0
|
2
|
+
* *appmap.yml* package definition may specify `gem`.
|
3
|
+
* Skip loading the railtie if `APPMAP_INITIALIZE` environment variable
|
4
|
+
is set to `false`.
|
5
|
+
|
6
|
+
# v0.35.2
|
7
|
+
* Make sure `MethodEvent#display_string` works when the value's `#to_s` and/or `#inspect`
|
8
|
+
methods have problems.
|
9
|
+
|
10
|
+
# v0.35.1
|
11
|
+
* Take out hooking of `IO` and `Logger` methods.
|
12
|
+
* Enable logging if either `APPMAP_DEBUG` or `DEBUG` is `true`.
|
13
|
+
|
14
|
+
# v0.35.0
|
15
|
+
* Provide a custom display string for files and HTTP requests.
|
16
|
+
* Report `mime_type` on HTTP response.
|
17
|
+
|
18
|
+
# v0.34.6
|
19
|
+
* Only warn once about problems determining database version for an ActiveRecord
|
20
|
+
connection.
|
21
|
+
|
22
|
+
# v0.34.5
|
23
|
+
* Ensure that hooking a method doesn't change its arity.
|
24
|
+
|
1
25
|
# v0.34.4
|
2
26
|
* Make sure `AppMap:Rails::SQLExaminer::ActiveRecordExaminer.server_version` only calls
|
3
27
|
`ActiveRecord::Base.connection.database_version` if it's available.
|
data/README.md
CHANGED
@@ -57,6 +57,15 @@ end
|
|
57
57
|
|
58
58
|
Then install with `bundle`.
|
59
59
|
|
60
|
+
**Railtie**
|
61
|
+
|
62
|
+
If you are using Ruby on Rails, require the railtie after Rails is loaded.
|
63
|
+
|
64
|
+
```
|
65
|
+
# application.rb is a good place to do this, along with all the other railties.
|
66
|
+
require 'appmap/railtie'
|
67
|
+
```
|
68
|
+
|
60
69
|
# Configuration
|
61
70
|
|
62
71
|
When you run your program, the `appmap` gem reads configuration settings from `appmap.yml`. Here's a sample configuration
|
@@ -67,6 +76,7 @@ name: MyProject
|
|
67
76
|
packages:
|
68
77
|
- path: app/controllers
|
69
78
|
- path: app/models
|
79
|
+
- gem: activerecord
|
70
80
|
```
|
71
81
|
|
72
82
|
* **name** Provides the project name (required)
|
@@ -78,6 +88,7 @@ Each entry in the `packages` list is a YAML object which has the following keys:
|
|
78
88
|
|
79
89
|
* **path** The path to the source code directory. The path may be relative to the current working directory, or it may
|
80
90
|
be an absolute path.
|
91
|
+
* **gem** As an alternative to specifying the path, specify the name of a dependency gem. When using `gem`, don't specify `path`.
|
81
92
|
* **exclude** A list of files and directories which will be ignored. By default, all modules, classes and public
|
82
93
|
functions are inspected.
|
83
94
|
|
data/Rakefile
CHANGED
@@ -113,7 +113,7 @@ namespace :spec do
|
|
113
113
|
desc ruby_version
|
114
114
|
task ruby_version, [:specs] => ["compile", "build:fixtures:#{ruby_version}:all"] do |_, task_args|
|
115
115
|
run_specs(ruby_version, task_args)
|
116
|
-
end.tap do|t|
|
116
|
+
end.tap do |t|
|
117
117
|
desc "Run all specs"
|
118
118
|
task :all, [:specs] => t
|
119
119
|
end
|
data/appmap.gemspec
CHANGED
@@ -30,7 +30,7 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.add_dependency 'parser'
|
31
31
|
spec.add_dependency 'rack'
|
32
32
|
|
33
|
-
spec.add_development_dependency 'bundler', '
|
33
|
+
spec.add_development_dependency 'bundler', '>= 1.16'
|
34
34
|
spec.add_development_dependency 'minitest', '~> 5.0'
|
35
35
|
spec.add_development_dependency 'pry-byebug'
|
36
36
|
spec.add_development_dependency 'rake', '>= 12.3.3'
|
data/appmap.yml
CHANGED
data/ext/appmap/appmap.c
CHANGED
@@ -8,7 +8,12 @@
|
|
8
8
|
(!SPECIAL_CONST_P(obj) && \
|
9
9
|
(BUILTIN_TYPE(obj) == T_CLASS || BUILTIN_TYPE(obj) == T_MODULE))
|
10
10
|
|
11
|
-
|
11
|
+
#define ARITIES_KEY "__arities__"
|
12
|
+
|
13
|
+
VALUE am_AppMapHook;
|
14
|
+
|
15
|
+
static VALUE
|
16
|
+
singleton_method_owner_name(VALUE klass, VALUE method)
|
12
17
|
{
|
13
18
|
VALUE owner = rb_funcall(method, rb_intern("owner"), 0);
|
14
19
|
VALUE attached = rb_ivar_get(owner, rb_intern("__attached__"));
|
@@ -27,10 +32,64 @@ static VALUE singleton_method_owner_name(VALUE klass, VALUE method)
|
|
27
32
|
// #to_s on the method's owner and hope for the best.
|
28
33
|
return rb_funcall(owner, rb_intern("to_s"), 0);
|
29
34
|
}
|
30
|
-
|
35
|
+
|
36
|
+
|
37
|
+
static VALUE
|
38
|
+
am_define_method_with_arity(VALUE mod, VALUE name, VALUE arity, VALUE proc)
|
39
|
+
{
|
40
|
+
VALUE arities_key = rb_intern(ARITIES_KEY);
|
41
|
+
VALUE arities = rb_ivar_get(mod, arities_key);
|
42
|
+
|
43
|
+
if (arities == Qundef || NIL_P(arities)) {
|
44
|
+
arities = rb_hash_new();
|
45
|
+
rb_ivar_set(mod, arities_key, arities);
|
46
|
+
}
|
47
|
+
rb_hash_aset(arities, name, arity);
|
48
|
+
|
49
|
+
return rb_funcall(mod, rb_intern("define_method"), 2, name, proc);
|
50
|
+
}
|
51
|
+
|
52
|
+
static VALUE
|
53
|
+
am_get_method_arity(VALUE method, VALUE orig_arity_method)
|
54
|
+
{
|
55
|
+
VALUE owner = rb_funcall(method, rb_intern("owner"), 0);
|
56
|
+
VALUE arities = rb_ivar_get(owner, rb_intern(ARITIES_KEY));
|
57
|
+
VALUE name = rb_funcall(method, rb_intern("name"), 0);
|
58
|
+
VALUE arity = Qnil;
|
59
|
+
// See if we saved an arity for the method.
|
60
|
+
if (!NIL_P(arities)) {
|
61
|
+
arity = rb_hash_aref(arities, name);
|
62
|
+
}
|
63
|
+
// Didn't find one, call the original method.
|
64
|
+
if (NIL_P(arity)) {
|
65
|
+
VALUE bound_method = rb_funcall(orig_arity_method, rb_intern("bind"), 1, method);
|
66
|
+
arity = rb_funcall(bound_method, rb_intern("call"), 0);
|
67
|
+
}
|
68
|
+
|
69
|
+
return arity;
|
70
|
+
}
|
71
|
+
|
72
|
+
static VALUE
|
73
|
+
am_unbound_method_arity(VALUE method)
|
74
|
+
{
|
75
|
+
VALUE orig_unbound_method_arity = rb_ivar_get(am_AppMapHook, rb_intern("@unbound_method_arity"));
|
76
|
+
return am_get_method_arity(method, orig_unbound_method_arity);
|
77
|
+
}
|
78
|
+
|
79
|
+
static VALUE
|
80
|
+
am_method_arity(VALUE method)
|
81
|
+
{
|
82
|
+
VALUE orig_method_arity = rb_ivar_get(am_AppMapHook, rb_intern("@method_arity"));
|
83
|
+
return am_get_method_arity(method, orig_method_arity);
|
84
|
+
}
|
85
|
+
|
31
86
|
void Init_appmap() {
|
32
87
|
VALUE appmap = rb_define_module("AppMap");
|
33
|
-
|
88
|
+
am_AppMapHook = rb_define_class_under(appmap, "Hook", rb_cObject);
|
89
|
+
|
90
|
+
rb_define_singleton_method(am_AppMapHook, "singleton_method_owner_name", singleton_method_owner_name, 1);
|
34
91
|
|
35
|
-
|
92
|
+
rb_define_method(rb_cModule, "define_method_with_arity", am_define_method_with_arity, 3);
|
93
|
+
rb_define_method(rb_cUnboundMethod, "arity", am_unbound_method_arity, 0);
|
94
|
+
rb_define_method(rb_cMethod, "arity", am_method_arity, 0);
|
36
95
|
}
|
data/lib/appmap.rb
CHANGED
@@ -84,7 +84,7 @@ module AppMap
|
|
84
84
|
|
85
85
|
# Builds a class map from a config and a list of Ruby methods.
|
86
86
|
def class_map(methods)
|
87
|
-
ClassMap.build_from_methods(
|
87
|
+
ClassMap.build_from_methods(methods)
|
88
88
|
end
|
89
89
|
|
90
90
|
# Returns default metadata detected from the Ruby system and from the
|
data/lib/appmap/class_map.rb
CHANGED
@@ -61,30 +61,29 @@ module AppMap
|
|
61
61
|
location: location,
|
62
62
|
static: static,
|
63
63
|
labels: labels
|
64
|
-
}.delete_if { |
|
64
|
+
}.delete_if { |_, v| v.nil? || v == [] }
|
65
65
|
end
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
69
|
class << self
|
70
|
-
def build_from_methods(
|
70
|
+
def build_from_methods(methods)
|
71
71
|
root = Types::Root.new
|
72
72
|
methods.each do |method|
|
73
|
-
|
74
|
-
or raise "No package found for method #{method}"
|
75
|
-
add_function root, package, method
|
73
|
+
add_function root, method
|
76
74
|
end
|
77
75
|
root.children.map(&:to_h)
|
78
76
|
end
|
79
77
|
|
80
78
|
protected
|
81
79
|
|
82
|
-
def add_function(root,
|
80
|
+
def add_function(root, method)
|
81
|
+
package = method.package
|
83
82
|
static = method.static
|
84
83
|
|
85
84
|
object_infos = [
|
86
85
|
{
|
87
|
-
name: package.
|
86
|
+
name: package.name,
|
88
87
|
type: 'package'
|
89
88
|
}
|
90
89
|
]
|
data/lib/appmap/config.rb
CHANGED
@@ -2,15 +2,39 @@
|
|
2
2
|
|
3
3
|
module AppMap
|
4
4
|
class Config
|
5
|
-
Package = Struct.new(:path, :package_name, :exclude, :labels) do
|
6
|
-
|
7
|
-
|
5
|
+
Package = Struct.new(:path, :gem, :package_name, :exclude, :labels) do
|
6
|
+
class << self
|
7
|
+
def build_from_path(path, package_name: nil, exclude: [], labels: [])
|
8
|
+
Package.new(path, nil, package_name, exclude, labels)
|
9
|
+
end
|
10
|
+
|
11
|
+
def build_from_gem(gem, package_name: nil, exclude: [], labels: [])
|
12
|
+
gem_paths(gem).map do |gem_path|
|
13
|
+
Package.new(gem_path, gem, package_name, exclude, labels)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private_class_method :new
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def gem_paths(gem)
|
22
|
+
gemspec = Gem.loaded_specs[gem] or raise "Gem #{gem.inspect} not found"
|
23
|
+
gemspec.source_paths.map do |path|
|
24
|
+
File.join(gemspec.gem_dir, path)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def name
|
30
|
+
gem || path
|
8
31
|
end
|
9
|
-
|
32
|
+
|
10
33
|
def to_h
|
11
34
|
{
|
12
35
|
path: path,
|
13
36
|
package_name: package_name,
|
37
|
+
gem: gem,
|
14
38
|
exclude: exclude.blank? ? nil : exclude,
|
15
39
|
labels: labels.blank? ? nil : labels
|
16
40
|
}.compact
|
@@ -20,31 +44,29 @@ module AppMap
|
|
20
44
|
Hook = Struct.new(:method_names, :package) do
|
21
45
|
end
|
22
46
|
|
23
|
-
|
47
|
+
OPENSSL_PACKAGES = Package.build_from_path('openssl', package_name: 'openssl', labels: %w[security crypto])
|
24
48
|
|
25
49
|
# Methods that should always be hooked, with their containing
|
26
50
|
# package and labels that should be applied to them.
|
27
51
|
HOOKED_METHODS = {
|
28
|
-
'ActiveSupport::SecurityUtils' => Hook.new(:secure_compare, Package.
|
52
|
+
'ActiveSupport::SecurityUtils' => Hook.new(:secure_compare, Package.build_from_path('active_support', package_name: 'active_support', labels: %w[security crypto]))
|
29
53
|
}.freeze
|
30
54
|
|
31
55
|
BUILTIN_METHODS = {
|
32
|
-
'OpenSSL::PKey::PKey' => Hook.new(:sign,
|
33
|
-
'Digest::Instance' => Hook.new(:digest,
|
34
|
-
'OpenSSL::X509::Request' => Hook.new(%i[sign verify],
|
35
|
-
'OpenSSL::PKCS5' => Hook.new(%i[pbkdf2_hmac_sha1 pbkdf2_hmac],
|
36
|
-
'OpenSSL::Cipher' => Hook.new(%i[encrypt decrypt final],
|
37
|
-
'OpenSSL::X509::Certificate' => Hook.new(:sign,
|
38
|
-
'
|
39
|
-
'Net::
|
40
|
-
'Net::
|
41
|
-
'Net::
|
42
|
-
'
|
43
|
-
'
|
44
|
-
'
|
45
|
-
'
|
46
|
-
'JSON::Ext::Parser' => Hook.new(:parse, Package.new('json', package_name: 'json', labels: %w[serialization json])),
|
47
|
-
'JSON::Ext::Generator::State' => Hook.new(:generate, Package.new('json', package_name: 'json', labels: %w[serialization json]))
|
56
|
+
'OpenSSL::PKey::PKey' => Hook.new(:sign, OPENSSL_PACKAGES),
|
57
|
+
'Digest::Instance' => Hook.new(:digest, OPENSSL_PACKAGES),
|
58
|
+
'OpenSSL::X509::Request' => Hook.new(%i[sign verify], OPENSSL_PACKAGES),
|
59
|
+
'OpenSSL::PKCS5' => Hook.new(%i[pbkdf2_hmac_sha1 pbkdf2_hmac], OPENSSL_PACKAGES),
|
60
|
+
'OpenSSL::Cipher' => Hook.new(%i[encrypt decrypt final], OPENSSL_PACKAGES),
|
61
|
+
'OpenSSL::X509::Certificate' => Hook.new(:sign, OPENSSL_PACKAGES),
|
62
|
+
'Net::HTTP' => Hook.new(:request, Package.build_from_path('net/http', package_name: 'net/http', labels: %w[http io])),
|
63
|
+
'Net::SMTP' => Hook.new(:send, Package.build_from_path('net/smtp', package_name: 'net/smtp', labels: %w[smtp email io])),
|
64
|
+
'Net::POP3' => Hook.new(:mails, Package.build_from_path('net/pop3', package_name: 'net/pop', labels: %w[pop pop3 email io])),
|
65
|
+
'Net::IMAP' => Hook.new(:send_command, Package.build_from_path('net/imap', package_name: 'net/imap', labels: %w[imap email io])),
|
66
|
+
'Marshal' => Hook.new(%i[dump load], Package.build_from_path('marshal', labels: %w[serialization marshal])),
|
67
|
+
'Psych' => Hook.new(%i[dump dump_stream load load_stream parse parse_stream], Package.build_from_path('yaml', package_name: 'psych', labels: %w[serialization yaml])),
|
68
|
+
'JSON::Ext::Parser' => Hook.new(:parse, Package.build_from_path('json', package_name: 'json', labels: %w[serialization json])),
|
69
|
+
'JSON::Ext::Generator::State' => Hook.new(:generate, Package.build_from_path('json', package_name: 'json', labels: %w[serialization json]))
|
48
70
|
}.freeze
|
49
71
|
|
50
72
|
attr_reader :name, :packages
|
@@ -64,8 +86,16 @@ module AppMap
|
|
64
86
|
# Loads configuration from a Hash.
|
65
87
|
def load(config_data)
|
66
88
|
packages = (config_data['packages'] || []).map do |package|
|
67
|
-
|
68
|
-
|
89
|
+
gem = package['gem']
|
90
|
+
path = package['path']
|
91
|
+
raise 'AppMap package configuration should specify gem or path, not both' if gem && path
|
92
|
+
|
93
|
+
if gem
|
94
|
+
Package.build_from_gem(gem, exclude: package['exclude'] || [])
|
95
|
+
else
|
96
|
+
[ Package.build_from_path(path, exclude: package['exclude'] || []) ]
|
97
|
+
end
|
98
|
+
end.flatten
|
69
99
|
Config.new config_data['name'], packages
|
70
100
|
end
|
71
101
|
end
|
@@ -105,7 +135,7 @@ module AppMap
|
|
105
135
|
hook = find_hook(defined_class)
|
106
136
|
return nil unless hook
|
107
137
|
|
108
|
-
Array(hook.method_names).include?(method_name) ? hook.package : nil
|
138
|
+
Array(hook.method_names).include?(method_name) ? hook.package : nil
|
109
139
|
end
|
110
140
|
|
111
141
|
def find_hook(defined_class)
|
data/lib/appmap/event.rb
CHANGED
@@ -31,25 +31,43 @@ module AppMap
|
|
31
31
|
def display_string(value)
|
32
32
|
return nil unless value
|
33
33
|
|
34
|
+
value_string = custom_display_string(value) || default_display_string(value)
|
35
|
+
|
36
|
+
(value_string||'')[0...LIMIT].encode('utf-8', invalid: :replace, undef: :replace, replace: '_')
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
|
41
|
+
def custom_display_string(value)
|
42
|
+
case value
|
43
|
+
when File
|
44
|
+
"#{value.class}[path=#{value.path}]"
|
45
|
+
when Net::HTTP
|
46
|
+
"#{value.class}[#{value.address}:#{value.port}]"
|
47
|
+
when Net::HTTPGenericRequest
|
48
|
+
"#{value.class}[#{value.method} #{value.path}]"
|
49
|
+
end
|
50
|
+
rescue StandardError
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
|
54
|
+
def default_display_string(value)
|
34
55
|
last_resort_string = lambda do
|
35
56
|
warn "AppMap encountered an error inspecting a #{value.class.name}: #{$!.message}"
|
36
57
|
'*Error inspecting variable*'
|
37
58
|
end
|
38
59
|
|
39
|
-
|
60
|
+
begin
|
61
|
+
value.to_s
|
62
|
+
rescue NoMethodError
|
40
63
|
begin
|
41
|
-
value.
|
42
|
-
rescue NoMethodError
|
43
|
-
begin
|
44
|
-
value.inspect
|
45
|
-
rescue StandardError
|
46
|
-
last_resort_string.call
|
47
|
-
end
|
64
|
+
value.inspect
|
48
65
|
rescue StandardError
|
49
66
|
last_resort_string.call
|
50
67
|
end
|
51
|
-
|
52
|
-
|
68
|
+
rescue StandardError
|
69
|
+
last_resort_string.call
|
70
|
+
end
|
53
71
|
end
|
54
72
|
end
|
55
73
|
end
|
data/lib/appmap/hook.rb
CHANGED
@@ -4,7 +4,10 @@ require 'English'
|
|
4
4
|
|
5
5
|
module AppMap
|
6
6
|
class Hook
|
7
|
-
LOG = (ENV['DEBUG'] == 'true')
|
7
|
+
LOG = (ENV['APPMAP_DEBUG'] == 'true' || ENV['DEBUG'] == 'true')
|
8
|
+
|
9
|
+
@unbound_method_arity = ::UnboundMethod.instance_method(:arity)
|
10
|
+
@method_arity = ::Method.instance_method(:arity)
|
8
11
|
|
9
12
|
class << self
|
10
13
|
def lock_builtins
|
@@ -45,7 +48,6 @@ module AppMap
|
|
45
48
|
hook = lambda do |hook_cls|
|
46
49
|
lambda do |method_id|
|
47
50
|
method = hook_cls.public_instance_method(method_id)
|
48
|
-
hook_method = Hook::Method.new(hook_cls, method)
|
49
51
|
|
50
52
|
warn "AppMap: Examining #{hook_cls} #{method.name}" if LOG
|
51
53
|
|
@@ -53,14 +55,16 @@ module AppMap
|
|
53
55
|
# Skip methods that have no instruction sequence, as they are obviously trivial.
|
54
56
|
next unless disasm
|
55
57
|
|
56
|
-
# Don't try and trace the AppMap methods or there will be
|
57
|
-
# a stack overflow in the defined hook method.
|
58
|
-
next if /\AAppMap[:\.]/.match?(hook_method.method_display_name)
|
59
|
-
|
60
58
|
next unless \
|
61
59
|
config.always_hook?(hook_cls, method.name) ||
|
62
60
|
config.included_by_location?(method)
|
63
61
|
|
62
|
+
hook_method = Hook::Method.new(config.package_for_method(method), hook_cls, method)
|
63
|
+
|
64
|
+
# Don't try and trace the AppMap methods or there will be
|
65
|
+
# a stack overflow in the defined hook method.
|
66
|
+
next if /\AAppMap[:\.]/.match?(hook_method.method_display_name)
|
67
|
+
|
64
68
|
hook_method.activate
|
65
69
|
end
|
66
70
|
end
|
@@ -94,9 +98,9 @@ module AppMap
|
|
94
98
|
end
|
95
99
|
|
96
100
|
if method
|
97
|
-
Hook::Method.new(cls, method).activate
|
101
|
+
Hook::Method.new(hook.package, cls, method).activate
|
98
102
|
else
|
99
|
-
warn "Method #{method_name} not found on #{cls.name}"
|
103
|
+
warn "Method #{method_name} not found on #{cls.name}"
|
100
104
|
end
|
101
105
|
end
|
102
106
|
end
|