rookout 0.1.24 → 0.1.28
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 +4 -4
- data/lib/rookout/augs/aug_factory.rb +7 -2
- data/lib/rookout/augs/aug_rate_limiter.rb +22 -20
- data/lib/rookout/com_ws/agent_com_ws.rb +19 -2
- data/lib/rookout/com_ws/information.rb +1 -1
- data/lib/rookout/com_ws/websocket_client.rb +1 -2
- data/lib/rookout/commit.rb +1 -1
- data/lib/rookout/interface.rb +1 -0
- data/lib/rookout/logger.rb +10 -2
- data/lib/rookout/processor/namespaces/ruby_object_namespace.rb +2 -0
- data/lib/rookout/rookout_singleton.rb +3 -2
- data/lib/rookout/services/position.rb +8 -5
- data/lib/rookout/utils.rb +11 -0
- data/lib/rookout/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3056007f4e19ad4f973d551922cc733ceb394515a2cebad17f8e6d1186b3ec79
|
4
|
+
data.tar.gz: ee4920718d14a9ac843134a6fe37afa3b5292274924a6ded0c76247d9605f695
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a7a7ae5c046fa155ba5146ef30a2e381abb439ddd0936f56f3302258f72d7ae499bc18359cd8d5156434e809fc9704b93250e383c98ed3f09f89a80b56877c71
|
7
|
+
data.tar.gz: c71d7b41cb93686cae932edab6ce62c21d79e56b1368befe548db2046a5cf366c64d48112b07d6c09b49fdb0cb05949f3ffcfe15df90f763bb75e537aef886eb
|
@@ -10,6 +10,7 @@ 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 "../utils"
|
13
14
|
|
14
15
|
class AugFactory
|
15
16
|
def initialize output
|
@@ -34,7 +35,8 @@ module Rookout
|
|
34
35
|
|
35
36
|
rate_limit = create_rate_limit configuration
|
36
37
|
|
37
|
-
|
38
|
+
max_aug_time_ns = Utils.milliseconds_to_nanoseconds max_aug_time
|
39
|
+
aug = Aug.new aug_id, action, condition, rate_limit, max_aug_time_ns
|
38
40
|
|
39
41
|
location_configuration = configuration["location"]
|
40
42
|
raise Exceptions::RookAugInvalidKey.new("location", configuration) unless location_configuration.is_a? Hash
|
@@ -72,7 +74,10 @@ module Rookout
|
|
72
74
|
|
73
75
|
rate_limit_modifier = configuration["rateLimitModifier"] || 5
|
74
76
|
|
75
|
-
|
77
|
+
window_quota_ns = Utils.milliseconds_to_nanoseconds window_quota
|
78
|
+
window_size_ns = Utils.milliseconds_to_nanoseconds window_size
|
79
|
+
|
80
|
+
AugRateLimiter.new window_quota_ns, window_size_ns, rate_limit_modifier
|
76
81
|
end
|
77
82
|
end
|
78
83
|
end
|
@@ -1,10 +1,12 @@
|
|
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
11
|
@active_weight = quota / active_limit
|
10
12
|
|
@@ -18,24 +20,22 @@ module Rookout
|
|
18
20
|
start_time ||= Time.now
|
19
21
|
|
20
22
|
# If quota, verify it
|
21
|
-
if @
|
23
|
+
if @has_quota
|
22
24
|
# Get current time
|
23
|
-
|
25
|
+
now_ns = Utils.time_to_nanoseconds start_time
|
24
26
|
|
25
27
|
# Calculate window keys
|
26
|
-
current_window_key =
|
27
|
-
prev_window_key = current_window_key - @window_size
|
28
|
+
current_window_key, prev_window_key = timestamp_to_window_keys now_ns
|
28
29
|
|
29
30
|
@mutex.synchronize do
|
30
31
|
# Clean old windows
|
31
|
-
cleanup
|
32
|
-
|
32
|
+
cleanup now_ns
|
33
33
|
# Increase active count
|
34
34
|
@active_count += 1
|
35
35
|
active = true
|
36
36
|
|
37
37
|
# If exceeding quota
|
38
|
-
if current_usage(
|
38
|
+
if current_usage(now_ns, current_window_key, prev_window_key) > @quota
|
39
39
|
warning = Processor::RookError.new Exceptions::RookRuleRateLimited.new
|
40
40
|
UserWarnings.notify_warning warning
|
41
41
|
return
|
@@ -46,7 +46,9 @@ module Rookout
|
|
46
46
|
begin
|
47
47
|
yield
|
48
48
|
ensure
|
49
|
-
|
49
|
+
if @has_quota
|
50
|
+
@mutex.synchronize { record_usage current_window_key, Utils.time_to_nanoseconds(Time.now) - now_ns }
|
51
|
+
end
|
50
52
|
end
|
51
53
|
ensure
|
52
54
|
# Reduce active count
|
@@ -55,7 +57,15 @@ module Rookout
|
|
55
57
|
|
56
58
|
private
|
57
59
|
|
58
|
-
|
60
|
+
attr_reader :windows # will be used only in tests using <OBJ>.send(:windows)
|
61
|
+
|
62
|
+
def timestamp_to_window_keys now_ns
|
63
|
+
current_window_key = (now_ns / @window_size) * @window_size
|
64
|
+
prev_window_key = current_window_key - @window_size
|
65
|
+
[current_window_key, prev_window_key]
|
66
|
+
end
|
67
|
+
|
68
|
+
def current_usage now_ns, current_window_key, prev_window_key
|
59
69
|
# Get usage information
|
60
70
|
current_window_usage = @windows[current_window_key]
|
61
71
|
if current_window_usage.nil?
|
@@ -65,7 +75,7 @@ module Rookout
|
|
65
75
|
prev_window_usage = @windows[prev_window_key] || 0
|
66
76
|
|
67
77
|
# Previous window weight
|
68
|
-
prev_weight = 1 - (
|
78
|
+
prev_weight = 1 - (now_ns - current_window_key) / @window_size.to_f
|
69
79
|
|
70
80
|
# Final weighted usage
|
71
81
|
(prev_window_usage * prev_weight) + (@active_count * @active_weight) + current_window_usage
|
@@ -80,16 +90,8 @@ module Rookout
|
|
80
90
|
@windows[current_window_key] += [duration, 5].max.to_f
|
81
91
|
end
|
82
92
|
|
83
|
-
def cleanup
|
84
|
-
|
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
|
93
|
+
def cleanup now_ns
|
94
|
+
@windows.reject! { |key, _| key < (now_ns - @window_size * 5) } if @windows.length > 10
|
93
95
|
end
|
94
96
|
end
|
95
97
|
end
|
@@ -25,7 +25,7 @@ module Rookout
|
|
25
25
|
|
26
26
|
attr_reader :pending_messages
|
27
27
|
|
28
|
-
def initialize output, agent_host, agent_port, proxy, token, labels
|
28
|
+
def initialize output, agent_host, agent_port, proxy, token, labels, print_on_connect
|
29
29
|
agent_host_with_protocl = agent_host.include?("://") ? agent_host : "ws://#{agent_host}"
|
30
30
|
@uri = "#{agent_host_with_protocl}:#{agent_port}/v1"
|
31
31
|
if proxy.nil? || proxy.empty?
|
@@ -48,6 +48,8 @@ module Rookout
|
|
48
48
|
@running = false
|
49
49
|
@ready_event = Concurrent::Event.new
|
50
50
|
once("Com::Rookout::InitialAugsCommand") { @ready_event.set }
|
51
|
+
|
52
|
+
@print_on_initial_connection = print_on_connect
|
51
53
|
end
|
52
54
|
|
53
55
|
def add message
|
@@ -101,6 +103,7 @@ module Rookout
|
|
101
103
|
|
102
104
|
private
|
103
105
|
|
106
|
+
# rubocop:disable Style/StderrPuts
|
104
107
|
def connection_thread
|
105
108
|
backoff = Backoff.new
|
106
109
|
|
@@ -108,6 +111,10 @@ module Rookout
|
|
108
111
|
begin
|
109
112
|
client = open_new_connection
|
110
113
|
|
114
|
+
if @print_on_initial_connection
|
115
|
+
@print_on_initial_connection = false
|
116
|
+
STDERR.puts "[Rookout] Successfully connected to controller"
|
117
|
+
end
|
111
118
|
Logger.instance.debug "WebSocket connected successfully"
|
112
119
|
Logger.instance.info "Finished initialization"
|
113
120
|
|
@@ -127,7 +134,10 @@ module Rookout
|
|
127
134
|
backoff.after_disconnect
|
128
135
|
Logger.instance.debug "Reconnecting"
|
129
136
|
end
|
137
|
+
rescue Exception => e
|
138
|
+
Logger.instance.error "Unexpected error in connection_thread", e
|
130
139
|
end
|
140
|
+
# rubocop:enable Style/StderrPuts
|
131
141
|
|
132
142
|
def open_new_connection
|
133
143
|
client = WebsocketClient.new @uri, @proxy, @token
|
@@ -149,7 +159,14 @@ module Rookout
|
|
149
159
|
].freeze
|
150
160
|
|
151
161
|
def connection_pump client
|
152
|
-
on_outgoing_exit = proc {
|
162
|
+
on_outgoing_exit = proc {
|
163
|
+
begin
|
164
|
+
client.close
|
165
|
+
rescue Exception => e
|
166
|
+
Logger.instance.error "Unexpected error exiting outgoing thread", e
|
167
|
+
end
|
168
|
+
}
|
169
|
+
|
153
170
|
@outgoing_thread = Thread.new { outgoing client, on_outgoing_exit }
|
154
171
|
@outgoing_thread.name = "rookout-outgoing-thread"
|
155
172
|
|
@@ -17,7 +17,7 @@ module Rookout
|
|
17
17
|
@labels["rookout_debug"] = "on" if Config.debug
|
18
18
|
|
19
19
|
k8_namespace = create_cluster_namespace k8s_file_path
|
20
|
-
unless k8_namespace == ""
|
20
|
+
unless k8_namespace == "" || @labels.key?("k8s_namespace")
|
21
21
|
@labels["k8s_namespace"] = k8_namespace
|
22
22
|
end
|
23
23
|
|
@@ -5,7 +5,6 @@ module Rookout
|
|
5
5
|
require "uri"
|
6
6
|
|
7
7
|
require_relative "../config"
|
8
|
-
require_relative "../logger"
|
9
8
|
require_relative "../exceptions"
|
10
9
|
|
11
10
|
class WebsocketClient
|
@@ -65,7 +64,7 @@ module Rookout
|
|
65
64
|
|
66
65
|
begin
|
67
66
|
@driver.close
|
68
|
-
rescue RuntimeError, Errno::EPIPE
|
67
|
+
rescue RuntimeError, Errno::EPIPE, OpenSSL::OpenSSLError
|
69
68
|
# Protocol close may fail if the connection is already closed
|
70
69
|
nil
|
71
70
|
end
|
data/lib/rookout/commit.rb
CHANGED
data/lib/rookout/interface.rb
CHANGED
data/lib/rookout/logger.rb
CHANGED
@@ -99,6 +99,7 @@ module Rookout
|
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
102
|
+
# rubocop:disable Style/RescueStandardError
|
102
103
|
def log level, message, args
|
103
104
|
level_no = LOG_LEVELS.index level
|
104
105
|
if level_no.nil?
|
@@ -110,11 +111,18 @@ module Rookout
|
|
110
111
|
|
111
112
|
record = LogRecord.new level, message, args
|
112
113
|
@handlers.each { |handler| handler.call record }
|
114
|
+
rescue
|
115
|
+
# Log may never throw
|
116
|
+
nil
|
113
117
|
end
|
118
|
+
# rubocop:enable Style/RescueStandardError
|
114
119
|
|
115
120
|
def build_handlers
|
116
|
-
|
117
|
-
|
121
|
+
if Config.logger_log_to_stderr
|
122
|
+
@handlers.push new_file_handler unless Config.logger_filename.nil? || Config.logger_filename.empty?
|
123
|
+
@handlers.push new_stderr_handler
|
124
|
+
end
|
125
|
+
|
118
126
|
@handlers.push new_remote_handler
|
119
127
|
end
|
120
128
|
|
@@ -40,7 +40,8 @@ module Rookout
|
|
40
40
|
@services_started = false
|
41
41
|
end
|
42
42
|
|
43
|
-
def connect token: nil, host: nil, port: nil, proxy: nil, labels: [], async_start: false, fork: false
|
43
|
+
def connect token: nil, host: nil, port: nil, proxy: nil, labels: [], async_start: false, fork: false,
|
44
|
+
throw_errors: false
|
44
45
|
raise Exceptions::RookInterfaceException, "Multiple connection attempts not supported!" unless @agent_com.nil?
|
45
46
|
|
46
47
|
if fork
|
@@ -52,7 +53,7 @@ module Rookout
|
|
52
53
|
|
53
54
|
Logger.instance.debug "Initiating AgentCom-\t#{host}:#{port}"
|
54
55
|
|
55
|
-
@agent_com = ComWs::AgentComWs.new @output, host, port, proxy, token, labels
|
56
|
+
@agent_com = ComWs::AgentComWs.new @output, host, port, proxy, token, labels, !throw_errors
|
56
57
|
@output.agent_com = @agent_com
|
57
58
|
@command_handler = ComWs::CommandHandler.new @agent_com, @aug_manager
|
58
59
|
|
@@ -18,6 +18,7 @@ module Rookout
|
|
18
18
|
def initialize tracer
|
19
19
|
@tracer = tracer
|
20
20
|
@augs = {}
|
21
|
+
@augs_lock = Mutex.new
|
21
22
|
@iseqs = []
|
22
23
|
@trace_point = TracePoint.new :script_compiled do |tp|
|
23
24
|
begin
|
@@ -41,7 +42,7 @@ module Rookout
|
|
41
42
|
def add_aug location
|
42
43
|
positions = evaluate_all_scripts_to_location location
|
43
44
|
@tracer.add_breakpoint_aug positions, location unless positions.empty?
|
44
|
-
@augs[location.id] = location
|
45
|
+
@augs_lock.synchronize { @augs[location.id] = location }
|
45
46
|
end
|
46
47
|
|
47
48
|
def remove_aug aug_id
|
@@ -73,11 +74,13 @@ module Rookout
|
|
73
74
|
filename = iseq.absolute_path
|
74
75
|
return if filename.nil?
|
75
76
|
|
76
|
-
@
|
77
|
-
|
78
|
-
|
77
|
+
@augs_lock.synchronize do
|
78
|
+
@augs.each_value do |location|
|
79
|
+
position = evaluate_script_to_location iseq, filename, location
|
80
|
+
next if position.nil?
|
79
81
|
|
80
|
-
|
82
|
+
@tracer.add_breakpoint_aug [position], location
|
83
|
+
end
|
81
84
|
end
|
82
85
|
end
|
83
86
|
|
data/lib/rookout/utils.rb
CHANGED
@@ -6,4 +6,15 @@ module Utils
|
|
6
6
|
def uuid
|
7
7
|
SecureRandom.uuid.gsub(/-/, "")
|
8
8
|
end
|
9
|
+
|
10
|
+
def milliseconds_to_nanoseconds milliseconds
|
11
|
+
nano = milliseconds * (10**6)
|
12
|
+
nano.to_i
|
13
|
+
end
|
14
|
+
|
15
|
+
def time_to_nanoseconds time_obj
|
16
|
+
secs = time_obj.to_i
|
17
|
+
nsecs = time_obj.nsec
|
18
|
+
(10**9) * secs + nsecs
|
19
|
+
end
|
9
20
|
end
|
data/lib/rookout/version.rb
CHANGED
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.
|
4
|
+
version: 0.1.28
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Liran Haimovitch
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-10-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: binding_of_caller
|
@@ -72,14 +72,14 @@ dependencies:
|
|
72
72
|
requirements:
|
73
73
|
- - '='
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: 3.
|
75
|
+
version: 3.17.3
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - '='
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 3.
|
82
|
+
version: 3.17.3
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: google-style
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|