appmap 0.34.4 → 0.34.5
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 +3 -0
- data/README.md +9 -0
- data/ext/appmap/appmap.c +63 -4
- data/lib/appmap/hook.rb +3 -0
- data/lib/appmap/hook/method.rb +27 -24
- data/lib/appmap/util.rb +1 -1
- data/lib/appmap/version.rb +1 -1
- data/spec/hook_spec.rb +7 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3b4318e1ef7e025a8f616022cefd323784e7b8ee8ccf06b1b7167b9937e860df
|
|
4
|
+
data.tar.gz: c6a743f2c7f4ebe8cd58f7ae971b5dae15791bc808dab9d4dcf87f4971986818
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9f271a71bb8bffa7004d054ae91646c9c93a476b15cbe80c459a9cafcb13ab0169be6c8a2db9b8cc993c3bc767deef4c9c0ca4befe6bd6881cf2d93c7b692b64
|
|
7
|
+
data.tar.gz: 3b6c5067a325fa2a0aed71b5ed92179196061cd6cfa015f907a25dab798e757c2cd53efbd028513df1f22cc2e2b8aa9345f8d19aa27018eccfbee4cd39766ece
|
data/CHANGELOG.md
CHANGED
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
|
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/hook.rb
CHANGED
data/lib/appmap/hook/method.rb
CHANGED
|
@@ -30,7 +30,7 @@ module AppMap
|
|
|
30
30
|
msg = if method_display_name
|
|
31
31
|
"#{method_display_name}"
|
|
32
32
|
else
|
|
33
|
-
"#{hook_method.name} (class resolution
|
|
33
|
+
"#{hook_method.name} (class resolution deferred)"
|
|
34
34
|
end
|
|
35
35
|
warn "AppMap: Hooking " + msg
|
|
36
36
|
end
|
|
@@ -41,36 +41,39 @@ module AppMap
|
|
|
41
41
|
after_hook = self.method(:after_hook)
|
|
42
42
|
with_disabled_hook = self.method(:with_disabled_hook)
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
hook_method_def = nil
|
|
45
|
+
hook_class.instance_eval do
|
|
46
|
+
hook_method_def = Proc.new do |*args, &block|
|
|
47
|
+
instance_method = hook_method.bind(self).to_proc
|
|
46
48
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
# We may not have gotten the class for the method during
|
|
50
|
+
# initialization (e.g. for a singleton method on an embedded
|
|
51
|
+
# struct), so make sure we have it now.
|
|
52
|
+
defined_class,_ = Hook.qualify_method_name(hook_method) unless defined_class
|
|
51
53
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
hook_disabled = Thread.current[HOOK_DISABLE_KEY]
|
|
55
|
+
enabled = true if !hook_disabled && AppMap.tracing.enabled?
|
|
56
|
+
return instance_method.call(*args, &block) unless enabled
|
|
55
57
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
58
|
+
call_event, start_time = with_disabled_hook.() do
|
|
59
|
+
before_hook.(self, defined_class, args)
|
|
60
|
+
end
|
|
61
|
+
return_value = nil
|
|
62
|
+
exception = nil
|
|
63
|
+
begin
|
|
64
|
+
return_value = instance_method.(*args, &block)
|
|
65
|
+
rescue
|
|
66
|
+
exception = $ERROR_INFO
|
|
67
|
+
raise
|
|
68
|
+
ensure
|
|
69
|
+
with_disabled_hook.() do
|
|
70
|
+
after_hook.(call_event, start_time, return_value, exception)
|
|
71
|
+
end
|
|
69
72
|
end
|
|
70
73
|
end
|
|
71
74
|
end
|
|
75
|
+
hook_class.define_method_with_arity(hook_method.name, hook_method.arity, hook_method_def)
|
|
72
76
|
end
|
|
73
|
-
|
|
74
77
|
protected
|
|
75
78
|
|
|
76
79
|
def before_hook(receiver, defined_class, args)
|
data/lib/appmap/util.rb
CHANGED
|
@@ -43,7 +43,7 @@ module AppMap
|
|
|
43
43
|
require 'hashie'
|
|
44
44
|
h.extend(Hashie::Extensions::DeepLocate)
|
|
45
45
|
keys = %i(path location)
|
|
46
|
-
|
|
46
|
+
h.deep_locate ->(k,v,o) {
|
|
47
47
|
next unless keys.include?(k)
|
|
48
48
|
|
|
49
49
|
fix = ->(v) {v.gsub(%r{#{Gem.dir}/gems/.*(?=lib)}, '')}
|
data/lib/appmap/version.rb
CHANGED
data/spec/hook_spec.rb
CHANGED
|
@@ -669,4 +669,11 @@ describe 'AppMap class Hooking', docker: false do
|
|
|
669
669
|
end
|
|
670
670
|
end
|
|
671
671
|
end
|
|
672
|
+
|
|
673
|
+
it "preserves the arity of hooked methods" do
|
|
674
|
+
invoke_test_file 'spec/fixtures/hook/instance_method.rb' do
|
|
675
|
+
expect(InstanceMethod.instance_method(:say_echo).arity).to be(1)
|
|
676
|
+
expect(InstanceMethod.new.method(:say_echo).arity).to be(1)
|
|
677
|
+
end
|
|
678
|
+
end
|
|
672
679
|
end
|
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.34.
|
|
4
|
+
version: 0.34.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kevin Gilpin
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2020-09-
|
|
11
|
+
date: 2020-09-23 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|