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,158 @@
1
+ module Rookout
2
+ require "fileutils"
3
+ require "English"
4
+
5
+ require_relative "config"
6
+
7
+ class Logger
8
+ require "singleton"
9
+ include Singleton
10
+
11
+ LOG_LEVELS = [:DEBUG, :INFO, :WARNING, :ERROR].freeze
12
+
13
+ def initialize
14
+ @verbosity = LOG_LEVELS.index(Config.logger_log_level) || LOG_LEVELS.index(:INFO)
15
+
16
+ @output = nil
17
+ @handlers = []
18
+ build_handlers
19
+ end
20
+
21
+ def register_output output
22
+ @output = output
23
+ end
24
+
25
+ def remove_output _output
26
+ @output = nil
27
+ end
28
+
29
+ def debug message, *args
30
+ log :DEBUG, message, args
31
+ end
32
+
33
+ def info message, *args
34
+ log :INFO, message, args
35
+ end
36
+
37
+ def warning message, *args
38
+ log :WARNING, message, args
39
+ end
40
+
41
+ def error message, *args
42
+ log :ERROR, message, args
43
+ end
44
+
45
+ def exception message, exc
46
+ # TODO: REVIEW HOW TO REPORT EXCEPTIONS
47
+ error message, exc
48
+ end
49
+
50
+ private
51
+
52
+ class LogRecord
53
+ def initialize level, message, arguments
54
+ @level = level
55
+ @time = Time.new
56
+ @message = message
57
+ @formatted_message = message % arguments
58
+ @arguments = arguments
59
+ set_caller
60
+ end
61
+
62
+ attr_reader :level, :time, :filename, :lineno, :message, :formatted_message, :arguments
63
+
64
+ def format
65
+ "#{@time} #{Process.pid}:#{Thread.current.name}-" \
66
+ "#{File.basename @filename}:#{@label}@#{lineno} - #{@level} - #{formatted_message}"
67
+ end
68
+
69
+ private
70
+
71
+ def set_caller
72
+ @filename = nil
73
+ @lineno = nil
74
+ @label = nil
75
+
76
+ caller_locations(4, 7).each do |caller|
77
+ next if caller.absolute_path.end_with? "lib/rookout/logger.rb"
78
+
79
+ @filename = caller.path
80
+ @lineno = caller.lineno
81
+ @label = caller.label
82
+ break
83
+ end
84
+ end
85
+ end
86
+
87
+ def log level, message, args
88
+ level_no = LOG_LEVELS.index level
89
+ if level_no.nil?
90
+ level = :ERROR
91
+ level_no = LOG_LEVELS.index level
92
+ end
93
+
94
+ return if level_no < @verbosity
95
+
96
+ record = LogRecord.new level, message, args
97
+ @handlers.each { |handler| handler.call record }
98
+ end
99
+
100
+ def build_handlers
101
+ @handlers.push new_file_handler unless Config.logger_filename.nil? || Config.logger_filename.empty?
102
+ @handlers.push new_stderr_handler if Config.logger_log_to_stderr
103
+ @handlers.push new_remote_handler
104
+ end
105
+
106
+ def new_file_handler
107
+ log_file_path = calculate_log_file_path
108
+ directory = File.dirname log_file_path
109
+
110
+ begin
111
+ FileUtils.mkdir_p directory
112
+ file = File.open log_file_path, "a"
113
+ rescue SystemCallError => e
114
+ file = nil
115
+
116
+ if Config.debug
117
+ STDERR.puts "[Rookout] Failed to open log file: #{log_file_path}"
118
+ STDERR.puts e.backtrace
119
+ end
120
+ end
121
+
122
+ ->(record) { file.write record.format + "\n" if file }
123
+ end
124
+
125
+ def calculate_log_file_path
126
+ return Config.logger_filename if absolute_path? Config.logger_filename
127
+
128
+ if RUBY_PLATFORM.include? "darwin"
129
+ File.join ENV["HOME"], Config.logger_filename
130
+ elsif RUBY_PLATFORM.match?(/cygwin|mswin|mingw|bccwin|wince|emx/)
131
+ File.join ENV["USERPROFILE"], Config.logger_filename
132
+ else
133
+ File.join "/var/log", Config.logger_filename
134
+ end
135
+ end
136
+
137
+ def new_stderr_handler
138
+ ->(record) { STDERR.puts record.format }
139
+ end
140
+
141
+ def new_remote_handler
142
+ lambda do |record|
143
+ return unless @output
144
+ @output.send_log_message record.level,
145
+ record.time,
146
+ record.filename,
147
+ record.lineno,
148
+ record.message,
149
+ record.formatted_message,
150
+ record.arguments
151
+ end
152
+ end
153
+
154
+ def absolute_path? path
155
+ path == File.absolute_path(path)
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,26 @@
1
+ module Rookout
2
+ module Processor
3
+ module NamespaceSerializer
4
+ require_relative "../logger"
5
+
6
+ require_relative "../protobuf/variant_pb"
7
+
8
+ module_function
9
+
10
+ def dump namespace, log_errors = true
11
+ namespace.dump log_errors
12
+ rescue StandardError => e
13
+ message = "Failed to serialize namespace"
14
+ variant = Com::Rookout::Variant.new variant_type: :VARIANT_ERROR
15
+
16
+ if log_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
+ end
25
+ end
26
+ end
@@ -0,0 +1,45 @@
1
+ module Rookout
2
+ module Processor
3
+ module Namespaces
4
+ require_relative "namespace"
5
+ require_relative "ruby_object_namespace"
6
+
7
+ require_relative "../../exceptions"
8
+
9
+ require_relative "../../protobuf/variant_pb"
10
+
11
+ class ContainerNamespace < Namespace
12
+ def initialize hash = {}
13
+ @hash = hash
14
+ end
15
+
16
+ def call_method name, args
17
+ return RubyObjectNamespace.new @hash.length if name == "size"
18
+ super
19
+ end
20
+
21
+ def read_attribute name
22
+ raise Exceptions::RookAttributeNotFound, name unless @hash.key? name
23
+ @hash[name]
24
+ end
25
+
26
+ def write_attribute name, value
27
+ @hash[name] = value
28
+ end
29
+
30
+ def dump log_object_errors
31
+ variant = Com::Rookout::Variant.new variant_type: :VARIANT_NAMESPACE,
32
+ namespace_value: Com::Rookout::Variant::Namespace.new
33
+
34
+ @hash.each do |key, value|
35
+ dumped_value = value.dump log_object_errors
36
+ namespace = Com::Rookout::Variant::NamedValue.new name: key, value: dumped_value
37
+ variant.namespace_value.attributes << namespace
38
+ end
39
+
40
+ variant
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,65 @@
1
+ module Rookout
2
+ module Processor
3
+ module Namespaces
4
+ require_relative "namespace"
5
+ require_relative "ruby_object_namespace"
6
+ require_relative "container_namespace"
7
+ require_relative "../../exceptions"
8
+
9
+ class FrameNamespace < Namespace
10
+ def initialize binding
11
+ @binding = binding
12
+ end
13
+
14
+ def read_attribute name
15
+ raise Exceptions::RookAttributeNotFound, name unless @binding.local_variable_defined? name
16
+ RubyObjectNamespace.new @binding.local_variable_get name
17
+ end
18
+
19
+ def call_method name, args
20
+ case name
21
+ when "filename"
22
+ RubyObjectNamespace.new @binding.source_location[0]
23
+ when "line"
24
+ RubyObjectNamespace.new @binding.source_location[1]
25
+ when "function"
26
+ RubyObjectNamespace.new @binding.eval("__method__").to_s
27
+ when "module"
28
+ RubyObjectNamespace.new @binding.source_location[0]
29
+ when "locals"
30
+ locals args
31
+ when "dump"
32
+ result = {
33
+ "filename" => RubyObjectNamespace.new(@binding.source_location[0]),
34
+ "line" => RubyObjectNamespace.new(@binding.source_location[1]),
35
+ "function" => RubyObjectNamespace.new(@binding.eval("__method__").to_s),
36
+ "module" => RubyObjectNamespace.new(@binding.source_location[0]),
37
+ "locals" => locals(args)
38
+ }
39
+ ContainerNamespace.new result
40
+ else
41
+ super
42
+ end
43
+ end
44
+
45
+ def locals args
46
+ dump_config = nil
47
+ unless args.nil?
48
+ dump_config = OBJECT_DUMP_TABLE[args.downcase]
49
+ end
50
+
51
+ hash = {}
52
+ local_variables = @binding.local_variables
53
+ local_variables.each do |var|
54
+ value = @binding.local_variable_get var
55
+ hash[var.to_s] = RubyObjectNamespace.new value, dump_config
56
+ end
57
+
58
+ hash["self"] = RubyObjectNamespace.new @binding.receiver, dump_config
59
+
60
+ ContainerNamespace.new hash
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,28 @@
1
+ module Rookout
2
+ module Processor
3
+ module Namespaces
4
+ class Namespace
5
+ require_relative "../../exceptions"
6
+ def call_method name, _args
7
+ raise Exceptions::RookMethodNotFound, self.class.to_s, name
8
+ end
9
+
10
+ def read_attribute name
11
+ raise Exceptions::RookAttributeNotFound, name
12
+ end
13
+
14
+ def write_attribute name, _value
15
+ raise Exceptions::RookWriteAttributeNotSupported, self.class.to_s, name
16
+ end
17
+
18
+ def read_key key
19
+ raise Exceptions::RookKeyNotFound, key
20
+ end
21
+
22
+ def dump _log_object_errors
23
+ raise NotImplementedError
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,32 @@
1
+ module Rookout
2
+ module Processor
3
+ module Namespaces
4
+ require_relative "namespace"
5
+ require_relative "ruby_object_namespace"
6
+
7
+ require_relative "../../protobuf/variant_pb"
8
+
9
+ class RubyUtilsNamespace < Namespace
10
+ def initialize
11
+ super
12
+ end
13
+
14
+ def call_method _name, _args
15
+ RubyObjectNamespace nil
16
+ end
17
+
18
+ def read_attribute _name
19
+ RubyObjectNamespace nil
20
+ end
21
+
22
+ def read_key _key
23
+ RubyObjectNamespace nil
24
+ end
25
+
26
+ def dump _log_object_errors
27
+ Com::Rookout::Variant.new variant_type: :VARIANT_NONE
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,97 @@
1
+ module Rookout
2
+ module Processor
3
+ module Namespaces
4
+ require "bigdecimal"
5
+ require "google/protobuf/well_known_types"
6
+
7
+ require_relative "../../exceptions"
8
+
9
+ require_relative "namespace"
10
+ require_relative "ruby_object_serializer"
11
+
12
+ class ObjectDumpConfig
13
+ def initialize max_depth, max_width, max_collection_depth, max_string
14
+ @max_depth = max_depth
15
+ @max_width = max_width
16
+ @max_collection_depth = max_collection_depth
17
+ @max_string = max_string
18
+ end
19
+
20
+ attr_reader :max_depth, :max_width, :max_collection_depth, :max_string
21
+ end
22
+
23
+ OBJECT_DUMP_CONFIG_STRICT = ObjectDumpConfig.new 2, 10, 1, 128
24
+ OBJECT_DUMP_CONFIG_DEFAULT = ObjectDumpConfig.new 4, 20, 2, 512
25
+ OBJECT_DUMP_CONFIG_TOLERANT = ObjectDumpConfig.new 5, 50, 4, 4 * 1024
26
+
27
+ OBJECT_DUMP_CONFIG_STRING = ObjectDumpConfig.new 1, 0, 0, 64 * 1024
28
+ OBJECT_DUMP_CONFIG_COLLECTION = ObjectDumpConfig.new 4, 100, 2, 512
29
+
30
+ OBJECT_DUMP_TABLE = {
31
+ "" => OBJECT_DUMP_CONFIG_DEFAULT,
32
+ "strict" => OBJECT_DUMP_CONFIG_STRICT,
33
+ "default" => OBJECT_DUMP_CONFIG_DEFAULT,
34
+ "tolerant" => OBJECT_DUMP_CONFIG_TOLERANT
35
+ }.freeze
36
+
37
+ class RubyObjectNamespace < Namespace
38
+ include RubyObjectSerializer
39
+
40
+ def initialize obj, dump_config = OBJECT_DUMP_CONFIG_DEFAULT
41
+ @obj = obj
42
+ @dump_config = dump_config
43
+ end
44
+
45
+ attr_reader :obj, :dump_config
46
+
47
+ def tailor_limits!
48
+ if @obj.is_a? String
49
+ @dump_config = OBJECT_DUMP_CONFIG_STRING
50
+ elsif @obj.is_a?(Hash) || @obj.is_a?(Array)
51
+ @dump_config = OBJECT_DUMP_CONFIG_COLLECTION
52
+ end
53
+ self
54
+ end
55
+
56
+ def read_attribute name
57
+ attributes = @obj.instance_variables
58
+ raise RookAttributeNotFound, name unless attributes.include? name.to_sym
59
+ RubyObjectNamespace.new @obj.instance_variable_get(name)
60
+ end
61
+
62
+ def read_key key
63
+ if @obj.is_a? Array
64
+ key_int = key.to_i
65
+ return RubyObjectNamespace.new @obj[key_int] if key_int >= 0 && key_int < @obj.length
66
+ raise Exceptions::RookKeyNotFound, key
67
+
68
+ elsif @obj.is_a? Hash
69
+ return RubyObjectNamespace.new @obj[key] if @obj.key? key
70
+ return RubyObjectNamespace.new @obj[key.to_sym] if key.is_a?(String) && @obj.key?(key.to_sym)
71
+
72
+ @obj.each { |it, value| return RubyObjectNamespace.new value if it.to_s == key }
73
+
74
+ raise Exceptions::RookKeyNotFound, key
75
+ else
76
+ raise Exceptions::RookInvalidObjectForAccess.new(obj.class.to_s, "ReadKey")
77
+ end
78
+ end
79
+
80
+ def call_method name, args
81
+ case name
82
+ when "type"
83
+ RubyObjectNamespace.new @obj.class.to_s
84
+ when "size"
85
+ RubyObjectNamespace.new @obj.length
86
+ else
87
+ super
88
+ end
89
+ end
90
+
91
+ def dump log_object_errors
92
+ dump_raw_object @obj, 0, @dump_config, log_object_errors
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end