ace-eye 0.6.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.
- checksums.yaml +7 -0
- data/.gitignore +38 -0
- data/.rspec +2 -0
- data/.travis.yml +6 -0
- data/CHANGES.md +77 -0
- data/Gemfile +6 -0
- data/LICENSE +22 -0
- data/README.md +212 -0
- data/Rakefile +35 -0
- data/bin/eye +5 -0
- data/bin/loader_eye +72 -0
- data/bin/runner +16 -0
- data/examples/dependency.eye +17 -0
- data/examples/notify.eye +19 -0
- data/examples/plugin/README.md +15 -0
- data/examples/plugin/main.eye +15 -0
- data/examples/plugin/plugin.rb +63 -0
- data/examples/process_thin.rb +29 -0
- data/examples/processes/em.rb +57 -0
- data/examples/processes/forking.rb +20 -0
- data/examples/processes/sample.rb +144 -0
- data/examples/processes/thin.ru +12 -0
- data/examples/puma.eye +29 -0
- data/examples/rbenv.eye +11 -0
- data/examples/sidekiq.eye +23 -0
- data/examples/test.eye +87 -0
- data/examples/thin-farm.eye +30 -0
- data/examples/unicorn.eye +39 -0
- data/eye.gemspec +40 -0
- data/lib/eye.rb +28 -0
- data/lib/eye/application.rb +73 -0
- data/lib/eye/checker.rb +258 -0
- data/lib/eye/checker/children_count.rb +44 -0
- data/lib/eye/checker/children_memory.rb +12 -0
- data/lib/eye/checker/cpu.rb +17 -0
- data/lib/eye/checker/cputime.rb +13 -0
- data/lib/eye/checker/file_ctime.rb +24 -0
- data/lib/eye/checker/file_size.rb +34 -0
- data/lib/eye/checker/file_touched.rb +15 -0
- data/lib/eye/checker/http.rb +96 -0
- data/lib/eye/checker/memory.rb +17 -0
- data/lib/eye/checker/nop.rb +6 -0
- data/lib/eye/checker/runtime.rb +18 -0
- data/lib/eye/checker/socket.rb +159 -0
- data/lib/eye/child_process.rb +101 -0
- data/lib/eye/cli.rb +185 -0
- data/lib/eye/cli/commands.rb +78 -0
- data/lib/eye/cli/render.rb +130 -0
- data/lib/eye/cli/server.rb +93 -0
- data/lib/eye/client.rb +32 -0
- data/lib/eye/config.rb +91 -0
- data/lib/eye/control.rb +2 -0
- data/lib/eye/controller.rb +54 -0
- data/lib/eye/controller/commands.rb +88 -0
- data/lib/eye/controller/helpers.rb +101 -0
- data/lib/eye/controller/load.rb +224 -0
- data/lib/eye/controller/options.rb +18 -0
- data/lib/eye/controller/send_command.rb +177 -0
- data/lib/eye/controller/status.rb +72 -0
- data/lib/eye/dsl.rb +53 -0
- data/lib/eye/dsl/application_opts.rb +39 -0
- data/lib/eye/dsl/chain.rb +12 -0
- data/lib/eye/dsl/child_process_opts.rb +13 -0
- data/lib/eye/dsl/config_opts.rb +55 -0
- data/lib/eye/dsl/group_opts.rb +32 -0
- data/lib/eye/dsl/helpers.rb +20 -0
- data/lib/eye/dsl/main.rb +51 -0
- data/lib/eye/dsl/opts.rb +151 -0
- data/lib/eye/dsl/process_opts.rb +36 -0
- data/lib/eye/dsl/pure_opts.rb +121 -0
- data/lib/eye/dsl/validation.rb +88 -0
- data/lib/eye/group.rb +140 -0
- data/lib/eye/group/chain.rb +81 -0
- data/lib/eye/loader.rb +10 -0
- data/lib/eye/local.rb +100 -0
- data/lib/eye/logger.rb +104 -0
- data/lib/eye/notify.rb +118 -0
- data/lib/eye/notify/jabber.rb +30 -0
- data/lib/eye/notify/mail.rb +48 -0
- data/lib/eye/process.rb +85 -0
- data/lib/eye/process/children.rb +60 -0
- data/lib/eye/process/commands.rb +280 -0
- data/lib/eye/process/config.rb +81 -0
- data/lib/eye/process/controller.rb +73 -0
- data/lib/eye/process/data.rb +78 -0
- data/lib/eye/process/monitor.rb +108 -0
- data/lib/eye/process/notify.rb +32 -0
- data/lib/eye/process/scheduler.rb +82 -0
- data/lib/eye/process/states.rb +86 -0
- data/lib/eye/process/states_history.rb +66 -0
- data/lib/eye/process/system.rb +97 -0
- data/lib/eye/process/trigger.rb +34 -0
- data/lib/eye/process/validate.rb +33 -0
- data/lib/eye/process/watchers.rb +66 -0
- data/lib/eye/reason.rb +20 -0
- data/lib/eye/server.rb +60 -0
- data/lib/eye/sigar.rb +5 -0
- data/lib/eye/system.rb +139 -0
- data/lib/eye/system_resources.rb +99 -0
- data/lib/eye/trigger.rb +136 -0
- data/lib/eye/trigger/check_dependency.rb +30 -0
- data/lib/eye/trigger/flapping.rb +41 -0
- data/lib/eye/trigger/stop_children.rb +17 -0
- data/lib/eye/trigger/transition.rb +15 -0
- data/lib/eye/trigger/wait_dependency.rb +49 -0
- data/lib/eye/utils.rb +45 -0
- data/lib/eye/utils/alive_array.rb +57 -0
- data/lib/eye/utils/celluloid_chain.rb +71 -0
- data/lib/eye/utils/celluloid_klass.rb +5 -0
- data/lib/eye/utils/leak_19.rb +10 -0
- data/lib/eye/utils/mini_active_support.rb +111 -0
- data/lib/eye/utils/pmap.rb +7 -0
- data/lib/eye/utils/tail.rb +20 -0
- metadata +398 -0
data/lib/eye/logger.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
class Eye::Logger
|
4
|
+
attr_accessor :prefix, :subprefix
|
5
|
+
|
6
|
+
class InnerLogger < Logger
|
7
|
+
FORMAT = '%d.%m.%Y %H:%M:%S'
|
8
|
+
|
9
|
+
def initialize(*args)
|
10
|
+
super
|
11
|
+
|
12
|
+
self.formatter = Proc.new do |s, d, p, m|
|
13
|
+
"#{d.strftime(FORMAT)} #{s.ljust(5)} -- #{m}\n"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
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
|
29
|
+
|
30
|
+
Logger::Severity.constants.each do |level|
|
31
|
+
method_name = level.to_s.downcase
|
32
|
+
define_method method_name do |msg|
|
33
|
+
logger.send(method_name, msg)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def log_ex(ex)
|
38
|
+
error "#{ex.message} #{ex.backtrace}"
|
39
|
+
# notify here?
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
Logger::Severity.constants.each do |level|
|
44
|
+
method_name = level.to_s.downcase
|
45
|
+
define_method method_name do |msg|
|
46
|
+
self.class.inner_logger.send(method_name, "#{prefix_str}#{msg}")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def initialize(prefix = nil, subprefix = nil)
|
51
|
+
@prefix = prefix
|
52
|
+
@subprefix = subprefix
|
53
|
+
end
|
54
|
+
|
55
|
+
class << self
|
56
|
+
attr_reader :dev, :log_level, :args
|
57
|
+
|
58
|
+
def link_logger(dev, *args)
|
59
|
+
old_dev = @dev
|
60
|
+
@dev = dev ? dev.to_s : nil
|
61
|
+
@dev_fd = @dev
|
62
|
+
@args = args
|
63
|
+
|
64
|
+
@dev_fd = STDOUT if @dev.to_s.downcase == 'stdout'
|
65
|
+
@dev_fd = STDERR if @dev.to_s.downcase == 'stderr'
|
66
|
+
|
67
|
+
@inner_logger = InnerLogger.new(@dev_fd, *args)
|
68
|
+
@inner_logger.level = self.log_level || Logger::INFO
|
69
|
+
|
70
|
+
rescue Errno::ENOENT, Errno::EACCES
|
71
|
+
@dev = old_dev
|
72
|
+
raise
|
73
|
+
end
|
74
|
+
|
75
|
+
def reopen
|
76
|
+
link_logger(dev, *args)
|
77
|
+
end
|
78
|
+
|
79
|
+
def log_level=(level)
|
80
|
+
@log_level = level
|
81
|
+
@inner_logger.level = self.log_level if @inner_logger
|
82
|
+
end
|
83
|
+
|
84
|
+
def inner_logger
|
85
|
+
@inner_logger ||= InnerLogger.new(nil)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def prefix_str
|
92
|
+
@pref_string ||= begin
|
93
|
+
pref_string = ''
|
94
|
+
|
95
|
+
if @prefix
|
96
|
+
pref_string = "[#{@prefix}] "
|
97
|
+
pref_string += "#{@subprefix} " if @subprefix
|
98
|
+
end
|
99
|
+
|
100
|
+
pref_string
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
data/lib/eye/notify.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'celluloid'
|
2
|
+
|
3
|
+
class Eye::Notify
|
4
|
+
include Celluloid
|
5
|
+
include Eye::Dsl::Validation
|
6
|
+
|
7
|
+
autoload :Mail, 'eye/notify/mail'
|
8
|
+
autoload :Jabber, 'eye/notify/jabber'
|
9
|
+
|
10
|
+
TYPES = {:mail => 'Mail', :jabber => 'Jabber'}
|
11
|
+
|
12
|
+
def self.get_class(type)
|
13
|
+
klass = eval("Eye::Notify::#{TYPES[type]}") rescue nil
|
14
|
+
raise "unknown notifier :#{type}" unless klass
|
15
|
+
if deps = klass.requires
|
16
|
+
Array(deps).each { |d| require d }
|
17
|
+
end
|
18
|
+
klass
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.validate!(options)
|
22
|
+
get_class(options[:type]).validate(options)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.notify(contact, message_h)
|
26
|
+
contact = contact.to_s
|
27
|
+
settings = Eye::Control.settings
|
28
|
+
needed_hash = (settings[:contacts] || {})[contact]
|
29
|
+
|
30
|
+
if needed_hash.blank?
|
31
|
+
error "contact #{contact} not found; check your configuration"
|
32
|
+
return
|
33
|
+
end
|
34
|
+
|
35
|
+
create_proc = lambda do |nh|
|
36
|
+
type = nh[:type]
|
37
|
+
config = (settings[type] || {}).merge(nh[:opts] || {}).merge(:contact => nh[:contact])
|
38
|
+
klass = get_class(type)
|
39
|
+
notify = klass.new(config, message_h)
|
40
|
+
notify.async_notify if notify
|
41
|
+
end
|
42
|
+
|
43
|
+
if needed_hash.is_a?(Array)
|
44
|
+
needed_hash.each{|nh| create_proc[nh] }
|
45
|
+
else
|
46
|
+
create_proc[needed_hash]
|
47
|
+
end
|
48
|
+
|
49
|
+
rescue Exception, Timeout::Error => ex
|
50
|
+
log_ex(ex)
|
51
|
+
end
|
52
|
+
|
53
|
+
TIMEOUT = 1 * 60
|
54
|
+
|
55
|
+
def initialize(options = {}, message_h = {})
|
56
|
+
@message_h = message_h
|
57
|
+
@options = options
|
58
|
+
|
59
|
+
debug "created notifier #{options}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def logger_sub_tag
|
63
|
+
@options[:contact]
|
64
|
+
end
|
65
|
+
|
66
|
+
def async_notify
|
67
|
+
async.notify
|
68
|
+
after(TIMEOUT){ terminate }
|
69
|
+
end
|
70
|
+
|
71
|
+
def notify
|
72
|
+
debug "start notify #{@message_h}"
|
73
|
+
execute
|
74
|
+
debug "end notify #{@message_h}"
|
75
|
+
terminate
|
76
|
+
end
|
77
|
+
|
78
|
+
def execute
|
79
|
+
raise NotImplementedError
|
80
|
+
end
|
81
|
+
|
82
|
+
param :contact, [String]
|
83
|
+
|
84
|
+
def message_subject
|
85
|
+
"[#{msg_host}] [#{msg_full_name}] #{msg_message}"
|
86
|
+
end
|
87
|
+
|
88
|
+
def message_body
|
89
|
+
"#{message_subject} at #{Eye::Utils.human_time2(msg_at)}"
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.register(base)
|
93
|
+
name = base.to_s.gsub('Eye::Notify::', '')
|
94
|
+
type = name.underscore.to_sym
|
95
|
+
Eye::Notify::TYPES[type] = name
|
96
|
+
Eye::Notify.const_set(name, base)
|
97
|
+
Eye::Dsl::ConfigOpts.add_notify(type)
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.requires
|
101
|
+
end
|
102
|
+
|
103
|
+
class Custom < Eye::Notify
|
104
|
+
def self.inherited(base)
|
105
|
+
super
|
106
|
+
register(base)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
%w{at host message name full_name pid level}.each do |name|
|
113
|
+
define_method("msg_#{name}") do
|
114
|
+
@message_h[name.to_sym]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'xmpp4r'
|
2
|
+
|
3
|
+
class Eye::Notify::Jabber < Eye::Notify
|
4
|
+
|
5
|
+
# Eye.config do
|
6
|
+
# jabber :host => "some.host", :port => 12345, :user => "eye@some.host", :password => "123456"
|
7
|
+
# contact :vasya, :jabber, "vasya@some.host"
|
8
|
+
# end
|
9
|
+
|
10
|
+
param :host, String, true
|
11
|
+
param :port, [String, Fixnum], true
|
12
|
+
param :user, String, true
|
13
|
+
param :password, String
|
14
|
+
|
15
|
+
def execute
|
16
|
+
debug "send jabber #{[host, port, user, password]} - #{[contact, message_body]}"
|
17
|
+
|
18
|
+
mes = ::Jabber::Message.new(contact, message_body)
|
19
|
+
mes.set_type(:normal)
|
20
|
+
mes.set_id('1')
|
21
|
+
mes.set_subject(message_subject)
|
22
|
+
|
23
|
+
client = ::Jabber::Client.new(::Jabber::JID.new("#{user}/Eye"))
|
24
|
+
client.connect(host, port)
|
25
|
+
client.auth(password)
|
26
|
+
client.send(mes)
|
27
|
+
client.close
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'net/smtp'
|
2
|
+
|
3
|
+
class Eye::Notify::Mail < Eye::Notify
|
4
|
+
|
5
|
+
# Eye.config do
|
6
|
+
# mail :host => "some.host", :port => 12345, :user => "eye@some.host", :password => "123456", :domain => "some.host"
|
7
|
+
# contact :vasya, :mail, "vasya@some.host"
|
8
|
+
# end
|
9
|
+
|
10
|
+
param :host, String, true
|
11
|
+
param :port, [String, Fixnum], true
|
12
|
+
|
13
|
+
param :domain, String
|
14
|
+
param :user, String
|
15
|
+
param :password, String
|
16
|
+
param :auth, Symbol, nil, nil, [:plain, :login, :cram_md5]
|
17
|
+
|
18
|
+
param :starttls, [TrueClass, FalseClass]
|
19
|
+
|
20
|
+
param :from_mail, String
|
21
|
+
param :from_name, String, nil, 'eye'
|
22
|
+
|
23
|
+
def execute
|
24
|
+
smtp
|
25
|
+
end
|
26
|
+
|
27
|
+
def smtp
|
28
|
+
args = [host, port, domain, user, password, auth]
|
29
|
+
debug "called smtp with #{args}"
|
30
|
+
smtp = Net::SMTP.new host, port
|
31
|
+
smtp.enable_starttls if starttls
|
32
|
+
|
33
|
+
smtp.start(domain, user, password, auth) do |s|
|
34
|
+
s.send_message(message, from_mail || user, contact)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def message
|
39
|
+
h = []
|
40
|
+
h << "From: #{from_name} <#{from_mail || user}>" if from_mail || user
|
41
|
+
h << "To: <#{contact}>"
|
42
|
+
h << "Subject: #{message_subject}"
|
43
|
+
h << "Date: #{msg_at.httpdate}"
|
44
|
+
h << "Message-Id: <#{rand(1000000000).to_s(36)}.#{$$}.#{contact}>"
|
45
|
+
"#{h * "\n"}\n#{message_body}"
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
data/lib/eye/process.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'celluloid'
|
2
|
+
|
3
|
+
class Eye::Process
|
4
|
+
include Celluloid
|
5
|
+
|
6
|
+
autoload :Config, 'eye/process/config'
|
7
|
+
autoload :Commands, 'eye/process/commands'
|
8
|
+
autoload :Data, 'eye/process/data'
|
9
|
+
autoload :Watchers, 'eye/process/watchers'
|
10
|
+
autoload :Monitor, 'eye/process/monitor'
|
11
|
+
autoload :System, 'eye/process/system'
|
12
|
+
autoload :Controller, 'eye/process/controller'
|
13
|
+
autoload :StatesHistory, 'eye/process/states_history'
|
14
|
+
autoload :Children, 'eye/process/children'
|
15
|
+
autoload :Trigger, 'eye/process/trigger'
|
16
|
+
autoload :Notify, 'eye/process/notify'
|
17
|
+
autoload :Scheduler, 'eye/process/scheduler'
|
18
|
+
autoload :Validate, 'eye/process/validate'
|
19
|
+
|
20
|
+
attr_accessor :pid, :watchers, :config, :states_history,
|
21
|
+
:children, :triggers, :name, :state_reason, :flapping_times,
|
22
|
+
:parent_pid
|
23
|
+
|
24
|
+
def initialize(config)
|
25
|
+
raise 'you must supply a pid_file location' unless config[:pid_file]
|
26
|
+
|
27
|
+
@config = prepare_config(config)
|
28
|
+
|
29
|
+
@watchers = {}
|
30
|
+
@children = {}
|
31
|
+
@triggers = []
|
32
|
+
@name = @config[:name]
|
33
|
+
|
34
|
+
@flapping_times = 0
|
35
|
+
|
36
|
+
@states_history = Eye::Process::StatesHistory.new(100)
|
37
|
+
@states_history << :unmonitored
|
38
|
+
|
39
|
+
debug "creating with config: #{@config.inspect}"
|
40
|
+
|
41
|
+
add_triggers
|
42
|
+
|
43
|
+
super() # for statemachine
|
44
|
+
end
|
45
|
+
|
46
|
+
# c(), self[]
|
47
|
+
include Eye::Process::Config
|
48
|
+
|
49
|
+
# full_name, status_data
|
50
|
+
include Eye::Process::Data
|
51
|
+
|
52
|
+
# commands:
|
53
|
+
# start_process, stop_process, restart_process
|
54
|
+
include Eye::Process::Commands
|
55
|
+
|
56
|
+
# start, stop, restart, monitor, unmonit, delete
|
57
|
+
include Eye::Process::Controller
|
58
|
+
|
59
|
+
# add_watchers, remove_watchers:
|
60
|
+
include Eye::Process::Watchers
|
61
|
+
|
62
|
+
# check alive, crash methods:
|
63
|
+
include Eye::Process::Monitor
|
64
|
+
|
65
|
+
# system methods:
|
66
|
+
include Eye::Process::System
|
67
|
+
|
68
|
+
# manage child methods
|
69
|
+
include Eye::Process::Children
|
70
|
+
|
71
|
+
# manage triggers methods
|
72
|
+
include Eye::Process::Trigger
|
73
|
+
|
74
|
+
# manage notify methods
|
75
|
+
include Eye::Process::Notify
|
76
|
+
|
77
|
+
# scheduler
|
78
|
+
include Eye::Process::Scheduler
|
79
|
+
|
80
|
+
# validate
|
81
|
+
extend Eye::Process::Validate
|
82
|
+
end
|
83
|
+
|
84
|
+
# include state_machine states
|
85
|
+
require_relative 'process/states'
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Eye::Process::Children
|
2
|
+
|
3
|
+
def add_children
|
4
|
+
add_or_update_children
|
5
|
+
end
|
6
|
+
|
7
|
+
def add_or_update_children
|
8
|
+
return unless self[:monitor_children]
|
9
|
+
return unless self.up?
|
10
|
+
return if @updating_children
|
11
|
+
@updating_children = true
|
12
|
+
|
13
|
+
unless self.pid
|
14
|
+
warn "can't add children; pid not set"
|
15
|
+
return
|
16
|
+
end
|
17
|
+
|
18
|
+
now_children = Eye::SystemResources.children(self.pid)
|
19
|
+
new_children = []
|
20
|
+
exist_children = []
|
21
|
+
|
22
|
+
now_children.each do |child_pid|
|
23
|
+
if self.children[child_pid]
|
24
|
+
exist_children << child_pid
|
25
|
+
else
|
26
|
+
new_children << child_pid
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
removed_children = self.children.keys - now_children
|
31
|
+
|
32
|
+
if new_children.present?
|
33
|
+
new_children.each do |child_pid|
|
34
|
+
self.children[child_pid] = Eye::ChildProcess.new(child_pid, self[:monitor_children], logger.prefix, self.pid)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
if removed_children.present?
|
39
|
+
removed_children.each{|child_pid| remove_child(child_pid) }
|
40
|
+
end
|
41
|
+
|
42
|
+
h = {:new => new_children.size, :removed => removed_children.size, :exists => exist_children.size }
|
43
|
+
debug "children info: #{ h.inspect }"
|
44
|
+
|
45
|
+
@updating_children = false
|
46
|
+
h
|
47
|
+
end
|
48
|
+
|
49
|
+
def remove_children
|
50
|
+
if children.present?
|
51
|
+
children.keys.each{|child_pid| remove_child(child_pid) }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def remove_child(child_pid)
|
56
|
+
child = self.children.delete(child_pid)
|
57
|
+
child.destroy if child && child.alive?
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|