appmap 0.53.0 → 0.54.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/lib/appmap.rb +28 -110
- data/lib/appmap/agent.rb +115 -0
- data/lib/appmap/class_map.rb +2 -2
- data/lib/appmap/config.rb +11 -3
- data/lib/appmap/handler/net_http.rb +2 -1
- data/lib/appmap/handler/rails/request_handler.rb +2 -1
- data/lib/appmap/metadata.rb +4 -2
- data/lib/appmap/minitest.rb +2 -0
- data/lib/appmap/railtie.rb +2 -2
- data/lib/appmap/rspec.rb +5 -3
- data/lib/appmap/swagger.rb +2 -0
- data/lib/appmap/swagger/configuration.rb +70 -0
- data/lib/appmap/swagger/markdown_descriptions.rb +43 -0
- data/lib/appmap/swagger/rake_tasks.rb +43 -0
- data/lib/appmap/swagger/stable.rb +37 -0
- data/lib/appmap/version.rb +1 -1
- data/package.json +0 -1
- data/spec/config_spec.rb +0 -1
- data/spec/fixtures/hook/.gitignore +2 -0
- data/spec/fixtures/hook/app/controllers/api/api_keys_controller.rb +1 -0
- data/spec/fixtures/hook/app/controllers/organizations_controller.rb +1 -0
- data/spec/fixtures/hook/app/models/api_key.rb +1 -0
- data/spec/fixtures/hook/app/models/configuration.rb +1 -0
- data/spec/fixtures/hook/app/models/show.rb +1 -0
- data/spec/fixtures/hook/app/models/user.rb +1 -0
- data/spec/fixtures/hook/revoke_api_key.appmap.json +847 -0
- data/spec/fixtures/hook/spec/api_spec.rb +1 -0
- data/spec/fixtures/hook/spec/user_spec.rb +1 -0
- data/spec/fixtures/hook/user_page_scenario.appmap.json +1722 -0
- data/spec/fixtures/rails5_users_app/config/environments/test.rb +3 -0
- data/spec/fixtures/rails6_users_app/Dockerfile +0 -1
- data/spec/fixtures/rails6_users_app/appmap.yml +3 -1
- data/spec/fixtures/rails6_users_app/config/environments/test.rb +3 -0
- data/spec/fixtures/rails6_users_app/lib/tasks/appmap.rake +13 -0
- data/spec/rails_recording_spec.rb +1 -1
- data/spec/swagger/swagger_spec.rb +47 -0
- data/test/gem_test.rb +1 -0
- metadata +21 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a00ec7ef6ec83aebf28d11c8004c89885ae32562ef6384c6c7880ca09d380027
|
4
|
+
data.tar.gz: a16129c01467f043eb18786ea8f3cae2df65226b924e6f85b40614f7d563e8a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: daeec49a1a7e46fa5d5f572755725d766a2c37e00f8013d93ac1cde6d7dcff504633b4ca74cbbc94c9a3d355bc221d795970e0af393be29557f03d8fbe06114a
|
7
|
+
data.tar.gz: f1c8b85f2e9224604f3138c208dbcff0dbb939aa1038834a8ca761b290b5f07086023857881dd4c14c37644a9ae403108ba059c4a337796ea7ecab0e6b2826bb
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
# [0.54.0](https://github.com/applandinc/appmap-ruby/compare/v0.53.0...v0.54.0) (2021-06-24)
|
2
|
+
|
3
|
+
|
4
|
+
### Bug Fixes
|
5
|
+
|
6
|
+
* Handle new behavior in RSpec ExampleGroup ([176d0df](https://github.com/applandinc/appmap-ruby/commit/176d0dfca0b2e4cc5a8908fa67c01dd0c79ef175))
|
7
|
+
|
8
|
+
|
9
|
+
### Features
|
10
|
+
|
11
|
+
* Add swagger rake task ([0aaae49](https://github.com/applandinc/appmap-ruby/commit/0aaae4973f0df530c75ed92b93f8a1940a948091))
|
12
|
+
|
1
13
|
# [0.53.0](https://github.com/applandinc/appmap-ruby/compare/v0.52.1...v0.53.0) (2021-06-23)
|
2
14
|
|
3
15
|
|
data/lib/appmap.rb
CHANGED
@@ -1,116 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
# This is the file that's loaded when you require 'appmap'.
|
4
|
+
# If you require this file, we assume that you want to automatically activate all
|
5
|
+
# the AppMap functionality that seems suitable for your project.
|
6
|
+
# For example, if your project is a Rails project, the Railtie will be loaded.
|
7
|
+
# If your bundle includes rspec, the appmap/rspec will be loaded.
|
8
|
+
#
|
9
|
+
# If you don't want this "all-in" behavior, then you can use the 'require' option
|
10
|
+
# in your Gemfile to selectively activate just the AppMap features that you want. Then
|
11
|
+
# you can manually configure/require other features, elsewhere in your code.
|
12
|
+
# Note that you should always require 'appmap/agent' as early as possible, so that it can
|
13
|
+
# observe and hook as much code loading as possible.
|
14
|
+
#
|
15
|
+
# Modules that you can load independently include:
|
16
|
+
# - appmap/agent
|
17
|
+
# - appmap/railtie
|
18
|
+
# - appmap/rspec
|
19
|
+
# - appmap/minitest
|
20
|
+
# - appmap/swagger (Rake task)
|
9
21
|
|
10
22
|
require 'appmap/version'
|
11
|
-
require 'appmap/
|
12
|
-
require 'appmap/hook'
|
13
|
-
require 'appmap/config'
|
14
|
-
require 'appmap/trace'
|
15
|
-
require 'appmap/class_map'
|
16
|
-
require 'appmap/metadata'
|
17
|
-
require 'appmap/open'
|
18
|
-
|
19
|
-
# load extension
|
20
|
-
require 'appmap/appmap'
|
21
|
-
|
22
|
-
module AppMap
|
23
|
-
class << self
|
24
|
-
@configuration = nil
|
25
|
-
@configuration_file_path = nil
|
26
|
-
|
27
|
-
# Gets the configuration. If there is no configuration, the default
|
28
|
-
# configuration is initialized.
|
29
|
-
def configuration
|
30
|
-
@configuration ||= initialize_configuration
|
31
|
-
end
|
32
|
-
|
33
|
-
# Sets the configuration. This is only expected to happen once per
|
34
|
-
# Ruby process.
|
35
|
-
def configuration=(config)
|
36
|
-
warn 'AppMap is already configured' if @configuration && config
|
37
|
-
|
38
|
-
@configuration = config
|
39
|
-
end
|
40
|
-
|
41
|
-
def default_config_file_path
|
42
|
-
ENV['APPMAP_CONFIG_FILE'] || 'appmap.yml'
|
43
|
-
end
|
44
|
-
|
45
|
-
# Configures AppMap for recording. Default behavior is to configure from
|
46
|
-
# APPMAP_CONFIG_FILE, or 'appmap.yml'. If no config file is available, a
|
47
|
-
# configuration will be automatically generated and used - and the user is prompted
|
48
|
-
# to create the config file.
|
49
|
-
#
|
50
|
-
# This method also activates the code hooks which record function calls as trace events.
|
51
|
-
# Call this function before the program code is loaded by the Ruby VM, otherwise
|
52
|
-
# the load events won't be seen and the hooks won't activate.
|
53
|
-
def initialize_configuration(config_file_path = default_config_file_path)
|
54
|
-
Util.startup_message "Configuring AppMap from path #{config_file_path}"
|
55
|
-
Config.load_from_file(config_file_path).tap do |configuration|
|
56
|
-
self.configuration = configuration
|
57
|
-
Hook.new(configuration).enable
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def info(msg)
|
62
|
-
if defined?(::Rails) && defined?(::Rails.logger)
|
63
|
-
::Rails.logger.info msg
|
64
|
-
else
|
65
|
-
warn msg
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
# Used to start tracing, stop tracing, and record events.
|
70
|
-
def tracing
|
71
|
-
@tracing ||= Trace::Tracing.new
|
72
|
-
end
|
73
|
-
|
74
|
-
# Records the events which occur while processing a block,
|
75
|
-
# and returns an AppMap as a Hash.
|
76
|
-
def record
|
77
|
-
tracer = tracing.trace
|
78
|
-
begin
|
79
|
-
yield
|
80
|
-
ensure
|
81
|
-
tracing.delete(tracer)
|
82
|
-
end
|
83
|
-
|
84
|
-
events = [].tap do |event_list|
|
85
|
-
event_list << tracer.next_event.to_h while tracer.event?
|
86
|
-
end
|
87
|
-
{
|
88
|
-
'version' => AppMap::APPMAP_FORMAT_VERSION,
|
89
|
-
'metadata' => detect_metadata,
|
90
|
-
'classMap' => class_map(tracer.event_methods),
|
91
|
-
'events' => events
|
92
|
-
}
|
93
|
-
end
|
94
|
-
|
95
|
-
# Uploads an AppMap to the AppLand website and displays it.
|
96
|
-
def open(appmap = nil, &block)
|
97
|
-
appmap ||= AppMap.record(&block)
|
98
|
-
AppMap::Open.new(appmap).perform
|
99
|
-
end
|
100
|
-
|
101
|
-
# Builds a class map from a config and a list of Ruby methods.
|
102
|
-
def class_map(methods)
|
103
|
-
ClassMap.build_from_methods(methods)
|
104
|
-
end
|
105
|
-
|
106
|
-
# Returns default metadata detected from the Ruby system and from the
|
107
|
-
# filesystem.
|
108
|
-
def detect_metadata
|
109
|
-
@metadata ||= Metadata.detect.freeze
|
110
|
-
@metadata.deep_dup
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
23
|
+
require 'appmap/agent'
|
114
24
|
|
115
25
|
lambda do
|
116
26
|
Initializer = Struct.new(:class_name, :module_name, :gem_module_name)
|
@@ -118,7 +28,10 @@ lambda do
|
|
118
28
|
INITIALIZERS = {
|
119
29
|
'Rails::Railtie' => Initializer.new('AppMap::Railtie', 'appmap/railtie', 'railtie'),
|
120
30
|
'RSpec' => Initializer.new('AppMap::RSpec', 'appmap/rspec', 'rspec-core'),
|
121
|
-
'Minitest::Unit::TestCase' => Initializer.new('AppMap::Minitest', 'appmap/minitest', 'minitest')
|
31
|
+
'Minitest::Unit::TestCase' => Initializer.new('AppMap::Minitest', 'appmap/minitest', 'minitest'),
|
32
|
+
'Rake' => [
|
33
|
+
Initializer.new('AppMap::Swagger', 'appmap/swagger', 'rake')
|
34
|
+
]
|
122
35
|
}
|
123
36
|
|
124
37
|
TracePoint.new(:class) do |tp|
|
@@ -155,6 +68,11 @@ lambda do
|
|
155
68
|
if defined?(::Minitest)
|
156
69
|
require 'appmap/minitest'
|
157
70
|
end
|
71
|
+
|
72
|
+
if defined?(::Rake)
|
73
|
+
require 'appmap/swagger'
|
74
|
+
end
|
75
|
+
|
158
76
|
end.call
|
159
77
|
|
160
78
|
AppMap.initialize_configuration if ENV['APPMAP'] == 'true'
|
data/lib/appmap/agent.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
require_relative 'version'
|
2
|
+
require_relative 'hook'
|
3
|
+
require_relative 'config'
|
4
|
+
require_relative 'trace'
|
5
|
+
require_relative 'class_map'
|
6
|
+
require_relative 'metadata'
|
7
|
+
require_relative 'util'
|
8
|
+
require_relative 'open'
|
9
|
+
|
10
|
+
# load extension
|
11
|
+
require_relative 'appmap'
|
12
|
+
|
13
|
+
module AppMap
|
14
|
+
class << self
|
15
|
+
@configuration = nil
|
16
|
+
@configuration_file_path = nil
|
17
|
+
|
18
|
+
# Gets the configuration. If there is no configuration, the default
|
19
|
+
# configuration is initialized.
|
20
|
+
def configuration
|
21
|
+
@configuration ||= initialize_configuration
|
22
|
+
end
|
23
|
+
|
24
|
+
# Sets the configuration. This is only expected to happen once per
|
25
|
+
# Ruby process.
|
26
|
+
def configuration=(config)
|
27
|
+
warn 'AppMap is already configured' if @configuration && config
|
28
|
+
|
29
|
+
@configuration = config
|
30
|
+
end
|
31
|
+
|
32
|
+
def default_config_file_path
|
33
|
+
ENV['APPMAP_CONFIG_FILE'] || 'appmap.yml'
|
34
|
+
end
|
35
|
+
|
36
|
+
# Configures AppMap for recording. Default behavior is to configure from
|
37
|
+
# APPMAP_CONFIG_FILE, or 'appmap.yml'. If no config file is available, a
|
38
|
+
# configuration will be automatically generated and used - and the user is prompted
|
39
|
+
# to create the config file.
|
40
|
+
#
|
41
|
+
# This method also activates the code hooks which record function calls as trace events.
|
42
|
+
# Call this function before the program code is loaded by the Ruby VM, otherwise
|
43
|
+
# the load events won't be seen and the hooks won't activate.
|
44
|
+
def initialize_configuration(config_file_path = default_config_file_path)
|
45
|
+
Util.startup_message "Configuring AppMap from path #{config_file_path}"
|
46
|
+
Config.load_from_file(config_file_path).tap do |configuration|
|
47
|
+
self.configuration = configuration
|
48
|
+
Hook.new(configuration).enable
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def info(msg)
|
53
|
+
if defined?(::Rails) && defined?(::Rails.logger)
|
54
|
+
::Rails.logger.info msg
|
55
|
+
else
|
56
|
+
warn msg
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def config_message(msg)
|
61
|
+
logger = if defined?(::Rails) && ::Rails.logger
|
62
|
+
::Rails.logger
|
63
|
+
elsif ENV['DEBUG'] == 'true'
|
64
|
+
method(:warn)
|
65
|
+
else
|
66
|
+
->(msg) { }
|
67
|
+
end
|
68
|
+
logger.call(msg)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Used to start tracing, stop tracing, and record events.
|
72
|
+
def tracing
|
73
|
+
@tracing ||= Trace::Tracing.new
|
74
|
+
end
|
75
|
+
|
76
|
+
# Records the events which occur while processing a block,
|
77
|
+
# and returns an AppMap as a Hash.
|
78
|
+
def record
|
79
|
+
tracer = tracing.trace
|
80
|
+
begin
|
81
|
+
yield
|
82
|
+
ensure
|
83
|
+
tracing.delete(tracer)
|
84
|
+
end
|
85
|
+
|
86
|
+
events = [].tap do |event_list|
|
87
|
+
event_list << tracer.next_event.to_h while tracer.event?
|
88
|
+
end
|
89
|
+
{
|
90
|
+
'version' => AppMap::APPMAP_FORMAT_VERSION,
|
91
|
+
'metadata' => detect_metadata,
|
92
|
+
'classMap' => class_map(tracer.event_methods),
|
93
|
+
'events' => events
|
94
|
+
}
|
95
|
+
end
|
96
|
+
|
97
|
+
# Uploads an AppMap to the AppLand website and displays it.
|
98
|
+
def open(appmap = nil, &block)
|
99
|
+
appmap ||= AppMap.record(&block)
|
100
|
+
AppMap::Open.new(appmap).perform
|
101
|
+
end
|
102
|
+
|
103
|
+
# Builds a class map from a config and a list of Ruby methods.
|
104
|
+
def class_map(methods)
|
105
|
+
ClassMap.build_from_methods(methods)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Returns default metadata detected from the Ruby system and from the
|
109
|
+
# filesystem.
|
110
|
+
def detect_metadata
|
111
|
+
@metadata ||= Metadata.detect.freeze
|
112
|
+
Util.deep_dup(@metadata)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
data/lib/appmap/class_map.rb
CHANGED
@@ -111,7 +111,7 @@ module AppMap
|
|
111
111
|
end
|
112
112
|
|
113
113
|
comment = method.comment
|
114
|
-
function_info[:comment] = comment unless
|
114
|
+
function_info[:comment] = comment unless Util.blank?(comment)
|
115
115
|
|
116
116
|
function_info[:labels] = parse_labels(comment) + (method.labels || [])
|
117
117
|
object_infos << function_info
|
@@ -119,7 +119,7 @@ module AppMap
|
|
119
119
|
parent = root
|
120
120
|
object_infos.each do |info|
|
121
121
|
parent = find_or_create parent.children, info do
|
122
|
-
Types.const_get(info[:type]
|
122
|
+
Types.const_get(Util.classify(info[:type])).new(info[:name].to_s).tap do |type|
|
123
123
|
info.keys.tap do |keys|
|
124
124
|
keys.delete(:name)
|
125
125
|
keys.delete(:type)
|
data/lib/appmap/config.rb
CHANGED
@@ -5,6 +5,7 @@ require 'appmap/util'
|
|
5
5
|
require 'appmap/handler/net_http'
|
6
6
|
require 'appmap/handler/rails/template'
|
7
7
|
require 'appmap/service/guesser'
|
8
|
+
require 'appmap/swagger/configuration'
|
8
9
|
|
9
10
|
module AppMap
|
10
11
|
class Config
|
@@ -81,8 +82,8 @@ module AppMap
|
|
81
82
|
package_name: package_name,
|
82
83
|
gem: gem,
|
83
84
|
handler_class: handler_class.name,
|
84
|
-
exclude:
|
85
|
-
labels:
|
85
|
+
exclude: Util.blank?(exclude) ? nil : exclude,
|
86
|
+
labels: Util.blank?(labels) ? nil : labels,
|
86
87
|
shallow: shallow
|
87
88
|
}.compact
|
88
89
|
end
|
@@ -226,15 +227,17 @@ module AppMap
|
|
226
227
|
'JSON::Ext::Generator::State' => TargetMethods.new(:generate, Package.build_from_path('json', package_name: 'json', labels: %w[format.json.generate])),
|
227
228
|
}.freeze
|
228
229
|
|
229
|
-
attr_reader :name, :appmap_dir, :packages, :exclude, :hooked_methods, :builtin_hooks
|
230
|
+
attr_reader :name, :appmap_dir, :packages, :exclude, :swagger_config, :hooked_methods, :builtin_hooks
|
230
231
|
|
231
232
|
def initialize(name,
|
232
233
|
packages: [],
|
234
|
+
swagger_config: Swagger::Configuration.new,
|
233
235
|
exclude: [],
|
234
236
|
functions: [])
|
235
237
|
@name = name
|
236
238
|
@appmap_dir = AppMap::DEFAULT_APPMAP_DIR
|
237
239
|
@packages = packages
|
240
|
+
@swagger_config = swagger_config
|
238
241
|
@hook_paths = Set.new(packages.map(&:path))
|
239
242
|
@exclude = exclude
|
240
243
|
@builtin_hooks = BUILTIN_HOOKS
|
@@ -351,6 +354,11 @@ module AppMap
|
|
351
354
|
end
|
352
355
|
end
|
353
356
|
|
357
|
+
if config_data['swagger']
|
358
|
+
swagger_config = Swagger::Configuration.load(config_data['swagger'])
|
359
|
+
config_params[:swagger_config] = swagger_config
|
360
|
+
end
|
361
|
+
|
354
362
|
Config.new name, config_params
|
355
363
|
end
|
356
364
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'appmap/event'
|
4
|
+
require 'appmap/util'
|
4
5
|
|
5
6
|
module AppMap
|
6
7
|
module Handler
|
@@ -38,7 +39,7 @@ module AppMap
|
|
38
39
|
headers: headers
|
39
40
|
}.compact
|
40
41
|
|
41
|
-
unless
|
42
|
+
unless Util.blank?(params)
|
42
43
|
h[:message] = params.keys.map do |key|
|
43
44
|
val = params[key]
|
44
45
|
{
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'appmap/event'
|
4
4
|
require 'appmap/hook'
|
5
|
+
require 'appmap/util'
|
5
6
|
|
6
7
|
module AppMap
|
7
8
|
module Handler
|
@@ -40,7 +41,7 @@ module AppMap
|
|
40
41
|
headers: headers,
|
41
42
|
}.compact
|
42
43
|
|
43
|
-
unless
|
44
|
+
unless Util.blank?(params)
|
44
45
|
h[:message] = params.keys.map do |key|
|
45
46
|
val = params[key]
|
46
47
|
{
|
data/lib/appmap/metadata.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'appmap/util'
|
4
|
+
|
3
5
|
module AppMap
|
4
6
|
module Metadata
|
5
7
|
class << self
|
@@ -40,9 +42,9 @@ module AppMap
|
|
40
42
|
git_sha = `git rev-parse HEAD`.strip
|
41
43
|
git_status = `git status -s`.split("\n").map(&:strip)
|
42
44
|
git_last_annotated_tag = `git describe --abbrev=0 2>/dev/null`.strip
|
43
|
-
git_last_annotated_tag = nil if
|
45
|
+
git_last_annotated_tag = nil if Util.blank?(git_last_annotated_tag)
|
44
46
|
git_last_tag = `git describe --abbrev=0 --tags 2>/dev/null`.strip
|
45
|
-
git_last_tag = nil if
|
47
|
+
git_last_tag = nil if Util.blank?(git_last_tag)
|
46
48
|
git_commits_since_last_annotated_tag = `git describe`.strip =~ /-(\d+)-(\w+)$/[1] rescue 0 if git_last_annotated_tag
|
47
49
|
git_commits_since_last_tag = `git describe --tags`.strip =~ /-(\d+)-(\w+)$/[1] rescue 0 if git_last_tag
|
48
50
|
|
data/lib/appmap/minitest.rb
CHANGED
data/lib/appmap/railtie.rb
CHANGED
@@ -5,8 +5,8 @@ module AppMap
|
|
5
5
|
class Railtie < ::Rails::Railtie
|
6
6
|
initializer 'appmap.remote_recording' do
|
7
7
|
require 'appmap/middleware/remote_recording'
|
8
|
-
Rails.application.config.middleware.
|
9
|
-
|
8
|
+
Rails.application.config.middleware.insert_before \
|
9
|
+
ActionDispatch::Executor,
|
10
10
|
AppMap::Middleware::RemoteRecording
|
11
11
|
end
|
12
12
|
|