google-cloud-debugger 0.32.6 → 0.33.0

Sign up to get free protection for your applications and to get access to all the features.
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