rookout 0.1.0 → 0.1.56

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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rookout/atfork.rb +73 -0
  3. data/lib/rookout/augs/actions/action_run_processor.rb +4 -3
  4. data/lib/rookout/augs/aug.rb +33 -91
  5. data/lib/rookout/augs/aug_factory.rb +94 -27
  6. data/lib/rookout/augs/aug_rate_limiter.rb +50 -47
  7. data/lib/rookout/augs/augs_manager.rb +3 -1
  8. data/lib/rookout/augs/conditions/condition.rb +4 -2
  9. data/lib/rookout/augs/limits_manager.rb +32 -0
  10. data/lib/rookout/augs/locations/location.rb +75 -1
  11. data/lib/rookout/augs/locations/location_exception_handler.rb +22 -0
  12. data/lib/rookout/augs/locations/location_file_line.rb +21 -5
  13. data/lib/rookout/com_ws/agent_com_ws.rb +97 -58
  14. data/lib/rookout/com_ws/backoff.rb +5 -10
  15. data/lib/rookout/com_ws/command_handler.rb +1 -1
  16. data/lib/rookout/com_ws/envelope_wrapper.rb +68 -0
  17. data/lib/rookout/com_ws/git.rb +1 -1
  18. data/lib/rookout/com_ws/information.rb +95 -4
  19. data/lib/rookout/com_ws/output.rb +69 -21
  20. data/lib/rookout/com_ws/pinger.rb +41 -0
  21. data/lib/rookout/com_ws/websocket_client.rb +173 -0
  22. data/lib/rookout/commit.rb +3 -0
  23. data/lib/rookout/config.rb +94 -18
  24. data/lib/rookout/exceptions.rb +147 -12
  25. data/lib/rookout/interface.rb +95 -32
  26. data/lib/rookout/logger.rb +39 -10
  27. data/lib/rookout/processor/namespace_serializer.rb +2 -2
  28. data/lib/rookout/processor/namespace_serializer2.rb +331 -0
  29. data/lib/rookout/processor/namespaces/container_namespace.rb +5 -0
  30. data/lib/rookout/processor/namespaces/frame_namespace.rb +20 -17
  31. data/lib/rookout/processor/namespaces/namespace.rb +3 -2
  32. data/lib/rookout/processor/namespaces/noop_namespace.rb +4 -8
  33. data/lib/rookout/processor/namespaces/ruby_object_namespace.rb +39 -22
  34. data/lib/rookout/processor/namespaces/ruby_object_serializer.rb +15 -12
  35. data/lib/rookout/processor/namespaces/ruby_utils_namespace.rb +0 -4
  36. data/lib/rookout/processor/namespaces/stack_namespace.rb +6 -4
  37. data/lib/rookout/processor/namespaces/traceback_namespace.rb +13 -9
  38. data/lib/rookout/processor/operations/set_operation.rb +6 -1
  39. data/lib/rookout/processor/paths/arithmetic_path.rb +5 -3
  40. data/lib/rookout/processor/paths/canopy/actions.rb +5 -1
  41. data/lib/rookout/processor/paths/canopy/consts.rb +6 -4
  42. data/lib/rookout/processor/paths/canopy/maps.rb +286 -286
  43. data/lib/rookout/processor/paths/canopy/markers.rb +35 -4
  44. data/lib/rookout/processor/processor_factory.rb +0 -2
  45. data/lib/rookout/processor/rook_error.rb +6 -1
  46. data/lib/rookout/protobuf/controller_info_pb.rb +1 -0
  47. data/lib/rookout/protobuf/messages_pb.rb +54 -0
  48. data/lib/rookout/protobuf/variant2_pb.rb +42 -0
  49. data/lib/rookout/protobuf/variant_pb.rb +22 -0
  50. data/lib/rookout/rookout_singleton.rb +23 -5
  51. data/lib/rookout/sanitizer.rb +22 -0
  52. data/lib/rookout/services/position.rb +92 -75
  53. data/lib/rookout/services/tracer.rb +30 -16
  54. data/lib/rookout/start.rb +12 -0
  55. data/lib/rookout/trigger_services.rb +2 -2
  56. data/lib/rookout/user_warnings.rb +2 -0
  57. data/lib/rookout/utils.rb +34 -0
  58. data/lib/rookout/version.rb +1 -2
  59. data/lib/rookout.rb +4 -0
  60. metadata +77 -51
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 17eda3a68e52adf758e353e65066c8e68e65c5df18e67299c95e111a60717260
4
- data.tar.gz: fd7cadcf2f2890130e9d92c6f56312c7c1a6bf1ad55efc84a83c39ad67f68020
3
+ metadata.gz: c8fa5b3d059bebfddb806d412ee19edc5680ace455a7e69d947533d91fb68a74
4
+ data.tar.gz: eac042dc2b354ce73a66220b6ae7623be14824e540fc306b6b84a2fc9c5b304d
5
5
  SHA512:
6
- metadata.gz: c1968166a99e6c85d7476de449bea06d7105bd9b0b71681c8c4263ccc33d88440e2a956a1d29d4681db44af1d6a8ea5e1cfb142895c182bb1388868c6f920035
7
- data.tar.gz: f805c321af5605bade4d443557b3c575d7f432afa392820c4589bc8023af8a971e7a7d72f851ff2899ae7c4aca5fd3864f4e35dd0fb5e942cc4c3e570402cbdc
6
+ metadata.gz: 28c4a962c4478dfeda21ad68e3eceb88f1bb0596a6eb885d741ab483b7ca00e34ee4827d84095b60827c46b8bd2f0adab662fc718cd0ed32fe3ac1feb6a511f1
7
+ data.tar.gz: 6f56418601b7e1fc343f6699fa9fd605860751cacec89368382c1e38fa5ab265af9a9c5ff7e7947bce8d65151365dbee01e2dfb4f4960458243345bd30aabccd
@@ -0,0 +1,73 @@
1
+ module Rookout
2
+ class ForkManager
3
+ require "singleton"
4
+ include Singleton
5
+
6
+ def initialize
7
+ @active = false
8
+ end
9
+
10
+ def activate!
11
+ @active = true
12
+ end
13
+
14
+ def disable!
15
+ @active = false
16
+ end
17
+
18
+ def active?
19
+ @active
20
+ end
21
+
22
+ def fork_hook original_fork
23
+ if block_given?
24
+ original_fork.call do
25
+ post_fork_child if active?
26
+ yield
27
+ end
28
+ else
29
+ res = original_fork.call
30
+ post_fork_child if active? && !res
31
+ res
32
+ end
33
+ end
34
+
35
+ def post_fork_child
36
+ require_relative "rookout_singleton"
37
+ require_relative "interface"
38
+
39
+ RookoutSingleton.instance.post_fork_clean
40
+ Interface.instance.stop
41
+ Interface.instance.start post_fork: true
42
+
43
+ # Disable fork handler in child process
44
+ disable!
45
+ end
46
+ end
47
+ end
48
+
49
+ alias _rookout_original_fork fork
50
+
51
+ def self.fork &block
52
+ Rookout::ForkManager.instance.fork_hook method(:_rookout_original_fork), &block
53
+ end
54
+
55
+ def fork &block
56
+ Rookout::ForkManager.instance.fork_hook method(:_rookout_original_fork), &block
57
+ end
58
+
59
+ module Kernel
60
+ alias _rookout_original_fork fork
61
+
62
+ def self.fork &block
63
+ Rookout::ForkManager.instance.fork_hook method(:_rookout_original_fork), &block
64
+ end
65
+ end
66
+
67
+ module Process
68
+ alias _rookout_original_fork fork
69
+
70
+ def self.fork &block
71
+ Rookout::ForkManager.instance.fork_hook method(:_rookout_original_fork), &block
72
+ end
73
+ end
@@ -5,6 +5,7 @@ module Rookout
5
5
  module Actions
6
6
  class ActionRunProcessor < Action
7
7
  def initialize arguments, processor_factory
8
+ super()
8
9
  @processor = processor_factory.create_processor arguments["operations"]
9
10
 
10
11
  post_operations = arguments["post_operations"]
@@ -15,12 +16,12 @@ module Rookout
15
16
  end
16
17
  end
17
18
 
18
- def execute aug_id, report_id, namespace, _output
19
+ def execute aug_id, report_id, namespace, output
19
20
  @processor.process namespace
20
- @output.send_user_message aug_id, report_id, namespace.read_attribute("store")
21
+ output.send_user_message aug_id, report_id, namespace.read_attribute("store")
21
22
  return unless @post_processor
22
23
 
23
- @output.flush_message
24
+ output.flush_message
24
25
  @post_processor.process namespace
25
26
  end
26
27
  end
@@ -1,121 +1,63 @@
1
- require_relative "../logger"
2
- require_relative "../user_warnings"
3
- require_relative "../processor/rook_error"
4
-
5
1
  module Rookout
6
2
  module Augs
7
- require "securerandom"
8
- require "concurrent-ruby/concurrent/atom"
3
+ require_relative "../utils"
9
4
 
10
5
  require_relative "../processor/namespaces/frame_namespace"
11
6
  require_relative "../processor/namespaces/stack_namespace"
12
7
  require_relative "../processor/namespaces/container_namespace"
13
8
  require_relative "../processor/namespaces/ruby_utils_namespace"
14
9
  require_relative "../processor/namespaces/noop_namespace"
15
-
16
10
  require_relative "../logger"
17
11
 
18
- MAX_LOG_CACHE_SIZE = 10
19
-
20
12
  class Aug
21
- def initialize aug_id, location, action, condition, rate_limiter, _max_aug_time, output
22
- # NOTE: max_aux_time is not implemented
23
-
13
+ def initialize aug_id, action, condition, limits_manager, _max_aug_time
24
14
  @id = aug_id
25
- @location = location
26
15
  @action = action
27
16
  @condition = condition
28
- @rate_limiter = rate_limiter
29
- @output = output
17
+ @limits_manager = limits_manager
30
18
 
19
+ @executed = false
31
20
  @enabled = true
32
21
  @status = nil
33
22
  @log_cache = []
34
23
  end
35
- end
36
-
37
- attr_reader :id
38
24
 
39
- def add_aug trigger_services
40
- @location.add_aug trigger_services, self
41
- rescue SystemExit
42
- raise
43
- rescue Exception => e
44
- message = "Exception when adding aug"
45
- Logger.instance.error message, e
46
- notify_error RookError.new e, message
47
- end
25
+ attr_reader :id
48
26
 
49
- def execute frame, extracted
50
- return unless @enabled
27
+ def execute frame_binding, stack_trace, extracted, output
28
+ return unless @enabled
51
29
 
52
- UserWarnings.with self do
53
- begin
54
- namespace = create_namespaces frame, extracted
30
+ if output.user_messages_queue_full?
31
+ output.send_output_queue_full_warning @id
32
+ return
33
+ end
55
34
 
56
- return if @condition && !@condition.evaluate(namespace)
35
+ namespace = create_namespaces frame_binding, stack_trace, extracted
36
+ return if @condition && !@condition.evaluate(namespace)
57
37
 
58
- @rate_limiter.with_limit do
59
- report_id = SecureRandom.uuid
60
- @action.execute @aug_id, report_id, namespace, @output
61
- end
62
- rescue SystemExit
63
- raise
64
- rescue Exception => e
65
- message = "Exception while processing Aug"
66
- error = RookError.new e, message
67
- notify_warning error unless silence_log? error
38
+ should_skip_limiters = @condition.nil? && !@executed
39
+ @limits_manager.with_limit should_skip_limiters do
40
+ @executed = true
41
+ report_id = Utils.uuid
42
+ Logger.instance.info "Executing aug-\t#{id} (msg ID #{report_id})"
43
+ @action.execute @id, report_id, namespace, output
68
44
  end
69
45
  end
70
- end
71
-
72
- def notify_active
73
- send_rule_status :Active
74
- end
75
-
76
- def notify_pending
77
- send_rule_status :Pending
78
- end
79
-
80
- def notify_removed
81
- send_rule_status :Deleted
82
- end
83
-
84
- def notify_error error
85
- send_rule_status :Error, error
86
- end
87
-
88
- def notify_warning error
89
- return if silence_log? error
90
- send_rule_status :Warning, error
91
- end
92
-
93
- private
94
-
95
- def create_namespaces frame, extracted
96
- ContainerNamespace.new("frame": Processor::Namespaces::FrameNamespace.new(frame[1]),
97
- "stack": Processor::Namespaces::StackNamespace.new(frame, 1),
98
- "extracted": Processor::Namespaces::ContainerNamespace.new(extracted),
99
- "store": Processor::Namespaces::ContainerNamespace.new,
100
- "temp": Processor::Namespaces::ContainerNamespace.new,
101
- "utils": Processor::Namespaces::RubyUtisNamespace.new,
102
- "trace": Processor::Namespaces::NoopNamespace.new)
103
- end
104
-
105
- def silence_log? error
106
- return true if @log_cache.length >= MAX_LOG_CACHE_SIZE || @log_cache.include(error.message)
107
-
108
- @log_cache << error.message
109
- false
110
- end
111
46
 
112
- def send_rule_status status, error = nil
113
- return unless @status != status
114
-
115
- Logger.instance.info "Updating rule status for #{@id} to #{status}"
116
- @status = status
117
-
118
- @output.send_rule_status @id, status, error
47
+ private
48
+
49
+ def create_namespaces frame_binding, stack_trace, extracted
50
+ Processor::Namespaces::ContainerNamespace.new(
51
+ "frame" => Processor::Namespaces::FrameNamespace.new(frame_binding, stack_trace[0]),
52
+ "stack" => Processor::Namespaces::StackNamespace.new(stack_trace),
53
+ "extracted" => Processor::Namespaces::ContainerNamespace.new(extracted),
54
+ "store" => Processor::Namespaces::ContainerNamespace.new,
55
+ "temp" => Processor::Namespaces::ContainerNamespace.new,
56
+ "utils" => Processor::Namespaces::RubyUtilsNamespace.new,
57
+ "trace" => Processor::Namespaces::NoopNamespace.new,
58
+ "state" => Processor::Namespaces::NoopNamespace.new
59
+ )
60
+ end
119
61
  end
120
62
  end
121
63
  end
@@ -6,7 +6,13 @@ module Rookout
6
6
 
7
7
  require_relative "actions/action_run_processor"
8
8
  require_relative "conditions/condition"
9
+ require_relative "locations/location_file_line"
10
+ require_relative "locations/location_exception_handler"
9
11
  require_relative "aug_rate_limiter"
12
+ require_relative "aug"
13
+ require_relative "limits_manager"
14
+ require_relative "../utils"
15
+ require_relative "../logger"
10
16
 
11
17
  class AugFactory
12
18
  def initialize output
@@ -16,53 +22,114 @@ module Rookout
16
22
 
17
23
  def create_aug configuration
18
24
  aug_id = configuration["id"]
19
- raise Exceptions.RookAugInvalidKey "id", configuration unless aug_id.is_a? String
20
-
21
- location_configuration = configuration["location"]
22
- raise Exceptions.RookAugInvalidKey "location", configuration unless location_configuration.is_a? Hash
23
- location = create_location location_configuration
25
+ raise Exceptions::RookAugInvalidKey.new("id", configuration) unless aug_id.is_a? String
24
26
 
25
27
  action_configuration = configuration["action"]
26
- raise Exceptions.RookAugInvalidKey "action", configuration unless action_configuration.is_a? Hash
27
- action = Actions.ActionRunProcess.new action_configuration, @factory
28
+ raise Exceptions::RookAugInvalidKey.new("action", configuration) unless action_configuration.is_a? Hash
29
+ action = Actions::ActionRunProcessor.new action_configuration, @factory
28
30
 
29
- max_aug_time = configuration["maxAugTime"] || Config.INSTRUMENTATION_MAX_AUG_TIME
31
+ max_aug_time = configuration["maxAugTime"] || Config.instrumentation_max_aug_time
30
32
 
31
33
  condition_configuration = configuration["conditional"]
32
- raise Exceptions.RookAugInvalidKey "conditional", configuration unless condition_configuration.is_a? String
33
- condition = Conditions.Condition.new condition_configuration
34
+ unless condition_configuration.nil? || condition_configuration.is_a?(String)
35
+ raise Exceptions::RookAugInvalidKey.new("conditional", configuration)
36
+ end
37
+ condition = condition_configuration.nil? ? nil : Conditions::Condition.new(condition_configuration)
34
38
 
35
- rate_limit = create_rate_limit configuration
39
+ limits_manager = create_limits_manager configuration
36
40
 
37
- Aug.new aug_id, location, action, condition, rate_limit, max_aug_time, @output
41
+ max_aug_time_ns = Utils.milliseconds_to_nanoseconds max_aug_time
42
+ aug = Aug.new aug_id, action, condition, limits_manager, max_aug_time_ns
43
+
44
+ location_configuration = configuration["location"]
45
+ raise Exceptions::RookAugInvalidKey.new("location", configuration) unless location_configuration.is_a? Hash
46
+ create_location location_configuration, aug
38
47
  end
39
48
 
40
49
  private
41
50
 
42
- def create_location configuration
51
+ def create_location configuration, aug
43
52
  name = configuration["name"]
44
- raise Exceptions.RookObjectNameMissing if name.nil?
45
- raise Exceptions.RookUnsupportedLocation if name != "file_line"
53
+ raise Exceptions::RookObjectNameMissing, configuration if name.nil?
54
+
55
+ case name
56
+ when "file_line"
57
+ Locations::LocationFileLine.new configuration, @output, aug
58
+ when "exception_handler"
59
+ Locations::LocationExceptionHandler.new configuration, @output, aug
60
+ when "log_handler"
61
+ raise Exceptions::RookUnsupportedLiveLogger
62
+ else
63
+ raise Exceptions::RookUnsupportedLocation, configuration if name != "file_line"
64
+ end
65
+ end
46
66
 
47
- Locations.LocationFileLine.new configuration, @factory
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
+ unless rate_limit.nil?
72
+ limiters.append AugRateLimiter.new(*rate_limit)
73
+ end
74
+ else
75
+ limiters.append global_rate_limiter
76
+ end
77
+
78
+ LimitsManager.new limiters
48
79
  end
49
80
 
50
- def create_rate_limit configuration
51
- window_quota = 200
52
- window_size = 5000
81
+ def global_rate_limiter
82
+ if @global_rate_limiter.nil? && Rookout::Config.global_rate_limit != ""
83
+ begin
84
+ rate_limit = parse_rate_limit Rookout::Config.global_rate_limit,
85
+ "0", 0, 0
86
+ if rate_limit.nil?
87
+ raise Exceptions::RookInvalidRateLimitConfiguration, Rookout::Config.global_rate_limit
88
+ end
89
+ rescue Exceptions::RookInvalidRateLimitConfiguration => e
90
+ Logger.instance.warning "Failed to create global rate limiter: #{e.message}"
91
+ err = Processor::RookError.new e
92
+ UserWarnings.notify_error err
93
+ return nil
94
+ end
53
95
 
54
- rate_limit = configuration["rate_limit"]
55
- if rate_limit
56
- rate_limit_splitted = rate_limit.split "/"
57
- if rate_limit_splitted.length == 2
58
- window_quota = rate_limit_splitted[0]
59
- window_size = rate_limit_splitted[1]
96
+ @global_rate_limiter = AugRateLimiter.new(*rate_limit)
97
+ Logger.instance.debug "Using global rate limiter with configuration: #{rate_limit}"
98
+ Rookout::Config.using_global_rate_limiter = true
99
+ end
100
+
101
+ @global_rate_limiter
102
+ end
103
+
104
+ def parse_rate_limit config, modifier_config, default_quota, default_window
105
+ window_quota = default_quota
106
+ window_size = default_window
107
+
108
+ unless config.nil? || config.empty?
109
+ rate_limit_split = config.split "/"
110
+ unless rate_limit_split.length == 2 && \
111
+ Utils.is_number?(rate_limit_split[0]) && \
112
+ Utils.is_number?(rate_limit_split[1])
113
+ raise Exceptions::RookInvalidRateLimitConfiguration, config
60
114
  end
115
+
116
+ window_quota = rate_limit_split[0].to_i
117
+ window_size = rate_limit_split[1].to_i
61
118
  end
62
119
 
63
- rate_limit_modifier = configuration["rateLimitModifier"] || 5
120
+ window_quota_ns = Utils.milliseconds_to_nanoseconds window_quota
121
+ window_size_ns = Utils.milliseconds_to_nanoseconds window_size
122
+ rate_limit_modifier = modifier_config.to_i || 5
123
+
124
+ if window_quota_ns == 0
125
+ return nil
126
+ end
127
+
128
+ if window_quota_ns >= window_size_ns
129
+ raise Exceptions::RookInvalidRateLimitConfiguration, config
130
+ end
64
131
 
65
- AugRateLimiter.new window_quota, window_size, rate_limit_modifier
132
+ [window_quota_ns, window_size_ns, rate_limit_modifier]
66
133
  end
67
134
  end
68
135
  end
@@ -1,61 +1,72 @@
1
1
  module Rookout
2
2
  module Augs
3
3
  require_relative "../exceptions"
4
+ require_relative "../utils"
4
5
 
5
6
  class AugRateLimiter
6
7
  def initialize quota, window_size, active_limit
7
8
  @quota = quota
9
+ @has_quota = !@quota.nil? && (@quota > 0)
8
10
  @window_size = window_size
9
- @active_weight = quota / active_limit
11
+ if active_limit > 0
12
+ @active_weight = quota / active_limit
13
+ else
14
+ @active_weight = 0
15
+ end
10
16
 
11
17
  @mutex = Mutex.new
12
18
  @active_count = 0
13
19
  @windows = {}
14
20
  end
15
21
 
16
- def with_limit start_time = nil
17
- active = false
18
- start_time ||= Time.new
19
-
20
- # If quota, verify it
21
- if @quota
22
- # Get current time
23
- now_ms = (now * 1000).to_i
24
-
25
- # Calculate window keys
26
- current_window_key = (now_ms / @window_size) * @window_size
27
- prev_window_key = current_window_key - @window_size
28
-
29
- @mutex.synchronize do
30
- # Clean old windows
31
- cleanup now_ms
32
-
33
- # Increase active count
34
- @active_count += 1
35
- active = true
36
-
37
- # If exceeding quota
38
- if current_usage(now_ms, current_window_key, prev_window_key) > @quota
39
- warning = 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
- @mutex.synchronize { record_usage current_window_key, (Time.now - start_time) * 1000 } if @quota
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
+ time_used = Utils.time_to_nanoseconds(Time.now) - now_ns
52
+ time_recorded = time_used > Config.min_rate_limit_value_ns ? time_used : Config.min_rate_limit_value_ns
53
+ @mutex.synchronize { record_usage current_window_key, time_recorded }
50
54
  end
51
- ensure
52
55
  # Reduce active count
53
- @mutex.synchronize { @active_count -= 1 } if active
56
+ @mutex.synchronize { @active_count -= 1 }
54
57
  end
55
58
 
56
59
  private
57
60
 
58
- def current_usage now_ms, current_window_key, prev_window_key
61
+ attr_reader :windows # will be used only in tests using <OBJ>.send(:windows)
62
+
63
+ def timestamp_to_window_keys now_ns
64
+ current_window_key = (now_ns / @window_size) * @window_size
65
+ prev_window_key = current_window_key - @window_size
66
+ [current_window_key, prev_window_key]
67
+ end
68
+
69
+ def current_usage now_ns, current_window_key, prev_window_key
59
70
  # Get usage information
60
71
  current_window_usage = @windows[current_window_key]
61
72
  if current_window_usage.nil?
@@ -65,7 +76,7 @@ module Rookout
65
76
  prev_window_usage = @windows[prev_window_key] || 0
66
77
 
67
78
  # Previous window weight
68
- prev_weight = 1 - (now_ms - current_window_key) / @window_size.to_f
79
+ prev_weight = 1 - ((now_ns - current_window_key) / @window_size.to_f)
69
80
 
70
81
  # Final weighted usage
71
82
  (prev_window_usage * prev_weight) + (@active_count * @active_weight) + current_window_usage
@@ -77,19 +88,11 @@ module Rookout
77
88
  return if prev_value.nil?
78
89
 
79
90
  # Add value to quota
80
- @windows[current_window_key] += max(duration, 5).to_f
91
+ @windows[current_window_key] += [duration, 5].max.to_f
81
92
  end
82
93
 
83
- def cleanup now_ms
84
- # Don't bother with contention
85
- return if @mutex.locked?
86
-
87
- @mutex.synchronize do
88
- # every 5 windows-times, clear windows older than 10 window-times
89
- if @windows.length > 10
90
- @windows.reject! { |key, _| key < (now_ms - @window_size * 5) }
91
- end
92
- end
94
+ def cleanup now_ns
95
+ @windows.reject! { |key, _| key < (now_ns - (@window_size * 5)) } if @windows.length > 10
93
96
  end
94
97
  end
95
98
  end
@@ -2,6 +2,8 @@ module Rookout
2
2
  module Augs
3
3
  require_relative "../logger"
4
4
 
5
+ require_relative "../processor/rook_error"
6
+
5
7
  require_relative "aug_factory"
6
8
 
7
9
  class AugsManager
@@ -43,7 +45,7 @@ module Rookout
43
45
  return
44
46
  end
45
47
 
46
- error = RookError.new e, message
48
+ error = Rookout::Processor::RookError.new e, message
47
49
  @output.send_rule_status aug_id, "Error", error
48
50
  return
49
51
  end
@@ -1,13 +1,15 @@
1
1
  module Rookout
2
2
  module Augs
3
3
  module Conditions
4
+ require_relative "../../processor/paths/arithmetic_path"
5
+
4
6
  class Condition
5
7
  def initialize condition
6
- @path = ArithmeticPath.new condition
8
+ @path = Processor::Paths::ArithmeticPath.new condition
7
9
  end
8
10
 
9
11
  def evaluate namespace
10
- @path.read_from(namespace).object == true
12
+ @path.read_from(namespace).obj == true
11
13
  end
12
14
  end
13
15
  end
@@ -0,0 +1,32 @@
1
+ module Rookout
2
+ module Augs
3
+ class LimitsManager
4
+ def initialize limiters
5
+ @limiters = limiters
6
+ end
7
+
8
+ def with_limit skip_limiters, start_time = nil
9
+ start_time ||= Time.now
10
+ can_execute = true
11
+ after_execute = []
12
+
13
+ @limiters.each do |limiter|
14
+ limiter_passed = limiter.before_run start_time
15
+ if limiter_passed || skip_limiters
16
+ after_execute.append -> { limiter.after_run start_time }
17
+ else
18
+ can_execute = false
19
+ end
20
+ end
21
+
22
+ if can_execute
23
+ yield
24
+ end
25
+ ensure
26
+ unless after_execute.nil?
27
+ after_execute.each(&:call)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end