appmap 0.100.0 → 0.102.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.
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