google-cloud-debugger 0.40.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +18 -0
  3. data/AUTHENTICATION.md +178 -0
  4. data/CHANGELOG.md +233 -0
  5. data/CODE_OF_CONDUCT.md +40 -0
  6. data/CONTRIBUTING.md +188 -0
  7. data/INSTRUMENTATION.md +115 -0
  8. data/LICENSE +201 -0
  9. data/LOGGING.md +32 -0
  10. data/OVERVIEW.md +266 -0
  11. data/TROUBLESHOOTING.md +31 -0
  12. data/ext/google/cloud/debugger/debugger_c/debugger.c +31 -0
  13. data/ext/google/cloud/debugger/debugger_c/debugger.h +26 -0
  14. data/ext/google/cloud/debugger/debugger_c/evaluator.c +115 -0
  15. data/ext/google/cloud/debugger/debugger_c/evaluator.h +25 -0
  16. data/ext/google/cloud/debugger/debugger_c/extconf.rb +22 -0
  17. data/ext/google/cloud/debugger/debugger_c/tracer.c +542 -0
  18. data/ext/google/cloud/debugger/debugger_c/tracer.h +25 -0
  19. data/lib/google-cloud-debugger.rb +181 -0
  20. data/lib/google/cloud/debugger.rb +259 -0
  21. data/lib/google/cloud/debugger/agent.rb +255 -0
  22. data/lib/google/cloud/debugger/backoff.rb +70 -0
  23. data/lib/google/cloud/debugger/breakpoint.rb +443 -0
  24. data/lib/google/cloud/debugger/breakpoint/evaluator.rb +1099 -0
  25. data/lib/google/cloud/debugger/breakpoint/source_location.rb +74 -0
  26. data/lib/google/cloud/debugger/breakpoint/stack_frame.rb +109 -0
  27. data/lib/google/cloud/debugger/breakpoint/status_message.rb +93 -0
  28. data/lib/google/cloud/debugger/breakpoint/validator.rb +92 -0
  29. data/lib/google/cloud/debugger/breakpoint/variable.rb +595 -0
  30. data/lib/google/cloud/debugger/breakpoint/variable_table.rb +96 -0
  31. data/lib/google/cloud/debugger/breakpoint_manager.rb +311 -0
  32. data/lib/google/cloud/debugger/credentials.rb +50 -0
  33. data/lib/google/cloud/debugger/debuggee.rb +222 -0
  34. data/lib/google/cloud/debugger/debuggee/app_uniquifier_generator.rb +76 -0
  35. data/lib/google/cloud/debugger/logpoint.rb +98 -0
  36. data/lib/google/cloud/debugger/middleware.rb +200 -0
  37. data/lib/google/cloud/debugger/project.rb +110 -0
  38. data/lib/google/cloud/debugger/rails.rb +174 -0
  39. data/lib/google/cloud/debugger/request_quota_manager.rb +95 -0
  40. data/lib/google/cloud/debugger/service.rb +88 -0
  41. data/lib/google/cloud/debugger/snappoint.rb +208 -0
  42. data/lib/google/cloud/debugger/tracer.rb +137 -0
  43. data/lib/google/cloud/debugger/transmitter.rb +199 -0
  44. data/lib/google/cloud/debugger/version.rb +22 -0
  45. 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