appmap 0.48.1 → 0.51.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +42 -0
- data/README.md +3 -332
- data/lib/appmap.rb +33 -6
- data/lib/appmap/config.rb +123 -33
- data/lib/appmap/hook.rb +15 -30
- data/lib/appmap/minitest.rb +8 -2
- data/lib/appmap/railtie.rb +7 -0
- data/lib/appmap/rspec.rb +8 -2
- data/lib/appmap/util.rb +21 -0
- data/lib/appmap/version.rb +3 -1
- data/spec/abstract_controller_base_spec.rb +57 -18
- data/spec/config_spec.rb +21 -0
- data/spec/fixtures/rails5_users_app/config/application.rb +0 -8
- data/spec/fixtures/rails5_users_app/spec/rails_helper.rb +0 -2
- data/spec/fixtures/rails6_users_app/config/application.rb +0 -8
- data/spec/fixtures/rails6_users_app/spec/rails_helper.rb +0 -2
- data/spec/hook_spec.rb +2 -2
- data/spec/record_net_http_spec.rb +1 -1
- metadata +2 -4
- data/spec/fixtures/rails5_users_app/config/initializers/record_button.rb +0 -3
- data/spec/fixtures/rails6_users_app/config/initializers/record_button.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8a51a7f69ebbca275fd9a215a52cd3e4d8db739e8e6cecf3eb522871f23295b5
|
4
|
+
data.tar.gz: 58f033b5c4f8756532dd3dbe83c631b36560e3215a342f804916de205f53cb56
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e52a4b23f708892b12c3ca68a2b5e3c13a2c9b1d1b52057ede1548faa7c7d03914296ebb1402c7c1cd1f0540df1d6182ffa09de2cf3558410d499703bc8b352f
|
7
|
+
data.tar.gz: 32201a386bc48ef35395e702a46661f78b12c4b15cab6214203e91e3599537cc53742f5ef2848ecf3d73b3c6c007413b55b4ea22bc4f8c83131733b9b2ace4a3
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,45 @@
|
|
1
|
+
## [0.51.1](https://github.com/applandinc/appmap-ruby/compare/v0.51.0...v0.51.1) (2021-06-21)
|
2
|
+
|
3
|
+
|
4
|
+
### Bug Fixes
|
5
|
+
|
6
|
+
* Add missing require 'yaml' ([1187a02](https://github.com/applandinc/appmap-ruby/commit/1187a023243caaab8cd48de5cbbddefa361636ad))
|
7
|
+
|
8
|
+
# [0.51.0](https://github.com/applandinc/appmap-ruby/compare/v0.50.0...v0.51.0) (2021-06-21)
|
9
|
+
|
10
|
+
|
11
|
+
### Features
|
12
|
+
|
13
|
+
* Provide default appmap.yml settings ([7fa8159](https://github.com/applandinc/appmap-ruby/commit/7fa8159b5020e35f13379017b44906d671e62e64))
|
14
|
+
|
15
|
+
# [0.50.0](https://github.com/applandinc/appmap-ruby/compare/v0.49.0...v0.50.0) (2021-06-17)
|
16
|
+
|
17
|
+
|
18
|
+
### Bug Fixes
|
19
|
+
|
20
|
+
* Remove appmap configuration in test cases which now occurs automatically ([7391c4c](https://github.com/applandinc/appmap-ruby/commit/7391c4c36ed80f98a6b82ccd43f05de488e7cd2f))
|
21
|
+
|
22
|
+
|
23
|
+
### Features
|
24
|
+
|
25
|
+
* Direct minitest and rspec startup messages to the Rails log, when available ([15f6444](https://github.com/applandinc/appmap-ruby/commit/15f6444b0fad3ce7d9e91273b6a1116e470c2a89))
|
26
|
+
* Enroll railtie, rspec, and minitest helpers automatically ([1709374](https://github.com/applandinc/appmap-ruby/commit/1709374ee7b5183482c55cf4c7386266fa517262))
|
27
|
+
* railtie enrolls the app in remote recording ([3a1f8aa](https://github.com/applandinc/appmap-ruby/commit/3a1f8aac1d83c4df04b5da55ed33d418235e348b))
|
28
|
+
|
29
|
+
# [0.49.0](https://github.com/applandinc/appmap-ruby/compare/v0.48.2...v0.49.0) (2021-06-16)
|
30
|
+
|
31
|
+
|
32
|
+
### Features
|
33
|
+
|
34
|
+
* Add refinement to the labels ([6a93396](https://github.com/applandinc/appmap-ruby/commit/6a93396ba73f1b3ed21b4e9e15a2c271af04d866))
|
35
|
+
|
36
|
+
## [0.48.2](https://github.com/applandinc/appmap-ruby/compare/v0.48.1...v0.48.2) (2021-05-26)
|
37
|
+
|
38
|
+
|
39
|
+
### Bug Fixes
|
40
|
+
|
41
|
+
* Correct the method-hooking logic to capture some missing model methods ([be529bd](https://github.com/applandinc/appmap-ruby/commit/be529bdce7d4fdf9f1a2fdd32259d792f29f4f13))
|
42
|
+
|
1
43
|
## [0.48.1](https://github.com/applandinc/appmap-ruby/compare/v0.48.0...v0.48.1) (2021-05-25)
|
2
44
|
|
3
45
|
|
data/README.md
CHANGED
@@ -1,17 +1,6 @@
|
|
1
1
|
|
2
2
|
- [About](#about)
|
3
|
-
|
4
|
-
- [Installation](#installation)
|
5
|
-
- [Configuration](#configuration)
|
6
|
-
- [Labels](#labels)
|
7
|
-
- [Running](#running)
|
8
|
-
- [RSpec](#rspec)
|
9
|
-
- [Minitest](#minitest)
|
10
|
-
- [Cucumber](#cucumber)
|
11
|
-
- [Remote recording](#remote-recording)
|
12
|
-
- [AppMap for VSCode](#appmap-for-vscode)
|
13
|
-
- [AppMap Swagger](#appmap-swagger)
|
14
|
-
- [Uploading AppMaps](#uploading-appmaps)
|
3
|
+
- [Usage](#usage)
|
15
4
|
- [Development](#development)
|
16
5
|
- [Internal architecture](#internal-architecture)
|
17
6
|
- [Running tests](#running-tests)
|
@@ -19,7 +8,6 @@
|
|
19
8
|
- [`test/fixtures`](#testfixtures)
|
20
9
|
- [`spec/fixtures`](#specfixtures)
|
21
10
|
|
22
|
-
|
23
11
|
# About
|
24
12
|
|
25
13
|
`appmap-ruby` is a Ruby Gem for recording
|
@@ -29,326 +17,9 @@
|
|
29
17
|
SHA, labels, etc). It's more granular than a performance profile, but it's less
|
30
18
|
granular than a full debug trace. It's designed to be optimal for understanding the design intent and structure of code and key data flows.
|
31
19
|
|
32
|
-
|
33
|
-
|
34
|
-
* Run your tests (RSpec, Minitest, Cucumber) with the environment variable `APPMAP=true`. An AppMap will be generated for each spec.
|
35
|
-
* Run your application server with AppMap remote recording enabled, and use the [AppLand
|
36
|
-
browser extension](https://github.com/applandinc/appland-browser-extension) to start,
|
37
|
-
stop, and upload recordings.
|
38
|
-
* Wrap some code in an `AppMap.record` block, which returns JSON containing the code execution trace.
|
39
|
-
|
40
|
-
Once you have made a recording, there are two ways to view automatically generated diagrams of the AppMaps.
|
41
|
-
|
42
|
-
The first option is to load the diagrams directly in your IDE, using the [AppMap extension for VSCode](https://marketplace.visualstudio.com/items?itemName=appland.appmap).
|
43
|
-
|
44
|
-
The second option is to upload them to the [AppLand server](https://app.land) using the [AppLand CLI](https://github.com/applandinc/appland-cli/releases).
|
45
|
-
|
46
|
-
### Supported versions
|
47
|
-
|
48
|
-
* Ruby 2.5, 2.6, 2.7
|
49
|
-
* Rails 5, 6
|
50
|
-
|
51
|
-
Support for new versions is added frequently, please check back regularly for updates.
|
52
|
-
|
53
|
-
# Installation
|
54
|
-
|
55
|
-
<a href="https://www.loom.com/share/78ab32a312ff4b85aa8827a37f1cb655"> <p>Quick and easy setup of the AppMap gem for Rails - Watch Video</p> <img style="max-width:300px;" src="https://cdn.loom.com/sessions/thumbnails/78ab32a312ff4b85aa8827a37f1cb655-with-play.gif"> </a>
|
56
|
-
|
57
|
-
|
58
|
-
Add `gem 'appmap'` to **beginning** of your Gemfile. We recommend that you add the `appmap` gem to the `:development, :test` group. Your Gemfile should look something like this:
|
59
|
-
|
60
|
-
```
|
61
|
-
source 'https://rubygems.org'
|
62
|
-
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
63
|
-
|
64
|
-
# Optional rubRuby version
|
65
|
-
# ruby '2.7.2'
|
66
|
-
|
67
|
-
group :development, :test do
|
68
|
-
gem 'appmap'
|
69
|
-
end
|
70
|
-
```
|
71
|
-
|
72
|
-
Install with `bundle install`, as usual.
|
73
|
-
|
74
|
-
It's important to add the `appmap` gem before any other gems that you may want to instrument. There is more about this in the section on adding gems to the *appmap.yml*.
|
75
|
-
|
76
|
-
**Railtie**
|
77
|
-
|
78
|
-
If you are using Ruby on Rails, require the railtie after Rails is loaded.
|
79
|
-
|
80
|
-
```
|
81
|
-
# application.rb is a good place to do this, along with all the other railties.
|
82
|
-
# Don't require the railtie in environments that don't bundle the appmap gem.
|
83
|
-
require 'appmap/railtie' if defined?(AppMap).
|
84
|
-
```
|
85
|
-
|
86
|
-
# Configuration
|
87
|
-
|
88
|
-
When you run your program, the `appmap` gem reads configuration settings from `appmap.yml`. Here's a sample configuration
|
89
|
-
file for a typical Rails project:
|
90
|
-
|
91
|
-
```yaml
|
92
|
-
# 'name' should generally be the same as the code repo name.
|
93
|
-
name: my_project
|
94
|
-
packages:
|
95
|
-
- path: app/controllers
|
96
|
-
- path: app/models
|
97
|
-
# Exclude sub-paths within the package path
|
98
|
-
exclude:
|
99
|
-
- concerns/accessor
|
100
|
-
- path: app/jobs
|
101
|
-
- path: app/helpers
|
102
|
-
# Include the gems that you want to see in the dependency maps.
|
103
|
-
# These are just examples.
|
104
|
-
- gem: activerecord
|
105
|
-
- gem: devise
|
106
|
-
- gem: aws-sdk
|
107
|
-
- gem: will_paginate
|
108
|
-
# Global exclusion of a class name
|
109
|
-
exclude:
|
110
|
-
- MyClass
|
111
|
-
- MyClass#my_instance_method
|
112
|
-
- MyClass.my_class_method
|
113
|
-
functions:
|
114
|
-
- packages: myapp
|
115
|
-
class: ControllerHelper
|
116
|
-
function: logged_in_user
|
117
|
-
labels: [ authentication ]
|
118
|
-
```
|
119
|
-
|
120
|
-
* **name** Provides the project name (required)
|
121
|
-
* **packages** A list of source code directories which should be recorded.
|
122
|
-
* **exclude** A list of classes and/or methods to definitively exclude from recording.
|
123
|
-
* **functions** A list of specific functions, scoped by package and class, to record.
|
124
|
-
|
125
|
-
**packages**
|
126
|
-
|
127
|
-
Each entry in the `packages` list is a YAML object which has the following keys:
|
128
|
-
|
129
|
-
* **path** The path to the source code directory. The path may be relative to the current working directory, or it may
|
130
|
-
be an absolute path.
|
131
|
-
* **gem** As an alternative to specifying the path, specify the name of a dependency gem. When using `gem`, don't specify `path`. In your `Gemfile`, the `appmap` gem **must** be listed **before** any gem that you specify in your *appmap.yml*.
|
132
|
-
* **exclude** A list of files and directories which will be ignored. By default, all modules, classes and public
|
133
|
-
functions are inspected. See also: global `exclude` list.
|
134
|
-
* **shallow** When set to `true`, only the first function call entry into a package will be recorded. Subsequent function calls within
|
135
|
-
the same package are not recorded unless code execution leaves the package and re-enters it. Default: `true` when using `gem`,
|
136
|
-
`false` when using `path`.
|
137
|
-
|
138
|
-
**exclude**
|
139
|
-
|
140
|
-
Optional list of fully qualified class and method names. Separate class and method names with period (`.`) for class methods and hash (`#`) for instance methods.
|
141
|
-
|
142
|
-
**functions**
|
143
|
-
|
144
|
-
Optional list of `class, function` pairs. The `package` name is used to place the function within the class map, and does not have to match
|
145
|
-
the folder or gem name. The primary use of `functions` is to apply specific labels to functions whose source code is not accessible (e.g., it's in a Gem).
|
146
|
-
For functions which are part of the application code, use `@label` or `@labels` in code comments to apply labels.
|
147
|
-
|
148
|
-
# Labels
|
149
|
-
|
150
|
-
The [AppMap data format](https://github.com/applandinc/appmap) provides for class and function `labels`, which can be used to enhance the AppMap visualizations, and to programatically analyze the data.
|
151
|
-
|
152
|
-
You can apply function labels using source code comments in your Ruby code. To apply a labels to a function, add a `@label` or `@labels` line to the comment which immediately precedes a function.
|
153
|
-
|
154
|
-
For example, if you add this comment to your source code:
|
155
|
-
|
156
|
-
```ruby
|
157
|
-
class ApiKey
|
158
|
-
# @labels provider.authentication security
|
159
|
-
def authenticate(key)
|
160
|
-
# logic to verify the key here...
|
161
|
-
end
|
162
|
-
end
|
163
|
-
```
|
164
|
-
|
165
|
-
Then the AppMap metadata section for this function will include:
|
166
|
-
|
167
|
-
```json
|
168
|
-
{
|
169
|
-
"name": "authenticate",
|
170
|
-
"type": "function",
|
171
|
-
"labels": [ "provider.authentication", "security" ]
|
172
|
-
}
|
173
|
-
```
|
174
|
-
|
175
|
-
|
176
|
-
# Running
|
177
|
-
|
178
|
-
## RSpec
|
179
|
-
|
180
|
-
To record RSpec tests, follow these additional steps:
|
181
|
-
|
182
|
-
1) Require `appmap/rspec` in your `spec_helper.rb` before any other classes are loaded.
|
183
|
-
|
184
|
-
```ruby
|
185
|
-
require 'appmap/rspec'
|
186
|
-
```
|
187
|
-
|
188
|
-
Note that `spec_helper.rb` in a Rails project typically loads the application's classes this way:
|
189
|
-
|
190
|
-
```ruby
|
191
|
-
require File.expand_path("../../config/environment", __FILE__)
|
192
|
-
```
|
193
|
-
|
194
|
-
and `appmap/rspec` must be required before this:
|
195
|
-
|
196
|
-
```ruby
|
197
|
-
require 'appmap/rspec'
|
198
|
-
require File.expand_path("../../config/environment", __FILE__)
|
199
|
-
```
|
200
|
-
|
201
|
-
2) Run the tests with the environment variable `APPMAP=true`:
|
202
|
-
|
203
|
-
```sh-session
|
204
|
-
$ APPMAP=true bundle exec rspec
|
205
|
-
```
|
206
|
-
|
207
|
-
Each RSpec test will output an AppMap file into the directory `tmp/appmap/rspec`. For example:
|
208
|
-
|
209
|
-
```
|
210
|
-
$ find tmp/appmap/rspec
|
211
|
-
Hello_says_hello_when_prompted.appmap.json
|
212
|
-
```
|
213
|
-
|
214
|
-
## Minitest
|
215
|
-
|
216
|
-
To record Minitest tests, follow these additional steps:
|
217
|
-
|
218
|
-
1) Require `appmap/minitest` in `test_helper.rb`
|
219
|
-
|
220
|
-
```ruby
|
221
|
-
require 'appmap/minitest'
|
222
|
-
```
|
223
|
-
|
224
|
-
Note that `test_helper.rb` in a Rails project typically loads the application's classes this way:
|
225
|
-
|
226
|
-
```ruby
|
227
|
-
require_relative '../config/environment'
|
228
|
-
```
|
229
|
-
|
230
|
-
and `appmap/minitest` must be required before this:
|
231
|
-
|
232
|
-
```ruby
|
233
|
-
require 'appmap/minitest'
|
234
|
-
require_relative '../config/environment'
|
235
|
-
```
|
236
|
-
|
237
|
-
2) Run your tests as you normally would with the environment variable `APPMAP=true`. For example:
|
238
|
-
|
239
|
-
```
|
240
|
-
$ APPMAP=true bundle exec rake test
|
241
|
-
```
|
242
|
-
|
243
|
-
or
|
244
|
-
|
245
|
-
```
|
246
|
-
$ APPMAP=true bundle exec ruby -Ilib -Itest test/*_test.rb
|
247
|
-
```
|
248
|
-
|
249
|
-
Each Minitest test will output an AppMap file into the directory `tmp/appmap/minitest`. For example:
|
250
|
-
|
251
|
-
```
|
252
|
-
$ find tmp/appmap/minitest
|
253
|
-
Hello_says_hello_when_prompted.appmap.json
|
254
|
-
```
|
255
|
-
|
256
|
-
## Cucumber
|
257
|
-
|
258
|
-
To record Cucumber tests, follow these additional steps:
|
259
|
-
|
260
|
-
1) Require `appmap/cucumber` in `support/env.rb`:
|
261
|
-
|
262
|
-
```ruby
|
263
|
-
require 'appmap/cucumber'
|
264
|
-
```
|
265
|
-
|
266
|
-
Be sure to require it before `config/environment` is required.
|
267
|
-
|
268
|
-
2) Create an `Around` hook in `support/hooks.rb` to record the scenario:
|
269
|
-
|
270
|
-
|
271
|
-
```ruby
|
272
|
-
if AppMap::Cucumber.enabled?
|
273
|
-
Around('not @appmap-disable') do |scenario, block|
|
274
|
-
appmap = AppMap.record do
|
275
|
-
block.call
|
276
|
-
end
|
277
|
-
|
278
|
-
AppMap::Cucumber.write_scenario(scenario, appmap)
|
279
|
-
end
|
280
|
-
end
|
281
|
-
```
|
282
|
-
|
283
|
-
3) Run the tests with the environment variable `APPMAP=true`:
|
284
|
-
|
285
|
-
```sh-session
|
286
|
-
$ APPMAP=true bundle exec cucumber
|
287
|
-
```
|
288
|
-
|
289
|
-
Each Cucumber test will output an AppMap file into the directory `tmp/appmap/cucumber`. For example:
|
290
|
-
|
291
|
-
```
|
292
|
-
$ find tmp/appmap/cucumber
|
293
|
-
Hello_Says_hello_when_prompted.appmap.json
|
294
|
-
```
|
295
|
-
|
296
|
-
## Remote recording
|
297
|
-
|
298
|
-
To manually record ad-hoc AppMaps of your Ruby app, use AppMap remote recording.
|
299
|
-
|
300
|
-
1. Add the AppMap remote recording middleware. For example, in `config/initializers/appmap_remote_recording.rb`:
|
301
|
-
|
302
|
-
```ruby
|
303
|
-
if defined?(AppMap)
|
304
|
-
require 'appmap/middleware/remote_recording'
|
305
|
-
|
306
|
-
Rails.application.config.middleware.insert_after \
|
307
|
-
Rails::Rack::Logger,
|
308
|
-
AppMap::Middleware::RemoteRecording
|
309
|
-
end
|
310
|
-
```
|
311
|
-
|
312
|
-
2. (optional) Download and unpack the [AppLand browser extension](https://github.com/applandinc/appland-browser-extension). Install into Chrome using `chrome://extensions/`. Turn on "Developer Mode" and then load the extension using the "Load unpacked" button.
|
313
|
-
|
314
|
-
3. Start your Rails application server, with `APPMAP_RECORD=true`. For example:
|
315
|
-
|
316
|
-
```sh-session
|
317
|
-
$ APPMAP_RECORD=true bundle exec rails server
|
318
|
-
```
|
319
|
-
|
320
|
-
4. Start the recording
|
321
|
-
|
322
|
-
Option 1: Open the AppLand browser extension and push `Start`.
|
323
|
-
Option 2: `curl -XPOST localhost:3000/_appmap/record` (be sure and get the port number right)
|
324
|
-
|
325
|
-
5. Use your app. For example, perform a login flow, or run through a manual UI test.
|
326
|
-
|
327
|
-
6. Finish the recording.
|
328
|
-
|
329
|
-
Option 1: Open the AppLand browser extension and push `Stop`. The recording will be transferred to the AppLand website and opened in your browser.
|
330
|
-
Option 2: `curl -XDELETE localhost:3000/_appmap/record > recording.appmap.json` - Saves the recording as a local file.
|
331
|
-
|
332
|
-
|
333
|
-
# AppMap for VSCode
|
334
|
-
|
335
|
-
The [AppMap extension for VSCode](https://marketplace.visualstudio.com/items?itemName=appland.appmap) helps you navigate your code more efficiently with interactive, accurate software architecture diagrams right in your IDE. In less than two minutes you can go from installing the AppMap extension to exploring maps of your code's architecture. AppMap helps you:
|
336
|
-
|
337
|
-
* Onboard to code architecture, with no extra work for the team
|
338
|
-
* Conduct code and design reviews using live and accurate data
|
339
|
-
* Troubleshoot hard-to-understand bugs using a "top-down" approach.
|
340
|
-
|
341
|
-
Each interactive diagram links directly to the source code, and the information is easy to share.
|
342
|
-
|
343
|
-
# AppMap Swagger
|
344
|
-
|
345
|
-
[appmap_swagger](https://github.com/applandinc/appmap_swagger-ruby) is a tool to generate Swagger files from AppMap data. With `appmap_swagger`, you can add Swagger to your Ruby or Ruby on Rails project, with no need to write or modify code. Use the Swagger UI to interact with your web services API as you build it, and use diffs of Swagger to perform code review of web service changes.
|
346
|
-
|
347
|
-
# Uploading AppMaps
|
348
|
-
|
349
|
-
[https://app.land](https://app.land) can be used to store, analyze, and share AppMaps.
|
20
|
+
# Usage
|
350
21
|
|
351
|
-
|
22
|
+
Visit the [AppMap for Ruby](https://appland.com/docs/reference/appmap-ruby.html) reference page on AppLand.com for a complete reference guide.
|
352
23
|
|
353
24
|
# Development
|
354
25
|
[![Build Status](https://travis-ci.com/applandinc/appmap-ruby.svg?branch=master)](https://travis-ci.com/applandinc/appmap-ruby)
|
data/lib/appmap.rb
CHANGED
@@ -27,7 +27,7 @@ module AppMap
|
|
27
27
|
# Gets the configuration. If there is no configuration, the default
|
28
28
|
# configuration is initialized.
|
29
29
|
def configuration
|
30
|
-
@configuration ||=
|
30
|
+
@configuration ||= initialize_configuration
|
31
31
|
end
|
32
32
|
|
33
33
|
# Sets the configuration. This is only expected to happen once per
|
@@ -38,12 +38,19 @@ module AppMap
|
|
38
38
|
@configuration = config
|
39
39
|
end
|
40
40
|
|
41
|
-
|
41
|
+
def default_config_file_path
|
42
|
+
ENV['APPMAP_CONFIG_FILE'] || 'appmap.yml'
|
43
|
+
end
|
44
|
+
|
45
|
+
# Configures AppMap for recording. Default behavior is to configure from
|
46
|
+
# APPMAP_CONFIG_FILE, or 'appmap.yml'. If no config file is available, a
|
47
|
+
# configuration will be automatically generated and used - and the user is prompted
|
48
|
+
# to create the config file.
|
49
|
+
#
|
42
50
|
# This method also activates the code hooks which record function calls as trace events.
|
43
51
|
# Call this function before the program code is loaded by the Ruby VM, otherwise
|
44
52
|
# the load events won't be seen and the hooks won't activate.
|
45
|
-
def
|
46
|
-
raise "AppMap configuration file #{config_file_path} does not exist" unless ::File.exists?(config_file_path)
|
53
|
+
def initialize_configuration(config_file_path = default_config_file_path)
|
47
54
|
warn "Configuring AppMap from path #{config_file_path}"
|
48
55
|
Config.load_from_file(config_file_path).tap do |configuration|
|
49
56
|
self.configuration = configuration
|
@@ -51,6 +58,14 @@ module AppMap
|
|
51
58
|
end
|
52
59
|
end
|
53
60
|
|
61
|
+
def info(msg)
|
62
|
+
if defined?(::Rails) && defined?(::Rails.logger)
|
63
|
+
::Rails.logger.info msg
|
64
|
+
else
|
65
|
+
warn msg
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
54
69
|
# Used to start tracing, stop tracing, and record events.
|
55
70
|
def tracing
|
56
71
|
@tracing ||= Trace::Tracing.new
|
@@ -97,5 +112,17 @@ module AppMap
|
|
97
112
|
end
|
98
113
|
end
|
99
114
|
|
100
|
-
|
101
|
-
|
115
|
+
if defined?(::Rails::Railtie)
|
116
|
+
require 'appmap/railtie'
|
117
|
+
end
|
118
|
+
|
119
|
+
if defined?(::RSpec)
|
120
|
+
require 'appmap/rspec'
|
121
|
+
end
|
122
|
+
|
123
|
+
# defined?(::Minitest) returns nil...
|
124
|
+
if Gem.loaded_specs['minitest']
|
125
|
+
require 'appmap/minitest'
|
126
|
+
end
|
127
|
+
|
128
|
+
AppMap.initialize_configuration if ENV['APPMAP'] == 'true'
|
data/lib/appmap/config.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'yaml'
|
3
4
|
require 'appmap/handler/net_http'
|
4
5
|
require 'appmap/handler/rails/template'
|
5
6
|
|
@@ -167,8 +168,10 @@ module AppMap
|
|
167
168
|
),
|
168
169
|
package_hooks('actionpack',
|
169
170
|
[
|
170
|
-
method_hook('ActionDispatch::Request::Session', %i[
|
171
|
-
method_hook('ActionDispatch::
|
171
|
+
method_hook('ActionDispatch::Request::Session', %i[[] dig values fetch], %w[http.session.read]),
|
172
|
+
method_hook('ActionDispatch::Request::Session', %i[destroy[]= clear update delete merge], %w[http.session.write]),
|
173
|
+
method_hook('ActionDispatch::Cookies::CookieJar', %i[[]= clear update delete recycle], %w[http.session.read]),
|
174
|
+
method_hook('ActionDispatch::Cookies::CookieJar', %i[[]= clear update delete recycle], %w[http.session.write]),
|
172
175
|
method_hook('ActionDispatch::Cookies::EncryptedCookieJar', %i[[]= clear update delete recycle], %w[http.cookie crypto.encrypt])
|
173
176
|
],
|
174
177
|
package_name: 'action_dispatch'
|
@@ -213,15 +216,22 @@ module AppMap
|
|
213
216
|
# This is happening: Method send_command not found on Net::IMAP
|
214
217
|
# 'Net::IMAP' => TargetMethods.new(:send_command, Package.build_from_path('net/imap', package_name: 'net/imap', labels: %w[protocol.email.imap])),
|
215
218
|
# 'Marshal' => TargetMethods.new(%i[dump load], Package.build_from_path('marshal', labels: %w[format.marshal])),
|
216
|
-
'Psych' =>
|
217
|
-
|
218
|
-
|
219
|
+
'Psych' => [
|
220
|
+
TargetMethods.new(%i[load load_stream parse parse_stream], Package.build_from_path('yaml', package_name: 'psych', labels: %w[format.yaml.parse])),
|
221
|
+
TargetMethods.new(%i[dump dump_stream], Package.build_from_path('yaml', package_name: 'psych', labels: %w[format.yaml.generate])),
|
222
|
+
],
|
223
|
+
'JSON::Ext::Parser' => TargetMethods.new(:parse, Package.build_from_path('json', package_name: 'json', labels: %w[format.json.parse])),
|
224
|
+
'JSON::Ext::Generator::State' => TargetMethods.new(:generate, Package.build_from_path('json', package_name: 'json', labels: %w[format.json.generate])),
|
219
225
|
}.freeze
|
220
226
|
|
221
|
-
attr_reader :name, :packages, :exclude, :hooked_methods, :builtin_hooks
|
227
|
+
attr_reader :name, :appmap_dir, :packages, :exclude, :hooked_methods, :builtin_hooks
|
222
228
|
|
223
|
-
def initialize(name,
|
229
|
+
def initialize(name,
|
230
|
+
packages: [],
|
231
|
+
exclude: [],
|
232
|
+
functions: [])
|
224
233
|
@name = name
|
234
|
+
@appmap_dir = AppMap::DEFAULT_APPMAP_DIR
|
225
235
|
@packages = packages
|
226
236
|
@hook_paths = Set.new(packages.map(&:path))
|
227
237
|
@exclude = exclude
|
@@ -248,38 +258,118 @@ module AppMap
|
|
248
258
|
class << self
|
249
259
|
# Loads configuration data from a file, specified by the file name.
|
250
260
|
def load_from_file(config_file_name)
|
251
|
-
|
252
|
-
|
261
|
+
logo = lambda do
|
262
|
+
Util.color(<<~LOGO, :magenta)
|
263
|
+
___ __ ___
|
264
|
+
/ _ | ___ ___ / |/ /__ ____
|
265
|
+
/ __ |/ _ \\/ _ \\/ /|_/ / _ `/ _ \\
|
266
|
+
/_/ |_/ .__/ .__/_/ /_/\\_,_/ .__/
|
267
|
+
/_/ /_/ /_/
|
268
|
+
LOGO
|
269
|
+
end
|
270
|
+
|
271
|
+
config_present = true if File.exists?(config_file_name)
|
272
|
+
|
273
|
+
config_data = if config_present
|
274
|
+
YAML.safe_load(::File.read(config_file_name))
|
275
|
+
else
|
276
|
+
warn logo.()
|
277
|
+
warn ''
|
278
|
+
warn Util.color(%Q|NOTICE: The AppMap config file #{config_file_name} was not found!|, :magenta, bold: true)
|
279
|
+
warn ''
|
280
|
+
warn Util.color(<<~MISSING_FILE_MSG, :magenta)
|
281
|
+
AppMap uses this file to customize its behavior. For example, you can use
|
282
|
+
the 'packages' setting to indicate which local file paths and dependency
|
283
|
+
gems you want to include in the AppMap. Since you haven't provided specific
|
284
|
+
settings, the appmap gem will try and guess some reasonable defaults.
|
285
|
+
To suppress this message, create the file:
|
286
|
+
|
287
|
+
#{Pathname.new(config_file_name).expand_path}.
|
288
|
+
|
289
|
+
Here are the default settings that will be used in the meantime. You can
|
290
|
+
copy and paste this example to start your appmap.yml.
|
291
|
+
MISSING_FILE_MSG
|
292
|
+
{}
|
293
|
+
end
|
294
|
+
load(config_data).tap do |config|
|
295
|
+
config_yaml = {
|
296
|
+
'name' => config.name,
|
297
|
+
'packages' => config.packages.select{|p| p.path}.map do |pkg|
|
298
|
+
{ 'path' => pkg.path }
|
299
|
+
end,
|
300
|
+
'exclude' => []
|
301
|
+
}.compact
|
302
|
+
unless config_present
|
303
|
+
warn Util.color(YAML.dump(config_yaml), :magenta)
|
304
|
+
warn logo.()
|
305
|
+
end
|
306
|
+
end
|
253
307
|
end
|
254
308
|
|
255
309
|
# Loads configuration from a Hash.
|
256
310
|
def load(config_data)
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
311
|
+
name = config_data['name'] || guess_name
|
312
|
+
config_params = {
|
313
|
+
exclude: config_data['exclude']
|
314
|
+
}.compact
|
315
|
+
|
316
|
+
if config_data['functions']
|
317
|
+
config_params[:functions] = config_data['functions'].map do |function_data|
|
318
|
+
package = function_data['package']
|
319
|
+
cls = function_data['class']
|
320
|
+
functions = function_data['function'] || function_data['functions']
|
321
|
+
raise %q(AppMap config 'function' element should specify 'package', 'class' and 'function' or 'functions') unless package && cls && functions
|
322
|
+
|
323
|
+
functions = Array(functions).map(&:to_sym)
|
324
|
+
labels = function_data['label'] || function_data['labels']
|
325
|
+
labels = Array(labels).map(&:to_s) if labels
|
326
|
+
Function.new(package, cls, labels, functions)
|
327
|
+
end
|
266
328
|
end
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
329
|
+
|
330
|
+
config_params[:packages] = \
|
331
|
+
if config_data['packages']
|
332
|
+
config_data['packages'].map do |package|
|
333
|
+
gem = package['gem']
|
334
|
+
path = package['path']
|
335
|
+
raise %q(AppMap config 'package' element should specify 'gem' or 'path', not both) if gem && path
|
336
|
+
|
337
|
+
if gem
|
338
|
+
shallow = package['shallow']
|
339
|
+
# shallow is true by default for gems
|
340
|
+
shallow = true if shallow.nil?
|
341
|
+
Package.build_from_gem(gem, exclude: package['exclude'] || [], shallow: shallow)
|
342
|
+
else
|
343
|
+
Package.build_from_path(path, exclude: package['exclude'] || [], shallow: package['shallow'])
|
344
|
+
end
|
345
|
+
end.compact
|
277
346
|
else
|
278
|
-
|
347
|
+
Array(guess_paths).map do |path|
|
348
|
+
Package.build_from_path(path)
|
349
|
+
end
|
279
350
|
end
|
280
|
-
|
281
|
-
|
282
|
-
|
351
|
+
|
352
|
+
Config.new name, config_params
|
353
|
+
end
|
354
|
+
|
355
|
+
def guess_name
|
356
|
+
reponame = lambda do
|
357
|
+
next unless File.directory?('.git')
|
358
|
+
|
359
|
+
repo_name = `git config --get remote.origin.url`.strip
|
360
|
+
repo_name.split('/').last.split('.').first unless repo_name == ''
|
361
|
+
end
|
362
|
+
dirname = -> { Dir.pwd.split('/').last }
|
363
|
+
|
364
|
+
reponame.() || dirname.()
|
365
|
+
end
|
366
|
+
|
367
|
+
def guess_paths
|
368
|
+
if defined?(::Rails)
|
369
|
+
%w[app/controllers app/models]
|
370
|
+
elsif File.directory?('lib')
|
371
|
+
%w[lib]
|
372
|
+
end
|
283
373
|
end
|
284
374
|
end
|
285
375
|
|
@@ -289,7 +379,7 @@ module AppMap
|
|
289
379
|
packages: packages.map(&:to_h),
|
290
380
|
functions: @functions.map(&:to_h),
|
291
381
|
exclude: exclude
|
292
|
-
}
|
382
|
+
}.compact
|
293
383
|
end
|
294
384
|
|
295
385
|
# Determines if methods defined in a file path should possibly be hooked.
|
data/lib/appmap/hook.rb
CHANGED
@@ -36,7 +36,7 @@ module AppMap
|
|
36
36
|
|
37
37
|
def initialize(config)
|
38
38
|
@config = config
|
39
|
-
@
|
39
|
+
@trace_enabled = []
|
40
40
|
# Paths that are known to be non-tracing
|
41
41
|
@notrace_paths = Set.new
|
42
42
|
end
|
@@ -47,10 +47,8 @@ module AppMap
|
|
47
47
|
|
48
48
|
hook_builtins
|
49
49
|
|
50
|
-
@trace_begin = TracePoint.new(:class, &method(:trace_class))
|
51
50
|
@trace_end = TracePoint.new(:end, &method(:trace_end))
|
52
|
-
|
53
|
-
@trace_begin.enable(&block)
|
51
|
+
@trace_end.enable(&block)
|
54
52
|
end
|
55
53
|
|
56
54
|
# hook_builtins builds hooks for code that is built in to the Ruby standard library.
|
@@ -96,29 +94,22 @@ module AppMap
|
|
96
94
|
|
97
95
|
protected
|
98
96
|
|
99
|
-
def trace_class(trace_point)
|
100
|
-
path = trace_point.path
|
101
|
-
|
102
|
-
return if @notrace_paths.member?(path)
|
103
|
-
|
104
|
-
if config.path_enabled?(path)
|
105
|
-
location = trace_location(trace_point)
|
106
|
-
warn "Entering hook-enabled location #{location}" if Hook::LOG || Hook::LOG_HOOK
|
107
|
-
@trace_locations << location
|
108
|
-
unless @trace_end.enabled?
|
109
|
-
warn "Enabling hooking" if Hook::LOG || Hook::LOG_HOOK
|
110
|
-
@trace_end.enable
|
111
|
-
end
|
112
|
-
else
|
113
|
-
@notrace_paths << path
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
97
|
def trace_location(trace_point)
|
118
98
|
[ trace_point.path, trace_point.lineno ].join(':')
|
119
99
|
end
|
120
100
|
|
121
101
|
def trace_end(trace_point)
|
102
|
+
location = trace_location(trace_point)
|
103
|
+
warn "Class or module ends at location #{trace_location(trace_point)}" if Hook::LOG || Hook::LOG_HOOK
|
104
|
+
|
105
|
+
path = trace_point.path
|
106
|
+
enabled = !@notrace_paths.member?(path) && config.path_enabled?(path)
|
107
|
+
if !enabled
|
108
|
+
warn "Not hooking - path is not enabled" if Hook::LOG || Hook::LOG_HOOK
|
109
|
+
@notrace_paths << path
|
110
|
+
return
|
111
|
+
end
|
112
|
+
|
122
113
|
cls = trace_point.self
|
123
114
|
|
124
115
|
instance_methods = cls.public_instance_methods(false) - OBJECT_INSTANCE_METHODS
|
@@ -151,7 +142,8 @@ module AppMap
|
|
151
142
|
warn "AppMap: Examining #{hook_cls} #{method.name}" if LOG
|
152
143
|
|
153
144
|
disasm = RubyVM::InstructionSequence.disasm(method)
|
154
|
-
# Skip methods that have no instruction sequence, as they are
|
145
|
+
# Skip methods that have no instruction sequence, as they are either have no body or they are or native.
|
146
|
+
# TODO: Figure out how to tell the difference?
|
155
147
|
next unless disasm
|
156
148
|
|
157
149
|
package = config.lookup_package(hook_cls, method)
|
@@ -170,13 +162,6 @@ module AppMap
|
|
170
162
|
# uninitialized constant Faraday::Connection
|
171
163
|
warn "NameError in #{__FILE__}: #{$!.message}"
|
172
164
|
end
|
173
|
-
|
174
|
-
location = @trace_locations.pop
|
175
|
-
warn "Leaving hook-enabled location #{location}" if Hook::LOG || Hook::LOG_HOOK
|
176
|
-
if @trace_locations.empty?
|
177
|
-
warn "Disabling hooking" if Hook::LOG || Hook::LOG_HOOK
|
178
|
-
@trace_end.disable
|
179
|
-
end
|
180
165
|
end
|
181
166
|
end
|
182
167
|
end
|
data/lib/appmap/minitest.rb
CHANGED
@@ -54,15 +54,21 @@ module AppMap
|
|
54
54
|
|
55
55
|
@recordings_by_test = {}
|
56
56
|
@event_methods = Set.new
|
57
|
+
@recording_count = 0
|
57
58
|
|
58
59
|
class << self
|
59
60
|
def init
|
60
|
-
warn 'Configuring AppMap recorder for Minitest'
|
61
|
-
|
62
61
|
FileUtils.mkdir_p APPMAP_OUTPUT_DIR
|
63
62
|
end
|
64
63
|
|
64
|
+
def first_recording?
|
65
|
+
@recording_count == 0
|
66
|
+
end
|
67
|
+
|
65
68
|
def begin_test(test, name)
|
69
|
+
AppMap.info 'Configuring AppMap recorder for Minitest' if first_recording?
|
70
|
+
@recording_count += 1
|
71
|
+
|
66
72
|
@recordings_by_test[test.object_id] = Recording.new(test, name)
|
67
73
|
end
|
68
74
|
|
data/lib/appmap/railtie.rb
CHANGED
@@ -3,6 +3,13 @@
|
|
3
3
|
module AppMap
|
4
4
|
# Railtie connects the AppMap recorder to Rails-specific features.
|
5
5
|
class Railtie < ::Rails::Railtie
|
6
|
+
initializer 'appmap.remote_recording' do
|
7
|
+
require 'appmap/middleware/remote_recording'
|
8
|
+
Rails.application.config.middleware.insert_after \
|
9
|
+
Rails::Rack::Logger,
|
10
|
+
AppMap::Middleware::RemoteRecording
|
11
|
+
end
|
12
|
+
|
6
13
|
# appmap.subscribe subscribes to ActiveSupport Notifications so that they can be recorded as
|
7
14
|
# AppMap events.
|
8
15
|
initializer 'appmap.subscribe' do |_| # params: app
|
data/lib/appmap/rspec.rb
CHANGED
@@ -139,15 +139,21 @@ module AppMap
|
|
139
139
|
|
140
140
|
@recordings_by_example = {}
|
141
141
|
@event_methods = Set.new
|
142
|
+
@recording_count = 0
|
142
143
|
|
143
144
|
class << self
|
144
145
|
def init
|
145
|
-
warn 'Configuring AppMap recorder for RSpec'
|
146
|
-
|
147
146
|
FileUtils.mkdir_p APPMAP_OUTPUT_DIR
|
148
147
|
end
|
149
148
|
|
149
|
+
def first_recording?
|
150
|
+
@recording_count == 0
|
151
|
+
end
|
152
|
+
|
150
153
|
def begin_spec(example)
|
154
|
+
AppMap.info 'Configuring AppMap recorder for RSpec' if first_recording?
|
155
|
+
@recording_count += 1
|
156
|
+
|
151
157
|
@recordings_by_example[example.object_id] = Recording.new(example)
|
152
158
|
end
|
153
159
|
|
data/lib/appmap/util.rb
CHANGED
@@ -4,6 +4,21 @@ require 'bundler'
|
|
4
4
|
|
5
5
|
module AppMap
|
6
6
|
module Util
|
7
|
+
# https://wynnnetherland.com/journal/a-stylesheet-author-s-guide-to-terminal-colors/
|
8
|
+
# Embed in a String to clear all previous ANSI sequences.
|
9
|
+
CLEAR = "\e[0m"
|
10
|
+
BOLD = "\e[1m"
|
11
|
+
|
12
|
+
# Colors
|
13
|
+
BLACK = "\e[30m"
|
14
|
+
RED = "\e[31m"
|
15
|
+
GREEN = "\e[32m"
|
16
|
+
YELLOW = "\e[33m"
|
17
|
+
BLUE = "\e[34m"
|
18
|
+
MAGENTA = "\e[35m"
|
19
|
+
CYAN = "\e[36m"
|
20
|
+
WHITE = "\e[37m"
|
21
|
+
|
7
22
|
class << self
|
8
23
|
# scenario_filename builds a suitable file name from a scenario name.
|
9
24
|
# Special characters are removed, and the file name is truncated to fit within
|
@@ -128,6 +143,12 @@ module AppMap
|
|
128
143
|
FileUtils.mv tempfile.path, filename
|
129
144
|
end
|
130
145
|
end
|
146
|
+
|
147
|
+
def color(text, color, bold: false)
|
148
|
+
color = Util.const_get(color.to_s.upcase) if color.is_a?(Symbol)
|
149
|
+
bold = bold ? BOLD : ""
|
150
|
+
"#{bold}#{color}#{text}#{CLEAR}"
|
151
|
+
end
|
131
152
|
end
|
132
153
|
end
|
133
154
|
end
|
data/lib/appmap/version.rb
CHANGED
@@ -1,9 +1,30 @@
|
|
1
1
|
require 'rails_spec_helper'
|
2
2
|
|
3
3
|
describe 'Rails' do
|
4
|
+
shared_context 'rails integration test setup' do
|
5
|
+
def tmpdir
|
6
|
+
'tmp/spec/AbstractControllerBase'
|
7
|
+
end
|
8
|
+
|
9
|
+
unless use_existing_data?
|
10
|
+
before(:all) do
|
11
|
+
FileUtils.rm_rf tmpdir
|
12
|
+
FileUtils.mkdir_p tmpdir
|
13
|
+
run_spec 'spec/controllers/users_controller_spec.rb'
|
14
|
+
run_spec 'spec/controllers/users_controller_api_spec.rb'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:appmap) { JSON.parse File.read File.join tmpdir, 'appmap/rspec', appmap_json_file }
|
19
|
+
let(:appmap_json_path) { File.join(tmpdir, 'appmap/rspec', appmap_json_file) }
|
20
|
+
let(:appmap) { JSON.parse File.read(appmap_json_path) }
|
21
|
+
let(:events) { appmap['events'] }
|
22
|
+
end
|
23
|
+
|
4
24
|
%w[5 6].each do |rails_major_version| # rubocop:disable Metrics/BlockLength
|
5
25
|
context "#{rails_major_version}" do
|
6
26
|
include_context 'Rails app pg database', "spec/fixtures/rails#{rails_major_version}_users_app" unless use_existing_data?
|
27
|
+
include_context 'rails integration test setup'
|
7
28
|
|
8
29
|
def run_spec(spec_name)
|
9
30
|
cmd = <<~CMD.gsub "\n", ' '
|
@@ -13,24 +34,6 @@ describe 'Rails' do
|
|
13
34
|
run_cmd cmd, chdir: fixture_dir
|
14
35
|
end
|
15
36
|
|
16
|
-
def tmpdir
|
17
|
-
'tmp/spec/AbstractControllerBase'
|
18
|
-
end
|
19
|
-
|
20
|
-
unless use_existing_data?
|
21
|
-
before(:all) do
|
22
|
-
FileUtils.rm_rf tmpdir
|
23
|
-
FileUtils.mkdir_p tmpdir
|
24
|
-
run_spec 'spec/controllers/users_controller_spec.rb'
|
25
|
-
run_spec 'spec/controllers/users_controller_api_spec.rb'
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
let(:appmap) { JSON.parse File.read File.join tmpdir, 'appmap/rspec', appmap_json_file }
|
30
|
-
let(:appmap_json_path) { File.join(tmpdir, 'appmap/rspec', appmap_json_file) }
|
31
|
-
let(:appmap) { JSON.parse File.read(appmap_json_path) }
|
32
|
-
let(:events) { appmap['events'] }
|
33
|
-
|
34
37
|
describe 'an API route' do
|
35
38
|
describe 'creating an object' do
|
36
39
|
let(:appmap_json_file) do
|
@@ -253,4 +256,40 @@ describe 'Rails' do
|
|
253
256
|
end
|
254
257
|
end
|
255
258
|
end
|
259
|
+
|
260
|
+
describe 'with default appmap.yml' do
|
261
|
+
include_context 'Rails app pg database', "spec/fixtures/rails5_users_app" unless use_existing_data?
|
262
|
+
include_context 'rails integration test setup'
|
263
|
+
|
264
|
+
def run_spec(spec_name)
|
265
|
+
cmd = <<~CMD.gsub "\n", ' '
|
266
|
+
docker-compose run --rm -e RAILS_ENV=test -e APPMAP=true -e APPMAP_CONFIG_FILE=no/such/file
|
267
|
+
-v #{File.absolute_path tmpdir}:/app/tmp app ./bin/rspec #{spec_name}
|
268
|
+
CMD
|
269
|
+
run_cmd cmd, chdir: fixture_dir
|
270
|
+
end
|
271
|
+
|
272
|
+
let(:appmap_json_file) do
|
273
|
+
'Api_UsersController_POST_api_users_with_required_parameters_creates_a_user.appmap.json'
|
274
|
+
end
|
275
|
+
|
276
|
+
it 'http_server_request is recorded' do
|
277
|
+
expect(events).to include(
|
278
|
+
hash_including(
|
279
|
+
'http_server_request' => hash_including(
|
280
|
+
'request_method' => 'POST',
|
281
|
+
'path_info' => '/api/users'
|
282
|
+
)
|
283
|
+
)
|
284
|
+
)
|
285
|
+
end
|
286
|
+
|
287
|
+
it 'controller method is recorded' do
|
288
|
+
expect(events).to include hash_including(
|
289
|
+
'defined_class' => 'Api::UsersController',
|
290
|
+
'method_id' => 'build_user',
|
291
|
+
'path' => 'app/controllers/api/users_controller.rb',
|
292
|
+
)
|
293
|
+
end
|
294
|
+
end
|
256
295
|
end
|
data/spec/config_spec.rb
CHANGED
@@ -55,4 +55,25 @@ describe AppMap::Config, docker: false do
|
|
55
55
|
|
56
56
|
expect(config.to_h.deep_stringify_keys!).to eq(config_expectation)
|
57
57
|
end
|
58
|
+
|
59
|
+
context do
|
60
|
+
let(:warnings) { @warnings ||= [] }
|
61
|
+
let(:warning) { warnings.join }
|
62
|
+
before do
|
63
|
+
expect(AppMap::Config).to receive(:warn).at_least(1) { |msg| warnings << msg }
|
64
|
+
end
|
65
|
+
it 'prints a warning and uses a default config' do
|
66
|
+
config = AppMap::Config.load_from_file 'no/such/file'
|
67
|
+
expect(config.to_h).to eq(YAML.load(<<~CONFIG))
|
68
|
+
:name: appmap-ruby
|
69
|
+
:packages:
|
70
|
+
- :path: lib
|
71
|
+
:handler_class: AppMap::Handler::Function
|
72
|
+
:shallow: false
|
73
|
+
:functions: []
|
74
|
+
:exclude: []
|
75
|
+
CONFIG
|
76
|
+
expect(warning).to include('NOTICE: The AppMap config file no/such/file was not found!')
|
77
|
+
end
|
78
|
+
end
|
58
79
|
end
|
@@ -21,14 +21,6 @@ when 'activerecord'
|
|
21
21
|
require 'database_cleaner-active_record' if Rails.env.test?
|
22
22
|
end
|
23
23
|
|
24
|
-
require 'appmap/railtie' if defined?(AppMap)
|
25
|
-
|
26
|
-
# require "active_storage/engine"
|
27
|
-
# require "action_mailer/railtie"
|
28
|
-
# require "action_cable/engine"
|
29
|
-
# require "sprockets/railtie"
|
30
|
-
# require "rails/test_unit/railtie"
|
31
|
-
|
32
24
|
# Require the gems listed in Gemfile, including any gems
|
33
25
|
# you've limited to :test, :development, or :production.
|
34
26
|
Bundler.require(*Rails.groups)
|
@@ -7,8 +7,6 @@ abort("The Rails environment is running in production mode!") if Rails.env.produ
|
|
7
7
|
require 'rspec/rails'
|
8
8
|
# Add additional requires below this line. Rails is not loaded until this point!
|
9
9
|
|
10
|
-
require 'appmap/rspec'
|
11
|
-
|
12
10
|
# Requires supporting ruby files with custom matchers and macros, etc, in
|
13
11
|
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
|
14
12
|
# run as spec files by default. This means that files in spec/support that end
|
@@ -21,14 +21,6 @@ when 'activerecord'
|
|
21
21
|
require 'database_cleaner-active_record' if Rails.env.test?
|
22
22
|
end
|
23
23
|
|
24
|
-
require 'appmap/railtie' if defined?(AppMap)
|
25
|
-
|
26
|
-
# require "active_storage/engine"
|
27
|
-
# require "action_mailer/railtie"
|
28
|
-
# require "action_cable/engine"
|
29
|
-
# require "sprockets/railtie"
|
30
|
-
# require "rails/test_unit/railtie"
|
31
|
-
|
32
24
|
# Require the gems listed in Gemfile, including any gems
|
33
25
|
# you've limited to :test, :development, or :production.
|
34
26
|
Bundler.require(*Rails.groups)
|
@@ -7,8 +7,6 @@ abort("The Rails environment is running in production mode!") if Rails.env.produ
|
|
7
7
|
require 'rspec/rails'
|
8
8
|
# Add additional requires below this line. Rails is not loaded until this point!
|
9
9
|
|
10
|
-
require 'appmap/rspec'
|
11
|
-
|
12
10
|
# Requires supporting ruby files with custom matchers and macros, etc, in
|
13
11
|
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
|
14
12
|
# run as spec files by default. This means that files in spec/support that end
|
data/spec/hook_spec.rb
CHANGED
@@ -21,7 +21,7 @@ describe 'AppMap class Hooking', docker: false do
|
|
21
21
|
def invoke_test_file(file, setup: nil, &block)
|
22
22
|
AppMap.configuration = nil
|
23
23
|
package = AppMap::Config::Package.build_from_path(file)
|
24
|
-
config = AppMap::Config.new('hook_spec', [ package ])
|
24
|
+
config = AppMap::Config.new('hook_spec', packages: [ package ])
|
25
25
|
AppMap.configuration = config
|
26
26
|
tracer = nil
|
27
27
|
AppMap::Hook.new(config).enable do
|
@@ -57,7 +57,7 @@ describe 'AppMap class Hooking', docker: false do
|
|
57
57
|
it 'excludes named classes and methods' do
|
58
58
|
load 'spec/fixtures/hook/exclude.rb'
|
59
59
|
package = AppMap::Config::Package.build_from_path('spec/fixtures/hook/exclude.rb')
|
60
|
-
config = AppMap::Config.new('hook_spec', [ package ], exclude: %w[ExcludeTest])
|
60
|
+
config = AppMap::Config.new('hook_spec', packages: [ package ], exclude: %w[ExcludeTest])
|
61
61
|
AppMap.configuration = config
|
62
62
|
|
63
63
|
expect(config.never_hook?(ExcludeTest, ExcludeTest.new.method(:instance_method))).to be_truthy
|
@@ -62,7 +62,7 @@ describe 'Net::HTTP handler' do
|
|
62
62
|
end
|
63
63
|
|
64
64
|
context 'with trace enabled' do
|
65
|
-
let(:configuration) { AppMap::Config.new('record_net_http_spec'
|
65
|
+
let(:configuration) { AppMap::Config.new('record_net_http_spec') }
|
66
66
|
|
67
67
|
after do
|
68
68
|
AppMap.configuration = nil
|
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.
|
4
|
+
version: 0.51.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Gilpin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-06-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -455,7 +455,6 @@ files:
|
|
455
455
|
- spec/fixtures/rails5_users_app/config/initializers/filter_parameter_logging.rb
|
456
456
|
- spec/fixtures/rails5_users_app/config/initializers/inflections.rb
|
457
457
|
- spec/fixtures/rails5_users_app/config/initializers/mime_types.rb
|
458
|
-
- spec/fixtures/rails5_users_app/config/initializers/record_button.rb
|
459
458
|
- spec/fixtures/rails5_users_app/config/initializers/wrap_parameters.rb
|
460
459
|
- spec/fixtures/rails5_users_app/config/locales/en.yml
|
461
460
|
- spec/fixtures/rails5_users_app/config/routes.rb
|
@@ -527,7 +526,6 @@ files:
|
|
527
526
|
- spec/fixtures/rails6_users_app/config/initializers/filter_parameter_logging.rb
|
528
527
|
- spec/fixtures/rails6_users_app/config/initializers/inflections.rb
|
529
528
|
- spec/fixtures/rails6_users_app/config/initializers/mime_types.rb
|
530
|
-
- spec/fixtures/rails6_users_app/config/initializers/record_button.rb
|
531
529
|
- spec/fixtures/rails6_users_app/config/initializers/wrap_parameters.rb
|
532
530
|
- spec/fixtures/rails6_users_app/config/locales/en.yml
|
533
531
|
- spec/fixtures/rails6_users_app/config/routes.rb
|