rookout 0.1.37 → 0.1.40

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 661b78a375817aaf8b11e7d11baa2a1a55824a4faeb7b07800b2ab77d05fb21a
4
- data.tar.gz: d2abdb693639eddc830978c88a426f8d660db1ddcc09359d190eac69e2686de2
3
+ metadata.gz: 7605e9deab6fab2b1456185132e9db8100f143e0486a6cbef13a20a368047ad1
4
+ data.tar.gz: 900c58be123cfad2b749a16dce8ed3e6fa572af1177ee3778fe9318c02a2f81b
5
5
  SHA512:
6
- metadata.gz: 4cfd877508902044f7a6a003ed6b9f4e87f24452dac85873f4281b30e17445f085f4cc7d46dea0919a6536755f01b81b67d89ce4a21eb063f97f69a51403053b
7
- data.tar.gz: 606d7c8765066bd747ab7d3ecf098c39c934f023708d7e6eef7348bded9bb5b5175b101faf548f39838408ff865b383cab876f41c39fae0c0d6c2acd8d33d036
6
+ metadata.gz: 0d4bf7792481a091c0110353cf727f44486b08dd099bba996ce83c7b05e88213f8a714dcbfb2840944876a49a8a794f2496c501c1c19ec5c341f1493ab925ace
7
+ data.tar.gz: 5069a96af2a1a11b0e7d07be6def3a42bdbf0b94658bc16ff652d06ae623295f5c9b4ea02cbee21cae3d68a236f283568d0136d04edcc51937c68c4a31ba635b
@@ -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.nil?
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 = "e56488a23c33cbe4ad104217694c08c994586597".freeze
2
+ COMMIT = "c62d573f33d1f62ad05aec7d28a4757fafb9a2b4".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 = nil
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?
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."
@@ -9,6 +9,13 @@ module Rookout
9
9
  require_relative "./namespaces/container_namespace"
10
10
  require_relative "./namespaces/traceback_namespace"
11
11
 
12
+ begin
13
+ require "hashie/mash"
14
+ MASH = ::Hashie::Mash
15
+ rescue LoadError
16
+ MASH = nil
17
+ end
18
+
12
19
  def initialize
13
20
  @string_cache = {}
14
21
  @estimated_pending_bytes = 0
@@ -98,7 +105,7 @@ module Rookout
98
105
  dump_time obj, variant
99
106
  elsif obj.class == Array
100
107
  dump_array obj, variant, current_depth, config, log_object_errors
101
- elsif obj.class == Hash
108
+ elsif obj.class == Hash || (!MASH.nil? && obj.is_a?(MASH))
102
109
  dump_hash obj, variant, current_depth, config, log_object_errors
103
110
  elsif obj.is_a? Exception
104
111
  dump_exception obj, variant, current_depth, config, log_object_errors
@@ -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.37".freeze
2
+ VERSION = "0.1.40".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.37
4
+ version: 0.1.40
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-07-24 00:00:00.000000000 Z
11
+ date: 2022-09-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: binding_of_caller
@@ -192,6 +192,20 @@ dependencies:
192
192
  - - ">="
193
193
  - !ruby/object:Gem::Version
194
194
  version: '1.0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: hashie
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: 5.0.0
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: 5.0.0
195
209
  description: rookout is the Ruby SDK for the Rookout Debugging Platform
196
210
  email:
197
211
  - support@rookout.com
@@ -211,6 +225,7 @@ files:
211
225
  - lib/rookout/augs/aug_rate_limiter.rb
212
226
  - lib/rookout/augs/augs_manager.rb
213
227
  - lib/rookout/augs/conditions/condition.rb
228
+ - lib/rookout/augs/limits_manager.rb
214
229
  - lib/rookout/augs/locations/location.rb
215
230
  - lib/rookout/augs/locations/location_exception_handler.rb
216
231
  - lib/rookout/augs/locations/location_file_line.rb
@@ -259,6 +274,7 @@ files:
259
274
  - lib/rookout/protobuf/variant2_pb.rb
260
275
  - lib/rookout/protobuf/variant_pb.rb
261
276
  - lib/rookout/rookout_singleton.rb
277
+ - lib/rookout/sanitizer.rb
262
278
  - lib/rookout/services/position.rb
263
279
  - lib/rookout/services/tracer.rb
264
280
  - lib/rookout/trigger_services.rb
@@ -285,7 +301,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
285
301
  - !ruby/object:Gem::Version
286
302
  version: '0'
287
303
  requirements: []
288
- rubygems_version: 3.1.6
304
+ rubygems_version: 3.3.7
289
305
  signing_key:
290
306
  specification_version: 4
291
307
  summary: rookout is the Ruby SDK for the Rookout Debugging Platform