appmap 0.88.0 → 0.90.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +0 -1
- data/CHANGELOG.md +21 -0
- data/Gemfile +2 -0
- data/README.md +3 -5
- data/appmap.gemspec +4 -2
- data/lib/appmap/config.rb +18 -12
- data/lib/appmap/gem_hooks/jwt.yml +8 -0
- data/lib/appmap/middleware/remote_recording.rb +51 -6
- data/lib/appmap/trace.rb +8 -4
- data/lib/appmap/version.rb +1 -1
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 463d826fad7ff1f1f143f350e329e0d9f58c649c6a517b519c42e852d620318a
|
4
|
+
data.tar.gz: f1429c965be9a9913c2163245e3cee99b6b014d73c85d77c19b1d1198b5e92ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8fb3886bd1f864f4619f5dc0bd158381b4c959a385990d786d45228c0a2f01169511ef0a3ebafec6e01874af566bb286edfb38367f34b83facb7959ded3bd4ae
|
7
|
+
data.tar.gz: 96adc82206bf8fb319675a6107281c1ebfb19c8254daac59ae9e88ebceeec8adc446b459a68fa3483108426cb5a65bfbecb42205b4b797ae3301777b6e473233
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
# [0.90.0](https://github.com/applandinc/appmap-ruby/compare/v0.89.0...v0.90.0) (2022-09-15)
|
2
|
+
|
3
|
+
|
4
|
+
### Features
|
5
|
+
|
6
|
+
* Include required_ruby_version in the gemspec ([a5d7c6b](https://github.com/applandinc/appmap-ruby/commit/a5d7c6b7b255f817f3ceec5924cd799d2565daa4))
|
7
|
+
* Save default appmap.yml ([77a08d5](https://github.com/applandinc/appmap-ruby/commit/77a08d5ebbe2f49f19237242a62d05aadcc84228))
|
8
|
+
|
9
|
+
# [0.89.0](https://github.com/applandinc/appmap-ruby/compare/v0.88.0...v0.89.0) (2022-09-07)
|
10
|
+
|
11
|
+
|
12
|
+
### Bug Fixes
|
13
|
+
|
14
|
+
* Make Rack a runtime dependency ([3f2924d](https://github.com/applandinc/appmap-ruby/commit/3f2924d41af291bfe771829c2ea7978332ff1d44))
|
15
|
+
|
16
|
+
|
17
|
+
### Features
|
18
|
+
|
19
|
+
* Add builtin labels for JWT ([3569333](https://github.com/applandinc/appmap-ruby/commit/3569333e99f82e03fff892001f2b65eb9e8aa52a))
|
20
|
+
* Write an AppMap for each observed HTTP request ([2e89eaf](https://github.com/applandinc/appmap-ruby/commit/2e89eaf1b1f327771d1f4f0642fa6c202e0f3afb))
|
21
|
+
|
1
22
|
# [0.88.0](https://github.com/applandinc/appmap-ruby/compare/v0.87.0...v0.88.0) (2022-08-31)
|
2
23
|
|
3
24
|
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -92,9 +92,7 @@ You can launch a database like this:
|
|
92
92
|
```
|
93
93
|
➜ docker-compose -p appmap-ruby up -d
|
94
94
|
... stuff
|
95
|
-
➜ docker-compose
|
96
|
-
|
97
|
-
|
98
|
-
appmap-ruby_pg_1 docker-entrypoint.sh postgres Up (healthy) 0.0.0.0:59134->5432/tcp
|
99
|
-
➜ export DATABASE_URL=postgres://postgres@localhost:59134
|
95
|
+
➜ docker-compose port pg 5432
|
96
|
+
0.0.0.0:64479
|
97
|
+
➜ export DATABASE_URL=postgres://postgres@localhost:64479
|
100
98
|
```
|
data/appmap.gemspec
CHANGED
@@ -12,6 +12,8 @@ Gem::Specification.new do |spec|
|
|
12
12
|
spec.authors = ['Kevin Gilpin']
|
13
13
|
spec.email = ['kgilpin@gmail.com']
|
14
14
|
|
15
|
+
spec.required_ruby_version = '>= 2.6.0'
|
16
|
+
|
15
17
|
spec.summary = %q{Record the operation of a Ruby program, using the AppLand 'AppMap' format.}
|
16
18
|
spec.homepage = AppMap::URL
|
17
19
|
spec.license = 'MIT'
|
@@ -28,10 +30,10 @@ Gem::Specification.new do |spec|
|
|
28
30
|
spec.require_paths = ['lib']
|
29
31
|
|
30
32
|
spec.add_dependency 'method_source'
|
31
|
-
spec.add_dependency 'rack'
|
32
33
|
spec.add_dependency 'reverse_markdown'
|
33
34
|
|
34
35
|
spec.add_runtime_dependency 'activesupport'
|
36
|
+
spec.add_runtime_dependency 'rack'
|
35
37
|
|
36
38
|
spec.add_development_dependency 'bundler', '>= 1.16'
|
37
39
|
spec.add_development_dependency 'minitest', '~> 5.15'
|
@@ -39,7 +41,7 @@ Gem::Specification.new do |spec|
|
|
39
41
|
spec.add_development_dependency 'rake', '>= 12.3.3'
|
40
42
|
spec.add_development_dependency 'rdoc'
|
41
43
|
spec.add_development_dependency 'rubocop'
|
42
|
-
spec.add_development_dependency
|
44
|
+
spec.add_development_dependency 'rake-compiler'
|
43
45
|
|
44
46
|
# Testing
|
45
47
|
spec.add_development_dependency 'climate_control'
|
data/lib/appmap/config.rb
CHANGED
@@ -338,28 +338,34 @@ module AppMap
|
|
338
338
|
AppMap uses this file to customize its behavior. For example, you can use
|
339
339
|
the 'packages' setting to indicate which local file paths and dependency
|
340
340
|
gems you want to include in the AppMap. Since you haven't provided specific
|
341
|
-
settings, the appmap gem will
|
342
|
-
To suppress this message, create the file:
|
343
|
-
|
344
|
-
#{Pathname.new(config_file_name).expand_path}
|
345
|
-
|
346
|
-
Here are the default settings that will be used in the meantime. You can
|
347
|
-
copy and paste this example to start your appmap.yml.
|
341
|
+
settings, the appmap gem will use these default options:
|
348
342
|
MISSING_FILE_MSG
|
349
343
|
{}
|
350
344
|
end
|
351
345
|
|
352
346
|
load(config_data).tap do |config|
|
353
|
-
|
347
|
+
{
|
354
348
|
'name' => config.name,
|
355
349
|
'packages' => config.packages.select{|p| p.path}.map do |pkg|
|
356
350
|
{ 'path' => pkg.path }
|
357
351
|
end,
|
358
352
|
'exclude' => []
|
359
|
-
}.compact
|
360
|
-
|
361
|
-
|
362
|
-
|
353
|
+
}.compact.tap do |config_yaml|
|
354
|
+
unless config_present
|
355
|
+
warn Util.color(YAML.dump(config_yaml), :magenta)
|
356
|
+
dirname = Pathname.new(config_file_name).dirname.expand_path
|
357
|
+
if Dir.exists?(dirname) && File.writable?(dirname)
|
358
|
+
warn Util.color(<<~CONFIG_FILE_MSG, :magenta)
|
359
|
+
This file will be saved to #{Pathname.new(config_file_name).expand_path},
|
360
|
+
where you can customize it.
|
361
|
+
CONFIG_FILE_MSG
|
362
|
+
File.write(config_file_name, YAML.dump(config_yaml))
|
363
|
+
end
|
364
|
+
warn Util.color(<<~CONFIG_FILE_MSG, :magenta)
|
365
|
+
For more information, see https://appmap.io/docs/reference/appmap-ruby.html#configuration
|
366
|
+
CONFIG_FILE_MSG
|
367
|
+
warn logo.()
|
368
|
+
end
|
363
369
|
end
|
364
370
|
end
|
365
371
|
end
|
@@ -2,7 +2,8 @@
|
|
2
2
|
|
3
3
|
module AppMap
|
4
4
|
module Middleware
|
5
|
-
# RemoteRecording adds `/_appmap/record` routes to control recordings via HTTP requests
|
5
|
+
# RemoteRecording adds `/_appmap/record` routes to control recordings via HTTP requests.
|
6
|
+
# It can also be enabled to emit an AppMap for each request.
|
6
7
|
class RemoteRecording
|
7
8
|
def initialize(app)
|
8
9
|
require 'json'
|
@@ -21,7 +22,7 @@ module AppMap
|
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
24
|
-
def
|
25
|
+
def ws_start_recording
|
25
26
|
return [ 409, 'Recording is already in progress' ] if @tracer
|
26
27
|
|
27
28
|
@events = []
|
@@ -32,7 +33,7 @@ module AppMap
|
|
32
33
|
[ 200 ]
|
33
34
|
end
|
34
35
|
|
35
|
-
def
|
36
|
+
def ws_stop_recording(req)
|
36
37
|
return [ 404, 'No recording is in progress' ] unless @tracer
|
37
38
|
|
38
39
|
tracer = @tracer
|
@@ -75,10 +76,50 @@ module AppMap
|
|
75
76
|
end
|
76
77
|
|
77
78
|
def call(env)
|
79
|
+
# Note: Puma config is avaliable here. For example:
|
80
|
+
# $ env['puma.config'].final_options[:workers]
|
81
|
+
# 0
|
82
|
+
|
78
83
|
req = Rack::Request.new(env)
|
79
84
|
return handle_record_request(req) if req.path == '/_appmap/record'
|
80
85
|
|
81
|
-
|
86
|
+
start_time = Time.now
|
87
|
+
# Support multi-threaded web server such as Puma by recording each thread
|
88
|
+
# into a separate Tracer.
|
89
|
+
tracer = AppMap.tracing.trace(thread: Thread.current) if record_all_requests?
|
90
|
+
|
91
|
+
@app.call(env).tap do |status, headers|
|
92
|
+
if tracer
|
93
|
+
AppMap.tracing.delete(tracer)
|
94
|
+
|
95
|
+
events = tracer.events.map(&:to_h)
|
96
|
+
|
97
|
+
appmap_name = "#{req.request_method} #{req.path} (#{status}) - #{start_time.strftime('%T.%L')}"
|
98
|
+
appmap_file_name = AppMap::Util.scenario_filename([ start_time.to_f, req.url ].join('_'))
|
99
|
+
output_dir = File.join(AppMap::DEFAULT_APPMAP_DIR, 'requests')
|
100
|
+
appmap_file_path = File.join(output_dir, appmap_file_name)
|
101
|
+
|
102
|
+
metadata = AppMap.detect_metadata
|
103
|
+
metadata[:name] = appmap_name
|
104
|
+
metadata[:timestamp] = start_time.to_f
|
105
|
+
metadata[:recorder] = {
|
106
|
+
name: 'record_requests'
|
107
|
+
}
|
108
|
+
|
109
|
+
appmap = {
|
110
|
+
version: AppMap::APPMAP_FORMAT_VERSION,
|
111
|
+
classMap: AppMap.class_map(tracer.event_methods),
|
112
|
+
metadata: metadata,
|
113
|
+
events: events
|
114
|
+
}
|
115
|
+
|
116
|
+
FileUtils.mkdir_p(output_dir)
|
117
|
+
File.write(appmap_file_path, JSON.generate(appmap))
|
118
|
+
|
119
|
+
headers['AppMap-Name'] = File.expand_path(appmap_name)
|
120
|
+
headers['AppMap-File-Name'] = File.expand_path(appmap_file_path)
|
121
|
+
end
|
122
|
+
end
|
82
123
|
end
|
83
124
|
|
84
125
|
def recording_state
|
@@ -92,9 +133,9 @@ module AppMap
|
|
92
133
|
if method.eql?('GET')
|
93
134
|
recording_state
|
94
135
|
elsif method.eql?('POST')
|
95
|
-
|
136
|
+
ws_start_recording
|
96
137
|
elsif method.eql?('DELETE')
|
97
|
-
|
138
|
+
ws_stop_recording(req)
|
98
139
|
else
|
99
140
|
[ 404, '' ]
|
100
141
|
end
|
@@ -106,6 +147,10 @@ module AppMap
|
|
106
147
|
headers['Content-Type'] && headers['Content-Type'] =~ /html/
|
107
148
|
end
|
108
149
|
|
150
|
+
def record_all_requests?
|
151
|
+
ENV['APPMAP_RECORD_REQUESTS'] == 'true'
|
152
|
+
end
|
153
|
+
|
109
154
|
def recording?
|
110
155
|
!@event_thread.nil?
|
111
156
|
end
|
data/lib/appmap/trace.rb
CHANGED
@@ -48,8 +48,8 @@ module AppMap
|
|
48
48
|
@tracers.empty?
|
49
49
|
end
|
50
50
|
|
51
|
-
def trace(enable: true)
|
52
|
-
Tracer.new.tap do |tracer|
|
51
|
+
def trace(enable: true, thread: nil)
|
52
|
+
Tracer.new(thread_id: thread&.object_id).tap do |tracer|
|
53
53
|
@tracers << tracer
|
54
54
|
tracer.enable if enable
|
55
55
|
end
|
@@ -64,7 +64,7 @@ module AppMap
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def record_event(event, package: nil, defined_class: nil, method: nil)
|
67
|
-
@tracers.each do |tracer|
|
67
|
+
@tracers.select { |tracer| tracer.thread_id.nil? || tracer.thread_id === event.thread_id }.each do |tracer|
|
68
68
|
tracer.record_event(event, package: package, defined_class: defined_class, method: method)
|
69
69
|
end
|
70
70
|
end
|
@@ -114,14 +114,16 @@ module AppMap
|
|
114
114
|
|
115
115
|
class Tracer
|
116
116
|
attr_accessor :stacks
|
117
|
+
attr_reader :thread_id, :events
|
117
118
|
|
118
119
|
# Records the events which happen in a program.
|
119
|
-
def initialize
|
120
|
+
def initialize(thread_id: nil)
|
120
121
|
@events = []
|
121
122
|
@last_package_for_thread = {}
|
122
123
|
@methods = Set.new
|
123
124
|
@stack_printer = StackPrinter.new if StackPrinter.enabled?
|
124
125
|
@enabled = false
|
126
|
+
@thread_id = thread_id
|
125
127
|
end
|
126
128
|
|
127
129
|
def enable
|
@@ -143,6 +145,8 @@ module AppMap
|
|
143
145
|
def record_event(event, package: nil, defined_class: nil, method: nil)
|
144
146
|
return unless @enabled
|
145
147
|
|
148
|
+
raise "Expected event in thread #{@thread_id}, got #{event.thread_id}" if @thread_id && @thread_id != event.thread_id
|
149
|
+
|
146
150
|
@stack_printer.record(event) if @stack_printer
|
147
151
|
@last_package_for_thread[Thread.current.object_id] = package if package
|
148
152
|
@events << event
|
data/lib/appmap/version.rb
CHANGED
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.90.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: 2022-
|
11
|
+
date: 2022-09-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: method_source
|
@@ -25,7 +25,7 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: reverse_markdown
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: activesupport
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: rack
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
@@ -386,6 +386,7 @@ files:
|
|
386
386
|
- lib/appmap/gem_hooks/activerecord.yml
|
387
387
|
- lib/appmap/gem_hooks/cancancan.yml
|
388
388
|
- lib/appmap/gem_hooks/devise.yml
|
389
|
+
- lib/appmap/gem_hooks/jwt.yml
|
389
390
|
- lib/appmap/gem_hooks/pandoc-ruby.yml
|
390
391
|
- lib/appmap/gem_hooks/rails.yml
|
391
392
|
- lib/appmap/gem_hooks/railties.yml
|
@@ -445,7 +446,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
445
446
|
requirements:
|
446
447
|
- - ">="
|
447
448
|
- !ruby/object:Gem::Version
|
448
|
-
version:
|
449
|
+
version: 2.6.0
|
449
450
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
450
451
|
requirements:
|
451
452
|
- - ">="
|