appmap 0.38.1 → 0.41.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +5 -1
  3. data/.travis.yml +2 -23
  4. data/CHANGELOG.md +26 -1
  5. data/CONTRIBUTING.md +22 -0
  6. data/README.md +119 -53
  7. data/Rakefile +3 -3
  8. data/lib/appmap/class_map.rb +25 -8
  9. data/lib/appmap/config.rb +41 -21
  10. data/lib/appmap/event.rb +14 -4
  11. data/lib/appmap/hook.rb +18 -3
  12. data/lib/appmap/rails/request_handler.rb +17 -3
  13. data/lib/appmap/railtie.rb +1 -5
  14. data/lib/appmap/version.rb +2 -2
  15. data/spec/abstract_controller_base_spec.rb +116 -86
  16. data/spec/config_spec.rb +1 -0
  17. data/spec/fixtures/hook/exclude.rb +15 -0
  18. data/spec/fixtures/hook/labels.rb +6 -0
  19. data/spec/fixtures/rails5_users_app/Gemfile +2 -3
  20. data/spec/fixtures/rails5_users_app/app/controllers/users_controller.rb +8 -0
  21. data/spec/fixtures/rails5_users_app/appmap.yml +4 -1
  22. data/spec/fixtures/rails5_users_app/config/application.rb +2 -0
  23. data/spec/fixtures/rails5_users_app/config/routes.rb +1 -1
  24. data/spec/fixtures/rails5_users_app/spec/controllers/users_controller_spec.rb +11 -0
  25. data/spec/fixtures/rails6_users_app/Gemfile +2 -3
  26. data/spec/fixtures/rails6_users_app/app/controllers/users_controller.rb +8 -0
  27. data/spec/fixtures/rails6_users_app/appmap.yml +4 -1
  28. data/spec/fixtures/rails6_users_app/config/application.rb +2 -0
  29. data/spec/fixtures/rails6_users_app/config/routes.rb +1 -1
  30. data/spec/fixtures/rails6_users_app/spec/controllers/users_controller_spec.rb +11 -0
  31. data/spec/hook_spec.rb +41 -41
  32. data/spec/rails_spec_helper.rb +2 -2
  33. data/spec/record_sql_rails_pg_spec.rb +1 -1
  34. data/spec/rspec_feature_metadata_spec.rb +1 -1
  35. data/spec/spec_helper.rb +1 -0
  36. data/test/fixtures/gem_test/appmap.yml +1 -1
  37. data/test/fixtures/gem_test/test/parser_test.rb +12 -0
  38. data/test/gem_test.rb +4 -4
  39. metadata +6 -69
  40. data/spec/abstract_controller4_base_spec.rb +0 -66
  41. data/spec/fixtures/rails4_users_app/.gitignore +0 -13
  42. data/spec/fixtures/rails4_users_app/.rbenv-gemsets +0 -2
  43. data/spec/fixtures/rails4_users_app/.ruby-version +0 -1
  44. data/spec/fixtures/rails4_users_app/Dockerfile +0 -30
  45. data/spec/fixtures/rails4_users_app/Dockerfile.pg +0 -3
  46. data/spec/fixtures/rails4_users_app/Gemfile +0 -77
  47. data/spec/fixtures/rails4_users_app/README.rdoc +0 -28
  48. data/spec/fixtures/rails4_users_app/Rakefile +0 -6
  49. data/spec/fixtures/rails4_users_app/app/assets/images/.keep +0 -0
  50. data/spec/fixtures/rails4_users_app/app/assets/javascripts/application.js +0 -16
  51. data/spec/fixtures/rails4_users_app/app/assets/stylesheets/application.css +0 -15
  52. data/spec/fixtures/rails4_users_app/app/controllers/api/users_controller.rb +0 -27
  53. data/spec/fixtures/rails4_users_app/app/controllers/application_controller.rb +0 -5
  54. data/spec/fixtures/rails4_users_app/app/controllers/concerns/.keep +0 -0
  55. data/spec/fixtures/rails4_users_app/app/controllers/health_controller.rb +0 -5
  56. data/spec/fixtures/rails4_users_app/app/controllers/users_controller.rb +0 -5
  57. data/spec/fixtures/rails4_users_app/app/helpers/application_helper.rb +0 -2
  58. data/spec/fixtures/rails4_users_app/app/mailers/.keep +0 -0
  59. data/spec/fixtures/rails4_users_app/app/models/.keep +0 -0
  60. data/spec/fixtures/rails4_users_app/app/models/concerns/.keep +0 -0
  61. data/spec/fixtures/rails4_users_app/app/models/user.rb +0 -18
  62. data/spec/fixtures/rails4_users_app/app/views/layouts/application.html.haml +0 -7
  63. data/spec/fixtures/rails4_users_app/app/views/users/index.html.haml +0 -7
  64. data/spec/fixtures/rails4_users_app/appmap.yml +0 -3
  65. data/spec/fixtures/rails4_users_app/bin/rails +0 -9
  66. data/spec/fixtures/rails4_users_app/bin/setup +0 -29
  67. data/spec/fixtures/rails4_users_app/bin/spring +0 -17
  68. data/spec/fixtures/rails4_users_app/config.ru +0 -4
  69. data/spec/fixtures/rails4_users_app/config/application.rb +0 -26
  70. data/spec/fixtures/rails4_users_app/config/boot.rb +0 -3
  71. data/spec/fixtures/rails4_users_app/config/database.yml +0 -18
  72. data/spec/fixtures/rails4_users_app/config/environment.rb +0 -5
  73. data/spec/fixtures/rails4_users_app/config/environments/development.rb +0 -41
  74. data/spec/fixtures/rails4_users_app/config/environments/production.rb +0 -79
  75. data/spec/fixtures/rails4_users_app/config/environments/test.rb +0 -42
  76. data/spec/fixtures/rails4_users_app/config/initializers/assets.rb +0 -11
  77. data/spec/fixtures/rails4_users_app/config/initializers/backtrace_silencers.rb +0 -7
  78. data/spec/fixtures/rails4_users_app/config/initializers/cookies_serializer.rb +0 -3
  79. data/spec/fixtures/rails4_users_app/config/initializers/filter_parameter_logging.rb +0 -4
  80. data/spec/fixtures/rails4_users_app/config/initializers/inflections.rb +0 -16
  81. data/spec/fixtures/rails4_users_app/config/initializers/mime_types.rb +0 -4
  82. data/spec/fixtures/rails4_users_app/config/initializers/session_store.rb +0 -3
  83. data/spec/fixtures/rails4_users_app/config/initializers/to_time_preserves_timezone.rb +0 -10
  84. data/spec/fixtures/rails4_users_app/config/initializers/wrap_parameters.rb +0 -14
  85. data/spec/fixtures/rails4_users_app/config/locales/en.yml +0 -23
  86. data/spec/fixtures/rails4_users_app/config/routes.rb +0 -12
  87. data/spec/fixtures/rails4_users_app/config/secrets.yml +0 -22
  88. data/spec/fixtures/rails4_users_app/create_app +0 -23
  89. data/spec/fixtures/rails4_users_app/db/migrate/20191127112304_create_users.rb +0 -10
  90. data/spec/fixtures/rails4_users_app/db/schema.rb +0 -26
  91. data/spec/fixtures/rails4_users_app/db/seeds.rb +0 -7
  92. data/spec/fixtures/rails4_users_app/docker-compose.yml +0 -26
  93. data/spec/fixtures/rails4_users_app/lib/assets/.keep +0 -0
  94. data/spec/fixtures/rails4_users_app/lib/tasks/.keep +0 -0
  95. data/spec/fixtures/rails4_users_app/log/.keep +0 -0
  96. data/spec/fixtures/rails4_users_app/public/404.html +0 -67
  97. data/spec/fixtures/rails4_users_app/public/422.html +0 -67
  98. data/spec/fixtures/rails4_users_app/public/500.html +0 -66
  99. data/spec/fixtures/rails4_users_app/public/favicon.ico +0 -0
  100. data/spec/fixtures/rails4_users_app/public/robots.txt +0 -5
  101. data/spec/fixtures/rails4_users_app/spec/controllers/users_controller_api_spec.rb +0 -49
  102. data/spec/fixtures/rails4_users_app/spec/rails_helper.rb +0 -95
  103. data/spec/fixtures/rails4_users_app/spec/spec_helper.rb +0 -96
  104. data/spec/fixtures/rails4_users_app/test/fixtures/users.yml +0 -9
  105. data/spec/record_sql_rails4_pg_spec.rb +0 -75
  106. data/test/fixtures/gem_test/test/to_param_test.rb +0 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0255347aa61c6f39bfec0f43a78b3cc3060bd20e4f80f1e39e0ff3714a52dff3
4
- data.tar.gz: 822bc2fe118426d6d9c9437c85ead8e603a446cabd6bd49d0053c2b1cfaf3789
3
+ metadata.gz: 75523ebe41aa8e327db7ff2acc4fa20bf1283474b97baf6610e11292bb1abb8b
4
+ data.tar.gz: 1c0293cf928ff1f6615d7f0a72a6ba7a03acdee04d00065ffc4a0eb41e0192ad
5
5
  SHA512:
6
- metadata.gz: 031534a5eb015fa99d6ad161665b131677cadbe41ed1bce20357cb1ded7ba19e5f0bcbe37cfef0c8ad35cc2904fe83e4cc9d2b12d04260b970d24cc9aea64ba3
7
- data.tar.gz: e7996262f4da21936567c1238df624220987ed04bf5aebd9a525da4d3f181ca752c1060056a5bb41b52c9cdb29e958cf7335973ac7076113278c7e8583755477
6
+ metadata.gz: c0a39d8067f455a1c0179c65a7f17ffd041de405bc3c48be567970e2b987765216a33801e7c486c6aeee66cae5c2291f91196c3132bd9ad65d147617f6282468
7
+ data.tar.gz: bdc24d37f171945127c2ff67c834fa55932c019dbbe5e74a2f1625d11b12ca881e6a2d0c6419c0ffe625bba3295b5ef2ef1e96d6256f152ca7fbaa3d2a99b52d
data/.rubocop.yml CHANGED
@@ -4,6 +4,9 @@ AllCops:
4
4
  Layout/CaseIndentation:
5
5
  EnforcedStyle: end
6
6
 
7
+ Layout/FirstArgumentIndentation:
8
+ EnforcedStyle: consistent
9
+
7
10
  Layout/SpaceInsideArrayLiteralBrackets:
8
11
  Enabled: false
9
12
 
@@ -17,13 +20,14 @@ Layout/LineLength:
17
20
  Metrics/BlockLength:
18
21
  ExcludedMethods:
19
22
  - it
23
+ - context
20
24
 
21
25
  Style/MultilineBlockChain:
22
26
  Enabled: false
23
27
 
24
28
  Style/NumericPredicate:
25
29
  Enabled: false
26
-
30
+
27
31
  Style/AndOr:
28
32
  Enabled: false
29
33
 
data/.travis.yml CHANGED
@@ -16,29 +16,8 @@ before_script:
16
16
 
17
17
  jobs:
18
18
  include:
19
- - stage: minitest
19
+ - stage: test
20
20
  script:
21
21
  - mkdir tmp
22
- - bundle exec rake minitest
23
-
24
- - stage: base
25
- script:
26
- - bundle exec rake build:base:2.5
27
- - stage: base
28
- script:
29
- - bundle exec rake build:base:2.6
30
-
31
- - stage: fixtures
32
- script:
33
- - bundle exec rake build:fixtures:2.5:all
34
- - stage: fixtures
35
- script:
36
- - bundle exec rake build:fixtures:2.6:all
37
-
38
- - stage: spec
39
- script:
40
- - bundle exec rake spec:2.5
41
- - stage: spec
42
- script:
43
- - bundle exec rake spec:2.6
22
+ - bundle exec rake test
44
23
 
data/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
- # v0.38.1
1
+ # v0.41.1
2
+
3
+ * Make best effort to ensure that class name is not `null` in the appmap.json.
4
+ * Don't try and instrument gems which are a dependency of the this gem.
5
+ * Fix a nil exception when applying the exclude list to builtins.
6
+
7
+ # v0.41.0
8
+
9
+ * Adjust some label names to match `provider.*`, `format.*`.
10
+ * Add global `exclude` list to *appmap.yml* which can be used to definitively exclude specific classes and methods.
11
+
12
+ # v0.40.0
2
13
 
14
+ * Parse source code comments into function labels.
15
+
16
+ # v0.39.2
17
+ * Correctly recognize normalized path info for subengines.
18
+
19
+ # v0.39.1
20
+ * Support Ruby 2.7.
21
+ * Remove support for Rails 4.
22
+ * Stop recommending `-t appmap` argument for `rspec`.
23
+
24
+ # v0.39.0
25
+ * Recognize and record `normalized_path_info` in Rails applications, per 1.4 AppMap format version.
26
+
27
+ # v0.38.1
3
28
  * Package configuration can be `shallow`, in case which only the initial entry into the package is recorded.
4
29
 
5
30
  # v0.37.2
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,22 @@
1
+ # Contributing to appmap-ruby
2
+
3
+ We are incredibly thankful for the contributions we receive from the community. Before contributing, please take a moment to read our [Contributor License Agreement](https://github.com/applandorg/community/blob/master/docs/CLA%20Instructions.pdf) and our [Code of Conduct](https://github.com/applandorg/community/blob/master/docs/Code%20of%20Conduct%20for%20Contributors.pdf).
4
+
5
+ ## Contributor License Agreement
6
+ We require our external contributors to sign a Contributor License Agreement ("CLA") in order to ensure that
7
+ our projects remain licensed under Free and Open Source licenses such as while allowing
8
+ Appland to build a sustainable business.
9
+
10
+ AppLand is committed to having a true Free and Open Source Software license for our
11
+ non-commercial software. A CLA enables AppLand to safely commercialize our products while
12
+ keeping a standard FOSS license with all the rights that license grants to users.
13
+
14
+ * [Contributor License Agreement](https://github.com/applandorg/community/blob/master/docs/CLA%20Instructions.pdf)
15
+
16
+
17
+ ## Code of Conduct
18
+
19
+ We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and
20
+ healthy community.
21
+
22
+ * [Code of Conduct](https://github.com/applandorg/community/blob/master/docs/Code%20of%20Conduct%20for%20Contributors.pdf)
data/README.md CHANGED
@@ -1,13 +1,16 @@
1
1
 
2
2
  - [About](#about)
3
+ - [Supported versions](#supported-versions)
3
4
  - [Installation](#installation)
4
5
  - [Configuration](#configuration)
6
+ - [Labels](#labels)
5
7
  - [Running](#running)
6
8
  - [RSpec](#rspec)
7
9
  - [Minitest](#minitest)
8
10
  - [Cucumber](#cucumber)
9
11
  - [Remote recording](#remote-recording)
10
- - [Ruby on Rails](#ruby-on-rails)
12
+ - [Server process recording](#server-process-recording)
13
+ - [AppMap for VSCode](#appmap-for-vscode)
11
14
  - [Uploading AppMaps](#uploading-appmaps)
12
15
  - [Development](#development)
13
16
  - [Running tests](#running-tests)
@@ -23,41 +26,51 @@
23
26
  "AppMap" is a data format which records code structure (modules, classes, and methods), code execution events
24
27
  (function calls and returns), and code metadata (repo name, repo URL, commit
25
28
  SHA, labels, etc). It's more granular than a performance profile, but it's less
26
- granular than a full debug trace. It's designed to be optimal for understanding the design intent and behavior of code.
29
+ 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.
27
30
 
28
31
  There are several ways to record AppMaps of your Ruby program using the `appmap` gem:
29
32
 
30
- * Run your RSpec tests with the environment variable `APPMAP=true`. An AppMap will be generated for each spec.
33
+ * Run your tests (RSpec, Minitest, Cucumber) with the environment variable `APPMAP=true`. An AppMap will be generated for each spec.
31
34
  * Run your application server with AppMap remote recording enabled, and use the [AppLand
32
35
  browser extension](https://github.com/applandinc/appland-browser-extension) to start,
33
36
  stop, and upload recordings.
34
- * Run the command `appmap record <program>` to record the entire execution of a program.
37
+ * Wrap some code in an `AppMap.record` block, which returns JSON containing the code execution trace.
35
38
 
36
- Once you have recorded some AppMaps (for example, by running RSpec tests), you use the `appland upload` command
37
- to upload them to the AppLand server. This command, and some others, is provided
38
- by the [AppLand CLI](https://github.com/applandinc/appland-cli/releases).
39
- Then, on the [AppLand website](https://app.land), you can
40
- visualize the design of your code and share links with collaborators.
39
+ Once you have made a recording, there are two ways to view automatically generated diagrams of the AppMaps.
40
+
41
+ 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).
42
+
43
+ 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).
44
+
45
+ ### Supported versions
46
+
47
+ * Ruby 2.5, 2.6, 2.7
48
+ * Rails 5, 6
49
+
50
+ Support for new versions is added frequently, please check back regularly for updates.
41
51
 
42
52
  # Installation
43
53
 
44
- Add `gem 'appmap'` to your Gemfile just as you would any other dependency.
54
+ <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>
45
55
 
46
- **Global installation**
56
+
57
+ 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:
47
58
 
48
59
  ```
49
- gem 'appmap'
50
- ```
60
+ source 'https://rubygems.org'
61
+ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
51
62
 
52
- **Install in test, development groups**
63
+ # Optional rubRuby version
64
+ # ruby '2.7.2'
53
65
 
54
- ```
55
66
  group :development, :test do
56
67
  gem 'appmap'
57
68
  end
58
69
  ```
59
70
 
60
- Then install with `bundle`.
71
+ Install with `bundle install`, as usual.
72
+
73
+ 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*.
61
74
 
62
75
  **Railtie**
63
76
 
@@ -65,7 +78,8 @@ If you are using Ruby on Rails, require the railtie after Rails is loaded.
65
78
 
66
79
  ```
67
80
  # application.rb is a good place to do this, along with all the other railties.
68
- require 'appmap/railtie'
81
+ # Don't require the railtie in environments that don't bundle the appmap gem.
82
+ require 'appmap/railtie' if defined?(AppMap).
69
83
  ```
70
84
 
71
85
  # Configuration
@@ -74,15 +88,28 @@ When you run your program, the `appmap` gem reads configuration settings from `a
74
88
  file for a typical Rails project:
75
89
 
76
90
  ```yaml
77
- name: MyProject
91
+ # 'name' should generally be the same as the code repo name.
92
+ name: my_project
78
93
  packages:
79
94
  - path: app/controllers
80
95
  - path: app/models
96
+ - path: app/jobs
97
+ - path: app/helpers
98
+ # Include the gems that you want to see in the dependency maps.
99
+ # These are just examples.
81
100
  - gem: activerecord
101
+ - gem: devise
102
+ - gem: aws-sdk
103
+ - gem: will_paginate
104
+ exclude:
105
+ - MyClass
106
+ - MyClass#my_instance_method
107
+ - MyClass.my_class_method
82
108
  ```
83
109
 
84
110
  * **name** Provides the project name (required)
85
- * **packages** A list of source code directories which should be instrumented.
111
+ * **packages** A list of source code directories which should be recorded.
112
+ * **exclude** A list of classes and/or methods to definitively exclude from recording.
86
113
 
87
114
  **packages**
88
115
 
@@ -90,13 +117,46 @@ Each entry in the `packages` list is a YAML object which has the following keys:
90
117
 
91
118
  * **path** The path to the source code directory. The path may be relative to the current working directory, or it may
92
119
  be an absolute path.
93
- * **gem** As an alternative to specifying the path, specify the name of a dependency gem. When using `gem`, don't specify `path`.
120
+ * **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*.
94
121
  * **exclude** A list of files and directories which will be ignored. By default, all modules, classes and public
95
- functions are inspected.
122
+ functions are inspected. See also: global `exclude` list.
96
123
  * **shallow** When set to `true`, only the first function call entry into a package will be recorded. Subsequent function calls within
97
124
  the same package are not recorded unless code execution leaves the package and re-enters it. Default: `true` when using `gem`,
98
125
  `false` when using `path`.
99
126
 
127
+ **exclude**
128
+
129
+ Optional list of fully qualified class and method names. Separate class and method names with period (`.`) for class methods and hash (`#`) for instance methods.
130
+
131
+
132
+ # Labels
133
+
134
+ 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.
135
+
136
+ 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.
137
+
138
+ For example, if you add this comment to your source code:
139
+
140
+ ```ruby
141
+ class ApiKey
142
+ # @labels provider.authentication security
143
+ def authenticate(key)
144
+ # logic to verify the key here...
145
+ end
146
+ end
147
+ ```
148
+
149
+ Then the AppMap metadata section for this function will include:
150
+
151
+ ```json
152
+ {
153
+ "name": "authenticate",
154
+ "type": "function",
155
+ "labels": [ "provider.authentication", "security" ]
156
+ }
157
+ ```
158
+
159
+
100
160
  # Running
101
161
 
102
162
  ## RSpec
@@ -122,13 +182,10 @@ require 'appmap/rspec'
122
182
  require File.expand_path("../../config/environment", __FILE__)
123
183
  ```
124
184
 
125
- 2) *Optional* Add `feature: '<feature name>'` and `feature_group: '<feature group name>'` annotations to your
126
- examples.
127
-
128
- 3) Run the tests with the environment variable `APPMAP=true`:
185
+ 2) Run the tests with the environment variable `APPMAP=true`:
129
186
 
130
187
  ```sh-session
131
- $ APPMAP=true bundle exec rspec -t appmap
188
+ $ APPMAP=true bundle exec rspec
132
189
  ```
133
190
 
134
191
  Each RSpec test will output an AppMap file into the directory `tmp/appmap/rspec`. For example:
@@ -138,23 +195,6 @@ $ find tmp/appmap/rspec
138
195
  Hello_says_hello_when_prompted.appmap.json
139
196
  ```
140
197
 
141
- If you include the `feature` and `feature_group` metadata, these attributes will be exported to the AppMap file in the
142
- `metadata` section. It will look something like this:
143
-
144
- ```json
145
- {
146
- ...
147
- "metadata": {
148
- "name": "Hello app says hello when prompted",
149
- "feature": "Hello app says hello",
150
- "feature_group": "Hello"
151
- },
152
- ...
153
- }
154
- ```
155
-
156
- If you don't explicitly declare `feature` and `feature_group`, then they will be inferred from the spec name and example descriptions.
157
-
158
198
  ## Minitest
159
199
 
160
200
  To record Minitest tests, follow these additional steps:
@@ -171,17 +211,23 @@ Note that `test_helper.rb` in a Rails project typically loads the application's
171
211
  require_relative '../config/environment'
172
212
  ```
173
213
 
174
- and `appmap/rspec` must be required before this:
214
+ and `appmap/minitest` must be required before this:
175
215
 
176
216
  ```ruby
177
- require 'appmap/rspec'
217
+ require 'appmap/minitest'
178
218
  require_relative '../config/environment'
179
219
  ```
180
220
 
181
- 2) Run the tests with the environment variable `APPMAP=true`:
221
+ 2) Run your tests as you normally would with the environment variable `APPMAP=true`. For example:
182
222
 
183
- ```sh-session
184
- $ APPMAP=true bundle exec -Ilib -Itest test/*
223
+ ```
224
+ $ APPMAP=true bundle exec rake test
225
+ ```
226
+
227
+ or
228
+
229
+ ```
230
+ $ APPMAP=true bundle exec ruby -Ilib -Itest test/*_test.rb
185
231
  ```
186
232
 
187
233
  Each Minitest test will output an AppMap file into the directory `tmp/appmap/minitest`. For example:
@@ -238,9 +284,9 @@ To manually record ad-hoc AppMaps of your Ruby app, use AppMap remote recording.
238
284
  1. Add the AppMap remote recording middleware. For example, in `config/initializers/appmap_remote_recording.rb`:
239
285
 
240
286
  ```ruby
241
- require 'appmap/middleware/remote_recording'
287
+ if defined?(AppMap)
288
+ require 'appmap/middleware/remote_recording'
242
289
 
243
- unless Rails.env.test?
244
290
  Rails.application.config.middleware.insert_after \
245
291
  Rails::Rack::Logger,
246
292
  AppMap::Middleware::RemoteRecording
@@ -261,14 +307,34 @@ $ bundle exec rails server
261
307
 
262
308
  6. Open the AppLand browser extension and push `Stop`. The recording will be transferred to the AppLand website and opened in your browser.
263
309
 
264
- ## Ruby on Rails
310
+ ## Server process recording
265
311
 
266
- If your app uses Ruby on Rails, the AppMap Railtie will be automatically enabled. Set the Rails config flag `app.config.appmap.enabled = true` to record the entire execution of your Rails app.
312
+ Add this line to *configuration.rb*:
267
313
 
268
- Note that using this method is kind of a blunt instrument. Recording RSpecs and using Remote Recording are usually better options.
314
+ ```ruby
315
+ module MyApp
316
+ class Application < Rails::Application
317
+ ...
318
+
319
+ config.appmap.enabled = true if ENV['APPMAP_RECORD']
320
+
321
+ ...
322
+ end
323
+ end
324
+ ```
325
+
326
+ With this setting, you can run your Rails server with `APPMAP_RECORD=true`. When the server exits, an *appmap.json* file will be written to the project directory. This is a great way to start the server, interact with your app as a user (or through it's API), and then view an AppMap of everything that happened.
327
+
328
+ Be sure and set `WEB_CONCURRENCY=1`, if you are using a webserver that can run multiple processes. You only want there to be one process while you are recording, otherwise they will both try and write *appmap.json* and one of them will clobber the other.
329
+
330
+ # AppMap for VSCode
331
+
332
+ The [AppMap extension for VSCode](https://marketplace.visualstudio.com/items?itemName=appland.appmap) is a great way to onboard developers to new code, and troubleshoot hard-to-understand bugs with visuals.
269
333
 
270
334
  # Uploading AppMaps
271
335
 
336
+ [https://app.land](https://app.land) can be used to store, analyze, and share AppMaps.
337
+
272
338
  For instructions on uploading, see the documentation of the [AppLand CLI](https://github.com/applandinc/appland-cli).
273
339
 
274
340
  # Development
data/Rakefile CHANGED
@@ -18,12 +18,12 @@ namespace 'gem' do
18
18
  require 'bundler/gem_tasks'
19
19
  end
20
20
 
21
- RUBY_VERSIONS=%w[2.5 2.6]
22
- FIXTURE_APPS=%w[rack_users_app rails6_users_app rails5_users_app rails4_users_app]
21
+ RUBY_VERSIONS=%w[2.5 2.6 2.7]
22
+ FIXTURE_APPS=%w[rack_users_app rails6_users_app rails5_users_app]
23
23
 
24
24
  def run_cmd(*cmd)
25
25
  $stderr.puts "Running: #{cmd}"
26
- out,s = Open3.capture2e(*cmd)
26
+ out, s = Open3.capture2e(*cmd)
27
27
  unless s.success?
28
28
  $stderr.puts <<-END
29
29
  Command failed:
@@ -113,17 +113,18 @@ module AppMap
113
113
  [ method.defined_class, static ? '.' : '#', method.name ].join
114
114
  end
115
115
 
116
+ source, comment = begin
117
+ [ method.source, method.comment ]
118
+ rescue MethodSource::SourceNotFoundError
119
+ [ nil, nil, ]
120
+ end
121
+
116
122
  if include_source
117
- begin
118
- function_info[:source] = method.source
119
- comment = method.comment || ''
120
- function_info[:comment] = comment unless comment.empty?
121
- rescue MethodSource::SourceNotFoundError
122
- # pass
123
- end
123
+ function_info[:source] = source unless source.blank?
124
+ function_info[:comment] = comment unless comment.blank?
124
125
  end
125
126
 
126
- function_info[:labels] = package.labels if package.labels
127
+ function_info[:labels] = parse_labels(comment) + (package.labels || [])
127
128
  object_infos << function_info
128
129
 
129
130
  parent = root
@@ -141,6 +142,22 @@ module AppMap
141
142
  end
142
143
  end
143
144
 
145
+ # Labels can be embedded in the function comment. Label format is similar to YARD and JavaDoc.
146
+ # The keyword is @labels or @label. The keyword is followed by space-separated labels.
147
+ # For example:
148
+ # @label provider.authentication security
149
+ def parse_labels(comment)
150
+ return [] unless comment
151
+
152
+ comment
153
+ .split("\n")
154
+ .map { |line| line.match(/^\s*#\s*@labels?\s+(.*)/) }
155
+ .compact
156
+ .map { |match| match[1] }
157
+ .inject([]) { |accum, labels| accum += labels.split(/\s+/); accum }
158
+ .sort
159
+ end
160
+
144
161
  def find_or_create(list, info)
145
162
  obj = list.find { |item| item.type == info[:type] && item.name == info[:name] }
146
163
  return obj if obj