sqreen 1.19.1 → 1.20.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -0
  3. data/lib/sqreen/agent_message.rb +20 -0
  4. data/lib/sqreen/aggregated_metric.rb +25 -0
  5. data/lib/sqreen/attack_detected.html +1 -2
  6. data/lib/sqreen/ca.crt +24 -0
  7. data/lib/sqreen/configuration.rb +10 -4
  8. data/lib/sqreen/deferred_logger.rb +4 -0
  9. data/lib/sqreen/deliveries/batch.rb +4 -1
  10. data/lib/sqreen/deliveries/simple.rb +4 -0
  11. data/lib/sqreen/endpoint_testing.rb +184 -0
  12. data/lib/sqreen/event.rb +7 -5
  13. data/lib/sqreen/events/attack.rb +23 -18
  14. data/lib/sqreen/events/remote_exception.rb +0 -22
  15. data/lib/sqreen/events/request_record.rb +15 -70
  16. data/lib/sqreen/frameworks/request_recorder.rb +13 -2
  17. data/lib/sqreen/graft/call.rb +32 -19
  18. data/lib/sqreen/graft/callback.rb +1 -1
  19. data/lib/sqreen/graft/hook.rb +97 -116
  20. data/lib/sqreen/graft/hook_point.rb +1 -1
  21. data/lib/sqreen/kit/signals/specialized/aggregated_metric.rb +72 -0
  22. data/lib/sqreen/kit/signals/specialized/attack.rb +57 -0
  23. data/lib/sqreen/kit/signals/specialized/binning_metric.rb +76 -0
  24. data/lib/sqreen/kit/signals/specialized/http_trace.rb +26 -0
  25. data/lib/sqreen/kit/signals/specialized/sdk_track_call.rb +50 -0
  26. data/lib/sqreen/kit/signals/specialized/sqreen_exception.rb +57 -0
  27. data/lib/sqreen/legacy/instrumentation.rb +10 -10
  28. data/lib/sqreen/legacy/old_event_submission_strategy.rb +221 -0
  29. data/lib/sqreen/legacy/waf_redactions.rb +49 -0
  30. data/lib/sqreen/log/loggable.rb +2 -1
  31. data/lib/sqreen/logger.rb +4 -0
  32. data/lib/sqreen/metrics/base.rb +3 -0
  33. data/lib/sqreen/metrics_store.rb +22 -12
  34. data/lib/sqreen/performance_notifications/binned_metrics.rb +8 -2
  35. data/lib/sqreen/rules.rb +4 -2
  36. data/lib/sqreen/rules/not_found_cb.rb +2 -0
  37. data/lib/sqreen/rules/rule_cb.rb +2 -0
  38. data/lib/sqreen/rules/waf_cb.rb +13 -10
  39. data/lib/sqreen/runner.rb +75 -8
  40. data/lib/sqreen/sensitive_data_redactor.rb +19 -31
  41. data/lib/sqreen/session.rb +51 -43
  42. data/lib/sqreen/signals/conversions.rb +283 -0
  43. data/lib/sqreen/signals/http_trace_redaction.rb +111 -0
  44. data/lib/sqreen/signals/signals_submission_strategy.rb +78 -0
  45. data/lib/sqreen/version.rb +1 -1
  46. data/lib/sqreen/weave/legacy/instrumentation.rb +56 -53
  47. metadata +45 -7
  48. data/lib/sqreen/backport.rb +0 -9
  49. data/lib/sqreen/backport/clock_gettime.rb +0 -74
  50. data/lib/sqreen/backport/original_name.rb +0 -88
@@ -30,27 +30,5 @@ module Sqreen
30
30
  def klass
31
31
  payload['exception'].class.name
32
32
  end
33
-
34
- def to_hash
35
- exception = payload['exception']
36
- ev = {
37
- :klass => exception.class.name,
38
- :message => exception.message,
39
- :params => payload['request_params'],
40
- :time => payload['time'],
41
- :infos => {
42
- :client_ip => payload['client_ip'],
43
- },
44
- :request => payload['request_infos'],
45
- :headers => payload['headers'],
46
- :rule_name => payload['rule_name'],
47
- :rulespack_id => payload['rulespack_id'],
48
- }
49
-
50
- ev[:infos].merge!(payload['infos']) if payload['infos']
51
- return ev unless exception.backtrace
52
- ev[:context] = { :backtrace => exception.backtrace.map(&:to_s) }
53
- ev
54
- end
55
33
  end
56
34
  end
@@ -14,6 +14,10 @@ require 'sqreen/sensitive_data_redactor'
14
14
  module Sqreen
15
15
  # When a request is deeemed worthy of being sent to the backend
16
16
  class RequestRecord < Sqreen::Event
17
+ attr_reader :redactor
18
+
19
+ # @param [Hash] payload
20
+ # @param [Sqreen::SensitiveDataRedactor] redactor
17
21
  def initialize(payload, redactor = nil)
18
22
  @redactor = redactor
19
23
  super(payload)
@@ -23,74 +27,18 @@ module Sqreen
23
27
  (payload && payload[:observed]) || {}
24
28
  end
25
29
 
26
- def to_hash
27
- res = { :version => '20171208' }
28
- if payload[:observed]
29
- res[:observed] = payload[:observed].dup
30
- rulespack = nil
31
- if observed[:attacks]
32
- res[:observed][:attacks] = observed[:attacks].map do |att|
33
- natt = att.dup
34
- rulespack = natt.delete(:rulespack_id) || rulespack
35
- natt
36
- end
37
- end
38
- if observed[:sqreen_exceptions]
39
- res[:observed][:sqreen_exceptions] = observed[:sqreen_exceptions].map do |exc|
40
- nex = exc.dup
41
- excp = nex.delete(:exception)
42
- if excp
43
- nex[:message] = excp.message
44
- nex[:klass] = excp.class.name
45
- end
46
- rulespack = nex.delete(:rulespack_id) || rulespack
47
- nex
48
- end
49
- end
50
- res[:rulespack_id] = rulespack unless rulespack.nil?
51
- if observed[:observations]
52
- res[:observed][:observations] = observed[:observations].map do |cat, key, value, time|
53
- { :category => cat, :key => key, :value => value, :time => time }
54
- end
55
- end
56
- if observed[:sdk]
57
- res[:observed][:sdk] = processed_sdk_calls
58
- end
59
- end
60
- res[:local] = payload['local'] if payload['local']
61
- if payload['request']
62
- res[:request] = payload['request'].dup
63
- res[:client_ip] = res[:request].delete(:client_ip) if res[:request][:client_ip]
64
- else
65
- res[:request] = {}
66
- end
67
- if payload['response']
68
- res[:response] = payload['response'].dup
69
- else
70
- res[:response] = {}
71
- end
72
-
73
- res[:request][:parameters] = payload['params'] if payload['params']
74
- res[:request][:headers] = payload['headers'] if payload['headers']
75
-
76
- res = Sqreen::EncodingSanitizer.sanitize(res)
30
+ def last_identify_args
31
+ return nil unless observed[:sdk]
77
32
 
78
- if @redactor
79
- res[:request], redacted = @redactor.redact(res[:request])
80
- if redacted.any? && res[:observed] && res[:observed][:attacks]
81
- res[:observed][:attacks] = @redactor.redact_attacks!(res[:observed][:attacks], redacted)
82
- end
83
- if redacted.any? && res[:observed] && res[:observed][:sqreen_exceptions]
84
- res[:observed][:sqreen_exceptions] = @redactor.redact_exceptions!(res[:observed][:sqreen_exceptions], redacted)
85
- end
33
+ observed[:sdk].reverse_each do |meth, _time, *args|
34
+ next unless meth == :identify
35
+ return args
86
36
  end
87
-
88
- res
37
+ nil
89
38
  end
90
39
 
91
- private
92
-
93
40
  def processed_sdk_calls
41
+ return [] unless observed[:sdk]
94
42
  auth_keys = last_identify_id
95
43
 
96
44
  observed[:sdk].map do |meth, time, *args|
@@ -102,6 +50,8 @@ module Sqreen
102
50
  end
103
51
  end
104
52
 
53
+ private
54
+
105
55
  def inject_identifiers(args, meth, auth_keys)
106
56
  return args unless meth == :track && auth_keys
107
57
 
@@ -118,13 +68,8 @@ module Sqreen
118
68
  end
119
69
 
120
70
  def last_identify_id
121
- return nil unless observed[:sdk]
122
-
123
- observed[:sdk].reverse_each do |meth, _time, *args|
124
- next unless meth == :identify
125
- return args.first if args.respond_to? :first
126
- end
127
- nil
71
+ args = last_identify_args
72
+ args.first if args.respond_to? :first
128
73
  end
129
74
  end
130
75
  end
@@ -58,12 +58,20 @@ module Sqreen
58
58
  Sqreen.log.debug { "close_request_record called. observed_items: #{observed_items}" }
59
59
 
60
60
  clean_request_record if observed_items.nil?
61
- if only_metric_observation
61
+ if Sqreen.features['use_signals'] || only_metric_observation
62
62
  push_metrics(observations_queue, queue)
63
- return clean_request_record
64
63
  end
64
+
65
+ if only_metric_observation
66
+ clean_request_record
67
+ return
68
+ end
69
+
70
+ # signals require request section to be present
71
+ payload_requests << 'request'
65
72
  payload = payload_creator.payload(payload_requests)
66
73
  payload[:observed] = observed_items
74
+
67
75
  queue.push create_request_record(payload)
68
76
  clean_request_record
69
77
  end
@@ -79,10 +87,13 @@ module Sqreen
79
87
  @redactor ||= SensitiveDataRedactor.from_config
80
88
  end
81
89
 
90
+ # pushes metric observations to the observations queue
91
+ # and clears the list for the request record
82
92
  def push_metrics(observations_queue, event_queue)
83
93
  observed_items[:observations].each do |obs|
84
94
  observations_queue.push obs
85
95
  end
96
+ observed_items[:observations] = []
86
97
  return unless observations_queue.size > MAX_OBS_QUEUE_LENGTH / 2
87
98
  event_queue.push Sqreen::METRICS_EVENT
88
99
  end
@@ -98,53 +98,66 @@ module Sqreen
98
98
  Process.clock_gettime(Process::CLOCK_MONOTONIC)
99
99
  end
100
100
 
101
- attr_reader :tag
101
+ attr_reader :tag, :size, :duration
102
102
 
103
103
  def initialize(tag, &block)
104
104
  @tag = tag
105
- @blips = []
106
105
  @block = block
107
- end
108
-
109
- def duration
110
- @blips.each_with_index.reduce(0) { |a, (e, i)| i.even? ? a - e : a + e }
106
+ @duration = 0
107
+ @size = 0
111
108
  end
112
109
 
113
110
  def elapsed
114
- @blips.each_with_index.reduce(0) { |a, (e, i)| i.even? ? a - e : a + e } + Timer.read
111
+ @duration + Timer.read
115
112
  end
116
113
 
117
114
  def ignore
118
- @blips << Timer.read
115
+ @size += 1
116
+ @duration += Timer.read
119
117
  yield(self)
120
118
  ensure
121
- @blips << Timer.read
119
+ @size += 1
120
+ @duration -= Timer.read
122
121
  end
123
122
 
124
- def measure
125
- @blips << Timer.read
123
+ def measure(opts = nil)
124
+ now = Timer.read
125
+ ignore = opts[:ignore] if opts
126
+ if ignore
127
+ ignore.size += 1
128
+ ignore.duration += now
129
+ end
130
+ @size += 1
131
+ @duration -= now
126
132
  yield(self)
127
133
  ensure
128
- @blips << Timer.read
134
+ now = Timer.read
135
+ if ignore
136
+ ignore.size += 1
137
+ ignore.duration -= now
138
+ end
139
+ @size += 1
140
+ @duration += now
129
141
  @block.call(self) if @block
130
- Sqreen::Graft.logger.debug { "#{@tag}: time=%.03fus" % (duration * 1_000_000) }
131
142
  end
132
143
 
133
144
  def start
134
- @blips << Timer.read
145
+ @size += 1
146
+ @duration -= Timer.read
135
147
  end
136
148
 
137
149
  def stop
138
- @blips << Timer.read
139
- end
140
-
141
- def size
142
- @blips.size
150
+ @size += 1
151
+ @duration += Timer.read
143
152
  end
144
153
 
145
154
  def to_s
146
155
  "#{@tag}: time=%.03fus" % (duration * 1_000_000)
147
156
  end
157
+
158
+ protected
159
+
160
+ attr_writer :size, :duration
148
161
  end
149
162
  end
150
163
  end
@@ -21,7 +21,7 @@ module Sqreen
21
21
  end
22
22
 
23
23
  def call(*args, &block)
24
- Sqreen::Graft.logger.debug { "[#{Process.pid}] Callback #{@name} disabled:#{disabled?}" }
24
+ # Sqreen::Graft.logger.debug { "[#{Process.pid}] Callback #{@name} disabled:#{disabled?}" } if Sqreen::Graft.logger.debug?
25
25
  return if @disabled
26
26
  @block.call(*args, &block)
27
27
  end
@@ -46,27 +46,31 @@ module Sqreen
46
46
  end
47
47
 
48
48
  def before(tag = nil, opts = {}, &block)
49
- return @before.sort_by(&:rank) if block.nil?
49
+ return @before if block.nil?
50
50
 
51
51
  @before << Callback.new(callback_name(:before, tag), opts, &block)
52
+ @before.sort_by!(&:rank)
52
53
  end
53
54
 
54
55
  def after(tag = nil, opts = {}, &block)
55
- return @after.sort_by(&:rank) if block.nil?
56
+ return @after if block.nil?
56
57
 
57
58
  @after << Callback.new(callback_name(:after, tag), opts, &block)
59
+ @after.sort_by!(&:rank)
58
60
  end
59
61
 
60
62
  def raised(tag = nil, opts = {}, &block)
61
- return @raised.sort_by(&:rank) if block.nil?
63
+ return @raised if block.nil?
62
64
 
63
65
  @raised << Callback.new(callback_name(:raised, tag), opts, &block)
66
+ @raised.sort_by!(&:rank)
64
67
  end
65
68
 
66
69
  def ensured(tag = nil, opts = {}, &block)
67
- return @ensured.sort_by(&:rank) if block.nil?
70
+ return @ensured if block.nil?
68
71
 
69
72
  @ensured << Callback.new(callback_name(:ensured, tag), opts, &block)
73
+ @ensured.sort_by!(&:rank)
70
74
  end
71
75
 
72
76
  def depends_on(&block)
@@ -112,6 +116,13 @@ module Sqreen
112
116
  end
113
117
 
114
118
  def self.wrapper(hook)
119
+ timed_hooks_proc = proc do |t|
120
+ Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:timed_hooks] << t
121
+ end
122
+ timed_callbacks_proc = proc do |t|
123
+ Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:timed_callbacks] << t
124
+ end
125
+
115
126
  Proc.new do |*args, &block|
116
127
  if Thread.current[:sqreen_hook_entered] || Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:time_budget_expended]
117
128
  if hook.point.super?
@@ -121,10 +132,12 @@ module Sqreen
121
132
  end
122
133
  end
123
134
 
124
- Timer.new(hook.point) do |t|
125
- Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:timed_hooks] << t
126
- end.measure do |chrono|
127
- Sqreen::Graft.logger.debug { "[#{Process.pid}] Hook #{hook.point} disabled:#{hook.disabled?} caller:#{Kernel.caller[2].inspect}" }
135
+ hook_point_super = hook.point.super?
136
+ logger = Sqreen::Graft.logger
137
+ logger_debug = Sqreen::Graft.logger.debug?
138
+
139
+ Timer.new(hook.point, &timed_hooks_proc).measure do |chrono|
140
+ logger.debug { "[#{Process.pid}] Hook #{hook.point} disabled:#{hook.disabled?} caller:#{Kernel.caller[2].inspect}" } if logger_debug
128
141
 
129
142
  budget = Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:time_budget]
130
143
  timer = Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:timer] if budget
@@ -143,37 +156,29 @@ module Sqreen
143
156
  # TODO: TimedHookCall TimedCallbackCall
144
157
  # TODO: TimeBoundHookCall TimeBoundCallbackCall TimeBoundFlow?
145
158
 
146
- Timer.new("#{hook.point}@before") do |t|
147
- Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:timed_hooks_before] << t
148
- end.measure do |before_chrono|
149
- hook.before.each do |c|
150
- next if c.ignore && c.ignore.call
151
-
152
- if timer && !c.mandatory
153
- remaining = budget - timer.elapsed
154
- unless remaining > 0
155
- Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:skipped_callbacks] << c && Thread.current[:sqreen_http_request][:time_budget_expended] = true
156
- next
157
- end
159
+ hook.before.each do |c|
160
+ next if c.ignore && c.ignore.call
161
+
162
+ if timer && !c.mandatory
163
+ remaining = budget - timer.elapsed
164
+ unless remaining > 0
165
+ Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:skipped_callbacks] << c && Thread.current[:sqreen_http_request][:time_budget_expended] = true
166
+ next
158
167
  end
168
+ end
159
169
 
160
- flow = catch(Ball.new) do |ball|
161
- Timer.new(c.name) do |t|
162
- Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:timed_callbacks] << t
163
- end.measure do
164
- before_chrono.ignore do
165
- c.call(CallbackCall.new(c, remaining, hooked_call.instance, hooked_call.args_passed), ball)
166
- end
167
- end
170
+ flow = catch(Ball.new) do |ball|
171
+ Timer.new(c.name, &timed_callbacks_proc).measure(ignore: chrono) do
172
+ c.call(CallbackCall.new(c, remaining, hooked_call.instance, hooked_call.args_passed), ball)
168
173
  end
174
+ end
169
175
 
170
- next unless c.flow && flow.is_a?(Flow)
171
- hooked_call.raise = flow.raise and hooked_call.raising = true if flow.raise?
172
- hooked_call.args_pass = flow.args and hooked_call.args_passing = true if flow.args?
173
- hooked_call.return = flow.return and hooked_call.returning = true if flow.return?
174
- break if flow.break?
175
- end unless hook.disabled?
176
- end
176
+ next unless c.flow && flow.is_a?(Flow)
177
+ hooked_call.raise = flow.raise and hooked_call.raising = true if flow.raise?
178
+ hooked_call.args_pass = flow.args and hooked_call.args_passing = true if flow.args?
179
+ hooked_call.return = flow.return and hooked_call.returning = true if flow.return?
180
+ break if flow.break?
181
+ end unless hook.disabled?
177
182
 
178
183
  raise hooked_call.raise if hooked_call.raising
179
184
  return hooked_call.return if hooked_call.returning
@@ -184,7 +189,7 @@ module Sqreen
184
189
 
185
190
  begin
186
191
  chrono.ignore do
187
- if hook.point.super?
192
+ if hook_point_super
188
193
  hooked_call.returned = super(*(hooked_call.args_passing ? hooked_call.args_pass : hooked_call.args_passed), &block)
189
194
  else
190
195
  hooked_call.returned = hook.point.apply(hooked_call.instance, 'sqreen_hook', *(hooked_call.args_passing ? hooked_call.args_pass : hooked_call.args_passed), &block)
@@ -195,40 +200,32 @@ module Sqreen
195
200
  Thread.current[:sqreen_hook_entered] = true
196
201
  hooked_call.raised = e
197
202
 
198
- Sqreen::Graft.logger.debug { "[#{Process.pid}] Hook #{hook.point} disabled:#{hook.disabled?} exception:#{e}" }
203
+ logger.debug { "[#{Process.pid}] Hook #{hook.point} disabled:#{hook.disabled?} exception:#{e}" } if logger_debug
199
204
  raise if hook.raised.empty?
200
205
 
201
- Timer.new("#{hook.point}@raised") do |t|
202
- Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:timed_hooks_raised] << t
203
- end.measure do |raised_chrono|
204
- hook.raised.each do |c|
205
- next if c.ignore && c.ignore.call
206
-
207
- if timer && !c.mandatory
208
- remaining = budget - timer.elapsed
209
- unless remaining > 0
210
- Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:skipped_callbacks] << c && Thread.current[:sqreen_http_request][:time_budget_expended] = true
211
- next
212
- end
206
+ hook.raised.each do |c|
207
+ next if c.ignore && c.ignore.call
208
+
209
+ if timer && !c.mandatory
210
+ remaining = budget - timer.elapsed
211
+ unless remaining > 0
212
+ Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:skipped_callbacks] << c && Thread.current[:sqreen_http_request][:time_budget_expended] = true
213
+ next
213
214
  end
215
+ end
214
216
 
215
- flow = catch(Ball.new) do |ball|
216
- Timer.new(c.name) do |t|
217
- Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:timed_callbacks] << t
218
- end.measure do
219
- raised_chrono.ignore do
220
- 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)
221
- end
222
- end
217
+ flow = catch(Ball.new) do |ball|
218
+ Timer.new(c.name, &timed_callbacks_proc).measure(ignore: chrono) do
219
+ 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)
223
220
  end
221
+ end
224
222
 
225
- next unless c.flow && flow.is_a?(Flow)
226
- hooked_call.raise = flow.raise and hooked_call.raising = true if flow.raise?
227
- hooked_call.return = flow.return and hooked_call.returning = true if flow.return?
228
- hooked_call.retrying = true if flow.retry?
229
- break if flow.break?
230
- end unless hook.disabled?
231
- end
223
+ next unless c.flow && flow.is_a?(Flow)
224
+ hooked_call.raise = flow.raise and hooked_call.raising = true if flow.raise?
225
+ hooked_call.return = flow.return and hooked_call.returning = true if flow.return?
226
+ hooked_call.retrying = true if flow.retry?
227
+ break if flow.break?
228
+ end unless hook.disabled?
232
229
 
233
230
  retry if hooked_call.retrying
234
231
  raise hooked_call.raise if hooked_call.raising
@@ -238,72 +235,56 @@ module Sqreen
238
235
  timer.start if timer
239
236
  Thread.current[:sqreen_hook_entered] = true
240
237
 
241
- Timer.new("#{hook.point}@after") do |t|
242
- Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:timed_hooks_after] << t
243
- end.measure do |after_chrono|
244
- hook.after.each do |c|
245
- next if c.ignore && c.ignore.call
246
-
247
- if timer && !c.mandatory
248
- remaining = budget - timer.elapsed
249
- unless remaining > 0
250
- Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:skipped_callbacks] << c && Thread.current[:sqreen_http_request][:time_budget_expended] = true
251
- next
252
- end
238
+ hook.after.each do |c|
239
+ next if c.ignore && c.ignore.call
240
+
241
+ if timer && !c.mandatory
242
+ remaining = budget - timer.elapsed
243
+ unless remaining > 0
244
+ Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:skipped_callbacks] << c && Thread.current[:sqreen_http_request][:time_budget_expended] = true
245
+ next
253
246
  end
247
+ end
254
248
 
255
- flow = catch(Ball.new) do |ball|
256
- Timer.new(c.name) do |t|
257
- Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:timed_callbacks] << t
258
- end.measure do
259
- after_chrono.ignore do
260
- 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)
261
- end
262
- end
249
+ flow = catch(Ball.new) do |ball|
250
+ Timer.new(c.name, &timed_callbacks_proc).measure(ignore: chrono) do
251
+ 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)
263
252
  end
253
+ end
264
254
 
265
- next unless c.flow && flow.is_a?(Flow)
266
- hooked_call.raise = flow.raise and hooked_call.raising = true if flow.raise?
267
- hooked_call.return = flow.return and hooked_call.returning = true if flow.return?
268
- break if flow.break?
269
- end unless hook.disabled?
270
- end
255
+ next unless c.flow && flow.is_a?(Flow)
256
+ hooked_call.raise = flow.raise and hooked_call.raising = true if flow.raise?
257
+ hooked_call.return = flow.return and hooked_call.returning = true if flow.return?
258
+ break if flow.break?
259
+ end unless hook.disabled?
271
260
 
272
261
  raise hooked_call.raise if hooked_call.raising
273
262
  return hooked_call.returning ? hooked_call.return : hooked_call.returned
274
263
  ensure
275
264
  # TODO: timer.start if someone has thrown?
276
265
 
277
- Timer.new("#{hook.point}@ensured") do |t|
278
- Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:timed_hooks_ensured] << t
279
- end.measure do |ensured_chrono|
280
- hook.ensured.each do |c|
281
- next if c.ignore && c.ignore.call
282
-
283
- if timer && !c.mandatory
284
- remaining = budget - timer.elapsed
285
- unless remaining > 0
286
- Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:skipped_callbacks] << c && Thread.current[:sqreen_http_request][:time_budget_expended] = true
287
- next
288
- end
266
+ hook.ensured.each do |c|
267
+ next if c.ignore && c.ignore.call
268
+
269
+ if timer && !c.mandatory
270
+ remaining = budget - timer.elapsed
271
+ unless remaining > 0
272
+ Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:skipped_callbacks] << c && Thread.current[:sqreen_http_request][:time_budget_expended] = true
273
+ next
289
274
  end
275
+ end
290
276
 
291
- flow = catch(Ball.new) do |ball|
292
- Timer.new(c.name) do |t|
293
- Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:timed_callbacks] << t
294
- end.measure do
295
- ensured_chrono.ignore do
296
- 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)
297
- end
298
- end
277
+ flow = catch(Ball.new) do |ball|
278
+ Timer.new(c.name, &timed_callbacks_proc).measure(ignore: chrono) do
279
+ 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)
299
280
  end
281
+ end
300
282
 
301
- next unless c.flow && flow.is_a?(Flow)
302
- hooked_call.raise = flow.raise and hooked_call.raising = true if flow.raise?
303
- hooked_call.return = flow.return and hooked_call.returning = true if flow.return?
304
- break if flow.break?
305
- end unless hook.disabled?
306
- end
283
+ next unless c.flow && flow.is_a?(Flow)
284
+ hooked_call.raise = flow.raise and hooked_call.raising = true if flow.raise?
285
+ hooked_call.return = flow.return and hooked_call.returning = true if flow.return?
286
+ break if flow.break?
287
+ end unless hook.disabled?
307
288
 
308
289
  Thread.current[:sqreen_hook_entered] = false
309
290
  timer.stop if timer