cognizant 0.0.1 → 0.0.2
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 +2 -1
- data/README.md +118 -57
- data/bin/cognizant +156 -36
- data/bin/cognizantd +19 -9
- data/cognizant.gemspec +9 -3
- data/examples/cognizantd.yml +37 -10
- data/examples/redis-server.rb +19 -8
- data/lib/cognizant/process/actions.rb +3 -17
- data/lib/cognizant/process/condition_check.rb +59 -0
- data/lib/cognizant/process/conditions/always_true.rb +15 -0
- data/lib/cognizant/process/conditions/cpu_usage.rb +21 -0
- data/lib/cognizant/process/conditions/flapping.rb +57 -0
- data/lib/cognizant/process/conditions/memory_usage.rb +32 -0
- data/lib/cognizant/process/conditions/poll_condition.rb +23 -0
- data/lib/cognizant/process/conditions/trigger_condition.rb +52 -0
- data/lib/cognizant/process/conditions.rb +16 -0
- data/lib/cognizant/process/execution.rb +5 -5
- data/lib/cognizant/process/pid.rb +4 -2
- data/lib/cognizant/process/status.rb +4 -16
- data/lib/cognizant/process.rb +92 -12
- data/lib/cognizant/server/commands.rb +50 -23
- data/lib/cognizant/server/daemon.rb +57 -19
- data/lib/cognizant/server/interface.rb +58 -32
- data/lib/cognizant/system/ps.rb +61 -0
- data/lib/cognizant/system/signal.rb +37 -0
- data/lib/cognizant/system.rb +28 -0
- data/lib/cognizant/util/rotational_array.rb +17 -0
- data/lib/cognizant/util/symbolize_hash_keys.rb +19 -0
- data/lib/cognizant/version.rb +1 -1
- data/lib/cognizant.rb +5 -2
- metadata +70 -10
- data/lib/cognizant/client/cli.rb +0 -9
- data/lib/cognizant/client/interface.rb +0 -33
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,31 +1,32 @@
|
|
1
|
-
# Cognizant
|
1
|
+
# Cognizant: system utility to supervise your processes
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
Let us say that you have a program that is critical for your application. Any
|
4
|
+
downtime for the processes of this program would hurt your business. You want
|
5
|
+
to make sure these processes are always up and working. If anything unexpected
|
6
|
+
happens to their state, you want to be notified about it.
|
5
7
|
|
6
|
-
|
8
|
+
Enter Cognizant. Cognizant is a system utility that supervises your processes,
|
9
|
+
monitoring and ensuring their state based on a flexible criteria.
|
10
|
+
|
11
|
+
In simpler terms, it keeps your processes up and running. It ensures
|
7
12
|
that something productive (like restart) is done when the process being
|
8
13
|
monitored matches a certain condition (like RAM, CPU usage or a custom
|
9
14
|
condition).
|
10
15
|
|
11
|
-
|
12
|
-
|
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).
|
16
|
+
And if it matters, cognizant means "having knowledge or being aware of",
|
17
|
+
according to Apple's Dictionary.
|
17
18
|
|
18
19
|
Cognizant can be used to monitor any long running process, including the
|
19
|
-
following
|
20
|
+
following:
|
20
21
|
|
21
22
|
- Web servers (Nginx, Apache httpd, WebSocket, etc.)
|
22
23
|
- Databases (Redis, MongoDB, MySQL, PostgreSQL, etc.)
|
23
|
-
- Job workers (Resque, Sidekiq, etc.)
|
24
|
+
- Job workers (Resque, Sidekiq, Qless, etc.)
|
24
25
|
- Message queue applications (RabbitMQ, Beanstalkd, etc.)
|
25
|
-
- Logs collection
|
26
|
+
- Logs collection daemons
|
26
27
|
- Or any other program that needs to keep running
|
27
28
|
|
28
|
-
|
29
|
+
### Monitoring
|
29
30
|
|
30
31
|
Cognizant can be used to monitor an application process' state so that it
|
31
32
|
is running at all times. When cognizant is instructed to monitor a process,
|
@@ -33,13 +34,23 @@ by default, the process will automatically be started. These processes are
|
|
33
34
|
automatically monitored for their state. i.e. a process is automatically
|
34
35
|
started again if it stops unexpectedly.
|
35
36
|
|
36
|
-
|
37
|
+
### Conditions
|
37
38
|
|
38
39
|
Conditions provide a way to monitor and act on more than just the state of a
|
39
40
|
process. For example, conditions can monitor the resource utilization (RAM,
|
40
41
|
CPU, etc.) of the application process and restart it if it matches a
|
41
42
|
condition.
|
42
43
|
|
44
|
+
See examples for conditions usage.
|
45
|
+
|
46
|
+
### Notifications
|
47
|
+
|
48
|
+
PS: Notifications currently need work.
|
49
|
+
|
50
|
+
Notifications provide a way to alert system administrator of unexpected events
|
51
|
+
happening with the process. Notifications can use multiple gateways, including
|
52
|
+
email and twitter [direct message].
|
53
|
+
|
43
54
|
## Getting started
|
44
55
|
|
45
56
|
Cognizant is written in the Ruby programming language, and hence depends on
|
@@ -73,17 +84,44 @@ The daemon, with it's default options, requires superuser access to certain syst
|
|
73
84
|
|
74
85
|
To start without superuser access, specify these file and directory config variables to where the user starting it has write access:
|
75
86
|
|
76
|
-
$ cognizantd
|
87
|
+
$ cognizantd ./examples/cognizantd.yml
|
77
88
|
|
78
89
|
# assuming that:
|
79
90
|
|
80
|
-
$ cat ~/.
|
91
|
+
$ cat ~/.examples/cognizantd.yml # find this file in source code for latest version
|
81
92
|
---
|
82
93
|
socket: ~/.cognizant/cognizantd.sock
|
83
94
|
pidfile: ~/.cognizant/cognizantd.pid
|
84
95
|
logfile: ~/.cognizant/cognizantd.log
|
85
96
|
pids_dir: ~/.cognizant/pids/
|
86
97
|
logs_dir: ~/.cognizant/logs/
|
98
|
+
|
99
|
+
monitor: {
|
100
|
+
redis-server-1: {
|
101
|
+
group: redis,
|
102
|
+
start_command: /usr/local/bin/redis-server -,
|
103
|
+
start_with_input: "daemonize no\nport 6666",
|
104
|
+
ping_command: redis-cli -p 6666 PING,
|
105
|
+
stop_signals: [TERM, INT]
|
106
|
+
},
|
107
|
+
redis-server-2: {
|
108
|
+
group: redis,
|
109
|
+
start_command: /usr/local/bin/redis-server -,
|
110
|
+
start_with_input: "daemonize no\nport 7777",
|
111
|
+
ping_command: redis-cli -p 7777 PING,
|
112
|
+
stop_command: redis-cli -p 7777 SHUTDOWN
|
113
|
+
},
|
114
|
+
sleep: {
|
115
|
+
start_command: sleep 3,
|
116
|
+
checks: {
|
117
|
+
flapping: {
|
118
|
+
times: 4,
|
119
|
+
within: 15, # Seconds.
|
120
|
+
retry_after: 30 # Seconds.
|
121
|
+
}
|
122
|
+
}
|
123
|
+
}
|
124
|
+
}
|
87
125
|
|
88
126
|
or
|
89
127
|
|
@@ -91,56 +129,76 @@ or
|
|
91
129
|
$ echo <<EOF | cognizantd -
|
92
130
|
---
|
93
131
|
socket: ~/.cognizant/cognizantd.sock
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
132
|
+
...
|
133
|
+
monitor: {
|
134
|
+
...
|
135
|
+
...
|
136
|
+
}
|
98
137
|
EOF
|
99
138
|
|
139
|
+
Process information can also be provided via Ruby code. See `load` command below.
|
140
|
+
|
100
141
|
## Using the administration utility
|
101
142
|
|
102
143
|
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
144
|
|
104
|
-
Here
|
145
|
+
Here are some basic operational commands:
|
105
146
|
|
106
|
-
$ cognizant monitor
|
107
|
-
|
108
|
-
--chdir /apps/example/current/ \
|
109
|
-
--start_command "bundle exec rake resque:work"
|
147
|
+
$ cognizant monitor redis # by group name
|
148
|
+
$ cognizant restart redis-server-1 # by process name
|
110
149
|
|
111
|
-
|
150
|
+
To get cognizant to ignore a particular process' state:
|
112
151
|
|
113
|
-
$ cognizant
|
114
|
-
---
|
115
|
-
resque-worker-1: {
|
116
|
-
state: running,
|
117
|
-
uptime: 3600 # 1 hour
|
118
|
-
}
|
152
|
+
$ cognizant unmonitor sleep-10
|
119
153
|
|
120
|
-
|
154
|
+
Now check status of all managed processes:
|
121
155
|
|
122
|
-
$ cognizant status
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
156
|
+
$ cognizant status
|
157
|
+
+----------------+-------+--------------------------------------+
|
158
|
+
| Process | Group | State |
|
159
|
+
+----------------+-------+--------------------------------------+
|
160
|
+
| redis-server-1 | redis | running since 1 minute |
|
161
|
+
+----------------+-------+--------------------------------------+
|
162
|
+
| redis-server-2 | redis | running since 2 minutes |
|
163
|
+
+----------------+-------+--------------------------------------+
|
164
|
+
| sleep-10 | | unmonitored since less than a minute |
|
165
|
+
+----------------+-------+--------------------------------------+
|
166
|
+
2012-11-23 01:16:18 +0530
|
167
|
+
|
168
|
+
Here's how you tell cognizant to start monitoring new processes:
|
169
|
+
|
170
|
+
$ cognizant load ./examples/redis-server.rb # find this file in source code
|
171
|
+
|
172
|
+
All of the available commands are:
|
173
|
+
|
174
|
+
- `help` - Shows a list of commands or help for one command
|
175
|
+
- `status [name]` - Display status of managed process(es) or group(s)
|
176
|
+
- `load ./cog.rb` - Loads the process information from specified Ruby file
|
177
|
+
- `monitor name` - Monitor the specified process or group
|
178
|
+
- `unmonitor name` - Unmonitor the specified process or group
|
179
|
+
- `start name` - Start the specified process or group
|
180
|
+
- `stop name` - Stop the specified process or group
|
181
|
+
- `restart name` - Restart the specified process or group
|
182
|
+
- `shutdown` - Stop the monitoring daemon without affecting processes
|
183
|
+
|
184
|
+
See `cognizant help` for options.
|
185
|
+
|
186
|
+
## Contributing
|
187
|
+
|
188
|
+
Contributions are definitely welcome. To contribute, just follow the usual
|
189
|
+
workflow:
|
190
|
+
|
191
|
+
1. Fork Cognizant
|
192
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
193
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
194
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
195
|
+
5. Create new Github pull request
|
138
196
|
|
139
|
-
|
197
|
+
## Compatibility
|
140
198
|
|
141
|
-
Cognizant
|
199
|
+
Cognizant was developed and tested under Ruby 1.9.2-p290.
|
142
200
|
|
143
|
-
|
201
|
+
## Similar programs
|
144
202
|
|
145
203
|
- Monit
|
146
204
|
- God (Ruby)
|
@@ -151,10 +209,13 @@ Cognizant can be used on any operating system where Ruby 1.9+ works.
|
|
151
209
|
- Systemd
|
152
210
|
- Launchd
|
153
211
|
|
154
|
-
###
|
212
|
+
### Links
|
155
213
|
|
156
|
-
|
214
|
+
- Documentation: http://rubydoc.info/github/Gurpartap/cognizant/frames
|
215
|
+
- Source: https://github.com/Gurpartap/cognizant
|
216
|
+
- Rubygems: https://rubygems.org/gems/cognizant
|
157
217
|
|
158
|
-
|
218
|
+
## About
|
159
219
|
|
160
|
-
|
220
|
+
Cognizant is a project of [Gurpartap Singh](http://gurpartap.com/). Feel free
|
221
|
+
to get in touch.
|
data/bin/cognizant
CHANGED
@@ -1,58 +1,178 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
require "cognizant/version"
|
4
|
+
require "gli"
|
5
|
+
require "formatador"
|
6
|
+
require "socket"
|
7
|
+
require "json"
|
8
|
+
|
9
|
+
include GLI::App
|
10
|
+
|
3
11
|
# Set the process name.
|
4
12
|
$0 = File.basename(__FILE__)
|
5
13
|
|
6
|
-
#
|
14
|
+
# Set to flush standard output/error immediately.
|
7
15
|
$stdout.sync = true
|
8
16
|
$stderr.sync = true
|
9
17
|
|
10
|
-
|
11
|
-
|
18
|
+
program_desc "administration utility for cognizantd"
|
19
|
+
@version = Cognizant::VERSION
|
12
20
|
|
13
|
-
|
14
|
-
socket: "/var/run/cognizant/cognizantd.sock"
|
15
|
-
}
|
21
|
+
sort_help :manually
|
16
22
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
cognizant [OPTIONS] command
|
23
|
+
desc "The socket lock file of the daemon server"
|
24
|
+
arg_name "FILE"
|
25
|
+
flag :socket, :type => String, :default_value => "/var/run/cognizant/cognizantd.sock"
|
21
26
|
|
22
|
-
|
23
|
-
|
27
|
+
desc "The server address of the daemon server"
|
28
|
+
arg_name "ADDRESS"
|
29
|
+
flag "bind-address", :type => String
|
24
30
|
|
25
|
-
|
26
|
-
|
27
|
-
|
31
|
+
desc "The server port of the daemon server"
|
32
|
+
arg_name "PORT"
|
33
|
+
flag :port, :type => Integer
|
28
34
|
|
29
|
-
|
30
|
-
|
31
|
-
|
35
|
+
desc "Username to use for authentication with server"
|
36
|
+
arg_name "USERNAME"
|
37
|
+
flag :username, :type => String
|
32
38
|
|
33
|
-
|
34
|
-
|
35
|
-
|
39
|
+
desc "Password to use for authentication with server"
|
40
|
+
arg_name "PASSWORD"
|
41
|
+
flag :password, :type => String
|
36
42
|
|
37
|
-
|
38
|
-
|
39
|
-
end
|
43
|
+
desc "Print the version number and exit"
|
44
|
+
switch :version, :negatable => false
|
40
45
|
|
41
|
-
|
42
|
-
|
43
|
-
|
46
|
+
desc "Turn on tracing, enabling full backtrace"
|
47
|
+
switch :trace, :negatable => false
|
48
|
+
|
49
|
+
desc "Display status of managed process(es) or group(s)"
|
50
|
+
arg_name "process_name", :optional
|
51
|
+
command :status do |c|
|
52
|
+
c.action do |global_options, options, args|
|
53
|
+
connect_and_perform(global_options, :status, args) do |output|
|
54
|
+
begin
|
55
|
+
JSON.parse(output)
|
44
56
|
|
45
|
-
|
46
|
-
|
57
|
+
status_data = JSON.parse(output)
|
58
|
+
status_data.each_with_index do |process, index|
|
59
|
+
status_data[index]["State"] = "[green]#{process["State"]}[/] since #{distance_of_time_in_words(Time.now.to_i - process["Since"])}"
|
60
|
+
status_data[index]["Memory"] = number_to_human_size(process["Memory"] * 1024) # Convert kilobytes to bytes.
|
61
|
+
end
|
62
|
+
|
63
|
+
formatador = Formatador.new
|
64
|
+
formatador.display_line
|
65
|
+
formatador.display_table(status_data, ["Process", "Group", "State", "PID", "% CPU", "Memory"])
|
66
|
+
formatador.display_line(Time.now)
|
67
|
+
formatador.display_line
|
68
|
+
rescue => e
|
69
|
+
Formatador.display_line("[red]#{output}[/]")
|
70
|
+
end
|
47
71
|
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
desc "Loads the process information from specified Ruby file"
|
76
|
+
arg_name "file"
|
77
|
+
command :load do |c|
|
78
|
+
c.action do |global_options, options, args|
|
79
|
+
connect_and_perform(global_options, :load, args)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
desc "Monitor the specified process or group"
|
84
|
+
arg_name "process_name"
|
85
|
+
command :monitor do |c|
|
86
|
+
c.action do |global_options, options, args|
|
87
|
+
connect_and_perform(global_options, :monitor, args)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
desc "Unmonitor the specified process or group"
|
92
|
+
arg_name "process_name"
|
93
|
+
command :unmonitor do |c|
|
94
|
+
c.action do |global_options, options, args|
|
95
|
+
connect_and_perform(global_options, :unmonitor, args)
|
96
|
+
end
|
97
|
+
end
|
48
98
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
99
|
+
desc "Start the specified process or group"
|
100
|
+
arg_name "process_name"
|
101
|
+
command :start do |c|
|
102
|
+
c.action do |global_options, options, args|
|
103
|
+
connect_and_perform(global_options, :start, args)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
desc "Stop the specified process or group"
|
108
|
+
arg_name "process_name"
|
109
|
+
command :stop do |c|
|
110
|
+
c.action do |global_options, options, args|
|
111
|
+
connect_and_perform(global_options, :stop, args)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
desc "Restart the specified process or group"
|
116
|
+
arg_name "process_name"
|
117
|
+
command :restart do |c|
|
118
|
+
c.action do |global_options, options, args|
|
119
|
+
connect_and_perform(global_options, :restart, args)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
desc "Stop the monitoring daemon without affecting processes"
|
124
|
+
command :shutdown do |c|
|
125
|
+
c.action do |global_options, options, args|
|
126
|
+
connect_and_perform(global_options, :shutdown, args)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def connect_and_perform(global_options, task, args, &block)
|
131
|
+
output_handler = Proc.new do |socket|
|
132
|
+
socket.write("#{task.to_s} #{args.join(' ')}")
|
133
|
+
socket.flush
|
134
|
+
output = socket.gets
|
135
|
+
if block
|
136
|
+
block.call(output)
|
137
|
+
else
|
138
|
+
Formatador.display_line(output)
|
53
139
|
end
|
54
|
-
end
|
140
|
+
end
|
55
141
|
|
56
|
-
|
57
|
-
|
142
|
+
if global_options[:socket]
|
143
|
+
output_handler.call(UNIXSocket.new(global_options[:socket]))
|
144
|
+
else
|
145
|
+
output_handler.call(TCPSocket.new(global_options["bind-address"], global_options["port"]))
|
146
|
+
end
|
58
147
|
end
|
148
|
+
|
149
|
+
def distance_of_time_in_words(seconds)
|
150
|
+
minutes = seconds / 60
|
151
|
+
return nil if minutes < 0
|
152
|
+
case minutes
|
153
|
+
when 0 then "less than a minute"
|
154
|
+
when 1..59 then pluralize((minutes/1).floor, "minute", "minutes")
|
155
|
+
when 60..1439 then pluralize((minutes/60).floor, "hour", "hours")
|
156
|
+
when 1440..11519 then pluralize((minutes/1440).floor, "day", "days")
|
157
|
+
when 11520..43199 then pluralize((minutes/11520).floor, "week", "weeks")
|
158
|
+
when 43200..525599 then pluralize((minutes/43200).floor, "month", "months")
|
159
|
+
else pluralize((minutes/525600).floor, "year", "years")
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
SIZE_PREFIX = %w(TiB GiB MiB KiB Bytes).freeze
|
164
|
+
def number_to_human_size(size)
|
165
|
+
size = size.to_f
|
166
|
+
i = SIZE_PREFIX.length - 1
|
167
|
+
while size > 512 && i > 0
|
168
|
+
i -= 1
|
169
|
+
size /= 1024
|
170
|
+
end
|
171
|
+
((size > 9 || size.modulo(1) < 0.1 ? "%d" : "%.1f") % size) + " " + SIZE_PREFIX[i]
|
172
|
+
end
|
173
|
+
|
174
|
+
def pluralize(count, singular, plural)
|
175
|
+
"#{count || 0} " + ((count == 1 || count =~ /^1(\.0+)?$/) ? singular : plural)
|
176
|
+
end
|
177
|
+
|
178
|
+
exit run(ARGV)
|
data/bin/cognizantd
CHANGED
@@ -8,27 +8,34 @@ $stdout.sync = true
|
|
8
8
|
$stderr.sync = true
|
9
9
|
|
10
10
|
begin
|
11
|
-
require
|
11
|
+
require "optparse"
|
12
|
+
require "cognizant/version"
|
12
13
|
|
13
14
|
options = {}
|
14
15
|
|
15
16
|
OptionParser.new do |opts|
|
16
17
|
opts.banner = <<-EOF
|
17
|
-
|
18
|
-
cognizantd
|
18
|
+
NAME
|
19
|
+
cognizantd - system utility daemon to supervise your processes
|
19
20
|
|
20
|
-
|
21
|
+
SYNOPSIS:
|
22
|
+
cognizantd [global options] [config file | -]
|
23
|
+
|
24
|
+
VERSION
|
25
|
+
#{Cognizant::VERSION}
|
26
|
+
|
27
|
+
GLOBAL OPTIONS:
|
21
28
|
EOF
|
22
29
|
|
23
|
-
opts.on("--[no-]daemonize", "Whether or not to daemonize
|
30
|
+
opts.on("--[no-]daemonize", "Whether or not to daemonize cognizantd into background.") do |value|
|
24
31
|
options[:daemonize] = value
|
25
32
|
end
|
26
33
|
|
27
|
-
opts.on("--pidfile FILE", String, "The pid lock file for the daemon.") do |value|
|
34
|
+
opts.on("--pidfile FILE", String, "The pid (process identifier) lock file for the daemon.") do |value|
|
28
35
|
options[:pidfile] = value
|
29
36
|
end
|
30
37
|
|
31
|
-
opts.on("--logfile FILE", String, "The file to log the daemon's
|
38
|
+
opts.on("--logfile FILE", String, "The file to log the daemon's operational information into.") do |value|
|
32
39
|
options[:logfile] = value
|
33
40
|
end
|
34
41
|
|
@@ -89,23 +96,26 @@ begin
|
|
89
96
|
end
|
90
97
|
|
91
98
|
opts.on("-v", "--version", "Print the version number and exit.") do
|
92
|
-
require
|
99
|
+
require "cognizant/version"
|
93
100
|
$stdout.puts Cognizant::VERSION
|
94
101
|
exit(0)
|
95
102
|
end
|
96
103
|
end.parse!
|
97
104
|
|
98
105
|
if config_file = ARGV.shift
|
106
|
+
require "cognizant/util/symbolize_hash_keys"
|
107
|
+
|
99
108
|
if config_file.eql?("-")
|
100
109
|
config = YAML.load(ARGF.read)
|
101
110
|
else
|
102
111
|
config = YAML.load_file(config_file)
|
103
112
|
end
|
104
113
|
config = config.inject({}) { |c,(k,v)| c[k.gsub("-", "_").to_sym] = v; c }
|
114
|
+
config.deep_symbolize_keys!
|
105
115
|
options = config.merge(options)
|
106
116
|
end
|
107
117
|
|
108
|
-
require
|
118
|
+
require "cognizant/server"
|
109
119
|
Cognizant::Server.start(options)
|
110
120
|
rescue => exception
|
111
121
|
if exception.instance_of?(SystemExit)
|
data/cognizant.gemspec
CHANGED
@@ -4,9 +4,9 @@ require File.expand_path('../lib/cognizant/version', __FILE__)
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
5
|
gem.authors = ["Gurpartap Singh"]
|
6
6
|
gem.email = ["contact@gurpartap.com"]
|
7
|
-
gem.description = "
|
8
|
-
gem.summary = "Cognizant is
|
9
|
-
gem.homepage = "http://
|
7
|
+
gem.description = "Cognizant is a process management system utility that supervises your processes, ensuring their state based on a flexible criteria."
|
8
|
+
gem.summary = "Cognizant is a process management system utility that supervises your processes, ensuring their state based on a flexible criteria."
|
9
|
+
gem.homepage = "http://github.com/Gurpartap/cognizant"
|
10
10
|
|
11
11
|
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
12
12
|
gem.files = `git ls-files`.split("\n")
|
@@ -19,6 +19,12 @@ Gem::Specification.new do |gem|
|
|
19
19
|
gem.add_development_dependency "redcarpet"
|
20
20
|
gem.add_development_dependency "yard"
|
21
21
|
|
22
|
+
# cognizantd
|
22
23
|
gem.add_dependency "eventmachine"
|
23
24
|
gem.add_dependency "state_machine"
|
25
|
+
gem.add_dependency "activesupport"
|
26
|
+
|
27
|
+
# cognizant
|
28
|
+
gem.add_dependency "gli"
|
29
|
+
gem.add_dependency "formatador"
|
24
30
|
end
|
data/examples/cognizantd.yml
CHANGED
@@ -7,17 +7,44 @@ pids_dir: ~/.cognizant/pids/
|
|
7
7
|
logs_dir: ~/.cognizant/logs/
|
8
8
|
|
9
9
|
monitor: {
|
10
|
-
redis-server: {
|
10
|
+
redis-server-1: {
|
11
|
+
autostart: false,
|
12
|
+
group: redis,
|
11
13
|
start_command: /usr/local/bin/redis-server -,
|
12
|
-
start_with_input: daemonize no,
|
13
|
-
ping_command: redis-cli PING,
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
start_with_input: "daemonize no\nport 6666",
|
15
|
+
ping_command: redis-cli -p 6666 PING,
|
16
|
+
stop_signals: [TERM, INT],
|
17
|
+
checks: {
|
18
|
+
cpu_usage: {
|
19
|
+
every: 3,
|
20
|
+
above: 60,
|
21
|
+
times: 3,
|
22
|
+
do: restart
|
23
|
+
},
|
24
|
+
memory_usage: {
|
25
|
+
every: 5, # Seconds.
|
26
|
+
above: 1220608, # Bytes.
|
27
|
+
times: [3, 5], # Three out of five times.
|
28
|
+
do: stop # Defaults to restart.
|
29
|
+
}
|
30
|
+
}
|
18
31
|
},
|
19
|
-
|
20
|
-
|
21
|
-
|
32
|
+
redis-server-2: {
|
33
|
+
autostart: false,
|
34
|
+
group: redis,
|
35
|
+
start_command: /usr/local/bin/redis-server -,
|
36
|
+
start_with_input: "daemonize no\nport 7777",
|
37
|
+
ping_command: redis-cli -p 7777 PING,
|
38
|
+
stop_command: redis-cli -p 7777 SHUTDOWN
|
39
|
+
},
|
40
|
+
sleep: {
|
41
|
+
start_command: sleep 3,
|
42
|
+
checks: {
|
43
|
+
flapping: {
|
44
|
+
times: 4,
|
45
|
+
within: 15, # Seconds.
|
46
|
+
retry_after: 30 # Seconds.
|
47
|
+
}
|
48
|
+
}
|
22
49
|
}
|
23
50
|
}
|
data/examples/redis-server.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
Cognizant.monitor
|
4
|
-
process.group
|
5
|
-
process.uid
|
6
|
-
process.gid
|
7
|
-
process.start_command
|
8
|
-
process.ping_command
|
1
|
+
# 2 slave instances to master at port 6000.
|
2
|
+
3.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
9
|
|
10
10
|
slaveof = i == 0 ? "" : "slaveof 127.0.0.1 6000"
|
11
11
|
process.start_with_input = <<-heredoc
|
@@ -13,5 +13,16 @@
|
|
13
13
|
port 600#{i}
|
14
14
|
#{slaveof}
|
15
15
|
heredoc
|
16
|
+
|
17
|
+
# process.on :always_true, :every => 2.seconds, :times => 3 do |p|
|
18
|
+
# `say "Boom!"`
|
19
|
+
# end
|
20
|
+
|
21
|
+
process.check(:flapping, :times => 2, :within => 30.seconds, :retry_after => 7.seconds)
|
22
|
+
process.check(:cpu_usage, :every => 3.seconds, :above => 60, :times => 3, :do => :restart)
|
23
|
+
|
24
|
+
process.check(:memory_usage, :every => 5.seconds, :above => 100.megabytes, :times => [3, 5]) do |p|
|
25
|
+
p.restart # Restart is the default anyways.
|
26
|
+
end
|
16
27
|
end
|
17
28
|
end
|