appmap 0.88.0 → 0.90.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
- - ">="
|