google-cloud-debugger 0.25.0 → 0.26.1
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|