cognizant 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +160 -0
- data/Rakefile +2 -0
- data/bin/cognizant +58 -0
- data/bin/cognizantd +124 -0
- data/cognizant.gemspec +24 -0
- data/examples/cognizantd.yml +23 -0
- data/examples/redis-server.rb +17 -0
- data/examples/resque.rb +10 -0
- data/images/logo-small.png +0 -0
- data/images/logo.png +0 -0
- data/images/logo.pxm +0 -0
- data/lib/cognizant/client/cli.rb +9 -0
- data/lib/cognizant/client/interface.rb +33 -0
- data/lib/cognizant/logging.rb +33 -0
- data/lib/cognizant/process/actions/restart.rb +60 -0
- data/lib/cognizant/process/actions/start.rb +70 -0
- data/lib/cognizant/process/actions/stop.rb +59 -0
- data/lib/cognizant/process/actions.rb +96 -0
- data/lib/cognizant/process/attributes.rb +81 -0
- data/lib/cognizant/process/execution.rb +176 -0
- data/lib/cognizant/process/pid.rb +28 -0
- data/lib/cognizant/process/status.rb +27 -0
- data/lib/cognizant/process.rb +149 -0
- data/lib/cognizant/server/commands.rb +53 -0
- data/lib/cognizant/server/daemon.rb +239 -0
- data/lib/cognizant/server/interface.rb +60 -0
- data/lib/cognizant/server.rb +14 -0
- data/lib/cognizant/validations.rb +142 -0
- data/lib/cognizant/version.rb +3 -0
- data/lib/cognizant.rb +7 -0
- metadata +169 -0
data/.gitignore
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--asset images:images
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Gurpartap Singh
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
# Cognizant
|
2
|
+
|
3
|
+
Cognizant is a system utility that supervises your processes, ensuring their
|
4
|
+
state based on a flexible criteria.
|
5
|
+
|
6
|
+
In simpler terms, cognizant keeps your processes up and running. It ensures
|
7
|
+
that something productive (like restart) is done when the process being
|
8
|
+
monitored matches a certain condition (like RAM, CPU usage or a custom
|
9
|
+
condition).
|
10
|
+
|
11
|
+
PS: Although the core works efficiently, yet the command interface to the
|
12
|
+
utility, documentation and some other features need a lot of work.
|
13
|
+
Contributions will be overwhelmingly welcomed!
|
14
|
+
|
15
|
+
PS2: This README is written as a roadmap for the features cognizant would
|
16
|
+
ideally provide. Some of them might not yet be implemented (e.g. conditions).
|
17
|
+
|
18
|
+
Cognizant can be used to monitor any long running process, including the
|
19
|
+
following examples:
|
20
|
+
|
21
|
+
- Web servers (Nginx, Apache httpd, WebSocket, etc.)
|
22
|
+
- Databases (Redis, MongoDB, MySQL, PostgreSQL, etc.)
|
23
|
+
- Job workers (Resque, Sidekiq, etc.)
|
24
|
+
- Message queue applications (RabbitMQ, Beanstalkd, etc.)
|
25
|
+
- Logs collection daemon
|
26
|
+
- Or any other program that needs to keep running
|
27
|
+
|
28
|
+
## Monitoring
|
29
|
+
|
30
|
+
Cognizant can be used to monitor an application process' state so that it
|
31
|
+
is running at all times. When cognizant is instructed to monitor a process,
|
32
|
+
by default, the process will automatically be started. These processes are
|
33
|
+
automatically monitored for their state. i.e. a process is automatically
|
34
|
+
started again if it stops unexpectedly.
|
35
|
+
|
36
|
+
## Conditions
|
37
|
+
|
38
|
+
Conditions provide a way to monitor and act on more than just the state of a
|
39
|
+
process. For example, conditions can monitor the resource utilization (RAM,
|
40
|
+
CPU, etc.) of the application process and restart it if it matches a
|
41
|
+
condition.
|
42
|
+
|
43
|
+
## Getting started
|
44
|
+
|
45
|
+
Cognizant is written in the Ruby programming language, and hence depends on
|
46
|
+
it. Ensure that you have Ruby 1.9+ installed and run:
|
47
|
+
|
48
|
+
$ gem install cognizant
|
49
|
+
|
50
|
+
## Architecture overview
|
51
|
+
|
52
|
+
_____
|
53
|
+
___________ |
|
54
|
+
____________ ____________ | | |
|
55
|
+
| | | | -----> | Process A | |
|
56
|
+
| Admin | | Monitoring | |___________| |
|
57
|
+
| Utility | -----> | Daemon | ___________ | -- Managed Processes
|
58
|
+
| >_ | | | | | |
|
59
|
+
|____________| |____________| -----> | Process B | |
|
60
|
+
|___________| |
|
61
|
+
_____|
|
62
|
+
|
63
|
+
Since cognizant administration and process monitoring are two separate concerns, they are serviced by separate applications, `cognizant` and `cognizantd`, respectively.
|
64
|
+
|
65
|
+
## Starting the monitoring daemon
|
66
|
+
|
67
|
+
Cognizant runs the monitoring essentials through the `cognizantd` daemon application, which also maintains a server for accepting commands from the `cognizant` administration utility.
|
68
|
+
|
69
|
+
The daemon, with it's default options, requires superuser access to certain system directories for storing logs and pid files. It can be started as follows:
|
70
|
+
|
71
|
+
$ sudo cognizantd # ubuntu, debian, os x, etc.
|
72
|
+
$ su -c 'cognizantd' # amazon linux, centos, rhel, etc.
|
73
|
+
|
74
|
+
To start without superuser access, specify these file and directory config variables to where the user starting it has write access:
|
75
|
+
|
76
|
+
$ cognizantd ~/.cognizant/cognizantd.yml
|
77
|
+
|
78
|
+
# assuming that:
|
79
|
+
|
80
|
+
$ cat ~/.cognizant/cognizantd.yml
|
81
|
+
---
|
82
|
+
socket: ~/.cognizant/cognizantd.sock
|
83
|
+
pidfile: ~/.cognizant/cognizantd.pid
|
84
|
+
logfile: ~/.cognizant/cognizantd.log
|
85
|
+
pids_dir: ~/.cognizant/pids/
|
86
|
+
logs_dir: ~/.cognizant/logs/
|
87
|
+
|
88
|
+
or
|
89
|
+
|
90
|
+
# pass config directly into the daemon's STDIN
|
91
|
+
$ echo <<EOF | cognizantd -
|
92
|
+
---
|
93
|
+
socket: ~/.cognizant/cognizantd.sock
|
94
|
+
pidfile: ~/.cognizant/cognizantd.pid
|
95
|
+
logfile: ~/.cognizant/cognizantd.log
|
96
|
+
pids_dir: ~/.cognizant/pids/
|
97
|
+
logs_dir: ~/.cognizant/logs/
|
98
|
+
EOF
|
99
|
+
|
100
|
+
## Using the administration utility
|
101
|
+
|
102
|
+
Cognizant can be administered using the `cognizant` command line utility. This is an application for performing administration tasks like monitoring, starting, stopping processes or loading configuration and processes' information.
|
103
|
+
|
104
|
+
Here's how you tell cognizant to start monitoring a new process:
|
105
|
+
|
106
|
+
$ cognizant monitor --name resque-worker-1 \
|
107
|
+
--group resque \
|
108
|
+
--chdir /apps/example/current/ \
|
109
|
+
--start_command "bundle exec rake resque:work"
|
110
|
+
|
111
|
+
Now check it's status:
|
112
|
+
|
113
|
+
$ cognizant status resque-worker-1
|
114
|
+
---
|
115
|
+
resque-worker-1: {
|
116
|
+
state: running,
|
117
|
+
uptime: 3600 # 1 hour
|
118
|
+
}
|
119
|
+
|
120
|
+
Or check status of all processes:
|
121
|
+
|
122
|
+
$ cognizant status resque-worker-1
|
123
|
+
---
|
124
|
+
redis-server: {
|
125
|
+
state: running,
|
126
|
+
uptime: 5400 # 1 hour 30 minutes
|
127
|
+
},
|
128
|
+
resque-worker-1: {
|
129
|
+
group: resque,
|
130
|
+
state: running,
|
131
|
+
uptime: 3600 # 1 hour
|
132
|
+
},
|
133
|
+
resque-worker-2: {
|
134
|
+
group: resque,
|
135
|
+
state: stoppped,
|
136
|
+
uptime: 0
|
137
|
+
}
|
138
|
+
|
139
|
+
### Works anywhere
|
140
|
+
|
141
|
+
Cognizant can be used on any operating system where Ruby 1.9+ works.
|
142
|
+
|
143
|
+
### What are the other programs similar to cognizant?
|
144
|
+
|
145
|
+
- Monit
|
146
|
+
- God (Ruby)
|
147
|
+
- Bluepill (Ruby)
|
148
|
+
- Supervisord (Python)
|
149
|
+
- Upstart
|
150
|
+
- SysV Init
|
151
|
+
- Systemd
|
152
|
+
- Launchd
|
153
|
+
|
154
|
+
### Which one of these should I be using?
|
155
|
+
|
156
|
+
The one that gets your job done efficiently.
|
157
|
+
|
158
|
+
### What does the term "cognizant" mean?
|
159
|
+
|
160
|
+
If it matters, cognizant means "having knowledge or being aware of", according to Apple's Dictionary.
|
data/Rakefile
ADDED
data/bin/cognizant
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Set the process name.
|
4
|
+
$0 = File.basename(__FILE__)
|
5
|
+
|
6
|
+
# Flush standard output/error immediately.
|
7
|
+
$stdout.sync = true
|
8
|
+
$stderr.sync = true
|
9
|
+
|
10
|
+
begin
|
11
|
+
require 'optparse'
|
12
|
+
|
13
|
+
options = {
|
14
|
+
socket: "/var/run/cognizant/cognizantd.sock"
|
15
|
+
}
|
16
|
+
|
17
|
+
OptionParser.new do |opts|
|
18
|
+
opts.banner = <<-EOF
|
19
|
+
Usage:
|
20
|
+
cognizant [OPTIONS] command
|
21
|
+
|
22
|
+
Options:
|
23
|
+
EOF
|
24
|
+
|
25
|
+
opts.on("-s FILE", "--socket FILE", String, "The socket lock file for the server") do |value|
|
26
|
+
options[:socket] = value
|
27
|
+
end
|
28
|
+
|
29
|
+
opts.on("-b ADDRESS", "--bind-address ADDRESS", String, "The interface to bind the TCP server to.") do |value|
|
30
|
+
options[:bind_address] = value
|
31
|
+
end
|
32
|
+
|
33
|
+
opts.on("-p PORT", "--port PORT", Integer, "The TCP port to start the server with.") do |value|
|
34
|
+
options[:port] = value
|
35
|
+
end
|
36
|
+
|
37
|
+
opts.on("--username USERNAME", String, "Username for securing server access.") do |value|
|
38
|
+
options[:username] = value
|
39
|
+
end
|
40
|
+
|
41
|
+
opts.on("--password PASSWORD", String, "Password to accompany the username.") do |value|
|
42
|
+
options[:password] = value
|
43
|
+
end
|
44
|
+
|
45
|
+
opts.on("-t", "--trace", "Turn on tracing, enable full backtrace.") do
|
46
|
+
options[:trace] = true
|
47
|
+
end
|
48
|
+
|
49
|
+
opts.on("-v", "--version", "Print the version number and exit.") do
|
50
|
+
require 'cognizant/version'
|
51
|
+
$stdout.puts Cognizant::VERSION
|
52
|
+
exit(0)
|
53
|
+
end
|
54
|
+
end.parse!
|
55
|
+
|
56
|
+
require 'cognizant'
|
57
|
+
Cognizant.add_process(options)
|
58
|
+
end
|
data/bin/cognizantd
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Set the process name.
|
4
|
+
$0 = File.basename(__FILE__)
|
5
|
+
|
6
|
+
# Flush standard output/error immediately.
|
7
|
+
$stdout.sync = true
|
8
|
+
$stderr.sync = true
|
9
|
+
|
10
|
+
begin
|
11
|
+
require 'optparse'
|
12
|
+
|
13
|
+
options = {}
|
14
|
+
|
15
|
+
OptionParser.new do |opts|
|
16
|
+
opts.banner = <<-EOF
|
17
|
+
Usage:
|
18
|
+
cognizantd [OPTIONS] [CONFIG | -]
|
19
|
+
|
20
|
+
Options:
|
21
|
+
EOF
|
22
|
+
|
23
|
+
opts.on("--[no-]daemonize", "Whether or not to daemonize cognizant into background.") do |value|
|
24
|
+
options[:daemonize] = value
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on("--pidfile FILE", String, "The pid lock file for the daemon.") do |value|
|
28
|
+
options[:pidfile] = value
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on("--logfile FILE", String, "The file to log the daemon's operations information into.") do |value|
|
32
|
+
options[:logfile] = value
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on("--loglevel LEVEL", String, "The level of information to log.") do |value|
|
36
|
+
options[:loglevel] = value
|
37
|
+
end
|
38
|
+
|
39
|
+
opts.on("--env ENV", String, "Environment variables for managed processes to inherit.") do |value|
|
40
|
+
options[:env] = value
|
41
|
+
end
|
42
|
+
|
43
|
+
opts.on("--chdir DIRECTORY", String, "The current working directory for the managed processes to start with.") do |value|
|
44
|
+
options[:chdir] = value
|
45
|
+
end
|
46
|
+
|
47
|
+
opts.on("--umask UMASK", String, "Permission mode limitations for file and directory creation.") do |value|
|
48
|
+
options[:umask] = value
|
49
|
+
end
|
50
|
+
|
51
|
+
opts.on("--user USER", String, "Run the daemon and managed processes as the given user.") do |value|
|
52
|
+
options[:user] = value
|
53
|
+
end
|
54
|
+
|
55
|
+
opts.on("--group GROUP", String, "Run the daemon and managed processes as the given user group.") do |value|
|
56
|
+
options[:group] = value
|
57
|
+
end
|
58
|
+
|
59
|
+
opts.on("--pids-dir DIRECTORY", String, "Directory to store the pid files of managed processes, when required.") do |value|
|
60
|
+
options[:pids_dir] = value
|
61
|
+
end
|
62
|
+
|
63
|
+
opts.on("--logs-dir DIRECTORY", String, "Directory to store the log files of managed processes, when required.") do |value|
|
64
|
+
options[:logs_dir] = value
|
65
|
+
end
|
66
|
+
|
67
|
+
opts.on("-s FILE", "--socket FILE", String, "The socket lock file for the server") do |value|
|
68
|
+
options[:socket] = value
|
69
|
+
end
|
70
|
+
|
71
|
+
opts.on("-b ADDRESS", "--bind-address ADDRESS", String, "The interface to bind the TCP server to.") do |value|
|
72
|
+
options[:bind_address] = value
|
73
|
+
end
|
74
|
+
|
75
|
+
opts.on("-p PORT", "--port PORT", Integer, "The TCP port to start the server with.") do |value|
|
76
|
+
options[:port] = value
|
77
|
+
end
|
78
|
+
|
79
|
+
opts.on("--username USERNAME", String, "Username for securing server access.") do |value|
|
80
|
+
options[:username] = value
|
81
|
+
end
|
82
|
+
|
83
|
+
opts.on("--password PASSWORD", String, "Password to accompany the username.") do |value|
|
84
|
+
options[:password] = value
|
85
|
+
end
|
86
|
+
|
87
|
+
opts.on("-t", "--trace", "Turn on tracing, enable full backtrace.") do
|
88
|
+
options[:trace] = true
|
89
|
+
end
|
90
|
+
|
91
|
+
opts.on("-v", "--version", "Print the version number and exit.") do
|
92
|
+
require 'cognizant/version'
|
93
|
+
$stdout.puts Cognizant::VERSION
|
94
|
+
exit(0)
|
95
|
+
end
|
96
|
+
end.parse!
|
97
|
+
|
98
|
+
if config_file = ARGV.shift
|
99
|
+
if config_file.eql?("-")
|
100
|
+
config = YAML.load(ARGF.read)
|
101
|
+
else
|
102
|
+
config = YAML.load_file(config_file)
|
103
|
+
end
|
104
|
+
config = config.inject({}) { |c,(k,v)| c[k.gsub("-", "_").to_sym] = v; c }
|
105
|
+
options = config.merge(options)
|
106
|
+
end
|
107
|
+
|
108
|
+
require 'cognizant/server'
|
109
|
+
Cognizant::Server.start(options)
|
110
|
+
rescue => exception
|
111
|
+
if exception.instance_of?(SystemExit)
|
112
|
+
raise
|
113
|
+
else
|
114
|
+
$stderr.puts "ERROR: While executing #{$0} ... (#{exception.class})"
|
115
|
+
$stderr.puts " #{exception.message}\n\n"
|
116
|
+
if options[:trace]
|
117
|
+
$stderr.puts exception.backtrace.join("\n")
|
118
|
+
$stderr.puts "\n(See usage by running #{$0} with --help)"
|
119
|
+
else
|
120
|
+
$stderr.puts "(See full trace by running #{$0} with --trace)"
|
121
|
+
end
|
122
|
+
exit(1)
|
123
|
+
end
|
124
|
+
end
|
data/cognizant.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/cognizant/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Gurpartap Singh"]
|
6
|
+
gem.email = ["contact@gurpartap.com"]
|
7
|
+
gem.description = "Process monitoring and management framework"
|
8
|
+
gem.summary = "Cognizant is an advanced and efficient process monitoring and management framework."
|
9
|
+
gem.homepage = "http://gurpartap.github.com/cognizant/"
|
10
|
+
|
11
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
12
|
+
gem.files = `git ls-files`.split("\n")
|
13
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
14
|
+
gem.name = "cognizant"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Cognizant::VERSION
|
17
|
+
|
18
|
+
gem.add_development_dependency "rake"
|
19
|
+
gem.add_development_dependency "redcarpet"
|
20
|
+
gem.add_development_dependency "yard"
|
21
|
+
|
22
|
+
gem.add_dependency "eventmachine"
|
23
|
+
gem.add_dependency "state_machine"
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
---
|
2
|
+
daemonize: false
|
3
|
+
pidfile: ~/.cognizant/cognizantd.pid
|
4
|
+
logfile: ~/.cognizant/cognizantd.log
|
5
|
+
socket: ~/.cognizant/cognizantd.sock
|
6
|
+
pids_dir: ~/.cognizant/pids/
|
7
|
+
logs_dir: ~/.cognizant/logs/
|
8
|
+
|
9
|
+
monitor: {
|
10
|
+
redis-server: {
|
11
|
+
start_command: /usr/local/bin/redis-server -,
|
12
|
+
start_with_input: daemonize no,
|
13
|
+
ping_command: redis-cli PING,
|
14
|
+
autostart: true,
|
15
|
+
stop_timeout: 5,
|
16
|
+
start_timeout: 2,
|
17
|
+
restart_timeout: 2
|
18
|
+
},
|
19
|
+
sleep-10: {
|
20
|
+
start_command: sleep 10,
|
21
|
+
autostart: true
|
22
|
+
}
|
23
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# 4 slave instances to master at port 6000.
|
2
|
+
5.times do |i|
|
3
|
+
Cognizant.monitor "redis-server-600#{i}" do |process|
|
4
|
+
process.group = "redis"
|
5
|
+
process.uid = "redis"
|
6
|
+
process.gid = "redis"
|
7
|
+
process.start_command = "redis-server -"
|
8
|
+
process.ping_command = "redis-cli -p 600#{i} PING"
|
9
|
+
|
10
|
+
slaveof = i == 0 ? "" : "slaveof 127.0.0.1 6000"
|
11
|
+
process.start_with_input = <<-heredoc
|
12
|
+
daemonize no
|
13
|
+
port 600#{i}
|
14
|
+
#{slaveof}
|
15
|
+
heredoc
|
16
|
+
end
|
17
|
+
end
|
data/examples/resque.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
5.times do |i|
|
2
|
+
Cognizant.monitor "resque-worker-#{i}" do |process|
|
3
|
+
process.group = "resque"
|
4
|
+
process.uid = "deploy"
|
5
|
+
process.gid = "deploy"
|
6
|
+
process.chdir = "/apps/example/current/"
|
7
|
+
process.env = { "QUEUE" => "*", "RACK_ENV" => "production" }
|
8
|
+
process.start_command = "bundle exec rake resque:work"
|
9
|
+
end
|
10
|
+
end
|
Binary file
|
data/images/logo.png
ADDED
Binary file
|
data/images/logo.pxm
ADDED
Binary file
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "eventmachine"
|
2
|
+
|
3
|
+
module Cognizant
|
4
|
+
module Client
|
5
|
+
class Interface
|
6
|
+
def initialize(server = nil)
|
7
|
+
@sock = EventMachine.connect(server, Client::Interface::Handler)
|
8
|
+
end
|
9
|
+
|
10
|
+
def method_missing(*meth, &blk)
|
11
|
+
@sock.queue << blk
|
12
|
+
@sock.send_object(meth)
|
13
|
+
end
|
14
|
+
|
15
|
+
class Handler < EventMachine::Connection
|
16
|
+
# include EventMachine::Protocols::SASLauthclient
|
17
|
+
include EventMachine::Protocols::ObjectProtocol
|
18
|
+
|
19
|
+
attr_reader :queue
|
20
|
+
|
21
|
+
def post_init
|
22
|
+
@queue = []
|
23
|
+
end
|
24
|
+
|
25
|
+
def receive_object(obj)
|
26
|
+
if callback = @queue.shift
|
27
|
+
callback.call(obj)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "logger"
|
2
|
+
|
3
|
+
module Cognizant
|
4
|
+
module Logging
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def add_log_adapter(file)
|
8
|
+
@files ||= Array.new
|
9
|
+
@files << file unless @files.include?(file)
|
10
|
+
@logger = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def log
|
14
|
+
@files ||= Array.new($stdout)
|
15
|
+
@logger ||= Logger.new(Files.new(*@files))
|
16
|
+
end
|
17
|
+
alias :logger :log
|
18
|
+
|
19
|
+
class Files
|
20
|
+
def initialize(*files)
|
21
|
+
@files = files
|
22
|
+
end
|
23
|
+
|
24
|
+
def write(*args)
|
25
|
+
@files.each { |t| t.write(*args) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def close
|
29
|
+
@files.each(&:close)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Cognizant
|
2
|
+
class Process
|
3
|
+
module Actions
|
4
|
+
module Restart
|
5
|
+
# Environment variables for process during restart.
|
6
|
+
# @return [Hash] Defaults to {}
|
7
|
+
attr_accessor :restart_env
|
8
|
+
|
9
|
+
# The command to run before the process is restarted. The exit status
|
10
|
+
# of this command determines whether or not to proceed.
|
11
|
+
# @return [String] Defaults to nil
|
12
|
+
attr_accessor :restart_before_command
|
13
|
+
|
14
|
+
# The command to restart the process with. This command can optionally
|
15
|
+
# be similar in behavior to the stop command, since the process will
|
16
|
+
# anyways be automatically started again, if autostart is set to true.
|
17
|
+
# @return [String] Defaults to nil
|
18
|
+
attr_accessor :restart_command
|
19
|
+
|
20
|
+
# The signals to pass to the process one by one attempting to restart
|
21
|
+
# it. Each signal is passed within the timeout period over equally
|
22
|
+
# distributed intervals (min. 2 seconds). Override with signals without
|
23
|
+
# "KILL" to never force kill the process.
|
24
|
+
# e.g. ["TERM", "INT"]
|
25
|
+
# @return [Array] Defaults to ["TERM", "INT", "KILL"]
|
26
|
+
attr_accessor :restart_signals
|
27
|
+
|
28
|
+
# The grace time period in seconds for the process to stop within
|
29
|
+
# (for restart). Covers the time period for the restart command or
|
30
|
+
# signals. After the timeout is over, the process is checked for
|
31
|
+
# running status and if not stopped, it re-enters the auto start
|
32
|
+
# lifecycle based on conditions.
|
33
|
+
# @return [String] Defaults to 10
|
34
|
+
attr_accessor :restart_timeout
|
35
|
+
|
36
|
+
# The command to run after the process is restarted.
|
37
|
+
# @return [String] Defaults to nil
|
38
|
+
attr_accessor :restart_after_command
|
39
|
+
|
40
|
+
def restart_process
|
41
|
+
result_handler = Proc.new do |result|
|
42
|
+
# If it is a boolean and value is true OR if it's an execution result and it succeeded.
|
43
|
+
if (!!result == result and result) or (result.respond_to?(:succeeded?) and result.succeeded?)
|
44
|
+
unlink_pid unless pid_running?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
execute_action(
|
48
|
+
result_handler,
|
49
|
+
env: (self.env || {}).merge(self.restart_env || {}),
|
50
|
+
before: self.restart_before_command,
|
51
|
+
command: self.restart_command,
|
52
|
+
signals: self.restart_signals,
|
53
|
+
after: self.restart_after_command,
|
54
|
+
timeout: self.restart_timeout
|
55
|
+
)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|