google-cloud-debugger 0.26.1 → 0.27.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/ext/google/cloud/debugger/debugger_c/evaluator.c +8 -3
- data/ext/google/cloud/debugger/debugger_c/tracer.c +3 -13
- data/lib/google/cloud/debugger/agent.rb +21 -3
- data/lib/google/cloud/debugger/breakpoint.rb +110 -107
- data/lib/google/cloud/debugger/breakpoint/evaluator.rb +49 -162
- data/lib/google/cloud/debugger/breakpoint/status_message.rb +95 -0
- data/lib/google/cloud/debugger/breakpoint/validator.rb +91 -0
- data/lib/google/cloud/debugger/breakpoint/variable.rb +313 -41
- data/lib/google/cloud/debugger/breakpoint/variable_table.rb +96 -0
- data/lib/google/cloud/debugger/breakpoint_manager.rb +45 -10
- data/lib/google/cloud/debugger/credentials.rb +2 -1
- data/lib/google/cloud/debugger/logpoint.rb +97 -0
- data/lib/google/cloud/debugger/middleware.rb +16 -5
- data/lib/google/cloud/debugger/request_quota_manager.rb +95 -0
- data/lib/google/cloud/debugger/snappoint.rb +208 -0
- data/lib/google/cloud/debugger/tracer.rb +20 -32
- data/lib/google/cloud/debugger/version.rb +1 -1
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 51d29e7310e1ea9e0f409ee2e2198d52af61c163
|
4
|
+
data.tar.gz: 0e8474858473a49f70b06481f281c98b79e0bd70
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a1e9da07abc025976a843eee2a93d545a09beedac8b7bfc34345ffd77e676ad17a9827fcafd285be65a05ed2d0adfd5380f2f06a12bcaa63b8cf7a000ac88eed
|
7
|
+
data.tar.gz: b91cc538bbdc514d8105ae0220c482df52be13539c36ad3cb50bb4d0db071a54c146a687c5a34af40a36de04ddd012b283b26b2a309d0d30ef616450c27c33f9
|
@@ -23,19 +23,24 @@ eval_trace_callback(void *data, rb_trace_arg_t *trace_arg)
|
|
23
23
|
{
|
24
24
|
rb_event_flag_t event = rb_tracearg_event_flag(trace_arg);
|
25
25
|
VALUE evaluator = (VALUE)data;
|
26
|
-
VALUE klass
|
27
|
-
VALUE obj
|
28
|
-
VALUE method_id
|
26
|
+
VALUE klass;
|
27
|
+
VALUE obj;
|
28
|
+
VALUE method_id;
|
29
29
|
ID trace_func_cb_id;
|
30
30
|
ID trace_c_func_cb_id;
|
31
31
|
|
32
32
|
CONST_ID(trace_func_cb_id, "trace_func_callback");
|
33
33
|
CONST_ID(trace_c_func_cb_id, "trace_c_func_callback");
|
34
34
|
|
35
|
+
obj = rb_tracearg_self(trace_arg);
|
36
|
+
method_id = rb_tracearg_method_id(trace_arg);
|
37
|
+
|
35
38
|
if (event & RUBY_EVENT_CALL) {
|
36
39
|
rb_funcall(evaluator, trace_func_cb_id, 2, obj, method_id);
|
37
40
|
}
|
38
41
|
if (event & RUBY_EVENT_C_CALL) {
|
42
|
+
klass = rb_tracearg_defined_class(trace_arg);
|
43
|
+
|
39
44
|
rb_funcall(evaluator, trace_c_func_cb_id, 3, obj, klass, method_id);
|
40
45
|
}
|
41
46
|
|
@@ -144,17 +144,13 @@ line_trace_callback(rb_event_flag_t event, VALUE data, VALUE obj, ID mid, VALUE
|
|
144
144
|
VALUE trace_binding;
|
145
145
|
VALUE call_stack_bindings;
|
146
146
|
|
147
|
-
int i;
|
148
147
|
VALUE matching_result = match_breakpoints(self, c_trace_path, c_trace_lineno);
|
149
|
-
VALUE *c_matching_breakpoints;
|
150
|
-
VALUE matching_breakpoint;
|
151
|
-
int matching_breakpoints_len;
|
152
148
|
|
153
149
|
ID callers_id;
|
154
|
-
ID
|
150
|
+
ID breakpoints_hit_id;
|
155
151
|
|
156
152
|
CONST_ID(callers_id, "callers");
|
157
|
-
CONST_ID(
|
153
|
+
CONST_ID(breakpoints_hit_id, "breakpoints_hit");
|
158
154
|
|
159
155
|
// If matching result isn't an array, it means we're in completely wrong file,
|
160
156
|
// or not on the right line. Turn line tracing off if we're in wrong file.
|
@@ -165,17 +161,11 @@ line_trace_callback(rb_event_flag_t event, VALUE data, VALUE obj, ID mid, VALUE
|
|
165
161
|
return;
|
166
162
|
}
|
167
163
|
|
168
|
-
c_matching_breakpoints = RARRAY_PTR(matching_result);
|
169
|
-
matching_breakpoints_len = RARRAY_LEN(matching_result);
|
170
164
|
trace_binding = rb_binding_new();
|
171
165
|
call_stack_bindings = rb_funcall(trace_binding, callers_id, 0);
|
172
166
|
rb_ary_pop(call_stack_bindings);
|
173
167
|
|
174
|
-
|
175
|
-
for (i = 0; i < matching_breakpoints_len; i++) {
|
176
|
-
matching_breakpoint = c_matching_breakpoints[i];
|
177
|
-
rb_funcall(self, breakpoint_hit_id, 2, matching_breakpoint, call_stack_bindings);
|
178
|
-
}
|
168
|
+
rb_funcall(self, breakpoints_hit_id, 2, matching_result, call_stack_bindings);
|
179
169
|
|
180
170
|
return;
|
181
171
|
}
|
@@ -90,6 +90,19 @@ module Google
|
|
90
90
|
# The logger used to write the results of Logpoints.
|
91
91
|
attr_accessor :logger
|
92
92
|
|
93
|
+
##
|
94
|
+
# A quota tracking object helps tracking resource consumption during
|
95
|
+
# evaluations.
|
96
|
+
attr_accessor :quota_manager
|
97
|
+
|
98
|
+
##
|
99
|
+
# Absolute path to the debuggee Ruby application root directory. The
|
100
|
+
# Stackdriver Debugger service creates canonical breakpoints with only
|
101
|
+
# relative path. So the debugger agent combines the relative path to
|
102
|
+
# the application directory to trace and evaluate breakpoints.
|
103
|
+
# @return [String]
|
104
|
+
attr_accessor :app_root
|
105
|
+
|
93
106
|
##
|
94
107
|
# @private The last exception captured in the agent child thread
|
95
108
|
attr_reader :last_exception
|
@@ -102,11 +115,13 @@ module Google
|
|
102
115
|
# @param [Google::Cloud::Logging::Logger] logger The logger used
|
103
116
|
# to write the results of Logpoints.
|
104
117
|
# @param [String] module_name Name for the debuggee application.
|
105
|
-
# Optional.
|
106
118
|
# @param [String] module_version Version identifier for the debuggee
|
107
|
-
# application.
|
119
|
+
# application.
|
120
|
+
# @param [String] app_root Absolute path to the root directory of
|
121
|
+
# the debuggee application. Default to Rack root.
|
108
122
|
#
|
109
|
-
def initialize service, logger: nil, module_name:, module_version
|
123
|
+
def initialize service, logger: nil, module_name:, module_version:,
|
124
|
+
app_root: nil
|
110
125
|
super()
|
111
126
|
|
112
127
|
@service = service
|
@@ -121,6 +136,9 @@ module Google
|
|
121
136
|
|
122
137
|
@logger = logger || default_logger
|
123
138
|
|
139
|
+
@app_root = app_root
|
140
|
+
@app_root ||= Rack::Directory.new("").root if defined? Rack::Directory
|
141
|
+
|
124
142
|
# Agent actor thread needs to force exit immediately.
|
125
143
|
set_cleanup_options timeout: 0
|
126
144
|
end
|
@@ -17,11 +17,21 @@ require "time"
|
|
17
17
|
require "google/cloud/debugger/breakpoint/evaluator"
|
18
18
|
require "google/cloud/debugger/breakpoint/source_location"
|
19
19
|
require "google/cloud/debugger/breakpoint/stack_frame"
|
20
|
+
require "google/cloud/debugger/breakpoint/status_message"
|
21
|
+
require "google/cloud/debugger/breakpoint/validator"
|
20
22
|
require "google/cloud/debugger/breakpoint/variable"
|
23
|
+
require "google/cloud/debugger/breakpoint/variable_table"
|
21
24
|
|
22
25
|
module Google
|
23
26
|
module Cloud
|
24
27
|
module Debugger
|
28
|
+
##
|
29
|
+
# # Breakpoint
|
30
|
+
#
|
31
|
+
# Abstract class that represents a breakpoint, which can be set and
|
32
|
+
# triggered in a debuggee application. Maps to gRPC struct
|
33
|
+
# {Google::Devtools::Clouddebugger::V2::Breakpoint}.
|
34
|
+
#
|
25
35
|
class Breakpoint
|
26
36
|
include MonitorMixin
|
27
37
|
|
@@ -34,6 +44,11 @@ module Google
|
|
34
44
|
# @return [Symbol]
|
35
45
|
attr_accessor :action
|
36
46
|
|
47
|
+
##
|
48
|
+
# Absolute path to the debuggee Ruby application root directory.
|
49
|
+
# @return [String]
|
50
|
+
attr_accessor :app_root
|
51
|
+
|
37
52
|
##
|
38
53
|
# Only relevant when action is LOG. Defines the message to log when the
|
39
54
|
# breakpoint hits. The message may include parameter placeholders $0,
|
@@ -124,8 +139,7 @@ module Google
|
|
124
139
|
# field. The stored objects are nameless and get their name from the
|
125
140
|
# referencing variable. The effective variable is a merge of the
|
126
141
|
# referencing variable and the referenced variable.
|
127
|
-
|
128
|
-
# attr_accessor :variable_table
|
142
|
+
attr_accessor :variable_table
|
129
143
|
|
130
144
|
##
|
131
145
|
# A set of custom breakpoint properties, populated by the agent, to be
|
@@ -145,6 +159,8 @@ module Google
|
|
145
159
|
|
146
160
|
@id = id
|
147
161
|
@action = :CAPTURE
|
162
|
+
# Use relative path for SourceLocation, because that's how the server
|
163
|
+
# side canonical breakpoints are defined.
|
148
164
|
@location = SourceLocation.new.tap do |sl|
|
149
165
|
sl.path = path
|
150
166
|
sl.line = line.to_i
|
@@ -153,6 +169,7 @@ module Google
|
|
153
169
|
@evaluated_expressions = []
|
154
170
|
@stack_frames = []
|
155
171
|
@labels = {}
|
172
|
+
@variable_table = VariableTable.new
|
156
173
|
end
|
157
174
|
|
158
175
|
##
|
@@ -160,26 +177,39 @@ module Google
|
|
160
177
|
# from a Google::Devtools::Clouddebugger::V2::Breakpoint object.
|
161
178
|
def self.from_grpc grpc
|
162
179
|
return new if grpc.nil?
|
163
|
-
|
180
|
+
|
181
|
+
breakpoint = grpc.action == :LOG ? Logpoint.new : Snappoint.new
|
182
|
+
breakpoint.tap do |b|
|
164
183
|
b.id = grpc.id
|
165
184
|
b.action = grpc.action
|
166
185
|
b.condition = grpc.condition
|
167
|
-
b.create_time = timestamp_from_grpc grpc.create_time
|
168
|
-
b.evaluated_expressions =
|
169
|
-
Breakpoint::Variable.from_grpc_list grpc.evaluated_expressions
|
170
186
|
b.expressions = grpc.expressions.to_a
|
171
|
-
b.final_time = timestamp_from_grpc grpc.final_time
|
172
187
|
b.labels = hashify_labels grpc.labels
|
173
188
|
b.log_message_format = grpc.log_message_format
|
174
189
|
b.log_level = grpc.log_level
|
175
|
-
b.location = Breakpoint::SourceLocation.from_grpc grpc.location
|
176
190
|
b.is_final_state = grpc.is_final_state
|
177
|
-
b.status = grpc.status
|
178
|
-
b.stack_frames = stack_frames_from_grpc grpc
|
179
191
|
b.user_email = grpc.user_email
|
192
|
+
|
193
|
+
assign_complex_grpc_fields grpc, b
|
180
194
|
end
|
181
195
|
end
|
182
196
|
|
197
|
+
##
|
198
|
+
# @private Helper method that helps extracting complex fields from
|
199
|
+
# grpc struct into a breakpoint.
|
200
|
+
def self.assign_complex_grpc_fields grpc, breakpoint
|
201
|
+
breakpoint.create_time = timestamp_from_grpc grpc.create_time
|
202
|
+
breakpoint.evaluated_expressions =
|
203
|
+
Breakpoint::Variable.from_grpc_list grpc.evaluated_expressions
|
204
|
+
breakpoint.final_time = timestamp_from_grpc grpc.final_time
|
205
|
+
breakpoint.location =
|
206
|
+
Breakpoint::SourceLocation.from_grpc grpc.location
|
207
|
+
breakpoint.stack_frames = stack_frames_from_grpc grpc
|
208
|
+
breakpoint.status = Breakpoint::StatusMessage.from_grpc grpc.status
|
209
|
+
breakpoint.variable_table =
|
210
|
+
Breakpoint::VariableTable.from_grpc grpc.variable_table
|
211
|
+
end
|
212
|
+
|
183
213
|
##
|
184
214
|
# @private Extract array of stack_frame from grpc
|
185
215
|
def self.stack_frames_from_grpc grpc
|
@@ -205,8 +235,10 @@ module Google
|
|
205
235
|
end
|
206
236
|
end
|
207
237
|
|
208
|
-
private_class_method :stack_frames_from_grpc,
|
209
|
-
:
|
238
|
+
private_class_method :stack_frames_from_grpc,
|
239
|
+
:timestamp_from_grpc,
|
240
|
+
:hashify_labels,
|
241
|
+
:assign_complex_grpc_fields
|
210
242
|
|
211
243
|
##
|
212
244
|
# Marks a breakpoint as complete if this breakpoint isn't completed
|
@@ -220,7 +252,21 @@ module Google
|
|
220
252
|
end
|
221
253
|
end
|
222
254
|
|
223
|
-
|
255
|
+
##
|
256
|
+
# Check if the breakpoint has been evaluated or set to a final error
|
257
|
+
# state.
|
258
|
+
def complete?
|
259
|
+
is_final_state ? true : false
|
260
|
+
end
|
261
|
+
|
262
|
+
##
|
263
|
+
# Check if the breakpoint is valid or not. Invoke validation function
|
264
|
+
# if breakpoint hasn't been finallized yet.
|
265
|
+
def valid?
|
266
|
+
Validator.validate self unless complete?
|
267
|
+
|
268
|
+
status && status.is_error ? false : true
|
269
|
+
end
|
224
270
|
|
225
271
|
##
|
226
272
|
# Get the file path of this breakpoint
|
@@ -244,44 +290,33 @@ module Google
|
|
244
290
|
|
245
291
|
##
|
246
292
|
# Evaluate the breakpoint's condition expression against a given binding
|
247
|
-
# object. Returns true if the condition expression evalutes to true
|
248
|
-
#
|
293
|
+
# object. Returns true if the condition expression evalutes to true or
|
294
|
+
# there isn't a condition; otherwise false. Set breakpoint to error
|
295
|
+
# state if exception happens.
|
249
296
|
#
|
250
297
|
# @param [Binding] binding A Ruby Binding object
|
251
|
-
# @return [Boolean] True if condition evalutes to true
|
252
|
-
# condition evaluates to false or error raised
|
253
|
-
#
|
298
|
+
# @return [Boolean] True if condition evalutes to true or there isn't a
|
299
|
+
# condition. False if condition evaluates to false or error raised
|
300
|
+
# during evaluation.
|
254
301
|
def check_condition binding
|
255
302
|
return true if condition.nil? || condition.empty?
|
256
|
-
|
257
|
-
Evaluator.
|
258
|
-
rescue
|
259
|
-
set_error_state "Unable to evaluate condition",
|
260
|
-
refers_to: :BREAKPOINT_CONDITION
|
261
|
-
false
|
262
|
-
end
|
263
|
-
end
|
303
|
+
condition_result =
|
304
|
+
Evaluator.readonly_eval_expression binding, condition
|
264
305
|
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
#
|
272
|
-
# @param [Array<Binding>] call_stack_bindings An array of Ruby Binding
|
273
|
-
# objects, from the call stack that leads to the triggering of the
|
274
|
-
# breakpoints.
|
275
|
-
#
|
276
|
-
# @return [Boolean] True if evaluated successfully; false otherwise.
|
277
|
-
#
|
278
|
-
def evaluate call_stack_bindings
|
279
|
-
case action
|
280
|
-
when :CAPTURE
|
281
|
-
evaluate_snapshot_point call_stack_bindings
|
282
|
-
when :LOG
|
283
|
-
evaluate_logpoint call_stack_bindings[0]
|
306
|
+
if condition_result.is_a?(Exception) &&
|
307
|
+
condition_result.instance_variable_get(:@mutation_cause)
|
308
|
+
set_error_state "Error: #{condition_result.message}",
|
309
|
+
refers_to: StatusMessage::BREAKPOINT_CONDITION
|
310
|
+
|
311
|
+
return false
|
284
312
|
end
|
313
|
+
|
314
|
+
|
315
|
+
condition_result ? true : false
|
316
|
+
rescue => e
|
317
|
+
set_error_state "Error: #{e.message}",
|
318
|
+
refers_to: StatusMessage::BREAKPOINT_CONDITION
|
319
|
+
false
|
285
320
|
end
|
286
321
|
|
287
322
|
##
|
@@ -313,8 +348,9 @@ module Google
|
|
313
348
|
user_email: user_email,
|
314
349
|
stack_frames: stack_frames_to_grpc,
|
315
350
|
evaluated_expressions: evaluated_expressions_to_grpc,
|
316
|
-
status:
|
317
|
-
labels: labels_to_grpc
|
351
|
+
status: status_to_grpc,
|
352
|
+
labels: labels_to_grpc,
|
353
|
+
variable_table: variable_table.to_grpc
|
318
354
|
)
|
319
355
|
end
|
320
356
|
|
@@ -324,79 +360,39 @@ module Google
|
|
324
360
|
# completed if is_final is true.
|
325
361
|
#
|
326
362
|
# @param [String] message The error message
|
327
|
-
# @param [
|
328
|
-
#
|
329
|
-
#
|
363
|
+
# @param [Symbol] refers_to Enum that specifies what the error refers
|
364
|
+
# to. Defaults :UNSPECIFIED. See {Breakpoint::StatusMessage} class for
|
365
|
+
# list of possible values
|
330
366
|
# @param [Boolean] is_final Marks the breakpoint as final if true.
|
331
367
|
# Defaults true.
|
332
368
|
#
|
333
|
-
# @return [Google::
|
369
|
+
# @return [Google::Cloud::Debugger::Breakpoint::StatusMessage] The grpc
|
334
370
|
# StatusMessage object, which describes the breakpoint's error state.
|
335
|
-
def set_error_state message, refers_to:
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
description: description
|
343
|
-
)
|
371
|
+
def set_error_state message, refers_to: StatusMessage::UNSPECIFIED,
|
372
|
+
is_final: true
|
373
|
+
@status = StatusMessage.new.tap do |s|
|
374
|
+
s.is_error = true
|
375
|
+
s.refers_to = refers_to
|
376
|
+
s.description = message
|
377
|
+
end
|
344
378
|
|
345
379
|
complete if is_final
|
346
380
|
|
347
381
|
@status
|
348
382
|
end
|
349
383
|
|
350
|
-
private
|
351
|
-
|
352
384
|
##
|
353
|
-
#
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
begin
|
361
|
-
unless expressions.empty?
|
362
|
-
@evaluated_expressions =
|
363
|
-
Evaluator.eval_expressions top_binding, @expressions
|
364
|
-
end
|
365
|
-
|
366
|
-
@stack_frames = Evaluator.eval_call_stack call_stack_bindings
|
367
|
-
|
368
|
-
complete
|
369
|
-
rescue
|
370
|
-
return false
|
371
|
-
end
|
372
|
-
end
|
373
|
-
|
374
|
-
true
|
375
|
-
end
|
376
|
-
|
377
|
-
##
|
378
|
-
# @private Evaluate logpoint
|
379
|
-
def evaluate_logpoint binding
|
380
|
-
synchronize do
|
381
|
-
return false if complete? || !check_condition(binding)
|
382
|
-
|
383
|
-
begin
|
384
|
-
unless expressions.empty?
|
385
|
-
@evaluated_expressions = expressions.map do |expression|
|
386
|
-
Evaluator.readonly_eval_expression binding, expression
|
387
|
-
end
|
388
|
-
end
|
389
|
-
@evaluated_log_message =
|
390
|
-
Evaluator.format_message log_message_format,
|
391
|
-
evaluated_expressions
|
392
|
-
rescue
|
393
|
-
return false
|
394
|
-
end
|
385
|
+
# Get full absolute file path by combining the relative file path
|
386
|
+
# with application root directory path.
|
387
|
+
def full_path
|
388
|
+
if app_root.nil? || app_root.empty?
|
389
|
+
path
|
390
|
+
else
|
391
|
+
File.join app_root, path
|
395
392
|
end
|
396
|
-
|
397
|
-
true
|
398
393
|
end
|
399
394
|
|
395
|
+
private
|
400
396
|
|
401
397
|
##
|
402
398
|
# @private Formats the labels so they can be saved to a
|
@@ -417,11 +413,18 @@ module Google
|
|
417
413
|
|
418
414
|
##
|
419
415
|
# @private Exports the Breakpoint stack_frames to an array of
|
420
|
-
# Google::Devtools::Clouddebugger::V2::
|
416
|
+
# Google::Devtools::Clouddebugger::V2::Variable objects.
|
421
417
|
def evaluated_expressions_to_grpc
|
422
418
|
evaluated_expressions.nil? ? [] : evaluated_expressions.map(&:to_grpc)
|
423
419
|
end
|
424
420
|
|
421
|
+
##
|
422
|
+
# @private Exports Breakpoint status to
|
423
|
+
# Google::Devtools::Clouddebugger::V2::StatusMessage object
|
424
|
+
def status_to_grpc
|
425
|
+
status.nil? ? nil: status.to_grpc
|
426
|
+
end
|
427
|
+
|
425
428
|
##
|
426
429
|
# @private Formats the timestamp as a Google::Protobuf::Timestamp
|
427
430
|
# object.
|