eye 0.1.11

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.
Files changed (190) hide show
  1. data/.gitignore +31 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +22 -0
  5. data/README.md +132 -0
  6. data/Rakefile +18 -0
  7. data/bin/eye +282 -0
  8. data/bin/loader_eye +56 -0
  9. data/examples/processes/em.rb +56 -0
  10. data/examples/processes/forking.rb +20 -0
  11. data/examples/processes/sample.rb +144 -0
  12. data/examples/rbenv.eye +11 -0
  13. data/examples/test.eye +65 -0
  14. data/examples/unicorn.eye +29 -0
  15. data/eye.gemspec +37 -0
  16. data/lib/eye.rb +25 -0
  17. data/lib/eye/application.rb +65 -0
  18. data/lib/eye/checker.rb +118 -0
  19. data/lib/eye/checker/cpu.rb +27 -0
  20. data/lib/eye/checker/file_ctime.rb +29 -0
  21. data/lib/eye/checker/file_size.rb +38 -0
  22. data/lib/eye/checker/http.rb +94 -0
  23. data/lib/eye/checker/memory.rb +27 -0
  24. data/lib/eye/checker/socket.rb +148 -0
  25. data/lib/eye/checker/validation.rb +49 -0
  26. data/lib/eye/child_process.rb +75 -0
  27. data/lib/eye/client.rb +32 -0
  28. data/lib/eye/control.rb +2 -0
  29. data/lib/eye/controller.rb +43 -0
  30. data/lib/eye/controller/commands.rb +64 -0
  31. data/lib/eye/controller/helpers.rb +61 -0
  32. data/lib/eye/controller/load.rb +224 -0
  33. data/lib/eye/controller/send_command.rb +88 -0
  34. data/lib/eye/controller/status.rb +136 -0
  35. data/lib/eye/dsl.rb +52 -0
  36. data/lib/eye/dsl/application_opts.rb +33 -0
  37. data/lib/eye/dsl/chain.rb +12 -0
  38. data/lib/eye/dsl/child_process_opts.rb +7 -0
  39. data/lib/eye/dsl/config_opts.rb +11 -0
  40. data/lib/eye/dsl/group_opts.rb +27 -0
  41. data/lib/eye/dsl/helpers.rb +12 -0
  42. data/lib/eye/dsl/main.rb +58 -0
  43. data/lib/eye/dsl/opts.rb +88 -0
  44. data/lib/eye/dsl/process_opts.rb +21 -0
  45. data/lib/eye/dsl/pure_opts.rb +132 -0
  46. data/lib/eye/dsl/validate.rb +41 -0
  47. data/lib/eye/group.rb +125 -0
  48. data/lib/eye/group/chain.rb +68 -0
  49. data/lib/eye/io/unix_server.rb +44 -0
  50. data/lib/eye/io/unix_socket.rb +39 -0
  51. data/lib/eye/loader.rb +13 -0
  52. data/lib/eye/logger.rb +80 -0
  53. data/lib/eye/process.rb +83 -0
  54. data/lib/eye/process/child.rb +61 -0
  55. data/lib/eye/process/commands.rb +256 -0
  56. data/lib/eye/process/config.rb +70 -0
  57. data/lib/eye/process/controller.rb +72 -0
  58. data/lib/eye/process/data.rb +46 -0
  59. data/lib/eye/process/monitor.rb +97 -0
  60. data/lib/eye/process/notify.rb +17 -0
  61. data/lib/eye/process/scheduler.rb +50 -0
  62. data/lib/eye/process/states.rb +92 -0
  63. data/lib/eye/process/states_history.rb +62 -0
  64. data/lib/eye/process/system.rb +60 -0
  65. data/lib/eye/process/trigger.rb +32 -0
  66. data/lib/eye/process/watchers.rb +67 -0
  67. data/lib/eye/server.rb +51 -0
  68. data/lib/eye/settings.rb +35 -0
  69. data/lib/eye/system.rb +145 -0
  70. data/lib/eye/system_resources.rb +83 -0
  71. data/lib/eye/trigger.rb +53 -0
  72. data/lib/eye/trigger/flapping.rb +24 -0
  73. data/lib/eye/utils.rb +5 -0
  74. data/lib/eye/utils/alive_array.rb +31 -0
  75. data/lib/eye/utils/celluloid_chain.rb +51 -0
  76. data/lib/eye/utils/leak_19.rb +7 -0
  77. data/lib/eye/utils/tail.rb +20 -0
  78. data/spec/checker/cpu_spec.rb +58 -0
  79. data/spec/checker/file_ctime_spec.rb +34 -0
  80. data/spec/checker/file_size_spec.rb +107 -0
  81. data/spec/checker/http_spec.rb +109 -0
  82. data/spec/checker/memory_spec.rb +64 -0
  83. data/spec/checker/socket_spec.rb +116 -0
  84. data/spec/checker_spec.rb +188 -0
  85. data/spec/child_process/child_process_spec.rb +46 -0
  86. data/spec/client_server_spec.rb +34 -0
  87. data/spec/controller/commands_spec.rb +92 -0
  88. data/spec/controller/controller_spec.rb +133 -0
  89. data/spec/controller/find_objects_spec.rb +150 -0
  90. data/spec/controller/group_spec.rb +110 -0
  91. data/spec/controller/intergration_spec.rb +327 -0
  92. data/spec/controller/load_spec.rb +326 -0
  93. data/spec/controller/races_spec.rb +70 -0
  94. data/spec/controller/stop_on_delete_spec.rb +157 -0
  95. data/spec/dsl/chain_spec.rb +140 -0
  96. data/spec/dsl/checks_spec.rb +202 -0
  97. data/spec/dsl/config_spec.rb +44 -0
  98. data/spec/dsl/dsl_spec.rb +73 -0
  99. data/spec/dsl/getter_spec.rb +223 -0
  100. data/spec/dsl/integration_spec.rb +311 -0
  101. data/spec/dsl/load_spec.rb +52 -0
  102. data/spec/dsl/process_spec.rb +330 -0
  103. data/spec/dsl/sub_procs_spec.rb +93 -0
  104. data/spec/dsl/with_server_spec.rb +104 -0
  105. data/spec/example/em.rb +57 -0
  106. data/spec/example/forking.rb +20 -0
  107. data/spec/example/sample.rb +154 -0
  108. data/spec/fixtures/dsl/0.rb +8 -0
  109. data/spec/fixtures/dsl/0a.rb +8 -0
  110. data/spec/fixtures/dsl/0c.rb +8 -0
  111. data/spec/fixtures/dsl/1.rb +5 -0
  112. data/spec/fixtures/dsl/bad.eye +6 -0
  113. data/spec/fixtures/dsl/configs/1.eye +3 -0
  114. data/spec/fixtures/dsl/configs/2.eye +1 -0
  115. data/spec/fixtures/dsl/configs/3.eye +1 -0
  116. data/spec/fixtures/dsl/configs/4.eye +3 -0
  117. data/spec/fixtures/dsl/empty.eye +20 -0
  118. data/spec/fixtures/dsl/include_test.eye +5 -0
  119. data/spec/fixtures/dsl/include_test/1.rb +6 -0
  120. data/spec/fixtures/dsl/include_test/ha.rb +4 -0
  121. data/spec/fixtures/dsl/include_test2.eye +5 -0
  122. data/spec/fixtures/dsl/integration.eye +30 -0
  123. data/spec/fixtures/dsl/integration2.eye +32 -0
  124. data/spec/fixtures/dsl/integration_locks.eye +30 -0
  125. data/spec/fixtures/dsl/integration_sor.eye +32 -0
  126. data/spec/fixtures/dsl/integration_sor2.eye +27 -0
  127. data/spec/fixtures/dsl/integration_sor3.eye +32 -0
  128. data/spec/fixtures/dsl/load.eye +25 -0
  129. data/spec/fixtures/dsl/load2.eye +7 -0
  130. data/spec/fixtures/dsl/load2_dup2.eye +13 -0
  131. data/spec/fixtures/dsl/load2_dup_pid.eye +7 -0
  132. data/spec/fixtures/dsl/load3.eye +10 -0
  133. data/spec/fixtures/dsl/load4.eye +7 -0
  134. data/spec/fixtures/dsl/load5.eye +8 -0
  135. data/spec/fixtures/dsl/load6.eye +17 -0
  136. data/spec/fixtures/dsl/load_dubls.eye +36 -0
  137. data/spec/fixtures/dsl/load_dup_ex_names.eye +15 -0
  138. data/spec/fixtures/dsl/load_error.eye +5 -0
  139. data/spec/fixtures/dsl/load_error_folder/load3.eye +10 -0
  140. data/spec/fixtures/dsl/load_error_folder/load4.eye +7 -0
  141. data/spec/fixtures/dsl/load_folder/load3.eye +10 -0
  142. data/spec/fixtures/dsl/load_folder/load4.eye +7 -0
  143. data/spec/fixtures/dsl/load_int.eye +8 -0
  144. data/spec/fixtures/dsl/load_int2.eye +13 -0
  145. data/spec/fixtures/dsl/load_logger.eye +26 -0
  146. data/spec/fixtures/dsl/load_logger2.eye +3 -0
  147. data/spec/fixtures/dsl/long_load.eye +5 -0
  148. data/spec/fixtures/dsl/subfolder1/proc1.rb +3 -0
  149. data/spec/fixtures/dsl/subfolder2.eye +9 -0
  150. data/spec/fixtures/dsl/subfolder2/common.rb +1 -0
  151. data/spec/fixtures/dsl/subfolder2/proc2.rb +3 -0
  152. data/spec/fixtures/dsl/subfolder2/sub/proc3.rb +6 -0
  153. data/spec/fixtures/dsl/subfolder3.eye +8 -0
  154. data/spec/fixtures/dsl/subfolder3/common.rb +1 -0
  155. data/spec/fixtures/dsl/subfolder3/proc4.rb +3 -0
  156. data/spec/fixtures/dsl/subfolder3/sub/proc5.rb +6 -0
  157. data/spec/fixtures/dsl/subfolder4.eye +6 -0
  158. data/spec/fixtures/dsl/subfolder4/a.rb +2 -0
  159. data/spec/fixtures/dsl/subfolder4/b.rb +1 -0
  160. data/spec/fixtures/dsl/subfolder4/c.rb +1 -0
  161. data/spec/mock_spec.rb +32 -0
  162. data/spec/process/checks/child_checks_spec.rb +79 -0
  163. data/spec/process/checks/cpu_spec.rb +114 -0
  164. data/spec/process/checks/ctime_spec.rb +43 -0
  165. data/spec/process/checks/fsize_spec.rb +22 -0
  166. data/spec/process/checks/http_spec.rb +52 -0
  167. data/spec/process/checks/intergration_spec.rb +32 -0
  168. data/spec/process/checks/memory_spec.rb +113 -0
  169. data/spec/process/child_process_spec.rb +125 -0
  170. data/spec/process/config_spec.rb +75 -0
  171. data/spec/process/controller_spec.rb +173 -0
  172. data/spec/process/monitoring_spec.rb +180 -0
  173. data/spec/process/restart_spec.rb +174 -0
  174. data/spec/process/scheduler_spec.rb +150 -0
  175. data/spec/process/start_spec.rb +261 -0
  176. data/spec/process/states_history_spec.rb +118 -0
  177. data/spec/process/stop_spec.rb +150 -0
  178. data/spec/process/system_spec.rb +100 -0
  179. data/spec/process/triggers/flapping_spec.rb +81 -0
  180. data/spec/process/update_config_spec.rb +63 -0
  181. data/spec/spec_helper.rb +120 -0
  182. data/spec/support/rr_celluloid.rb +36 -0
  183. data/spec/support/scheduler_hack.rb +16 -0
  184. data/spec/support/spec_support.rb +164 -0
  185. data/spec/system_resources_spec.rb +59 -0
  186. data/spec/system_spec.rb +170 -0
  187. data/spec/utils/alive_array_spec.rb +50 -0
  188. data/spec/utils/celluloid_chain_spec.rb +82 -0
  189. data/spec/utils/tail_spec.rb +21 -0
  190. metadata +558 -0
@@ -0,0 +1,49 @@
1
+ module Eye::Checker::Validation
2
+ class Error < Exception; end
3
+
4
+ def inherited(subclass)
5
+ subclass.validates = self.validates.clone
6
+ subclass.should_bes = self.should_bes.clone
7
+ subclass.defaults = self.defaults.clone
8
+ end
9
+
10
+ attr_accessor :validates, :should_bes, :defaults
11
+
12
+ def validates; @validates ||= {}; end
13
+ def should_bes; @should_bes ||= []; end
14
+ def defaults; @defaults ||= {}; end
15
+
16
+ def param(param, types = [], should_be = false, default = nil)
17
+ param = param.to_sym
18
+
19
+ validates[param] = types
20
+ should_bes << param if should_be
21
+ defaults[param] = default
22
+
23
+ define_method "#{param}" do
24
+ @options[param.to_sym] || default
25
+ end
26
+ end
27
+
28
+ def validate(options = {})
29
+ options.each do |param, value|
30
+ types = validates[param.to_sym]
31
+ unless types
32
+ if param.to_sym != :type
33
+ raise Error, "#{self.name} unknown param :#{param} value #{value.inspect}"
34
+ end
35
+ end
36
+
37
+ next if types.blank?
38
+
39
+ types = Array(types)
40
+ good = types.any?{|type| value.is_a?(type) }
41
+ raise Error, "#{self.name} bad param :#{param} value #{value.inspect}, type #{types.inspect}" unless good
42
+ end
43
+
44
+ should_bes.each do |param|
45
+ raise Error, "#{self.name} bad param :#{param}, value should be" unless options[param.to_sym] || defaults[param.to_sym]
46
+ end
47
+ end
48
+
49
+ end
@@ -0,0 +1,75 @@
1
+ require 'celluloid'
2
+
3
+ class Eye::ChildProcess
4
+ include Celluloid
5
+
6
+ # needs: kill_process
7
+ include Eye::Process::Commands
8
+
9
+ # easy config + defaults: prepare_config, c, []
10
+ include Eye::Process::Config
11
+
12
+ # conditional watchers: start_checkers
13
+ include Eye::Process::Watchers
14
+
15
+ # system methods: send_signal
16
+ include Eye::Process::System
17
+
18
+ # logger methods: info, ...
19
+ include Eye::Logger::Helpers
20
+
21
+ # self_status_data
22
+ include Eye::Process::Data
23
+
24
+ # manage notify methods
25
+ include Eye::Process::Notify
26
+
27
+ # scheduler
28
+ include Eye::Process::Scheduler
29
+
30
+ attr_reader :pid, :name, :config, :watchers
31
+
32
+ def initialize(pid, config = {}, logger_prefix = nil)
33
+ raise 'Empty pid' unless pid
34
+
35
+ @pid = pid
36
+ @config = prepare_config(config)
37
+ @name = '=child='
38
+
39
+ @logger = Eye::Logger.new("#{logger_prefix} child:#{pid}")
40
+
41
+ @watchers = {}
42
+
43
+ debug "start monitoring CHILD config: #{@config.inspect}"
44
+
45
+ start_checkers
46
+ end
47
+
48
+ def state
49
+ :up
50
+ end
51
+
52
+ def stop
53
+ kill_process
54
+ end
55
+
56
+ def restart
57
+ stop
58
+ end
59
+
60
+ def monitor
61
+ end
62
+
63
+ def unmonitor
64
+ end
65
+
66
+ def delete
67
+ remove_watchers
68
+ terminate
69
+ end
70
+
71
+ def status_data(debug = false)
72
+ self_status_data(debug)
73
+ end
74
+
75
+ end
@@ -0,0 +1,32 @@
1
+ require 'socket'
2
+ require 'timeout'
3
+
4
+ class Eye::Client
5
+ attr_reader :socket_path
6
+
7
+ def initialize(socket_path)
8
+ @socket_path = socket_path
9
+ end
10
+
11
+ def command(cmd, *args)
12
+ attempt_command([cmd, *args] * '|')
13
+ end
14
+
15
+ def attempt_command(pack)
16
+ Timeout.timeout(Eye::Settings.client_timeout) do
17
+ return send_request(pack)
18
+ end
19
+
20
+ rescue Timeout::Error, EOFError
21
+ :timeouted
22
+ end
23
+
24
+ def send_request(pack)
25
+ UNIXSocket.open(@socket_path) do |socket|
26
+ socket.puts(pack)
27
+ data = socket.read
28
+ res = Marshal.load(data) rescue :corrupred_marshal
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,2 @@
1
+ # controller global singlton
2
+ Eye::Control = Eye::Controller.new
@@ -0,0 +1,43 @@
1
+ require 'celluloid'
2
+
3
+ require 'yaml'
4
+ require 'active_support'
5
+ require 'active_support/core_ext/object/blank'
6
+ require 'active_support/core_ext/object/try'
7
+ require 'active_support/core_ext/numeric'
8
+ require 'active_support/core_ext/string/filters'
9
+
10
+ require_relative 'utils/leak_19'
11
+
12
+ Eye.send(:extend, Eye::Logger::Helpers)
13
+
14
+ class Eye::Controller
15
+ include Celluloid
16
+
17
+ autoload :Load, 'eye/controller/load'
18
+ autoload :Helpers, 'eye/controller/helpers'
19
+ autoload :Commands, 'eye/controller/commands'
20
+ autoload :Status, 'eye/controller/status'
21
+ autoload :SendCommand, 'eye/controller/send_command'
22
+
23
+ include Eye::Logger::Helpers
24
+ include Eye::Controller::Load
25
+ include Eye::Controller::Helpers
26
+ include Eye::Controller::Commands
27
+ include Eye::Controller::Status
28
+ include Eye::Controller::SendCommand
29
+
30
+ attr_reader :applications, :current_config
31
+
32
+ def initialize
33
+ @applications = []
34
+ @current_config = Eye::Dsl.initial_config
35
+
36
+ Eye.instance_variable_set(:@logger, Eye::Logger.new('eye'))
37
+ @logger = Eye.logger
38
+ Celluloid::logger = Eye.logger
39
+
40
+ Eye::SystemResources.setup
41
+ end
42
+
43
+ end
@@ -0,0 +1,64 @@
1
+ module Eye::Controller::Commands
2
+
3
+ # Main method, answer for the client command
4
+ def command(cmd, *args)
5
+ debug "client command: #{cmd} #{args * ', '}"
6
+
7
+ start_at = Time.now
8
+ cmd = cmd.to_sym
9
+
10
+ res = case cmd
11
+ when :start, :stop, :restart, :unmonitor, :monitor
12
+ send_command(cmd, *args)
13
+ when :delete
14
+ exclusive{ send_command(cmd, *args) }
15
+ when :signal
16
+ signal(*args)
17
+ when :load
18
+ exclusive{ load(*args) }
19
+ when :info
20
+ info_string(*args)
21
+ when :object_info
22
+ info_data(*args)
23
+ when :xinfo
24
+ info_string_debug(*args)
25
+ when :oinfo
26
+ info_string_short
27
+ when :quit
28
+ quit
29
+ when :check
30
+ check(*args)
31
+ when :explain
32
+ explain(*args)
33
+ when :match
34
+ match(*args)
35
+ when :ping
36
+ :pong
37
+ when :logger_dev
38
+ Eye::Logger.dev
39
+ else
40
+ :unknown_command
41
+ end
42
+
43
+ GC.start
44
+ info "client command: #{cmd} #{args * ', '} (#{Time.now - start_at}s)"
45
+
46
+ res
47
+ end
48
+
49
+ private
50
+
51
+ def quit
52
+ info 'exiting...'
53
+ delete
54
+ sleep 1
55
+ Eye::System.send_signal($$) # soft terminate
56
+ sleep 2
57
+ Eye::System.send_signal($$, 9)
58
+ end
59
+
60
+ def delete
61
+ send_command(:delete)
62
+ end
63
+
64
+ end
@@ -0,0 +1,61 @@
1
+ module Eye::Controller::Helpers
2
+
3
+ def set_proc_line
4
+ str = "eye monitoring v#{Eye::VERSION}"
5
+ str += " (#{@applications.map(&:name) * ', '})" if @applications.present?
6
+ $0 = str
7
+ end
8
+
9
+ def process_by_name(name)
10
+ all_processes.detect{|c| c.name == name}
11
+ end
12
+
13
+ def group_by_name(name)
14
+ all_groups.detect{|c| c.name == name}
15
+ end
16
+
17
+ def application_by_name(name)
18
+ @applications.detect{|c| c.name == name}
19
+ end
20
+
21
+ def all_processes
22
+ processes = []
23
+ all_groups.each do |gr|
24
+ processes += gr.processes.to_a
25
+ end
26
+
27
+ processes
28
+ end
29
+
30
+ def all_groups
31
+ groups = []
32
+ @applications.each do |app|
33
+ groups += app.groups.to_a
34
+ end
35
+
36
+ groups
37
+ end
38
+
39
+ # {'app_name' => {'group_name' => {'process_name' => 'pid_file'}}}
40
+ def short_tree
41
+ res = {}
42
+ @applications.each do |app|
43
+ res2 = {}
44
+
45
+ app.groups.each do |group|
46
+ res3 = {}
47
+
48
+ group.processes.each do |process|
49
+ res3[process.name] = process[:pid_file_ex]
50
+ end
51
+
52
+ res2[group.name] = res3
53
+ end
54
+
55
+ res[app.name] = res2
56
+ end
57
+
58
+ res
59
+ end
60
+
61
+ end
@@ -0,0 +1,224 @@
1
+ module Eye::Controller::Load
2
+ include Eye::Dsl::Validate
3
+
4
+ def check(filename = '')
5
+ catch_load_error(filename) do
6
+ parse_config(filename)
7
+ end
8
+ end
9
+
10
+ def explain(filename)
11
+ catch_load_error(filename) do
12
+ parse_set_of_configs(filename)
13
+ end
14
+ end
15
+
16
+ # filename is a path, or folder, or mask
17
+ def load(filename = '')
18
+ catch_load_error(filename) do
19
+ _load(filename)
20
+ set_proc_line
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ # regexp for clean backtrace to show for user
27
+ BT_REGX = %r[/lib/eye/|lib/celluloid|internal:prelude|logger.rb:].freeze
28
+
29
+ def catch_load_error(filename, &block)
30
+ res = block.call
31
+
32
+ {:error => false, :config => res}
33
+ rescue Eye::Dsl::Error, Exception, NoMethodError => ex
34
+ error "load: config error <#{filename}>: #{ex.message}"
35
+
36
+ # filter backtrace for user output
37
+ bt = (ex.backtrace || []).reject{|line| line.to_s =~ BT_REGX }
38
+ error bt.join("\n")
39
+
40
+ res = {:error => true, :message => ex.message}
41
+ res.merge!(:backtrace => bt) if bt.present?
42
+ res
43
+ end
44
+
45
+ # return: result, config
46
+ def parse_config(filename = '', &block)
47
+ raise Eye::Dsl::Error, "config file '#{filename}' not found!" unless File.exists?(filename)
48
+
49
+ cfg = Eye::Dsl.parse(nil, filename)
50
+ validate( merge_configs(@current_config, cfg) )
51
+
52
+ cfg
53
+ end
54
+
55
+ def parse_set_of_configs(filename)
56
+ mask = if File.directory?(filename)
57
+ File.join filename, '{*.eye}'
58
+ else
59
+ filename
60
+ end
61
+
62
+ debug "load: globbing mask #{mask}"
63
+ configs = []
64
+
65
+ Dir[mask].each do |config_path|
66
+ info "load: config #{config_path}"
67
+ configs << parse_config(config_path)
68
+ end
69
+
70
+ raise Eye::Dsl::Error, "config file '#{mask}' not found!" if configs.blank?
71
+
72
+ new_cfg = @current_config
73
+ configs.each do |cfg|
74
+ new_cfg = merge_configs(new_cfg, cfg)
75
+ end
76
+
77
+ validate(new_cfg)
78
+
79
+ new_cfg
80
+ end
81
+
82
+ def _load(filename)
83
+ new_cfg = parse_set_of_configs(filename)
84
+
85
+ load_config(new_cfg)
86
+
87
+ GC.start
88
+ end
89
+
90
+ def load_config(new_config)
91
+ load_options(new_config[:config])
92
+ create_objects(new_config[:applications])
93
+ @current_config = new_config
94
+ end
95
+
96
+ def merge_configs(old_config, new_config)
97
+ {:config => old_config[:config].merge(new_config[:config]),
98
+ :applications => old_config[:applications].merge(new_config[:applications])}
99
+ end
100
+
101
+ # load global config options
102
+ def load_options(opts)
103
+ return if opts.blank?
104
+
105
+ if opts[:logger]
106
+ # do not apply logger, if in stdout state
107
+ if !%w{stdout stderr}.include?(Eye::Logger.dev)
108
+ if opts[:logger].blank?
109
+ Eye::Logger.link_logger(nil)
110
+ else
111
+ Eye::Logger.link_logger(opts[:logger])
112
+ end
113
+ end
114
+
115
+ Eye::Logger.log_level = opts[:logger_level] if opts[:logger_level]
116
+ end
117
+ end
118
+
119
+ # create objects as diff, from configs
120
+ def create_objects(apps_config)
121
+ debug 'create objects'
122
+ apps_config.each do |app_name, app_cfg|
123
+ update_or_create_application(app_name, app_cfg.clone)
124
+ end
125
+
126
+ # sorting applications
127
+ @applications.sort_by!(&:name)
128
+ end
129
+
130
+ def update_or_create_application(app_name, app_config)
131
+ @old_groups = {}
132
+ @old_processes = {}
133
+
134
+ app = @applications.detect{|c| c.name == app_name}
135
+
136
+ if app
137
+ app.groups.each do |group|
138
+ @old_groups[group.name] = group
139
+ group.processes.each do |proc|
140
+ @old_processes[proc.name] = proc
141
+ end
142
+ end
143
+
144
+ @applications.delete(app)
145
+
146
+ debug "update app #{app_name}"
147
+ else
148
+ debug "create app #{app_name}"
149
+ end
150
+
151
+ app = Eye::Application.new(app_name, app_config)
152
+ @applications << app
153
+ @added_groups, @added_processes = [], []
154
+
155
+ new_groups = app_config.delete(:groups) || {}
156
+ new_groups.each do |group_name, group_cfg|
157
+ group = update_or_create_group(group_name, group_cfg.clone)
158
+ app.add_group(group)
159
+ group.resort_processes
160
+ end
161
+
162
+ # now, need to clear @old_groups, and @old_processes
163
+ @old_groups.each{|_, group| group.clear; group.send_command(:delete) }
164
+ @old_processes.each{|_, process| process.send_command(:delete) if process.alive? }
165
+
166
+ # schedule monitoring for new groups, processes
167
+ added_fully_groups = []
168
+ @added_groups.each do |group|
169
+ if group.processes.size > 0 && (group.processes.pure - @added_processes).size == 0
170
+ added_fully_groups << group
171
+ @added_processes -= group.processes.pure
172
+ end
173
+ end
174
+
175
+ added_fully_groups.each{|group| group.send_command :monitor }
176
+ @added_processes.each{|process| process.send_command :monitor }
177
+
178
+ # remove links to prevent memory leaks
179
+ @old_groups = nil
180
+ @old_processes = nil
181
+ @added_groups = nil
182
+ @added_processes = nil
183
+
184
+ app
185
+ end
186
+
187
+ def update_or_create_group(group_name, group_config)
188
+ group = if @old_groups[group_name]
189
+ debug "update group #{group_name}"
190
+ group = @old_groups.delete(group_name)
191
+ group.schedule :update_config, group_config, 'load config'
192
+ group.clear
193
+ group
194
+ else
195
+ debug "create group #{group_name}"
196
+ gr = Eye::Group.new(group_name, group_config)
197
+ @added_groups << gr
198
+ gr
199
+ end
200
+
201
+ processes = group_config.delete(:processes) || {}
202
+ processes.each do |process_name, process_cfg|
203
+ process = update_or_create_process(process_name, process_cfg.clone)
204
+ group.add_process(process)
205
+ end
206
+
207
+ group
208
+ end
209
+
210
+ def update_or_create_process(process_name, process_cfg)
211
+ if @old_processes[process_name]
212
+ debug "update process #{process_name}"
213
+ process = @old_processes.delete(process_name)
214
+ process.schedule :update_config, process_cfg, 'load config'
215
+ process
216
+ else
217
+ debug "create process #{process_name}"
218
+ process = Eye::Process.new(process_cfg)
219
+ @added_processes << process
220
+ process
221
+ end
222
+ end
223
+
224
+ end