rookout 0.1.0 → 0.1.1

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.
@@ -14,7 +14,7 @@ module Rookout
14
14
  def initialize labels
15
15
  @agent_id = nil
16
16
  @labels = labels.clone
17
- @labels["rookout_debug"] = "on"
17
+ @labels["rookout_debug"] = "on" if Config.debug
18
18
 
19
19
  @ip_addr = local_ip
20
20
 
@@ -0,0 +1,36 @@
1
+ module Rookout
2
+ module ComWs
3
+ require_relative "../logger"
4
+
5
+ class Pinger
6
+ def initialize connection, interval, timeout
7
+ @interval = interval
8
+ @timeout = timeout
9
+ @connection = connection
10
+
11
+ @last_pong = Time.now
12
+ @last_ping = Time.now
13
+ end
14
+
15
+ def repeat
16
+ loop do
17
+ if Time.now - @last_ping > @interval
18
+ Logger.instance.debug "Sending Ping"
19
+ @last_ping = Time.now
20
+ @connection.ping Time.now.to_s do
21
+ Logger.instance.debug "Got Ping reply"
22
+ @last_pong = Time.now
23
+ end
24
+ end
25
+
26
+ if Time.now - @last_pong > @timeout
27
+ Logger.instance.debug "Ping timeout"
28
+ break
29
+ end
30
+
31
+ yield
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,143 @@
1
+ module Rookout
2
+ module ComWs
3
+ require "openssl"
4
+ require "websocket/driver"
5
+
6
+ require_relative "../config"
7
+ require_relative "../logger"
8
+ require_relative "../exceptions"
9
+
10
+ class WebsocketClient
11
+ def initialize url, proxy, token
12
+ @token = token
13
+ @connection = WebsocketConnection.new url, proxy
14
+ @driver = nil
15
+ @error = nil
16
+ @last_ping = nil
17
+ end
18
+
19
+ def connect
20
+ # TODO: add proxy support
21
+ @connection.connect
22
+ @driver = WebSocket::Driver.client @connection
23
+
24
+ headers.each do |key, value|
25
+ @driver.set_header key, value
26
+ end
27
+
28
+ @driver.on :error do |error|
29
+ @error = error
30
+ end
31
+
32
+ # Connect to the remote server
33
+ @driver.start
34
+ # TODO: ADD CONNECT TIMEOUT
35
+ while @driver.state == :connecting
36
+ recv_data = @connection.read_char
37
+ @driver.parse recv_data
38
+ end
39
+
40
+ raise Exceptions::RookWebsocketException, @error if @driver.state != :open
41
+ end
42
+
43
+ def connection_pump message_handler
44
+ @driver.on :message do |e|
45
+ message_handler.call e.data
46
+ end
47
+
48
+ until @driver.state == :closed
49
+ recv_data = @connection.read_char
50
+ @driver.parse recv_data
51
+ end
52
+ end
53
+
54
+ def send_frame msg
55
+ @driver.binary msg
56
+ end
57
+
58
+ def ping message, &callback
59
+ @driver.ping message, &callback
60
+ end
61
+
62
+ def close
63
+ return if @driver.nil?
64
+
65
+ @driver.close
66
+ @connection.close
67
+ end
68
+
69
+ private
70
+
71
+ def headers
72
+ result = {
73
+ "User-Agent" => "RookoutAgent/#{Config.rookout_version}+#{Config.rookout_commit}"
74
+ }
75
+
76
+ result["X-Rookout-Token"] = @token unless @token.nil?
77
+
78
+ result
79
+ end
80
+ end
81
+
82
+ class WebsocketConnection
83
+ def initialize url, proxy
84
+ @url = url
85
+ @proxy = proxy
86
+
87
+ @uri = URI.parse @url
88
+ @secure = %w[https wss].include? @uri.scheme
89
+
90
+ @socket = nil
91
+ end
92
+
93
+ def connect
94
+ if @secure
95
+ @socket = ssl_connect
96
+ else
97
+ @socket = tcp_connect
98
+ end
99
+ end
100
+
101
+ attr_reader :url
102
+
103
+ def read_char
104
+ @socket.getc
105
+ end
106
+
107
+ def write buffer
108
+ @socket << buffer
109
+ end
110
+
111
+ def close
112
+ return if @socket.nil?
113
+
114
+ @socket.close
115
+ @socket = nil
116
+ end
117
+
118
+ private
119
+
120
+ def tcp_connect
121
+ TCPSocket.new @uri.host,
122
+ @uri.port || (@secure ? 443 : 80)
123
+ end
124
+
125
+ def ssl_connect
126
+ tcp_socket = tcp_connect
127
+
128
+ ctx = ::OpenSSL::SSL::SSLContext.new
129
+ ctx.min_version = ::OpenSSL::SSL::TLS1_2_VERSION
130
+ cert_store = ::OpenSSL::X509::Store.new
131
+ cert_store.set_default_paths
132
+ ctx.cert_store = cert_store
133
+
134
+ ssl_socket = ::OpenSSL::SSL::SSLSocket.new tcp_socket, ctx
135
+ ssl_socket.hostname = @uri.host
136
+ ssl_socket.sync_close = true
137
+ ssl_socket.connect
138
+
139
+ ssl_socket
140
+ end
141
+ end
142
+ end
143
+ end
@@ -1,5 +1,6 @@
1
1
  module Rookout
2
2
  require_relative "version"
3
+ require_relative "commit"
3
4
 
4
5
  module Config
5
6
  # Magic to allow for module variables to be easily accessible
@@ -136,5 +136,45 @@ module Rookout
136
136
  super "No Rookout token was supplied. Make sure to pass the Rookout Token when starting the rook"
137
137
  end
138
138
  end
139
+
140
+ class RookInvalidOptions < ToolException
141
+ def initialize description
142
+ super description
143
+ end
144
+ end
145
+
146
+ class RookCrcMismatchException < ToolException
147
+ def initialize filepath, expected, calculated
148
+ super "Line CRC32s do not match! path: #{filepath}, expected: #{expected}, calculated:#{calculated}",
149
+ {
150
+ "filepath" => filepath,
151
+ "expected" => expected,
152
+ "calculated" => calculated
153
+ }
154
+ end
155
+ end
156
+
157
+ class RookLineMoved < ToolException
158
+ def initialize filepath, old_line_no, new_line_no
159
+ super "Line has moved! path: #{filepath}, original line no: #{old_line_no}, new line no: #{new_line_no}",
160
+ {
161
+ "filepath" => filepath,
162
+ "old_line_no" => old_line_no,
163
+ "new_line_no" => new_line_no
164
+ }
165
+ end
166
+ end
167
+
168
+ class RookCommunicationException < ToolException
169
+ def initialize
170
+ super "Failed to connect to the controller - will continue attempting in the background"
171
+ end
172
+ end
173
+
174
+ class RookWebsocketException < ToolException
175
+ def initialize error
176
+ super "Error from Websocket #{error}", { "error" => error }
177
+ end
178
+ end
139
179
  end
140
180
  end
@@ -5,6 +5,7 @@ module Rookout
5
5
 
6
6
  require_relative "config"
7
7
  require_relative "exceptions"
8
+ include Exceptions
8
9
 
9
10
  def initialize
10
11
  @rook = nil
@@ -19,24 +20,21 @@ module Rookout
19
20
  require_relative "rookout_singleton"
20
21
 
21
22
  configure_logging options
22
- labels = options[:labels] || parse_labels(ENV["ROOKOUT_LABELS"])
23
- validate_labels labels
24
-
25
23
  configure_git options
26
24
 
27
- com = configure_com options
28
-
29
- async_start = true? ENV["ROOKOUT_ASYNC_START"]
30
- fork = evaluate_flag options[:fork], "ROOKOUT_ENABLE_FORK"
31
-
32
- print_config com, labels: labels, async_start: async_start, fork: fork if Config.debug
25
+ start_options = configure_start_options options
26
+ print_config start_options
33
27
 
34
28
  rook = RookoutSingleton.instance
35
- rook.connect com[:token], com[:host], com[:port], com[:proxy], labels, async_start, fork
36
-
37
- # TODO: ADD DETAILED PROCESSING FOR SPECIFIC ERRORS
29
+ rook.connect(**start_options)
30
+ rescue RookMissingToken, RookInvalidToken, RookInvalidOptions, RookVersionNotSupported => e
31
+ raise if throw_errors
32
+ STDERR.puts "[Rookout] Failed to start Rookout: #{e.message}"
33
+ rescue RookCommunicationException => e
34
+ raise if throw_errors
35
+ STDERR.puts "[Rookout] " + e.message
38
36
  rescue Exception => e
39
- puts e.full_message if Config.debug
37
+ STDERR.puts e.full_message if Config.debug
40
38
  raise if throw_errors
41
39
  end
42
40
  end
@@ -59,7 +57,7 @@ module Rookout
59
57
  def configure_logging options
60
58
  if Config.debug
61
59
  log_to_stderr = true
62
- log_level = "DEBUG"
60
+ log_level = :DEBUG
63
61
  else
64
62
  log_to_stderr = evaluate_flag options[:log_to_stderr], "ROOKOUT_LOG_TO_STDERR"
65
63
  log_level = options[:log_level] || ENV["ROOKOUT_LOG_FILE"]
@@ -77,16 +75,22 @@ module Rookout
77
75
  Config.user_git_commit = options[:git_commit] if options[:git_commit]
78
76
  end
79
77
 
80
- def configure_com options
78
+ def configure_start_options options
81
79
  host = evaluate_config options[:host], "ROOKOUT_CONTROLLER_HOST", "wss://control.rookout.com"
82
80
  port = evaluate_config options[:port], "ROOKOUT_CONTROLLER_PORT", 443
83
81
  proxy = evaluate_config options[:proxy], "ROOKOUT_PROXY"
84
82
  token = evaluate_config options[:token], "ROOKOUT_TOKEN"
85
83
 
86
- raise Exceptions::RookMissingToken if token.nil? && host == "wss://control.rookout.com"
84
+ raise RookMissingToken if token.nil? && host == "wss://control.rookout.com"
87
85
  verify_token token if token
88
86
 
89
- { host: host, port: port, proxy: proxy, token: token }
87
+ labels = options[:labels] || parse_labels(ENV["ROOKOUT_LABELS"])
88
+ validate_labels labels
89
+
90
+ async_start = true? ENV["ROOKOUT_ASYNC_START"]
91
+ fork = evaluate_flag options[:fork], "ROOKOUT_ENABLE_FORK"
92
+
93
+ { host: host, port: port, proxy: proxy, token: token, labels: labels, async_start: async_start, fork: fork }
90
94
  end
91
95
 
92
96
  def evaluate_flag argument, env_var_name
@@ -120,21 +124,22 @@ module Rookout
120
124
  def validate_labels labels
121
125
  labels.each do |label_name, _|
122
126
  if label_name.start_with? "$"
123
- raise Exceptions::RookInvalidLabel, label_name
127
+ raise RookInvalidLabel, label_name
124
128
  end
125
129
  end
126
130
  end
127
131
 
128
132
  def verify_token token
129
- raise Exceptions::RookInvalidOptions, "Rookout token should be a String" unless token.is_a? String
130
- raise Exceptions::RookInvalidOptions, "Rookout token should be 64 characters" unless token.length == 64
131
- raise Exceptions::RookInvalidOptions, "Rookout token must consist of only hexadecimal characters" unless
133
+ raise RookInvalidOptions, "Rookout token should be a String" unless token.is_a? String
134
+ raise RookInvalidOptions, "Rookout token should be 64 characters" unless token.length == 64
135
+ raise RookInvalidOptions, "Rookout token must consist of only hexadecimal characters" unless
132
136
  token.match(/^[0-9a-zA-Z]{0,64}$/)
133
137
  end
134
138
 
135
- def print_config com, options
136
- puts "[Rookout] Communication Options: #{com}"
137
- puts "[Rookout] Other Options #{options}"
139
+ def print_config options
140
+ return unless Config.debug
141
+
142
+ puts "[Rookout] Start Options: #{options}"
138
143
  end
139
144
  end
140
145
  end
@@ -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
@@ -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
@@ -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, self.class.to_s, name
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, self.class.to_s, name
15
+ raise Exceptions::RookWriteAttributeNotSupported.new(self.class.to_s, name)
16
16
  end
17
17
 
18
18
  def read_key key
@@ -6,7 +6,7 @@ module Rookout
6
6
 
7
7
  require_relative "../../protobuf/variant_pb"
8
8
 
9
- class RubyUtilsNamespace < Namespace
9
+ class NoopNamespace < Namespace
10
10
  def initialize
11
11
  super
12
12
  end
@@ -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 == true || obj == false
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.RookClassCannotBeSerialized, obj.class, "Unknown Numeric Type"
107
+ raise Exceptions::RookClassCannotBeSerialized.new(obj.class, "Unknown Numeric Type")
108
108
  end
109
109
  # TODO: ADD SUPPORT FOR RATIONALS
110
110
  end