rookout 0.1.38 → 0.1.41

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e7230e6476d46d4184cd1887296f946c67fcc2e5e35b3b404f9f66444ef4d964
4
- data.tar.gz: '098f43b827ae84b56adb3e19905899487d3082ce66862b1938bf823ec2cee7de'
3
+ metadata.gz: 07a2d9fa41fdf140e81f22c1a46f47bbaf5412b31d1ab62c1f59460c07113c03
4
+ data.tar.gz: 9dd40c49cc6b8417aa3424cedd26aad1b8e63813fe0e2fcc063749d03c20f602
5
5
  SHA512:
6
- metadata.gz: 81e11a89868203775659bcab8b1a9ac4141cba01ca33ab6bd3f33f71d4be46c39f2652d1b3a2c413260104cf8b215c448ba8251081bb2e389fe32c12238fe5c4
7
- data.tar.gz: 22c3bbe9a67a1cefa8cc1928c4882fb585c479bb0e36b75c4ebf9abe0c7b5839e364169347b7c37b8dd40aec14641449e7ddf55db968378e9f2bcc876c9bcf4e
6
+ metadata.gz: 7204403b2efd52cce60b533b396c93ffc963b60554d3fbf4fbc414f4a2d6a80c0ced39e7d6c6cceda6d2470ee46563cc8704871b058957599f8b6f7ad1d433ff
7
+ data.tar.gz: 2a05c92e5f984035bcbe84e5e4f2f25be8b2458032272c03fd4e94f8e94252bcaf8c11d7989c294e5a7d07773e95170bb7f479c3806945636869b2b7b491349d
@@ -10,13 +10,11 @@ module Rookout
10
10
  require_relative "../logger"
11
11
 
12
12
  class Aug
13
- def initialize aug_id, action, condition, rate_limiter, _max_aug_time
14
- # NOTE: max_aux_time is not implemented
15
-
13
+ def initialize aug_id, action, condition, limits_manager, _max_aug_time
16
14
  @id = aug_id
17
15
  @action = action
18
16
  @condition = condition
19
- @rate_limiter = rate_limiter
17
+ @limits_manager = limits_manager
20
18
 
21
19
  @enabled = true
22
20
  @status = nil
@@ -36,7 +34,7 @@ module Rookout
36
34
  namespace = create_namespaces frame, extracted
37
35
  return if @condition && !@condition.evaluate(namespace)
38
36
 
39
- @rate_limiter.with_limit do
37
+ @limits_manager.with_limit do
40
38
  report_id = Utils.uuid
41
39
  Logger.instance.info "Executing aug-\t#{id} (msg ID #{report_id})"
42
40
  @action.execute @id, report_id, namespace, output
@@ -10,7 +10,9 @@ module Rookout
10
10
  require_relative "locations/location_exception_handler"
11
11
  require_relative "aug_rate_limiter"
12
12
  require_relative "aug"
13
+ require_relative "limits_manager"
13
14
  require_relative "../utils"
15
+ require_relative "../logger"
14
16
 
15
17
  class AugFactory
16
18
  def initialize output
@@ -34,10 +36,10 @@ module Rookout
34
36
  end
35
37
  condition = condition_configuration.nil? ? nil : Conditions::Condition.new(condition_configuration)
36
38
 
37
- rate_limit = create_rate_limit configuration
39
+ limits_manager = create_limits_manager configuration
38
40
 
39
41
  max_aug_time_ns = Utils.milliseconds_to_nanoseconds max_aug_time
40
- aug = Aug.new aug_id, action, condition, rate_limit, max_aug_time_ns
42
+ aug = Aug.new aug_id, action, condition, limits_manager, max_aug_time_ns
41
43
 
42
44
  location_configuration = configuration["location"]
43
45
  raise Exceptions::RookAugInvalidKey.new("location", configuration) unless location_configuration.is_a? Hash
@@ -62,25 +64,48 @@ module Rookout
62
64
  end
63
65
  end
64
66
 
65
- def create_rate_limit configuration
66
- window_quota = 200
67
- window_size = 5000
67
+ def create_limits_manager configuration
68
+ limiters = []
69
+ if global_rate_limiter.nil?
70
+ rate_limit = parse_rate_limit configuration["rateLimit"], configuration["rateLimitModifier"], 200, 5000
71
+ limiters.append AugRateLimiter.new(*rate_limit)
72
+ else
73
+ limiters.append global_rate_limiter
74
+ end
68
75
 
69
- rate_limit = configuration["rateLimit"]
70
- if rate_limit
71
- rate_limit_splitted = rate_limit.split "/"
72
- if rate_limit_splitted.length == 2
73
- window_quota = rate_limit_splitted[0].to_i
74
- window_size = rate_limit_splitted[1].to_i
75
- end
76
+ LimitsManager.new limiters
77
+ end
78
+
79
+ def global_rate_limiter
80
+ if @global_rate_limiter.nil? && Rookout::Config.global_rate_limit != ""
81
+ rate_limit = parse_rate_limit Rookout::Config.global_rate_limit, "0", 0, 0
82
+ @global_rate_limiter = AugRateLimiter.new(*rate_limit)
83
+ Logger.instance.debug "Using global rate limiter with configuration: #{rate_limit}"
84
+ Rookout::Config.using_global_rate_limiter = true
76
85
  end
77
86
 
78
- rate_limit_modifier = configuration["rateLimitModifier"] || 5
87
+ @global_rate_limiter
88
+ end
89
+
90
+ def parse_rate_limit config, modifier_config, default_quota, default_window
91
+ window_quota = default_quota
92
+ window_size = default_window
93
+
94
+ unless config.nil? || config.empty?
95
+ rate_limit_split = config.split "/"
96
+ unless rate_limit_split.length == 2 && rate_limit_split[0].is_number? && rate_limit_split[1].is_number?
97
+ raise Exceptions::RookInvalidRateLimitConfiguration, config
98
+ end
99
+
100
+ window_quota = rate_limit_split[0].to_i
101
+ window_size = rate_limit_split[1].to_i
102
+ end
79
103
 
80
104
  window_quota_ns = Utils.milliseconds_to_nanoseconds window_quota
81
105
  window_size_ns = Utils.milliseconds_to_nanoseconds window_size
106
+ rate_limit_modifier = modifier_config.to_i || 5
82
107
 
83
- AugRateLimiter.new window_quota_ns, window_size_ns, rate_limit_modifier
108
+ [window_quota_ns, window_size_ns, rate_limit_modifier]
84
109
  end
85
110
  end
86
111
  end
@@ -8,51 +8,50 @@ module Rookout
8
8
  @quota = quota
9
9
  @has_quota = !@quota.nil? && (@quota > 0)
10
10
  @window_size = window_size
11
- @active_weight = quota / active_limit
11
+ if active_limit > 0
12
+ @active_weight = quota / active_limit
13
+ else
14
+ @active_weight = 0
15
+ end
12
16
 
13
17
  @mutex = Mutex.new
14
18
  @active_count = 0
15
19
  @windows = {}
16
20
  end
17
21
 
18
- def with_limit start_time = nil
19
- active = false
20
- start_time ||= Time.now
21
-
22
- # If quota, verify it
23
- if @has_quota
24
- # Get current time
25
- now_ns = Utils.time_to_nanoseconds start_time
26
-
27
- # Calculate window keys
28
- current_window_key, prev_window_key = timestamp_to_window_keys now_ns
29
-
30
- @mutex.synchronize do
31
- # Clean old windows
32
- cleanup now_ns
33
- # Increase active count
34
- @active_count += 1
35
- active = true
36
-
37
- # If exceeding quota
38
- if current_usage(now_ns, current_window_key, prev_window_key) > @quota
39
- warning = Processor::RookError.new Exceptions::RookRuleRateLimited.new
40
- UserWarnings.notify_warning warning
41
- return
42
- end
22
+ def before_run start_time
23
+ # If no quota, we can safely exit
24
+ unless @has_quota
25
+ return true
26
+ end
27
+ now_ns = Utils.time_to_nanoseconds start_time
28
+ current_window_key, prev_window_key = timestamp_to_window_keys now_ns
29
+
30
+ @mutex.synchronize do
31
+ # Clean old windows
32
+ cleanup now_ns
33
+ usage = current_usage now_ns, current_window_key, prev_window_key
34
+ @active_count += 1
35
+
36
+ # If exceeding quota
37
+ if usage > @quota
38
+ warning = Processor::RookError.new Exceptions::RookRuleRateLimited.create
39
+ UserWarnings.notify_warning warning
40
+ return false
43
41
  end
42
+
43
+ return true
44
44
  end
45
+ end
45
46
 
46
- begin
47
- yield
48
- ensure
49
- if @has_quota
50
- @mutex.synchronize { record_usage current_window_key, Utils.time_to_nanoseconds(Time.now) - now_ns }
51
- end
47
+ def after_run start_time
48
+ if @has_quota
49
+ now_ns = Utils.time_to_nanoseconds start_time
50
+ current_window_key, = timestamp_to_window_keys now_ns
51
+ @mutex.synchronize { record_usage current_window_key, Utils.time_to_nanoseconds(Time.now) - now_ns }
52
52
  end
53
- ensure
54
53
  # Reduce active count
55
- @mutex.synchronize { @active_count -= 1 } if active
54
+ @mutex.synchronize { @active_count -= 1 }
56
55
  end
57
56
 
58
57
  private
@@ -0,0 +1,31 @@
1
+ module Rookout
2
+ module Augs
3
+ class LimitsManager
4
+ def initialize limiters
5
+ @limiters = limiters
6
+ end
7
+
8
+ def with_limit start_time = nil
9
+ start_time ||= Time.now
10
+ can_execute = true
11
+ after_execute = []
12
+
13
+ @limiters.each do |limiter|
14
+ if limiter.before_run start_time
15
+ after_execute.append -> { limiter.after_run start_time }
16
+ else
17
+ can_execute = false
18
+ end
19
+ end
20
+
21
+ if can_execute
22
+ yield
23
+ end
24
+ ensure
25
+ unless after_execute.nil?
26
+ after_execute.each(&:call)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,3 +1,3 @@
1
1
  module Rookout
2
- COMMIT = "d0495f7919f4fa023c9192c095b24bcdfbf4c825".freeze
2
+ COMMIT = "ed682099e24a661d30178506cb58f2a25d4af877".freeze
3
3
  end
@@ -76,8 +76,18 @@ module Rookout
76
76
 
77
77
  Rookout::Config.true_values = ["y", "Y", "yes", "Yes", "YES", "true", "True", "TRUE", "1"]
78
78
 
79
+ attr_accessor :global_rate_limit
80
+ attr_accessor :using_global_rate_limiter
81
+
82
+ Rookout::Config.global_rate_limit = ""
83
+ Rookout::Config.using_global_rate_limiter = false
79
84
 
80
85
  def update_config configuration
86
+ update_var2_config configuration
87
+ update_global_rate_limit_config configuration
88
+ end
89
+
90
+ def update_var2_config configuration
81
91
  is_config_proto2 = configuration["RUBY_PROTOBUF_VERSION_2"]
82
92
  return if is_config_proto2.nil?
83
93
  is_env_proto2 = ENV["ROOKOUT_Protobuf_Version2"]
@@ -89,6 +99,18 @@ module Rookout
89
99
  end
90
100
  Logger.instance.info "Updating ROOKOUT_Protobuf_Version2 value to: #{@protobuf_version2}"
91
101
  end
102
+
103
+ def update_global_rate_limit_config configuration
104
+ global_rate_limit = ENV["ROOKOUT_GLOBAL_RATE_LIMIT"]
105
+ if global_rate_limit.nil?
106
+ global_rate_limit = configuration["RUBY_GLOBAL_RATE_LIMIT"]
107
+ end
108
+
109
+ return if global_rate_limit.nil? || global_rate_limit == ""
110
+
111
+ @global_rate_limit = global_rate_limit
112
+ Logger.instance.info "Updating global rate limit to: #{global_rate_limit}"
113
+ end
92
114
  end
93
115
  end
94
116
  end
@@ -95,13 +95,29 @@ module Rookout
95
95
  end
96
96
  end
97
97
 
98
- class RookRuleRateLimited < ToolException
98
+ class RookRuleAugRateLimited < ToolException
99
99
  def initialize
100
100
  super "Breakpoint was disabled due to rate-limiting. " \
101
101
  "For more information: https://docs.rookout.com/docs/breakpoints-tasks.html#rate-limiting"
102
102
  end
103
103
  end
104
104
 
105
+ class RookRuleGlobalRateLimited < ToolException
106
+ def initialize
107
+ super "Breakpoint was disabled due to global rate-limiting. " \
108
+ "For more information: https://docs.rookout.com/docs/breakpoints-tasks.html#rate-limiting"
109
+ end
110
+ end
111
+
112
+ class RookRuleRateLimited
113
+ def self.create
114
+ if Rookout::Config.using_global_rate_limiter
115
+ return RookRuleGlobalRateLimited.new
116
+ end
117
+ RookRuleAugRateLimited.new
118
+ end
119
+ end
120
+
105
121
  class RookInvalidToken < ToolException
106
122
  def initialize token = ""
107
123
  super "The Rookout token supplied #{token[0..6]} is not valid; please check the token and try again",
@@ -214,6 +230,15 @@ module Rookout
214
230
  end
215
231
  end
216
232
 
233
+ class RookInvalidRateLimitConfiguration < ToolException
234
+ def initialize config
235
+ super "Invalid rate limit configuration: #{config}",
236
+ {
237
+ "rate_limit_config" => config
238
+ }
239
+ end
240
+ end
241
+
217
242
  class RookUnsupportedLiveLogger < ToolException
218
243
  def initialize
219
244
  super "Live Logger is not supported. Try using Rookout Live Debugger instead."
@@ -0,0 +1,22 @@
1
+ require "set"
2
+ module Rookout
3
+ class Sanitizer
4
+ @@blacklisted_properties = Set["labels", "ROOKOUT_LABELS"]
5
+
6
+ def self.sanitize_object! obj
7
+ obj.each_key do |key|
8
+ if obj[key].is_a?(String) && !@@blacklisted_properties.include?(key.to_s)
9
+ obj[key] = obj[key].strip
10
+ end
11
+ end
12
+ end
13
+
14
+ def self.sanitize_properties!
15
+ ENV.each do |key, val|
16
+ if key.start_with?("ROOKOUT_") && !@@blacklisted_properties.include?(key.to_s)
17
+ ENV[key] = val.strip
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
data/lib/rookout/utils.rb CHANGED
@@ -18,3 +18,9 @@ module Utils
18
18
  ((10**9) * secs) + nsecs
19
19
  end
20
20
  end
21
+
22
+ class String
23
+ def is_number?
24
+ to_f.to_s == self || to_i.to_s == self
25
+ end
26
+ end
@@ -1,3 +1,3 @@
1
1
  module Rookout
2
- VERSION = "0.1.38".freeze
2
+ VERSION = "0.1.41".freeze
3
3
  end
data/lib/rookout.rb CHANGED
@@ -2,6 +2,10 @@ module Rookout
2
2
  module_function
3
3
 
4
4
  def start options = {}
5
+ require_relative "rookout/sanitizer"
6
+ Sanitizer.sanitize_object! options
7
+ Sanitizer.sanitize_properties!
8
+
5
9
  require_relative "rookout/interface"
6
10
  Interface.instance.start options
7
11
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rookout
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.38
4
+ version: 0.1.41
5
5
  platform: ruby
6
6
  authors:
7
7
  - Liran Haimovitch
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-23 00:00:00.000000000 Z
11
+ date: 2022-09-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: binding_of_caller
@@ -225,6 +225,7 @@ files:
225
225
  - lib/rookout/augs/aug_rate_limiter.rb
226
226
  - lib/rookout/augs/augs_manager.rb
227
227
  - lib/rookout/augs/conditions/condition.rb
228
+ - lib/rookout/augs/limits_manager.rb
228
229
  - lib/rookout/augs/locations/location.rb
229
230
  - lib/rookout/augs/locations/location_exception_handler.rb
230
231
  - lib/rookout/augs/locations/location_file_line.rb
@@ -273,6 +274,7 @@ files:
273
274
  - lib/rookout/protobuf/variant2_pb.rb
274
275
  - lib/rookout/protobuf/variant_pb.rb
275
276
  - lib/rookout/rookout_singleton.rb
277
+ - lib/rookout/sanitizer.rb
276
278
  - lib/rookout/services/position.rb
277
279
  - lib/rookout/services/tracer.rb
278
280
  - lib/rookout/trigger_services.rb