appmap 0.102.2 → 0.103.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 +4 -4
- data/.rubocop.yml +6 -0
- data/.standard.yml +1 -0
- data/.travis.yml +2 -2
- data/CHANGELOG.md +17 -0
- data/appmap.gemspec +35 -36
- data/lib/appmap/agent.rb +28 -24
- data/lib/appmap/class_map.rb +36 -31
- data/lib/appmap/config.rb +132 -110
- data/lib/appmap/cucumber.rb +25 -25
- data/lib/appmap/detect_enabled.rb +30 -28
- data/lib/appmap/gem_hooks/activejob.yml +0 -1
- data/lib/appmap/hook/method/ruby2.rb +19 -8
- data/lib/appmap/hook/method/ruby3.rb +20 -13
- data/lib/appmap/hook/method.rb +27 -27
- data/lib/appmap/hook/record_around.rb +77 -0
- data/lib/appmap/hook.rb +74 -44
- data/lib/appmap/metadata.rb +6 -18
- data/lib/appmap/middleware/remote_recording.rb +26 -27
- data/lib/appmap/minitest.rb +27 -27
- data/lib/appmap/rspec.rb +37 -37
- data/lib/appmap/trace.rb +14 -12
- data/lib/appmap/util.rb +71 -61
- data/lib/appmap/version.rb +1 -1
- metadata +5 -16
data/lib/appmap/rspec.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require_relative
|
6
|
-
require
|
7
|
-
require
|
3
|
+
require_relative "../appmap"
|
4
|
+
require_relative "util"
|
5
|
+
require_relative "detect_enabled"
|
6
|
+
require "set"
|
7
|
+
require "fileutils"
|
8
8
|
|
9
9
|
module AppMap
|
10
10
|
module RSpec
|
11
|
-
APPMAP_OUTPUT_DIR =
|
12
|
-
LOG = (ENV[
|
11
|
+
APPMAP_OUTPUT_DIR = File.join(AppMap.output_dir, "rspec")
|
12
|
+
LOG = (ENV["APPMAP_DEBUG"] == "true" || ENV["DEBUG"] == "true")
|
13
13
|
|
14
14
|
def self.metadata
|
15
15
|
AppMap.detect_metadata
|
@@ -52,7 +52,7 @@ module AppMap
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def description
|
55
|
-
description? ? description_args.join(
|
55
|
+
description? ? description_args.join(" ") : nil
|
56
56
|
end
|
57
57
|
|
58
58
|
def parent
|
@@ -69,7 +69,7 @@ module AppMap
|
|
69
69
|
example_group.parent_groups.first
|
70
70
|
end
|
71
71
|
|
72
|
-
example_group_parent == example_group ? nil : ScopeExampleGroup.new(example_group_parent)
|
72
|
+
(example_group_parent == example_group) ? nil : ScopeExampleGroup.new(example_group_parent)
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
@@ -83,7 +83,7 @@ module AppMap
|
|
83
83
|
# This is the ugliest thing ever but I don't want to lose it.
|
84
84
|
# All the WebDriver calls are getting app-mapped and it's really unclear
|
85
85
|
# what they are.
|
86
|
-
page.driver.options[:http_client].instance_variable_get(
|
86
|
+
page.driver.options[:http_client].instance_variable_get(:@server_url).port
|
87
87
|
end
|
88
88
|
|
89
89
|
warn "Starting recording of example #{example}@#{source_location}" if AppMap::RSpec::LOG
|
@@ -92,14 +92,14 @@ module AppMap
|
|
92
92
|
end
|
93
93
|
|
94
94
|
def source_location
|
95
|
-
result = example.location_rerun_argument.split(
|
96
|
-
result = result[2..-1] if result.index(
|
95
|
+
result = example.location_rerun_argument.split(":")[0]
|
96
|
+
result = result[2..-1] if result.index("./") == 0
|
97
97
|
result
|
98
98
|
end
|
99
99
|
|
100
100
|
def finish(failure, exception)
|
101
101
|
failed = true if failure || exception
|
102
|
-
warn "Finishing recording of #{failed ?
|
102
|
+
warn "Finishing recording of #{failed ? "failed " : ""} example #{example}" if AppMap::RSpec::LOG
|
103
103
|
warn "Exception: #{exception}" if exception && AppMap::RSpec::LOG
|
104
104
|
|
105
105
|
if failed
|
@@ -130,21 +130,21 @@ module AppMap
|
|
130
130
|
description.reverse!
|
131
131
|
|
132
132
|
normalize = lambda do |desc|
|
133
|
-
desc.gsub(
|
134
|
-
|
135
|
-
|
136
|
-
|
133
|
+
desc.gsub("it should behave like", "")
|
134
|
+
.gsub(/Controller$/, "")
|
135
|
+
.gsub(/\s+/, " ")
|
136
|
+
.strip
|
137
137
|
end
|
138
138
|
|
139
|
-
full_description = normalize.call(description.join(
|
139
|
+
full_description = normalize.call(description.join(" "))
|
140
140
|
|
141
141
|
AppMap::RSpec.save name: full_description,
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
142
|
+
class_map: class_map,
|
143
|
+
source_location: source_location,
|
144
|
+
test_status: exception ? "failed" : "succeeded",
|
145
|
+
test_failure: test_failure,
|
146
|
+
exception: exception,
|
147
|
+
events: events
|
148
148
|
end
|
149
149
|
end
|
150
150
|
|
@@ -169,10 +169,10 @@ module AppMap
|
|
169
169
|
# The example is empty except for assertions. So RSwag has its own recorder, and RSpec
|
170
170
|
# recording is disabled so it won't clobber the AppMap with empty data.
|
171
171
|
recording = if example.metadata[:appmap] == false || example.metadata[:rswag]
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
172
|
+
:disabled
|
173
|
+
else
|
174
|
+
Recording.new(example)
|
175
|
+
end
|
176
176
|
|
177
177
|
@recordings_by_example[example] = recording
|
178
178
|
end
|
@@ -185,7 +185,7 @@ module AppMap
|
|
185
185
|
end
|
186
186
|
|
187
187
|
def config
|
188
|
-
@config or raise
|
188
|
+
@config or raise "AppMap is not configured"
|
189
189
|
end
|
190
190
|
|
191
191
|
def add_event_methods(event_methods)
|
@@ -193,20 +193,20 @@ module AppMap
|
|
193
193
|
end
|
194
194
|
|
195
195
|
def save(name:, class_map:, source_location:, test_status:, test_failure:, exception:, events:, frameworks: [],
|
196
|
-
|
196
|
+
recorder: nil)
|
197
197
|
metadata = AppMap::RSpec.metadata.tap do |m|
|
198
198
|
m[:name] = name
|
199
199
|
m[:source_location] = source_location
|
200
200
|
m[:app] = AppMap.configuration.name
|
201
201
|
m[:frameworks] ||= []
|
202
202
|
m[:frameworks] << {
|
203
|
-
name:
|
204
|
-
version: Gem.loaded_specs[
|
203
|
+
name: "rspec",
|
204
|
+
version: Gem.loaded_specs["rspec-core"]&.version&.to_s
|
205
205
|
}
|
206
206
|
m[:frameworks] += frameworks
|
207
207
|
m[:recorder] = recorder || {
|
208
|
-
name:
|
209
|
-
type:
|
208
|
+
name: "rspec",
|
209
|
+
type: "tests"
|
210
210
|
}
|
211
211
|
m[:test_status] = test_status
|
212
212
|
m[:test_failure] = test_failure if test_failure
|
@@ -242,9 +242,9 @@ module AppMap
|
|
242
242
|
end
|
243
243
|
|
244
244
|
if AppMap::RSpec.enabled?
|
245
|
-
require
|
246
|
-
require
|
247
|
-
require
|
245
|
+
require "active_support/inflector/transliterate"
|
246
|
+
require "rspec/core"
|
247
|
+
require "rspec/core/example"
|
248
248
|
|
249
249
|
module RSpec
|
250
250
|
module Core
|
data/lib/appmap/trace.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "delegate"
|
4
4
|
|
5
5
|
module AppMap
|
6
6
|
module Trace
|
@@ -21,7 +21,7 @@ module AppMap
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def comment
|
24
|
-
return nil if source_location.nil? || source_location.first.start_with?(
|
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
27
|
@comment ||= RubyMethod.last_comment(*source_location)
|
@@ -71,8 +71,8 @@ module AppMap
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
-
def enabled?
|
75
|
-
@tracers.any?
|
74
|
+
def enabled?(thread_id: nil)
|
75
|
+
@tracers.any? { |t| t.enabled?(thread_id: thread_id) }
|
76
76
|
end
|
77
77
|
|
78
78
|
def last_package_for_current_thread
|
@@ -103,11 +103,11 @@ module AppMap
|
|
103
103
|
class StackPrinter
|
104
104
|
class << self
|
105
105
|
def enabled?
|
106
|
-
ENV[
|
106
|
+
ENV["APPMAP_PRINT_STACKS"] == "true"
|
107
107
|
end
|
108
108
|
|
109
109
|
def depth
|
110
|
-
(ENV[
|
110
|
+
(ENV["APPMAP_STACK_DEPTH"] || 20).to_i
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
@@ -116,21 +116,21 @@ module AppMap
|
|
116
116
|
end
|
117
117
|
|
118
118
|
def record(event)
|
119
|
-
stack = caller.select { |line| !line.index(
|
119
|
+
stack = caller.select { |line| !line.index("/lib/appmap/") }[0...StackPrinter.depth].join("\n ")
|
120
120
|
stack_hash = Digest::SHA256.hexdigest(stack)
|
121
121
|
return if @@stacks[stack_hash]
|
122
122
|
|
123
123
|
@@stacks[stack_hash] = stack
|
124
124
|
puts
|
125
|
-
puts
|
126
|
-
puts
|
125
|
+
puts "Event: " + event.to_h.map { |k, v| ["#{k}: #{v}"] }.join(", ")
|
126
|
+
puts " " + stack
|
127
127
|
puts
|
128
128
|
end
|
129
129
|
end
|
130
130
|
|
131
131
|
class Tracer
|
132
132
|
attr_accessor :stacks
|
133
|
-
attr_reader
|
133
|
+
attr_reader :thread_id, :events
|
134
134
|
|
135
135
|
# Records the events which happen in a program.
|
136
136
|
def initialize(thread_id: nil)
|
@@ -146,8 +146,10 @@ module AppMap
|
|
146
146
|
@enabled = true
|
147
147
|
end
|
148
148
|
|
149
|
-
def enabled?
|
150
|
-
@enabled
|
149
|
+
def enabled?(thread_id: nil)
|
150
|
+
return false unless @enabled
|
151
|
+
|
152
|
+
thread_id.nil? || @thread_id.nil? || @thread_id == thread_id
|
151
153
|
end
|
152
154
|
|
153
155
|
# Private function. Use AppMap.tracing#delete.
|
data/lib/appmap/util.rb
CHANGED
@@ -1,88 +1,92 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "bundler"
|
4
|
+
require "fileutils"
|
5
5
|
|
6
|
+
# rubocop:disable Metrics/MethodLength
|
7
|
+
# rubocop:disable Metrics/ModuleLength
|
8
|
+
# rubocop:disable Metrics/ClassLength
|
9
|
+
# rubocop:disable Metrics/AbcSize
|
6
10
|
module AppMap
|
7
11
|
module Util
|
8
12
|
# https://wynnnetherland.com/journal/a-stylesheet-author-s-guide-to-terminal-colors/
|
9
13
|
# Embed in a String to clear all previous ANSI sequences.
|
10
|
-
CLEAR
|
11
|
-
BOLD
|
14
|
+
CLEAR = "\e[0m"
|
15
|
+
BOLD = "\e[1m"
|
12
16
|
|
13
17
|
# Colors
|
14
|
-
BLACK
|
15
|
-
RED
|
16
|
-
GREEN
|
17
|
-
YELLOW
|
18
|
-
BLUE
|
18
|
+
BLACK = "\e[30m"
|
19
|
+
RED = "\e[31m"
|
20
|
+
GREEN = "\e[32m"
|
21
|
+
YELLOW = "\e[33m"
|
22
|
+
BLUE = "\e[34m"
|
19
23
|
MAGENTA = "\e[35m"
|
20
|
-
CYAN
|
21
|
-
WHITE
|
24
|
+
CYAN = "\e[36m"
|
25
|
+
WHITE = "\e[37m"
|
22
26
|
|
23
27
|
class << self
|
24
28
|
def parse_function_name(name)
|
25
|
-
package_tokens = name.split(
|
29
|
+
package_tokens = name.split("/")
|
26
30
|
|
27
31
|
class_and_name = package_tokens.pop
|
28
|
-
class_name, function_name, static = if class_and_name.include?(
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
class_name, function_name, static = if class_and_name.include?(".")
|
33
|
+
class_and_name.split(".",
|
34
|
+
2) + [true]
|
35
|
+
else
|
36
|
+
class_and_name.split(
|
37
|
+
"#", 2
|
38
|
+
) + [false]
|
39
|
+
end
|
36
40
|
|
37
41
|
raise "Malformed fully-qualified function name #{name}" unless function_name
|
38
42
|
|
39
|
-
[
|
43
|
+
[package_tokens.empty? ? "ruby" : package_tokens.join("/"), class_name, static, function_name]
|
40
44
|
end
|
41
45
|
|
42
46
|
# scenario_filename builds a suitable file name from a scenario name.
|
43
47
|
# Special characters are removed, and the file name is truncated to fit within
|
44
48
|
# shell limitations.
|
45
|
-
def scenario_filename(name, max_length: 255, separator:
|
49
|
+
def scenario_filename(name, max_length: 255, separator: "_", extension: ".appmap.json")
|
46
50
|
# Cribbed from v5 version of ActiveSupport:Inflector#parameterize:
|
47
51
|
# https://github.com/rails/rails/blob/v5.2.4/activesupport/lib/active_support/inflector/transliterate.rb#L92
|
48
52
|
# Replace accented chars with their ASCII equivalents.
|
49
53
|
|
50
|
-
fname = name.encode(
|
54
|
+
fname = name.encode("utf-8", invalid: :replace, undef: :replace, replace: "_")
|
51
55
|
|
52
56
|
# Turn unwanted chars into the separator.
|
53
57
|
fname.gsub!(/[^a-z0-9\-_]+/i, separator)
|
54
58
|
|
55
59
|
re_sep = Regexp.escape(separator)
|
56
|
-
re_duplicate_separator
|
60
|
+
re_duplicate_separator = /#{re_sep}{2,}/
|
57
61
|
re_leading_trailing_separator = /^#{re_sep}|#{re_sep}$/i
|
58
62
|
|
59
63
|
# No more than one of the separator in a row.
|
60
64
|
fname.gsub!(re_duplicate_separator, separator)
|
61
65
|
|
62
66
|
# Finally, Remove leading/trailing separator.
|
63
|
-
fname.gsub!(re_leading_trailing_separator,
|
67
|
+
fname.gsub!(re_leading_trailing_separator, "")
|
64
68
|
|
65
69
|
if (fname.length + extension.length) > max_length
|
66
|
-
require
|
67
|
-
require
|
70
|
+
require "base64"
|
71
|
+
require "digest"
|
68
72
|
fname_digest = Base64.urlsafe_encode64 Digest::MD5.digest(fname), padding: false
|
69
|
-
fname[max_length - fname_digest.length - extension.length - 1..-1] = [
|
73
|
+
fname[max_length - fname_digest.length - extension.length - 1..-1] = ["-", fname_digest].join
|
70
74
|
end
|
71
75
|
|
72
|
-
[
|
76
|
+
[fname, extension].join
|
73
77
|
end
|
74
78
|
|
75
79
|
# sanitize_paths removes ephemeral values from objects with
|
76
80
|
# embedded paths (e.g. an event or a classmap), making events
|
77
81
|
# easier to compare across runs.
|
78
82
|
def sanitize_paths(h)
|
79
|
-
require
|
83
|
+
require "hashie"
|
80
84
|
h.extend(Hashie::Extensions::DeepLocate)
|
81
85
|
keys = %i[path location]
|
82
86
|
h.deep_locate lambda { |k, _v, o|
|
83
87
|
next unless keys.include?(k)
|
84
88
|
|
85
|
-
fix = ->(v) { v.gsub(%r{#{Gem.dir}/gems/.*(?=lib)},
|
89
|
+
fix = ->(v) { v.gsub(%r{#{Gem.dir}/gems/.*(?=lib)}, "") }
|
86
90
|
keys.each { |k| o[k] = fix.call(o[k]) if o[k] }
|
87
91
|
}
|
88
92
|
|
@@ -105,8 +109,8 @@ module AppMap
|
|
105
109
|
headers = event.dig(field, :headers)
|
106
110
|
next unless headers
|
107
111
|
|
108
|
-
headers[
|
109
|
-
headers[
|
112
|
+
headers["Date"] = "<instanceof date>" if headers["Date"]
|
113
|
+
headers["Server"] = headers["Server"].match(/^(\w+)/)[0] if headers["Server"]
|
110
114
|
end
|
111
115
|
|
112
116
|
case event[:event]
|
@@ -122,8 +126,8 @@ module AppMap
|
|
122
126
|
blank?(headers) ? nil : headers
|
123
127
|
end
|
124
128
|
|
125
|
-
unless env[
|
126
|
-
warn
|
129
|
+
unless env["rack.version"]
|
130
|
+
warn "Request headers does not contain rack.version. HTTP_ prefix is not expected."
|
127
131
|
return finalize_headers.call(env.dup)
|
128
132
|
end
|
129
133
|
|
@@ -131,15 +135,15 @@ module AppMap
|
|
131
135
|
# Apparently, it's following the CGI spec in doing so.
|
132
136
|
# https://datatracker.ietf.org/doc/html/rfc3875#section-4.1.18
|
133
137
|
matching_headers = env
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
key = kv[0].sub(/^HTTP_/,
|
138
|
+
.select { |k, _v| k.to_s.start_with? "HTTP_" }
|
139
|
+
.merge(
|
140
|
+
"CONTENT_TYPE" => env["CONTENT_TYPE"],
|
141
|
+
"CONTENT_LENGTH" => env["CONTENT_LENGTH"],
|
142
|
+
"AUTHORIZATION" => env["AUTHORIZATION"]
|
143
|
+
)
|
144
|
+
.reject { |_k, v| blank?(v) }
|
145
|
+
.each_with_object({}) do |kv, memo|
|
146
|
+
key = kv[0].sub(/^HTTP_/, "").split("_").map(&:capitalize).join("-")
|
143
147
|
value = kv[1]
|
144
148
|
memo[key] = value
|
145
149
|
end
|
@@ -147,9 +151,9 @@ module AppMap
|
|
147
151
|
end
|
148
152
|
|
149
153
|
def normalize_path(path)
|
150
|
-
is_local_path
|
151
|
-
is_bundled_path
|
152
|
-
is_vendored_path = -> { path.index(File.join(Dir.pwd,
|
154
|
+
is_local_path = -> { path.index(Dir.pwd) == 0 }
|
155
|
+
is_bundled_path = -> { path.index(Bundler.bundle_path.to_s) == 0 }
|
156
|
+
is_vendored_path = -> { path.index(File.join(Dir.pwd, "vendor/bundle")) == 0 }
|
153
157
|
|
154
158
|
if is_local_path.call && !is_bundled_path.call && !is_vendored_path.call
|
155
159
|
path[Dir.pwd.length + 1..-1]
|
@@ -168,13 +172,13 @@ module AppMap
|
|
168
172
|
def extract_test_failure(exception)
|
169
173
|
return unless exception
|
170
174
|
|
171
|
-
{
|
175
|
+
{message: exception.message}.tap do |test_failure|
|
172
176
|
first_location = exception.backtrace_locations&.find do |location|
|
173
177
|
!Pathname.new(normalize_path(location.absolute_path || location.path)).absolute?
|
174
178
|
end
|
175
179
|
if first_location
|
176
180
|
test_failure[:location] =
|
177
|
-
[
|
181
|
+
[normalize_path(first_location.path), first_location.lineno].join(":")
|
178
182
|
end
|
179
183
|
end
|
180
184
|
end
|
@@ -182,21 +186,23 @@ module AppMap
|
|
182
186
|
# Convert a Rails-style path from /org/:org_id(.:format)
|
183
187
|
# to Swagger-style paths like /org/{org_id}
|
184
188
|
def swaggerize_path(path)
|
185
|
-
path = path.split(
|
186
|
-
tokens = path.split(
|
189
|
+
path = path.split("(.")[0]
|
190
|
+
tokens = path.split("/")
|
187
191
|
tokens.map do |token|
|
188
192
|
# stop matching if an ending ) is found
|
189
193
|
token.gsub(/^:(.*[^)])/, '{\1}')
|
190
|
-
end.join(
|
194
|
+
end.join("/")
|
191
195
|
end
|
192
196
|
|
193
197
|
# Atomically writes AppMap data to +filename+.
|
194
198
|
def write_appmap(filename, appmap)
|
195
|
-
require
|
199
|
+
require "tmpdir"
|
200
|
+
|
201
|
+
FileUtils.mkdir_p(File.dirname(filename))
|
196
202
|
|
197
203
|
# This is what Ruby Tempfile does; but we don't want the file to be unlinked.
|
198
204
|
mode = File::RDWR | File::CREAT | File::EXCL
|
199
|
-
::Dir::Tmpname.create([
|
205
|
+
::Dir::Tmpname.create(["appmap_", ".json"]) do |tmpname|
|
200
206
|
tempfile = File.open(tmpname, mode)
|
201
207
|
tempfile.write(JSON.generate(appmap))
|
202
208
|
tempfile.close
|
@@ -207,7 +213,7 @@ module AppMap
|
|
207
213
|
|
208
214
|
def color(text, color, bold: false)
|
209
215
|
color = Util.const_get(color.to_s.upcase) if color.is_a?(Symbol)
|
210
|
-
bold
|
216
|
+
bold = bold ? BOLD : ""
|
211
217
|
"#{bold}#{color}#{text}#{CLEAR}"
|
212
218
|
end
|
213
219
|
|
@@ -219,24 +225,24 @@ module AppMap
|
|
219
225
|
def underscore(camel_cased_word)
|
220
226
|
return camel_cased_word unless /[A-Z-]|::/.match?(camel_cased_word)
|
221
227
|
|
222
|
-
word = camel_cased_word.to_s.gsub(
|
228
|
+
word = camel_cased_word.to_s.gsub("::", "/")
|
223
229
|
# word.gsub!(inflections.acronyms_underscore_regex) { "#{$1 && '_' }#{$2.downcase}" }
|
224
230
|
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
|
225
231
|
word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
|
226
|
-
word.tr!(
|
232
|
+
word.tr!("-", "_")
|
227
233
|
word.downcase!
|
228
234
|
word
|
229
235
|
end
|
230
236
|
|
231
237
|
def deep_dup(hash)
|
232
|
-
require
|
238
|
+
require "active_support/core_ext"
|
233
239
|
hash.deep_dup
|
234
240
|
end
|
235
241
|
|
236
242
|
def blank?(obj)
|
237
243
|
return true if obj.nil?
|
238
244
|
|
239
|
-
return true if obj.is_a?(String) && obj ==
|
245
|
+
return true if obj.is_a?(String) && obj == ""
|
240
246
|
|
241
247
|
return true if obj.respond_to?(:length) && obj.length == 0
|
242
248
|
|
@@ -257,7 +263,7 @@ module AppMap
|
|
257
263
|
def startup_message(msg)
|
258
264
|
if defined?(::Rails) && defined?(::Rails.logger) && ::Rails.logger
|
259
265
|
::Rails.logger.info msg
|
260
|
-
elsif ENV[
|
266
|
+
elsif ENV["DEBUG"] == "true"
|
261
267
|
warn msg
|
262
268
|
end
|
263
269
|
|
@@ -265,7 +271,7 @@ module AppMap
|
|
265
271
|
end
|
266
272
|
|
267
273
|
def ruby_minor_version
|
268
|
-
@ruby_minor_version ||= RUBY_VERSION.split(
|
274
|
+
@ruby_minor_version ||= RUBY_VERSION.split(".")[0..1].join(".").to_f
|
269
275
|
end
|
270
276
|
|
271
277
|
def gettime
|
@@ -274,3 +280,7 @@ module AppMap
|
|
274
280
|
end
|
275
281
|
end
|
276
282
|
end
|
283
|
+
# rubocop:enable Metrics/MethodLength
|
284
|
+
# rubocop:enable Metrics/ModuleLength
|
285
|
+
# rubocop:enable Metrics/ClassLength
|
286
|
+
# rubocop:enable Metrics/AbcSize
|
data/lib/appmap/version.rb
CHANGED
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.
|
4
|
+
version: 0.103.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-
|
11
|
+
date: 2023-12-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: method_source
|
@@ -150,20 +150,6 @@ dependencies:
|
|
150
150
|
- - ">="
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '0'
|
153
|
-
- !ruby/object:Gem::Dependency
|
154
|
-
name: standardrb
|
155
|
-
requirement: !ruby/object:Gem::Requirement
|
156
|
-
requirements:
|
157
|
-
- - "~>"
|
158
|
-
- !ruby/object:Gem::Version
|
159
|
-
version: '1.0'
|
160
|
-
type: :development
|
161
|
-
prerelease: false
|
162
|
-
version_requirements: !ruby/object:Gem::Requirement
|
163
|
-
requirements:
|
164
|
-
- - "~>"
|
165
|
-
- !ruby/object:Gem::Version
|
166
|
-
version: '1.0'
|
167
153
|
- !ruby/object:Gem::Dependency
|
168
154
|
name: climate_control
|
169
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -324,8 +310,10 @@ files:
|
|
324
310
|
- ".nvmrc"
|
325
311
|
- ".rbenv-gemsets"
|
326
312
|
- ".releaserc.yml"
|
313
|
+
- ".rubocop.yml"
|
327
314
|
- ".ruby-version"
|
328
315
|
- ".rufo"
|
316
|
+
- ".standard.yml"
|
329
317
|
- ".travis.yml"
|
330
318
|
- ARCHITECTURE.md
|
331
319
|
- CHANGELOG.md
|
@@ -414,6 +402,7 @@ files:
|
|
414
402
|
- lib/appmap/hook/method.rb
|
415
403
|
- lib/appmap/hook/method/ruby2.rb
|
416
404
|
- lib/appmap/hook/method/ruby3.rb
|
405
|
+
- lib/appmap/hook/record_around.rb
|
417
406
|
- lib/appmap/hook_log.rb
|
418
407
|
- lib/appmap/metadata.rb
|
419
408
|
- lib/appmap/middleware/remote_recording.rb
|