appmap 0.100.0 → 0.102.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5f52fa6b2d5e7414553f16fbcf018b4d32214bdfcda4afd2567d9bef11203979
4
- data.tar.gz: 0d456c7e95dc01ae731bbe9def89ba1585651412d6d8a35eaa2f9c4f83580d2f
3
+ metadata.gz: 1df97ff2f7c62ce830193389327e102a89798678350dbc653aecc98157e502cb
4
+ data.tar.gz: ff14a72537014f549a5094b592a6dd28e9a6658679e0c411529d7c4c12491822
5
5
  SHA512:
6
- metadata.gz: a07b7341627a96c8ef21930d21a095e9cf849cf06b882d980ec670ce07003dc28e68d2a30e930fb203bf4315ca7aba1f60d43e5d7053d2e56e598ed7d6709302
7
- data.tar.gz: 691c992e647a2760de0ae0ec75c00efb6824b008abd85f6506c31d34175e52d178d5e3297ab3414eb918fc3e083bba208b0b04c9c74f763330bc4333eb078ce1
6
+ metadata.gz: 21781f0d7b9d61d72cd6b442b1105a1eabd19ba07ccca62bb8fd5acaede9e6db2a3cf5594a80c1270ff574d977b709c22031a12a88361cd36fe3013e5238cb03
7
+ data.tar.gz: bcc9fd8526da90172d0f7f159a1c4a61a0245e70d1d800f38b98e1d13f0a35ee26898c064107a0de5eb3f7d11d1eecf98c12df1f14a4c37cb72582a1a6bdcf1d
data/CHANGELOG.md CHANGED
@@ -1,3 +1,22 @@
1
+ # [0.102.0](https://github.com/getappmap/appmap-ruby/compare/v0.101.0...v0.102.0) (2023-07-18)
2
+
3
+
4
+ ### Features
5
+
6
+ * Discourage conflicting recording methods ([f86303b](https://github.com/getappmap/appmap-ruby/commit/f86303bf1b62d5131d9ed2c10e01225ec21c1405))
7
+
8
+ # [0.101.0](https://github.com/getappmap/appmap-ruby/compare/v0.100.0...v0.101.0) (2023-07-17)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * Auto-enable tracing on block recording ([59886b6](https://github.com/getappmap/appmap-ruby/commit/59886b6b4720240e9f961a8b76f3035eaf3be44e))
14
+
15
+
16
+ ### Features
17
+
18
+ * Record RSwag ([a60d480](https://github.com/getappmap/appmap-ruby/commit/a60d4803feeab519ef4eae1702da00e3dc2dd4ea))
19
+
1
20
  # [0.100.0](https://github.com/getappmap/appmap-ruby/compare/v0.99.4...v0.100.0) (2023-07-11)
2
21
 
3
22
 
data/lib/appmap/agent.rb CHANGED
@@ -73,6 +73,7 @@ module AppMap
73
73
  # and returns an AppMap as a Hash.
74
74
  def record
75
75
  tracer = tracing.trace
76
+ tracer.enable
76
77
  begin
77
78
  yield
78
79
  ensure
@@ -1,13 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'appmap'
4
- require 'appmap/util'
3
+ require_relative '../appmap'
4
+ require_relative './util'
5
+ require_relative './detect_enabled'
5
6
  require 'fileutils'
6
7
 
7
8
  module AppMap
8
9
  module Cucumber
9
10
  APPMAP_OUTPUT_DIR = 'tmp/appmap/cucumber'
10
-
11
+
11
12
  ScenarioAttributes = Struct.new(:name, :feature, :feature_group)
12
13
 
13
14
  ProviderStruct = Struct.new(:scenario) do
@@ -43,11 +44,13 @@ module AppMap
43
44
 
44
45
  class << self
45
46
  def init
47
+ AppMap::DetectEnabled.discourage_conflicting_recording_methods :cucumber
48
+
46
49
  warn 'Configuring AppMap recorder for Cucumber'
47
50
 
48
51
  FileUtils.mkdir_p APPMAP_OUTPUT_DIR
49
52
  end
50
-
53
+
51
54
  def write_scenario(scenario, appmap)
52
55
  appmap['metadata'] = update_metadata(scenario, appmap['metadata'])
53
56
  scenario_filename = AppMap::Util.scenario_filename(appmap['metadata']['name'])
@@ -62,7 +65,7 @@ module AppMap
62
65
  def run
63
66
  init
64
67
  end
65
-
68
+
66
69
  protected
67
70
 
68
71
  def cucumber_version
@@ -9,6 +9,32 @@ module AppMap
9
9
  @@detected_for_method = {}
10
10
 
11
11
  class << self
12
+ def discourage_conflicting_recording_methods(recording_method)
13
+ return if ENV['APPMAP_DISCOURAGE_CONFLICTING_RECORDING_METHODS'] == 'false'
14
+
15
+ return unless enabled?(recording_method.to_sym) && enabled?(:requests)
16
+
17
+ warn Util.color <<~MSG, :yellow
18
+ AppMap recording is enabled for both 'requests' and '#{recording_method}'. This is not recommended
19
+ because the recordings will contain duplicitive information, and in some case may conflict with each other.
20
+ MSG
21
+
22
+ return unless ENV['APPMAP'] == 'true'
23
+
24
+ warn Util.color <<~MSG, :yellow
25
+ The environment contains APPMAP=true, which is not recommended in this application environment because
26
+ it enables all recording methods. Consider letting AppMap detect the appropriate recording method,
27
+ or explicitly enabling only the recording methods you want to use using environment variables like
28
+ APPMAP_RECORD_REQUESTS, APPMAP_RECORD_RSPEC, etc.
29
+
30
+ See https://appmap.io/docs/reference/appmap-ruby.html#advanced-runtime-options for more information.
31
+ MSG
32
+ end
33
+
34
+ def enabled?(recording_method)
35
+ new(recording_method).enabled?
36
+ end
37
+
12
38
  def clear_cache
13
39
  @@detected_for_method = {}
14
40
  end
@@ -19,20 +45,20 @@ module AppMap
19
45
  end
20
46
 
21
47
  def enabled?
22
- unless @@detected_for_method[@recording_method].nil?
23
- return @@detected_for_method[@recording_method]
24
- end
48
+ return @@detected_for_method[@recording_method] unless @@detected_for_method[@recording_method].nil?
25
49
 
26
- raise "Unrecognized recording method: #{@recording_method}" if @recording_method && !AppMap::RECORDING_METHODS.member?(@recording_method)
50
+ if @recording_method && !AppMap::RECORDING_METHODS.member?(@recording_method)
51
+ raise "Unrecognized recording method: #{@recording_method}"
52
+ end
27
53
 
28
54
  message, enabled, enabled_by_env = detect_enabled
29
55
 
30
56
  @@detected_for_method[@recording_method] = enabled
31
57
 
32
- if @recording_method
33
- if enabled && enabled_by_app_env?
34
- warn AppMap::Util.color("AppMap #{@recording_method.nil? ? '' : "#{@recording_method} "}recording is enabled because #{message}", :magenta)
35
- end
58
+ if @recording_method && (enabled && enabled_by_app_env?)
59
+ warn AppMap::Util.color(
60
+ "AppMap #{@recording_method.nil? ? '' : "#{@recording_method} "}recording is enabled because #{message}", :magenta
61
+ )
36
62
  end
37
63
 
38
64
  enabled
@@ -49,48 +75,41 @@ module AppMap
49
75
  ]
50
76
 
51
77
  message, enabled = []
52
- while enabled.nil? && !detection_functions.empty?
53
- message, enabled = method(detection_functions.shift).call
54
- end
78
+ message, enabled = method(detection_functions.shift).call while enabled.nil? && !detection_functions.empty?
55
79
 
56
- unless enabled.nil?
57
- _, enabled_by_env = enabled_by_app_env?
58
- return [ message, enabled, enabled_by_env ]
59
- else
60
- return [ 'it is not enabled by any configuration or framework', false, false ]
61
- end
80
+ return [ 'it is not enabled by any configuration or framework', false, false ] if enabled.nil?
81
+
82
+ _, enabled_by_env = enabled_by_app_env?
83
+ [ message, enabled, enabled_by_env ]
62
84
  end
63
85
 
64
86
  def enabled_by_testing?
65
- if %i[rspec minitest cucumber].member?(@recording_method)
66
- [ "running tests with #{@recording_method}", true ]
67
- end
87
+ return unless %i[rspec minitest cucumber].member?(@recording_method)
88
+
89
+ [ "running tests with #{@recording_method}", true ]
68
90
  end
69
91
 
70
92
  def enabled_by_app_env?
71
93
  env_name, app_env = detect_app_env
72
- if @recording_method.nil?
73
- return [ "#{env_name} is '#{app_env}'", true ] if %w[test development].member?(app_env)
74
- end
94
+ return [ "#{env_name} is '#{app_env}'", true ] if @recording_method.nil? && %w[test development].member?(app_env)
75
95
 
76
- if %i[remote requests].member?(@recording_method)
77
- return [ "#{env_name} is '#{app_env}'", true ] if app_env == 'development'
78
- end
96
+ return unless %i[remote requests].member?(@recording_method)
97
+ return [ "#{env_name} is '#{app_env}'", true ] if app_env == 'development'
79
98
  end
80
99
 
81
100
  def detect_app_env
82
101
  if rails_env
83
- return [ 'RAILS_ENV', rails_env ]
102
+ [ 'RAILS_ENV', rails_env ]
84
103
  elsif ENV['APP_ENV']
85
- return [ 'APP_ENV', ENV['APP_ENV']]
104
+ [ 'APP_ENV', ENV['APP_ENV']]
86
105
  end
87
106
  end
88
107
 
89
108
  def globally_enabled?
90
109
  # Don't auto-enable request recording in the 'test' environment, because users probably don't want
91
110
  # AppMaps of both test cases and requests. Requests recording can always be enabled by APPMAP_RECORD_REQUESTS=true.
92
- requests_recording_in_test = -> () { [ :requests ].member?(@recording_method) && detect_app_env == 'test' }
93
- [ 'APPMAP=true', true ] if ENV['APPMAP'] == 'true' && !requests_recording_in_test.()
111
+ requests_recording_in_test = -> { [ :requests ].member?(@recording_method) && detect_app_env == 'test' }
112
+ [ 'APPMAP=true', true ] if ENV['APPMAP'] == 'true' && !requests_recording_in_test.call
94
113
  end
95
114
 
96
115
  def globally_disabled?
@@ -114,7 +133,7 @@ module AppMap
114
133
  def rails_env
115
134
  return Rails.env if defined?(::Rails::Railtie)
116
135
 
117
- return ENV['RAILS_ENV']
136
+ ENV.fetch('RAILS_ENV', nil)
118
137
  end
119
138
  end
120
139
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'appmap'
4
- require 'appmap/util'
3
+ require_relative '../appmap'
4
+ require_relative './util'
5
+ require_relative './detect_enabled'
5
6
  require 'fileutils'
6
7
  require 'active_support'
7
8
  require 'active_support/core_ext'
@@ -32,7 +33,9 @@ module AppMap
32
33
 
33
34
  def finish(failures, exception)
34
35
  failed = failures.any? || exception
35
- warn "Finishing recording of #{failed ? 'failed ' : ''} test #{test.class}.#{test.name}" if AppMap::Minitest::LOG
36
+ if AppMap::Minitest::LOG
37
+ warn "Finishing recording of #{failed ? 'failed ' : ''} test #{test.class}.#{test.name}"
38
+ end
36
39
  warn "Exception: #{exception}" if exception && AppMap::Minitest::LOG
37
40
 
38
41
  if failed
@@ -78,7 +81,8 @@ module AppMap
78
81
  end
79
82
 
80
83
  def begin_test(test, name)
81
- AppMap.info 'Configuring AppMap recorder for Minitest' if first_recording?
84
+ AppMap::DetectEnabled.discourage_conflicting_recording_methods :minitest if first_recording?
85
+
82
86
  @recording_count += 1
83
87
 
84
88
  @recordings_by_test[test.object_id] = Recording.new(test, name)
@@ -107,24 +111,22 @@ module AppMap
107
111
  m[:frameworks] ||= []
108
112
  m[:frameworks] << {
109
113
  name: 'minitest',
110
- version: Gem.loaded_specs['minitest']&.version&.to_s,
114
+ version: Gem.loaded_specs['minitest']&.version&.to_s
111
115
  }
112
116
  m[:recorder] = {
113
117
  name: 'minitest',
114
- type: 'tests',
118
+ type: 'tests'
115
119
  }
116
120
  m[:test_status] = test_status
117
121
  m[:test_failure] = test_failure if test_failure
118
- if exception
119
- m[:exception] = Util.format_exception(exception)
120
- end
122
+ m[:exception] = Util.format_exception(exception) if exception
121
123
  end
122
124
 
123
125
  appmap = {
124
126
  version: AppMap::APPMAP_FORMAT_VERSION,
125
127
  metadata: metadata,
126
128
  classMap: class_map,
127
- events: events,
129
+ events: events
128
130
  }.compact
129
131
  fname = AppMap::Util.scenario_filename(name)
130
132
 
data/lib/appmap/rspec.rb CHANGED
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'appmap'
4
- require 'appmap/util'
3
+ require_relative '../appmap'
4
+ require_relative './util'
5
+ require_relative './detect_enabled'
5
6
  require 'set'
6
7
  require 'fileutils'
7
8
 
@@ -68,7 +69,7 @@ module AppMap
68
69
  example_group.parent_groups.first
69
70
  end
70
71
 
71
- example_group_parent != example_group ? ScopeExampleGroup.new(example_group_parent) : nil
72
+ example_group_parent == example_group ? nil : ScopeExampleGroup.new(example_group_parent)
72
73
  end
73
74
  end
74
75
 
@@ -87,7 +88,7 @@ module AppMap
87
88
 
88
89
  warn "Starting recording of example #{example}@#{source_location}" if AppMap::RSpec::LOG
89
90
  @trace = AppMap.tracing.trace
90
- @webdriver_port = webdriver_port.()
91
+ @webdriver_port = webdriver_port.call
91
92
  end
92
93
 
93
94
  def source_location
@@ -147,7 +148,7 @@ module AppMap
147
148
  end
148
149
  end
149
150
 
150
- @recordings_by_example = {}
151
+ @recordings_by_example = {}.tap(&:compare_by_identity)
151
152
  @event_methods = Set.new
152
153
  @recording_count = 0
153
154
 
@@ -161,34 +162,38 @@ module AppMap
161
162
  end
162
163
 
163
164
  def begin_spec(example)
164
- AppMap.info 'Configuring AppMap recorder for RSpec' if first_recording?
165
- @recording_count += 1
166
-
167
- recording = if example.metadata[:appmap] != false
168
- Recording.new(example)
169
- else
170
- :false
171
- end
165
+ AppMap::DetectEnabled.discourage_conflicting_recording_methods :rspec if first_recording?
172
166
 
173
- @recordings_by_example[example.object_id] = recording
167
+ @recording_count += 1
168
+ # Disable RSpec recording for RSwag, because all the action happens in the before block.
169
+ # The example is empty except for assertions. So RSwag has its own recorder, and RSpec
170
+ # recording is disabled so it won't clobber the AppMap with empty data.
171
+ recording = if example.metadata[:appmap] == false || example.metadata[:rswag]
172
+ :disabled
173
+ else
174
+ Recording.new(example)
175
+ end
176
+
177
+ @recordings_by_example[example] = recording
174
178
  end
175
179
 
176
180
  def end_spec(example, exception:)
177
- recording = @recordings_by_example.delete(example.object_id)
181
+ recording = @recordings_by_example.delete(example)
178
182
  return warn "No recording found for #{example}" unless recording
179
183
 
180
- recording.finish example.execution_result.exception || exception, exception unless recording == :false
184
+ recording.finish example.execution_result.exception || exception, exception unless recording == :disabled
181
185
  end
182
186
 
183
187
  def config
184
- @config or raise "AppMap is not configured"
188
+ @config or raise 'AppMap is not configured'
185
189
  end
186
190
 
187
191
  def add_event_methods(event_methods)
188
192
  @event_methods += event_methods
189
193
  end
190
194
 
191
- def save(name:, class_map:, source_location:, test_status:, test_failure:, exception:, events:)
195
+ def save(name:, class_map:, source_location:, test_status:, test_failure:, exception:, events:, frameworks: [],
196
+ recorder: nil)
192
197
  metadata = AppMap::RSpec.metadata.tap do |m|
193
198
  m[:name] = name
194
199
  m[:source_location] = source_location
@@ -198,7 +203,8 @@ module AppMap
198
203
  name: 'rspec',
199
204
  version: Gem.loaded_specs['rspec-core']&.version&.to_s
200
205
  }
201
- m[:recorder] = {
206
+ m[:frameworks] += frameworks
207
+ m[:recorder] = recorder || {
202
208
  name: 'rspec',
203
209
  type: 'tests'
204
210
  }
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'appmap'
4
+
5
+ module AppMap
6
+ module Rswag
7
+ def self.record(metadata, &block)
8
+ description = metadata[:full_description]
9
+ warn "Recording of RSwag test #{description}" if AppMap::RSpec::LOG
10
+ source_location = (metadata[:example_group] || {})[:location]
11
+
12
+ appmap = AppMap.record(&block)
13
+
14
+ events = appmap['events']
15
+ class_map = appmap['classMap']
16
+
17
+ exception = (events.last || {})[:exception]
18
+ failed = true if exception
19
+ warn "Finishing recording of #{failed ? 'failed ' : ''} RSwag test #{description}" if AppMap::RSpec::LOG
20
+ warn "Exception: #{exception}" if exception && AppMap::RSpec::LOG
21
+
22
+ if failed
23
+ warn "Failure exception: #{exception}" if AppMap::RSpec::LOG
24
+ test_failure = Util.extract_test_failure(exception)
25
+ end
26
+
27
+ AppMap::RSpec.save name: description,
28
+ class_map: class_map,
29
+ source_location: source_location,
30
+ test_status: exception ? 'failed' : 'succeeded',
31
+ test_failure: test_failure,
32
+ exception: exception,
33
+ events: events,
34
+ frameworks: [
35
+ { name: 'rswag',
36
+ version: Gem.loaded_specs['rswag-specs']&.version&.to_s }
37
+ ],
38
+ recorder: {
39
+ name: 'rswag',
40
+ type: 'tests'
41
+ }
42
+ end
43
+
44
+ class << self
45
+ def enabled?
46
+ RSpec.enabled? && defined?(Rswag)
47
+ end
48
+ end
49
+ end
50
+
51
+ if Rswag.enabled?
52
+ require 'rswag'
53
+ require 'rswag/specs'
54
+ require 'appmap/rspec'
55
+
56
+ module ::Rswag
57
+ module Specs
58
+ module ExampleHelpers
59
+ alias submit_request_without_appmap submit_request
60
+
61
+ def submit_request(metadata)
62
+ AppMap::Rswag.record(metadata) do
63
+ submit_request_without_appmap(metadata)
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
data/lib/appmap/trace.rb CHANGED
@@ -24,7 +24,7 @@ module AppMap
24
24
  return nil if source_location.nil? || source_location.first.start_with?('<')
25
25
 
26
26
  # Do not use method_source's comment method because it's slow
27
- @comment ||= RubyMethod.last_comment *source_location
27
+ @comment ||= RubyMethod.last_comment(*source_location)
28
28
  rescue Errno::EINVAL, Errno::ENOENT
29
29
  nil
30
30
  end
@@ -41,8 +41,6 @@ module AppMap
41
41
  @package.labels
42
42
  end
43
43
 
44
- private
45
-
46
44
  # Read file and get last comment before line.
47
45
  def self.last_comment(file, line_number)
48
46
  File.open(file) do |f|
@@ -114,19 +112,19 @@ module AppMap
114
112
  end
115
113
 
116
114
  def initialize
117
- @@stacks ||= Hash.new
115
+ @@stacks ||= {}
118
116
  end
119
117
 
120
118
  def record(event)
121
119
  stack = caller.select { |line| !line.index('/lib/appmap/') }[0...StackPrinter.depth].join("\n ")
122
120
  stack_hash = Digest::SHA256.hexdigest(stack)
123
- unless @@stacks[stack_hash]
124
- @@stacks[stack_hash] = stack
125
- puts
126
- puts 'Event: ' + event.to_h.map { |k, v| [ "#{k}: #{v}" ] }.join(", ")
127
- puts ' ' + stack
128
- puts
129
- end
121
+ return if @@stacks[stack_hash]
122
+
123
+ @@stacks[stack_hash] = stack
124
+ puts
125
+ puts 'Event: ' + event.to_h.map { |k, v| [ "#{k}: #{v}" ] }.join(', ')
126
+ puts ' ' + stack
127
+ puts
130
128
  end
131
129
  end
132
130
 
@@ -163,7 +161,9 @@ module AppMap
163
161
  def record_event(event, package: nil, defined_class: nil, method: nil)
164
162
  return unless @enabled
165
163
 
166
- raise "Expected event in thread #{@thread_id}, got #{event.thread_id}" if @thread_id && @thread_id != event.thread_id
164
+ if @thread_id && @thread_id != event.thread_id
165
+ raise "Expected event in thread #{@thread_id}, got #{event.thread_id}"
166
+ end
167
167
 
168
168
  @stack_printer.record(event) if @stack_printer
169
169
  @last_package_for_thread[Thread.current.object_id] = package if package
data/lib/appmap/util.rb CHANGED
@@ -25,9 +25,17 @@ module AppMap
25
25
  package_tokens = name.split('/')
26
26
 
27
27
  class_and_name = package_tokens.pop
28
- class_name, function_name, static = class_and_name.include?('.') ? class_and_name.split('.', 2) + [ true ] : class_and_name.split('#', 2) + [ false ]
28
+ class_name, function_name, static = if class_and_name.include?('.')
29
+ class_and_name.split('.',
30
+ 2) + [ true ]
31
+ else
32
+ class_and_name.split(
33
+ '#', 2
34
+ ) + [ false ]
35
+ end
29
36
 
30
37
  raise "Malformed fully-qualified function name #{name}" unless function_name
38
+
31
39
  [ package_tokens.empty? ? 'ruby' : package_tokens.join('/'), class_name, static, function_name ]
32
40
  end
33
41
 
@@ -70,20 +78,20 @@ module AppMap
70
78
  def sanitize_paths(h)
71
79
  require 'hashie'
72
80
  h.extend(Hashie::Extensions::DeepLocate)
73
- keys = %i(path location)
74
- h.deep_locate ->(k,v,o) {
81
+ keys = %i[path location]
82
+ h.deep_locate lambda { |k, _v, o|
75
83
  next unless keys.include?(k)
76
-
77
- fix = ->(v) {v.gsub(%r{#{Gem.dir}/gems/.*(?=lib)}, '')}
78
- keys.each {|k| o[k] = fix.(o[k]) if o[k] }
84
+
85
+ fix = ->(v) { v.gsub(%r{#{Gem.dir}/gems/.*(?=lib)}, '') }
86
+ keys.each { |k| o[k] = fix.call(o[k]) if o[k] }
79
87
  }
80
88
 
81
89
  h
82
90
  end
83
-
91
+
84
92
  # sanitize_event removes ephemeral values from an event, making
85
93
  # events easier to compare across runs.
86
- def sanitize_event(event, &block)
94
+ def sanitize_event(event)
87
95
  event.delete(:thread_id)
88
96
  event.delete(:elapsed)
89
97
  event.delete(:elapsed_instrumentation)
@@ -114,8 +122,8 @@ module AppMap
114
122
  blank?(headers) ? nil : headers
115
123
  end
116
124
 
117
- if !env['rack.version']
118
- warn "Request headers does not contain rack.version. HTTP_ prefix is not expected."
125
+ unless env['rack.version']
126
+ warn 'Request headers does not contain rack.version. HTTP_ prefix is not expected.'
119
127
  return finalize_headers.call(env.dup)
120
128
  end
121
129
 
@@ -123,18 +131,18 @@ module AppMap
123
131
  # Apparently, it's following the CGI spec in doing so.
124
132
  # https://datatracker.ietf.org/doc/html/rfc3875#section-4.1.18
125
133
  matching_headers = env
126
- .select { |k,v| k.to_s.start_with? 'HTTP_' }
127
- .merge(
128
- 'CONTENT_TYPE' => env['CONTENT_TYPE'],
129
- 'CONTENT_LENGTH' => env['CONTENT_LENGTH'],
130
- 'AUTHORIZATION' => env['AUTHORIZATION']
131
- )
132
- .reject { |k,v| blank?(v) }
133
- .each_with_object({}) do |kv, memo|
134
- key = kv[0].sub(/^HTTP_/, '').split('_').map(&:capitalize).join('-')
135
- value = kv[1]
136
- memo[key] = value
137
- end
134
+ .select { |k, _v| k.to_s.start_with? 'HTTP_' }
135
+ .merge(
136
+ 'CONTENT_TYPE' => env['CONTENT_TYPE'],
137
+ 'CONTENT_LENGTH' => env['CONTENT_LENGTH'],
138
+ 'AUTHORIZATION' => env['AUTHORIZATION']
139
+ )
140
+ .reject { |_k, v| blank?(v) }
141
+ .each_with_object({}) do |kv, memo|
142
+ key = kv[0].sub(/^HTTP_/, '').split('_').map(&:capitalize).join('-')
143
+ value = kv[1]
144
+ memo[key] = value
145
+ end
138
146
  finalize_headers.call(matching_headers)
139
147
  end
140
148
 
@@ -143,7 +151,7 @@ module AppMap
143
151
  is_bundled_path = -> { path.index(Bundler.bundle_path.to_s) == 0 }
144
152
  is_vendored_path = -> { path.index(File.join(Dir.pwd, 'vendor/bundle')) == 0 }
145
153
 
146
- if is_local_path.() && !is_bundled_path.() && !is_vendored_path.()
154
+ if is_local_path.call && !is_bundled_path.call && !is_vendored_path.call
147
155
  path[Dir.pwd.length + 1..-1]
148
156
  else
149
157
  path
@@ -153,7 +161,7 @@ module AppMap
153
161
  def format_exception(exception)
154
162
  {
155
163
  class: exception.class.name,
156
- message: AppMap::Event::MethodEvent.display_string(exception.to_s),
164
+ message: AppMap::Event::MethodEvent.display_string(exception.to_s)
157
165
  }
158
166
  end
159
167
 
@@ -164,7 +172,10 @@ module AppMap
164
172
  first_location = exception.backtrace_locations&.find do |location|
165
173
  !Pathname.new(normalize_path(location.absolute_path || location.path)).absolute?
166
174
  end
167
- test_failure[:location] = [ normalize_path(first_location.path), first_location.lineno ].join(':') if first_location
175
+ if first_location
176
+ test_failure[:location] =
177
+ [ normalize_path(first_location.path), first_location.lineno ].join(':')
178
+ end
168
179
  end
169
180
  end
170
181
 
@@ -175,7 +186,7 @@ module AppMap
175
186
  tokens = path.split('/')
176
187
  tokens.map do |token|
177
188
  # stop matching if an ending ) is found
178
- token.gsub(/^:(.*[^\)])/, '{\1}')
189
+ token.gsub(/^:(.*[^)])/, '{\1}')
179
190
  end.join('/')
180
191
  end
181
192
 
@@ -196,22 +207,23 @@ module AppMap
196
207
 
197
208
  def color(text, color, bold: false)
198
209
  color = Util.const_get(color.to_s.upcase) if color.is_a?(Symbol)
199
- bold = bold ? BOLD : ""
210
+ bold = bold ? BOLD : ''
200
211
  "#{bold}#{color}#{text}#{CLEAR}"
201
212
  end
202
213
 
203
214
  def classify(word)
204
- word.split(/[\-_]/).map(&:capitalize).join
215
+ word.split(/[-_]/).map(&:capitalize).join
205
216
  end
206
217
 
207
218
  # https://api.rubyonrails.org/v6.1.3.2/classes/ActiveSupport/Inflector.html#method-i-underscore
208
219
  def underscore(camel_cased_word)
209
220
  return camel_cased_word unless /[A-Z-]|::/.match?(camel_cased_word)
210
- word = camel_cased_word.to_s.gsub("::", "/")
221
+
222
+ word = camel_cased_word.to_s.gsub('::', '/')
211
223
  # word.gsub!(inflections.acronyms_underscore_regex) { "#{$1 && '_' }#{$2.downcase}" }
212
224
  word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
213
225
  word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
214
- word.tr!("-", "_")
226
+ word.tr!('-', '_')
215
227
  word.downcase!
216
228
  word
217
229
  end
@@ -223,7 +235,7 @@ module AppMap
223
235
 
224
236
  def blank?(obj)
225
237
  return true if obj.nil?
226
-
238
+
227
239
  return true if obj.is_a?(String) && obj == ''
228
240
 
229
241
  return true if obj.respond_to?(:length) && obj.length == 0
@@ -3,7 +3,7 @@
3
3
  module AppMap
4
4
  URL = 'https://github.com/applandinc/appmap-ruby'
5
5
 
6
- VERSION = '0.100.0'
6
+ VERSION = '0.102.0'
7
7
 
8
8
  APPMAP_FORMAT_VERSION = '1.12.0'
9
9
 
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.100.0
4
+ version: 0.102.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: 2023-07-11 00:00:00.000000000 Z
11
+ date: 2023-07-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: method_source
@@ -425,6 +425,7 @@ files:
425
425
  - lib/appmap/record.rb
426
426
  - lib/appmap/recording_methods.rb
427
427
  - lib/appmap/rspec.rb
428
+ - lib/appmap/rswag.rb
428
429
  - lib/appmap/service/config_analyzer.rb
429
430
  - lib/appmap/service/guesser.rb
430
431
  - lib/appmap/service/integration_test_path_finder.rb