rookout 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +12 -0
  3. data/bin/rookout +30 -0
  4. data/lib/rookout.rb +18 -0
  5. data/lib/rookout/augs/actions/action.rb +11 -0
  6. data/lib/rookout/augs/actions/action_run_processor.rb +29 -0
  7. data/lib/rookout/augs/aug.rb +121 -0
  8. data/lib/rookout/augs/aug_factory.rb +69 -0
  9. data/lib/rookout/augs/aug_rate_limiter.rb +96 -0
  10. data/lib/rookout/augs/augs_manager.rb +77 -0
  11. data/lib/rookout/augs/conditions/condition.rb +15 -0
  12. data/lib/rookout/augs/locations/location.rb +11 -0
  13. data/lib/rookout/augs/locations/location_file_line.rb +26 -0
  14. data/lib/rookout/com_ws/agent_com_ws.rb +221 -0
  15. data/lib/rookout/com_ws/backoff.rb +35 -0
  16. data/lib/rookout/com_ws/command_handler.rb +22 -0
  17. data/lib/rookout/com_ws/git.rb +53 -0
  18. data/lib/rookout/com_ws/information.rb +85 -0
  19. data/lib/rookout/com_ws/output.rb +135 -0
  20. data/lib/rookout/com_ws/token_bucket.rb +36 -0
  21. data/lib/rookout/config.rb +55 -0
  22. data/lib/rookout/exceptions.rb +140 -0
  23. data/lib/rookout/interface.rb +140 -0
  24. data/lib/rookout/logger.rb +158 -0
  25. data/lib/rookout/processor/namespace_serializer.rb +26 -0
  26. data/lib/rookout/processor/namespaces/container_namespace.rb +45 -0
  27. data/lib/rookout/processor/namespaces/frame_namespace.rb +65 -0
  28. data/lib/rookout/processor/namespaces/namespace.rb +28 -0
  29. data/lib/rookout/processor/namespaces/noop_namespace.rb +32 -0
  30. data/lib/rookout/processor/namespaces/ruby_object_namespace.rb +97 -0
  31. data/lib/rookout/processor/namespaces/ruby_object_serializer.rb +208 -0
  32. data/lib/rookout/processor/namespaces/ruby_utils_namespace.rb +65 -0
  33. data/lib/rookout/processor/namespaces/stack_namespace.rb +30 -0
  34. data/lib/rookout/processor/namespaces/traceback_namespace.rb +40 -0
  35. data/lib/rookout/processor/operations/operation.rb +11 -0
  36. data/lib/rookout/processor/operations/set_operation.rb +48 -0
  37. data/lib/rookout/processor/paths/arithmetic_path.rb +84 -0
  38. data/lib/rookout/processor/paths/canopy/actions.rb +184 -0
  39. data/lib/rookout/processor/paths/canopy/consts.rb +82 -0
  40. data/lib/rookout/processor/paths/canopy/maps.rb +2837 -0
  41. data/lib/rookout/processor/paths/canopy/markers.rb +186 -0
  42. data/lib/rookout/processor/paths/path.rb +15 -0
  43. data/lib/rookout/processor/processor.rb +34 -0
  44. data/lib/rookout/processor/processor_factory.rb +23 -0
  45. data/lib/rookout/processor/rook_error.rb +45 -0
  46. data/lib/rookout/protobuf/.gitignore +0 -0
  47. data/lib/rookout/protobuf/agent_info_pb.rb +68 -0
  48. data/lib/rookout/protobuf/controller_info_pb.rb +29 -0
  49. data/lib/rookout/protobuf/envelope_pb.rb +21 -0
  50. data/lib/rookout/protobuf/messages_pb.rb +189 -0
  51. data/lib/rookout/protobuf/variant_pb.rb +139 -0
  52. data/lib/rookout/rookout_singleton.rb +73 -0
  53. data/lib/rookout/services/position.rb +163 -0
  54. data/lib/rookout/services/tracer.rb +83 -0
  55. data/lib/rookout/trigger_services.rb +34 -0
  56. data/lib/rookout/user_warnings.rb +25 -0
  57. data/lib/rookout/version.rb +4 -0
  58. metadata +269 -0
@@ -0,0 +1,208 @@
1
+ module Rookout
2
+ module Processor
3
+ module Namespaces
4
+ module RubyObjectSerializer
5
+ require_relative "../../logger"
6
+ require_relative "../rook_error"
7
+
8
+ require_relative "../../protobuf/variant_pb"
9
+
10
+ def dump_raw_object obj, current_depth, config, log_object_errors
11
+ unsafe_dump_object obj, current_depth, config, log_object_errors
12
+ rescue StandardError => e
13
+ message = "Failed to serialize object"
14
+ variant = Com::Rookout::Variant.new variant_type: :VARIANT_ERROR
15
+
16
+ if log_object_errors
17
+ Logger.instance.exception message, e
18
+
19
+ error = RookError.new e, message
20
+ variant = error.dumps
21
+ end
22
+ variant
23
+ end
24
+
25
+ # rubocop:disable Metrics/PerceivedComplexity
26
+ # rubocop:disable Metrics/CyclomaticComplexity
27
+ def unsafe_dump_object obj, current_depth, config, log_object_errors
28
+ variant = create_base_variant obj, current_depth, config, log_object_errors
29
+
30
+ if obj.nil?
31
+ dump_nil variant
32
+ elsif obj.is_a?(Numeric) || obj == true || obj == false
33
+ dump_numeric obj, variant
34
+ elsif obj.is_a?(String) || obj.is_a?(Symbol)
35
+ dump_string obj, variant, config
36
+ elsif obj.is_a? Time
37
+ dump_time obj, variant
38
+ elsif obj.is_a? Array
39
+ dump_array obj, variant, current_depth, config, log_object_errors
40
+ elsif obj.is_a? Hash
41
+ dump_hash obj, variant, current_depth, config, log_object_errors
42
+ elsif obj.is_a? Exception
43
+ dump_exception obj, variant, current_depth, config, log_object_errors
44
+ elsif obj.is_a?(Method) || obj.is_a?(Proc) || obj.is_a?(Class) || obj.is_a?(Module)
45
+ dump_code_object obj, variant
46
+ else
47
+ dump_user_class variant
48
+ end
49
+
50
+ variant
51
+ end
52
+
53
+ # rubocop:enable Metrics/CyclomaticComplexity
54
+ # rubocop:enable Metrics/PerceivedComplexity
55
+
56
+ def create_base_variant obj, current_depth, config, log_object_errors
57
+ variant = Com::Rookout::Variant.new original_type: obj.class.to_s
58
+
59
+ object_weight = obj.instance_variables.length > config.max_width ? 2 : 1
60
+ next_depth = current_depth + object_weight
61
+ if next_depth >= config.max_depth
62
+ variant.max_depth = true
63
+ return variant
64
+ end
65
+
66
+ obj.instance_variables.each do |name|
67
+ raw_value = obj.instance_variable_get name
68
+ variant_value = dump_raw_object raw_value, current_depth + 1, config, log_object_errors
69
+ variant.attributes << Com::Rookout::Variant::NamedValue.new(name: name, value: variant_value)
70
+ end
71
+
72
+ variant
73
+ end
74
+
75
+ def dump_nil variant
76
+ variant.variant_type = :VARIANT_NONE
77
+ end
78
+
79
+ # Based off protobuf for Python
80
+ INT32_MIN = -2147483648
81
+ INT32_MAX = 2147483647
82
+ INT64_MIN = -(1 << 63)
83
+ INT64_MAX = (1 << 63) - 1
84
+
85
+ def dump_numeric obj, variant
86
+ if obj == true
87
+ variant.variant_type = :VARIANT_INT
88
+ variant.int_value = 1
89
+ elsif obj == false
90
+ variant.variant_type = :VARIANT_INT
91
+ variant.int_value = 0
92
+ elsif obj.is_a? Integer
93
+ dump_integer obj, variant
94
+ elsif obj.is_a? Float
95
+ variant.variant_type = :VARIANT_DOUBLE
96
+ variant.double_value = obj.to_f
97
+ elsif obj.is_a? BigDecimal
98
+ serialized_decimal = obj.to_s
99
+ variant.variant_type = :VARIANT_STRING
100
+ variant.string_value = Com::Rookout::Variant::String.new value: serialized_decimal,
101
+ original_size: serialized_decimal.length
102
+ elsif obj.is_a? Complex
103
+ variant.variant_type = :VARIANT_COMPLEX
104
+ variant.complex_value = Com::Rookout::Variant::Complex.new real: obj.real.to_f,
105
+ imaginary: obj.imaginary.to_f
106
+ else
107
+ raise Exceptions.RookClassCannotBeSerialized, obj.class, "Unknown Numeric Type"
108
+ end
109
+ # TODO: ADD SUPPORT FOR RATIONALS
110
+ end
111
+
112
+ def dump_integer obj, variant
113
+ if obj > INT32_MIN && obj < INT32_MAX
114
+ variant.variant_type = :VARIANT_INT
115
+ variant.int_value = obj
116
+ elsif obj > INT64_MIN && obj < INT64_MAX
117
+ variant.variant_type = :VARIANT_LONG
118
+ variant.long_value = obj
119
+ else
120
+ variant.variant_type = :VARIANT_LARGE_INT
121
+ variant.large_int_value = Com::Rookout::Variant::LargeInt.new value: obj.to_s
122
+ end
123
+ end
124
+
125
+ def dump_string obj, variant, config
126
+ if obj.length > config.max_string
127
+ final_obj = obj[0...config.max_string]
128
+ else
129
+ final_obj = obj
130
+ end
131
+
132
+ variant.variant_type = :VARIANT_STRING
133
+ variant.string_value = Com::Rookout::Variant::String.new value: final_obj, original_size: obj.length
134
+ end
135
+
136
+ def dump_time obj, variant
137
+ variant.variant_type = :VARIANT_TIME
138
+ variant.time_value = Google::Protobuf::Timestamp.new
139
+ variant.time_value.from_time obj
140
+ end
141
+
142
+ def dump_array obj, variant, current_depth, config, log_object_errors
143
+ variant.variant_type = :VARIANT_LIST
144
+ variant.list_value = Com::Rookout::Variant::List.new type: "array", original_size: obj.length
145
+
146
+ return unless current_depth < config.max_collection_depth
147
+
148
+ obj.each_with_index do |value, index|
149
+ break if index >= config.max_width
150
+ variant.list_value.values << dump_raw_object(value, current_depth + 1, config, log_object_errors)
151
+ end
152
+ end
153
+
154
+ def dump_hash obj, variant, current_depth, config, log_object_errors
155
+ variant.variant_type = :VARIANT_MAP
156
+ variant.map_value = Com::Rookout::Variant::Map.new original_size: obj.length
157
+
158
+ return unless current_depth < config.max_collection_depth
159
+
160
+ obj.each_with_index do |(key, value), index|
161
+ break if index >= config.max_width
162
+ key_variant = dump_raw_object key, current_depth + 1, config, log_object_errors
163
+ value_variant = dump_raw_object value, current_depth + 1, config, log_object_errors
164
+ pair = Com::Rookout::Variant::Pair.new first: key_variant, second: value_variant
165
+ variant.map_value.pairs << pair
166
+ end
167
+ end
168
+
169
+ def dump_exception obj, variant, current_depth, config, log_object_errors
170
+ variant.variant_type = :VARIANT_OBJECT
171
+
172
+ message = dump_raw_object obj.message, current_depth + 1, config, log_object_errors
173
+ variant.attributes << Com::Rookout::Variant::NamedValue.new(name: "message", value: message)
174
+
175
+ cause = dump_raw_object obj.cause, current_depth + 1, config, log_object_errors
176
+ variant.attributes << Com::Rookout::Variant::NamedValue.new(name: "cause", value: cause)
177
+
178
+ backtrace = dump_raw_object obj.backtrace, current_depth + 1, config, log_object_errors
179
+ variant.attributes << Com::Rookout::Variant::NamedValue.new(name: "backtrace", value: backtrace)
180
+ end
181
+
182
+ def dump_code_object obj, variant
183
+ variant.variant_type = :VARIANT_CODE_OBJECT
184
+
185
+ if obj.is_a?(Proc) || obj.is_a?(Method)
186
+ source_location = obj.source_location
187
+ else
188
+ source_location = [nil, nil]
189
+ end
190
+
191
+ if obj.is_a? Proc
192
+ name = ""
193
+ else
194
+ name = obj.name
195
+ end
196
+
197
+ variant.code_value = Com::Rookout::Variant::CodeObject.new name: name,
198
+ filename: source_location[0],
199
+ lineno: source_location[1]
200
+ end
201
+
202
+ def dump_user_class variant
203
+ variant.variant_type = :VARIANT_OBJECT
204
+ end
205
+ end
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,65 @@
1
+ module Rookout
2
+ module Processor
3
+ module Namespaces
4
+ require "English"
5
+
6
+ require_relative "../../exceptions"
7
+
8
+ require_relative "namespace"
9
+ require_relative "ruby_object_namespace"
10
+
11
+ class RubyUtilsNamespace < Namespace
12
+ def initialize
13
+ super
14
+ end
15
+
16
+ def call_method name, args
17
+ case name
18
+ when "exception"
19
+ RubyObjectNamespace.new $ERROR_INFO
20
+ when "module"
21
+ find_module args
22
+ when "env"
23
+ raise Exceptions::RookKeyNotFound, args unless ENV.include? args
24
+ RubyObjectNamespace.new ENV[args]
25
+ when "thread_id"
26
+ RubyObjectNamespace.new Thread.current.__id__
27
+ when "thread_name"
28
+ RubyObjectNamespace.new Thread.current.name
29
+ when "threads"
30
+ RubyObjectNamespace.new Thread.list
31
+ when "thread_tracebacks"
32
+ thread_tracebacks
33
+ else
34
+ super
35
+ end
36
+ end
37
+
38
+ def read_attribute _name
39
+ RubyObjectNamespace.new nil
40
+ end
41
+
42
+ def read_key _key
43
+ RubyObjectNamespace.new nil
44
+ end
45
+
46
+ private
47
+
48
+ def find_module args
49
+ RubyObjectNamespace.new Object.const_get(args)
50
+ rescue NameError
51
+ raise Exceptions::RookKeyNotFound, args
52
+ end
53
+
54
+ def thread_tracebacks
55
+ result = Thread.list.map do |thread|
56
+ { id: thread.__id__,
57
+ name: thread.name,
58
+ traceback: thread.backtrace }
59
+ end
60
+ RubyObjectNamespace.new result
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,30 @@
1
+ module Rookout
2
+ module Processor
3
+ module Namespaces
4
+ require_relative "namespace"
5
+ require_relative "frame_namespace"
6
+ require_relative "traceback_namespace"
7
+
8
+ class StackNamespace < Namespace
9
+ def initialize backtrace, offset = 0
10
+ @backtrace = backtrace
11
+ @offset = offset
12
+ end
13
+
14
+ def read_key key
15
+ FrameNamespace.new @backtrace[key + @offset]
16
+ end
17
+
18
+ def call_method name, args
19
+ return create_traceback args if name == "traceback"
20
+ super
21
+ end
22
+
23
+ def create_traceback args
24
+ args = 1000 if args == ""
25
+ TracebackNamespace.new @backtrace, @offset, args.to_i
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,40 @@
1
+ module Rookout
2
+ module Processor
3
+ module Namespaces
4
+ require_relative "namespace"
5
+ require_relative "frame_namespace"
6
+
7
+ require_relative "../../protobuf/variant_pb"
8
+
9
+ class TracebackNamespace < Namespace
10
+ def initialize backtrace, offset, depth
11
+ @backtrace = backtrace
12
+ @offset = offset
13
+ @depth = depth
14
+ end
15
+
16
+ def read_key key
17
+ FrameNamespace.new @backtrace[key + @offset]
18
+ end
19
+
20
+ def dump _log_object_errors
21
+ traceback = Com::Rookout::Variant::Traceback.new
22
+
23
+ @depth.times do |i|
24
+ position = i + @offset
25
+ break if position >= @backtrace.length
26
+ frame = @backtrace[position]
27
+
28
+ code_object = Com::Rookout::Variant::CodeObject.new filename: frame.source_location[0],
29
+ lineno: frame.source_location[1],
30
+ name: frame.eval("__method__").to_s
31
+
32
+ traceback.locations << code_object
33
+ end
34
+
35
+ Com::Rookout::Variant.new variant_type: :VARIANT_TRACEBACK, traceback: traceback
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,11 @@
1
+ module Rookout
2
+ module Processor
3
+ module Operations
4
+ class Operation
5
+ def execute _namespace
6
+ raise NotImplementedError
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,48 @@
1
+ module Rookout
2
+ module Processor
3
+ module Operations
4
+ require_relative "operation"
5
+
6
+ require_relative "../rook_error"
7
+ require_relative "../../logger"
8
+ require_relative "../../user_warnings"
9
+
10
+ class SetOperation < Operation
11
+ def initialize configuration, factory
12
+ @paths = []
13
+
14
+ configuration["paths"].each do |key, value|
15
+ begin
16
+ dest_path = factory.create_path key
17
+ source_path = factory.create_path value
18
+ @paths.push [dest_path, source_path]
19
+ rescue StandardError => e
20
+ message = "Failed to load dest:source path pair"
21
+ Logger.instance.exception message, e
22
+ warning = RookError.new e, message
23
+ UserWarnings.notify_warning warning
24
+ end
25
+ end
26
+ end
27
+
28
+ def execute namespace
29
+ @paths.each do |dest_path, source_path|
30
+ begin
31
+ value = source_path.read_from namespace
32
+ if value.is_a?(RubyObjectNamespace) && value.dump_config == Namespaces::OBJECT_DUMP_CONFIG_DEFAULT
33
+ value.tailor_limits!
34
+ end
35
+
36
+ dest_path.write_to namespace, value
37
+ rescue StandardError => e
38
+ message = "Failed to execute dest:source path pair"
39
+ Logger.instance.exception message, e
40
+ warning = RookError.new e, message
41
+ UserWarnings.notify_warning warning
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,84 @@
1
+ module Rookout
2
+ module Processor
3
+ module Paths
4
+ require_relative "path"
5
+
6
+ require_relative "../../exceptions"
7
+
8
+ require_relative "../namespaces/ruby_object_namespace"
9
+
10
+ require_relative "canopy/maps"
11
+ require_relative "canopy/actions"
12
+ require_relative "canopy/markers"
13
+
14
+ class ArithmeticPath < Path
15
+ def initialize path
16
+ if path.is_a? Hash
17
+ path = path["path"] || path[:path]
18
+ end
19
+
20
+ @raw_path = path
21
+
22
+ if path.start_with?("NOT(") && path.end_with?(")")
23
+ @path = path["NOT(".length..-2]
24
+ @negation = true
25
+ else
26
+ @path = path
27
+ @negation = false
28
+ end
29
+
30
+ raise RookInvalidArithmeticPath, @raw_path if @path.empty?
31
+ end
32
+
33
+ def read_from namespace
34
+ begin
35
+ result = Maps.parse @path, actions: Canopy::Actions.new(namespace)
36
+ rescue Maps::ParseError => e
37
+ raise RookInvalidArithmeticPath.new(@path, e)
38
+ end
39
+
40
+ normalize result
41
+ end
42
+
43
+ def write_to namespace, value
44
+ context = Canopy::Actions.new namespace
45
+
46
+ begin
47
+ # initialize operations chain - by parsing the expression - ignore return value
48
+ Maps.parse @path, actions: context
49
+ rescue Maps::ParseError => e
50
+ raise RookInvalidArithmeticPath.new(@path, e)
51
+ end
52
+
53
+ raise RookInvalidArithmeticPath, @raw_path if context.operations.empty?
54
+
55
+ (context.operations.length - 1).times do |i|
56
+ namespace = context.operations[i].read namespace, true
57
+ end
58
+
59
+ context.operations[context.operations.length - 1].write namespace, value
60
+ end
61
+
62
+ def normalize result
63
+ if result.is_a? Canopy::List
64
+ new_array = result.obj.map(&:obj)
65
+ return Namespaces::RubyObjectNamespace.new new_array
66
+ end
67
+
68
+ if result.is_a? Canopy::NamespaceResult
69
+ return result.obj
70
+ end
71
+
72
+ if result.is_a? Canopy::ToolExceptionMarker
73
+ raise result.obj if result.obj.is_a? Exceptions::ToolException
74
+ raise Exceptions::RookInvalidArithmeticPath, @raw_path, result.obj
75
+ end
76
+
77
+ res = result.obj
78
+ res = !res if [true, false].include?(res) && @negation
79
+ Namespaces::RubyObjectNamespace.new res
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end