appmap 0.102.2 → 0.103.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -1,4 +1,4 @@
|
|
1
|
-
require_relative
|
1
|
+
require_relative "recording_methods"
|
2
2
|
|
3
3
|
module AppMap
|
4
4
|
# Detects whether AppMap recording should be enabled. This test can be performed generally, or for
|
@@ -9,27 +9,29 @@ module AppMap
|
|
9
9
|
@@detected_for_method = {}
|
10
10
|
|
11
11
|
class << self
|
12
|
+
# rubocop:disable Metrics/MethodLength
|
12
13
|
def discourage_conflicting_recording_methods(recording_method)
|
13
|
-
return if ENV[
|
14
|
+
return if ENV["APPMAP_DISCOURAGE_CONFLICTING_RECORDING_METHODS"] == "false"
|
14
15
|
|
15
16
|
return unless enabled?(recording_method.to_sym) && enabled?(:requests)
|
16
17
|
|
17
18
|
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.
|
19
|
+
AppMap recording is enabled for both 'requests' and '#{recording_method}'. This is not recommended
|
20
|
+
because the recordings will contain duplicitive information, and in some case may conflict with each other.
|
20
21
|
MSG
|
21
22
|
|
22
|
-
return unless ENV[
|
23
|
+
return unless ENV["APPMAP"] == "true"
|
23
24
|
|
24
25
|
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.
|
26
|
+
The environment contains APPMAP=true, which is not recommended in this application environment because
|
27
|
+
it enables all recording methods. Consider letting AppMap detect the appropriate recording method,
|
28
|
+
or explicitly enabling only the recording methods you want to use using environment variables like
|
29
|
+
APPMAP_RECORD_REQUESTS, APPMAP_RECORD_RSPEC, etc.
|
30
|
+
|
31
|
+
See https://appmap.io/docs/reference/appmap-ruby.html#advanced-runtime-options for more information.
|
31
32
|
MSG
|
32
33
|
end
|
34
|
+
# rubocop:enable Metrics/MethodLength
|
33
35
|
|
34
36
|
def enabled?(recording_method)
|
35
37
|
new(recording_method).enabled?
|
@@ -57,7 +59,7 @@ See https://appmap.io/docs/reference/appmap-ruby.html#advanced-runtime-options f
|
|
57
59
|
|
58
60
|
if @recording_method && (enabled && enabled_by_app_env?)
|
59
61
|
warn AppMap::Util.color(
|
60
|
-
"AppMap #{@recording_method.nil? ?
|
62
|
+
"AppMap #{@recording_method.nil? ? "" : "#{@recording_method} "}recording is enabled because #{message}", :magenta
|
61
63
|
)
|
62
64
|
end
|
63
65
|
|
@@ -77,63 +79,63 @@ See https://appmap.io/docs/reference/appmap-ruby.html#advanced-runtime-options f
|
|
77
79
|
message, enabled = []
|
78
80
|
message, enabled = method(detection_functions.shift).call while enabled.nil? && !detection_functions.empty?
|
79
81
|
|
80
|
-
return [
|
82
|
+
return ["it is not enabled by any configuration or framework", false, false] if enabled.nil?
|
81
83
|
|
82
84
|
_, enabled_by_env = enabled_by_app_env?
|
83
|
-
[
|
85
|
+
[message, enabled, enabled_by_env]
|
84
86
|
end
|
85
87
|
|
86
88
|
def enabled_by_testing?
|
87
89
|
return unless %i[rspec minitest cucumber].member?(@recording_method)
|
88
90
|
|
89
|
-
[
|
91
|
+
["running tests with #{@recording_method}", true]
|
90
92
|
end
|
91
93
|
|
92
94
|
def enabled_by_app_env?
|
93
95
|
env_name, app_env = detect_app_env
|
94
|
-
return [
|
96
|
+
return ["#{env_name} is '#{app_env}'", true] if @recording_method.nil? && %w[test development].member?(app_env)
|
95
97
|
|
96
98
|
return unless %i[remote requests].member?(@recording_method)
|
97
|
-
|
99
|
+
["#{env_name} is '#{app_env}'", true] if app_env == "development"
|
98
100
|
end
|
99
101
|
|
100
102
|
def detect_app_env
|
101
103
|
if rails_env
|
102
|
-
[
|
103
|
-
elsif ENV[
|
104
|
-
[
|
104
|
+
["RAILS_ENV", rails_env]
|
105
|
+
elsif ENV["APP_ENV"]
|
106
|
+
["APP_ENV", ENV["APP_ENV"]]
|
105
107
|
end
|
106
108
|
end
|
107
109
|
|
108
110
|
def globally_enabled?
|
109
111
|
# Don't auto-enable request recording in the 'test' environment, because users probably don't want
|
110
112
|
# AppMaps of both test cases and requests. Requests recording can always be enabled by APPMAP_RECORD_REQUESTS=true.
|
111
|
-
requests_recording_in_test = -> { [
|
112
|
-
[
|
113
|
+
requests_recording_in_test = -> { [:requests].member?(@recording_method) && detect_app_env == "test" }
|
114
|
+
["APPMAP=true", true] if ENV["APPMAP"] == "true" && !requests_recording_in_test.call
|
113
115
|
end
|
114
116
|
|
115
117
|
def globally_disabled?
|
116
|
-
[
|
118
|
+
["APPMAP=false", false] if ENV["APPMAP"] == "false"
|
117
119
|
end
|
118
120
|
|
119
121
|
def recording_method_disabled?
|
120
122
|
return false unless @recording_method
|
121
123
|
|
122
|
-
env_var = [
|
123
|
-
[
|
124
|
+
env_var = ["APPMAP", "RECORD", @recording_method.upcase].join("_")
|
125
|
+
["#{["APPMAP", "RECORD", @recording_method.upcase].join("_")}=false", false] if ENV[env_var] == "false"
|
124
126
|
end
|
125
127
|
|
126
128
|
def recording_method_enabled?
|
127
129
|
return false unless @recording_method
|
128
130
|
|
129
|
-
env_var = [
|
130
|
-
[
|
131
|
+
env_var = ["APPMAP", "RECORD", @recording_method.upcase].join("_")
|
132
|
+
["#{["APPMAP", "RECORD", @recording_method.upcase].join("_")}=true", true] if ENV[env_var] == "true"
|
131
133
|
end
|
132
134
|
|
133
135
|
def rails_env
|
134
136
|
return Rails.env if defined?(::Rails::Railtie)
|
135
137
|
|
136
|
-
ENV.fetch(
|
138
|
+
ENV.fetch("RAILS_ENV", nil)
|
137
139
|
end
|
138
140
|
end
|
139
141
|
end
|
@@ -1,16 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "appmap/util"
|
4
|
+
require_relative "../record_around"
|
4
5
|
|
5
|
-
|
6
|
+
unless respond_to?(:ruby2_keywords, true)
|
7
|
+
def ruby2_keywords(*)
|
8
|
+
end
|
9
|
+
end
|
6
10
|
|
7
11
|
module AppMap
|
8
12
|
class Hook
|
9
13
|
# Delegation methods for Ruby 2.
|
10
14
|
# cf. https://eregon.me/blog/2019/11/10/the-delegation-challenge-of-ruby27.html
|
11
15
|
class Method
|
16
|
+
include RecordAround
|
17
|
+
|
12
18
|
ruby2_keywords def call(receiver, *args, &block)
|
13
19
|
call_event = false
|
20
|
+
record_around_before
|
14
21
|
if trace?
|
15
22
|
call_event, elapsed_before = with_disabled_hook { before_hook receiver, *args }
|
16
23
|
end
|
@@ -22,7 +29,7 @@ module AppMap
|
|
22
29
|
protected
|
23
30
|
|
24
31
|
def before_hook(receiver, *args)
|
25
|
-
before_hook_start_time = AppMap::Util.gettime
|
32
|
+
before_hook_start_time = AppMap::Util.gettime
|
26
33
|
call_event = handle_call(receiver, args)
|
27
34
|
if call_event
|
28
35
|
AppMap.tracing.record_event \
|
@@ -31,10 +38,11 @@ module AppMap
|
|
31
38
|
defined_class: defined_class,
|
32
39
|
method: hook_method
|
33
40
|
end
|
34
|
-
[call_event, AppMap::Util.gettime
|
41
|
+
[call_event, AppMap::Util.gettime - before_hook_start_time]
|
35
42
|
end
|
36
43
|
|
37
44
|
ruby2_keywords def do_call(receiver, *args, &block)
|
45
|
+
# Do not allow this to change to bind_call, it's not defined for Ruby 2.
|
38
46
|
hook_method.bind(receiver).call(*args, &block)
|
39
47
|
end
|
40
48
|
|
@@ -42,16 +50,19 @@ module AppMap
|
|
42
50
|
ruby2_keywords def trace_call(call_event, elapsed_before, receiver, *args, &block)
|
43
51
|
return do_call(receiver, *args, &block) unless call_event
|
44
52
|
|
45
|
-
start_time = AppMap::Util.gettime
|
53
|
+
start_time = AppMap::Util.gettime
|
46
54
|
begin
|
47
55
|
return_value = do_call(receiver, *args, &block)
|
48
56
|
rescue # rubocop:disable Style/RescueStandardError
|
49
57
|
exception = $ERROR_INFO
|
50
58
|
raise
|
51
59
|
ensure
|
52
|
-
after_start_time = AppMap::Util.gettime
|
53
|
-
|
54
|
-
|
60
|
+
after_start_time = AppMap::Util.gettime
|
61
|
+
begin
|
62
|
+
with_disabled_hook { after_hook receiver, call_event, elapsed_before, after_start_time - start_time, after_start_time, return_value, exception }
|
63
|
+
ensure
|
64
|
+
record_around_after
|
65
|
+
end
|
55
66
|
end
|
56
67
|
end
|
57
68
|
# rubocop:enable Metrics/MethodLength
|
@@ -1,17 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "appmap/util"
|
4
|
+
require_relative "../record_around"
|
4
5
|
|
5
6
|
module AppMap
|
6
7
|
class Hook
|
7
8
|
# Delegation methods for Ruby 3.
|
8
9
|
class Method
|
10
|
+
include RecordAround
|
11
|
+
|
9
12
|
def call(receiver, *args, **kwargs, &block)
|
10
13
|
call_event = false
|
14
|
+
record_around_before
|
11
15
|
if trace?
|
12
16
|
call_event, elapsed_before = with_disabled_hook { before_hook receiver, *args, **kwargs }
|
13
17
|
end
|
14
|
-
#
|
18
|
+
# NOTE: we can't short-circuit directly to do_call because then the call stack
|
15
19
|
# depth changes and eval handler doesn't work correctly
|
16
20
|
trace_call call_event, elapsed_before, receiver, *args, **kwargs, &block
|
17
21
|
end
|
@@ -19,7 +23,7 @@ module AppMap
|
|
19
23
|
protected
|
20
24
|
|
21
25
|
def before_hook(receiver, *args, **kwargs)
|
22
|
-
before_hook_start_time = AppMap::Util.gettime
|
26
|
+
before_hook_start_time = AppMap::Util.gettime
|
23
27
|
args = [*args, kwargs] if !kwargs.empty? || keyrest?
|
24
28
|
call_event = handle_call(receiver, args)
|
25
29
|
if call_event
|
@@ -29,31 +33,34 @@ module AppMap
|
|
29
33
|
defined_class: defined_class,
|
30
34
|
method: hook_method
|
31
35
|
end
|
32
|
-
[call_event, AppMap::Util.gettime
|
36
|
+
[call_event, AppMap::Util.gettime - before_hook_start_time]
|
33
37
|
end
|
34
38
|
|
35
39
|
def keyrest?
|
36
40
|
@keyrest ||= parameters.map(&:last).include? :keyrest
|
37
41
|
end
|
38
42
|
|
39
|
-
def do_call(receiver,
|
40
|
-
hook_method.bind_call(receiver,
|
43
|
+
def do_call(receiver, ...)
|
44
|
+
hook_method.bind_call(receiver, ...)
|
41
45
|
end
|
42
46
|
|
43
47
|
# rubocop:disable Metrics/MethodLength
|
44
|
-
def trace_call(call_event, elapsed_before, receiver,
|
45
|
-
return do_call(receiver,
|
48
|
+
def trace_call(call_event, elapsed_before, receiver, ...)
|
49
|
+
return do_call(receiver, ...) unless call_event
|
46
50
|
|
47
|
-
start_time = AppMap::Util.gettime
|
51
|
+
start_time = AppMap::Util.gettime
|
48
52
|
begin
|
49
|
-
return_value = do_call(receiver,
|
53
|
+
return_value = do_call(receiver, ...)
|
50
54
|
rescue # rubocop:disable Style/RescueStandardError
|
51
55
|
exception = $ERROR_INFO
|
52
56
|
raise
|
53
57
|
ensure
|
54
|
-
after_start_time = AppMap::Util.gettime
|
55
|
-
|
56
|
-
|
58
|
+
after_start_time = AppMap::Util.gettime
|
59
|
+
begin
|
60
|
+
with_disabled_hook { after_hook receiver, call_event, elapsed_before, after_start_time - start_time, after_start_time, return_value, exception }
|
61
|
+
ensure
|
62
|
+
record_around_after
|
63
|
+
end
|
57
64
|
end
|
58
65
|
end
|
59
66
|
# rubocop:enable Metrics/MethodLength
|
data/lib/appmap/hook/method.rb
CHANGED
@@ -1,17 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "appmap/util"
|
4
4
|
|
5
5
|
module AppMap
|
6
6
|
class Hook
|
7
7
|
class << self
|
8
8
|
def method_hash_key(cls, method)
|
9
|
-
[
|
9
|
+
[cls, method.name].hash
|
10
10
|
rescue TypeError => e
|
11
11
|
warn "Error building hash key for #{cls}, #{method}: #{e}"
|
12
12
|
end
|
13
13
|
end
|
14
|
-
|
15
14
|
|
16
15
|
SIGNATURES = {}
|
17
16
|
LOOKUP_SIGNATURE = lambda do |id|
|
@@ -32,19 +31,20 @@ module AppMap
|
|
32
31
|
method
|
33
32
|
end
|
34
33
|
|
35
|
-
RUBY_MAJOR_VERSION, RUBY_MINOR_VERSION, _ = RUBY_VERSION.split(
|
34
|
+
RUBY_MAJOR_VERSION, RUBY_MINOR_VERSION, _ = RUBY_VERSION.split(".").map(&:to_i)
|
36
35
|
|
37
36
|
# Single hooked method.
|
38
37
|
# Call #activate to override the original.
|
39
38
|
class Method
|
40
|
-
attr_reader :hook_package, :hook_class, :hook_method, :parameters, :arity
|
39
|
+
attr_reader :hook_package, :hook_class, :hook_method, :record_around, :parameters, :arity
|
41
40
|
|
42
|
-
HOOK_DISABLE_KEY =
|
41
|
+
HOOK_DISABLE_KEY = "AppMap::Hook.disable"
|
43
42
|
|
44
|
-
def initialize(hook_package, hook_class, hook_method)
|
43
|
+
def initialize(hook_package, hook_class, hook_method, record_around: false)
|
45
44
|
@hook_package = hook_package
|
46
45
|
@hook_class = hook_class
|
47
46
|
@hook_method = hook_method
|
47
|
+
@record_around = record_around
|
48
48
|
@parameters = hook_method.parameters
|
49
49
|
@arity = hook_method.arity
|
50
50
|
end
|
@@ -52,11 +52,11 @@ module AppMap
|
|
52
52
|
def activate
|
53
53
|
if HookLog.enabled?
|
54
54
|
msg = if method_display_name
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
HookLog.log "Hooking #{msg} at line #{(hook_method.source_location || []).join(
|
55
|
+
"#{method_display_name}"
|
56
|
+
else
|
57
|
+
"#{hook_method.name} (class resolution deferred)"
|
58
|
+
end
|
59
|
+
HookLog.log "Hooking #{msg} at line #{(hook_method.source_location || []).join(":")}"
|
60
60
|
end
|
61
61
|
|
62
62
|
hook_method_parameters = hook_method.parameters.dup.freeze
|
@@ -79,13 +79,13 @@ module AppMap
|
|
79
79
|
|
80
80
|
def defining_class(hook_class)
|
81
81
|
cls = if RUBY_MAJOR_VERSION == 2 && RUBY_MINOR_VERSION <= 5
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
82
|
+
hook_class
|
83
|
+
.ancestors
|
84
|
+
.select { |cls| cls.method_defined?(hook_method.name) }
|
85
|
+
.find { |cls| cls.instance_method(hook_method.name).owner == cls }
|
86
|
+
else
|
87
|
+
hook_class.ancestors.find { |cls| cls.method_defined?(hook_method.name, false) }
|
88
|
+
end
|
89
89
|
|
90
90
|
return cls if cls
|
91
91
|
|
@@ -93,7 +93,7 @@ module AppMap
|
|
93
93
|
end
|
94
94
|
|
95
95
|
def trace?
|
96
|
-
return false unless AppMap.tracing_enabled?
|
96
|
+
return false unless AppMap.tracing_enabled?(thread: Thread.current)
|
97
97
|
return false if Thread.current[HOOK_DISABLE_KEY]
|
98
98
|
return false if hook_package&.shallow? && AppMap.tracing.last_package_for_current_thread == hook_package
|
99
99
|
|
@@ -103,7 +103,7 @@ module AppMap
|
|
103
103
|
def method_display_name
|
104
104
|
return @method_display_name if @method_display_name
|
105
105
|
|
106
|
-
return @method_display_name = [defined_class,
|
106
|
+
return @method_display_name = [defined_class, "#", hook_method.name].join if defined_class
|
107
107
|
|
108
108
|
"#{hook_method.name} (class resolution deferred)"
|
109
109
|
end
|
@@ -114,7 +114,7 @@ module AppMap
|
|
114
114
|
|
115
115
|
def after_hook(_receiver, call_event, elapsed_before, elapsed, after_start_time, return_value, exception)
|
116
116
|
return_event = handle_return(call_event.id, elapsed, return_value, exception)
|
117
|
-
return_event.elapsed_instrumentation = elapsed_before + (AppMap::Util.gettime
|
117
|
+
return_event.elapsed_instrumentation = elapsed_before + (AppMap::Util.gettime - after_start_time)
|
118
118
|
AppMap.tracing.record_event(return_event) if return_event
|
119
119
|
end
|
120
120
|
|
@@ -141,20 +141,20 @@ module AppMap
|
|
141
141
|
end
|
142
142
|
end
|
143
143
|
|
144
|
-
unless ENV[
|
144
|
+
unless ENV["APPMAP_NO_PATCH_OBJECT"] == "true"
|
145
145
|
class Object
|
146
146
|
prepend AppMap::ObjectMethods
|
147
147
|
end
|
148
148
|
end
|
149
149
|
|
150
|
-
unless ENV[
|
150
|
+
unless ENV["APPMAP_NO_PATCH_MODULE"] == "true"
|
151
151
|
class Module
|
152
152
|
prepend AppMap::ModuleMethods
|
153
153
|
end
|
154
154
|
end
|
155
155
|
|
156
|
-
if RUBY_VERSION <
|
157
|
-
require
|
156
|
+
if RUBY_VERSION < "3"
|
157
|
+
require "appmap/hook/method/ruby2"
|
158
158
|
else
|
159
|
-
require
|
159
|
+
require "appmap/hook/method/ruby3"
|
160
160
|
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module AppMap
|
2
|
+
class Hook
|
3
|
+
# Start and stop a recording around a Hook::Method.
|
4
|
+
module RecordAround
|
5
|
+
APPMAP_OUTPUT_DIR = File.join(AppMap.output_dir, "requests")
|
6
|
+
|
7
|
+
# Context for a recording.
|
8
|
+
class Context
|
9
|
+
attr_reader :hook_method
|
10
|
+
|
11
|
+
def initialize(hook_method)
|
12
|
+
@hook_method = hook_method
|
13
|
+
@start_time = DateTime.now
|
14
|
+
@tracer = AppMap.tracing.trace(thread: Thread.current)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Finish recording the AppMap by collecting the events and classMap and writing the output file.
|
18
|
+
# rubocop:disable Metrics/MethodLength
|
19
|
+
# rubocop:disable Metrics/AbcSize
|
20
|
+
def finish
|
21
|
+
return unless @tracer
|
22
|
+
|
23
|
+
tracer = @tracer
|
24
|
+
@tracer = nil
|
25
|
+
AppMap.tracing.delete(tracer)
|
26
|
+
|
27
|
+
events = tracer.events.map(&:to_h)
|
28
|
+
|
29
|
+
timestamp = DateTime.now
|
30
|
+
appmap_name = "#{hook_method.name} (#{Thread.current.object_id}) - #{timestamp.strftime("%T.%L")}"
|
31
|
+
appmap_file_name = AppMap::Util.scenario_filename([timestamp.to_f, hook_method.name, Thread.current.object_id].join("_"))
|
32
|
+
|
33
|
+
metadata = AppMap.detect_metadata.tap do |metadata|
|
34
|
+
metadata[:name] = appmap_name
|
35
|
+
metadata[:source_location] = hook_method.source_location
|
36
|
+
metadata[:recorder] = {
|
37
|
+
name: "command",
|
38
|
+
type: "requests"
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
appmap = {
|
43
|
+
version: AppMap::APPMAP_FORMAT_VERSION,
|
44
|
+
classMap: AppMap.class_map(tracer.event_methods),
|
45
|
+
metadata: metadata,
|
46
|
+
events: events
|
47
|
+
}
|
48
|
+
|
49
|
+
AppMap::Util.write_appmap(File.join(APPMAP_OUTPUT_DIR, appmap_file_name), appmap)
|
50
|
+
end
|
51
|
+
# rubocop:enable Metrics/MethodLength
|
52
|
+
# rubocop:enable Metrics/AbcSize
|
53
|
+
end
|
54
|
+
|
55
|
+
# If requests recording is enabled, and we encounter a method which should always be recorded
|
56
|
+
# when requests recording is on, and there is no other recording in progress, then start a
|
57
|
+
# new recording and end it when the method returns.
|
58
|
+
def record_around?
|
59
|
+
(record_around && AppMap.recording_enabled?(:requests) && !AppMap.tracing_enabled?(thread: Thread.current))
|
60
|
+
end
|
61
|
+
|
62
|
+
def record_around_before
|
63
|
+
return unless record_around?
|
64
|
+
|
65
|
+
@record_around_context = Context.new(hook_method)
|
66
|
+
end
|
67
|
+
|
68
|
+
def record_around_after
|
69
|
+
return unless @record_around_context
|
70
|
+
|
71
|
+
context = @record_around_context
|
72
|
+
@record_around_context = nil
|
73
|
+
context.finish
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|