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,110 @@
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/errors"
17
+ require "google/cloud/debugger/agent"
18
+ require "google/cloud/debugger/credentials"
19
+ require "google/cloud/debugger/middleware"
20
+ require "google/cloud/debugger/service"
21
+
22
+ module Google
23
+ module Cloud
24
+ module Debugger
25
+ ##
26
+ # # Project
27
+ #
28
+ # Projects are top-level containers in Google Cloud Platform. They store
29
+ # information about billing and authorized users, and they control access
30
+ # to Stackdriver Debugger resources. Each project has a friendly name and
31
+ # a unique ID. Projects can be created only in the [Google Developers
32
+ # Console](https://console.developers.google.com).
33
+ #
34
+ # @example
35
+ # require "google/cloud/debugger"
36
+ #
37
+ # debugger = Google::Cloud::Debugger.new
38
+ # debugger.start
39
+ #
40
+ # See Google::Cloud#debugger
41
+ class Project
42
+ ##
43
+ # @private The gRPC Service object.
44
+ attr_accessor :service
45
+
46
+ ##
47
+ # The Stackdriver Debugger Agent object.
48
+ attr_reader :agent
49
+
50
+ ##
51
+ # @private Creates a new Project instance.
52
+ def initialize service, service_name:, service_version:
53
+ @service = service
54
+ @agent = Agent.new service, service_name: service_name,
55
+ service_version: service_version
56
+ end
57
+
58
+ ##
59
+ # The ID of the current project.
60
+ #
61
+ # @return [String] the Google Cloud project ID
62
+ #
63
+ # @example
64
+ # require "google/cloud/debugger"
65
+ #
66
+ # debugger = Google::Cloud::Debugger.new(
67
+ # project_id: "my-project",
68
+ # credentials: "/path/to/keyfile.json"
69
+ # )
70
+ #
71
+ # debugger.project_id #=> "my-project"
72
+ #
73
+ def project_id
74
+ service.project
75
+ end
76
+ alias project project_id
77
+
78
+ ##
79
+ # Start the Stackdriver Debugger Agent.
80
+ #
81
+ # @example
82
+ # require "google/cloud/debugger"
83
+ #
84
+ # debugger = Google::Cloud::Debugger.new
85
+ # debugger.start
86
+ #
87
+ # See {Agent#start} for more details.
88
+ def start
89
+ agent.start
90
+ end
91
+ alias attach start
92
+
93
+ ##
94
+ # Stop the Stackdriver Debugger Agent.
95
+ #
96
+ # @example
97
+ # require "google/cloud/debugger"
98
+ #
99
+ # debugger = Google::Cloud::Debugger.new
100
+ # debugger.start
101
+ # debugger.stop
102
+ #
103
+ # See {Agent#stop} for more details.
104
+ def stop
105
+ agent.stop
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,174 @@
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"
17
+
18
+ module Google
19
+ module Cloud
20
+ module Debugger
21
+ ##
22
+ # # Railtie
23
+ #
24
+ # Google::Cloud::Debugger::Railtie automatically adds the
25
+ # Google::Cloud::Debugger::Middleware to Rack in a Rails environment.
26
+ #
27
+ # The Middleware is only added when the
28
+ # `Google::Cloud.configure.use_debugger` setting is true or Rails is
29
+ # in the production environment.
30
+ #
31
+ # When loaded, the Google::Cloud::Debugger::Middleware will be inserted
32
+ # after the Rack::ETag Middleware, which is top of the Rack stack, closest
33
+ # to the application code.
34
+ #
35
+ # The Railtie should also initialize a debugger to be used by the
36
+ # Middleware. See the [Configuration
37
+ # Guide](https://googleapis.dev/ruby/stackdriver/latest/file.INSTRUMENTATION_CONFIGURATION.html)
38
+ # on how to configure the Railtie and Middleware.
39
+ #
40
+ class Railtie < ::Rails::Railtie
41
+ ##
42
+ # Inform the Railtie that it is safe to start debugger agents.
43
+ # This simply calls {Google::Cloud::Debugger::Middleware.start_agents}.
44
+ # See its documentation for more information.
45
+ #
46
+ def self.start_agents
47
+ Google::Cloud::Debugger::Middleware.start_agents
48
+ end
49
+
50
+ config.google_cloud = ::ActiveSupport::OrderedOptions.new unless
51
+ config.respond_to? :google_cloud
52
+ config.google_cloud[:debugger] = ::ActiveSupport::OrderedOptions.new
53
+ config.google_cloud.define_singleton_method :debugger do
54
+ self[:debugger]
55
+ end
56
+
57
+ initializer "Stackdriver.Debugger" do |app|
58
+ self.class.consolidate_rails_config app.config
59
+
60
+ self.class.init_middleware app if Cloud.configure.use_debugger
61
+ end
62
+
63
+ ##
64
+ # @private Init Debugger integration for Rails. Setup configuration and
65
+ # insert the Middleware.
66
+ def self.init_middleware app
67
+ app.middleware.insert_after Rack::ETag,
68
+ Google::Cloud::Debugger::Middleware
69
+ end
70
+
71
+ ##
72
+ # @private Consolidate Rails configuration into Debugger instrumentation
73
+ # configuration. Also consolidate the `use_debugger` setting by
74
+ # verifying credentials and Rails environment. The `use_debugger`
75
+ # setting will be true if credentials are valid, and the setting is
76
+ # manually set to true or Rails is in the production environment.
77
+ #
78
+ # @param [Rails::Railtie::Configuration] config The
79
+ # Rails.application.config
80
+ #
81
+ def self.consolidate_rails_config config
82
+ merge_rails_config config
83
+
84
+ init_default_config
85
+
86
+ # Done if Google::Cloud.configure.use_debugger is explicitly
87
+ # false
88
+ return if Google::Cloud.configure.use_debugger == false
89
+
90
+ # Verify credentials and set use_debugger to false if
91
+ # credentials are invalid
92
+ unless valid_credentials? Debugger.configure.project_id,
93
+ Debugger.configure.credentials
94
+ Cloud.configure.use_debugger = false
95
+ return
96
+ end
97
+
98
+ # Otherwise set use_debugger to true if Rails is running in
99
+ # the production environment
100
+ Google::Cloud.configure.use_debugger ||= ::Rails.env.production?
101
+ end
102
+
103
+ # rubocop:disable all
104
+
105
+ ##
106
+ # @private Merge Rails configuration into Debugger instrumentation
107
+ # configuration.
108
+ def self.merge_rails_config rails_config
109
+ gcp_config = rails_config.google_cloud
110
+ dbg_config = gcp_config.debugger
111
+
112
+ if Cloud.configure.use_debugger.nil?
113
+ Cloud.configure.use_debugger = gcp_config.use_debugger
114
+ end
115
+ Debugger.configure do |config|
116
+ config.project_id ||= begin
117
+ config.project || dbg_config.project_id || dbg_config.project
118
+ gcp_config.project_id || gcp_config.project
119
+ end
120
+ config.credentials ||= begin
121
+ config.keyfile || dbg_config.credentials || dbg_config.keyfile
122
+ gcp_config.credentials || gcp_config.keyfile
123
+ end
124
+ config.service_name ||= \
125
+ (dbg_config.service_name || gcp_config.service_name)
126
+ config.service_version ||= \
127
+ (dbg_config.service_version || gcp_config.service_version)
128
+ end
129
+ end
130
+
131
+ # rubocop:enable all
132
+
133
+ ##
134
+ # Fallback to default config values if config parameters not provided.
135
+ def self.init_default_config
136
+ config = Debugger.configure
137
+ config.project_id ||= Debugger.default_project_id
138
+ config.service_name ||= Debugger.default_service_name
139
+ config.service_version ||= Debugger.default_service_version
140
+ end
141
+
142
+ ##
143
+ # @private Verify credentials
144
+ def self.valid_credentials? project_id, credentials
145
+ begin
146
+ # if credentials is nil, get default
147
+ credentials ||= Debugger::Credentials.default
148
+ # only create a new Credentials object if the val isn't one already
149
+ unless credentials.is_a? Google::Auth::Credentials
150
+ # if credentials is not a Credentials object, create one
151
+ Debugger::Credentials.new credentials
152
+ end
153
+ rescue StandardError => e
154
+ STDOUT.puts "Note: Google::Cloud::Debugger is disabled because " \
155
+ "it failed to authorize with the service. (#{e.message})"
156
+ return false
157
+ end
158
+
159
+ if project_id.to_s.empty?
160
+ STDOUT.puts "Note: Google::Cloud::Debugger is disabled because " \
161
+ "the project ID could not be determined."
162
+ return false
163
+ end
164
+
165
+ true
166
+ end
167
+
168
+ private_class_method :merge_rails_config,
169
+ :init_default_config,
170
+ :valid_credentials?
171
+ end
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,95 @@
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
+ module Google
17
+ module Cloud
18
+ module Debugger
19
+ ##
20
+ # # RequestQuotaManager
21
+ #
22
+ # Tracking object used by debugger agent to manage quota in
23
+ # request-based applications. This class tracks the amount of time
24
+ # and number of breakpoints to evaluation in a single session.
25
+ #
26
+ # The debugger agent doesn't have use a quota manager by default, which
27
+ # means it will evaluate all breakpoints encountered and takes as much
28
+ # time as needed. This class is utilized by
29
+ # {Google::Cloud::Debugger::Middleware} class to limit latency overhead
30
+ # when used in Rack-based applications.
31
+ #
32
+ class RequestQuotaManager
33
+ # Default Total time allowed to consume, in seconds
34
+ DEFAULT_TIME_QUOTA = 0.05
35
+
36
+ # Default max number of breakpoints to evaluate
37
+ DEFAULT_COUNT_QUOTA = 10
38
+
39
+ ##
40
+ # The time quota for this manager
41
+ attr_accessor :time_quota
42
+
43
+ ##
44
+ # The count quota for this manager
45
+ attr_accessor :count_quota
46
+
47
+ ##
48
+ # The time quota used
49
+ attr_accessor :time_used
50
+
51
+ ##
52
+ # The count quota used
53
+ attr_accessor :count_used
54
+
55
+ ##
56
+ # Construct a new RequestQuotaManager instance
57
+ #
58
+ # @param [Float] time_quota The max quota for time consumed.
59
+ # @param [Integer] count_quota The max quota for count usage.
60
+ def initialize time_quota: DEFAULT_TIME_QUOTA,
61
+ count_quota: DEFAULT_COUNT_QUOTA
62
+ @time_quota = time_quota
63
+ @time_used = 0
64
+ @count_quota = count_quota
65
+ @count_used = 0
66
+ end
67
+
68
+ ##
69
+ # Check if there's more quota left.
70
+ #
71
+ # @return [Boolean] True if there's more quota; false otherwise.
72
+ def more?
73
+ (time_used < time_quota) && (count_used < count_quota)
74
+ end
75
+
76
+ ##
77
+ # Reset all the quota usage.
78
+ def reset
79
+ @time_used = 0
80
+ @count_used = 0
81
+ end
82
+
83
+ ##
84
+ # Notify the quota manager some resource has been consumed. Each time
85
+ # called increases the count quota usage.
86
+ #
87
+ # @param [Float] time Amount of time to deduct from the time quota.
88
+ def consume time: 0
89
+ @time_used += time
90
+ @count_used += 1
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,88 @@
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/errors"
17
+ require "google/cloud/debugger/version"
18
+ require "google/cloud/debugger/v2"
19
+ require "uri"
20
+
21
+ module Google
22
+ module Cloud
23
+ module Debugger
24
+ ##
25
+ # @private Represents the gRPC Debugger service, including all the API
26
+ # methods.
27
+ class Service
28
+ attr_accessor :project, :credentials, :timeout, :host
29
+
30
+ ##
31
+ # Creates a new Service instance.
32
+ def initialize project, credentials, timeout: nil, host: nil
33
+ @project = project
34
+ @credentials = credentials
35
+ @timeout = timeout
36
+ @host = host
37
+ end
38
+
39
+ def cloud_debugger
40
+ return mocked_debugger if mocked_debugger
41
+ @cloud_debugger ||=
42
+ V2::Controller::Client.new do |config|
43
+ config.credentials = credentials if credentials
44
+ config.timeout = timeout if timeout
45
+ config.endpoint = host if host
46
+ config.lib_name = "gccl"
47
+ config.lib_version = Google::Cloud::Debugger::VERSION
48
+ config.metadata = { "google-cloud-resource-prefix" => "projects/#{@project}" }
49
+ end
50
+ end
51
+ attr_accessor :mocked_debugger
52
+
53
+ def transmitter
54
+ return mocked_transmitter if mocked_transmitter
55
+ @transmitter ||=
56
+ V2::Controller::Client.new do |config|
57
+ config.credentials = credentials if credentials
58
+ config.timeout = timeout if timeout
59
+ config.endpoint = host if host
60
+ config.lib_name = "gccl"
61
+ config.lib_version = Google::Cloud::Debugger::VERSION
62
+ config.metadata = { "google-cloud-resource-prefix" => "projects/#{@project}" }
63
+ end
64
+ end
65
+ attr_accessor :mocked_transmitter
66
+
67
+ def register_debuggee debuggee_grpc
68
+ cloud_debugger.register_debuggee debuggee: debuggee_grpc
69
+ end
70
+
71
+ def list_active_breakpoints debuggee_id, wait_token
72
+ cloud_debugger.list_active_breakpoints debuggee_id: debuggee_id.to_s,
73
+ wait_token: wait_token.to_s,
74
+ success_on_timeout: true
75
+ end
76
+
77
+ def update_active_breakpoint debuggee_id, breakpoint
78
+ transmitter.update_active_breakpoint debuggee_id: debuggee_id.to_s,
79
+ breakpoint: breakpoint.to_grpc
80
+ end
81
+
82
+ def inspect
83
+ "#{self.class}(#{@project})"
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end