ace-eye 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|