appmap 0.39.1 → 0.40.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 384456ad51727b3c819e8307de92b2785da152a46c5fa60d0a4e6ff690dbb596
4
- data.tar.gz: e0d5a984bc74ee91b0f9428d83cbaac70c387b442cc55666f36b75907080e620
3
+ metadata.gz: 1b0943dadde84e67780d724918fa26377b869791eaab6edfb714e5081ecb5c80
4
+ data.tar.gz: c492323d80541a913b800924d04a7c24a6c8682263ba3ec4deabfa8d7ade3908
5
5
  SHA512:
6
- metadata.gz: 2f0670d632a370241168ad76ad30dd663568556ea3e524c48aafdbf86ae9d0c8e8f76f48a1c34a7a830457cff66c4417bbf19acb7ac952daeaaec65121e7a0d5
7
- data.tar.gz: 3f1bec26161a40c75487e7f98f039df0c135f7de77ee089d72dde29c1a5d5fd19b43661c6aff3c3de58e945b87d330b96a66738a95a208ec7a4e75db1bd85363
6
+ metadata.gz: 2a27e5b9bc3dafbba8aafd7035732b6ffcb813d57bb216d0e544af30260c0e26f23a920d1b2d6d35882046e74a57f8b492b12b9869de5d820ff6a4e09cafd716
7
+ data.tar.gz: f1bdc22fda7a6fdf0a37fc1d5bd419947e0fffa16511873dbe8a1549f30bf862566fe74fa4c9952c4338f5263414c99f3d598daec0a599b467e52ebac374b4f7
@@ -1,3 +1,10 @@
1
+ # v0.40.0
2
+
3
+ * Parse source code comments into function labels.
4
+
5
+ # v0.39.2
6
+ * Correctly recognize normalized path info for subengines.
7
+
1
8
  # v0.39.1
2
9
  * Support Ruby 2.7.
3
10
  * Remove support for Rails 4.
@@ -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,15 @@
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
+ - [AppMap for VSCode](#appmap-for-vscode)
11
13
  - [Uploading AppMaps](#uploading-appmaps)
12
14
  - [Development](#development)
13
15
  - [Running tests](#running-tests)
@@ -23,21 +25,21 @@
23
25
  "AppMap" is a data format which records code structure (modules, classes, and methods), code execution events
24
26
  (function calls and returns), and code metadata (repo name, repo URL, commit
25
27
  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.
28
+ 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
29
 
28
30
  There are several ways to record AppMaps of your Ruby program using the `appmap` gem:
29
31
 
30
- * Run your RSpec tests with the environment variable `APPMAP=true`. An AppMap will be generated for each spec.
32
+ * Run your tests (RSpec, Minitest, Cucumber) with the environment variable `APPMAP=true`. An AppMap will be generated for each spec.
31
33
  * Run your application server with AppMap remote recording enabled, and use the [AppLand
32
34
  browser extension](https://github.com/applandinc/appland-browser-extension) to start,
33
35
  stop, and upload recordings.
34
- * Run the command `appmap record <program>` to record the entire execution of a program.
36
+ * Wrap some code in an `AppMap.record` block, which returns JSON containing the code execution trace.
35
37
 
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.
38
+ Once you have made a recording, there are two ways to view automatically generated diagrams of the AppMaps.
39
+
40
+ 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).
41
+
42
+ 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).
41
43
 
42
44
  ### Supported versions
43
45
 
@@ -48,15 +50,10 @@ Support for new versions is added frequently, please check back regularly for up
48
50
 
49
51
  # Installation
50
52
 
51
- Add `gem 'appmap'` to your Gemfile just as you would any other dependency.
53
+ <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>
52
54
 
53
- **Global installation**
54
55
 
55
- ```
56
- gem 'appmap'
57
- ```
58
-
59
- **Install in test, development groups**
56
+ Add `gem 'appmap'` to your Gemfile just as you would any other dependency. We recommend that the Gem be added to the `:development, :test` section.
60
57
 
61
58
  ```
62
59
  group :development, :test do
@@ -72,7 +69,8 @@ If you are using Ruby on Rails, require the railtie after Rails is loaded.
72
69
 
73
70
  ```
74
71
  # application.rb is a good place to do this, along with all the other railties.
75
- require 'appmap/railtie'
72
+ # Don't require the railtie in environments that don't bundle the appmap gem.
73
+ require 'appmap/railtie' if defined?(AppMap).
76
74
  ```
77
75
 
78
76
  # Configuration
@@ -85,7 +83,14 @@ name: MyProject
85
83
  packages:
86
84
  - path: app/controllers
87
85
  - path: app/models
86
+ - path: app/jobs
87
+ - path: app/helpers
88
+ # Include the gems that you want to see in the dependency maps.
89
+ # These are just examples.
88
90
  - gem: activerecord
91
+ - gem: devise
92
+ - gem: aws-sdk
93
+ - gem: will_paginate
89
94
  ```
90
95
 
91
96
  * **name** Provides the project name (required)
@@ -104,6 +109,34 @@ Each entry in the `packages` list is a YAML object which has the following keys:
104
109
  the same package are not recorded unless code execution leaves the package and re-enters it. Default: `true` when using `gem`,
105
110
  `false` when using `path`.
106
111
 
112
+ # Labels
113
+
114
+ 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.
115
+
116
+ 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.
117
+
118
+ For example, if you add this comment to your source code:
119
+
120
+ ```ruby
121
+ class ApiKey
122
+ # @labels provider.authentication security
123
+ def authenticate(key)
124
+ # logic to verify the key here...
125
+ end
126
+ end
127
+ ```
128
+
129
+ Then the AppMap metadata section for this function will include:
130
+
131
+ ```json
132
+ {
133
+ "name": "authenticate",
134
+ "type": "function",
135
+ "labels": [ "provider.authentication", "security" ]
136
+ }
137
+ ```
138
+
139
+
107
140
  # Running
108
141
 
109
142
  ## RSpec
@@ -129,10 +162,7 @@ require 'appmap/rspec'
129
162
  require File.expand_path("../../config/environment", __FILE__)
130
163
  ```
131
164
 
132
- 2) *Optional* Add `feature: '<feature name>'` and `feature_group: '<feature group name>'` annotations to your
133
- examples.
134
-
135
- 3) Run the tests with the environment variable `APPMAP=true`:
165
+ 2) Run the tests with the environment variable `APPMAP=true`:
136
166
 
137
167
  ```sh-session
138
168
  $ APPMAP=true bundle exec rspec
@@ -145,23 +175,6 @@ $ find tmp/appmap/rspec
145
175
  Hello_says_hello_when_prompted.appmap.json
146
176
  ```
147
177
 
148
- If you include the `feature` and `feature_group` metadata, these attributes will be exported to the AppMap file in the
149
- `metadata` section. It will look something like this:
150
-
151
- ```json
152
- {
153
- ...
154
- "metadata": {
155
- "name": "Hello app says hello when prompted",
156
- "feature": "Hello app says hello",
157
- "feature_group": "Hello"
158
- },
159
- ...
160
- }
161
- ```
162
-
163
- If you don't explicitly declare `feature` and `feature_group`, then they will be inferred from the spec name and example descriptions.
164
-
165
178
  ## Minitest
166
179
 
167
180
  To record Minitest tests, follow these additional steps:
@@ -188,13 +201,13 @@ require_relative '../config/environment'
188
201
  2) Run your tests as you normally would with the environment variable `APPMAP=true`. For example:
189
202
 
190
203
  ```
191
- $ APPMAP=true bundle exec rake
204
+ $ APPMAP=true bundle exec rake test
192
205
  ```
193
206
 
194
207
  or
195
208
 
196
209
  ```
197
- $ APPMAP=true bundle exec -Ilib -Itest test/*
210
+ $ APPMAP=true bundle exec ruby -Ilib -Itest test/*_test.rb
198
211
  ```
199
212
 
200
213
  Each Minitest test will output an AppMap file into the directory `tmp/appmap/minitest`. For example:
@@ -251,9 +264,9 @@ To manually record ad-hoc AppMaps of your Ruby app, use AppMap remote recording.
251
264
  1. Add the AppMap remote recording middleware. For example, in `config/initializers/appmap_remote_recording.rb`:
252
265
 
253
266
  ```ruby
254
- require 'appmap/middleware/remote_recording'
267
+ if defined?(AppMap)
268
+ require 'appmap/middleware/remote_recording'
255
269
 
256
- unless Rails.env.test?
257
270
  Rails.application.config.middleware.insert_after \
258
271
  Rails::Rack::Logger,
259
272
  AppMap::Middleware::RemoteRecording
@@ -274,14 +287,14 @@ $ bundle exec rails server
274
287
 
275
288
  6. Open the AppLand browser extension and push `Stop`. The recording will be transferred to the AppLand website and opened in your browser.
276
289
 
277
- ## Ruby on Rails
278
-
279
- 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.
290
+ # AppMap for VSCode
280
291
 
281
- Note that using this method is kind of a blunt instrument. Recording RSpecs and using Remote Recording are usually better options.
292
+ 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.
282
293
 
283
294
  # Uploading AppMaps
284
295
 
296
+ [https://app.land](https://app.land) can be used to store, analyze, and share AppMaps.
297
+
285
298
  For instructions on uploading, see the documentation of the [AppLand CLI](https://github.com/applandinc/appland-cli).
286
299
 
287
300
  # Development
@@ -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
@@ -47,9 +47,14 @@ module AppMap
47
47
 
48
48
  private
49
49
 
50
- def normalized_path(request)
51
- route = ::Rails.application.routes.router.enum_for(:recognize, request).first
52
- route.first.path.spec.to_s if route
50
+ def normalized_path(request, router = ::Rails.application.routes.router)
51
+ router.recognize request do |route, _|
52
+ app = route.app
53
+ next unless app.matches? request
54
+ return normalized_path request, app.rack_app.routes.router if app.engine?
55
+
56
+ return route.path.spec.to_s
57
+ end
53
58
  end
54
59
  end
55
60
 
@@ -5,13 +5,9 @@ module AppMap
5
5
  class Railtie < ::Rails::Railtie
6
6
  config.appmap = ActiveSupport::OrderedOptions.new
7
7
 
8
- initializer 'appmap.init' do |_| # params: app
9
- require 'appmap'
10
- end
11
-
12
8
  # appmap.subscribe subscribes to ActiveSupport Notifications so that they can be recorded as
13
9
  # AppMap events.
14
- initializer 'appmap.subscribe', after: 'appmap.init' do |_| # params: app
10
+ initializer 'appmap.subscribe' do |_| # params: app
15
11
  require 'appmap/rails/sql_handler'
16
12
  require 'appmap/rails/request_handler'
17
13
  ActiveSupport::Notifications.subscribe 'sql.sequel', AppMap::Rails::SQLHandler.new
@@ -3,7 +3,7 @@
3
3
  module AppMap
4
4
  URL = 'https://github.com/applandinc/appmap-ruby'
5
5
 
6
- VERSION = '0.39.1'
6
+ VERSION = '0.40.0'
7
7
 
8
8
  APPMAP_FORMAT_VERSION = '1.4'
9
9
  end
@@ -0,0 +1,6 @@
1
+ # @label has-cls-label
2
+ class ClassWithLabel
3
+ # @label has-fn-label
4
+ def fn_with_label
5
+ end
6
+ end
@@ -33,11 +33,10 @@ appmap_options = \
33
33
  { path: appmap_path }
34
34
  else
35
35
  {}
36
- end.merge(require: %w[appmap appmap/railtie])
37
-
38
- gem 'appmap', appmap_options
36
+ end.merge(require: %w[appmap])
39
37
 
40
38
  group :development, :test do
39
+ gem 'appmap', appmap_options
41
40
  gem 'cucumber-rails', require: false
42
41
  gem 'rspec-rails'
43
42
  # Required for Sequel, since without ActiveRecord, the Rails transactional fixture support
@@ -19,6 +19,8 @@ when 'activerecord'
19
19
  require 'active_record/railtie'
20
20
  end
21
21
 
22
+ require 'appmap/railtie' if defined?(AppMap)
23
+
22
24
  # require "active_storage/engine"
23
25
  # require "action_mailer/railtie"
24
26
  # require "action_cable/engine"
@@ -34,11 +34,10 @@ appmap_options = \
34
34
  { path: appmap_path }
35
35
  else
36
36
  {}
37
- end.merge(require: %w[appmap appmap/railtie])
38
-
39
- gem 'appmap', appmap_options
37
+ end.merge(require: %w[appmap])
40
38
 
41
39
  group :development, :test do
40
+ gem 'appmap', appmap_options
42
41
  gem 'cucumber-rails', require: false
43
42
  gem 'rspec-rails'
44
43
  # Required for Sequel, since without ActiveRecord, the Rails transactional fixture support
@@ -19,6 +19,8 @@ when 'activerecord'
19
19
  require 'active_record/railtie'
20
20
  end
21
21
 
22
+ require 'appmap/railtie' if defined?(AppMap)
23
+
22
24
  # require "active_storage/engine"
23
25
  # require "action_mailer/railtie"
24
26
  # require "action_cable/engine"
@@ -61,6 +61,32 @@ describe 'AppMap class Hooking', docker: false do
61
61
  AppMap.configuration = nil
62
62
  end
63
63
 
64
+ it 'parses labels from comments' do
65
+ _, tracer = invoke_test_file 'spec/fixtures/hook/labels.rb' do
66
+ ClassWithLabel.new.fn_with_label
67
+ end
68
+ class_map = AppMap.class_map(tracer.event_methods).to_yaml
69
+ expect(Diffy::Diff.new(<<~YAML, class_map).to_s).to eq('')
70
+ ---
71
+ - :name: spec/fixtures/hook/labels.rb
72
+ :type: package
73
+ :children:
74
+ - :name: ClassWithLabel
75
+ :type: class
76
+ :children:
77
+ - :name: fn_with_label
78
+ :type: function
79
+ :location: spec/fixtures/hook/labels.rb:4
80
+ :static: false
81
+ :labels:
82
+ - has-fn-label
83
+ :comment: "# @label has-fn-label\\n"
84
+ :source: |2
85
+ def fn_with_label
86
+ end
87
+ YAML
88
+ end
89
+
64
90
  it 'hooks an instance method that takes no arguments' do
65
91
  events_yaml = <<~YAML
66
92
  ---
@@ -3,6 +3,7 @@ require 'net/http'
3
3
  require 'json'
4
4
  require 'yaml'
5
5
  require 'English'
6
+ require 'byebug'
6
7
  require 'webdrivers/chromedriver'
7
8
 
8
9
  # Disable default initialization of AppMap
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.39.1
4
+ version: 0.40.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-01-22 00:00:00.000000000 Z
11
+ date: 2021-01-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -319,6 +319,7 @@ files:
319
319
  - ".rubocop.yml"
320
320
  - ".travis.yml"
321
321
  - CHANGELOG.md
322
+ - CONTRIBUTING.md
322
323
  - Dockerfile.appmap
323
324
  - Gemfile
324
325
  - LICENSE.txt
@@ -386,6 +387,7 @@ files:
386
387
  - spec/fixtures/hook/constructor.rb
387
388
  - spec/fixtures/hook/exception_method.rb
388
389
  - spec/fixtures/hook/instance_method.rb
390
+ - spec/fixtures/hook/labels.rb
389
391
  - spec/fixtures/hook/singleton_method.rb
390
392
  - spec/fixtures/rack_users_app/.dockerignore
391
393
  - spec/fixtures/rack_users_app/.gitignore