google-cloud-debugger 0.40.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 +7 -0
- data/.yardopts +18 -0
- data/AUTHENTICATION.md +178 -0
- data/CHANGELOG.md +233 -0
- data/CODE_OF_CONDUCT.md +40 -0
- data/CONTRIBUTING.md +188 -0
- data/INSTRUMENTATION.md +115 -0
- data/LICENSE +201 -0
- data/LOGGING.md +32 -0
- data/OVERVIEW.md +266 -0
- data/TROUBLESHOOTING.md +31 -0
- data/ext/google/cloud/debugger/debugger_c/debugger.c +31 -0
- data/ext/google/cloud/debugger/debugger_c/debugger.h +26 -0
- data/ext/google/cloud/debugger/debugger_c/evaluator.c +115 -0
- data/ext/google/cloud/debugger/debugger_c/evaluator.h +25 -0
- data/ext/google/cloud/debugger/debugger_c/extconf.rb +22 -0
- data/ext/google/cloud/debugger/debugger_c/tracer.c +542 -0
- data/ext/google/cloud/debugger/debugger_c/tracer.h +25 -0
- data/lib/google-cloud-debugger.rb +181 -0
- data/lib/google/cloud/debugger.rb +259 -0
- data/lib/google/cloud/debugger/agent.rb +255 -0
- data/lib/google/cloud/debugger/backoff.rb +70 -0
- data/lib/google/cloud/debugger/breakpoint.rb +443 -0
- data/lib/google/cloud/debugger/breakpoint/evaluator.rb +1099 -0
- data/lib/google/cloud/debugger/breakpoint/source_location.rb +74 -0
- data/lib/google/cloud/debugger/breakpoint/stack_frame.rb +109 -0
- data/lib/google/cloud/debugger/breakpoint/status_message.rb +93 -0
- data/lib/google/cloud/debugger/breakpoint/validator.rb +92 -0
- data/lib/google/cloud/debugger/breakpoint/variable.rb +595 -0
- data/lib/google/cloud/debugger/breakpoint/variable_table.rb +96 -0
- data/lib/google/cloud/debugger/breakpoint_manager.rb +311 -0
- data/lib/google/cloud/debugger/credentials.rb +50 -0
- data/lib/google/cloud/debugger/debuggee.rb +222 -0
- data/lib/google/cloud/debugger/debuggee/app_uniquifier_generator.rb +76 -0
- data/lib/google/cloud/debugger/logpoint.rb +98 -0
- data/lib/google/cloud/debugger/middleware.rb +200 -0
- data/lib/google/cloud/debugger/project.rb +110 -0
- data/lib/google/cloud/debugger/rails.rb +174 -0
- data/lib/google/cloud/debugger/request_quota_manager.rb +95 -0
- data/lib/google/cloud/debugger/service.rb +88 -0
- data/lib/google/cloud/debugger/snappoint.rb +208 -0
- data/lib/google/cloud/debugger/tracer.rb +137 -0
- data/lib/google/cloud/debugger/transmitter.rb +199 -0
- data/lib/google/cloud/debugger/version.rb +22 -0
- metadata +353 -0
@@ -0,0 +1,96 @@
|
|
1
|
+
# Copyright 2017 Google LLC
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
require "forwardable"
|
17
|
+
|
18
|
+
module Google
|
19
|
+
module Cloud
|
20
|
+
module Debugger
|
21
|
+
class Breakpoint
|
22
|
+
##
|
23
|
+
# # VariableTable
|
24
|
+
#
|
25
|
+
# The variable_table exists to aid with computation, memory and network
|
26
|
+
# traffic optimization. It enables storing a variable once and reference
|
27
|
+
# it from multiple variables, including variables stored in the
|
28
|
+
# variable_table itself. For example, the same this object, which may
|
29
|
+
# appear at many levels of the stack, can have all of its data stored
|
30
|
+
# once in this table. The stack frame variables then would hold only a
|
31
|
+
# reference to it.
|
32
|
+
#
|
33
|
+
# The variable var_table_index field is an index into this repeated
|
34
|
+
# field. The stored objects are nameless and get their name from the
|
35
|
+
# referencing variable. The effective variable is a merge of the
|
36
|
+
# referencing variable and the referenced variable.
|
37
|
+
#
|
38
|
+
# See also {Breakpoint#variable_table}.
|
39
|
+
#
|
40
|
+
class VariableTable
|
41
|
+
extend Forwardable
|
42
|
+
|
43
|
+
##
|
44
|
+
# @private Array to store variables.
|
45
|
+
attr_accessor :variables
|
46
|
+
|
47
|
+
##
|
48
|
+
# @private Create a new VariableTable instance
|
49
|
+
def initialize
|
50
|
+
@variables = []
|
51
|
+
end
|
52
|
+
|
53
|
+
##
|
54
|
+
# @private Create a new VariableTable instance from a variable table
|
55
|
+
# gRPC struct
|
56
|
+
def self.from_grpc grpc_table
|
57
|
+
return if grpc_table.nil?
|
58
|
+
|
59
|
+
new.tap do |vt|
|
60
|
+
vt.variables = grpc_table.map do |grpc_var|
|
61
|
+
Breakpoint::Variable.from_grpc grpc_var
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# @private Search a variable in this VariableTable by matching
|
68
|
+
# object_id, return the array index if found.
|
69
|
+
def rb_var_index rb_var
|
70
|
+
variables.each_with_index do |var, i|
|
71
|
+
return i if var.source_var.object_id == rb_var.object_id
|
72
|
+
end
|
73
|
+
|
74
|
+
nil
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
# @private Add a Breakpoint::Variable to this VariableTable
|
79
|
+
def add var
|
80
|
+
return unless var.is_a? Breakpoint::Variable
|
81
|
+
|
82
|
+
variables << var
|
83
|
+
end
|
84
|
+
|
85
|
+
##
|
86
|
+
# @private Export this VariableTable as a gRPC struct
|
87
|
+
def to_grpc
|
88
|
+
variables.map(&:to_grpc).compact
|
89
|
+
end
|
90
|
+
|
91
|
+
def_instance_delegators :@variables, :size, :first, :[]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,311 @@
|
|
1
|
+
# Copyright 2017 Google LLC
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
require "google/cloud/debugger/snappoint"
|
17
|
+
require "google/cloud/debugger/logpoint"
|
18
|
+
|
19
|
+
module Google
|
20
|
+
module Cloud
|
21
|
+
module Debugger
|
22
|
+
##
|
23
|
+
# # BreakpointManager
|
24
|
+
#
|
25
|
+
# Responsible for querying Stackdriver Debugger service for any active
|
26
|
+
# breakpoints and keep an accurate local copies of the breakpoints.
|
27
|
+
#
|
28
|
+
# It correctly remembers which breakpoints are currently active and
|
29
|
+
# watched by the debugger agent, and which breakpoints are already
|
30
|
+
# completed. The BreakpointManager holds the record of truth for debugger
|
31
|
+
# breakpoints
|
32
|
+
#
|
33
|
+
class BreakpointManager
|
34
|
+
include MonitorMixin
|
35
|
+
|
36
|
+
##
|
37
|
+
# The debugger agent this tracer belongs to
|
38
|
+
# @return [Google::Cloud::Debugger::Agent]
|
39
|
+
attr_reader :agent
|
40
|
+
|
41
|
+
##
|
42
|
+
# @private The gRPC Service object.
|
43
|
+
attr_reader :service
|
44
|
+
|
45
|
+
##
|
46
|
+
# Application root directory, in absolute file path form.
|
47
|
+
# @return [String]
|
48
|
+
attr_reader :app_root
|
49
|
+
|
50
|
+
##
|
51
|
+
# Callback function invoked when new breakpoints are added or removed
|
52
|
+
# @return [Method]
|
53
|
+
attr_accessor :on_breakpoints_change
|
54
|
+
|
55
|
+
##
|
56
|
+
# @private The wait token from Stackdriver Debugger service used
|
57
|
+
# for breakpoints long polling
|
58
|
+
attr_reader :wait_token
|
59
|
+
|
60
|
+
##
|
61
|
+
# @private Construct new instance of BreakpointManager
|
62
|
+
def initialize agent, service
|
63
|
+
super()
|
64
|
+
|
65
|
+
@agent = agent
|
66
|
+
@service = service
|
67
|
+
|
68
|
+
@completed_breakpoints = []
|
69
|
+
@active_breakpoints = []
|
70
|
+
|
71
|
+
@wait_token = :init
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# Sync active breakpoints with Stackdriver Debugger service for a given
|
76
|
+
# debuggee application. Each request to the debugger service returns
|
77
|
+
# the full list of all active breakpoints. This method makes sure the
|
78
|
+
# local cache of active breakpoints is consistent with server
|
79
|
+
# breakpoints set.
|
80
|
+
#
|
81
|
+
# @param [String] debuggee_id Debuggee application ID
|
82
|
+
#
|
83
|
+
# @return [Boolean] True if synced successfully; otherwise false.
|
84
|
+
#
|
85
|
+
def sync_active_breakpoints debuggee_id
|
86
|
+
begin
|
87
|
+
response = service.list_active_breakpoints debuggee_id, @wait_token
|
88
|
+
rescue StandardError
|
89
|
+
return false
|
90
|
+
end
|
91
|
+
|
92
|
+
return true if response.wait_expired
|
93
|
+
|
94
|
+
@wait_token = response.next_wait_token
|
95
|
+
|
96
|
+
server_breakpoints =
|
97
|
+
convert_grpc_breakpoints response.breakpoints || []
|
98
|
+
|
99
|
+
update_breakpoints server_breakpoints
|
100
|
+
|
101
|
+
true
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# Update the local breakpoints cache with a list of server active
|
106
|
+
# breakpoints. New breakpoints will be added to local cache, and deleted
|
107
|
+
# breakpoints will be removed from local cache.
|
108
|
+
#
|
109
|
+
# It also correctly identifies evaluated active breakpoints from the
|
110
|
+
# server set of breakpoints, and does not re-add such evaluated
|
111
|
+
# breakpoints to the active list again.
|
112
|
+
#
|
113
|
+
# @param [Array<Google::Cloud::Debugger::Breakpoint>] server_breakpoints
|
114
|
+
# List of active breakpoints from Stackdriver Debugger service
|
115
|
+
#
|
116
|
+
def update_breakpoints server_breakpoints
|
117
|
+
synchronize do
|
118
|
+
new_breakpoints =
|
119
|
+
filter_breakpoints server_breakpoints - breakpoints
|
120
|
+
|
121
|
+
before_breakpoints_count = breakpoints.size
|
122
|
+
|
123
|
+
# Remember new active breakpoints from server
|
124
|
+
@active_breakpoints += new_breakpoints unless new_breakpoints.empty?
|
125
|
+
|
126
|
+
# Forget old breakpoints
|
127
|
+
@completed_breakpoints &= server_breakpoints
|
128
|
+
@active_breakpoints &= server_breakpoints
|
129
|
+
after_breakpoints_acount = breakpoints.size
|
130
|
+
|
131
|
+
breakpoints_updated =
|
132
|
+
!new_breakpoints.empty? ||
|
133
|
+
(before_breakpoints_count != after_breakpoints_acount)
|
134
|
+
|
135
|
+
on_breakpoints_change.call @active_breakpoints if
|
136
|
+
on_breakpoints_change.respond_to?(:call) && breakpoints_updated
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
##
|
141
|
+
# Evaluates a hit breakpoint, and submit the breakpoint to
|
142
|
+
# Transmitter if this breakpoint is evaluated successfully.
|
143
|
+
#
|
144
|
+
# See {Snappoint#evaluate} and {Logpoint#evaluate} for evaluation
|
145
|
+
# details.
|
146
|
+
#
|
147
|
+
# @param [Google::Cloud::Debugger::Breakpoint] breakpoint The breakpoint
|
148
|
+
# to be evaluated
|
149
|
+
# @param [Array<Binding>] call_stack_bindings An array of Ruby Binding
|
150
|
+
# objects, from the each frame of the call stack that leads to the
|
151
|
+
# triggering of the breakpoints.
|
152
|
+
#
|
153
|
+
def breakpoint_hit breakpoint, call_stack_bindings
|
154
|
+
breakpoint.evaluate call_stack_bindings
|
155
|
+
|
156
|
+
case breakpoint.action
|
157
|
+
when :CAPTURE
|
158
|
+
# Take this completed breakpoint off manager's active breakpoints
|
159
|
+
# list, submit the breakpoint snapshot, and update Tracer's
|
160
|
+
# breakpoints_cache.
|
161
|
+
|
162
|
+
return unless breakpoint.complete?
|
163
|
+
|
164
|
+
# Remove this breakpoint from active list
|
165
|
+
mark_off breakpoint
|
166
|
+
# Signal transmitter to submit this breakpoint
|
167
|
+
agent.transmitter.submit breakpoint
|
168
|
+
when :LOG
|
169
|
+
log_logpoint breakpoint
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
##
|
174
|
+
# Assume the given logpoint is successfully evaluated, log the
|
175
|
+
# evaluated log message via logger
|
176
|
+
#
|
177
|
+
# @param [Google::Cloud::Debugger::Breakpoint] logpoint The evaluated
|
178
|
+
# logpoint.
|
179
|
+
def log_logpoint logpoint
|
180
|
+
return unless agent.logger && logpoint.evaluated_log_message
|
181
|
+
|
182
|
+
message = "LOGPOINT: #{logpoint.evaluated_log_message}"
|
183
|
+
|
184
|
+
case logpoint.log_level
|
185
|
+
when :INFO
|
186
|
+
agent.logger.info message
|
187
|
+
when :WARNING
|
188
|
+
agent.logger.warn message
|
189
|
+
when :ERROR
|
190
|
+
agent.logger.error message
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
##
|
195
|
+
# Mark a given active breakpoint as completed. Meaning moving it from
|
196
|
+
# list of active breakpoints to completed breakpoints.
|
197
|
+
#
|
198
|
+
# @param [Google::Cloud::Debugger::Breakpoint] breakpoint The breakpoint
|
199
|
+
# to remove from local cache
|
200
|
+
#
|
201
|
+
# @return [Google::Cloud::Debugger::Breakpoint, NilClass] The same
|
202
|
+
# breakpoint if successfully marked off as completed. Nil if
|
203
|
+
# this breakpoint isn't found in the list of active breakpoints or
|
204
|
+
# failed to mark off as completed.
|
205
|
+
#
|
206
|
+
def mark_off breakpoint
|
207
|
+
synchronize do
|
208
|
+
breakpoint = @active_breakpoints.delete breakpoint
|
209
|
+
|
210
|
+
if breakpoint.nil?
|
211
|
+
nil
|
212
|
+
else
|
213
|
+
@completed_breakpoints << breakpoint
|
214
|
+
breakpoint
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
##
|
220
|
+
# Get a list of all breakpoints, both active and completed.
|
221
|
+
#
|
222
|
+
# @return [Array<Google::Cloud::Debugger::Breakpoint>] A list of all
|
223
|
+
# breakpoints.
|
224
|
+
def breakpoints
|
225
|
+
synchronize do
|
226
|
+
@active_breakpoints | @completed_breakpoints
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
##
|
231
|
+
# Get a list of all completed breakpoints.
|
232
|
+
#
|
233
|
+
# @return [Array<Google::Cloud::Debugger::Breakpoint>] A list of all
|
234
|
+
# completed breakpoints.
|
235
|
+
def completed_breakpoints
|
236
|
+
synchronize do
|
237
|
+
@completed_breakpoints
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
##
|
242
|
+
# Get a list of all active breakpoints.
|
243
|
+
#
|
244
|
+
# @return [Array<Google::Cloud::Debugger::Breakpoint>] A list of all
|
245
|
+
# active breakpoints.
|
246
|
+
def active_breakpoints
|
247
|
+
synchronize do
|
248
|
+
@active_breakpoints
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
##
|
253
|
+
# Check whether any active breakpoints haven't been completed yet.
|
254
|
+
#
|
255
|
+
# @return [Boolean] True if no more active breakpoints are left. False
|
256
|
+
# otherwise.
|
257
|
+
def all_complete?
|
258
|
+
synchronize do
|
259
|
+
@active_breakpoints.empty?
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
##
|
264
|
+
# Clear local breakpoints cache. Remove all active and completed
|
265
|
+
# breakpoints
|
266
|
+
def clear_breakpoints
|
267
|
+
synchronize do
|
268
|
+
@active_breakpoints.clear
|
269
|
+
@completed_breakpoints.clear
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
private
|
274
|
+
|
275
|
+
##
|
276
|
+
# @private Convert the list of grpc breakpoints from Debugger service to
|
277
|
+
# {Google::Cloud::Debugger::Breakpoint}.
|
278
|
+
def convert_grpc_breakpoints grpc_breakpoints
|
279
|
+
grpc_breakpoints.map do |grpc_b|
|
280
|
+
breakpoint = Breakpoint.from_grpc grpc_b
|
281
|
+
breakpoint.app_root = agent.app_root
|
282
|
+
breakpoint.init_var_table if breakpoint.is_a? Debugger::Snappoint
|
283
|
+
breakpoint
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
##
|
288
|
+
# @private Varify a list of given breakpoints. Filter out those
|
289
|
+
# aren't valid and submit them directly.
|
290
|
+
def filter_breakpoints breakpoints
|
291
|
+
valid_breakpoints = []
|
292
|
+
invalid_breakpoints = []
|
293
|
+
|
294
|
+
breakpoints.each do |breakpoint|
|
295
|
+
if breakpoint.valid?
|
296
|
+
valid_breakpoints << breakpoint
|
297
|
+
else
|
298
|
+
invalid_breakpoints << breakpoint
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
invalid_breakpoints.each do |breakpoint|
|
303
|
+
agent.transmitter.submit breakpoint if breakpoint.complete?
|
304
|
+
end
|
305
|
+
|
306
|
+
valid_breakpoints
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# Copyright 2017 Google LLC
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require "google/cloud/debugger/v2/debugger/credentials"
|
16
|
+
|
17
|
+
module Google
|
18
|
+
module Cloud
|
19
|
+
module Debugger
|
20
|
+
##
|
21
|
+
# # Credentials
|
22
|
+
#
|
23
|
+
# Represents the authentication and authorization used to connect to the
|
24
|
+
# Stackdriver Debugger service.
|
25
|
+
#
|
26
|
+
# @example
|
27
|
+
# require "google/cloud/debugger"
|
28
|
+
#
|
29
|
+
# keyfile = "/path/to/keyfile.json"
|
30
|
+
# creds = Google::Cloud::Debugger::Credentials.new keyfile
|
31
|
+
#
|
32
|
+
# debugger = Google::Cloud::Debugger.new(
|
33
|
+
# project_id: "my-project",
|
34
|
+
# credentials: creds
|
35
|
+
# )
|
36
|
+
#
|
37
|
+
# debugger.project_id #=> "my-project"
|
38
|
+
#
|
39
|
+
class Credentials < Google::Cloud::Debugger::V2::Debugger::Credentials
|
40
|
+
self.scope = [
|
41
|
+
"https://www.googleapis.com/auth/cloud-platform",
|
42
|
+
"https://www.googleapis.com/auth/cloud_debugger",
|
43
|
+
"https://www.googleapis.com/auth/logging.admin",
|
44
|
+
"https://www.googleapis.com/auth/logging.read",
|
45
|
+
"https://www.googleapis.com/auth/logging.write"
|
46
|
+
]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|