rookout 0.1.0 → 0.1.5
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/actions/action_run_processor.rb +3 -3
- data/lib/rookout/augs/aug.rb +24 -90
- data/lib/rookout/augs/aug_factory.rb +24 -14
- data/lib/rookout/augs/aug_rate_limiter.rb +3 -3
- data/lib/rookout/augs/augs_manager.rb +3 -1
- data/lib/rookout/augs/conditions/condition.rb +4 -2
- data/lib/rookout/augs/locations/location.rb +75 -1
- data/lib/rookout/augs/locations/location_exception_handler.rb +22 -0
- data/lib/rookout/augs/locations/location_file_line.rb +16 -4
- data/lib/rookout/com_ws/agent_com_ws.rb +28 -33
- data/lib/rookout/com_ws/information.rb +1 -1
- data/lib/rookout/com_ws/output.rb +4 -10
- data/lib/rookout/com_ws/pinger.rb +36 -0
- data/lib/rookout/com_ws/websocket_client.rb +143 -0
- data/lib/rookout/commit.rb +3 -0
- data/lib/rookout/config.rb +1 -0
- data/lib/rookout/exceptions.rb +40 -0
- data/lib/rookout/interface.rb +41 -24
- data/lib/rookout/logger.rb +16 -2
- data/lib/rookout/processor/namespace_serializer.rb +1 -1
- data/lib/rookout/processor/namespaces/frame_namespace.rb +1 -0
- data/lib/rookout/processor/namespaces/namespace.rb +2 -2
- data/lib/rookout/processor/namespaces/noop_namespace.rb +1 -1
- data/lib/rookout/processor/namespaces/ruby_object_serializer.rb +4 -3
- data/lib/rookout/processor/operations/set_operation.rb +4 -1
- data/lib/rookout/processor/paths/arithmetic_path.rb +1 -1
- data/lib/rookout/processor/paths/canopy/markers.rb +5 -2
- data/lib/rookout/rookout_singleton.rb +4 -3
- data/lib/rookout/services/position.rb +73 -73
- data/lib/rookout/services/tracer.rb +8 -5
- data/lib/rookout/trigger_services.rb +2 -2
- data/lib/rookout/user_warnings.rb +2 -0
- data/lib/rookout/utils.rb +9 -0
- data/lib/rookout/version.rb +1 -2
- metadata +37 -32
data/lib/rookout/logger.rb
CHANGED
@@ -11,6 +11,14 @@ module Rookout
|
|
11
11
|
LOG_LEVELS = [:DEBUG, :INFO, :WARNING, :ERROR].freeze
|
12
12
|
|
13
13
|
def initialize
|
14
|
+
# Detect unit tests
|
15
|
+
if ($PROGRAM_NAME.end_with?("minitest_runner.rb") ||
|
16
|
+
$PROGRAM_NAME.end_with?("tunit_or_minitest_in_folder_runner.rb")) &&
|
17
|
+
Dir.pwd.end_with?("ruby-sdk")
|
18
|
+
Config.logger_log_level = :DEBUG
|
19
|
+
Config.logger_log_to_stderr = true
|
20
|
+
end
|
21
|
+
|
14
22
|
@verbosity = LOG_LEVELS.index(Config.logger_log_level) || LOG_LEVELS.index(:INFO)
|
15
23
|
|
16
24
|
@output = nil
|
@@ -43,7 +51,6 @@ module Rookout
|
|
43
51
|
end
|
44
52
|
|
45
53
|
def exception message, exc
|
46
|
-
# TODO: REVIEW HOW TO REPORT EXCEPTIONS
|
47
54
|
error message, exc
|
48
55
|
end
|
49
56
|
|
@@ -54,7 +61,14 @@ module Rookout
|
|
54
61
|
@level = level
|
55
62
|
@time = Time.new
|
56
63
|
@message = message
|
57
|
-
@formatted_message = message % arguments
|
64
|
+
@formatted_message = @message % arguments
|
65
|
+
|
66
|
+
arguments.each do |argument|
|
67
|
+
if argument.is_a? Exception
|
68
|
+
@formatted_message += "\n" + argument.message + "\n" + argument.backtrace.join("\n\t")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
58
72
|
@arguments = arguments
|
59
73
|
set_caller
|
60
74
|
end
|
@@ -12,6 +12,7 @@ module Rookout
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def read_attribute name
|
15
|
+
return RubyObjectNamespace.new @binding.receiver if name == "self"
|
15
16
|
raise Exceptions::RookAttributeNotFound, name unless @binding.local_variable_defined? name
|
16
17
|
RubyObjectNamespace.new @binding.local_variable_get name
|
17
18
|
end
|
@@ -4,7 +4,7 @@ module Rookout
|
|
4
4
|
class Namespace
|
5
5
|
require_relative "../../exceptions"
|
6
6
|
def call_method name, _args
|
7
|
-
raise Exceptions::RookMethodNotFound
|
7
|
+
raise Exceptions::RookMethodNotFound.new(self.class.to_s, name)
|
8
8
|
end
|
9
9
|
|
10
10
|
def read_attribute name
|
@@ -12,7 +12,7 @@ module Rookout
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def write_attribute name, _value
|
15
|
-
raise Exceptions::RookWriteAttributeNotSupported
|
15
|
+
raise Exceptions::RookWriteAttributeNotSupported.new(self.class.to_s, name)
|
16
16
|
end
|
17
17
|
|
18
18
|
def read_key key
|
@@ -17,7 +17,7 @@ module Rookout
|
|
17
17
|
Logger.instance.exception message, e
|
18
18
|
|
19
19
|
error = RookError.new e, message
|
20
|
-
variant = error.dumps
|
20
|
+
variant.error_value = error.dumps
|
21
21
|
end
|
22
22
|
variant
|
23
23
|
end
|
@@ -29,7 +29,7 @@ module Rookout
|
|
29
29
|
|
30
30
|
if obj.nil?
|
31
31
|
dump_nil variant
|
32
|
-
elsif obj.is_a?(Numeric) || obj
|
32
|
+
elsif obj.is_a?(Numeric) || obj.is_a?(TrueClass) || obj.is_a?(FalseClass)
|
33
33
|
dump_numeric obj, variant
|
34
34
|
elsif obj.is_a?(String) || obj.is_a?(Symbol)
|
35
35
|
dump_string obj, variant, config
|
@@ -104,7 +104,7 @@ module Rookout
|
|
104
104
|
variant.complex_value = Com::Rookout::Variant::Complex.new real: obj.real.to_f,
|
105
105
|
imaginary: obj.imaginary.to_f
|
106
106
|
else
|
107
|
-
raise Exceptions.
|
107
|
+
raise Exceptions::RookClassCannotBeSerialized.new(obj.class, "Unknown Numeric Type")
|
108
108
|
end
|
109
109
|
# TODO: ADD SUPPORT FOR RATIONALS
|
110
110
|
end
|
@@ -123,6 +123,7 @@ module Rookout
|
|
123
123
|
end
|
124
124
|
|
125
125
|
def dump_string obj, variant, config
|
126
|
+
obj = obj.to_s
|
126
127
|
if obj.length > config.max_string
|
127
128
|
final_obj = obj[0...config.max_string]
|
128
129
|
else
|
@@ -3,6 +3,8 @@ module Rookout
|
|
3
3
|
module Operations
|
4
4
|
require_relative "operation"
|
5
5
|
|
6
|
+
require_relative "../namespaces/ruby_object_namespace"
|
7
|
+
|
6
8
|
require_relative "../rook_error"
|
7
9
|
require_relative "../../logger"
|
8
10
|
require_relative "../../user_warnings"
|
@@ -29,7 +31,8 @@ module Rookout
|
|
29
31
|
@paths.each do |dest_path, source_path|
|
30
32
|
begin
|
31
33
|
value = source_path.read_from namespace
|
32
|
-
if value.is_a?(RubyObjectNamespace) &&
|
34
|
+
if value.is_a?(Namespaces::RubyObjectNamespace) &&
|
35
|
+
value.dump_config == Namespaces::OBJECT_DUMP_CONFIG_DEFAULT
|
33
36
|
value.tailor_limits!
|
34
37
|
end
|
35
38
|
|
@@ -71,7 +71,7 @@ module Rookout
|
|
71
71
|
|
72
72
|
if result.is_a? Canopy::ToolExceptionMarker
|
73
73
|
raise result.obj if result.obj.is_a? Exceptions::ToolException
|
74
|
-
raise Exceptions::RookInvalidArithmeticPath
|
74
|
+
raise Exceptions::RookInvalidArithmeticPath.new(@raw_path, result.obj)
|
75
75
|
end
|
76
76
|
|
77
77
|
res = result.obj
|
@@ -4,6 +4,9 @@ module Rookout
|
|
4
4
|
module Canopy
|
5
5
|
require_relative "consts"
|
6
6
|
|
7
|
+
require_relative "../../../exceptions"
|
8
|
+
require_relative "../../namespaces/container_namespace"
|
9
|
+
|
7
10
|
class Marker; end
|
8
11
|
|
9
12
|
class Operation < Marker
|
@@ -12,7 +15,7 @@ module Rookout
|
|
12
15
|
end
|
13
16
|
|
14
17
|
def write _namespace, _value
|
15
|
-
raise Exception
|
18
|
+
raise Exception::RookOperationReadOnly, self.class.to_s
|
16
19
|
end
|
17
20
|
end
|
18
21
|
|
@@ -36,7 +39,7 @@ module Rookout
|
|
36
39
|
namespace.read_attribute @name
|
37
40
|
rescue Exceptions::RookAttributeNotFound
|
38
41
|
raise unless create
|
39
|
-
namespace.write_attribute name, ContainerNamespace.new
|
42
|
+
namespace.write_attribute @name, Namespaces::ContainerNamespace.new
|
40
43
|
end
|
41
44
|
|
42
45
|
def write namespace, value
|
@@ -40,7 +40,7 @@ module Rookout
|
|
40
40
|
@services_started = false
|
41
41
|
end
|
42
42
|
|
43
|
-
def connect token, host, port, proxy, labels, async_start,
|
43
|
+
def connect token: nil, host: nil, port: nil, proxy: nil, labels: [], async_start: false, **_
|
44
44
|
raise Exceptions::RookInterfaceException, "Multiple connection attempts not supported!" unless @agent_com.nil?
|
45
45
|
|
46
46
|
start_trigger_services
|
@@ -48,6 +48,7 @@ module Rookout
|
|
48
48
|
Logger.instance.debug "Initiating AgentCom-\t#{host}:#{port}"
|
49
49
|
|
50
50
|
@agent_com = ComWs::AgentComWs.new @output, host, port, proxy, token, labels
|
51
|
+
@output.agent_com = @agent_com
|
51
52
|
@command_handler = ComWs::CommandHandler.new @agent_com, @aug_manager
|
52
53
|
|
53
54
|
@agent_com.connect
|
@@ -65,8 +66,8 @@ module Rookout
|
|
65
66
|
private
|
66
67
|
|
67
68
|
def check_version_supported
|
68
|
-
raise Exceptions:: RookVersionNotSupported
|
69
|
-
raise Exceptions::RookVersionNotSupported
|
69
|
+
raise Exceptions:: RookVersionNotSupported.new("platform", RUBY_ENGINE) unless RUBY_ENGINE == "ruby"
|
70
|
+
raise Exceptions::RookVersionNotSupported.new("version", RUBY_VERSION) unless
|
70
71
|
RUBY_VERSION.start_with?("2.7") || RUBY_VERSION.start_with?("2.6")
|
71
72
|
end
|
72
73
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module Rookout
|
2
2
|
module Services
|
3
|
+
require "zlib"
|
4
|
+
|
3
5
|
require_relative "../logger"
|
4
6
|
require_relative "../exceptions"
|
5
7
|
|
@@ -16,10 +18,16 @@ module Rookout
|
|
16
18
|
def initialize tracer
|
17
19
|
@tracer = tracer
|
18
20
|
@augs = {}
|
21
|
+
@iseqs = []
|
19
22
|
@trace_point = TracePoint.new :script_compiled do |tp|
|
20
23
|
begin
|
21
24
|
begin
|
22
|
-
|
25
|
+
iseq = tp.instruction_sequence
|
26
|
+
# Ignore script without sources
|
27
|
+
if iseq.absolute_path
|
28
|
+
@iseqs << iseq
|
29
|
+
evaluate_script iseq
|
30
|
+
end
|
23
31
|
rescue Exception => e
|
24
32
|
Logger.instance.exception "Exception while evaluating script", e
|
25
33
|
end
|
@@ -30,22 +38,18 @@ module Rookout
|
|
30
38
|
@trace_point.enable
|
31
39
|
end
|
32
40
|
|
33
|
-
def add_aug location
|
34
|
-
positions =
|
35
|
-
|
36
|
-
|
37
|
-
else
|
38
|
-
@tracer.add_breakpoint_aug positions, aug
|
39
|
-
end
|
41
|
+
def add_aug location
|
42
|
+
positions = evaluate_all_scripts_to_location location
|
43
|
+
@tracer.add_breakpoint_aug positions, location unless positions.empty?
|
44
|
+
@augs[location.id] = location
|
40
45
|
end
|
41
46
|
|
42
47
|
def remove_aug aug_id
|
43
|
-
|
44
|
-
return if
|
48
|
+
location = @augs[aug_id]
|
49
|
+
return if location.nil?
|
45
50
|
|
46
51
|
@augs.delete [aug_id]
|
47
|
-
|
48
|
-
aug.notify_removed
|
52
|
+
location.notify_removed
|
49
53
|
end
|
50
54
|
|
51
55
|
def clear_augs
|
@@ -64,88 +68,47 @@ module Rookout
|
|
64
68
|
private
|
65
69
|
|
66
70
|
#########################################################################################
|
67
|
-
#
|
71
|
+
# ISEQ comparison Section
|
68
72
|
def evaluate_script iseq
|
69
73
|
filename = iseq.absolute_path
|
70
74
|
return if filename.nil?
|
71
75
|
|
72
|
-
@augs.
|
73
|
-
|
76
|
+
@augs.each_value do |location|
|
77
|
+
position = evaluate_script_to_location iseq, filename, location
|
78
|
+
next if position.nil?
|
74
79
|
|
75
|
-
|
76
|
-
# TODO: CHECK FILE AND LINE HASH COMPARED TO AUG
|
77
|
-
position = PositionMarker.new iseq.absolute_path, location.lineno, iseq
|
78
|
-
@tracer.add_breakpoint_aug [position], pair[1]
|
79
|
-
elsif suggested_match? location, filename
|
80
|
-
warning = Exceptions::RookSourceFilePathSuggestion.new location.filename, filename
|
81
|
-
pair[1].notify_warning warning
|
82
|
-
end
|
80
|
+
@tracer.add_breakpoint_aug [position], location
|
83
81
|
end
|
84
82
|
end
|
85
83
|
|
86
|
-
|
87
|
-
# Enumerating Section
|
88
|
-
def resolve_positions location, aug
|
89
|
-
# TODO: ADD HASHES AND SUGGESTIONS TO THIS FLOW
|
84
|
+
def evaluate_all_scripts_to_location location
|
90
85
|
positions = []
|
86
|
+
@iseqs.each do |iseq|
|
87
|
+
position = evaluate_script_to_location iseq, iseq.absolute_path, location
|
88
|
+
next if position.nil?
|
91
89
|
|
92
|
-
|
93
|
-
positions += scan_module_or_class mod, location, aug
|
94
|
-
end
|
95
|
-
|
96
|
-
ObjectSpace.each_object Class do |klass|
|
97
|
-
positions += scan_module_or_class klass, location, aug
|
90
|
+
positions << position
|
98
91
|
end
|
99
92
|
|
100
93
|
positions
|
101
94
|
end
|
102
95
|
|
103
|
-
def
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
method = mod.instance_method method_name
|
108
|
-
next unless method_match? method, location, aug
|
109
|
-
|
110
|
-
position = PositionMarker.new location.lineno, method
|
111
|
-
positions.push position
|
112
|
-
end
|
113
|
-
|
114
|
-
mod.private_instance_methods(false).each do |method_name|
|
115
|
-
method = mod.instance_method method_name
|
116
|
-
next unless method_match? method, location, aug
|
96
|
+
def evaluate_script_to_location iseq, filename, location
|
97
|
+
if exact_match? location.filename, filename
|
98
|
+
lineno = find_updated_line filename, location
|
99
|
+
return if lineno == -1
|
117
100
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
positions
|
123
|
-
end
|
124
|
-
|
125
|
-
def method_match? method, location, aug
|
126
|
-
return false unless method.source_location
|
127
|
-
filename = method.source_location[0]
|
128
|
-
|
129
|
-
if exact_match? location, filename
|
130
|
-
disasm_header = "== disasm: #<ISeq:#{method.name}@#{location.filename}:"
|
131
|
-
line_in_disasm = "(#{location.lineno.to_s.rjust 4})"
|
132
|
-
text = RubyVM::InstructionSequence.disasm method
|
133
|
-
return false if text.nil?
|
134
|
-
|
135
|
-
text.start_with?(disasm_header) && text.include?(line_in_disasm)
|
136
|
-
else
|
137
|
-
if suggested_match? location, filename
|
138
|
-
warning = Exceptions::RookSourceFilePathSuggestion.new location.filename, filename
|
139
|
-
aug.notify_warning warning
|
140
|
-
end
|
141
|
-
false
|
101
|
+
PositionMarker.new lineno, iseq
|
102
|
+
elsif suggested_match? location, filename
|
103
|
+
warning = Exceptions::RookSourceFilePathSuggestion.new location.filename, filename
|
104
|
+
location.notify_warning warning
|
142
105
|
end
|
143
106
|
end
|
144
107
|
|
145
108
|
#########################################################################################
|
146
109
|
# Utils
|
147
|
-
def exact_match?
|
148
|
-
|
110
|
+
def exact_match? location_filename, script_filename
|
111
|
+
script_filename.end_with? location_filename
|
149
112
|
end
|
150
113
|
|
151
114
|
def suggested_match? location, filename
|
@@ -158,6 +121,43 @@ module Rookout
|
|
158
121
|
content.gsub!(/(?:\r\n|\r|\n)/, "\n")
|
159
122
|
Digest::SHA2.new(256).hexdigest content
|
160
123
|
end
|
124
|
+
|
125
|
+
def find_updated_line filename, location
|
126
|
+
return location.lineno if location.line_crc.nil?
|
127
|
+
|
128
|
+
lines = File.readlines filename, chomp: true
|
129
|
+
line_crc32 = lines.length >= location.lineno ? crc_line(lines[location.lineno - 1]) : nil
|
130
|
+
return location.lineno if location.line_crc == line_crc32
|
131
|
+
|
132
|
+
if location.line_unique
|
133
|
+
first_line = nil
|
134
|
+
second_found = false
|
135
|
+
|
136
|
+
lines.each_with_index do |line, index|
|
137
|
+
if crc_line(line) == location.line_crc
|
138
|
+
if first_line.nil?
|
139
|
+
first_line = index
|
140
|
+
else
|
141
|
+
second_found = true
|
142
|
+
break
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
if first_line && !second_found
|
148
|
+
updated_line = first_line + 1
|
149
|
+
location.notify_warning Exceptions::RookLineMoved.new(filename, location.lineno, updated_line)
|
150
|
+
return updated_line
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
location.notify_error Exceptions::RookCrcMismatchException.new(filename, location.line_crc, line_crc32)
|
155
|
+
-1
|
156
|
+
end
|
157
|
+
|
158
|
+
def crc_line line
|
159
|
+
(Zlib.crc32(line) & 0xffffffff).to_s 16
|
160
|
+
end
|
161
161
|
end
|
162
162
|
end
|
163
163
|
end
|
@@ -1,9 +1,11 @@
|
|
1
1
|
module Rookout
|
2
2
|
module Services
|
3
|
-
|
4
|
-
include BindingOfCaller::BindingExtensions
|
3
|
+
require_relative "../logger"
|
5
4
|
|
6
5
|
class Tracer
|
6
|
+
require "binding_of_caller"
|
7
|
+
include BindingOfCaller::BindingExtensions
|
8
|
+
|
7
9
|
def initialize
|
8
10
|
@trace_points = {}
|
9
11
|
@augs = {}
|
@@ -19,7 +21,7 @@ module Rookout
|
|
19
21
|
begin
|
20
22
|
trace_point.enable target: position.method, target_line: position.lineno
|
21
23
|
rescue ArgumentError => e
|
22
|
-
raise Exceptions::RookSetTracepointFailed
|
24
|
+
raise Exceptions::RookSetTracepointFailed.new(position.lineno, e)
|
23
25
|
end
|
24
26
|
|
25
27
|
# We add and remove a dummy trace point to re-align the tracing mechanism as a result of some bug in adding
|
@@ -69,9 +71,10 @@ module Rookout
|
|
69
71
|
TracePoint.new :line do
|
70
72
|
begin
|
71
73
|
begin
|
72
|
-
|
74
|
+
# TODO: consider delaying callers (get bindings) until we actually need them in Aug.rb
|
75
|
+
aug.execute callers, nil
|
73
76
|
rescue Exception => e
|
74
|
-
Logger.instance.exception "Exception
|
77
|
+
Logger.instance.exception "Exception calling aug", e
|
75
78
|
end
|
76
79
|
rescue
|
77
80
|
# Don't leak any exception from here
|
@@ -17,8 +17,8 @@ module Rookout
|
|
17
17
|
@services.each_value { |service| service.remove_aug aug_id }
|
18
18
|
end
|
19
19
|
|
20
|
-
def clear_augs
|
21
|
-
@services.each_value
|
20
|
+
def clear_augs
|
21
|
+
@services.each_value(&:clear_augs)
|
22
22
|
end
|
23
23
|
|
24
24
|
def start
|