appmap 0.51.0 → 0.52.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -1
- data/CHANGELOG.md +38 -0
- data/Rakefile +21 -5
- data/appmap.gemspec +11 -6
- data/exe/appmap-agent-setup +47 -0
- data/exe/appmap-inspect +7 -0
- data/lib/appmap.rb +44 -12
- data/lib/appmap/command/agent_setup/init.rb +44 -0
- data/lib/appmap/command/inspect.rb +27 -0
- data/lib/appmap/command_error.rb +13 -0
- data/lib/appmap/config.rb +7 -25
- data/lib/appmap/handler/rails/template.rb +19 -5
- data/lib/appmap/node_cli.rb +59 -0
- data/lib/appmap/service/guesser.rb +19 -0
- data/lib/appmap/trace.rb +4 -2
- data/lib/appmap/util.rb +31 -2
- data/lib/appmap/version.rb +2 -1
- data/package.json +6 -7
- data/spec/fixtures/rails5_users_app/docker-compose.yml +1 -1
- data/spec/fixtures/rails6_users_app/Dockerfile +9 -0
- data/spec/fixtures/rails6_users_app/docker-compose.yml +1 -1
- data/spec/{abstract_controller_base_spec.rb → rails_recording_spec.rb} +2 -21
- data/spec/rails_spec_helper.rb +22 -0
- data/test/agent_setup_cli_test.rb +37 -0
- data/test/fixtures/gem_test/Gemfile +1 -0
- data/test/inspect_cli_test.rb +12 -0
- data/yarn.lock +477 -0
- metadata +23 -47
- data/lib/appmap/algorithm/prune_class_map.rb +0 -67
- data/lib/appmap/algorithm/stats.rb +0 -91
- data/lib/appmap/command/record.rb +0 -38
- data/lib/appmap/command/stats.rb +0 -14
- data/lore/pages/2019-05-21-install-and-record/index.pug +0 -51
- data/lore/pages/2019-05-21-install-and-record/install_example_appmap.png +0 -0
- data/lore/pages/2019-05-21-install-and-record/metadata.yml +0 -5
- data/lore/pages/layout.pug +0 -66
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-grid.css +0 -1912
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-grid.css.map +0 -1
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-grid.min.css +0 -7
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-grid.min.css.map +0 -1
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-reboot.css +0 -331
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-reboot.css.map +0 -1
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-reboot.min.css +0 -8
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-reboot.min.css.map +0 -1
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap.css +0 -9030
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap.css.map +0 -1
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap.min.css +0 -7
- data/lore/public/lib/bootstrap-4.1.3/css/bootstrap.min.css.map +0 -1
- data/lore/public/stylesheets/style.css +0 -8
- data/package-lock.json +0 -1064
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.52.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Gilpin
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-06-
|
11
|
+
date: 2021-06-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -24,20 +24,6 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: faraday
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: gli
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,7 +53,7 @@ dependencies:
|
|
67
53
|
- !ruby/object:Gem::Version
|
68
54
|
version: '0'
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
56
|
+
name: rack
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
72
58
|
requirements:
|
73
59
|
- - ">="
|
@@ -81,7 +67,7 @@ dependencies:
|
|
81
67
|
- !ruby/object:Gem::Version
|
82
68
|
version: '0'
|
83
69
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
70
|
+
name: reverse_markdown
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
86
72
|
requirements:
|
87
73
|
- - ">="
|
@@ -112,16 +98,16 @@ dependencies:
|
|
112
98
|
name: minitest
|
113
99
|
requirement: !ruby/object:Gem::Requirement
|
114
100
|
requirements:
|
115
|
-
- -
|
101
|
+
- - '='
|
116
102
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
103
|
+
version: 5.14.4
|
118
104
|
type: :development
|
119
105
|
prerelease: false
|
120
106
|
version_requirements: !ruby/object:Gem::Requirement
|
121
107
|
requirements:
|
122
|
-
- -
|
108
|
+
- - '='
|
123
109
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
110
|
+
version: 5.14.4
|
125
111
|
- !ruby/object:Gem::Dependency
|
126
112
|
name: pry-byebug
|
127
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -307,7 +293,9 @@ dependencies:
|
|
307
293
|
description:
|
308
294
|
email:
|
309
295
|
- kgilpin@gmail.com
|
310
|
-
executables:
|
296
|
+
executables:
|
297
|
+
- appmap-agent-setup
|
298
|
+
- appmap-inspect
|
311
299
|
extensions:
|
312
300
|
- ext/appmap/extconf.rb
|
313
301
|
extra_rdoc_files: []
|
@@ -335,14 +323,15 @@ files:
|
|
335
323
|
- examples/mock_webapp/lib/mock_webapp/controller.rb
|
336
324
|
- examples/mock_webapp/lib/mock_webapp/request.rb
|
337
325
|
- examples/mock_webapp/lib/mock_webapp/user.rb
|
326
|
+
- exe/appmap-agent-setup
|
327
|
+
- exe/appmap-inspect
|
338
328
|
- ext/appmap/appmap.c
|
339
329
|
- ext/appmap/extconf.rb
|
340
330
|
- lib/appmap.rb
|
341
|
-
- lib/appmap/algorithm/prune_class_map.rb
|
342
|
-
- lib/appmap/algorithm/stats.rb
|
343
331
|
- lib/appmap/class_map.rb
|
344
|
-
- lib/appmap/command/
|
345
|
-
- lib/appmap/command/
|
332
|
+
- lib/appmap/command/agent_setup/init.rb
|
333
|
+
- lib/appmap/command/inspect.rb
|
334
|
+
- lib/appmap/command_error.rb
|
346
335
|
- lib/appmap/config.rb
|
347
336
|
- lib/appmap/cucumber.rb
|
348
337
|
- lib/appmap/event.rb
|
@@ -356,34 +345,17 @@ files:
|
|
356
345
|
- lib/appmap/metadata.rb
|
357
346
|
- lib/appmap/middleware/remote_recording.rb
|
358
347
|
- lib/appmap/minitest.rb
|
348
|
+
- lib/appmap/node_cli.rb
|
359
349
|
- lib/appmap/open.rb
|
360
350
|
- lib/appmap/railtie.rb
|
361
351
|
- lib/appmap/record.rb
|
362
352
|
- lib/appmap/rspec.rb
|
353
|
+
- lib/appmap/service/guesser.rb
|
363
354
|
- lib/appmap/trace.rb
|
364
355
|
- lib/appmap/util.rb
|
365
356
|
- lib/appmap/version.rb
|
366
|
-
- lore/pages/2019-05-21-install-and-record/index.pug
|
367
|
-
- lore/pages/2019-05-21-install-and-record/install_example_appmap.png
|
368
|
-
- lore/pages/2019-05-21-install-and-record/metadata.yml
|
369
|
-
- lore/pages/layout.pug
|
370
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap-grid.css
|
371
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap-grid.css.map
|
372
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap-grid.min.css
|
373
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap-grid.min.css.map
|
374
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap-reboot.css
|
375
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap-reboot.css.map
|
376
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap-reboot.min.css
|
377
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap-reboot.min.css.map
|
378
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap.css
|
379
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap.css.map
|
380
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap.min.css
|
381
|
-
- lore/public/lib/bootstrap-4.1.3/css/bootstrap.min.css.map
|
382
|
-
- lore/public/stylesheets/style.css
|
383
|
-
- package-lock.json
|
384
357
|
- package.json
|
385
358
|
- release.sh
|
386
|
-
- spec/abstract_controller_base_spec.rb
|
387
359
|
- spec/class_map_spec.rb
|
388
360
|
- spec/config_spec.rb
|
389
361
|
- spec/fixtures/hook/attr_accessor.rb
|
@@ -548,6 +520,7 @@ files:
|
|
548
520
|
- spec/fixtures/rails6_users_app/users_app/.gitignore
|
549
521
|
- spec/hook_spec.rb
|
550
522
|
- spec/open_spec.rb
|
523
|
+
- spec/rails_recording_spec.rb
|
551
524
|
- spec/rails_spec_helper.rb
|
552
525
|
- spec/railtie_spec.rb
|
553
526
|
- spec/record_net_http_spec.rb
|
@@ -555,6 +528,7 @@ files:
|
|
555
528
|
- spec/remote_recording_spec.rb
|
556
529
|
- spec/spec_helper.rb
|
557
530
|
- spec/util_spec.rb
|
531
|
+
- test/agent_setup_cli_test.rb
|
558
532
|
- test/bundle_vendor_test.rb
|
559
533
|
- test/cucumber_test.rb
|
560
534
|
- test/expectations/openssl_test_key_sign1.json
|
@@ -599,11 +573,13 @@ files:
|
|
599
573
|
- test/fixtures/rspec_recorder/spec/labeled_hello_spec.rb
|
600
574
|
- test/fixtures/rspec_recorder/spec/plain_hello_spec.rb
|
601
575
|
- test/gem_test.rb
|
576
|
+
- test/inspect_cli_test.rb
|
602
577
|
- test/minitest_test.rb
|
603
578
|
- test/openssl_test.rb
|
604
579
|
- test/record_process_test.rb
|
605
580
|
- test/rspec_test.rb
|
606
581
|
- test/test_helper.rb
|
582
|
+
- yarn.lock
|
607
583
|
homepage: https://github.com/applandinc/appmap-ruby
|
608
584
|
licenses:
|
609
585
|
- MIT
|
@@ -1,67 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module AppMap
|
4
|
-
module Algorithm
|
5
|
-
# Prune a class map so that only functions, classes and packages which are referenced
|
6
|
-
# by some event are retained.
|
7
|
-
class PruneClassMap
|
8
|
-
attr_reader :class_map
|
9
|
-
# Set this attribute to a function which will log algorithm events.
|
10
|
-
attr_writer :logger
|
11
|
-
attr_accessor :events
|
12
|
-
|
13
|
-
# Construct the algorithm, with a class map that will be pruned in place.
|
14
|
-
def initialize(class_map)
|
15
|
-
@class_map = class_map
|
16
|
-
@logger = ->(msg) {}
|
17
|
-
end
|
18
|
-
|
19
|
-
def perform
|
20
|
-
# This proc counts the number of objects in the class map whose type is 'k'
|
21
|
-
count = proc do |k, e|
|
22
|
-
n = 0
|
23
|
-
n += 1 if e['type'] == k
|
24
|
-
n += (e['children'] || []).map { |child| count.call(k, child) }.reduce(0, :+)
|
25
|
-
n
|
26
|
-
end
|
27
|
-
|
28
|
-
@logger.call "Full classMap contains #{class_map.map { |m| count.call('class', m) }.reduce(0, :+)} classes"
|
29
|
-
|
30
|
-
# Prune all the classes which fail a test.
|
31
|
-
reject = proc do |list, test|
|
32
|
-
list.tap do |_|
|
33
|
-
list.each do |item|
|
34
|
-
children = item['children']
|
35
|
-
next unless children
|
36
|
-
|
37
|
-
reject.call(children, test)
|
38
|
-
end
|
39
|
-
list.reject!(&test)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
if events
|
44
|
-
locations = \
|
45
|
-
Set.new(events.select { |e| e['event'] == 'call' }
|
46
|
-
.map { |e| [ e['path'], e['lineno'] ].join(':') })
|
47
|
-
|
48
|
-
# Prune all functions which aren't called
|
49
|
-
reject.call class_map,
|
50
|
-
->(e) { e['type'] == 'function' && !locations.member?(e['location']) }
|
51
|
-
end
|
52
|
-
|
53
|
-
# Prune all empty classes
|
54
|
-
reject.call class_map,
|
55
|
-
->(e) { e['type'] == 'class' && (e['children'] || []).empty? }
|
56
|
-
|
57
|
-
# Prune all empty packages
|
58
|
-
reject.call class_map,
|
59
|
-
->(e) { e['type'] == 'package' && (e['children'] || []).empty? }
|
60
|
-
|
61
|
-
@logger.call "Pruned classMap contains #{class_map.map { |m| count.call('class', m) }.reduce(0, :+)} classes"
|
62
|
-
|
63
|
-
class_map
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
@@ -1,91 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module AppMap
|
4
|
-
module Algorithm
|
5
|
-
StatsStruct = Struct.new(:appmap)
|
6
|
-
|
7
|
-
# Compute AppMap statistics.
|
8
|
-
class Stats < StatsStruct
|
9
|
-
Result = Struct.new(:class_frequency, :method_frequency) do
|
10
|
-
def merge!(other)
|
11
|
-
merge = lambda do |freq, other_freq|
|
12
|
-
freq_by_name = freq.inject({}) do |table, entry|
|
13
|
-
table.tap do
|
14
|
-
table[entry.name] = entry
|
15
|
-
end
|
16
|
-
end
|
17
|
-
other_freq.each do |other_entry|
|
18
|
-
entry = freq_by_name[other_entry.name]
|
19
|
-
if entry
|
20
|
-
entry.count += other_entry.count
|
21
|
-
else
|
22
|
-
freq << other_entry
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
merge.call(class_frequency, other.class_frequency)
|
27
|
-
merge.call(method_frequency, other.method_frequency)
|
28
|
-
|
29
|
-
self
|
30
|
-
end
|
31
|
-
|
32
|
-
def sort!
|
33
|
-
comparator = ->(a,b) { b.count <=> a.count }
|
34
|
-
class_frequency.sort!(&comparator)
|
35
|
-
method_frequency.sort!(&comparator)
|
36
|
-
|
37
|
-
self
|
38
|
-
end
|
39
|
-
|
40
|
-
def limit!(limit)
|
41
|
-
self.class_frequency = class_frequency[0...limit]
|
42
|
-
self.method_frequency = method_frequency[0...limit]
|
43
|
-
|
44
|
-
self
|
45
|
-
end
|
46
|
-
|
47
|
-
def as_text
|
48
|
-
lines = [
|
49
|
-
"Class frequency:",
|
50
|
-
"----------------",
|
51
|
-
] + class_frequency.map(&:to_a).map(&:reverse).map { |line | line.join("\t") } + [
|
52
|
-
"",
|
53
|
-
"Method frequency:",
|
54
|
-
"----------------",
|
55
|
-
] + method_frequency.map(&:to_a).map(&:reverse).map { |line | line.join("\t") }
|
56
|
-
lines.join("\n")
|
57
|
-
end
|
58
|
-
end
|
59
|
-
Frequency = Struct.new(:name, :count)
|
60
|
-
|
61
|
-
def perform(limit: nil)
|
62
|
-
events = appmap['events'] || []
|
63
|
-
frequency_calc = lambda do |key_func|
|
64
|
-
events_by_key = events.inject(Hash.new(0)) do |memo, event|
|
65
|
-
key = key_func.call(event)
|
66
|
-
memo.tap do
|
67
|
-
memo[key] += 1 if key
|
68
|
-
end
|
69
|
-
end
|
70
|
-
events_by_key.map do |key, count|
|
71
|
-
Frequency.new(key, count)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
class_name_func = ->(event) { event['defined_class'] }
|
76
|
-
full_name_func = lambda do |event|
|
77
|
-
call = event['event'] == 'call'
|
78
|
-
class_name = event['defined_class']
|
79
|
-
static = event['static']
|
80
|
-
function_name = event['method_id']
|
81
|
-
[ class_name, static ? '.' : '#', function_name ].join if call && class_name && !static.nil? && function_name
|
82
|
-
end
|
83
|
-
|
84
|
-
class_frequency = frequency_calc.call(class_name_func)
|
85
|
-
method_frequency = frequency_calc.call(full_name_func)
|
86
|
-
|
87
|
-
Result.new(class_frequency, method_frequency)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module AppMap
|
4
|
-
module Command
|
5
|
-
RecordStruct = Struct.new(:config, :program)
|
6
|
-
|
7
|
-
class Record < RecordStruct
|
8
|
-
def perform(&block)
|
9
|
-
tracer = AppMap.tracing.trace
|
10
|
-
|
11
|
-
events = []
|
12
|
-
quit = false
|
13
|
-
event_thread = Thread.new do
|
14
|
-
while tracer.event? || !quit
|
15
|
-
event = tracer.next_event
|
16
|
-
if event
|
17
|
-
events << event.to_h
|
18
|
-
else
|
19
|
-
sleep 0.0001
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
event_thread.abort_on_exception = true
|
24
|
-
|
25
|
-
at_exit do
|
26
|
-
quit = true
|
27
|
-
event_thread.join
|
28
|
-
yield AppMap::APPMAP_FORMAT_VERSION,
|
29
|
-
AppMap.detect_metadata,
|
30
|
-
AppMap.class_map(tracer.event_methods),
|
31
|
-
events
|
32
|
-
end
|
33
|
-
|
34
|
-
load program if program
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
data/lib/appmap/command/stats.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module AppMap
|
4
|
-
module Command
|
5
|
-
StatsStruct = Struct.new(:appmap)
|
6
|
-
|
7
|
-
class Stats < StatsStruct
|
8
|
-
def perform(limit: nil)
|
9
|
-
require 'appmap/algorithm/stats'
|
10
|
-
AppMap::Algorithm::Stats.new(appmap).perform(limit: limit)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
extends ../layout
|
2
|
-
|
3
|
-
block objective
|
4
|
-
div.
|
5
|
-
Installation of the AppMap client for Ruby is a key step in the user adoption flow.
|
6
|
-
Let's create an example program which installs the #[code appmap] Ruby gem and runs it to record a
|
7
|
-
scenario of a sample app.
|
8
|
-
|
9
|
-
block approach
|
10
|
-
:markdown-it
|
11
|
-
The [examples](https://github.com/applandinc/appmap-ruby/blob/master/examples/) folder in this project contains a sample project called `mock_webapp`, which
|
12
|
-
performs the following:
|
13
|
-
|
14
|
-
* Requests a `User` object by id ("alice").
|
15
|
-
* The request is handled by a `Controller`.
|
16
|
-
* The `Controller` looks up the id in a `User` model.
|
17
|
-
* The `User` model looks up the id and returns a `User` object, or raises an error.
|
18
|
-
* The `Controller` renders the response as a Hash and returns it to the client.
|
19
|
-
|
20
|
-
A test program called `install.rb` installs the `appmap` Ruby gem and then records the `mock_webapp`.
|
21
|
-
To create an appmap of `install.rb`:
|
22
|
-
|
23
|
-
```
|
24
|
-
bundle exec exe/record examples/install.rb
|
25
|
-
```
|
26
|
-
|
27
|
-
To upload the AppMap to AppLand:
|
28
|
-
|
29
|
-
```
|
30
|
-
bundle exec exe/upload appmap.json
|
31
|
-
```
|
32
|
-
|
33
|
-
block results
|
34
|
-
:markdown-it
|
35
|
-
## AppMap of `install.rb`
|
36
|
-
|
37
|
-
[![AppMap of `install.rb`](install_example_appmap.png)](https://appland-staging.herokuapp.com/scenarios/ba2fc385-a96d-42bf-9ef8-cdbdab8a475d)
|
38
|
-
|
39
|
-
button(onclick="document.querySelector('#show-test-program').style.display = 'block';") Show test program code
|
40
|
-
div#show-test-program(style='display: none;')
|
41
|
-
pre
|
42
|
-
include ../../../examples/install.rb
|
43
|
-
|
44
|
-
block next_steps
|
45
|
-
:markdown-it
|
46
|
-
|
47
|
-
A related feature is the AppLand server receiving the scenario file and displaying it.
|
48
|
-
|
49
|
-
Here is an [AppMap of the server receiving a scenario file](https://appland-staging.herokuapp.com/scenarios/beb49bc7-b2ca-49b6-bac3-5d2eec2df062).
|
50
|
-
|
51
|
-
|
Binary file
|