appmap 0.70.0 → 0.72.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 64006e414b4b6cece101a113b5b5359c370b77b96761cfcb02818c07e621d8c5
4
- data.tar.gz: e7ab888c17031adb8ae993dae863539b32359e967c706b2cc2b13f1f2bb11761
3
+ metadata.gz: 3dffdfecec5017edcd8c551226e5915348ef7db45a3ab82e1ccc1ace4879d712
4
+ data.tar.gz: 462c0d8e46b2a7c278e95e526ff8b1de7fa4d966e38c481cf69c5e3d1d97817e
5
5
  SHA512:
6
- metadata.gz: e9b9fbf621b59dfb72875365d2c4485e174b4532b159d62854883e77fd741451f1e8ca4609b0a5323cccc562fcf31ead2ef19923bd3be3e6b0d5d28d5c188635
7
- data.tar.gz: 4a079f0b5ae28e45a065187e0044446bdbef6a5a91df88f9072b71a825a18c86e3ba6eaf8dc54102b224eb16f3eae1ea0b9e3b8da3958b209bdd9f5d78d0ac50
6
+ metadata.gz: fc3e0a0c0488be776f924a457e04afd1ea9048ee43fd9bbcd557f79fd45212e2036ac38e2df021dcfa3c4a7c47f5401ae8e983dae236bd6de13481df103f552f
7
+ data.tar.gz: e369f73989da51222f65a50697c2fdcae367db5a0742d5b9e9a77dab321bfe2b74e09d49eb1d56359cc6b6ac64817e73ef55f0dfdfae63ff2c7e5dbf9c6f9a87
data/CHANGELOG.md CHANGED
@@ -1,3 +1,37 @@
1
+ # [0.72.0](https://github.com/applandinc/appmap-ruby/compare/v0.71.0...v0.72.0) (2022-01-24)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Fix a stack overflow when an override is prepended ([540907b](https://github.com/applandinc/appmap-ruby/commit/540907b1a9fa063d25ddbaf406674f2e16b11bfe))
7
+ * Hook the first class or module in the ancestor chain ([8143f14](https://github.com/applandinc/appmap-ruby/commit/8143f145691a98e6e83563635db783ba8d393d9c))
8
+
9
+
10
+ ### Features
11
+
12
+ * Label JSON, Marshal and YAML with (de)serialize ([318d294](https://github.com/applandinc/appmap-ruby/commit/318d294c1d921dacb18f1d3e1776282d9f208215))
13
+
14
+ # [0.71.0](https://github.com/applandinc/appmap-ruby/compare/v0.70.2...v0.71.0) (2022-01-19)
15
+
16
+
17
+ ### Features
18
+
19
+ * Add labels for http.session.clear, dao.materialize, log ([8e6784b](https://github.com/applandinc/appmap-ruby/commit/8e6784b82959eb5924d4675b43f6b98c7bd1b779))
20
+
21
+ ## [0.70.2](https://github.com/applandinc/appmap-ruby/compare/v0.70.1...v0.70.2) (2022-01-12)
22
+
23
+
24
+ ### Bug Fixes
25
+
26
+ * switch to activesupport's deep_dup implementation ([7715f28](https://github.com/applandinc/appmap-ruby/commit/7715f28285fbdabdb4c8d652fb9ac31eb8d86eab))
27
+
28
+ ## [0.70.1](https://github.com/applandinc/appmap-ruby/compare/v0.70.0...v0.70.1) (2021-12-10)
29
+
30
+
31
+ ### Bug Fixes
32
+
33
+ * Use require_name as the default package 'path' for builtins ([bcb4367](https://github.com/applandinc/appmap-ruby/commit/bcb4367811992c924c76950a22d11ddc3057c1ee))
34
+
1
35
  # [0.70.0](https://github.com/applandinc/appmap-ruby/compare/v0.69.0...v0.70.0) (2021-12-08)
2
36
 
3
37
 
@@ -1,4 +1,8 @@
1
1
  - method: JSON::Ext::Parser#parse
2
- label: format.json.parse
2
+ labels:
3
+ - format.json.parse
4
+ - deserialize
3
5
  - method: JSON::Ext::Generator::State#generate
4
- label: format.json.generate
6
+ label:
7
+ - format.json.generate
8
+ - serialize
@@ -0,0 +1,3 @@
1
+ - method: Logger::LogDevice#write
2
+ require_name: logger
3
+ label: log
@@ -0,0 +1,12 @@
1
+ - methods:
2
+ - Marshal#load
3
+ - Marshal#restore
4
+ require_name: ruby
5
+ label:
6
+ - deserialize
7
+ - deserialize.unsafe
8
+ - methods:
9
+ - Marshal#dump
10
+ require_name: ruby
11
+ label:
12
+ - deserialize
@@ -1,10 +1,23 @@
1
1
  - methods:
2
2
  - Psych#load
3
+ - Psych#unsafe_load
4
+ - Psych#load_file
5
+ - Psych#unsafe_load_file
3
6
  - Psych#load_stream
4
7
  - Psych#parse
5
8
  - Psych#parse_stream
6
- label: format.yaml.parse
9
+ label:
10
+ - format.yaml.parse
11
+ - deserialize
12
+ - deserialize.unsafe
13
+ - methods:
14
+ - Psych#safe_load
15
+ label:
16
+ - format.yaml.parse
17
+ - deserialize
7
18
  - methods:
8
19
  - Psych#dump
9
20
  - Psych#dump_stream
10
- label: format.yaml.generate
21
+ label:
22
+ - format.yaml.generate
23
+ - serialize
data/lib/appmap/config.rb CHANGED
@@ -163,7 +163,7 @@ module AppMap
163
163
  def package_hooks(methods, path: nil, gem: nil, force: false, builtin: false, handler_class: nil, require_name: nil)
164
164
  Array(methods).map do |method|
165
165
  package = if builtin
166
- Package.build_from_builtin(path, require_name: require_name, labels: method.labels, shallow: false)
166
+ Package.build_from_builtin(path || require_name, require_name: require_name, labels: method.labels, shallow: false)
167
167
  elsif gem
168
168
  Package.build_from_gem(gem, require_name: require_name, labels: method.labels, shallow: false, force: force, optional: true)
169
169
  elsif path
@@ -10,17 +10,22 @@
10
10
  - methods:
11
11
  - ActionDispatch::Request::Session#destroy
12
12
  - ActionDispatch::Request::Session#[]=
13
- - ActionDispatch::Request::Session#clear
14
13
  - ActionDispatch::Request::Session#update
15
14
  - ActionDispatch::Request::Session#delete
16
15
  - ActionDispatch::Request::Session#merge
17
16
  - ActionDispatch::Cookies::CookieJar#[]=
18
- - ActionDispatch::Cookies::CookieJar#clear
19
17
  - ActionDispatch::Cookies::CookieJar#update
20
18
  - ActionDispatch::Cookies::CookieJar#delete
21
19
  - ActionDispatch::Cookies::CookieJar#recycle!
22
20
  label: http.session.write
23
21
  require_name: action_dispatch
22
+ - methods:
23
+ - ActionDispatch::Request::Session#clear
24
+ - ActionDispatch::Cookies::CookieJar#clear
25
+ labels:
26
+ - http.session.write
27
+ - http.session.clear
28
+ require_name: action_dispatch
24
29
  - methods:
25
30
  - ActionDispatch::Cookies::EncryptedCookieJar#[]=
26
31
  - ActionDispatch::Cookies::EncryptedCookieJar#clear
@@ -0,0 +1,2 @@
1
+ - method: ActiveRecord::Relation#records
2
+ label: dao.materialize
@@ -94,7 +94,7 @@ module AppMap
94
94
  end
95
95
  hook_method_def = hook_method_def.ruby2_keywords if hook_method_def.respond_to?(:ruby2_keywords)
96
96
 
97
- hook_class.define_method_with_arity(hook_method.name, hook_method.arity, hook_method_def)
97
+ hook_class.ancestors.first.define_method_with_arity(hook_method.name, hook_method.arity, hook_method_def)
98
98
  end
99
99
 
100
100
  protected
data/lib/appmap/util.rb CHANGED
@@ -195,8 +195,7 @@ module AppMap
195
195
  end
196
196
 
197
197
  def deep_dup(hash)
198
- # This is a simple way to avoid the need for deep_dup from activesupport.
199
- Marshal.load(Marshal.dump(hash))
198
+ hash.deep_dup
200
199
  end
201
200
 
202
201
  def blank?(obj)
@@ -3,7 +3,7 @@
3
3
  module AppMap
4
4
  URL = 'https://github.com/applandinc/appmap-ruby'
5
5
 
6
- VERSION = '0.70.0'
6
+ VERSION = '0.72.0'
7
7
 
8
8
  APPMAP_FORMAT_VERSION = '1.5.1'
9
9
 
data/lib/appmap.rb CHANGED
@@ -20,6 +20,13 @@
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
+
23
30
  require 'appmap/version'
24
31
  require 'appmap/agent'
25
32
 
@@ -60,11 +67,11 @@ lambda do
60
67
  if defined?(::Rails)
61
68
  require 'appmap/railtie'
62
69
  end
63
-
70
+
64
71
  if defined?(::RSpec)
65
72
  require 'appmap/rspec'
66
73
  end
67
-
74
+
68
75
  if defined?(::Minitest)
69
76
  require 'appmap/minitest'
70
77
  end
@@ -73,7 +80,7 @@ lambda do
73
80
  require 'appmap/swagger'
74
81
  require 'appmap/depends'
75
82
  end
76
-
83
+
77
84
  end.call unless ENV['APPMAP_AUTOREQUIRE'] == 'false'
78
85
 
79
86
  AppMap.initialize_configuration if ENV['APPMAP'] == 'true' && ENV['APPMAP_INITIALIZE'] != 'false'
data/spec/config_spec.rb CHANGED
@@ -20,227 +20,100 @@ describe AppMap::Config, docker: false do
20
20
  }.deep_stringify_keys!
21
21
  config = AppMap::Config.load(config_data)
22
22
 
23
- expect(JSON.parse(JSON.generate(config.as_json))).to eq(JSON.parse(<<~FIXTURE))
24
- {
25
- "name": "test",
26
- "appmap_dir": "tmp/appmap",
27
- "packages": [
23
+ expect(config.as_json.keys.sort).to eq(["appmap_dir", "builtin_hooks", "depends_config", "exclude", "functions", "gem_hooks", "hook_paths", "name", "packages", "swagger_config"])
24
+ expect(config.as_json['appmap_dir']).to eq('tmp/appmap')
25
+ expect(config.as_json['name']).to eq('test')
26
+ expect(config.as_json['packages']).to eq([])
27
+ expect(config.as_json['depends_config']).to eq({
28
+ "base_dir" => nil,
29
+ "base_branches" => [
30
+ "remotes/origin/main",
31
+ "remotes/origin/master"
28
32
  ],
29
- "swagger_config": {
30
- "project_name": null,
31
- "project_version": "1.0",
32
- "output_dir": "swagger",
33
- "description": "Generate Swagger from AppMaps"
34
- },
35
- "depends_config": {
36
- "base_dir": null,
37
- "base_branches": [
38
- "remotes/origin/main",
39
- "remotes/origin/master"
40
- ],
41
- "test_file_patterns": [
42
- "spec/**/*_spec.rb",
43
- "test/**/*_test.rb"
44
- ],
45
- "dependent_tasks": [
46
- "swagger"
47
- ],
48
- "description": "Bring AppMaps up to date with local file modifications, and updated derived data such as Swagger files",
49
- "rspec_environment_method": "AppMap::Depends.test_env",
50
- "minitest_environment_method": "AppMap::Depends.test_env",
51
- "rspec_select_tests_method": "AppMap::Depends.select_rspec_tests",
52
- "minitest_select_tests_method": "AppMap::Depends.select_minitest_tests",
53
- "rspec_test_command_method": "AppMap::Depends.rspec_test_command",
54
- "minitest_test_command_method": "AppMap::Depends.minitest_test_command"
55
- },
56
- "hook_paths": [
57
- "pkg",
58
- "#{Gem.loaded_specs['activesupport'].gem_dir}"
33
+ "test_file_patterns" => [
34
+ "spec/**/*_spec.rb",
35
+ "test/**/*_test.rb"
59
36
  ],
60
- "exclude": [
37
+ "dependent_tasks" => [
38
+ "swagger"
61
39
  ],
62
- "functions": [
63
- {
64
- "cls": "cls",
65
- "target_methods": {
66
- "package": "pkg",
67
- "method_names": [
68
- "fn"
69
- ]
70
- }
71
- },
72
- {
73
- "cls": "cls",
74
- "target_methods": {
75
- "package": "pkg",
76
- "method_names": [
77
- "new_fn"
78
- ]
79
- }
40
+ "description" => "Bring AppMaps up to date with local file modifications, and updated derived data such as Swagger files",
41
+ "rspec_environment_method" => "AppMap::Depends.test_env",
42
+ "minitest_environment_method" => "AppMap::Depends.test_env",
43
+ "rspec_select_tests_method" => "AppMap::Depends.select_rspec_tests",
44
+ "minitest_select_tests_method" => "AppMap::Depends.select_minitest_tests",
45
+ "rspec_test_command_method" => "AppMap::Depends.rspec_test_command",
46
+ "minitest_test_command_method" => "AppMap::Depends.minitest_test_command"
47
+ })
48
+ expect(config.as_json['swagger_config']).to eq({
49
+ "project_name" => nil,
50
+ "project_version" => "1.0",
51
+ "output_dir" => "swagger",
52
+ "description" => "Generate Swagger from AppMaps"
53
+ })
54
+ expect(config.as_json['hook_paths']).to eq([
55
+ "pkg",
56
+ "#{Gem.loaded_specs['activesupport'].gem_dir}"
57
+ ])
58
+ expect(config.as_json['exclude']).to eq([])
59
+ expect(config.as_json['functions'].map(&:deep_stringify_keys)).to eq([
60
+ {
61
+ "cls" => "cls",
62
+ "target_methods" => {
63
+ "package" => "pkg",
64
+ "method_names" => [
65
+ :fn
66
+ ]
80
67
  }
81
- ],
82
- "builtin_hooks": {
83
- "JSON::Ext::Parser": [
84
- {
85
- "package": "json",
86
- "method_names": [
87
- "parse"
88
- ]
89
- }
90
- ],
91
- "JSON::Ext::Generator::State": [
92
- {
93
- "package": "json",
94
- "method_names": [
95
- "generate"
96
- ]
97
- }
98
- ],
99
- "Net::HTTP": [
100
- {
101
- "package": "net/http",
102
- "method_names": [
103
- "request"
104
- ]
105
- }
106
- ],
107
- "OpenSSL::PKey::PKey": [
108
- {
109
- "package": "openssl",
110
- "method_names": [
111
- "sign"
112
- ]
113
- }
114
- ],
115
- "OpenSSL::X509::Request": [
116
- {
117
- "package": "openssl",
118
- "method_names": [
119
- "sign"
120
- ]
121
- },
122
- {
123
- "package": "openssl",
124
- "method_names": [
125
- "verify"
126
- ]
127
- }
128
- ],
129
- "OpenSSL::X509::Certificate": [
130
- {
131
- "package": "openssl",
132
- "method_names": [
133
- "sign"
134
- ]
135
- }
136
- ],
137
- "OpenSSL::PKCS5": [
138
- {
139
- "package": "openssl",
140
- "method_names": [
141
- "pbkdf2_hmac"
142
- ]
143
- },
144
- {
145
- "package": "openssl",
146
- "method_names": [
147
- "pbkdf2_hmac_sha1"
148
- ]
149
- }
150
- ],
151
- "OpenSSL::Cipher": [
152
- {
153
- "package": "openssl",
154
- "method_names": [
155
- "encrypt"
156
- ]
157
- },
158
- {
159
- "package": "openssl",
160
- "method_names": [
161
- "decrypt"
162
- ]
163
- }
164
- ],
165
- "Psych": [
166
- {
167
- "package": "yaml",
168
- "method_names": [
169
- "load"
170
- ]
171
- },
172
- {
173
- "package": "yaml",
174
- "method_names": [
175
- "load_stream"
176
- ]
177
- },
178
- {
179
- "package": "yaml",
180
- "method_names": [
181
- "parse"
182
- ]
183
- },
184
- {
185
- "package": "yaml",
186
- "method_names": [
187
- "parse_stream"
188
- ]
189
- },
190
- {
191
- "package": "yaml",
192
- "method_names": [
193
- "dump"
194
- ]
195
- },
196
- {
197
- "package": "yaml",
198
- "method_names": [
199
- "dump_stream"
200
- ]
201
- }
68
+ },
69
+ {
70
+ "cls" => "cls",
71
+ "target_methods" => {
72
+ "package" => "pkg",
73
+ "method_names" => [
74
+ :new_fn
75
+ ]
76
+ }
77
+ }
78
+ ])
79
+ expect(config.as_json['builtin_hooks']).to have_key('JSON::Ext::Parser')
80
+ expect(config.as_json['builtin_hooks']['JSON::Ext::Parser'].map(&:deep_stringify_keys)).to eq([{
81
+ "package" => "json",
82
+ "method_names" => [
83
+ :parse
84
+ ]
85
+ }
86
+ ])
87
+ expect(config.as_json['gem_hooks']).to have_key('cls')
88
+ expect(config.as_json['gem_hooks']['cls'].map(&:deep_stringify_keys)).to eq([
89
+ {
90
+ "package" => "pkg",
91
+ "method_names" => [
92
+ :fn
93
+ ]
94
+ },
95
+ {
96
+ "package" => "pkg",
97
+ "method_names" => [
98
+ :new_fn
99
+ ]
100
+ }
101
+ ])
102
+ expect(config.as_json['gem_hooks']).to have_key('ActiveSupport::Callbacks::CallbackSequence')
103
+ expect(config.as_json['gem_hooks']['ActiveSupport::Callbacks::CallbackSequence'].map(&:deep_stringify_keys)).to eq([
104
+ {
105
+ "package" => "activesupport",
106
+ "method_names" => [
107
+ :invoke_before
202
108
  ]
203
109
  },
204
- "gem_hooks": {
205
- "cls": [
206
- {
207
- "package": "pkg",
208
- "method_names": [
209
- "fn"
210
- ]
211
- },
212
- {
213
- "package": "pkg",
214
- "method_names": [
215
- "new_fn"
216
- ]
217
- }
218
- ],
219
- "ActiveSupport::Callbacks::CallbackSequence": [
220
- {
221
- "package": "activesupport",
222
- "method_names": [
223
- "invoke_before"
224
- ]
225
- },
226
- {
227
- "package": "activesupport",
228
- "method_names": [
229
- "invoke_after"
230
- ]
231
- }
232
- ],
233
- "ActiveSupport::SecurityUtils": [
234
- {
235
- "package": "activesupport",
236
- "method_names": [
237
- "secure_compare"
238
- ]
239
- }
110
+ {
111
+ "package" => "activesupport",
112
+ "method_names" => [
113
+ :invoke_after
240
114
  ]
241
115
  }
242
- }
243
- FIXTURE
116
+ ])
244
117
  end
245
118
 
246
119
  describe AppMap::Config::Package do
@@ -0,0 +1,14 @@
1
+
2
+ module PrependedModule
3
+ def say_hello
4
+ 'please allow me to ' + super
5
+ end
6
+ end
7
+
8
+ class PrependedClass
9
+ prepend PrependedModule
10
+
11
+ def say_hello
12
+ 'introduce myself'
13
+ end
14
+ end
data/spec/hook_spec.rb CHANGED
@@ -1110,4 +1110,30 @@ describe 'AppMap class Hooking', docker: false do
1110
1110
  end
1111
1111
  end
1112
1112
  end
1113
+
1114
+ describe 'prepended override' do
1115
+ it 'does not cause stack overflow error' do
1116
+ # For the purposes of this test, the code must be statically required, then hooked,
1117
+ # then executed.
1118
+
1119
+ require_relative './fixtures/hook/prepended_override'
1120
+ require 'appmap/hook/method'
1121
+
1122
+ pkg = AppMap::Config::Package.new('fixtures/hook/prependend_override')
1123
+ AppMap::Hook::Method.new(pkg, PrependedClass, PrependedClass.public_instance_method(:say_hello)).activate
1124
+
1125
+ tracer = AppMap.tracing.trace
1126
+ AppMap::Event.reset_id_counter
1127
+ begin
1128
+ expect(PrependedClass.new.say_hello).to eq('please allow me to introduce myself')
1129
+ ensure
1130
+ AppMap.tracing.delete(tracer)
1131
+ end
1132
+
1133
+ events = collect_events(tracer)
1134
+ expect(events.length).to eq(2)
1135
+ expect(events.first[:method_id]).to eq('say_hello')
1136
+ expect(events.second[:return_value][:value]).to eq('please allow me to introduce myself')
1137
+ end
1138
+ end
1113
1139
  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.70.0
4
+ version: 0.72.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-12-08 00:00:00.000000000 Z
11
+ date: 2022-01-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -3406,6 +3406,8 @@ files:
3406
3406
  - lib/appmap.rb
3407
3407
  - lib/appmap/agent.rb
3408
3408
  - lib/appmap/builtin_hooks/json.yml
3409
+ - lib/appmap/builtin_hooks/logger.yml
3410
+ - lib/appmap/builtin_hooks/marshal.yml
3409
3411
  - lib/appmap/builtin_hooks/net/http.yml
3410
3412
  - lib/appmap/builtin_hooks/openssl.yml
3411
3413
  - lib/appmap/builtin_hooks/yaml.yml
@@ -3431,6 +3433,7 @@ files:
3431
3433
  - lib/appmap/gem_hooks/actionview.yml
3432
3434
  - lib/appmap/gem_hooks/activejob-cancel.yml
3433
3435
  - lib/appmap/gem_hooks/activejob.yml
3436
+ - lib/appmap/gem_hooks/activerecord.yml
3434
3437
  - lib/appmap/gem_hooks/activesupport.yml
3435
3438
  - lib/appmap/gem_hooks/cancancan.yml
3436
3439
  - lib/appmap/gem_hooks/resque.yml
@@ -3507,6 +3510,7 @@ files:
3507
3510
  - spec/fixtures/hook/labels.rb
3508
3511
  - spec/fixtures/hook/method_named_call.rb
3509
3512
  - spec/fixtures/hook/pkg_a/a.rb
3513
+ - spec/fixtures/hook/prepended_override.rb
3510
3514
  - spec/fixtures/hook/protected_method.rb
3511
3515
  - spec/fixtures/hook/revoke_api_key.appmap.json
3512
3516
  - spec/fixtures/hook/singleton_method.rb