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