google-cloud-debugger 0.24.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +8 -0
  3. data/LICENSE +201 -0
  4. data/README.md +56 -0
  5. data/ext/google/cloud/debugger/debugger_c/debugger.c +31 -0
  6. data/ext/google/cloud/debugger/debugger_c/debugger.h +26 -0
  7. data/ext/google/cloud/debugger/debugger_c/evaluator.c +78 -0
  8. data/ext/google/cloud/debugger/debugger_c/evaluator.h +25 -0
  9. data/ext/google/cloud/debugger/debugger_c/extconf.rb +22 -0
  10. data/ext/google/cloud/debugger/debugger_c/tracer.c +478 -0
  11. data/ext/google/cloud/debugger/debugger_c/tracer.h +31 -0
  12. data/lib/google-cloud-debugger.rb +121 -0
  13. data/lib/google/cloud/debugger.rb +379 -0
  14. data/lib/google/cloud/debugger/agent.rb +204 -0
  15. data/lib/google/cloud/debugger/async_actor.rb +290 -0
  16. data/lib/google/cloud/debugger/breakpoint.rb +382 -0
  17. data/lib/google/cloud/debugger/breakpoint/evaluator.rb +1113 -0
  18. data/lib/google/cloud/debugger/breakpoint/source_location.rb +75 -0
  19. data/lib/google/cloud/debugger/breakpoint/stack_frame.rb +109 -0
  20. data/lib/google/cloud/debugger/breakpoint/variable.rb +304 -0
  21. data/lib/google/cloud/debugger/breakpoint_manager.rb +217 -0
  22. data/lib/google/cloud/debugger/credentials.rb +41 -0
  23. data/lib/google/cloud/debugger/debuggee.rb +204 -0
  24. data/lib/google/cloud/debugger/debuggee/app_uniquifier_generator.rb +78 -0
  25. data/lib/google/cloud/debugger/middleware.rb +77 -0
  26. data/lib/google/cloud/debugger/project.rb +135 -0
  27. data/lib/google/cloud/debugger/rails.rb +141 -0
  28. data/lib/google/cloud/debugger/service.rb +130 -0
  29. data/lib/google/cloud/debugger/tracer.rb +165 -0
  30. data/lib/google/cloud/debugger/transmitter.rb +129 -0
  31. data/lib/google/cloud/debugger/v2.rb +15 -0
  32. data/lib/google/cloud/debugger/v2/controller2_client.rb +299 -0
  33. data/lib/google/cloud/debugger/v2/controller2_client_config.json +43 -0
  34. data/lib/google/cloud/debugger/v2/debugger2_client.rb +378 -0
  35. data/lib/google/cloud/debugger/v2/debugger2_client_config.json +53 -0
  36. data/lib/google/cloud/debugger/v2/doc/google/devtools/clouddebugger/v2/data.rb +441 -0
  37. data/lib/google/cloud/debugger/v2/doc/google/devtools/clouddebugger/v2/debugger.rb +151 -0
  38. data/lib/google/cloud/debugger/v2/doc/google/devtools/source/v1/source_context.rb +161 -0
  39. data/lib/google/cloud/debugger/v2/doc/google/protobuf/timestamp.rb +81 -0
  40. data/lib/google/cloud/debugger/version.rb +22 -0
  41. data/lib/google/devtools/clouddebugger/v2/controller_pb.rb +47 -0
  42. data/lib/google/devtools/clouddebugger/v2/controller_services_pb.rb +97 -0
  43. data/lib/google/devtools/clouddebugger/v2/data_pb.rb +105 -0
  44. data/lib/google/devtools/clouddebugger/v2/debugger_pb.rb +74 -0
  45. data/lib/google/devtools/clouddebugger/v2/debugger_services_pb.rb +64 -0
  46. data/lib/google/devtools/source/v1/source_context_pb.rb +89 -0
  47. metadata +300 -0
@@ -0,0 +1,217 @@
1
+ # Copyright 2017 Google Inc. All rights reserved.
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
+ # http://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/breakpoint"
17
+
18
+ module Google
19
+ module Cloud
20
+ module Debugger
21
+ ##
22
+ # # BreakpointManager
23
+ #
24
+ # Responsible for querying Stackdriver Debugger service for any active
25
+ # breakpoints and keep an accurate local copies of the breakpoints.
26
+ #
27
+ # It correctly remembers which breakpoints are currently active and
28
+ # watched by the debugger agent, and which breakpoints are already
29
+ # completed. The BreakpointManager holds the record of truth for debugger
30
+ # breakpoints
31
+ #
32
+ class BreakpointManager
33
+ include MonitorMixin
34
+
35
+ ##
36
+ # @private The gRPC Service object.
37
+ attr_reader :service
38
+
39
+ ##
40
+ # Application root directory, in absolute file path form.
41
+ # @return [String]
42
+ attr_reader :app_root
43
+
44
+ ##
45
+ # Callback function invoked when new breakpoints are added or removed
46
+ # @return [Method]
47
+ attr_accessor :on_breakpoints_change
48
+
49
+ ##
50
+ # @private The wait token from Stackdriver Debugger service used
51
+ # for breakpoints long polling
52
+ attr_reader :wait_token
53
+
54
+ ##
55
+ # @private Construct new instance of BreakpointManager
56
+ def initialize service
57
+ super()
58
+
59
+ @service = service
60
+
61
+ @completed_breakpoints = []
62
+ @active_breakpoints = []
63
+
64
+ @wait_token = :init
65
+ end
66
+
67
+ ##
68
+ # Sync active breakpoints with Stackdriver Debugger service for a given
69
+ # debuggee application. Each request to the debugger service returns
70
+ # the full list of all active breakpoints. This method makes sure the
71
+ # local cache of active breakpoints is consistent with server
72
+ # breakpoints set.
73
+ #
74
+ # @param [String] debuggee_id Debuggee application ID
75
+ #
76
+ # @return [Boolean] True if synced successfully; otherwise false.
77
+ #
78
+ def sync_active_breakpoints debuggee_id
79
+ begin
80
+ response = service.list_active_breakpoints debuggee_id, @wait_token
81
+ rescue
82
+ return false
83
+ end
84
+
85
+ return true if response.wait_expired
86
+
87
+ @wait_token = response.next_wait_token
88
+
89
+ server_breakpoints = response.breakpoints || []
90
+ server_breakpoints = server_breakpoints.map do |grpc_b|
91
+ Breakpoint.from_grpc grpc_b
92
+ end
93
+
94
+ update_breakpoints server_breakpoints
95
+
96
+ true
97
+ end
98
+
99
+ ##
100
+ # Update the local breakpoints cache with a list of server active
101
+ # breakpoints. New breakpoints will be added to local cache, and deleted
102
+ # breakpoints will be removed from local cache.
103
+ #
104
+ # It also correctly identifies evaluated active breakpoints from the
105
+ # server set of breakpoints, and does not re-add such evaluated
106
+ # breakpoints to the active list again.
107
+ #
108
+ # @param [Array<Google::Cloud::Debugger::Breakpoint>] server_breakpoints
109
+ # List of active breakpoints from Stackdriver Debugger service
110
+ #
111
+ def update_breakpoints server_breakpoints
112
+ synchronize do
113
+ new_breakpoints =
114
+ server_breakpoints - @active_breakpoints - @completed_breakpoints
115
+ before_breakpoints_count =
116
+ @active_breakpoints.size + @completed_breakpoints.size
117
+
118
+ # Remember new active breakpoints from server
119
+ @active_breakpoints += new_breakpoints unless new_breakpoints.empty?
120
+
121
+ # Forget old breakpoints
122
+ @completed_breakpoints &= server_breakpoints
123
+ @active_breakpoints &= server_breakpoints
124
+ after_breakpoints_acount =
125
+ @active_breakpoints.size + @completed_breakpoints.size
126
+
127
+ breakpoints_updated =
128
+ !new_breakpoints.empty? ||
129
+ (before_breakpoints_count != after_breakpoints_acount)
130
+
131
+ on_breakpoints_change.call(@active_breakpoints) if
132
+ on_breakpoints_change.respond_to?(:call) && breakpoints_updated
133
+ end
134
+ end
135
+
136
+ ##
137
+ # Mark a given active breakpoint as completed. Meaning moving it from
138
+ # list of active breakpoints to completed breakpoints.
139
+ #
140
+ # @param [Google::Cloud::Debugger::Breakpoint] breakpoint The breakpoint
141
+ # to remove from local cache
142
+ #
143
+ # @return [Google::Cloud::Debugger::Breakpoint, NilClass] The same
144
+ # breakpoint if successfully marked off as completed. Nil if
145
+ # this breakpoint isn't found in the list of active breakpoints or
146
+ # failed to mark off as completed.
147
+ #
148
+ def mark_off breakpoint
149
+ synchronize do
150
+ breakpoint = @active_breakpoints.delete breakpoint
151
+
152
+ if breakpoint.nil?
153
+ nil
154
+ else
155
+ @completed_breakpoints << breakpoint
156
+ breakpoint
157
+ end
158
+ end
159
+ end
160
+
161
+ ##
162
+ # Get a list of all breakpoints, both active and completed.
163
+ #
164
+ # @return [Array<Google::Cloud::Debugger::Breakpoint>] A list of all
165
+ # breakpoints.
166
+ def breakpoints
167
+ synchronize do
168
+ @active_breakpoints | @completed_breakpoints
169
+ end
170
+ end
171
+
172
+ ##
173
+ # Get a list of all completed breakpoints.
174
+ #
175
+ # @return [Array<Google::Cloud::Debugger::Breakpoint>] A list of all
176
+ # completed breakpoints.
177
+ def completed_breakpoints
178
+ synchronize do
179
+ @completed_breakpoints
180
+ end
181
+ end
182
+
183
+ ##
184
+ # Get a list of all active breakpoints.
185
+ #
186
+ # @return [Array<Google::Cloud::Debugger::Breakpoint>] A list of all
187
+ # active breakpoints.
188
+ def active_breakpoints
189
+ synchronize do
190
+ @active_breakpoints
191
+ end
192
+ end
193
+
194
+ ##
195
+ # Check whether any active breakpoints haven't been completed yet.
196
+ #
197
+ # @return [Boolean] True if no more active breakpoints are left. False
198
+ # otherwise.
199
+ def all_complete?
200
+ synchronize do
201
+ @active_breakpoints.empty?
202
+ end
203
+ end
204
+
205
+ ##
206
+ # Clear local breakpoints cache. Remove all active and completed
207
+ # breakpoints
208
+ def clear_breakpoints
209
+ synchronize do
210
+ @active_breakpoints.clear
211
+ @completed_breakpoints.clear
212
+ end
213
+ end
214
+ end
215
+ end
216
+ end
217
+ end
@@ -0,0 +1,41 @@
1
+ # Copyright 2017 Google Inc. All rights reserved.
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
+ # http://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/credentials"
17
+
18
+ module Google
19
+ module Cloud
20
+ module Debugger
21
+ ##
22
+ # @private Represents the OAuth 2.0 signing logic for Debugger.
23
+ class Credentials < Google::Cloud::Credentials
24
+ SCOPE = ["https://www.googleapis.com/auth/cloud_debugger"]
25
+ PATH_ENV_VARS = %w(DEBUGGER_KEYFILE GOOGLE_CLOUD_KEYFILE GCLOUD_KEYFILE)
26
+ JSON_ENV_VARS = %w(DEBUGGER_KEYFILE_JSON GOOGLE_CLOUD_KEYFILE_JSON
27
+ GCLOUD_KEYFILE_JSON)
28
+
29
+ ##
30
+ # @private Create credentials with given scope and/or keyfile
31
+ def self.credentials_with_scope keyfile, scope = nil
32
+ if keyfile.nil?
33
+ default(scope: scope)
34
+ else
35
+ new(keyfile, scope: scope)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,204 @@
1
+ # Copyright 2017 Google Inc. All rights reserved.
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
+ # http://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 "digest/sha1"
17
+ require "google/cloud/debugger/debuggee/app_uniquifier_generator"
18
+ require "google/cloud/debugger/version"
19
+ require "json"
20
+
21
+ module Google
22
+ module Cloud
23
+ module Debugger
24
+ ##
25
+ # # Debuggee
26
+ #
27
+ # Represent a debuggee application. Contains information that identifies
28
+ # debuggee applications from each other. Maps to gRPC struct
29
+ # {Google::Devtools::Clouddebugger::V2::Debuggee}.
30
+ #
31
+ # It also automatically loads source context information generated from
32
+ # Cloud SDK. See [Stackdriver Debugger
33
+ # doc](https://cloud.google.com/debugger/docs/source-context#app_engine_standard_python)
34
+ # for more information on how to generate this source context information
35
+ # when used on Google Container Engine and Google Compute engine. This
36
+ # step is taken care of if debuggee application is hosted on Google App
37
+ # Engine Flexibile.
38
+ #
39
+ # To ensure the multiple instances of the application are indeed the same
40
+ # application, the debuggee also compute a "uniquifier" generated from
41
+ # source context or application source code.
42
+ #
43
+ class Debuggee
44
+ ##
45
+ # @private The gRPC Service object.
46
+ attr_reader :service
47
+
48
+ ##
49
+ # Name for the debuggee application
50
+ # @return [String]
51
+ attr_reader :module_name
52
+
53
+ ##
54
+ # Version identifier for the debuggee application
55
+ # @return [String]
56
+ attr_reader :module_version
57
+
58
+ ##
59
+ # Registered Debuggee ID. Set by Stackdriver Debugger service when
60
+ # a debuggee application is sucessfully registered.
61
+ # @return [String]
62
+ attr_reader :id
63
+
64
+ ##
65
+ # @private Construct a new instance of Debuggee
66
+ def initialize service, module_name:, module_version:
67
+ @service = service
68
+ @module_name = module_name
69
+ @module_version = module_version
70
+ @computed_uniquifier = nil
71
+ @id = nil
72
+ end
73
+
74
+ ##
75
+ # Register the current application as a debuggee with Stackdriver
76
+ # Debuggee service.
77
+ # @return [Boolean] True if registered sucessfully; otherwise false.
78
+ def register
79
+ begin
80
+ response = service.register_debuggee to_grpc
81
+ @id = response.debuggee.id
82
+ rescue
83
+ revoke_registration
84
+ end
85
+ registered?
86
+ end
87
+
88
+ ##
89
+ # Check whether this debuggee is currently registered or not
90
+ # @return [Boolean] True if debuggee is registered; otherwise false.
91
+ def registered?
92
+ !id.nil?
93
+ end
94
+
95
+ ##
96
+ # Revoke the registration of this debuggee
97
+ def revoke_registration
98
+ @id = nil
99
+ end
100
+
101
+ ##
102
+ # Convert this debuggee into a gRPC
103
+ # Google::Devtools::Clouddebugger::V2::Debuggee struct.
104
+ def to_grpc
105
+ debuggee_args = build_request_arg
106
+
107
+ Google::Devtools::Clouddebugger::V2::Debuggee.decode_json \
108
+ debuggee_args.to_json
109
+ end
110
+
111
+ private
112
+
113
+ ##
114
+ # @private Build the parameters for this debuggee
115
+ def build_request_arg
116
+ debuggee_args = {
117
+ project: project_id,
118
+ description: description,
119
+ labels: labels,
120
+ agent_version: agent_version
121
+ }
122
+
123
+ debuggee_args[:id] = id if id
124
+
125
+ source_context = read_app_json_file "source-context.json"
126
+ debuggee_args[:source_contexts] = [source_context] if source_context
127
+
128
+ source_contexts = read_app_json_file "source-contexts.json"
129
+ if source_contexts
130
+ debuggee_args[:ext_source_contexts] = source_contexts
131
+ elsif source_context
132
+ debuggee_args[:ext_source_contexts] = [{ context: source_context }]
133
+ end
134
+
135
+ debuggee_args[:uniquifier] = compute_uniquifier debuggee_args
136
+
137
+ debuggee_args
138
+ end
139
+
140
+ ##
141
+ # @private Build labels hash for this debuggee
142
+ def labels
143
+ {
144
+ "projectid" => String(project_id),
145
+ "module" => String(module_name),
146
+ "version" => String(module_version)
147
+ }
148
+ end
149
+
150
+ ##
151
+ # @private Build description string for this debuggee. In
152
+ # "<module name> - <module version>" format. Or just the module
153
+ # version if module name is missing.
154
+ #
155
+ # @return [String] A compact debuggee description.
156
+ #
157
+ def description
158
+ if module_version.nil? || module_version.empty?
159
+ module_name
160
+ else
161
+ "#{module_name} - #{module_version}"
162
+ end
163
+ end
164
+
165
+ ##
166
+ # @private Get debuggee project id
167
+ def project_id
168
+ service.project
169
+ end
170
+
171
+ ##
172
+ # @private Build debuggee agent version identifier
173
+ def agent_version
174
+ "google.com/ruby#{RUBY_VERSION}-#{Google::Cloud::Debugger::VERSION}"
175
+ end
176
+
177
+ ##
178
+ # @private Generate a debuggee uniquifier from source context
179
+ # information or application source code
180
+ def compute_uniquifier debuggee_args
181
+ return @computed_uniquifier if @computed_uniquifier
182
+
183
+ sha = Digest::SHA1.new
184
+ sha << debuggee_args.to_s
185
+
186
+ unless debuggee_args.key?(:source_contexts) ||
187
+ debuggee_args.key?(:ext_source_contexts)
188
+ AppUniquifierGenerator.generate_app_uniquifier sha
189
+ end
190
+
191
+ @computed_uniquifier = sha.hexdigest
192
+ end
193
+
194
+ ##
195
+ # @private Helper method to parse json file
196
+ def read_app_json_file file_path
197
+ JSON.parse File.read(file_path), symbolize_names: true
198
+ rescue
199
+ nil
200
+ end
201
+ end
202
+ end
203
+ end
204
+ end