appmap 0.53.0 → 0.54.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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/lib/appmap.rb +28 -110
  4. data/lib/appmap/agent.rb +115 -0
  5. data/lib/appmap/class_map.rb +2 -2
  6. data/lib/appmap/config.rb +11 -3
  7. data/lib/appmap/handler/net_http.rb +2 -1
  8. data/lib/appmap/handler/rails/request_handler.rb +2 -1
  9. data/lib/appmap/metadata.rb +4 -2
  10. data/lib/appmap/minitest.rb +2 -0
  11. data/lib/appmap/railtie.rb +2 -2
  12. data/lib/appmap/rspec.rb +5 -3
  13. data/lib/appmap/swagger.rb +2 -0
  14. data/lib/appmap/swagger/configuration.rb +70 -0
  15. data/lib/appmap/swagger/markdown_descriptions.rb +43 -0
  16. data/lib/appmap/swagger/rake_tasks.rb +43 -0
  17. data/lib/appmap/swagger/stable.rb +37 -0
  18. data/lib/appmap/version.rb +1 -1
  19. data/package.json +0 -1
  20. data/spec/config_spec.rb +0 -1
  21. data/spec/fixtures/hook/.gitignore +2 -0
  22. data/spec/fixtures/hook/app/controllers/api/api_keys_controller.rb +1 -0
  23. data/spec/fixtures/hook/app/controllers/organizations_controller.rb +1 -0
  24. data/spec/fixtures/hook/app/models/api_key.rb +1 -0
  25. data/spec/fixtures/hook/app/models/configuration.rb +1 -0
  26. data/spec/fixtures/hook/app/models/show.rb +1 -0
  27. data/spec/fixtures/hook/app/models/user.rb +1 -0
  28. data/spec/fixtures/hook/revoke_api_key.appmap.json +847 -0
  29. data/spec/fixtures/hook/spec/api_spec.rb +1 -0
  30. data/spec/fixtures/hook/spec/user_spec.rb +1 -0
  31. data/spec/fixtures/hook/user_page_scenario.appmap.json +1722 -0
  32. data/spec/fixtures/rails5_users_app/config/environments/test.rb +3 -0
  33. data/spec/fixtures/rails6_users_app/Dockerfile +0 -1
  34. data/spec/fixtures/rails6_users_app/appmap.yml +3 -1
  35. data/spec/fixtures/rails6_users_app/config/environments/test.rb +3 -0
  36. data/spec/fixtures/rails6_users_app/lib/tasks/appmap.rake +13 -0
  37. data/spec/rails_recording_spec.rb +1 -1
  38. data/spec/swagger/swagger_spec.rb +47 -0
  39. data/test/gem_test.rb +1 -0
  40. metadata +21 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 69fc6d5fce636d669cb33a9564a3c504eb255cb13a81985154589eb7cc6f9879
4
- data.tar.gz: f2400bbda425b4e0f8d72b52d7edfcf761c8356638691074c79b72fdbca9f086
3
+ metadata.gz: a00ec7ef6ec83aebf28d11c8004c89885ae32562ef6384c6c7880ca09d380027
4
+ data.tar.gz: a16129c01467f043eb18786ea8f3cae2df65226b924e6f85b40614f7d563e8a1
5
5
  SHA512:
6
- metadata.gz: 17016392e9b2931c961bf1cdb3c7f832af15896201b395995c124befb7de1987ee43997f9186c329f9fe6474101158c06a0772e8bf0bd6bbd9b9b4ddd84defeb
7
- data.tar.gz: 29fe408c9a44ec5cf8ffd410f732d6cc5959e045480c94406a4f9cc4abc2badbc1843f449bba0b8cd5e2b6269c71f8e5d603b9e99a902e63e6692d16af0e4c6f
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
- begin
4
- require 'active_support'
5
- require 'active_support/core_ext'
6
- rescue NameError
7
- warn 'active_support is not available. AppMap execution will continue optimistically without it...'
8
- end
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/util'
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'
@@ -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
@@ -111,7 +111,7 @@ module AppMap
111
111
  end
112
112
 
113
113
  comment = method.comment
114
- function_info[:comment] = comment unless comment.blank?
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].classify).new(info[:name].to_s).tap do |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: exclude.blank? ? nil : exclude,
85
- labels: labels.blank? ? nil : 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 params.blank?
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 params.blank?
44
+ unless Util.blank?(params)
44
45
  h[:message] = params.keys.map do |key|
45
46
  val = params[key]
46
47
  {
@@ -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 git_last_annotated_tag.blank?
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 git_last_tag.blank?
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
 
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'appmap/util'
4
+ require 'active_support'
5
+ require 'active_support/core_ext'
4
6
 
5
7
  module AppMap
6
8
  # Integration of AppMap with Minitest. When enabled with APPMAP=true, the AppMap tracer will
@@ -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.insert_after \
9
- Rails::Rack::Logger,
8
+ Rails.application.config.middleware.insert_before \
9
+ ActionDispatch::Executor,
10
10
  AppMap::Middleware::RemoteRecording
11
11
  end
12
12