sqreen 1.19.1 → 1.20.2

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