rookout 0.1.0 → 0.1.56

Sign up to get free protection for your applications and to get access to all the features.
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