google-cloud-debugger 0.25.0 → 0.26.1
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 +37 -10
- data/ext/google/cloud/debugger/debugger_c/tracer.c +76 -20
- data/lib/google/cloud/debugger/agent.rb +42 -19
- data/lib/google/cloud/debugger/breakpoint.rb +92 -36
- data/lib/google/cloud/debugger/breakpoint/evaluator.rb +27 -0
- data/lib/google/cloud/debugger/breakpoint_manager.rb +59 -1
- data/lib/google/cloud/debugger/middleware.rb +8 -0
- data/lib/google/cloud/debugger/tracer.rb +5 -22
- data/lib/google/cloud/debugger/transmitter.rb +27 -16
- data/lib/google/cloud/debugger/v2.rb +1 -1
- data/lib/google/cloud/debugger/v2/controller2_client.rb +11 -3
- data/lib/google/cloud/debugger/v2/controller2_client_config.json +1 -3
- data/lib/google/cloud/debugger/v2/debugger2_client.rb +13 -5
- data/lib/google/cloud/debugger/v2/debugger2_client_config.json +1 -3
- data/lib/google/cloud/debugger/version.rb +1 -1
- data/lib/google/devtools/clouddebugger/v2/data_pb.rb +1 -0
- metadata +18 -5
- data/lib/google/cloud/debugger/async_actor.rb +0 -290
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7a8f4cd45e74a4f18bf53c08fb05284529937c6b
|
4
|
+
data.tar.gz: '0718436023043859a8c9b958dc43bb623fb7ec79'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 323fde821b65e2167e7ea0b56f2ff988203d62d5391032890be39636bec869750e4bf701a7756b50b59b7b9eb11c71819a8a0df3830574304b7b3d38e1cfa595
|
7
|
+
data.tar.gz: e68aa3d18c0aaf72db470b4dba4e1ecf439da21b43aeb081a552a49d8da093121795ffd32beec52fda075b68a90564cc70a88b579fca4008b1f2b6386032920c
|
@@ -26,12 +26,17 @@ eval_trace_callback(void *data, rb_trace_arg_t *trace_arg)
|
|
26
26
|
VALUE klass = rb_tracearg_defined_class(trace_arg);
|
27
27
|
VALUE obj = rb_tracearg_self(trace_arg);
|
28
28
|
VALUE method_id = rb_tracearg_method_id(trace_arg);
|
29
|
+
ID trace_func_cb_id;
|
30
|
+
ID trace_c_func_cb_id;
|
31
|
+
|
32
|
+
CONST_ID(trace_func_cb_id, "trace_func_callback");
|
33
|
+
CONST_ID(trace_c_func_cb_id, "trace_c_func_callback");
|
29
34
|
|
30
35
|
if (event & RUBY_EVENT_CALL) {
|
31
|
-
rb_funcall(evaluator,
|
36
|
+
rb_funcall(evaluator, trace_func_cb_id, 2, obj, method_id);
|
32
37
|
}
|
33
38
|
if (event & RUBY_EVENT_C_CALL) {
|
34
|
-
rb_funcall(evaluator,
|
39
|
+
rb_funcall(evaluator, trace_c_func_cb_id, 3, obj, klass, method_id);
|
35
40
|
}
|
36
41
|
|
37
42
|
return;
|
@@ -40,13 +45,24 @@ eval_trace_callback(void *data, rb_trace_arg_t *trace_arg)
|
|
40
45
|
static VALUE
|
41
46
|
rb_disable_method_trace_for_thread(VALUE self)
|
42
47
|
{
|
43
|
-
VALUE current_thread
|
44
|
-
VALUE thread_variables_hash
|
45
|
-
VALUE trace_set
|
48
|
+
VALUE current_thread;
|
49
|
+
VALUE thread_variables_hash;
|
50
|
+
VALUE trace_set;
|
51
|
+
ID locals_id;
|
52
|
+
ID eval_trace_thread_id;
|
53
|
+
VALUE eval_trace_thread_flag;
|
54
|
+
|
55
|
+
CONST_ID(locals_id, "locals");
|
56
|
+
CONST_ID(eval_trace_thread_id, "gcloud_eval_trace_set");
|
57
|
+
eval_trace_thread_flag = ID2SYM(eval_trace_thread_id);
|
58
|
+
|
59
|
+
current_thread = rb_thread_current();
|
60
|
+
thread_variables_hash = rb_ivar_get(current_thread, locals_id);
|
61
|
+
trace_set = rb_hash_aref(thread_variables_hash, eval_trace_thread_flag);
|
46
62
|
|
47
63
|
if (RTEST(trace_set)) {
|
48
64
|
rb_thread_remove_event_hook(current_thread, (rb_event_hook_func_t)eval_trace_callback);
|
49
|
-
rb_hash_aset(thread_variables_hash,
|
65
|
+
rb_hash_aset(thread_variables_hash, eval_trace_thread_flag, Qfalse);
|
50
66
|
}
|
51
67
|
|
52
68
|
return Qnil;
|
@@ -55,13 +71,24 @@ rb_disable_method_trace_for_thread(VALUE self)
|
|
55
71
|
static VALUE
|
56
72
|
rb_enable_method_trace_for_thread(VALUE self)
|
57
73
|
{
|
58
|
-
VALUE current_thread
|
59
|
-
VALUE thread_variables_hash
|
60
|
-
VALUE trace_set
|
74
|
+
VALUE current_thread;
|
75
|
+
VALUE thread_variables_hash;
|
76
|
+
VALUE trace_set;
|
77
|
+
ID locals_id;
|
78
|
+
ID eval_trace_thread_id;
|
79
|
+
VALUE eval_trace_thread_flag;
|
80
|
+
|
81
|
+
CONST_ID(locals_id, "locals");
|
82
|
+
CONST_ID(eval_trace_thread_id, "gcloud_eval_trace_set");
|
83
|
+
eval_trace_thread_flag = ID2SYM(eval_trace_thread_id);
|
84
|
+
|
85
|
+
current_thread = rb_thread_current();
|
86
|
+
thread_variables_hash = rb_ivar_get(current_thread, locals_id);
|
87
|
+
trace_set = rb_hash_aref(thread_variables_hash, eval_trace_thread_flag);
|
61
88
|
|
62
89
|
if (!RTEST(trace_set)) {
|
63
90
|
rb_thread_add_event_hook2(current_thread, (rb_event_hook_func_t)eval_trace_callback, RUBY_EVENT_CALL | RUBY_EVENT_C_CALL, self, RUBY_EVENT_HOOK_FLAG_RAW_ARG | RUBY_EVENT_HOOK_FLAG_SAFE);
|
64
|
-
rb_hash_aset(thread_variables_hash,
|
91
|
+
rb_hash_aset(thread_variables_hash, eval_trace_thread_flag, Qtrue);
|
65
92
|
}
|
66
93
|
|
67
94
|
return Qnil;
|
@@ -150,6 +150,12 @@ line_trace_callback(rb_event_flag_t event, VALUE data, VALUE obj, ID mid, VALUE
|
|
150
150
|
VALUE matching_breakpoint;
|
151
151
|
int matching_breakpoints_len;
|
152
152
|
|
153
|
+
ID callers_id;
|
154
|
+
ID breakpoint_hit_id;
|
155
|
+
|
156
|
+
CONST_ID(callers_id, "callers");
|
157
|
+
CONST_ID(breakpoint_hit_id, "breakpoint_hit");
|
158
|
+
|
153
159
|
// If matching result isn't an array, it means we're in completely wrong file,
|
154
160
|
// or not on the right line. Turn line tracing off if we're in wrong file.
|
155
161
|
if (!RB_TYPE_P(matching_result, T_ARRAY)) {
|
@@ -162,13 +168,13 @@ line_trace_callback(rb_event_flag_t event, VALUE data, VALUE obj, ID mid, VALUE
|
|
162
168
|
c_matching_breakpoints = RARRAY_PTR(matching_result);
|
163
169
|
matching_breakpoints_len = RARRAY_LEN(matching_result);
|
164
170
|
trace_binding = rb_binding_new();
|
165
|
-
call_stack_bindings = rb_funcall(trace_binding,
|
171
|
+
call_stack_bindings = rb_funcall(trace_binding, callers_id, 0);
|
166
172
|
rb_ary_pop(call_stack_bindings);
|
167
173
|
|
168
174
|
// Evaluate each of the matching breakpoint
|
169
175
|
for (i = 0; i < matching_breakpoints_len; i++) {
|
170
176
|
matching_breakpoint = c_matching_breakpoints[i];
|
171
|
-
rb_funcall(self,
|
177
|
+
rb_funcall(self, breakpoint_hit_id, 2, matching_breakpoint, call_stack_bindings);
|
172
178
|
}
|
173
179
|
|
174
180
|
return;
|
@@ -185,16 +191,23 @@ disable_line_trace_for_thread(VALUE thread)
|
|
185
191
|
{
|
186
192
|
VALUE thread_variables_hash;
|
187
193
|
VALUE line_trace_set;
|
194
|
+
ID locals_id;
|
195
|
+
ID line_trace_thread_id;
|
196
|
+
VALUE line_trace_thread_flag;
|
197
|
+
|
198
|
+
CONST_ID(locals_id, "locals");
|
199
|
+
CONST_ID(line_trace_thread_id, "gcloud_line_trace_set");
|
200
|
+
line_trace_thread_flag = ID2SYM(line_trace_thread_id);
|
188
201
|
|
189
202
|
if (!RTEST(thread)) {
|
190
203
|
thread = rb_thread_current();
|
191
204
|
}
|
192
|
-
thread_variables_hash = rb_ivar_get(thread,
|
193
|
-
line_trace_set = rb_hash_aref(thread_variables_hash,
|
205
|
+
thread_variables_hash = rb_ivar_get(thread, locals_id);
|
206
|
+
line_trace_set = rb_hash_aref(thread_variables_hash, line_trace_thread_flag);
|
194
207
|
|
195
208
|
if (RTEST(line_trace_set)) {
|
196
209
|
rb_thread_remove_event_hook(thread, line_trace_callback);
|
197
|
-
rb_hash_aset(thread_variables_hash,
|
210
|
+
rb_hash_aset(thread_variables_hash, line_trace_thread_flag, Qfalse);
|
198
211
|
}
|
199
212
|
|
200
213
|
return Qnil;
|
@@ -208,13 +221,24 @@ disable_line_trace_for_thread(VALUE thread)
|
|
208
221
|
static VALUE
|
209
222
|
enable_line_trace_for_thread(VALUE self)
|
210
223
|
{
|
211
|
-
VALUE current_thread
|
212
|
-
VALUE thread_variables_hash
|
213
|
-
VALUE line_trace_set
|
224
|
+
VALUE current_thread;
|
225
|
+
VALUE thread_variables_hash;
|
226
|
+
VALUE line_trace_set;
|
227
|
+
ID locals_id;
|
228
|
+
ID line_trace_thread_id;
|
229
|
+
VALUE line_trace_thread_flag;
|
230
|
+
|
231
|
+
CONST_ID(locals_id, "locals");
|
232
|
+
CONST_ID(line_trace_thread_id, "gcloud_line_trace_set");
|
233
|
+
line_trace_thread_flag = ID2SYM(line_trace_thread_id);
|
234
|
+
|
235
|
+
current_thread = rb_thread_current();
|
236
|
+
thread_variables_hash = rb_ivar_get(current_thread, locals_id);
|
237
|
+
line_trace_set = rb_hash_aref(thread_variables_hash, line_trace_thread_flag);
|
214
238
|
|
215
239
|
if (!RTEST(line_trace_set)) {
|
216
240
|
rb_thread_add_event_hook(current_thread, line_trace_callback, RUBY_EVENT_LINE, self);
|
217
|
-
rb_hash_aset(thread_variables_hash,
|
241
|
+
rb_hash_aset(thread_variables_hash, line_trace_thread_flag, Qtrue);
|
218
242
|
}
|
219
243
|
|
220
244
|
return Qnil;
|
@@ -236,18 +260,26 @@ return_trace_callback(void *data, rb_trace_arg_t *trace_arg)
|
|
236
260
|
{
|
237
261
|
VALUE match_found;
|
238
262
|
VALUE self = (VALUE) data;
|
239
|
-
VALUE caller_locations
|
263
|
+
VALUE caller_locations;
|
240
264
|
VALUE *c_caller_locations;
|
241
265
|
VALUE caller_location;
|
242
266
|
VALUE caller_path;
|
243
267
|
|
268
|
+
ID caller_locations_id;
|
269
|
+
ID absolute_path_id;
|
270
|
+
|
271
|
+
CONST_ID(caller_locations_id, "caller_locations");
|
272
|
+
CONST_ID(absolute_path_id, "absolute_path");
|
273
|
+
|
274
|
+
caller_locations = rb_funcall(rb_mKernel, caller_locations_id, 2, INT2NUM(0), INT2NUM(1));
|
275
|
+
|
244
276
|
if(!RTEST(caller_locations)) {
|
245
277
|
return;
|
246
278
|
}
|
247
279
|
|
248
280
|
c_caller_locations = RARRAY_PTR(caller_locations);
|
249
281
|
caller_location = c_caller_locations[0];
|
250
|
-
caller_path = rb_funcall(caller_location,
|
282
|
+
caller_path = rb_funcall(caller_location, absolute_path_id, 0);
|
251
283
|
|
252
284
|
if(!RTEST(caller_path)) {
|
253
285
|
return;
|
@@ -273,16 +305,23 @@ disable_return_trace_for_thread(VALUE thread)
|
|
273
305
|
{
|
274
306
|
VALUE thread_variables_hash;
|
275
307
|
VALUE return_trace_set;
|
308
|
+
ID locals_id;
|
309
|
+
ID return_trace_thread_id;
|
310
|
+
VALUE return_trace_thread_flag;
|
311
|
+
|
312
|
+
CONST_ID(locals_id, "locals");
|
313
|
+
CONST_ID(return_trace_thread_id, "gcloud_return_trace_set");
|
314
|
+
return_trace_thread_flag = ID2SYM(return_trace_thread_id);
|
276
315
|
|
277
316
|
if (!RTEST(thread)) {
|
278
317
|
thread = rb_thread_current();
|
279
318
|
}
|
280
|
-
thread_variables_hash = rb_ivar_get(thread,
|
281
|
-
return_trace_set = rb_hash_aref(thread_variables_hash,
|
319
|
+
thread_variables_hash = rb_ivar_get(thread, locals_id);
|
320
|
+
return_trace_set = rb_hash_aref(thread_variables_hash, return_trace_thread_flag);
|
282
321
|
|
283
322
|
if (RTEST(return_trace_set)) {
|
284
323
|
rb_thread_remove_event_hook(thread, (rb_event_hook_func_t)return_trace_callback);
|
285
|
-
rb_hash_aset(thread_variables_hash,
|
324
|
+
rb_hash_aset(thread_variables_hash, return_trace_thread_flag, Qfalse);
|
286
325
|
}
|
287
326
|
|
288
327
|
return Qnil;
|
@@ -296,14 +335,26 @@ disable_return_trace_for_thread(VALUE thread)
|
|
296
335
|
static VALUE
|
297
336
|
enable_return_trace_for_thread(VALUE self)
|
298
337
|
{
|
299
|
-
VALUE current_thread
|
300
|
-
VALUE thread_variables_hash
|
301
|
-
VALUE return_trace_set
|
338
|
+
VALUE current_thread;
|
339
|
+
VALUE thread_variables_hash;
|
340
|
+
VALUE return_trace_set;
|
341
|
+
|
342
|
+
ID locals_id;
|
343
|
+
ID return_trace_thread_id;
|
344
|
+
VALUE return_trace_thread_flag;
|
345
|
+
|
346
|
+
CONST_ID(locals_id, "locals");
|
347
|
+
CONST_ID(return_trace_thread_id, "gcloud_return_trace_set");
|
348
|
+
return_trace_thread_flag = ID2SYM(return_trace_thread_id);
|
349
|
+
|
350
|
+
current_thread = rb_thread_current();
|
351
|
+
thread_variables_hash = rb_ivar_get(current_thread, locals_id);
|
352
|
+
return_trace_set = rb_hash_aref(thread_variables_hash, return_trace_thread_flag);
|
302
353
|
|
303
354
|
if (!RTEST(return_trace_set)) {
|
304
355
|
int return_tracepoint_event = RUBY_EVENT_END | RUBY_EVENT_RETURN | RUBY_EVENT_C_RETURN | RUBY_EVENT_B_RETURN;
|
305
356
|
rb_thread_add_event_hook2(current_thread, (rb_event_hook_func_t)return_trace_callback, return_tracepoint_event, self, RUBY_EVENT_HOOK_FLAG_RAW_ARG | RUBY_EVENT_HOOK_FLAG_SAFE);
|
306
|
-
rb_hash_aset(thread_variables_hash,
|
357
|
+
rb_hash_aset(thread_variables_hash, return_trace_thread_flag, Qtrue);
|
307
358
|
}
|
308
359
|
|
309
360
|
return Qnil;
|
@@ -398,9 +449,14 @@ rb_disable_traces(VALUE self)
|
|
398
449
|
int c_threads_len;
|
399
450
|
VALUE thread;
|
400
451
|
int i;
|
452
|
+
ID alive_q_id;
|
453
|
+
ID list_id;
|
454
|
+
|
455
|
+
CONST_ID(alive_q_id, "alive?");
|
456
|
+
CONST_ID(list_id, "list");
|
401
457
|
|
402
458
|
file_tracepoint = rb_iv_get(self, "@file_tracepoint");
|
403
|
-
threads = rb_funcall(rb_cThread,
|
459
|
+
threads = rb_funcall(rb_cThread, list_id, 0);
|
404
460
|
c_threads_len = RARRAY_LEN(threads);
|
405
461
|
c_threads = RARRAY_PTR(threads);
|
406
462
|
UNUSED(fiber_tracepoint);
|
@@ -416,7 +472,7 @@ rb_disable_traces(VALUE self)
|
|
416
472
|
|
417
473
|
for (i = 0; i < c_threads_len; i++) {
|
418
474
|
thread = c_threads[i];
|
419
|
-
if (RTEST(rb_funcall(thread,
|
475
|
+
if (RTEST(rb_funcall(thread, alive_q_id, 0))) {
|
420
476
|
disable_line_trace_for_thread(thread);
|
421
477
|
disable_return_trace_for_thread(thread);
|
422
478
|
}
|
@@ -13,12 +13,13 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
15
|
|
16
|
-
require "google/cloud/debugger/async_actor"
|
17
16
|
require "google/cloud/debugger/breakpoint_manager"
|
18
17
|
require "google/cloud/debugger/debuggee"
|
19
18
|
require "google/cloud/debugger/debugger_c"
|
20
19
|
require "google/cloud/debugger/tracer"
|
21
20
|
require "google/cloud/debugger/transmitter"
|
21
|
+
require "google/cloud/logging"
|
22
|
+
require "stackdriver/core/async_actor"
|
22
23
|
|
23
24
|
module Google
|
24
25
|
module Cloud
|
@@ -46,9 +47,13 @@ module Google
|
|
46
47
|
# agent.start
|
47
48
|
#
|
48
49
|
class Agent
|
50
|
+
##
|
51
|
+
# Name of the logpoints log file.
|
52
|
+
DEFAULT_LOG_NAME = "debugger_logpoints"
|
53
|
+
|
49
54
|
##
|
50
55
|
# @private Debugger Agent is an asynchronous actor
|
51
|
-
include AsyncActor
|
56
|
+
include Stackdriver::Core::AsyncActor
|
52
57
|
|
53
58
|
##
|
54
59
|
# @private The gRPC Service object.
|
@@ -81,6 +86,10 @@ module Google
|
|
81
86
|
# @return [Google::Cloud::Debugger::Transmiter]
|
82
87
|
attr_reader :transmitter
|
83
88
|
|
89
|
+
##
|
90
|
+
# The logger used to write the results of Logpoints.
|
91
|
+
attr_accessor :logger
|
92
|
+
|
84
93
|
##
|
85
94
|
# @private The last exception captured in the agent child thread
|
86
95
|
attr_reader :last_exception
|
@@ -90,23 +99,30 @@ module Google
|
|
90
99
|
#
|
91
100
|
# @param [Google::Cloud::Debugger::Service] service The gRPC Service
|
92
101
|
# object
|
102
|
+
# @param [Google::Cloud::Logging::Logger] logger The logger used
|
103
|
+
# to write the results of Logpoints.
|
93
104
|
# @param [String] module_name Name for the debuggee application.
|
94
105
|
# Optional.
|
95
106
|
# @param [String] module_version Version identifier for the debuggee
|
96
107
|
# application. Optional.
|
97
108
|
#
|
98
|
-
def initialize service, module_name:, module_version:
|
109
|
+
def initialize service, logger: nil, module_name:, module_version:
|
99
110
|
super()
|
100
111
|
|
101
112
|
@service = service
|
102
113
|
@debuggee = Debuggee.new service, module_name: module_name,
|
103
114
|
module_version: module_version
|
104
115
|
@tracer = Debugger::Tracer.new self
|
105
|
-
@breakpoint_manager = BreakpointManager.new service
|
116
|
+
@breakpoint_manager = BreakpointManager.new self, service
|
106
117
|
@breakpoint_manager.on_breakpoints_change =
|
107
118
|
method :breakpoints_change_callback
|
108
119
|
|
109
|
-
@transmitter = Transmitter.new
|
120
|
+
@transmitter = Transmitter.new self, service
|
121
|
+
|
122
|
+
@logger = logger || default_logger
|
123
|
+
|
124
|
+
# Agent actor thread needs to force exit immediately.
|
125
|
+
set_cleanup_options timeout: 0
|
110
126
|
end
|
111
127
|
|
112
128
|
##
|
@@ -126,7 +142,6 @@ module Google
|
|
126
142
|
# Once Debugger Agent is stopped, it cannot be started again.
|
127
143
|
#
|
128
144
|
def stop
|
129
|
-
tracer.stop
|
130
145
|
transmitter.stop
|
131
146
|
async_stop
|
132
147
|
end
|
@@ -154,6 +169,16 @@ module Google
|
|
154
169
|
@last_exception = e
|
155
170
|
end
|
156
171
|
|
172
|
+
##
|
173
|
+
# @private Callback function when the async actor thread state changes
|
174
|
+
def on_async_state_change
|
175
|
+
if async_running?
|
176
|
+
tracer.start
|
177
|
+
else
|
178
|
+
tracer.stop
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
157
182
|
private
|
158
183
|
|
159
184
|
##
|
@@ -184,19 +209,17 @@ module Google
|
|
184
209
|
end
|
185
210
|
|
186
211
|
##
|
187
|
-
# @private
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
end
|
199
|
-
end
|
212
|
+
# @private Create a default logger
|
213
|
+
def default_logger
|
214
|
+
project_id = @service.project
|
215
|
+
credentials = @service.credentials
|
216
|
+
logging = Google::Cloud::Logging::Project.new(
|
217
|
+
Google::Cloud::Logging::Service.new(
|
218
|
+
project_id, credentials))
|
219
|
+
resource =
|
220
|
+
Google::Cloud::Logging::Middleware.build_monitored_resource
|
221
|
+
|
222
|
+
logging.logger DEFAULT_LOG_NAME, resource
|
200
223
|
end
|
201
224
|
end
|
202
225
|
end
|
@@ -29,10 +29,26 @@ module Google
|
|
29
29
|
# Breakpoint identifier, unique in the scope of the debuggee.
|
30
30
|
attr_accessor :id
|
31
31
|
|
32
|
-
|
33
|
-
#
|
34
|
-
#
|
35
|
-
|
32
|
+
##
|
33
|
+
# Action to take when a breakpoint is hit. Either :CAPTURE or :LOG.
|
34
|
+
# @return [Symbol]
|
35
|
+
attr_accessor :action
|
36
|
+
|
37
|
+
##
|
38
|
+
# Only relevant when action is LOG. Defines the message to log when the
|
39
|
+
# breakpoint hits. The message may include parameter placeholders $0,
|
40
|
+
# $1, etc. These placeholders are replaced with the evaluated value of
|
41
|
+
# the appropriate expression. Expressions not referenced in
|
42
|
+
# logMessageFormat are not logged.
|
43
|
+
attr_accessor :log_message_format
|
44
|
+
|
45
|
+
##
|
46
|
+
# Indicates the severity of the log. Only relevant when action is LOG.
|
47
|
+
attr_accessor :log_level
|
48
|
+
|
49
|
+
##
|
50
|
+
# The evaluated log message when action is LOG.
|
51
|
+
attr_accessor :evaluated_log_message
|
36
52
|
|
37
53
|
##
|
38
54
|
# Breakpoint source location.
|
@@ -128,7 +144,7 @@ module Google
|
|
128
144
|
super()
|
129
145
|
|
130
146
|
@id = id
|
131
|
-
|
147
|
+
@action = :CAPTURE
|
132
148
|
@location = SourceLocation.new.tap do |sl|
|
133
149
|
sl.path = path
|
134
150
|
sl.line = line.to_i
|
@@ -144,19 +160,23 @@ module Google
|
|
144
160
|
# from a Google::Devtools::Clouddebugger::V2::Breakpoint object.
|
145
161
|
def self.from_grpc grpc
|
146
162
|
return new if grpc.nil?
|
147
|
-
new
|
148
|
-
b.
|
163
|
+
new.tap do |b|
|
164
|
+
b.id = grpc.id
|
165
|
+
b.action = grpc.action
|
149
166
|
b.condition = grpc.condition
|
150
|
-
b.
|
151
|
-
b.expressions = grpc.expressions.to_a
|
167
|
+
b.create_time = timestamp_from_grpc grpc.create_time
|
152
168
|
b.evaluated_expressions =
|
153
169
|
Breakpoint::Variable.from_grpc_list grpc.evaluated_expressions
|
154
|
-
b.
|
170
|
+
b.expressions = grpc.expressions.to_a
|
155
171
|
b.final_time = timestamp_from_grpc grpc.final_time
|
156
|
-
b.user_email = grpc.user_email
|
157
|
-
b.status = grpc.status
|
158
172
|
b.labels = hashify_labels grpc.labels
|
173
|
+
b.log_message_format = grpc.log_message_format
|
174
|
+
b.log_level = grpc.log_level
|
175
|
+
b.location = Breakpoint::SourceLocation.from_grpc grpc.location
|
176
|
+
b.is_final_state = grpc.is_final_state
|
177
|
+
b.status = grpc.status
|
159
178
|
b.stack_frames = stack_frames_from_grpc grpc
|
179
|
+
b.user_email = grpc.user_email
|
160
180
|
end
|
161
181
|
end
|
162
182
|
|
@@ -243,9 +263,11 @@ module Google
|
|
243
263
|
end
|
244
264
|
|
245
265
|
##
|
246
|
-
# Evaluate the breakpoint unless it's already marked as completed.
|
247
|
-
#
|
248
|
-
#
|
266
|
+
# Evaluate the breakpoint unless it's already marked as completed.
|
267
|
+
# Store evaluted results in @evaluated_expressions, @stack_frames, and
|
268
|
+
# @evaluated_log_message, depends on the action of breakpoint. Mark
|
269
|
+
# breakpoint complete if successfully evaluated a breakpoint with
|
270
|
+
# :CAPTURE action.
|
249
271
|
#
|
250
272
|
# @param [Array<Binding>] call_stack_bindings An array of Ruby Binding
|
251
273
|
# objects, from the call stack that leads to the triggering of the
|
@@ -253,28 +275,13 @@ module Google
|
|
253
275
|
#
|
254
276
|
# @return [Boolean] True if evaluated successfully; false otherwise.
|
255
277
|
#
|
256
|
-
def
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
# Abort evaluation if breakpoint condition isn't met
|
263
|
-
return false unless check_condition top_frame_binding
|
264
|
-
|
265
|
-
begin
|
266
|
-
@stack_frames = Evaluator.eval_call_stack call_stack_bindings
|
267
|
-
unless expressions.empty?
|
268
|
-
@evaluated_expressions =
|
269
|
-
Evaluator.eval_expressions top_frame_binding, @expressions
|
270
|
-
end
|
271
|
-
rescue
|
272
|
-
return false
|
273
|
-
end
|
274
|
-
|
275
|
-
complete
|
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]
|
276
284
|
end
|
277
|
-
true
|
278
285
|
end
|
279
286
|
|
280
287
|
##
|
@@ -342,6 +349,55 @@ module Google
|
|
342
349
|
|
343
350
|
private
|
344
351
|
|
352
|
+
##
|
353
|
+
# @private Evaluate snapshot point
|
354
|
+
def evaluate_snapshot_point call_stack_bindings
|
355
|
+
synchronize do
|
356
|
+
top_binding = call_stack_bindings[0]
|
357
|
+
|
358
|
+
return false if complete? || !check_condition(top_binding)
|
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
|
395
|
+
end
|
396
|
+
|
397
|
+
true
|
398
|
+
end
|
399
|
+
|
400
|
+
|
345
401
|
##
|
346
402
|
# @private Formats the labels so they can be saved to a
|
347
403
|
# Google::Devtools::Clouddebugger::V2::Breakpoint object.
|