cognizant 0.0.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.
- 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
|