sqreen 1.23.0 → 1.24.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -0
- data/bin/sqreen +43 -0
- data/lib/sqreen/configuration.rb +2 -0
- data/lib/sqreen/dependency/new_relic.rb +1 -1
- data/lib/sqreen/dependency/sinatra.rb +20 -0
- data/lib/sqreen/events/attack.rb +8 -0
- data/lib/sqreen/frameworks/generic.rb +12 -1
- data/lib/sqreen/graft/hook.rb +7 -295
- data/lib/sqreen/graft/hook.ruby_2.rb +305 -0
- data/lib/sqreen/graft/hook.ruby_3.rb +305 -0
- data/lib/sqreen/graft/hook_point.rb +6 -6
- data/lib/sqreen/graft/hook_point.ruby_2.rb +18 -0
- data/lib/sqreen/graft/hook_point.ruby_3.rb +19 -0
- data/lib/sqreen/rules/devise_signup_track_cb.rb +1 -1
- data/lib/sqreen/rules/rule_cb.rb +9 -0
- data/lib/sqreen/runner.rb +11 -0
- data/lib/sqreen/signals/conversions.rb +20 -4
- data/lib/sqreen/version.rb +1 -1
- data/lib/sqreen/weave/legacy/instrumentation.rb +6 -0
- metadata +15 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dea2ca186e8470cf1cec16ca8ab33156c1002d28004c3a68c2296e2ec5d9b7ed
|
4
|
+
data.tar.gz: 2722948150517f7f7c29c73fa9f49acac18266e2cc286e70907b8ff91ba535d1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ecf19e0200c0c1d9012f8140996e5c1918be31a9dcca081f302cdf05e818fe5137199489d30486eca18b814e6d98bfeda5efb1ee8103efe08d158fca5f12717
|
7
|
+
data.tar.gz: 6f01d3300a326c1504917cfe2e1a25f46020f936a5400d6b347a9a1d1001f616912fb58bffe466539ecb47ef259e233a9cc5652f6da2a1739e5c4cdd5f01949b
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,28 @@
|
|
1
|
+
## 1.24.2
|
2
|
+
|
3
|
+
* Fix kwargs for rule callbacks on Ruby 3+
|
4
|
+
* Fix properties propagation for custom events
|
5
|
+
* Fix Devise key type mismatch for signup
|
6
|
+
|
7
|
+
## 1.24.1
|
8
|
+
|
9
|
+
* Add Datadog trace keeping through sampling
|
10
|
+
* Improve Datadog correlation compatibility with Sinatra
|
11
|
+
* Improve attack event correlation with Datadog spans
|
12
|
+
|
13
|
+
## 1.24.0
|
14
|
+
|
15
|
+
* Add Sqreen event correlation with Datadog traces
|
16
|
+
|
17
|
+
## 1.23.2
|
18
|
+
|
19
|
+
* Fix compatibility with NewRelic for attack events
|
20
|
+
* Fix incorrect rule rejection despite all signature checks individually passing
|
21
|
+
|
22
|
+
## 1.23.1
|
23
|
+
|
24
|
+
* Improve compatibility with gems such as puma and graphql on Ruby 3.0
|
25
|
+
|
1
26
|
## 1.23.0
|
2
27
|
|
3
28
|
* Implement GraphQL support
|
data/bin/sqreen
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
def logger
|
4
|
+
@logger ||= Logger.new(STDOUT, level: :debug)
|
5
|
+
end
|
6
|
+
|
7
|
+
def verify(rules)
|
8
|
+
verifier = Sqreen::SqreenSignedVerifier.new
|
9
|
+
|
10
|
+
invalid_rules = rules.reject do |rule|
|
11
|
+
valid = verifier.verify(rule)
|
12
|
+
|
13
|
+
if valid
|
14
|
+
logger.debug { "rule: #{rule['name']} signed: true result: ok" }
|
15
|
+
else
|
16
|
+
logger.error { "rule: #{rule['name']} singed: true result: fail" }
|
17
|
+
end
|
18
|
+
|
19
|
+
valid
|
20
|
+
end
|
21
|
+
|
22
|
+
if invalid_rules.any?
|
23
|
+
logger.error { "weave: instrument status: abort reason: signature result: fail" }
|
24
|
+
raise Sqreen::Exception, "Signature error: rules: #{invalid_rules.map { |r| r['name'] }.inspect}"
|
25
|
+
else
|
26
|
+
logger.info { "weave: instrument rules: signed result: ok" }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def check_signature(file)
|
31
|
+
require 'json'
|
32
|
+
require 'logger'
|
33
|
+
require 'sqreen/sqreen_signed_verifier'
|
34
|
+
|
35
|
+
content = File.open(file, 'rb', &:read)
|
36
|
+
json = JSON.parse(content)
|
37
|
+
|
38
|
+
p verify(json)
|
39
|
+
end
|
40
|
+
|
41
|
+
case ARGV[0]
|
42
|
+
when 'check-signature' then check_signature(ARGV[1]) || exit(1)
|
43
|
+
end
|
data/lib/sqreen/configuration.rb
CHANGED
@@ -56,6 +56,8 @@ module Sqreen
|
|
56
56
|
:default => nil },
|
57
57
|
{ :env => :SQREEN_RULES_SIGNATURE, :name => :rules_verify_signature,
|
58
58
|
:default => true },
|
59
|
+
{ :env => :SQREEN_RULES_DUMP, :name => :rules_dump,
|
60
|
+
:default => false },
|
59
61
|
{ :env => :SQREEN_LOG_LEVEL, :name => :log_level,
|
60
62
|
:default => 'INFO', :choice => %w[UNKNOWN FATAL ERROR WARN INFO DEBUG] },
|
61
63
|
{ :env => :SQREEN_LOG_LOCATION, :name => :log_location,
|
@@ -19,7 +19,7 @@ module Sqreen
|
|
19
19
|
def ignore_sqreen_exceptions
|
20
20
|
return unless required?
|
21
21
|
|
22
|
-
NewRelic::Agent::Agent.instance.error_collector.ignore(['Sqreen::AttackBlocked'])
|
22
|
+
::NewRelic::Agent::Agent.instance.error_collector.ignore(['Sqreen::AttackBlocked'])
|
23
23
|
rescue ::Exception => e # rubocop:disable Lint/RescueException
|
24
24
|
Sqreen.log.warn "Failed ignoring AttackBlocked on NewRelic: #{e.inspect}"
|
25
25
|
end
|
@@ -61,6 +61,26 @@ module Sqreen
|
|
61
61
|
u.append(p)
|
62
62
|
end
|
63
63
|
end
|
64
|
+
|
65
|
+
insert_datadog_middleware(builder, *args, &block)
|
66
|
+
end
|
67
|
+
|
68
|
+
def insert_datadog_middleware(builder, *args, &block)
|
69
|
+
return unless defined?(Datadog) && Datadog.respond_to?(:configuration) && Datadog.configuration.instrumented_integrations.key?(:sinatra)
|
70
|
+
|
71
|
+
Datadog.configure do |c|
|
72
|
+
sinatra_config = Datadog.configuration[:sinatra]
|
73
|
+
|
74
|
+
c.use(
|
75
|
+
:rack,
|
76
|
+
service_name: sinatra_config[:service_name],
|
77
|
+
distributed_tracing: sinatra_config[:distributed_tracing],
|
78
|
+
) unless Datadog.configuration.instrumented_integrations.key?(:rack)
|
79
|
+
end
|
80
|
+
|
81
|
+
insert_middleware(builder, Datadog::Contrib::Rack::TraceMiddleware, args, block) do |p, u|
|
82
|
+
u.insert(0, p)
|
83
|
+
end
|
64
84
|
end
|
65
85
|
|
66
86
|
def wrap_middleware(middleware, *args, &block)
|
data/lib/sqreen/events/attack.rb
CHANGED
@@ -63,6 +63,14 @@ module Sqreen
|
|
63
63
|
payload['context']['backtrace']
|
64
64
|
end
|
65
65
|
|
66
|
+
def datadog_trace_id
|
67
|
+
payload['context']['datadog_trace_id']
|
68
|
+
end
|
69
|
+
|
70
|
+
def datadog_span_id
|
71
|
+
payload['context']['datadog_span_id']
|
72
|
+
end
|
73
|
+
|
66
74
|
def enqueue
|
67
75
|
Sqreen.queue.push(self)
|
68
76
|
end
|
@@ -173,7 +173,18 @@ module Sqreen
|
|
173
173
|
:remote_port => req.env['REMOTE_PORT'],
|
174
174
|
:remote_ip => remote_addr,
|
175
175
|
:client_ip => client_ip,
|
176
|
-
}
|
176
|
+
}.tap do |h|
|
177
|
+
h.merge!(
|
178
|
+
:datadog_trace_id => datadog_span.trace_id,
|
179
|
+
:datadog_span_id => datadog_span.span_id,
|
180
|
+
) if datadog_span
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def datadog_span
|
185
|
+
return unless defined?(Datadog) && (tracer = Datadog.tracer)
|
186
|
+
|
187
|
+
tracer.active_span
|
177
188
|
end
|
178
189
|
|
179
190
|
def response_infos
|
data/lib/sqreen/graft/hook.rb
CHANGED
@@ -4,9 +4,8 @@
|
|
4
4
|
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
5
5
|
|
6
6
|
require 'sqreen/graft'
|
7
|
-
require 'sqreen/graft/call'
|
8
|
-
require 'sqreen/graft/callback'
|
9
7
|
require 'sqreen/graft/hook_point'
|
8
|
+
require 'sqreen/graft/callback'
|
10
9
|
|
11
10
|
module Sqreen
|
12
11
|
module Graft
|
@@ -124,299 +123,12 @@ module Sqreen
|
|
124
123
|
@raised = []
|
125
124
|
@ensured = []
|
126
125
|
end
|
127
|
-
|
128
|
-
def self.wrapper(hook)
|
129
|
-
timed_hooks_proc = proc do |t|
|
130
|
-
if (request = Thread.current[:sqreen_http_request])
|
131
|
-
request[:timed_hooks] << t if request[:timed_level] >= 1
|
132
|
-
end
|
133
|
-
end
|
134
|
-
timed_callbacks_proc = proc do |t|
|
135
|
-
if (request = Thread.current[:sqreen_http_request])
|
136
|
-
request[:timed_callbacks] << t if request[:timed_level] >= 1
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
Proc.new do |*args, &block|
|
141
|
-
request = Thread.current[:sqreen_http_request]
|
142
|
-
|
143
|
-
if Thread.current[:sqreen_hook_entered]
|
144
|
-
if hook.point.super?
|
145
|
-
return super(*args, &block)
|
146
|
-
else
|
147
|
-
return hook.point.apply(self, 'sqreen_hook', *args, &block)
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
if request && request[:time_budget_expended] && (hook.before + hook.after + hook.raised + hook.ensured).none?(&:mandatory)
|
152
|
-
if request[:timed_level] >= 2
|
153
|
-
begin
|
154
|
-
request[:skipped_callbacks].concat(hook.before)
|
155
|
-
|
156
|
-
if hook.point.super?
|
157
|
-
return super(*args, &block)
|
158
|
-
else
|
159
|
-
return hook.point.apply(self, 'sqreen_hook', *args, &block)
|
160
|
-
end
|
161
|
-
rescue ::Exception # rubocop:disable Lint/RescueException
|
162
|
-
request[:skipped_callbacks].concat(hook.raised)
|
163
|
-
raise
|
164
|
-
else
|
165
|
-
request[:skipped_callbacks].concat(hook.after)
|
166
|
-
ensure
|
167
|
-
request[:skipped_callbacks].concat(hook.ensured)
|
168
|
-
end
|
169
|
-
else
|
170
|
-
if hook.point.super? # rubocop:disable Style/IfInsideElse
|
171
|
-
return super(*args, &block)
|
172
|
-
else
|
173
|
-
return hook.point.apply(self, 'sqreen_hook', *args, &block)
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
hook_point_super = hook.point.super?
|
179
|
-
logger = Sqreen::Graft.logger
|
180
|
-
logger_debug = Sqreen::Graft.logger.debug?
|
181
|
-
|
182
|
-
Timer.new(hook.point, &timed_hooks_proc).measure do |chrono|
|
183
|
-
# budget implies request
|
184
|
-
# TODO: make budget depend on a generic context (currently "request")
|
185
|
-
budget = request[:time_budget] if request
|
186
|
-
if budget
|
187
|
-
budget_threshold = request[:time_budget_threshold]
|
188
|
-
budget_ratio = request[:time_budget_ratio]
|
189
|
-
sqreen_timer = request[:sqreen_timer]
|
190
|
-
request_timer = request[:request_timer]
|
191
|
-
end
|
192
|
-
|
193
|
-
hooked_call = HookedCall.new(self, args)
|
194
|
-
|
195
|
-
begin
|
196
|
-
begin
|
197
|
-
sqreen_timer.start if budget
|
198
|
-
Thread.current[:sqreen_hook_entered] = true
|
199
|
-
|
200
|
-
# TODO: make Call have #ball to throw by cb
|
201
|
-
# TODO: can Call be the ball? r = catch(Call.new, &c)
|
202
|
-
# TODO: is catch return value a Call? a #dispatch?
|
203
|
-
# TODO: make before/after/raised return a CallbackCollection << Array (or extend with module)
|
204
|
-
# TODO: add CallbackCollection#each_with_call(instance, args) { |call| ... } ?
|
205
|
-
# TODO: HookCall x CallbackCollection#each_with_call x Flow
|
206
|
-
# TODO: TimedHookCall TimedCallbackCall
|
207
|
-
# TODO: TimeBoundHookCall TimeBoundCallbackCall TimeBoundFlow?
|
208
|
-
|
209
|
-
request_elapsed = request_timer.elapsed if budget
|
210
|
-
|
211
|
-
hook.before.each do |c|
|
212
|
-
next if c.ignore && c.ignore.call
|
213
|
-
|
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
|
228
|
-
end
|
229
|
-
|
230
|
-
flow = catch(Ball.new) do |ball|
|
231
|
-
Timer.new(c.name, &timed_callbacks_proc).measure(ignore: chrono) do
|
232
|
-
c.call(CallbackCall.new(c, remaining, hooked_call.instance, hooked_call.args_passed), ball)
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
next unless c.flow && flow.is_a?(Flow)
|
237
|
-
hooked_call.raise = flow.raise and hooked_call.raising = true if flow.raise?
|
238
|
-
hooked_call.args_pass = flow.args and hooked_call.args_passing = true if flow.args?
|
239
|
-
hooked_call.return = flow.return and hooked_call.returning = true if flow.return?
|
240
|
-
break if flow.break?
|
241
|
-
end unless hook.disabled?
|
242
|
-
rescue StandardError => e
|
243
|
-
Sqreen::Weave.logger.debug { "exception:#{e.class} when:before message:'#{e.message}' location:\"#{e.backtrace[0]}\"" }
|
244
|
-
Sqreen::RemoteException.record(e) if Sqreen.queue
|
245
|
-
end
|
246
|
-
|
247
|
-
raise hooked_call.raise if hooked_call.raising
|
248
|
-
return hooked_call.return if hooked_call.returning
|
249
|
-
ensure
|
250
|
-
Thread.current[:sqreen_hook_entered] = false
|
251
|
-
sqreen_timer.stop if budget
|
252
|
-
end unless hook.before.empty?
|
253
|
-
|
254
|
-
begin
|
255
|
-
chrono.ignore do
|
256
|
-
if hook_point_super
|
257
|
-
hooked_call.returned = super(*(hooked_call.args_passing ? hooked_call.args_pass : hooked_call.args_passed), &block)
|
258
|
-
else
|
259
|
-
hooked_call.returned = hook.point.apply(hooked_call.instance, 'sqreen_hook', *(hooked_call.args_passing ? hooked_call.args_pass : hooked_call.args_passed), &block)
|
260
|
-
end
|
261
|
-
end
|
262
|
-
rescue ::Exception => e # rubocop:disable Lint/RescueException
|
263
|
-
begin
|
264
|
-
sqreen_timer.start if budget
|
265
|
-
Thread.current[:sqreen_hook_entered] = true
|
266
|
-
hooked_call.raised = e
|
267
|
-
|
268
|
-
logger.debug { "[#{Process.pid}] Hook #{hook.point} disabled:#{hook.disabled?} exception:#{e}" } if logger_debug
|
269
|
-
|
270
|
-
# TODO: early escape causes raise too early then caught by ensure which mistakenly reports legit errors to sqreen
|
271
|
-
# raise if hook.raised.empty?
|
272
|
-
|
273
|
-
request_elapsed = request_timer.elapsed if budget
|
274
|
-
|
275
|
-
hook.raised.each do |c|
|
276
|
-
next if c.ignore && c.ignore.call
|
277
|
-
|
278
|
-
if budget && !c.mandatory
|
279
|
-
sqreen_elapsed = sqreen_timer.elapsed
|
280
|
-
if budget_ratio && !request[:time_budget_expended]
|
281
|
-
fixed_budget = budget_threshold
|
282
|
-
proportional_budget = (request_elapsed - sqreen_elapsed) * budget_ratio
|
283
|
-
remaining = (fixed_budget > proportional_budget ? fixed_budget : proportional_budget) - sqreen_elapsed
|
284
|
-
else
|
285
|
-
remaining = budget_threshold - sqreen_elapsed
|
286
|
-
end
|
287
|
-
unless remaining > 0
|
288
|
-
request[:skipped_callbacks] << c
|
289
|
-
request[:time_budget_expended] = true
|
290
|
-
next
|
291
|
-
end
|
292
|
-
end
|
293
|
-
|
294
|
-
flow = catch(Ball.new) do |ball|
|
295
|
-
Timer.new(c.name, &timed_callbacks_proc).measure(ignore: chrono) do
|
296
|
-
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)
|
297
|
-
end
|
298
|
-
end
|
299
|
-
|
300
|
-
next unless c.flow && flow.is_a?(Flow)
|
301
|
-
hooked_call.raise = flow.raise and hooked_call.raising = true if flow.raise?
|
302
|
-
hooked_call.return = flow.return and hooked_call.returning = true if flow.return?
|
303
|
-
hooked_call.retrying = true if flow.retry?
|
304
|
-
break if flow.break?
|
305
|
-
end unless hook.disabled?
|
306
|
-
rescue StandardError => e
|
307
|
-
Sqreen::Weave.logger.debug { "exception:#{e.class} when:raised message:'#{e.message}' location:\"#{e.backtrace[0]}\"" }
|
308
|
-
Sqreen::RemoteException.record(e) if Sqreen.queue
|
309
|
-
end
|
310
|
-
|
311
|
-
retry if hooked_call.retrying
|
312
|
-
raise hooked_call.raise if hooked_call.raising
|
313
|
-
return hooked_call.return if hooked_call.returning
|
314
|
-
raise
|
315
|
-
else
|
316
|
-
begin
|
317
|
-
sqreen_timer.start if budget
|
318
|
-
Thread.current[:sqreen_hook_entered] = true
|
319
|
-
|
320
|
-
# TODO: hooked_call.returning should be always false here?
|
321
|
-
return hooked_call.returning ? hooked_call.return : hooked_call.returned if hook.after.empty?
|
322
|
-
|
323
|
-
request_elapsed = request_timer.elapsed if budget
|
324
|
-
|
325
|
-
hook.after.each do |c|
|
326
|
-
next if c.ignore && c.ignore.call
|
327
|
-
|
328
|
-
if budget && !c.mandatory
|
329
|
-
sqreen_elapsed = sqreen_timer.elapsed
|
330
|
-
if budget_ratio && !request[:time_budget_expended]
|
331
|
-
fixed_budget = budget_threshold
|
332
|
-
proportional_budget = (request_elapsed - sqreen_elapsed) * budget_ratio
|
333
|
-
remaining = (fixed_budget > proportional_budget ? fixed_budget : proportional_budget) - sqreen_elapsed
|
334
|
-
else
|
335
|
-
remaining = budget_threshold - sqreen_elapsed
|
336
|
-
end
|
337
|
-
unless remaining > 0
|
338
|
-
request[:skipped_callbacks] << c
|
339
|
-
request[:time_budget_expended] = true
|
340
|
-
next
|
341
|
-
end
|
342
|
-
end
|
343
|
-
|
344
|
-
flow = catch(Ball.new) do |ball|
|
345
|
-
Timer.new(c.name, &timed_callbacks_proc).measure(ignore: chrono) do
|
346
|
-
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)
|
347
|
-
end
|
348
|
-
end
|
349
|
-
|
350
|
-
next unless c.flow && flow.is_a?(Flow)
|
351
|
-
hooked_call.raise = flow.raise and hooked_call.raising = true if flow.raise?
|
352
|
-
hooked_call.return = flow.return and hooked_call.returning = true if flow.return?
|
353
|
-
break if flow.break?
|
354
|
-
end unless hook.disabled?
|
355
|
-
rescue StandardError => e
|
356
|
-
Sqreen::Weave.logger.debug { "exception:#{e.class} when:after message:'#{e.message}' location:\"#{e.backtrace[0]}\"" }
|
357
|
-
Sqreen::RemoteException.record(e) if Sqreen.queue
|
358
|
-
end
|
359
|
-
|
360
|
-
raise hooked_call.raise if hooked_call.raising
|
361
|
-
return hooked_call.returning ? hooked_call.return : hooked_call.returned
|
362
|
-
ensure
|
363
|
-
begin
|
364
|
-
# TODO: sqreen_timer.start if someone has thrown?
|
365
|
-
# TODO: sqreen_timer.stop at end of rescue+else?
|
366
|
-
# TODO: Thread.current[:sqreen_hook_entered] = true if neither rescue nor else ie thrown?
|
367
|
-
# TODO: Thread.current[:sqreen_hook_entered] = false at end of rescue+else? (risky?)
|
368
|
-
|
369
|
-
# TODO: uniform early bail out? (but don't forget sqreen_hook_entered and sqreen_timer)
|
370
|
-
# return hooked_call.returning ? hooked_call.return : hooked_call.returned if hook.ensured.empty?
|
371
|
-
|
372
|
-
# done at either rescue or else
|
373
|
-
# request_elapsed = request_timer.elapsed if budget # && !hook.ensured.empty?
|
374
|
-
|
375
|
-
hook.ensured.each do |c|
|
376
|
-
next if c.ignore && c.ignore.call
|
377
|
-
|
378
|
-
if budget && !c.mandatory
|
379
|
-
sqreen_elapsed = sqreen_timer.elapsed
|
380
|
-
if budget_ratio && !request[:time_budget_expended]
|
381
|
-
fixed_budget = budget_threshold
|
382
|
-
proportional_budget = (request_elapsed - sqreen_elapsed) * budget_ratio
|
383
|
-
remaining = (fixed_budget > proportional_budget ? fixed_budget : proportional_budget) - sqreen_elapsed
|
384
|
-
else
|
385
|
-
remaining = budget_threshold - sqreen_elapsed
|
386
|
-
end
|
387
|
-
unless remaining > 0
|
388
|
-
request[:skipped_callbacks] << c
|
389
|
-
request[:time_budget_expended] = true
|
390
|
-
next
|
391
|
-
end
|
392
|
-
end
|
393
|
-
|
394
|
-
flow = catch(Ball.new) do |ball|
|
395
|
-
Timer.new(c.name, &timed_callbacks_proc).measure(ignore: chrono) do
|
396
|
-
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)
|
397
|
-
end
|
398
|
-
end
|
399
|
-
|
400
|
-
next unless c.flow && flow.is_a?(Flow)
|
401
|
-
hooked_call.raise = flow.raise and hooked_call.raising = true if flow.raise?
|
402
|
-
hooked_call.return = flow.return and hooked_call.returning = true if flow.return?
|
403
|
-
break if flow.break?
|
404
|
-
end unless hook.ensured.empty? || hook.disabled?
|
405
|
-
|
406
|
-
Thread.current[:sqreen_hook_entered] = false
|
407
|
-
sqreen_timer.stop if budget
|
408
|
-
rescue StandardError => e
|
409
|
-
Sqreen::Weave.logger.debug { "exception:#{e.class} when:ensured message:'#{e.message}' location:\"#{e.backtrace[0]}\"" }
|
410
|
-
Sqreen::RemoteException.record(e) if Sqreen.queue
|
411
|
-
end
|
412
|
-
|
413
|
-
# TODO: should we run the following?
|
414
|
-
# raise hooked_call.raise if hooked_call.raising
|
415
|
-
# return hooked_call.returning ? hooked_call.return : hooked_call.returned
|
416
|
-
end
|
417
|
-
end # chrono
|
418
|
-
end
|
419
|
-
end
|
420
126
|
end
|
421
127
|
end
|
422
128
|
end
|
129
|
+
|
130
|
+
if RUBY_VERSION =~ /^2\./
|
131
|
+
load File.join(__dir__, 'hook.ruby_2.rb')
|
132
|
+
else
|
133
|
+
load File.join(__dir__, 'hook.ruby_3.rb')
|
134
|
+
end
|