appmap 0.23.0 → 0.27.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +17 -8
- data/.travis.yml +6 -0
- data/CHANGELOG.md +43 -0
- data/README.md +33 -21
- data/Rakefile +3 -3
- data/appmap.gemspec +3 -1
- data/exe/appmap +5 -73
- data/lib/appmap.rb +61 -6
- data/lib/appmap/algorithm/prune_class_map.rb +2 -0
- data/lib/appmap/algorithm/stats.rb +4 -2
- data/lib/appmap/class_map.rb +143 -0
- data/lib/appmap/command/record.rb +8 -6
- data/lib/appmap/command/stats.rb +2 -0
- data/lib/appmap/event.rb +168 -0
- data/lib/appmap/hook.rb +152 -0
- data/lib/appmap/middleware/remote_recording.rb +14 -21
- data/lib/appmap/rails/action_handler.rb +10 -6
- data/lib/appmap/rails/sql_handler.rb +10 -13
- data/lib/appmap/railtie.rb +31 -18
- data/lib/appmap/rspec.rb +247 -260
- data/lib/appmap/trace.rb +88 -0
- data/lib/appmap/version.rb +1 -1
- data/package-lock.json +90 -92
- data/spec/abstract_controller4_base_spec.rb +1 -1
- data/spec/abstract_controller_base_spec.rb +7 -3
- data/spec/config_spec.rb +25 -0
- data/spec/fixtures/hook/attr_accessor.rb +5 -0
- data/spec/fixtures/hook/class_method.rb +17 -0
- data/spec/fixtures/hook/constructor.rb +7 -0
- data/spec/fixtures/hook/exception_method.rb +11 -0
- data/spec/fixtures/hook/instance_method.rb +23 -0
- data/spec/fixtures/rails4_users_app/app/controllers/api/users_controller.rb +3 -3
- data/spec/fixtures/rails4_users_app/config/database.yml +2 -1
- data/spec/fixtures/rails4_users_app/docker-compose.yml +2 -0
- data/spec/fixtures/rails_users_app/.ruby-version +1 -1
- data/spec/fixtures/rails_users_app/app/controllers/api/users_controller.rb +2 -2
- data/spec/fixtures/rails_users_app/config/database.yml +2 -1
- data/spec/fixtures/rails_users_app/create_app +1 -0
- data/spec/fixtures/rails_users_app/docker-compose.yml +4 -0
- data/spec/fixtures/rails_users_app/spec/models/user_spec.rb +1 -1
- data/spec/hook_spec.rb +369 -0
- data/spec/rails_spec_helper.rb +25 -16
- data/spec/railtie_spec.rb +1 -1
- data/spec/record_sql_rails_pg_spec.rb +1 -2
- data/spec/remote_recording_spec.rb +117 -0
- data/spec/spec_helper.rb +5 -0
- data/test/cli_test.rb +4 -46
- data/test/fixtures/cli_record_test/appmap.yml +2 -1
- data/test/fixtures/cli_record_test/lib/cli_record_test/main.rb +4 -2
- data/test/fixtures/rspec_recorder/Gemfile +1 -1
- data/test/fixtures/rspec_recorder/spec/decorated_hello_spec.rb +12 -0
- data/test/rspec_test.rb +5 -0
- data/test/test_helper.rb +0 -42
- metadata +46 -63
- data/exe/_appmap-record-self +0 -49
- data/lib/appmap/command/inspect.rb +0 -14
- data/lib/appmap/command/upload.rb +0 -99
- data/lib/appmap/config.rb +0 -65
- data/lib/appmap/config/directory.rb +0 -65
- data/lib/appmap/config/file.rb +0 -13
- data/lib/appmap/config/named_function.rb +0 -21
- data/lib/appmap/config/package_dir.rb +0 -52
- data/lib/appmap/config/path.rb +0 -25
- data/lib/appmap/feature.rb +0 -262
- data/lib/appmap/inspect.rb +0 -91
- data/lib/appmap/inspect/inspector.rb +0 -99
- data/lib/appmap/inspect/parse_node.rb +0 -170
- data/lib/appmap/inspect/parser.rb +0 -15
- data/lib/appmap/parser.rb +0 -60
- data/lib/appmap/rspec/parse_node.rb +0 -41
- data/lib/appmap/rspec/parser.rb +0 -15
- data/lib/appmap/trace/event_handler/rack_handler_webrick.rb +0 -65
- data/lib/appmap/trace/tracer.rb +0 -356
- data/spec/fixtures/rails_users_app/bin/_appmap-record-self +0 -29
- data/spec/rack_handler_webrick_spec.rb +0 -59
- data/test/config_test.rb +0 -149
- data/test/explict_inspect_test.rb +0 -29
- data/test/fixtures/active_record_like/active_record.rb +0 -2
- data/test/fixtures/active_record_like/active_record/aggregations.rb +0 -4
- data/test/fixtures/active_record_like/active_record/association.rb +0 -4
- data/test/fixtures/active_record_like/active_record/associations/join_dependency.rb +0 -6
- data/test/fixtures/active_record_like/active_record/associations/join_dependency/join_base.rb +0 -8
- data/test/fixtures/active_record_like/active_record/associations/join_dependency/join_part.rb +0 -8
- data/test/fixtures/active_record_like/active_record/caps/caps.rb +0 -4
- data/test/fixtures/ignore_non_ruby_file/class.rb +0 -3
- data/test/fixtures/ignore_non_ruby_file/non-ruby.txt +0 -1
- data/test/fixtures/includes_excludes/lib/a/a_1.rb +0 -6
- data/test/fixtures/includes_excludes/lib/a/a_2.rb +0 -6
- data/test/fixtures/includes_excludes/lib/a/x/x_1.rb +0 -8
- data/test/fixtures/includes_excludes/lib/b/b_1.rb +0 -6
- data/test/fixtures/includes_excludes/lib/root_1.rb +0 -4
- data/test/fixtures/inspect_multiple_subdirs/module_a.rb +0 -2
- data/test/fixtures/inspect_multiple_subdirs/module_a/class_a.rb +0 -5
- data/test/fixtures/inspect_multiple_subdirs/module_b.rb +0 -2
- data/test/fixtures/inspect_multiple_subdirs/module_b/class_b.rb +0 -5
- data/test/fixtures/inspect_multiple_subdirs/module_b/class_c.rb +0 -5
- data/test/fixtures/inspect_package/module_a/module_b/class_in_module.rb +0 -6
- data/test/fixtures/parse_file/defs_static_function.rb +0 -96
- data/test/fixtures/parse_file/function_within_class.rb +0 -36
- data/test/fixtures/parse_file/include_public_methods.rb +0 -127
- data/test/fixtures/parse_file/instance_function.rb +0 -17
- data/test/fixtures/parse_file/modules.rb +0 -71
- data/test/fixtures/parse_file/sclass_static_function.rb +0 -88
- data/test/fixtures/parse_file/toplevel_class.rb +0 -13
- data/test/fixtures/parse_file/toplevel_function.rb +0 -14
- data/test/fixtures/trace_test/trace_program_1.rb +0 -44
- data/test/implicit_inspect_test.rb +0 -33
- data/test/include_exclude_test.rb +0 -48
- data/test/prerecorded_trace_test.rb +0 -76
- data/test/trace_test.rb +0 -92
data/lib/appmap/rspec/parser.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'appmap/parser'
|
2
|
-
require 'appmap/rspec/parse_node'
|
3
|
-
|
4
|
-
module AppMap
|
5
|
-
module RSpec
|
6
|
-
# Parser processes a Ruby into a list of parse nodes and a list of comments.
|
7
|
-
class Parser < ::AppMap::Parser
|
8
|
-
protected
|
9
|
-
|
10
|
-
def build_parse_node(node, file_path, ancestors)
|
11
|
-
ParseNode.from_node(node, file_path, ancestors)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
@@ -1,65 +0,0 @@
|
|
1
|
-
module AppMap
|
2
|
-
module Trace
|
3
|
-
module EventHandler
|
4
|
-
# Use the `req` and `res` parameters on Rack::Handler::WEBrick to populate the
|
5
|
-
# `http_server_request` and `http_server_response` info on the trace event.
|
6
|
-
#
|
7
|
-
# See https://github.com/rack/rack/blob/b72bfc9435c118c54019efae1fedd119521b76df/lib/rack/handler/webrick.rb#L26
|
8
|
-
module RackHandlerWebrick
|
9
|
-
class Call < MethodEvent
|
10
|
-
attr_accessor :http_server_request
|
11
|
-
|
12
|
-
class << self
|
13
|
-
def build_from_tracepoint(mc = Call.new, tp, path)
|
14
|
-
mc.tap do |_|
|
15
|
-
req = value_in_binding(tp, :req)
|
16
|
-
|
17
|
-
# Don't try and grab 'parameters', because:
|
18
|
-
# a) They aren't needed.
|
19
|
-
# b) We want to avoid triggering side effects like reading the request body.
|
20
|
-
|
21
|
-
mc.http_server_request = {
|
22
|
-
request_method: req.request_method,
|
23
|
-
path_info: req.path_info,
|
24
|
-
protocol: "HTTP/#{req.http_version}"
|
25
|
-
}
|
26
|
-
|
27
|
-
MethodEvent.build_from_tracepoint(mc, tp, path)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def to_h
|
33
|
-
super.tap do |h|
|
34
|
-
h[:http_server_request] = http_server_request
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
class Return < MethodReturnIgnoreValue
|
40
|
-
attr_accessor :http_server_response
|
41
|
-
|
42
|
-
class << self
|
43
|
-
def build_from_tracepoint(mr = Return.new, tp, path, parent_id, elapsed)
|
44
|
-
mr.tap do |_|
|
45
|
-
res = value_in_binding(tp, :res)
|
46
|
-
|
47
|
-
mr.http_server_response = {
|
48
|
-
status: res.status
|
49
|
-
}
|
50
|
-
|
51
|
-
MethodReturnIgnoreValue.build_from_tracepoint(mr, tp, path, parent_id, elapsed)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def to_h
|
57
|
-
super.tap do |h|
|
58
|
-
h[:http_server_response] = http_server_response
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
data/lib/appmap/trace/tracer.rb
DELETED
@@ -1,356 +0,0 @@
|
|
1
|
-
module AppMap
|
2
|
-
module Trace
|
3
|
-
MethodEventStruct =
|
4
|
-
Struct.new(:id, :event, :defined_class, :method_id, :path, :lineno, :static, :thread_id)
|
5
|
-
|
6
|
-
class Tracers
|
7
|
-
def initialize
|
8
|
-
@tracers = []
|
9
|
-
end
|
10
|
-
|
11
|
-
def empty?
|
12
|
-
@tracers.empty?
|
13
|
-
end
|
14
|
-
|
15
|
-
def trace(functions, enable: true)
|
16
|
-
AppMap::Trace::Tracer.new(functions).tap do |tracer|
|
17
|
-
@tracers << tracer
|
18
|
-
tracer.enable if enable
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def record_event(event)
|
23
|
-
@tracers.each do |tracer|
|
24
|
-
tracer.record_event(event)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def delete(tracer)
|
29
|
-
return unless @tracers.member?(tracer)
|
30
|
-
|
31
|
-
@tracers.delete(tracer)
|
32
|
-
tracer.disable
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
class << self
|
37
|
-
def tracers
|
38
|
-
@tracers ||= Tracers.new
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
# @appmap
|
43
|
-
class MethodEvent < MethodEventStruct
|
44
|
-
LIMIT = 100
|
45
|
-
|
46
|
-
COUNTER_LOCK = Mutex.new # :nodoc:
|
47
|
-
@@id_counter = 0
|
48
|
-
|
49
|
-
class << self
|
50
|
-
# Build a new instance from a TracePoint.
|
51
|
-
def build_from_tracepoint(me, tp, path)
|
52
|
-
me.id = next_id
|
53
|
-
me.event = tp.event
|
54
|
-
|
55
|
-
if tp.defined_class.singleton_class?
|
56
|
-
me.defined_class = (tp.self.is_a?(Class) || tp.self.is_a?(Module)) ? tp.self.name : tp.self.class.name
|
57
|
-
else
|
58
|
-
me.defined_class = tp.defined_class.name
|
59
|
-
end
|
60
|
-
|
61
|
-
me.method_id = tp.method_id
|
62
|
-
me.path = path
|
63
|
-
me.lineno = tp.lineno
|
64
|
-
me.static = tp.defined_class.name.nil?
|
65
|
-
me.thread_id = Thread.current.object_id
|
66
|
-
end
|
67
|
-
|
68
|
-
# Gets the next serial id.
|
69
|
-
#
|
70
|
-
# This method is thread-safe.
|
71
|
-
# @appmap
|
72
|
-
def next_id
|
73
|
-
COUNTER_LOCK.synchronize do
|
74
|
-
@@id_counter += 1
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
# Gets a value, by key, from the trace point binding.
|
79
|
-
# If the method raises an error, it can be handled by the optional block.
|
80
|
-
def value_in_binding(tp, key, &block)
|
81
|
-
tp.binding.eval(key.to_s)
|
82
|
-
rescue NameError, ArgumentError
|
83
|
-
yield if block_given?
|
84
|
-
end
|
85
|
-
|
86
|
-
# Gets a display string for a value. This is not meant to be a machine deserializable value.
|
87
|
-
def display_string(value)
|
88
|
-
return nil unless value
|
89
|
-
|
90
|
-
last_resort_string = lambda do
|
91
|
-
warn "AppMap encountered an error inspecting a #{value.class.name}: #{$!.message}"
|
92
|
-
'*Error inspecting variable*'
|
93
|
-
end
|
94
|
-
|
95
|
-
value_string = \
|
96
|
-
begin
|
97
|
-
value.to_s
|
98
|
-
rescue NoMethodError
|
99
|
-
begin
|
100
|
-
value.inspect
|
101
|
-
rescue StandardError
|
102
|
-
last_resort_string.call
|
103
|
-
end
|
104
|
-
rescue StandardError
|
105
|
-
last_resort_string.call
|
106
|
-
end
|
107
|
-
|
108
|
-
value_string[0...LIMIT].encode('utf-8', invalid: :replace, undef: :replace, replace: '_')
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
alias static? static
|
113
|
-
end
|
114
|
-
|
115
|
-
# @appmap
|
116
|
-
class MethodCall < MethodEvent
|
117
|
-
attr_accessor :parameters, :receiver
|
118
|
-
|
119
|
-
class << self
|
120
|
-
# @appmap
|
121
|
-
def build_from_tracepoint(mc = MethodCall.new, tp, path)
|
122
|
-
mc.tap do |_|
|
123
|
-
mc.parameters = collect_parameters(tp)
|
124
|
-
mc.receiver = collect_self(tp)
|
125
|
-
MethodEvent.build_from_tracepoint(mc, tp, path)
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
def collect_self(tp)
|
130
|
-
{
|
131
|
-
class: tp.self.class.name,
|
132
|
-
object_id: tp.self.__id__,
|
133
|
-
value: display_string(tp.self)
|
134
|
-
}
|
135
|
-
end
|
136
|
-
|
137
|
-
def collect_parameters(tp)
|
138
|
-
-> { tp.self.method(tp.method_id).parameters rescue [] }.call.collect do |pinfo|
|
139
|
-
kind, key = pinfo
|
140
|
-
value = value_in_binding(tp, key)
|
141
|
-
{
|
142
|
-
name: key,
|
143
|
-
class: value.class.name,
|
144
|
-
object_id: value.__id__,
|
145
|
-
value: display_string(value),
|
146
|
-
kind: kind # :req, :rest, :key, :keyrest, :block
|
147
|
-
}
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
def to_h
|
153
|
-
super.tap do |h|
|
154
|
-
h[:parameters] = parameters
|
155
|
-
h[:receiver] = receiver
|
156
|
-
end
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
class MethodReturnIgnoreValue < MethodEvent
|
161
|
-
attr_accessor :parent_id, :elapsed
|
162
|
-
|
163
|
-
class << self
|
164
|
-
def build_from_tracepoint(mr = MethodReturnIgnoreValue.new, tp, path, parent_id, elapsed)
|
165
|
-
mr.tap do |_|
|
166
|
-
mr.parent_id = parent_id
|
167
|
-
mr.elapsed = elapsed
|
168
|
-
MethodEvent.build_from_tracepoint(mr, tp, path)
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
def to_h
|
174
|
-
super.tap do |h|
|
175
|
-
h[:parent_id] = parent_id
|
176
|
-
h[:elapsed] = elapsed
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
class MethodReturn < MethodReturnIgnoreValue
|
182
|
-
attr_accessor :return_value
|
183
|
-
|
184
|
-
class << self
|
185
|
-
def build_from_tracepoint(mr = MethodReturn.new, tp, path, parent_id, elapsed)
|
186
|
-
mr.tap do |_|
|
187
|
-
mr.return_value = {
|
188
|
-
class: tp.return_value.class.name,
|
189
|
-
value: display_string(tp.return_value),
|
190
|
-
object_id: tp.return_value.__id__
|
191
|
-
}
|
192
|
-
MethodReturnIgnoreValue.build_from_tracepoint(mr, tp, path, parent_id, elapsed)
|
193
|
-
end
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
def to_h
|
198
|
-
super.tap do |h|
|
199
|
-
h[:return_value] = return_value
|
200
|
-
end
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
# Processes a series of calls into recorded events.
|
205
|
-
# Each call to the handle should provide a TracePoint (or duck-typed object) as the argument.
|
206
|
-
# On each call, a MethodEvent is constructed according to the nature of the TracePoint, and then
|
207
|
-
# stored using the record_event method.
|
208
|
-
# @appmap
|
209
|
-
class TracePointHandler
|
210
|
-
attr_accessor :call_constructor, :return_constructor
|
211
|
-
|
212
|
-
DEFAULT_HANDLER_CLASSES = {
|
213
|
-
call: MethodCall,
|
214
|
-
return: MethodReturn
|
215
|
-
}.freeze
|
216
|
-
|
217
|
-
# @appmap
|
218
|
-
def initialize(tracer)
|
219
|
-
@pwd = Dir.pwd
|
220
|
-
@tracer = tracer
|
221
|
-
@call_stack = Hash.new { |h, k| h[k] = [] }
|
222
|
-
@handler_classes = {}
|
223
|
-
end
|
224
|
-
|
225
|
-
# @appmap
|
226
|
-
def handle(tp)
|
227
|
-
# Absoute paths which are within the current working directory are normalized
|
228
|
-
# to be relative paths.
|
229
|
-
path = tp.path
|
230
|
-
if path.index(@pwd) == 0
|
231
|
-
path = path[@pwd.length+1..-1]
|
232
|
-
end
|
233
|
-
|
234
|
-
method_event = \
|
235
|
-
if tp.event == :call && (function = @tracer.lookup_function(path, tp.lineno))
|
236
|
-
call_constructor = handler_class(function, tp.event)
|
237
|
-
call_constructor.build_from_tracepoint(tp, path).tap do |c|
|
238
|
-
@call_stack[Thread.current.object_id] << [ tp.defined_class, tp.method_id, c.id, Time.now, function ]
|
239
|
-
end
|
240
|
-
elsif (c = @call_stack[Thread.current.object_id].last) &&
|
241
|
-
c[0] == tp.defined_class &&
|
242
|
-
c[1] == tp.method_id
|
243
|
-
function = c[4]
|
244
|
-
@call_stack[Thread.current.object_id].pop
|
245
|
-
return_constructor = handler_class(function, tp.event)
|
246
|
-
return_constructor.build_from_tracepoint(tp, path, c[2], Time.now - c[3])
|
247
|
-
end
|
248
|
-
|
249
|
-
@tracer.record_event method_event if method_event
|
250
|
-
|
251
|
-
method_event
|
252
|
-
rescue
|
253
|
-
puts $!.message
|
254
|
-
puts $!.backtrace.join("\n")
|
255
|
-
# XXX If this exception doesn't get reraised, internal errors
|
256
|
-
# (e.g. a missing method on TracePoint) get silently
|
257
|
-
# ignored. This allows tests to pass that should fail, which
|
258
|
-
# is bad, but is it desirable otherwise?
|
259
|
-
raise
|
260
|
-
end
|
261
|
-
|
262
|
-
protected
|
263
|
-
|
264
|
-
# Figure out which handler class should be used for a trace event. It may be
|
265
|
-
# a custom handler, e.g. in case we are processing a special named function such as a
|
266
|
-
# web server entry point, or it may be the standard :call or :return handler.
|
267
|
-
def handler_class(function, event)
|
268
|
-
cache_key = [function.location, event]
|
269
|
-
cached_handler = @handler_classes[cache_key]
|
270
|
-
return cached_handler if cached_handler
|
271
|
-
|
272
|
-
return default_handler_class(event) unless function.handler_id
|
273
|
-
|
274
|
-
require "appmap/trace/event_handler/#{function.handler_id}"
|
275
|
-
|
276
|
-
AppMap::Trace::EventHandler
|
277
|
-
.const_get(function.handler_id.to_s.camelize)
|
278
|
-
.const_get(event.to_s.capitalize).tap do |handler|
|
279
|
-
@handler_classes[cache_key] = handler
|
280
|
-
end
|
281
|
-
end
|
282
|
-
|
283
|
-
def default_handler_class(event)
|
284
|
-
DEFAULT_HANDLER_CLASSES[event] or raise "No handler class for #{event.inspect}"
|
285
|
-
end
|
286
|
-
end
|
287
|
-
|
288
|
-
# @appmap
|
289
|
-
class Tracer
|
290
|
-
# Trace a specified set of functions.
|
291
|
-
#
|
292
|
-
# functions Array of AppMap::Feature::Function.
|
293
|
-
# @appmap
|
294
|
-
def initialize(functions)
|
295
|
-
@functions = functions
|
296
|
-
|
297
|
-
@functions_by_location = functions.each_with_object({}) do |m, memo|
|
298
|
-
path, lineno = m.location.split(':', 2)
|
299
|
-
memo[path] ||= {}
|
300
|
-
memo[path][lineno.to_i] = m
|
301
|
-
memo
|
302
|
-
end
|
303
|
-
|
304
|
-
@events_mutex = Mutex.new
|
305
|
-
@events = []
|
306
|
-
end
|
307
|
-
|
308
|
-
def enable
|
309
|
-
handler = TracePointHandler.new(self)
|
310
|
-
@trace_point = TracePoint.trace(:call, :return, &handler.method(:handle))
|
311
|
-
end
|
312
|
-
|
313
|
-
# Private function. Use AppMap.tracers#delete.
|
314
|
-
def disable # :nodoc:
|
315
|
-
@trace_point.disable
|
316
|
-
end
|
317
|
-
|
318
|
-
# Whether the indicated file path and lineno is a breakpoint on which
|
319
|
-
# execution should interrupted.
|
320
|
-
# @appmap
|
321
|
-
def lookup_function(path, lineno)
|
322
|
-
(methods_by_path = @functions_by_location[path]) && methods_by_path[lineno]
|
323
|
-
end
|
324
|
-
|
325
|
-
# Record a program execution event.
|
326
|
-
#
|
327
|
-
# The event should be one of the MethodEvent subclasses.
|
328
|
-
#
|
329
|
-
# This method is thread-safe.
|
330
|
-
# @appmap
|
331
|
-
def record_event(event)
|
332
|
-
@events_mutex.synchronize do
|
333
|
-
@events << event
|
334
|
-
end
|
335
|
-
end
|
336
|
-
|
337
|
-
# Whether there is an event available for processing.
|
338
|
-
#
|
339
|
-
# This method is thread-safe.
|
340
|
-
def event?
|
341
|
-
@events_mutex.synchronize do
|
342
|
-
!@events.empty?
|
343
|
-
end
|
344
|
-
end
|
345
|
-
|
346
|
-
# Gets the next available event, if any.
|
347
|
-
#
|
348
|
-
# This method is thread-safe.
|
349
|
-
def next_event
|
350
|
-
@events_mutex.synchronize do
|
351
|
-
@events.shift
|
352
|
-
end
|
353
|
-
end
|
354
|
-
end
|
355
|
-
end
|
356
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
#
|
5
|
-
# This file was generated by Bundler.
|
6
|
-
#
|
7
|
-
# The application '_appmap-record-self' is installed as part of a gem, and
|
8
|
-
# this file is here to facilitate running it.
|
9
|
-
#
|
10
|
-
|
11
|
-
require "pathname"
|
12
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
-
Pathname.new(__FILE__).realpath)
|
14
|
-
|
15
|
-
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
-
|
17
|
-
if File.file?(bundle_binstub)
|
18
|
-
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
-
load(bundle_binstub)
|
20
|
-
else
|
21
|
-
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
-
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
require "rubygems"
|
27
|
-
require "bundler/setup"
|
28
|
-
|
29
|
-
load Gem.bin_path("appmap", "_appmap-record-self")
|