appmap 0.53.0 → 0.54.0

Sign up to get free protection for your applications and to get access to all the features.
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