sqreen 1.21.0.beta3-java → 1.21.0-java

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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +28 -15
  3. data/lib/sqreen/condition_evaluator.rb +5 -6
  4. data/lib/sqreen/conditionable.rb +6 -24
  5. data/lib/sqreen/ecosystem.rb +29 -2
  6. data/lib/sqreen/ecosystem/databases/database_connection_data.rb +23 -0
  7. data/lib/sqreen/ecosystem/databases/mongo.rb +39 -0
  8. data/lib/sqreen/ecosystem/databases/mysql.rb +54 -0
  9. data/lib/sqreen/ecosystem/databases/postgres.rb +51 -0
  10. data/lib/sqreen/ecosystem/databases/redis.rb +36 -0
  11. data/lib/sqreen/ecosystem/exception_reporting.rb +4 -2
  12. data/lib/sqreen/ecosystem/messaging/bunny.rb +61 -0
  13. data/lib/sqreen/ecosystem/messaging/kafka.rb +70 -0
  14. data/lib/sqreen/ecosystem/messaging/kinesis.rb +66 -0
  15. data/lib/sqreen/ecosystem/messaging/sqs.rb +68 -0
  16. data/lib/sqreen/ecosystem/module_api/message_producer.rb +9 -3
  17. data/lib/sqreen/ecosystem/module_api/tracing/consumer_data.rb +13 -0
  18. data/lib/sqreen/ecosystem/module_api/tracing/messaging_data.rb +35 -0
  19. data/lib/sqreen/ecosystem/module_api/tracing/producer_data.rb +13 -0
  20. data/lib/sqreen/ecosystem/module_registry.rb +5 -1
  21. data/lib/sqreen/ecosystem/tracing/modules/client.rb +7 -3
  22. data/lib/sqreen/ecosystem/tracing/modules/consumer.rb +35 -0
  23. data/lib/sqreen/ecosystem/tracing/modules/determine_ip.rb +28 -0
  24. data/lib/sqreen/ecosystem/tracing/modules/producer.rb +35 -0
  25. data/lib/sqreen/ecosystem/tracing/signals/tracing_consumer.rb +56 -0
  26. data/lib/sqreen/ecosystem/tracing/signals/tracing_producer.rb +56 -0
  27. data/lib/sqreen/ecosystem_integration.rb +1 -7
  28. data/lib/sqreen/ecosystem_integration/around_callbacks.rb +10 -20
  29. data/lib/sqreen/ecosystem_integration/instrumentation_service.rb +4 -8
  30. data/lib/sqreen/graft/call.rb +1 -21
  31. data/lib/sqreen/graft/hook.rb +75 -83
  32. data/lib/sqreen/kit/signals/specialized/sqreen_exception.rb +2 -0
  33. data/lib/sqreen/metrics.rb +0 -1
  34. data/lib/sqreen/rules/custom_error_cb.rb +1 -1
  35. data/lib/sqreen/rules/rule_cb.rb +2 -2
  36. data/lib/sqreen/runner.rb +12 -27
  37. data/lib/sqreen/version.rb +1 -1
  38. data/lib/sqreen/weave/budget.rb +14 -3
  39. data/lib/sqreen/weave/legacy/instrumentation.rb +94 -145
  40. metadata +22 -9
  41. data/lib/sqreen/ecosystem/redis/redis_connection.rb +0 -43
  42. data/lib/sqreen/metrics/req_detailed.rb +0 -41
@@ -0,0 +1,56 @@
1
+ require 'sqreen/kit/configuration'
2
+ require 'sqreen/kit/signals/point'
3
+ require 'sqreen/kit/signals/dto_helper'
4
+
5
+ # reference: https://github.com/sqreen/SignalsSchemas/blob/master/schemas/payload/tracing/producer-2020-04-21/schema.cue
6
+
7
+ module Sqreen
8
+ module Ecosystem
9
+ module Tracing
10
+ module Signals
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ class Sqreen::Ecosystem::Tracing::Signals::TracingProducer < Sqreen::Kit::Signals::Point
17
+ readonly_attrs :payload_schema, :source, :signal_name
18
+
19
+ def initialize(values = {})
20
+ self.payload_schema = Payload::SCHEMA_VERSION
21
+ self.source = Sqreen::Kit::Configuration.default_source
22
+ self.signal_name = 'tracing.producer'
23
+ self.time = values[:time] || Time.now
24
+ super
25
+ end
26
+
27
+ def payload=(payload)
28
+ unless payload.is_a?(Payload)
29
+ raise ArgumentError, "Payload should be a #{Payload}"
30
+ end
31
+ super
32
+ end
33
+
34
+ class Payload
35
+ include Sqreen::Kit::Signals::DtoHelper
36
+
37
+ add_mandatory_attrs :message_type, :host, :tracing_identifier
38
+
39
+ SCHEMA_VERSION = 'tracing/producer-2020-04-21'.freeze
40
+
41
+ # @return [Symbol]
42
+ attr_accessor :message_type
43
+
44
+ # @return [String]
45
+ attr_accessor :host
46
+
47
+ # @return [String]
48
+ attr_accessor :ip
49
+
50
+ # @return [String]
51
+ attr_accessor :topic
52
+
53
+ # @return [String]
54
+ attr_accessor :tracing_identifier
55
+ end
56
+ end
@@ -1,8 +1,6 @@
1
1
  require 'sqreen/log/loggable'
2
- require 'sqreen/metrics_store'
3
2
  require 'sqreen/ecosystem'
4
3
  require 'sqreen/ecosystem/dispatch_table'
5
- require 'sqreen/ecosystem_integration/around_callbacks'
6
4
  require 'sqreen/ecosystem_integration/instrumentation_service'
7
5
  require 'sqreen/ecosystem_integration/request_lifecycle_tracking'
8
6
  require 'sqreen/ecosystem_integration/signal_consumption'
@@ -19,12 +17,9 @@ module Sqreen
19
17
  include Sqreen::Log::Loggable
20
18
 
21
19
  # @param [Sqreen::Framework] framework
22
- # @param [Proc] create_binning_metric
23
- def initialize(framework, queue, create_binning_metric)
20
+ def initialize(framework, queue)
24
21
  @framework = framework
25
22
  @queue = queue
26
- # XXX: created metrics are insulated from feature upgrades
27
- @create_binning_metric = create_binning_metric
28
23
  @request_lifecycle = RequestLifecycleTracking.new
29
24
  @online = false
30
25
  end
@@ -33,7 +28,6 @@ module Sqreen
33
28
  raise 'already initialized' if @online
34
29
 
35
30
  setup_dispatch_table
36
- AroundCallbacks.create_metric = @create_binning_metric
37
31
  Ecosystem.init
38
32
  logger.info 'Ecosystem successfully initialized'
39
33
  @online = true
@@ -1,8 +1,6 @@
1
- require 'sqreen/metrics_store'
2
1
  require 'sqreen/log/loggable'
3
2
  require 'sqreen/events/remote_exception'
4
3
  require 'sqreen/mono_time'
5
- require 'sqreen/graft/call'
6
4
 
7
5
  module Sqreen
8
6
  class EcosystemIntegration
@@ -10,32 +8,27 @@ module Sqreen
10
8
  class << self
11
9
  include Log::Loggable::ClassMethods
12
10
 
13
- # @return [Proc]
14
- attr_accessor :create_metric
15
-
16
11
  # for instrumentation hooks
17
- # instrumentation hooks already handle budgets/metrics
12
+ # instrumentation hooks already handle budgets, so nothing
13
+ # to do in that respect
18
14
  def wrap_instrumentation_hook(module_name, action, callable)
19
- # make tag similar to that of rules
20
- # TODO: move to structured tags to avoid silly string manips
21
- action_for_metric = if %w[pre post failing finally].include?(action)
22
- action
23
- else
24
- 'pre'
25
- end
26
- metric_name = "sq.ecosystem_#{module_name}.#{action_for_metric}"
27
- create_metric.call(metric_name)
15
+ perf_notif_name = "ecosystem_#{module_name}"
28
16
 
29
17
  Proc.new do |*args|
30
18
  begin
19
+ start = Sqreen.time
31
20
  callable.call(*args)
32
21
  rescue ::Exception => e # rubocop:disable Lint/RescueException
33
22
  # 2) rescue exceptions
34
23
  logger.warn { "Error in #{module_name}:#{action}: #{e.message}" }
35
24
  logger.debug { e.backtrace.map { |x| " #{x}" }.join("\n") }
36
25
  Sqreen::RemoteException.record(e)
37
- end # end begin
38
- end # end proc
26
+ ensure
27
+ # 3) contribute to performance metrics
28
+ stop = Sqreen.time
29
+ Sqreen::PerformanceNotifications.notify(perf_notif_name, action, start, stop)
30
+ end # end proc
31
+ end # end begin
39
32
  end
40
33
 
41
34
  # XXX: not used yet
@@ -43,8 +36,6 @@ module Sqreen
43
36
  timer_name = "ecosystem:#{module_name}@#{action}"
44
37
  perf_notif_name = "ecosystem_#{module_name}"
45
38
 
46
- # XXX: register metric
47
-
48
39
  Proc.new do |*args|
49
40
  begin
50
41
  req_storage = Thread.current[:sqreen_http_request]
@@ -85,7 +76,6 @@ module Sqreen
85
76
  if timer
86
77
  req_timer.include_measurements(timer) if req_timer
87
78
 
88
- # XXX: PerformanceNotifications is used no more
89
79
  Sqreen::PerformanceNotifications.notify(
90
80
  perf_notif_name, action, *timer.start_and_end
91
81
  )
@@ -12,26 +12,22 @@ module Sqreen
12
12
  hook = Sqreen::Graft::Hook[method].add do
13
13
  if spec[:before]
14
14
  cb = AroundCallbacks.wrap_instrumentation_hook(module_name, 'pre', spec[:before])
15
- tag = "weave,rule=ecosystem_#{module_name}"
16
- before(tag, flow: true, &cb)
15
+ before(nil, flow: true, &cb)
17
16
  end
18
17
 
19
18
  if spec[:after]
20
19
  cb = AroundCallbacks.wrap_instrumentation_hook(module_name, 'post', spec[:after])
21
- tag = "weave,rule=ecosystem_#{module_name}"
22
- after(tag, flow: true, &cb)
20
+ after(nil, flow: true, &cb)
23
21
  end
24
22
 
25
23
  if spec[:raised]
26
24
  cb = AroundCallbacks.wrap_instrumentation_hook(module_name, 'failing', spec[:raised])
27
- tag = "weave,rule=ecosystem_#{module_name}"
28
- raised(tag, flow: true, &cb)
25
+ raised(nil, flow: true, &cb)
29
26
  end
30
27
 
31
28
  if spec[:ensured]
32
29
  cb = AroundCallbacks.wrap_instrumentation_hook(module_name, 'finally', spec[:ensured])
33
- tag = "weave,rule=ecosystem_#{module_name}"
34
- ensured(tag, flow: true, &cb)
30
+ ensured(nil, flow: true, &cb)
35
31
  end
36
32
  end
37
33
  hook.install
@@ -27,10 +27,6 @@ module Sqreen
27
27
  def raise(value)
28
28
  Flow.raise(value)
29
29
  end
30
-
31
- def noop
32
- Flow.noop
33
- end
34
30
  end
35
31
 
36
32
  class Flow
@@ -50,17 +46,12 @@ module Sqreen
50
46
  def raise(value)
51
47
  new(:raise, value)
52
48
  end
53
-
54
- def noop
55
- new(:noop, nil)
56
- end
57
49
  end
58
50
 
59
51
  def initialize(action, value, brk = false)
60
52
  @action = action
61
53
  @value = value
62
54
  @break = brk
63
- @passed_conditions = false
64
55
  end
65
56
 
66
57
  def return?
@@ -100,16 +91,6 @@ module Sqreen
100
91
  def break?
101
92
  @break ? true : false
102
93
  end
103
-
104
- def passed_conditions!
105
- @passed_conditions = true
106
-
107
- self
108
- end
109
-
110
- def passed_conditions?
111
- @passed_conditions
112
- end
113
94
  end
114
95
 
115
96
  class TimerError < StandardError; end
@@ -120,7 +101,6 @@ module Sqreen
120
101
  end
121
102
 
122
103
  attr_reader :tag, :size
123
- attr_accessor :conditions_passed
124
104
 
125
105
  def initialize(tag, &block)
126
106
  @tag = tag
@@ -225,7 +205,7 @@ module Sqreen
225
205
  end
226
206
 
227
207
  def to_s
228
- "#{@tag}: time=%.03fus" % (@tally * 1_000_000)
208
+ "#{@tag}: time=%.03fus" % (duration * 1_000_000)
229
209
  end
230
210
 
231
211
  protected
@@ -7,8 +7,6 @@ require 'sqreen/graft'
7
7
  require 'sqreen/graft/call'
8
8
  require 'sqreen/graft/callback'
9
9
  require 'sqreen/graft/hook_point'
10
- require 'sqreen/weave'
11
- require 'sqreen/runner' # Sqreen.queue
12
10
 
13
11
  module Sqreen
14
12
  module Graft
@@ -138,13 +136,6 @@ module Sqreen
138
136
  request[:timed_callbacks] << t if request[:timed_level] >= 1
139
137
  end
140
138
  end
141
- # very hacky, but the non-local control flow with throw-catch
142
- # makes the solution non-obvious. needs to be revisited
143
- conditions_passed_proc = proc do
144
- if (request = Thread.current[:sqreen_http_request])
145
- request[:timed_callbacks].last.conditions_passed = true
146
- end
147
- end
148
139
 
149
140
  Proc.new do |*args, &block|
150
141
  request = Thread.current[:sqreen_http_request]
@@ -192,15 +183,18 @@ module Sqreen
192
183
  # budget implies request
193
184
  # TODO: make budget depend on a generic context (currently "request")
194
185
  budget = request[:time_budget] if request
195
- if request && (budget || request[:timed_level] >= 1)
186
+ if budget
187
+ budget_threshold = request[:time_budget_threshold]
188
+ budget_ratio = request[:time_budget_ratio]
196
189
  sqreen_timer = request[:sqreen_timer]
190
+ request_timer = request[:request_timer]
197
191
  end
198
192
 
199
193
  hooked_call = HookedCall.new(self, args)
200
194
 
201
195
  begin
202
196
  begin
203
- sqreen_timer.start if sqreen_timer
197
+ sqreen_timer.start if budget
204
198
  Thread.current[:sqreen_hook_entered] = true
205
199
 
206
200
  # TODO: make Call have #ball to throw by cb
@@ -212,34 +206,34 @@ module Sqreen
212
206
  # TODO: TimedHookCall TimedCallbackCall
213
207
  # TODO: TimeBoundHookCall TimeBoundCallbackCall TimeBoundFlow?
214
208
 
209
+ request_elapsed = request_timer.elapsed if budget
210
+
215
211
  hook.before.each do |c|
216
212
  next if c.ignore && c.ignore.call
217
213
 
218
- if budget && !c.mandatory && request[:time_budget_expended]
219
- request[:skipped_callbacks] << c
220
- next
214
+ if budget && !c.mandatory
215
+ sqreen_elapsed = sqreen_timer.elapsed
216
+ if budget_ratio && !request[:time_budget_expended]
217
+ fixed_budget = budget_threshold
218
+ proportional_budget = (request_elapsed - sqreen_elapsed) * budget_ratio
219
+ remaining = (fixed_budget > proportional_budget ? fixed_budget : proportional_budget) - sqreen_elapsed
220
+ else
221
+ remaining = budget_threshold - sqreen_elapsed
222
+ end
223
+ unless remaining > 0
224
+ request[:skipped_callbacks] << c
225
+ request[:time_budget_expended] = true
226
+ next
227
+ end
221
228
  end
222
229
 
223
- remaining = budget - sqreen_timer.elapsed if budget
224
-
225
- timer = nil
226
230
  flow = catch(Ball.new) do |ball|
227
- timer = Timer.new(c.name, &timed_callbacks_proc)
228
- timer.measure(ignore: chrono) do
231
+ Timer.new(c.name, &timed_callbacks_proc).measure(ignore: chrono) do
229
232
  c.call(CallbackCall.new(c, remaining, hooked_call.instance, hooked_call.args_passed), ball)
230
233
  end
231
234
  end
232
235
 
233
- if budget && timer
234
- remaining -= timer.duration
235
- if remaining < 0.0
236
- request[:time_budget_expended]
237
- request[:overtime_cb] = c.name
238
- end
239
- end
240
-
241
236
  next unless c.flow && flow.is_a?(Flow)
242
- conditions_passed_proc[] if flow.passed_conditions?
243
237
  hooked_call.raise = flow.raise and hooked_call.raising = true if flow.raise?
244
238
  hooked_call.args_pass = flow.args and hooked_call.args_passing = true if flow.args?
245
239
  hooked_call.return = flow.return and hooked_call.returning = true if flow.return?
@@ -254,7 +248,7 @@ module Sqreen
254
248
  return hooked_call.return if hooked_call.returning
255
249
  ensure
256
250
  Thread.current[:sqreen_hook_entered] = false
257
- sqreen_timer.stop if sqreen_timer
251
+ sqreen_timer.stop if budget
258
252
  end unless hook.before.empty?
259
253
 
260
254
  begin
@@ -267,41 +261,41 @@ module Sqreen
267
261
  end
268
262
  rescue ::Exception => e # rubocop:disable Lint/RescueException
269
263
  begin
270
- sqreen_timer.start if sqreen_timer
264
+ sqreen_timer.start if budget
271
265
  Thread.current[:sqreen_hook_entered] = true
272
266
  hooked_call.raised = e
273
267
 
274
268
  logger.debug { "[#{Process.pid}] Hook #{hook.point} disabled:#{hook.disabled?} exception:#{e}" } if logger_debug
275
269
  raise if hook.raised.empty?
276
270
 
271
+ request_elapsed = request_timer.elapsed if budget
272
+
277
273
  hook.raised.each do |c|
278
274
  next if c.ignore && c.ignore.call
279
275
 
280
- if budget && !c.mandatory && request[:time_budget_expended]
281
- request[:skipped_callbacks] << c
282
- next
276
+ if budget && !c.mandatory
277
+ sqreen_elapsed = sqreen_timer.elapsed
278
+ if budget_ratio && !request[:time_budget_expended]
279
+ fixed_budget = budget_threshold
280
+ proportional_budget = (request_elapsed - sqreen_elapsed) * budget_ratio
281
+ remaining = (fixed_budget > proportional_budget ? fixed_budget : proportional_budget) - sqreen_elapsed
282
+ else
283
+ remaining = budget_threshold - sqreen_elapsed
284
+ end
285
+ unless remaining > 0
286
+ request[:skipped_callbacks] << c
287
+ request[:time_budget_expended] = true
288
+ next
289
+ end
283
290
  end
284
291
 
285
- remaining = budget - sqreen_timer.elapsed if budget
286
-
287
- timer = nil
288
292
  flow = catch(Ball.new) do |ball|
289
- timer = Timer.new(c.name, &timed_callbacks_proc)
290
- timer.measure(ignore: chrono) do
293
+ Timer.new(c.name, &timed_callbacks_proc).measure(ignore: chrono) do
291
294
  c.call(CallbackCall.new(c, remaining, hooked_call.instance, hooked_call.args_passing ? hooked_call.args_pass : hooked_call.args_passed, hooked_call.raised), ball)
292
295
  end
293
296
  end
294
297
 
295
- if budget && timer
296
- remaining -= timer.duration
297
- if remaining < 0.0
298
- request[:time_budget_expended]
299
- request[:overtime_cb] = c.name
300
- end
301
- end
302
-
303
298
  next unless c.flow && flow.is_a?(Flow)
304
- conditions_passed_proc[] if flow.passed_conditions?
305
299
  hooked_call.raise = flow.raise and hooked_call.raising = true if flow.raise?
306
300
  hooked_call.return = flow.return and hooked_call.returning = true if flow.return?
307
301
  hooked_call.retrying = true if flow.retry?
@@ -318,40 +312,40 @@ module Sqreen
318
312
  raise
319
313
  else
320
314
  begin
321
- sqreen_timer.start if sqreen_timer
315
+ sqreen_timer.start if budget
322
316
  Thread.current[:sqreen_hook_entered] = true
323
317
 
324
318
  # TODO: hooked_call.returning should be always false here?
325
319
  return hooked_call.returning ? hooked_call.return : hooked_call.returned if hook.after.empty?
326
320
 
321
+ request_elapsed = request_timer.elapsed if budget
322
+
327
323
  hook.after.each do |c|
328
324
  next if c.ignore && c.ignore.call
329
325
 
330
- if budget && !c.mandatory && request[:time_budget_expended]
331
- request[:skipped_callbacks] << c
332
- next
326
+ if budget && !c.mandatory
327
+ sqreen_elapsed = sqreen_timer.elapsed
328
+ if budget_ratio && !request[:time_budget_expended]
329
+ fixed_budget = budget_threshold
330
+ proportional_budget = (request_elapsed - sqreen_elapsed) * budget_ratio
331
+ remaining = (fixed_budget > proportional_budget ? fixed_budget : proportional_budget) - sqreen_elapsed
332
+ else
333
+ remaining = budget_threshold - sqreen_elapsed
334
+ end
335
+ unless remaining > 0
336
+ request[:skipped_callbacks] << c
337
+ request[:time_budget_expended] = true
338
+ next
339
+ end
333
340
  end
334
341
 
335
- remaining = budget - sqreen_timer.elapsed if budget
336
-
337
- timer = nil
338
342
  flow = catch(Ball.new) do |ball|
339
- timer = Timer.new(c.name, &timed_callbacks_proc)
340
- timer.measure(ignore: chrono) do
343
+ Timer.new(c.name, &timed_callbacks_proc).measure(ignore: chrono) do
341
344
  c.call(CallbackCall.new(c, remaining, hooked_call.instance, hooked_call.args_passing ? hooked_call.args_pass : hooked_call.args_passed, nil, hooked_call.returned), ball)
342
345
  end
343
346
  end
344
347
 
345
- if budget && timer
346
- remaining -= timer.duration
347
- if remaining < 0.0
348
- request[:time_budget_expended]
349
- request[:overtime_cb] = c.name
350
- end
351
- end
352
-
353
348
  next unless c.flow && flow.is_a?(Flow)
354
- conditions_passed_proc[] if flow.passed_conditions?
355
349
  hooked_call.raise = flow.raise and hooked_call.raising = true if flow.raise?
356
350
  hooked_call.return = flow.return and hooked_call.returning = true if flow.return?
357
351
  break if flow.break?
@@ -379,38 +373,36 @@ module Sqreen
379
373
  hook.ensured.each do |c|
380
374
  next if c.ignore && c.ignore.call
381
375
 
382
- if budget && !c.mandatory && request[:time_budget_expended]
383
- request[:skipped_callbacks] << c
384
- next
376
+ if budget && !c.mandatory
377
+ sqreen_elapsed = sqreen_timer.elapsed
378
+ if budget_ratio && !request[:time_budget_expended]
379
+ fixed_budget = budget_threshold
380
+ proportional_budget = (request_elapsed - sqreen_elapsed) * budget_ratio
381
+ remaining = (fixed_budget > proportional_budget ? fixed_budget : proportional_budget) - sqreen_elapsed
382
+ else
383
+ remaining = budget_threshold - sqreen_elapsed
384
+ end
385
+ unless remaining > 0
386
+ request[:skipped_callbacks] << c
387
+ request[:time_budget_expended] = true
388
+ next
389
+ end
385
390
  end
386
391
 
387
- remaining = budget - sqreen_timer.elapsed if budget
388
-
389
- timer = nil
390
392
  flow = catch(Ball.new) do |ball|
391
- timer = Timer.new(c.name, &timed_callbacks_proc)
392
- timer.measure(ignore: chrono) do
393
+ Timer.new(c.name, &timed_callbacks_proc).measure(ignore: chrono) do
393
394
  c.call(CallbackCall.new(c, remaining, hooked_call.instance, hooked_call.args_passing ? hooked_call.args_pass : hooked_call.args_passed, nil, hooked_call.returned), ball)
394
395
  end
395
396
  end
396
397
 
397
- if budget && timer
398
- remaining -= timer.duration
399
- if remaining < 0.0
400
- request[:time_budget_expended]
401
- request[:overtime_cb] = c.name
402
- end
403
- end
404
-
405
398
  next unless c.flow && flow.is_a?(Flow)
406
- conditions_passed_proc[] if flow.passed_conditions?
407
399
  hooked_call.raise = flow.raise and hooked_call.raising = true if flow.raise?
408
400
  hooked_call.return = flow.return and hooked_call.returning = true if flow.return?
409
401
  break if flow.break?
410
402
  end unless hook.ensured.empty? || hook.disabled?
411
403
 
412
404
  Thread.current[:sqreen_hook_entered] = false
413
- sqreen_timer.stop if sqreen_timer
405
+ sqreen_timer.stop if budget
414
406
  rescue StandardError => e
415
407
  Sqreen::Weave.logger.debug { "exception:#{e.class} message:'#{e.message}' location:\"#{e.backtrace[0]}\"" }
416
408
  Sqreen::RemoteException.record(e) if Sqreen.queue