sqreen 1.18.5-java → 1.19.3-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 (180) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/lib/sqreen/actions.rb +2 -0
  4. data/lib/sqreen/actions/actions_index.rb +16 -0
  5. data/lib/sqreen/actions/base.rb +4 -10
  6. data/lib/sqreen/actions/block_ip.rb +2 -0
  7. data/lib/sqreen/actions/block_user.rb +2 -0
  8. data/lib/sqreen/actions/ip_range_indexed_action_class.rb +4 -24
  9. data/lib/sqreen/actions/ip_ranges_index.rb +32 -11
  10. data/lib/sqreen/actions/redirect_ip.rb +2 -0
  11. data/lib/sqreen/actions/redirect_user.rb +2 -0
  12. data/lib/sqreen/actions/repository.rb +27 -8
  13. data/lib/sqreen/actions/unknown_action_type.rb +4 -0
  14. data/lib/sqreen/actions/user_action_class.rb +5 -30
  15. data/lib/sqreen/actions/users_index.rb +35 -0
  16. data/lib/sqreen/agent.rb +2 -1
  17. data/lib/sqreen/attack_blocked.rb +2 -0
  18. data/lib/sqreen/backport.rb +2 -0
  19. data/lib/sqreen/backport/clock_gettime.rb +74 -0
  20. data/lib/sqreen/backport/original_name.rb +2 -0
  21. data/lib/sqreen/binding_accessor.rb +2 -0
  22. data/lib/sqreen/binding_accessor/path_elem.rb +2 -0
  23. data/lib/sqreen/binding_accessor/transforms.rb +8 -1
  24. data/lib/sqreen/call_countable.rb +2 -0
  25. data/lib/sqreen/capped_queue.rb +2 -0
  26. data/lib/sqreen/cb.rb +2 -0
  27. data/lib/sqreen/cb_tree.rb +2 -0
  28. data/lib/sqreen/condition_evaluator.rb +2 -0
  29. data/lib/sqreen/conditionable.rb +2 -0
  30. data/lib/sqreen/configuration.rb +14 -0
  31. data/lib/sqreen/context.rb +2 -0
  32. data/lib/sqreen/default_cb.rb +2 -0
  33. data/lib/sqreen/deferred_logger.rb +2 -0
  34. data/lib/sqreen/deliveries.rb +2 -0
  35. data/lib/sqreen/deliveries/batch.rb +2 -0
  36. data/lib/sqreen/deliveries/simple.rb +2 -0
  37. data/lib/sqreen/dependency.rb +3 -1
  38. data/lib/sqreen/dependency/detector.rb +22 -14
  39. data/lib/sqreen/dependency/libsqreen.rb +4 -0
  40. data/lib/sqreen/dependency/new_relic.rb +2 -0
  41. data/lib/sqreen/dependency/rack.rb +10 -5
  42. data/lib/sqreen/dependency/rails.rb +4 -0
  43. data/lib/sqreen/dependency/sentry.rb +2 -0
  44. data/lib/sqreen/dependency/sinatra.rb +12 -1
  45. data/lib/sqreen/encoding_sanitizer.rb +2 -0
  46. data/lib/sqreen/error_handling_middleware.rb +2 -0
  47. data/lib/sqreen/event.rb +2 -0
  48. data/lib/sqreen/events/attack.rb +2 -0
  49. data/lib/sqreen/events/remote_exception.rb +2 -0
  50. data/lib/sqreen/events/request_record.rb +2 -0
  51. data/lib/sqreen/exception.rb +2 -0
  52. data/lib/sqreen/formatter_with_tid.rb +2 -0
  53. data/lib/sqreen/framework_cb.rb +2 -0
  54. data/lib/sqreen/frameworks.rb +2 -0
  55. data/lib/sqreen/frameworks/generic.rb +2 -0
  56. data/lib/sqreen/frameworks/rails.rb +1 -0
  57. data/lib/sqreen/frameworks/rails3.rb +2 -0
  58. data/lib/sqreen/frameworks/request_recorder.rb +2 -0
  59. data/lib/sqreen/frameworks/sinatra.rb +2 -0
  60. data/lib/sqreen/frameworks/sqreen_test.rb +2 -0
  61. data/lib/sqreen/graft.rb +12 -0
  62. data/lib/sqreen/graft/call.rb +150 -0
  63. data/lib/sqreen/{dependency → graft}/callback.rb +12 -4
  64. data/lib/sqreen/graft/hook.rb +316 -0
  65. data/lib/sqreen/{dependency → graft}/hook_point.rb +152 -33
  66. data/lib/sqreen/graft/hook_point_error.rb +10 -0
  67. data/lib/sqreen/invalid_signature_exception.rb +2 -0
  68. data/lib/sqreen/js.rb +2 -0
  69. data/lib/sqreen/js/call_context.rb +2 -0
  70. data/lib/sqreen/js/context_pool.rb +2 -0
  71. data/lib/sqreen/js/exec_js_runnable.rb +2 -0
  72. data/lib/sqreen/js/execjs_adapter.rb +2 -0
  73. data/lib/sqreen/js/executable_js.rb +2 -0
  74. data/lib/sqreen/js/js_service.rb +2 -0
  75. data/lib/sqreen/js/js_service_adapter.rb +2 -0
  76. data/lib/sqreen/js/mini_racer_adapter.rb +2 -0
  77. data/lib/sqreen/js/mini_racer_executable_js.rb +2 -0
  78. data/lib/sqreen/js/thread_local_exec_js_runnable.rb +2 -0
  79. data/lib/sqreen/legacy.rb +8 -0
  80. data/lib/sqreen/{instrumentation.rb → legacy/instrumentation.rb} +31 -2
  81. data/lib/sqreen/log.rb +2 -0
  82. data/lib/sqreen/log/loggable.rb +28 -0
  83. data/lib/sqreen/logger.rb +2 -0
  84. data/lib/sqreen/metrics.rb +2 -0
  85. data/lib/sqreen/metrics/average.rb +2 -0
  86. data/lib/sqreen/metrics/base.rb +2 -0
  87. data/lib/sqreen/metrics/binning.rb +2 -0
  88. data/lib/sqreen/metrics/collect.rb +2 -0
  89. data/lib/sqreen/metrics/sum.rb +2 -0
  90. data/lib/sqreen/metrics_store.rb +2 -0
  91. data/lib/sqreen/metrics_store/already_registered_metric.rb +2 -0
  92. data/lib/sqreen/metrics_store/unknown_metric.rb +2 -0
  93. data/lib/sqreen/metrics_store/unregistered_metric.rb +2 -0
  94. data/lib/sqreen/middleware.rb +2 -0
  95. data/lib/sqreen/mono_time.rb +2 -0
  96. data/lib/sqreen/node.rb +2 -0
  97. data/lib/sqreen/not_implemented_yet.rb +2 -0
  98. data/lib/sqreen/null_logger.rb +2 -0
  99. data/lib/sqreen/payload_creator.rb +2 -0
  100. data/lib/sqreen/payload_creator/header_section.rb +2 -0
  101. data/lib/sqreen/performance_notifications.rb +2 -0
  102. data/lib/sqreen/performance_notifications/binned_metrics.rb +2 -0
  103. data/lib/sqreen/performance_notifications/log.rb +2 -0
  104. data/lib/sqreen/performance_notifications/log_performance.rb +2 -0
  105. data/lib/sqreen/performance_notifications/metrics.rb +2 -0
  106. data/lib/sqreen/performance_notifications/newrelic.rb +2 -0
  107. data/lib/sqreen/prefix.rb +2 -0
  108. data/lib/sqreen/rails_middleware.rb +2 -0
  109. data/lib/sqreen/remote_command.rb +2 -0
  110. data/lib/sqreen/remote_command/failure_output.rb +5 -0
  111. data/lib/sqreen/rules.rb +2 -0
  112. data/lib/sqreen/rules/attrs.rb +2 -0
  113. data/lib/sqreen/rules/auth_track_cb.rb +2 -0
  114. data/lib/sqreen/rules/binding_accessor_matcher_cb.rb +2 -0
  115. data/lib/sqreen/rules/binding_accessor_metrics.rb +2 -0
  116. data/lib/sqreen/rules/blacklist_ips_cb.rb +2 -0
  117. data/lib/sqreen/rules/count_http_codes.rb +2 -0
  118. data/lib/sqreen/rules/crawler_user_agent_matches_cb.rb +2 -0
  119. data/lib/sqreen/rules/crawler_user_agent_matches_metrics_cb.rb +2 -0
  120. data/lib/sqreen/rules/custom_error_cb.rb +2 -0
  121. data/lib/sqreen/rules/devise_auth_track_cb.rb +2 -0
  122. data/lib/sqreen/rules/devise_signup_track_cb.rb +2 -0
  123. data/lib/sqreen/rules/execjs_cb.rb +2 -0
  124. data/lib/sqreen/rules/headers_insert_cb.rb +7 -0
  125. data/lib/sqreen/rules/matcher_rule.rb +2 -0
  126. data/lib/sqreen/rules/not_found_cb.rb +7 -0
  127. data/lib/sqreen/rules/rails_parameters_cb.rb +2 -0
  128. data/lib/sqreen/rules/record_request_context.rb +2 -0
  129. data/lib/sqreen/rules/regexp_rule_cb.rb +2 -0
  130. data/lib/sqreen/rules/rule_cb.rb +2 -0
  131. data/lib/sqreen/rules/run_req_start_actions.rb +3 -1
  132. data/lib/sqreen/rules/run_user_actions.rb +3 -1
  133. data/lib/sqreen/rules/shell_env_cb.rb +2 -0
  134. data/lib/sqreen/rules/signup_track_cb.rb +2 -0
  135. data/lib/sqreen/rules/update_request_context.rb +2 -0
  136. data/lib/sqreen/rules/url_matches_cb.rb +2 -0
  137. data/lib/sqreen/rules/user_agent_matches_cb.rb +2 -0
  138. data/lib/sqreen/rules/waf_cb.rb +30 -7
  139. data/lib/sqreen/rules/xss_cb.rb +2 -0
  140. data/lib/sqreen/run_when_called_cb.rb +2 -0
  141. data/lib/sqreen/runner.rb +25 -7
  142. data/lib/sqreen/runtime_infos.rb +2 -0
  143. data/lib/sqreen/safe_json.rb +2 -0
  144. data/lib/sqreen/sdk.rb +4 -0
  145. data/lib/sqreen/sensitive_data_redactor.rb +2 -0
  146. data/lib/sqreen/serializer.rb +2 -0
  147. data/lib/sqreen/session.rb +2 -0
  148. data/lib/sqreen/shared_storage.rb +2 -0
  149. data/lib/sqreen/shared_storage23.rb +2 -0
  150. data/lib/sqreen/shrink_wrap.rb +16 -0
  151. data/lib/sqreen/signature_verifier.rb +2 -0
  152. data/lib/sqreen/sinatra_middleware.rb +2 -0
  153. data/lib/sqreen/sqreen_signed_verifier.rb +2 -0
  154. data/lib/sqreen/token_invalid_exception.rb +2 -0
  155. data/lib/sqreen/token_not_found_exception.rb +2 -0
  156. data/lib/sqreen/trie.rb +2 -0
  157. data/lib/sqreen/unauthorized.rb +2 -0
  158. data/lib/sqreen/util.rb +5 -0
  159. data/lib/sqreen/util/capped_array.rb +2 -0
  160. data/lib/sqreen/util/capped_hash.rb +2 -0
  161. data/lib/sqreen/util/capped_string.rb +2 -0
  162. data/lib/sqreen/util/capper.rb +2 -0
  163. data/lib/sqreen/version.rb +3 -1
  164. data/lib/sqreen/waf_error.rb +2 -0
  165. data/lib/sqreen/weave.rb +12 -0
  166. data/lib/sqreen/weave/hardcoded.rb +19 -0
  167. data/lib/sqreen/weave/instrumentor.rb +48 -0
  168. data/lib/sqreen/weave/legacy.rb +12 -0
  169. data/lib/sqreen/weave/legacy/instrumentation.rb +406 -0
  170. data/lib/sqreen/web_server.rb +2 -0
  171. data/lib/sqreen/web_server/generic.rb +2 -0
  172. data/lib/sqreen/web_server/passenger.rb +2 -0
  173. data/lib/sqreen/web_server/puma.rb +2 -0
  174. data/lib/sqreen/web_server/rainbows.rb +2 -0
  175. data/lib/sqreen/web_server/thin.rb +2 -0
  176. data/lib/sqreen/web_server/unicorn.rb +2 -0
  177. data/lib/sqreen/web_server/webrick.rb +2 -0
  178. data/lib/sqreen/worker.rb +2 -0
  179. metadata +26 -7
  180. data/lib/sqreen/dependency/hook.rb +0 -102
@@ -1,3 +1,5 @@
1
+ # typed: ignore
2
+
1
3
  # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
4
  # Please refer to our terms for more information: https://www.sqreen.com/terms.html
3
5
 
@@ -1,3 +1,5 @@
1
+ # typed: ignore
2
+
1
3
  # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
4
  # Please refer to our terms for more information: https://www.sqreen.com/terms.html
3
5
 
@@ -1,3 +1,4 @@
1
+ # typed: ignore
1
2
  # frozen_string_literal: true
2
3
 
3
4
  # Copyright (c) 2015 Sqreen. All Rights Reserved.
@@ -1,3 +1,5 @@
1
+ # typed: ignore
2
+
1
3
  # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
4
  # Please refer to our terms for more information: https://www.sqreen.com/terms.html
3
5
 
@@ -1,3 +1,5 @@
1
+ # typed: ignore
2
+
1
3
  # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
4
  # Please refer to our terms for more information: https://www.sqreen.com/terms.html
3
5
 
@@ -1,3 +1,5 @@
1
+ # typed: ignore
2
+
1
3
  # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
4
  # Please refer to our terms for more information: https://www.sqreen.com/terms.html
3
5
 
@@ -1,3 +1,5 @@
1
+ # typed: true
2
+
1
3
  # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
4
  # Please refer to our terms for more information: https://www.sqreen.com/terms.html
3
5
 
@@ -0,0 +1,12 @@
1
+ # typed: strong
2
+
3
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
4
+ # Please refer to our terms for more information: https://www.sqreen.com/terms.html
5
+
6
+ require 'sqreen/log/loggable'
7
+
8
+ module Sqreen
9
+ module Graft
10
+ include Sqreen::Log::Loggable
11
+ end
12
+ end
@@ -0,0 +1,150 @@
1
+ # typed: false
2
+
3
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
4
+ # Please refer to our terms for more information: https://www.sqreen.com/terms.html
5
+
6
+ require 'sqreen/backport/clock_gettime'
7
+ require 'sqreen/graft'
8
+
9
+ module Sqreen
10
+ module Graft
11
+ CallbackCall = Struct.new(:callback, :remaining, :instance, :args, :raised, :returned)
12
+ HookedCall = Struct.new(:instance, :args_passed, :args_pass, :raised, :returned, :return, :returning, :retrying, :args_passing, :raising, :raise)
13
+
14
+ class Ball
15
+ def return(value)
16
+ Flow.return(value)
17
+ end
18
+
19
+ def args(value)
20
+ Flow.args(value)
21
+ end
22
+
23
+ def retry
24
+ Flow.retry
25
+ end
26
+
27
+ def raise(value)
28
+ Flow.raise(value)
29
+ end
30
+ end
31
+
32
+ class Flow
33
+ class << self
34
+ def return(value)
35
+ new(:return, value)
36
+ end
37
+
38
+ def args(value)
39
+ new(:args, value)
40
+ end
41
+
42
+ def retry
43
+ new(:retry)
44
+ end
45
+
46
+ def raise(value)
47
+ new(:raise, value)
48
+ end
49
+ end
50
+
51
+ def initialize(action, value, brk = false)
52
+ @action = action
53
+ @value = value
54
+ @break = brk
55
+ end
56
+
57
+ def return?
58
+ @action == :return
59
+ end
60
+
61
+ def return
62
+ @value if return?
63
+ end
64
+
65
+ def raise?
66
+ @action == :raise
67
+ end
68
+
69
+ def raise
70
+ @value if raise?
71
+ end
72
+
73
+ def args?
74
+ @action == :args
75
+ end
76
+
77
+ def args
78
+ @value if args?
79
+ end
80
+
81
+ def retry?
82
+ @action == :retry
83
+ end
84
+
85
+ def break!
86
+ @break = true
87
+
88
+ self
89
+ end
90
+
91
+ def break?
92
+ @break ? true : false
93
+ end
94
+ end
95
+
96
+ class Timer
97
+ def self.read
98
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
99
+ end
100
+
101
+ attr_reader :tag
102
+
103
+ def initialize(tag, &block)
104
+ @tag = tag
105
+ @blips = []
106
+ @block = block
107
+ end
108
+
109
+ def duration
110
+ @blips.each_with_index.reduce(0) { |a, (e, i)| i.even? ? a - e : a + e }
111
+ end
112
+
113
+ def elapsed
114
+ @blips.each_with_index.reduce(0) { |a, (e, i)| i.even? ? a - e : a + e } + Timer.read
115
+ end
116
+
117
+ def ignore
118
+ @blips << Timer.read
119
+ yield(self)
120
+ ensure
121
+ @blips << Timer.read
122
+ end
123
+
124
+ def measure
125
+ @blips << Timer.read
126
+ yield(self)
127
+ ensure
128
+ @blips << Timer.read
129
+ @block.call(self) if @block
130
+ Sqreen::Graft.logger.debug { "#{@tag}: time=%.03fus" % (duration * 1_000_000) }
131
+ end
132
+
133
+ def start
134
+ @blips << Timer.read
135
+ end
136
+
137
+ def stop
138
+ @blips << Timer.read
139
+ end
140
+
141
+ def size
142
+ @blips.size
143
+ end
144
+
145
+ def to_s
146
+ "#{@tag}: time=%.03fus" % (duration * 1_000_000)
147
+ end
148
+ end
149
+ end
150
+ end
@@ -1,19 +1,27 @@
1
+ # typed: false
2
+
1
3
  # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
4
  # Please refer to our terms for more information: https://www.sqreen.com/terms.html
3
5
 
6
+ require 'sqreen/graft'
7
+
4
8
  module Sqreen
5
- module Dependency
9
+ module Graft
6
10
  class Callback
7
- attr_reader :name
11
+ attr_reader :name, :rank, :mandatory, :flow, :ignore
8
12
 
9
- def initialize(name = nil, &block)
13
+ def initialize(name = nil, opts = {}, &block)
10
14
  @name = name
15
+ @rank = opts[:rank] || 0
16
+ @mandatory = opts[:mandatory] || false
17
+ @flow = opts[:flow] || false
18
+ @ignore = opts[:ignore] || false
11
19
  @block = block
12
20
  @disabled = false
13
21
  end
14
22
 
15
23
  def call(*args, &block)
16
- Sqreen.log.debug "[#{Process.pid}] Callback #{@name} disabled:#{disabled?}"
24
+ Sqreen::Graft.logger.debug { "[#{Process.pid}] Callback #{@name} disabled:#{disabled?}" }
17
25
  return if @disabled
18
26
  @block.call(*args, &block)
19
27
  end
@@ -0,0 +1,316 @@
1
+ # typed: false
2
+
3
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
4
+ # Please refer to our terms for more information: https://www.sqreen.com/terms.html
5
+
6
+ require 'sqreen/graft'
7
+ require 'sqreen/graft/call'
8
+ require 'sqreen/graft/callback'
9
+ require 'sqreen/graft/hook_point'
10
+
11
+ module Sqreen
12
+ module Graft
13
+ class Hook
14
+ @hooks = {}
15
+
16
+ def self.[](hook_point, strategy = :chain)
17
+ @hooks[hook_point] ||= new(hook_point, nil, strategy)
18
+ end
19
+
20
+ def self.add(hook_point, strategy = :chain, &block)
21
+ self[hook_point, strategy].add(&block)
22
+ end
23
+
24
+ attr_reader :point
25
+
26
+ def initialize(hook_point, dependency_test = nil, strategy = :chain)
27
+ @disabled = false
28
+ @point = hook_point.is_a?(HookPoint) ? hook_point : HookPoint.new(hook_point, strategy)
29
+ @before = []
30
+ @after = []
31
+ @raised = []
32
+ @ensured = []
33
+ @dependency_test = dependency_test || Proc.new { point.exist? }
34
+ end
35
+
36
+ def dependency?
37
+ @dependency_test.call if @dependency_test
38
+ end
39
+
40
+ def add(&block)
41
+ tap { instance_eval(&block) }
42
+ end
43
+
44
+ def callback_name(whence, tag = nil)
45
+ "#{point}@#{whence}" << (tag ? ":#{tag}" : "")
46
+ end
47
+
48
+ def before(tag = nil, opts = {}, &block)
49
+ return @before.sort_by(&:rank) if block.nil?
50
+
51
+ @before << Callback.new(callback_name(:before, tag), opts, &block)
52
+ end
53
+
54
+ def after(tag = nil, opts = {}, &block)
55
+ return @after.sort_by(&:rank) if block.nil?
56
+
57
+ @after << Callback.new(callback_name(:after, tag), opts, &block)
58
+ end
59
+
60
+ def raised(tag = nil, opts = {}, &block)
61
+ return @raised.sort_by(&:rank) if block.nil?
62
+
63
+ @raised << Callback.new(callback_name(:raised, tag), opts, &block)
64
+ end
65
+
66
+ def ensured(tag = nil, opts = {}, &block)
67
+ return @ensured.sort_by(&:rank) if block.nil?
68
+
69
+ @ensured << Callback.new(callback_name(:ensured, tag), opts, &block)
70
+ end
71
+
72
+ def depends_on(&block)
73
+ @dependency_test = block
74
+ end
75
+
76
+ def enable
77
+ @disabled = false
78
+ end
79
+
80
+ def disable
81
+ @disabled = true
82
+ end
83
+
84
+ def disabled?
85
+ @disabled
86
+ end
87
+
88
+ def install
89
+ unless point.exist?
90
+ Sqreen::Graft.logger.debug { "[#{Process.pid}] #{point} not found" }
91
+ return
92
+ end
93
+ Sqreen::Graft.logger.debug { "[#{Process.pid}] Hook #{point}: installing" }
94
+
95
+ point.install('sqreen_hook', &Sqreen::Graft::Hook.wrapper(self))
96
+ end
97
+
98
+ def uninstall
99
+ unless point.exist?
100
+ Sqreen::Graft.logger.debug { "[#{Process.pid}] #{point} not found" }
101
+ return
102
+ end
103
+ Sqreen::Graft.logger.debug { "[#{Process.pid}] Hook #{point}: uninstalling" }
104
+
105
+ point.uninstall('sqreen_hook', &Sqreen::Graft::Hook.wrapper(self))
106
+ end
107
+
108
+ def clear
109
+ @before = []
110
+ @after = []
111
+ @raised = []
112
+ end
113
+
114
+ def self.wrapper(hook)
115
+ Proc.new do |*args, &block|
116
+ if Thread.current[:sqreen_hook_entered] || Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:time_budget_expended]
117
+ if hook.point.super?
118
+ return super(*args, &block)
119
+ else
120
+ return hook.point.apply(self, 'sqreen_hook', *args, &block)
121
+ end
122
+ end
123
+
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}" }
128
+
129
+ budget = Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:time_budget]
130
+ timer = Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:timer] if budget
131
+ hooked_call = HookedCall.new(self, args)
132
+
133
+ begin
134
+ timer.start if timer
135
+ Thread.current[:sqreen_hook_entered] = true
136
+
137
+ # TODO: make Call have #ball to throw by cb
138
+ # TODO: can Call be the ball? r = catch(Call.new, &c)
139
+ # TODO: is catch return value a Call? a #dispatch?
140
+ # TODO: make before/after/raised return a CallbackCollection << Array (or extend with module)
141
+ # TODO: add CallbackCollection#each_with_call(instance, args) { |call| ... } ?
142
+ # TODO: HookCall x CallbackCollection#each_with_call x Flow
143
+ # TODO: TimedHookCall TimedCallbackCall
144
+ # TODO: TimeBoundHookCall TimeBoundCallbackCall TimeBoundFlow?
145
+
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
158
+ end
159
+
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
168
+ end
169
+
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
177
+
178
+ raise hooked_call.raise if hooked_call.raising
179
+ return hooked_call.return if hooked_call.returning
180
+ ensure
181
+ Thread.current[:sqreen_hook_entered] = false
182
+ timer.stop if timer
183
+ end
184
+
185
+ begin
186
+ chrono.ignore do
187
+ if hook.point.super?
188
+ hooked_call.returned = super(*(hooked_call.args_passing ? hooked_call.args_pass : hooked_call.args_passed), &block)
189
+ else
190
+ hooked_call.returned = hook.point.apply(hooked_call.instance, 'sqreen_hook', *(hooked_call.args_passing ? hooked_call.args_pass : hooked_call.args_passed), &block)
191
+ end
192
+ end
193
+ rescue ::Exception => e # rubocop:disable Lint/RescueException
194
+ timer.start if timer
195
+ Thread.current[:sqreen_hook_entered] = true
196
+ hooked_call.raised = e
197
+
198
+ Sqreen::Graft.logger.debug { "[#{Process.pid}] Hook #{hook.point} disabled:#{hook.disabled?} exception:#{e}" }
199
+ raise if hook.raised.empty?
200
+
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
213
+ end
214
+
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
223
+ end
224
+
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
232
+
233
+ retry if hooked_call.retrying
234
+ raise hooked_call.raise if hooked_call.raising
235
+ return hooked_call.return if hooked_call.returning
236
+ raise
237
+ else
238
+ timer.start if timer
239
+ Thread.current[:sqreen_hook_entered] = true
240
+
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
253
+ end
254
+
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
263
+ end
264
+
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
271
+
272
+ raise hooked_call.raise if hooked_call.raising
273
+ return hooked_call.returning ? hooked_call.return : hooked_call.returned
274
+ ensure
275
+ # TODO: timer.start if someone has thrown?
276
+
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
289
+ end
290
+
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
299
+ end
300
+
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
307
+
308
+ Thread.current[:sqreen_hook_entered] = false
309
+ timer.stop if timer
310
+ end
311
+ end # chrono
312
+ end
313
+ end
314
+ end
315
+ end
316
+ end