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.
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