google-cloud-debugger 0.32.6 → 0.33.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dfc1df72a8c1dac4cc22461e3585b5b0f15dd2548897eedf015e161d76356eb7
4
- data.tar.gz: 4c39329e42f2c950ce17c19b68fe1910fe854e39b9460e97b06a20be075a23f2
3
+ metadata.gz: 00c6b1ccddbe80cd2b51abc2a65379ae322fc7be4a8e9cfceea63a9a512872c2
4
+ data.tar.gz: 4a04fae51a1926559250ae1a59c3f799d947a475d528ebdce174d31f6d37a62f
5
5
  SHA512:
6
- metadata.gz: f240803624c03f699e641992685374927788dbc581c462b5cbf632ab31e7baf5a4581acb0acdd2e5311967f1ff47f8224999ef48e7bf89f23a12085b846b1634
7
- data.tar.gz: d98a99abd03266bdbb4fad60cb41ff488f3635167d42a87cd8dd694ca7342e56436bc54848cc01b3e9e62ea2a61a38b736afe0268938733ada789b8ed002e7c4
6
+ metadata.gz: '05281486dd7ffeae6f63eaeaffb7b022c4493eef166bc36de1afa44e9e75402eddd2dcf3ebeca385898ba5745cf434a64215da679b13e0094a20c988c61d4238'
7
+ data.tar.gz: 19f169d36ac921d24c20488358f5c872d9abacf8e3668df261e1f62b29e996846faeadd96a8c375a1ce077588d8a604bf1dcb884119bf16b7d75183d61ff127d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Release History
2
2
 
3
+ ### 0.33.0 / 2019-02-01
4
+
5
+ * Add Debugger on_error configuration.
6
+ * Update Transmitter
7
+ * Add dependency on current-ruby.
8
+ * Add Transmitter#on_error method.
9
+ * Update Transmitter documentation.
10
+ * Make use of Credentials#project_id
11
+ * Use Credentials#project_id
12
+ If a project_id is not provided, use the value on the Credentials object.
13
+ This value was added in googleauth 0.7.0.
14
+ * Loosen googleauth dependency
15
+ Allow for new releases up to 0.10.
16
+ The googleauth devs have committed to maintanining the current API
17
+ and will not make backwards compatible changes before 0.10.
18
+
3
19
  ### 0.32.6 / 2018-11-15
4
20
 
5
21
  * Update network configuration.
@@ -178,4 +178,5 @@ Google::Cloud.configure.add_config! :debugger do |config|
178
178
  config.add_field! :client_config, nil, match: Hash
179
179
  config.add_field! :allow_mutating_methods, false
180
180
  config.add_field! :evaluation_time_limit, 0.05, match: Numeric
181
+ config.add_field! :on_error, nil, match: Proc
181
182
  end
@@ -85,30 +85,32 @@ module Google
85
85
  def self.new project_id: nil, credentials: nil, service_name: nil,
86
86
  service_version: nil, scope: nil, timeout: nil,
87
87
  client_config: nil, project: nil, keyfile: nil
88
- project_id ||= (project || default_project_id)
89
- project_id = project_id.to_s # Always cast to a string
88
+ project_id ||= (project || default_project_id)
89
+ service_name ||= default_service_name
90
+ service_version ||= default_service_version
91
+ scope ||= configure.scope
92
+ timeout ||= configure.timeout
93
+ client_config ||= configure.client_config
90
94
 
91
- service_name ||= default_service_name
92
95
  service_name = service_name.to_s
96
+ raise ArgumentError, "service_name is missing" if service_name.empty?
93
97
 
94
- service_version ||= default_service_version
95
98
  service_version = service_version.to_s
96
-
97
- raise ArgumentError, "project_id is missing" if project_id.empty?
98
- raise ArgumentError, "service_name is missing" if service_name.empty?
99
99
  if service_version.nil?
100
100
  raise ArgumentError, "service_version is missing"
101
101
  end
102
102
 
103
- scope ||= configure.scope
104
- timeout ||= configure.timeout
105
- client_config ||= configure.client_config
106
-
107
103
  credentials ||= (keyfile || default_credentials(scope: scope))
108
104
  unless credentials.is_a? Google::Auth::Credentials
109
105
  credentials = Debugger::Credentials.new credentials, scope: scope
110
106
  end
111
107
 
108
+ if credentials.respond_to? :project_id
109
+ project_id ||= credentials.project_id
110
+ end
111
+ project_id = project_id.to_s # Always cast to a string
112
+ raise ArgumentError, "project_id is missing" if project_id.empty?
113
+
112
114
  Debugger::Project.new(
113
115
  Debugger::Service.new(project_id, credentials,
114
116
  timeout: timeout, client_config: client_config),
@@ -147,6 +149,9 @@ module Google
147
149
  # state. Defaults to false.
148
150
  # * `evaluation_time_limit` - (Numeric) Time limit in seconds for
149
151
  # expression evaluation. Defaults to 0.05.
152
+ # * `on_error` - (Proc) A Proc to be run when an error is encountered
153
+ # on a background thread. The Proc must take the error object as the
154
+ # single argument.
150
155
  #
151
156
  # See the [Configuration
152
157
  # Guide](https://googleapis.github.io/google-cloud-ruby/docs/stackdriver/latest/file.INSTRUMENTATION_CONFIGURATION)
@@ -347,7 +347,7 @@ module Google
347
347
  is_final_state: is_final_state,
348
348
  create_time: timestamp_to_grpc(create_time),
349
349
  final_time: timestamp_to_grpc(final_time),
350
- user_email: user_email,
350
+ user_email: user_email.to_s,
351
351
  stack_frames: stack_frames_to_grpc,
352
352
  evaluated_expressions: evaluated_expressions_to_grpc,
353
353
  status: status_to_grpc,
@@ -77,23 +77,26 @@ module Google
77
77
 
78
78
  ##
79
79
  # @private Predefined regex. Saves time during runtime.
80
- BYTE_CODE_BLACKLIST_REGEX = /^\d+ #{BYTE_CODE_BLACKLIST.join '|'}/
80
+ BYTE_CODE_BLACKLIST_REGEX =
81
+ /^\d+ #{BYTE_CODE_BLACKLIST.join '|'}/.freeze
81
82
 
82
83
  ##
83
84
  # @private Predefined regex. Saves time during runtime.
84
85
  FULL_BYTE_CODE_BLACKLIST_REGEX = /^\d+ #{
85
86
  [*BYTE_CODE_BLACKLIST, *LOCAL_BYTE_CODE_BLACKLIST].join '|'
86
- }/
87
+ }/.freeze
87
88
 
88
89
  ##
89
90
  # @private Predefined regex. Saves time during runtime.
90
91
  FUNC_CALL_FLAG_BLACKLIST_REGEX =
91
- /<callinfo!.+#{FUNC_CALL_FLAG_BLACKLIST.join '|'}/
92
+ /<callinfo!.+#{FUNC_CALL_FLAG_BLACKLIST.join '|'}/.freeze
92
93
 
93
94
  ##
94
95
  # @private Predefined regex. Saves time during runtime.
95
96
  CATCH_TABLE_BLACKLIST_REGEX =
96
- /catch table.*catch type: #{CATCH_TABLE_TYPE_BLACKLIST.join '|'}/m
97
+ /catch table.*catch type: #{
98
+ CATCH_TABLE_TYPE_BLACKLIST.join '|'
99
+ }/m.freeze
97
100
 
98
101
  private_constant :BYTE_CODE_BLACKLIST_REGEX,
99
102
  :FULL_BYTE_CODE_BLACKLIST_REGEX,
@@ -13,34 +13,46 @@
13
13
  # limitations under the License.
14
14
 
15
15
 
16
- require "stackdriver/core/async_actor"
16
+ require "concurrent"
17
+ require "google/cloud/errors"
17
18
 
18
19
  module Google
19
20
  module Cloud
20
21
  module Debugger
22
+ ##
23
+ # # TransmitterError
24
+ #
25
+ # Used to indicate a problem submitting breakpoints. This can occur when
26
+ # there are not enough resources allocated for the amount of usage, or
27
+ # when the calling the API returns an error.
28
+ #
29
+ class TransmitterError < Google::Cloud::Error
30
+ # @!attribute [r] breakpoint
31
+ # @return [Array<Google::Cloud::Debugger::Breakpoint>] The
32
+ # individual error event that was not submitted to Stackdriver
33
+ # Debugger service.
34
+ attr_reader :breakpoint
35
+
36
+ def initialize message, breakpoint = nil
37
+ super(message)
38
+ @breakpoint = breakpoint
39
+ end
40
+ end
41
+
21
42
  ##
22
43
  # # Transmitter
23
44
  #
24
45
  # Responsible for submit evaluated breakpoints back to Stackdriver
25
- # Debugger service asynchronously. It has it's own dedicated child thread,
26
- # so it doesn't interfere with main Ruby application threads or the
27
- # debugger agent's thread.
46
+ # Debugger service asynchronously. It maintains a thread pool.
28
47
  #
29
48
  # The transmitter is controlled by the debugger agent it belongs to.
30
- # Debugger agent submits evaluated breakpoint into a thread safe queue,
31
- # and the transmitter operates directly on the queue along with minimal
32
- # interaction with the rest debugger agent components
49
+ # Debugger agent submits evaluated breakpoint asynchronously, and the
50
+ # transmitter submits the breakpoints to Stackdriver Debugger service.
33
51
  #
34
52
  class Transmitter
35
- include Stackdriver::Core::AsyncActor
36
-
37
- ##
38
- # @private Default maximum backlog size for the job queue
39
- DEFAULT_MAX_QUEUE_SIZE = 1000
40
-
41
53
  ##
42
- # @private The gRPC Service object.
43
- attr_accessor :service
54
+ # @private The gRPC Service object and thread pool.
55
+ attr_reader :service, :thread_pool
44
56
 
45
57
  ##
46
58
  # The debugger agent this transmiter belongs to
@@ -48,92 +60,138 @@ module Google
48
60
  attr_accessor :agent
49
61
 
50
62
  ##
51
- # Maxium backlog size for this transmitter's queue
52
- attr_accessor :max_queue_size
63
+ # Maximum backlog size for this transmitter's queue
64
+ attr_accessor :max_queue
65
+ alias max_queue_size max_queue
66
+ alias max_queue_size= max_queue=
67
+
68
+ ##
69
+ # Maximum threads used in the thread pool
70
+ attr_accessor :threads
53
71
 
54
72
  ##
55
- # @private Construct a new instance of Tramsnitter
56
- def initialize agent, service, max_queue_size = DEFAULT_MAX_QUEUE_SIZE
57
- super()
73
+ # @private Creates a new Transmitter instance.
74
+ def initialize agent, service, max_queue: 1000, threads: 10
75
+ @agent = agent
58
76
  @service = service
59
- @agent = agent
60
- @max_queue_size = max_queue_size
61
- @queue = []
62
- @queue_resource = new_cond
77
+
78
+ @max_queue = max_queue
79
+ @threads = threads
80
+
81
+ @thread_pool = Concurrent::CachedThreadPool.new max_threads: @threads,
82
+ max_queue: @max_queue
83
+
84
+ @error_callbacks = []
85
+
86
+ # Make sure all queued calls are completed when process exits.
87
+ at_exit { stop }
88
+ end
89
+
90
+ ##
91
+ # Enqueue an evaluated breakpoint to be submitted by the transmitter.
92
+ #
93
+ # @raise [TransmitterError] if there are no resources available to make
94
+ # queue the API call on the thread pool.
95
+ def submit breakpoint
96
+ Concurrent::Promises.future_on(@thread_pool, breakpoint) do |bp|
97
+ submit_sync bp
98
+ end
99
+ rescue Concurrent::RejectedExecutionError => e
100
+ raise TransmitterError.new(
101
+ "Error asynchronously submitting breakpoint: #{e.message}",
102
+ breakpoint
103
+ )
63
104
  end
64
105
 
65
106
  ##
66
- # Starts the transmitter and its worker thread
107
+ # Starts the transmitter and its thread pool.
108
+ #
109
+ # @return [Transmitter] returns self so calls can be chained.
67
110
  def start
68
- async_start
111
+ # no-op
112
+ self
69
113
  end
70
114
 
71
115
  ##
72
- # Stops the transmitter and its worker thread. Once stopped, cannot be
116
+ # Stops the transmitter and its thread pool. Once stopped, cannot be
73
117
  # started again.
74
- def stop
75
- async_stop
118
+ #
119
+ # @return [Transmitter] returns self so calls can be chained.
120
+ def stop timeout = nil
121
+ if @thread_pool
122
+ @thread_pool.shutdown
123
+ @thread_pool.wait_for_termination timeout
124
+ end
125
+
126
+ self
76
127
  end
77
128
 
78
129
  ##
79
- # Enqueue an evaluated breakpoints to be submitted by the transmitter.
130
+ # Whether the transmitter has been started.
80
131
  #
81
- # @param [Google::Cloud::Debugger::Breakpoint] breakpoint The evaluated
82
- # breakpoint to be submitted
83
- def submit breakpoint
84
- synchronize do
85
- @queue.push breakpoint
86
- @queue_resource.broadcast
87
- # Discard old entries if queue gets too large
88
- @queue.pop while @queue.size > @max_queue_size
89
- end
132
+ # @return [boolean] `true` when started, `false` otherwise.
133
+ #
134
+ def started?
135
+ @thread_pool.running? if @thread_pool
90
136
  end
91
137
 
92
138
  ##
93
- # @private Callback fucntion for AsyncActor module to run the async
94
- # job in a loop
95
- def run_backgrounder
96
- breakpoint = wait_next_item
97
- return if breakpoint.nil?
98
- begin
99
- service.update_active_breakpoint agent.debuggee.id, breakpoint
100
- rescue StandardError => e
101
- warn ["#{e.class}: #{e.message}", e.backtrace].join("\n\t")
102
- @last_exception = e
103
- end
139
+ # Whether the transmitter has been stopped.
140
+ #
141
+ # @return [boolean] `true` when stopped, `false` otherwise.
142
+ #
143
+ def stopped?
144
+ !started?
104
145
  end
105
146
 
106
147
  ##
107
- # @private Callback function when the async actor thread state changes
108
- def on_async_state_change
109
- synchronize do
110
- @queue_resource.broadcast
111
- end
148
+ # Register to be notified of errors when raised.
149
+ #
150
+ # If an unhandled error has occurred the transmitter will attempt to
151
+ # recover from the error and resume submitting breakpoints.
152
+ #
153
+ # Multiple error handlers can be added.
154
+ #
155
+ # @yield [callback] The block to be called when an error is raised.
156
+ # @yieldparam [Exception] error The error raised.
157
+ #
158
+ def on_error &block
159
+ @error_callbacks << block
112
160
  end
113
161
 
114
- private
162
+ protected
115
163
 
116
- ##
117
- # @private The the next item from the transmitter queue. If there are
118
- # no more item, it blocks the transmitter thread until an item is
119
- # enqueued
120
- def wait_next_item
121
- synchronize do
122
- @queue_resource.wait_while do
123
- async_suspended? || (async_running? && @queue.empty?)
164
+ # Calls all error callbacks.
165
+ def error! error
166
+ error_callbacks = @error_callbacks
167
+ error_callbacks = default_error_callbacks if error_callbacks.empty?
168
+ error_callbacks.each { |error_callback| error_callback.call error }
169
+ end
170
+
171
+ def default_error_callbacks
172
+ # This is memoized to reduce calls to the configuration.
173
+ @default_error_callbacks ||= begin
174
+ error_cb = Google::Cloud::Debugger.configuration.on_error
175
+ error_cb ||= Google::Cloud.configure.on_error
176
+ if error_cb
177
+ [error_cb]
178
+ else
179
+ []
124
180
  end
125
- @queue.pop
126
181
  end
127
182
  end
128
183
 
129
- ##
130
- # @private Override the #backgrounder_stoppable? method from AsyncActor
131
- # module. The actor can be gracefully stopped when queue is
132
- # empty.
133
- def backgrounder_stoppable?
134
- synchronize do
135
- @queue.empty?
136
- end
184
+ def submit_sync breakpoint
185
+ service.update_active_breakpoint agent.debuggee.id, breakpoint
186
+ rescue StandardError => e
187
+ sync_error = TransmitterError.new(
188
+ "Error asynchronously transmitting breakpoint: #{e.message}",
189
+ breakpoint
190
+ )
191
+ # Manually set backtrace so we don't have to raise
192
+ sync_error.set_backtrace caller
193
+
194
+ error! sync_error
137
195
  end
138
196
  end
139
197
  end
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Google LLC
1
+ # Copyright 2019 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Google LLC
1
+ # Copyright 2019 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Google LLC
1
+ # Copyright 2019 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Google LLC
1
+ # Copyright 2019 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Google LLC
1
+ # Copyright 2019 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Google LLC
1
+ # Copyright 2019 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Google LLC
1
+ # Copyright 2019 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Google LLC
1
+ # Copyright 2019 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Google LLC
1
+ # Copyright 2019 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Google LLC
1
+ # Copyright 2019 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
16
16
  module Google
17
17
  module Cloud
18
18
  module Debugger
19
- VERSION = "0.32.6".freeze
19
+ VERSION = "0.33.0".freeze
20
20
  end
21
21
  end
22
22
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google-cloud-debugger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.32.6
4
+ version: 0.33.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Heng Xiong
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-15 00:00:00.000000000 Z
11
+ date: 2019-02-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: binding_of_caller
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '1.3'
83
+ - !ruby/object:Gem::Dependency
84
+ name: concurrent-ruby
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: minitest
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -170,14 +184,14 @@ dependencies:
170
184
  requirements:
171
185
  - - "~>"
172
186
  - !ruby/object:Gem::Version
173
- version: 0.59.2
187
+ version: 0.61.0
174
188
  type: :development
175
189
  prerelease: false
176
190
  version_requirements: !ruby/object:Gem::Requirement
177
191
  requirements:
178
192
  - - "~>"
179
193
  - !ruby/object:Gem::Version
180
- version: 0.59.2
194
+ version: 0.61.0
181
195
  - !ruby/object:Gem::Dependency
182
196
  name: simplecov
183
197
  requirement: !ruby/object:Gem::Requirement
@@ -351,7 +365,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
351
365
  version: '0'
352
366
  requirements: []
353
367
  rubyforge_project:
354
- rubygems_version: 2.7.7
368
+ rubygems_version: 2.7.6
355
369
  signing_key:
356
370
  specification_version: 4
357
371
  summary: API Client and instrumentation library for Stackdriver Debugger