eye 0.3.2 → 0.4

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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rspec +1 -1
  4. data/.travis.yml +3 -1
  5. data/CHANGES.md +11 -2
  6. data/Gemfile +1 -0
  7. data/README.md +18 -14
  8. data/Rakefile +10 -3
  9. data/bin/eye +41 -27
  10. data/examples/process_thin.rb +1 -1
  11. data/examples/processes/em.rb +2 -2
  12. data/examples/processes/forking.rb +2 -2
  13. data/examples/processes/sample.rb +5 -5
  14. data/examples/rbenv.eye +1 -1
  15. data/examples/sidekiq.eye +2 -2
  16. data/examples/test.eye +10 -6
  17. data/examples/thin-farm.eye +1 -1
  18. data/examples/unicorn.eye +1 -1
  19. data/eye.gemspec +13 -7
  20. data/lib/eye.rb +6 -6
  21. data/lib/eye/application.rb +9 -6
  22. data/lib/eye/checker.rb +51 -21
  23. data/lib/eye/checker/file_size.rb +1 -1
  24. data/lib/eye/checker/http.rb +3 -3
  25. data/lib/eye/checker/memory.rb +1 -1
  26. data/lib/eye/checker/socket.rb +6 -6
  27. data/lib/eye/child_process.rb +7 -11
  28. data/lib/eye/client.rb +6 -6
  29. data/lib/eye/config.rb +2 -2
  30. data/lib/eye/controller.rb +11 -8
  31. data/lib/eye/controller/commands.rb +8 -9
  32. data/lib/eye/controller/helpers.rb +1 -0
  33. data/lib/eye/controller/load.rb +11 -7
  34. data/lib/eye/controller/send_command.rb +44 -19
  35. data/lib/eye/controller/show_history.rb +8 -7
  36. data/lib/eye/controller/status.rb +39 -26
  37. data/lib/eye/dsl.rb +3 -3
  38. data/lib/eye/dsl/application_opts.rb +4 -4
  39. data/lib/eye/dsl/config_opts.rb +4 -4
  40. data/lib/eye/dsl/helpers.rb +2 -2
  41. data/lib/eye/dsl/main.rb +2 -2
  42. data/lib/eye/dsl/opts.rb +19 -14
  43. data/lib/eye/dsl/process_opts.rb +1 -1
  44. data/lib/eye/dsl/pure_opts.rb +2 -2
  45. data/lib/eye/dsl/validation.rb +7 -5
  46. data/lib/eye/group.rb +17 -11
  47. data/lib/eye/group/chain.rb +3 -3
  48. data/lib/eye/loader.rb +8 -6
  49. data/lib/eye/logger.rb +14 -5
  50. data/lib/eye/notify.rb +13 -7
  51. data/lib/eye/notify/jabber.rb +2 -2
  52. data/lib/eye/notify/mail.rb +2 -2
  53. data/lib/eye/process.rb +10 -13
  54. data/lib/eye/process/child.rb +1 -1
  55. data/lib/eye/process/commands.rb +34 -32
  56. data/lib/eye/process/config.rb +17 -12
  57. data/lib/eye/process/controller.rb +3 -6
  58. data/lib/eye/process/data.rb +16 -5
  59. data/lib/eye/process/monitor.rb +12 -5
  60. data/lib/eye/process/notify.rb +1 -1
  61. data/lib/eye/process/scheduler.rb +3 -3
  62. data/lib/eye/process/states.rb +10 -13
  63. data/lib/eye/process/states_history.rb +3 -3
  64. data/lib/eye/process/system.rb +17 -21
  65. data/lib/eye/process/trigger.rb +11 -30
  66. data/lib/eye/process/watchers.rb +9 -9
  67. data/lib/eye/server.rb +14 -6
  68. data/lib/eye/settings.rb +4 -4
  69. data/lib/eye/system.rb +10 -7
  70. data/lib/eye/system_resources.rb +4 -4
  71. data/lib/eye/trigger.rb +58 -21
  72. data/lib/eye/trigger/flapping.rb +24 -4
  73. data/lib/eye/trigger/state.rb +28 -0
  74. data/lib/eye/utils/alive_array.rb +1 -1
  75. data/lib/eye/utils/celluloid_klass.rb +5 -0
  76. data/lib/eye/utils/pmap.rb +7 -0
  77. data/lib/eye/utils/tail.rb +1 -1
  78. metadata +39 -23
  79. data/lib/eye/utils/leak_19.rb +0 -7
@@ -27,13 +27,13 @@ class Eye::Dsl
27
27
  def parse(content = nil, filename = nil)
28
28
  Eye.parsed_config = Eye::Config.new
29
29
  Eye.parsed_filename = filename
30
-
30
+
31
31
  content = File.read(filename) if content.blank?
32
-
32
+
33
33
  silence_warnings do
34
34
  Kernel.eval(content, Eye::BINDING, filename.to_s)
35
35
  end
36
-
36
+
37
37
  Eye.parsed_config.validate!
38
38
  Eye.parsed_config
39
39
  end
@@ -10,11 +10,11 @@ class Eye::Dsl::ApplicationOpts < Eye::Dsl::Opts
10
10
  [:groups]
11
11
  end
12
12
 
13
- def group(name, &block)
13
+ def group(name, &block)
14
14
  Eye::Dsl.debug "=> group #{name}"
15
-
15
+
16
16
  opts = Eye::Dsl::GroupOpts.new(name, self)
17
- opts.instance_eval(&block)
17
+ opts.instance_eval(&block)
18
18
  if cfg = opts.config
19
19
  @config[:groups] ||= {}
20
20
 
@@ -22,7 +22,7 @@ class Eye::Dsl::ApplicationOpts < Eye::Dsl::Opts
22
22
  @config[:groups][name.to_s] ||= {}
23
23
  @config[:groups][name.to_s].merge!(cfg)
24
24
  @config[:groups][name.to_s][:processes] ||= {}
25
- @config[:groups][name.to_s][:processes].merge!(processes)
25
+ @config[:groups][name.to_s][:processes].merge!(processes)
26
26
  end
27
27
 
28
28
  Eye::Dsl.debug "<= group #{name}"
@@ -3,7 +3,7 @@ class Eye::Dsl::ConfigOpts < Eye::Dsl::PureOpts
3
3
  create_options_methods([:logger], String)
4
4
  create_options_methods([:logger_level], Fixnum)
5
5
  create_options_methods([:http], Hash)
6
-
6
+
7
7
  def set_logger(logger)
8
8
  logger.blank? ? super('') : super
9
9
  end
@@ -21,7 +21,7 @@ class Eye::Dsl::ConfigOpts < Eye::Dsl::PureOpts
21
21
  end
22
22
 
23
23
  def contact(contact_name, contact_type, contact, contact_opts = {})
24
- raise Eye::Dsl::Error, "unknown contact_type #{contact_type}" unless Eye::Notify::TYPES[contact_type]
24
+ raise Eye::Dsl::Error, "unknown contact_type #{contact_type}" unless Eye::Notify::TYPES[contact_type]
25
25
  raise Eye::Dsl::Error, "contact should be a String" unless contact.is_a?(String)
26
26
 
27
27
  notify_hash = @config[contact_type] || (@parent && @parent.config[contact_type]) || Eye::parsed_config.settings[contact_type] || {}
@@ -30,7 +30,7 @@ class Eye::Dsl::ConfigOpts < Eye::Dsl::PureOpts
30
30
  Eye::Notify.validate!(validate_hash)
31
31
 
32
32
  @config[:contacts] ||= {}
33
- @config[:contacts][contact_name.to_s] = {name: contact_name.to_s, type: contact_type,
33
+ @config[:contacts][contact_name.to_s] = {name: contact_name.to_s, type: contact_type,
34
34
  contact: contact, opts: contact_opts}
35
35
  end
36
36
 
@@ -44,5 +44,5 @@ class Eye::Dsl::ConfigOpts < Eye::Dsl::PureOpts
44
44
  @config[:contacts].merge!(cfg[:contacts])
45
45
  end
46
46
  end
47
-
47
+
48
48
  end
@@ -1,5 +1,5 @@
1
1
 
2
- # Dsl Helpers
2
+ # Dsl Helpers
3
3
 
4
4
  # current eye parsed config path
5
5
  def current_config_path
@@ -8,5 +8,5 @@ end
8
8
 
9
9
  # host name
10
10
  def hostname
11
- Eye::System.host
11
+ Eye::System.host
12
12
  end
@@ -2,7 +2,7 @@ module Eye::Dsl::Main
2
2
  attr_accessor :parsed_config, :parsed_filename
3
3
 
4
4
  def application(name, &block)
5
- Eye::Dsl.debug "=> app: #{name}"
5
+ Eye::Dsl.debug "=> app: #{name}"
6
6
  opts = Eye::Dsl::ApplicationOpts.new(name)
7
7
  opts.instance_eval(&block)
8
8
 
@@ -36,5 +36,5 @@ module Eye::Dsl::Main
36
36
 
37
37
  Eye::Dsl.debug "<= config"
38
38
  end
39
-
39
+
40
40
  end
@@ -1,14 +1,14 @@
1
1
  class Eye::Dsl::Opts < Eye::Dsl::PureOpts
2
2
 
3
- STR_OPTIONS = [ :pid_file, :working_dir, :stdout, :stderr, :stdall, :start_command,
3
+ STR_OPTIONS = [ :pid_file, :working_dir, :stdout, :stderr, :stdall, :start_command,
4
4
  :stop_command, :restart_command, :uid, :gid ]
5
5
  create_options_methods(STR_OPTIONS, String)
6
6
 
7
- BOOL_OPTIONS = [ :daemonize, :keep_alive, :control_pid, :auto_start, :stop_on_delete]
7
+ BOOL_OPTIONS = [ :daemonize, :keep_alive, :auto_start, :stop_on_delete, :clear_pid ]
8
8
  create_options_methods(BOOL_OPTIONS, [TrueClass, FalseClass])
9
9
 
10
10
  INTERVAL_OPTIONS = [ :check_alive_period, :start_timeout, :restart_timeout, :stop_timeout, :start_grace,
11
- :restart_grace, :stop_grace, :childs_update_period ]
11
+ :restart_grace, :stop_grace, :childs_update_period, :restore_in ]
12
12
  create_options_methods(INTERVAL_OPTIONS, [Fixnum, Float])
13
13
 
14
14
  create_options_methods([:environment], Hash)
@@ -32,20 +32,20 @@ class Eye::Dsl::Opts < Eye::Dsl::PureOpts
32
32
 
33
33
  opts.merge!(:type => nac[:type])
34
34
  Eye::Checker.validate!(opts)
35
-
35
+
36
36
  @config[:checks] ||= {}
37
37
  @config[:checks][nac[:name]] = opts
38
38
  end
39
39
 
40
40
  def triggers(type, opts = {})
41
- type = type.to_sym
42
- raise Eye::Dsl::Error, "unknown trigger type #{type}" unless Eye::Trigger::TYPES[type]
43
-
44
- opts.merge!(:type => type)
41
+ nac = Eye::Trigger.name_and_class(type.to_sym)
42
+ raise Eye::Dsl::Error, "unknown trigger type #{type}" unless nac
43
+
44
+ opts.merge!(:type => nac[:type])
45
45
  Eye::Trigger.validate!(opts)
46
46
 
47
47
  @config[:triggers] ||= {}
48
- @config[:triggers][type] = opts
48
+ @config[:triggers][nac[:name]] = opts
49
49
  end
50
50
 
51
51
  # clear checks from parent
@@ -57,14 +57,19 @@ class Eye::Dsl::Opts < Eye::Dsl::PureOpts
57
57
 
58
58
  # clear triggers from parent
59
59
  def notriggers(type)
60
- type = type.to_sym
61
- raise Eye::Dsl::Error, "unknown trigger type #{type}" unless Eye::Trigger::TYPES[type]
62
- @config[:triggers].try :delete, type
60
+ nac = Eye::Trigger.name_and_class(type.to_sym)
61
+ raise Eye::Dsl::Error, "unknown trigger type #{type}" unless nac
62
+ @config[:triggers].try :delete, nac[:name]
63
63
  end
64
64
 
65
+ alias check checks
66
+ alias nocheck nochecks
67
+ alias trigger triggers
68
+ alias notrigger notriggers
69
+
65
70
  def notify(contact, level = :warn)
66
71
  unless Eye::Process::Notify::LEVELS[level]
67
- raise Eye::Dsl::Error, "level should be in #{Eye::Process::Notify::LEVELS.keys}"
72
+ raise Eye::Dsl::Error, "level should be in #{Eye::Process::Notify::LEVELS.keys}"
68
73
  end
69
74
 
70
75
  @config[:notify] ||= {}
@@ -125,7 +130,7 @@ class Eye::Dsl::Opts < Eye::Dsl::PureOpts
125
130
  def with_server(glob = nil, &block)
126
131
  on_server = true
127
132
 
128
- if glob.present?
133
+ if glob.present?
129
134
  host = Eye::System.host
130
135
 
131
136
  if glob.is_a?(Array)
@@ -2,7 +2,7 @@ class Eye::Dsl::ProcessOpts < Eye::Dsl::Opts
2
2
 
3
3
  def monitor_children(&block)
4
4
  opts = Eye::Dsl::ChildProcessOpts.new
5
- opts.instance_eval(&block)
5
+ opts.instance_eval(&block) if block
6
6
  @config[:monitor_children] ||= {}
7
7
  @config[:monitor_children].merge!(opts.config)
8
8
  end
@@ -44,7 +44,7 @@ class Eye::Dsl::PureOpts
44
44
  attr_reader :config, :parent
45
45
 
46
46
  def initialize(name = nil, parent = nil, merge_parent_config = true)
47
- @name = name.to_s
47
+ @name = name.to_s
48
48
  @full_name = @name
49
49
 
50
50
  if parent
@@ -84,7 +84,7 @@ class Eye::Dsl::PureOpts
84
84
  self.class.with_parsed_file(proc) do |path|
85
85
  if File.exists?(path)
86
86
  Eye::Dsl.debug "=> load #{path}"
87
- self.instance_eval(File.read(path))
87
+ self.instance_eval(File.read(path))
88
88
  Eye::Dsl.debug "<= load #{path}"
89
89
  end
90
90
  end
@@ -23,24 +23,26 @@ module Eye::Dsl::Validation
23
23
  defaults[param] = default
24
24
  variants[param] = _variants
25
25
 
26
+ return if param == :do
27
+
26
28
  define_method "#{param}" do
27
- @options[param.to_sym] || default
29
+ @options[param] || default
28
30
  end
29
31
  end
30
32
 
31
- def validate(options = {})
32
- options.each do |param, value|
33
+ def validate(options = {})
34
+ options.each do |param, value|
33
35
  param = param.to_sym
34
36
  types = validates[param]
35
37
  unless types
36
38
  if param != :type
37
- raise Error, "#{self.name} unknown param :#{param} value #{value.inspect}"
39
+ raise Error, "#{self.name} unknown param :#{param} value #{value.inspect}"
38
40
  end
39
41
  end
40
42
 
41
43
  if self.variants[param]
42
44
  if value && !value.is_a?(Proc) && !self.variants[param].include?(value)
43
- raise Error, "#{value.inspect} should within #{self.variants[param].inspect}"
45
+ raise Error, "#{value.inspect} should within #{self.variants[param].inspect}"
44
46
  end
45
47
  end
46
48
 
@@ -5,7 +5,6 @@ class Eye::Group
5
5
 
6
6
  autoload :Chain, 'eye/group/chain'
7
7
 
8
- include Eye::Logger::Helpers
9
8
  include Eye::Process::Scheduler
10
9
  include Eye::Group::Chain
11
10
 
@@ -14,14 +13,21 @@ class Eye::Group
14
13
  def initialize(name, config)
15
14
  @name = name
16
15
  @config = config
17
- @logger = Eye::Logger.new(full_name)
18
16
  @processes = Eye::Utils::AliveArray.new
19
17
  @hidden = (name == '__default__')
20
18
  debug 'created'
21
19
  end
22
20
 
21
+ def logger_tag
22
+ full_name
23
+ end
24
+
25
+ def app_name
26
+ @config[:application]
27
+ end
28
+
23
29
  def full_name
24
- @full_name ||= "#{@config[:application]}:#{@name}"
30
+ @full_name ||= "#{app_name}:#{@name}"
25
31
  end
26
32
 
27
33
  def update_config(cfg)
@@ -47,14 +53,14 @@ class Eye::Group
47
53
 
48
54
  # show current chain
49
55
  if current_scheduled_command
50
- h.update(current_command: current_scheduled_command)
56
+ h.update(current_command: current_scheduled_command)
51
57
 
52
58
  if (chain_commands = scheduler_actions_list) && chain_commands.present?
53
- h.update(chain_commands: chain_commands)
59
+ h.update(chain_commands: chain_commands)
54
60
  end
55
61
 
56
62
  if @chain_processes_current && @chain_processes_count
57
- h.update(chain_progress: [@chain_processes_current, @chain_processes_count])
63
+ h.update(chain_progress: [@chain_processes_current, @chain_processes_count])
58
64
  end
59
65
  end
60
66
 
@@ -71,9 +77,9 @@ class Eye::Group
71
77
  case command
72
78
  when :delete
73
79
  delete *args
74
- when :break_chain
80
+ when :break_chain
75
81
  break_chain *args
76
- else
82
+ else
77
83
  schedule command, *args, Eye::Reason::User.new(command)
78
84
  end
79
85
  end
@@ -110,7 +116,7 @@ class Eye::Group
110
116
  def break_chain
111
117
  info "break chain"
112
118
  scheduler_clear_pending_list
113
- @chain_breaker = true
119
+ @chain_breaker = true
114
120
  end
115
121
 
116
122
  def clear
@@ -125,10 +131,10 @@ private
125
131
 
126
132
  def async_schedule(command, *args)
127
133
  info "send to all processes #{command} #{args.present? ? args*',' : nil}"
128
-
134
+
129
135
  @processes.each do |process|
130
136
  process.send_command(command, *args)
131
- end
137
+ end
132
138
  end
133
139
 
134
140
  end
@@ -17,7 +17,7 @@ private
17
17
  @chain_processes_current = @chain_processes_current.to_i + 1
18
18
 
19
19
  # to skip last sleep
20
- break if @chain_processes_current.to_i == @chain_processes_count.to_i
20
+ break if @chain_processes_current.to_i == @chain_processes_count.to_i
21
21
  break if @chain_breaker
22
22
 
23
23
  # wait next process
@@ -34,7 +34,7 @@ private
34
34
 
35
35
  def chain_schedule_process(process, type, command, *args)
36
36
  debug "chain_schedule_process #{process.name} #{type} #{command}"
37
-
37
+
38
38
  if type == :sync
39
39
  # sync command, with waiting
40
40
  # this is very hackety, because call method of the process without its scheduler
@@ -73,7 +73,7 @@ private
73
73
 
74
74
  {:type => type, :grace => grace}
75
75
  else
76
- # default chain case
76
+ # default chain case
77
77
  {:type => :async, :grace => DEFAULT_CHAIN}
78
78
  end
79
79
  end
@@ -1,12 +1,14 @@
1
1
  # mini bundler, for embedded server gem installation
2
2
 
3
- gem 'celluloid', '~> 0.13.0'
4
- gem 'celluloid-io', '~> 0.13.0'
3
+ gem 'celluloid', '~> 0.14.0'
4
+ gem 'celluloid-io', '~> 0.14.0'
5
5
  gem 'nio4r'
6
6
  gem 'timers'
7
7
 
8
- gem 'state_machine', '< 1.2'
9
- gem 'activesupport', '~> 3.2.0'
8
+ gem 'state_machine'
10
9
 
11
- gem 'i18n' # for as
12
- gem 'multi_json' # for as
10
+ if RUBY_VERSION == '1.9.2'
11
+ gem 'activesupport', '>= 3', '< 4.0'
12
+ else
13
+ gem 'activesupport', '>= 3'
14
+ end
@@ -11,17 +11,26 @@ class Eye::Logger
11
11
 
12
12
  self.formatter = Proc.new do |s, d, p, m|
13
13
  "#{d.strftime(FORMAT)} #{s.ljust(5)} -- #{m}\n"
14
- end
14
+ end
15
15
  end
16
16
  end
17
17
 
18
- module Helpers
19
- attr_reader :logger
18
+ module ObjectExt
19
+ def logger_tag
20
+ [Class, Module].include?(self.class) ? to_s : "<#{self.class.to_s}>"
21
+ end
22
+
23
+ def logger_sub_tag
24
+ end
25
+
26
+ def logger
27
+ @logger ||= Eye::Logger.new(logger_tag, logger_sub_tag)
28
+ end
20
29
 
21
30
  Logger::Severity.constants.each do |level|
22
31
  method_name = level.to_s.downcase
23
32
  define_method method_name do |msg|
24
- @logger.send(method_name, msg)
33
+ logger.send(method_name, msg)
25
34
  end
26
35
  end
27
36
  end
@@ -47,7 +56,7 @@ class Eye::Logger
47
56
 
48
57
  @dev_fd = STDOUT if @dev.to_s.downcase == 'stdout'
49
58
  @dev_fd = STDERR if @dev.to_s.downcase == 'stderr'
50
-
59
+
51
60
  @inner_logger = InnerLogger.new(@dev_fd)
52
61
  @inner_logger.level = self.log_level || Logger::INFO
53
62
  end
@@ -1,6 +1,5 @@
1
1
  class Eye::Notify
2
2
  include Celluloid
3
- include Eye::Logger::Helpers
4
3
  extend Eye::Dsl::Validation
5
4
 
6
5
  autoload :Mail, 'eye/notify/mail'
@@ -19,10 +18,14 @@ class Eye::Notify
19
18
  end
20
19
 
21
20
  def self.notify(contact, message_h)
21
+ contact = contact.to_s
22
22
  settings = Eye::Control.settings
23
- needed_hash = (settings[:contacts] || {})[contact.to_s]
23
+ needed_hash = (settings[:contacts] || {})[contact]
24
24
 
25
- return if needed_hash.blank?
25
+ if needed_hash.blank?
26
+ error "not found contact #{contact}! something wrong with config"
27
+ return
28
+ end
26
29
 
27
30
  create_proc = lambda do |nh|
28
31
  type = nh[:type]
@@ -42,11 +45,14 @@ class Eye::Notify
42
45
  TIMEOUT = 1.minute
43
46
 
44
47
  def initialize(options = {}, message_h = {})
45
- @logger = Eye::Logger.new("#{self.class.name.downcase} - #{options[:contact]}")
46
- debug "created notifier #{options}"
47
-
48
48
  @message_h = message_h
49
49
  @options = options
50
+
51
+ debug "created notifier #{options}"
52
+ end
53
+
54
+ def logger_sub_tag
55
+ @options[:contact]
50
56
  end
51
57
 
52
58
  def async_notify
@@ -70,7 +76,7 @@ class Eye::Notify
70
76
  def message_subject
71
77
  "[#{msg_host}] [#{msg_full_name}] #{msg_message}"
72
78
  end
73
-
79
+
74
80
  def message_body
75
81
  "#{message_subject} at #{msg_at.to_s(:short)}"
76
82
  end