resurrected_god 1.0.0 → 1.1.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 +4 -4
- data/History.md +25 -0
- data/README.md +3 -2
- data/bin/god +1 -0
- data/ext/god/extconf.rb +2 -0
- data/lib/god/behavior.rb +2 -0
- data/lib/god/behaviors/clean_pid_file.rb +2 -0
- data/lib/god/behaviors/clean_unix_socket.rb +2 -0
- data/lib/god/behaviors/notify_when_flapping.rb +2 -0
- data/lib/god/cli/command.rb +3 -1
- data/lib/god/cli/run.rb +2 -0
- data/lib/god/cli/version.rb +2 -0
- data/lib/god/condition.rb +2 -0
- data/lib/god/conditions/always.rb +2 -0
- data/lib/god/conditions/complex.rb +2 -0
- data/lib/god/conditions/cpu_usage.rb +2 -0
- data/lib/god/conditions/degrading_lambda.rb +2 -0
- data/lib/god/conditions/disk_usage.rb +2 -0
- data/lib/god/conditions/file_mtime.rb +2 -0
- data/lib/god/conditions/file_touched.rb +2 -0
- data/lib/god/conditions/flapping.rb +2 -0
- data/lib/god/conditions/http_response_code.rb +2 -0
- data/lib/god/conditions/lambda.rb +2 -0
- data/lib/god/conditions/memory_usage.rb +2 -0
- data/lib/god/conditions/process_exits.rb +2 -0
- data/lib/god/conditions/process_running.rb +5 -3
- data/lib/god/conditions/socket_responding.rb +4 -0
- data/lib/god/conditions/tries.rb +2 -0
- data/lib/god/configurable.rb +2 -1
- data/lib/god/contact.rb +3 -1
- data/lib/god/contacts/airbrake.rb +3 -2
- data/lib/god/contacts/email.rb +2 -0
- data/lib/god/contacts/slack.rb +2 -1
- data/lib/god/contacts/webhook.rb +2 -1
- data/lib/god/driver.rb +2 -0
- data/lib/god/errors.rb +2 -0
- data/lib/god/event_handler.rb +2 -0
- data/lib/god/event_handlers/dummy_handler.rb +3 -1
- data/lib/god/event_handlers/kqueue_handler.rb +3 -1
- data/lib/god/event_handlers/netlink_handler.rb +3 -1
- data/lib/god/logger.rb +2 -0
- data/lib/god/metric.rb +2 -0
- data/lib/god/process.rb +3 -1
- data/lib/god/registry.rb +2 -0
- data/lib/god/simple_logger.rb +2 -0
- data/lib/god/socket.rb +2 -0
- data/lib/god/sugar.rb +2 -0
- data/lib/god/sys_logger.rb +2 -0
- data/lib/god/system/portable_poller.rb +2 -0
- data/lib/god/system/process.rb +2 -0
- data/lib/god/system/slash_proc_poller.rb +4 -2
- data/lib/god/task.rb +2 -0
- data/lib/god/timeline.rb +3 -1
- data/lib/god/trigger.rb +2 -0
- data/lib/god/version.rb +3 -1
- data/lib/god/watch.rb +4 -2
- data/lib/god.rb +17 -17
- metadata +38 -18
- data/lib/god/contacts/campfire.rb +0 -119
- data/lib/god/contacts/prowl.rb +0 -56
- data/lib/god/contacts/scout.rb +0 -52
- data/lib/god/contacts/sensu.rb +0 -63
- data/lib/god/contacts/statsd.rb +0 -46
- data/lib/god/contacts/twitter.rb +0 -51
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e65b14e71958dd94729eeba93780283ccdb73e49a202859d816b94832656436f
|
|
4
|
+
data.tar.gz: 9a32895548e3f07d7a0e0f0907475d20217da6fe58e2227fcc5c852644b968b4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 37610457947e042fbeaa46aca0087b5f8cf022188ad9049c0512decf13136a879f19b8993da7ace3035dd574163d94fdd2ffb63bb148ab13513aaa45bcb29044
|
|
7
|
+
data.tar.gz: f0cc1a3ffc8a58c0c6b5285a30134a6a4657ed7479913b4bcfd66ebaf7978eba1aaf2ac3a409543ecf17caf84b872e48fa16b841056b56a07aa33eaadbcd4e3d
|
data/History.md
CHANGED
|
@@ -1,3 +1,28 @@
|
|
|
1
|
+
## 1.1.1 / 2023-12-29
|
|
2
|
+
|
|
3
|
+
* Minor Changes
|
|
4
|
+
* Add drb and syslog to runtime dependencies for Ruby 3.4+
|
|
5
|
+
|
|
6
|
+
## 1.1.0 / 2022-06-29
|
|
7
|
+
|
|
8
|
+
* Major Changes
|
|
9
|
+
* Drop support for Campfire
|
|
10
|
+
* Drop support for Prowl
|
|
11
|
+
* Drop support for Scout
|
|
12
|
+
* Drop support for Sensu
|
|
13
|
+
* Drop support for StatsD
|
|
14
|
+
* Drop support for Twitter
|
|
15
|
+
* Bug fixes
|
|
16
|
+
* Use `String#+@` to avoid modify frozen String in `God.running_load`
|
|
17
|
+
* Minor Enhancements
|
|
18
|
+
* Enable `frozen_string_literal` entirely
|
|
19
|
+
* Remove unused gems from Gemfile
|
|
20
|
+
* Regenerate documents by using AsciiDoctor
|
|
21
|
+
* Polish documents
|
|
22
|
+
* Avoid modifying constant `CONTACT_DEPS`
|
|
23
|
+
* Remove an unused variable in `God::Configurable#base_name`
|
|
24
|
+
* It was for fix MRI's local scope optimization bug.
|
|
25
|
+
|
|
1
26
|
## 1.0.0 / 2022-06-22
|
|
2
27
|
|
|
3
28
|
* Major Changes
|
data/README.md
CHANGED
|
@@ -2,7 +2,8 @@ ResurrectedGod: The Ruby Framework for Process Management
|
|
|
2
2
|
==============================================
|
|
3
3
|
|
|
4
4
|
[](https://badge.fury.io/rb/resurrected_god)
|
|
5
|
-
[](https://github.com/mishina2228/resurrected_god/actions/workflows/test.yml)
|
|
6
|
+
[](https://rubydoc.info/gems/resurrected_god)
|
|
6
7
|
[](https://codeclimate.com/github/mishina2228/resurrected_god/maintainability)
|
|
7
8
|
[](https://codecov.io/gh/mishina2228/resurrected_god)
|
|
8
9
|
|
|
@@ -25,7 +26,7 @@ Documentation
|
|
|
25
26
|
-------------
|
|
26
27
|
|
|
27
28
|
See in-repo documentation at [doc](doc).
|
|
28
|
-
See online documentation at
|
|
29
|
+
See online documentation at [here](https://mishina2228.github.io/resurrected_god/).
|
|
29
30
|
|
|
30
31
|
Community
|
|
31
32
|
---------
|
data/bin/god
CHANGED
data/ext/god/extconf.rb
CHANGED
data/lib/god/behavior.rb
CHANGED
data/lib/god/cli/command.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module God
|
|
2
4
|
module CLI
|
|
3
5
|
class Command
|
|
@@ -25,7 +27,7 @@ module God
|
|
|
25
27
|
def dispatch
|
|
26
28
|
if %w[load status signal log quit terminate].include?(@command)
|
|
27
29
|
setup
|
|
28
|
-
send("#{@command}_command")
|
|
30
|
+
send(:"#{@command}_command")
|
|
29
31
|
elsif %w[start stop restart monitor unmonitor remove].include?(@command)
|
|
30
32
|
setup
|
|
31
33
|
lifecycle_command
|
data/lib/god/cli/run.rb
CHANGED
data/lib/god/cli/version.rb
CHANGED
data/lib/god/condition.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module God
|
|
2
4
|
module Conditions
|
|
3
5
|
# Trigger when a process is running or not running depending on attributes.
|
|
@@ -46,13 +48,13 @@ module God
|
|
|
46
48
|
active = pid && System::Process.new(pid).exists?
|
|
47
49
|
|
|
48
50
|
if running && active
|
|
49
|
-
info.
|
|
51
|
+
info.push('process is running')
|
|
50
52
|
true
|
|
51
53
|
elsif !running && !active
|
|
52
|
-
info.
|
|
54
|
+
info.push('process is not running')
|
|
53
55
|
true
|
|
54
56
|
else
|
|
55
|
-
info.
|
|
57
|
+
info.push('process is not running') if running
|
|
56
58
|
false
|
|
57
59
|
end
|
|
58
60
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'socket'
|
|
2
4
|
include Socket::Constants
|
|
3
5
|
|
|
@@ -112,12 +114,14 @@ module God
|
|
|
112
114
|
begin
|
|
113
115
|
s = TCPSocket.new(addr, port)
|
|
114
116
|
rescue SystemCallError
|
|
117
|
+
# NOOP
|
|
115
118
|
end
|
|
116
119
|
status = responding != s.nil?
|
|
117
120
|
when 'unix'
|
|
118
121
|
begin
|
|
119
122
|
s = UNIXSocket.new(path)
|
|
120
123
|
rescue SystemCallError
|
|
124
|
+
# NOOP
|
|
121
125
|
end
|
|
122
126
|
status = responding != s.nil?
|
|
123
127
|
else
|
data/lib/god/conditions/tries.rb
CHANGED
data/lib/god/configurable.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module God
|
|
2
4
|
module Configurable
|
|
3
5
|
# Override this method in your Configurable (optional)
|
|
@@ -28,7 +30,6 @@ module God
|
|
|
28
30
|
end
|
|
29
31
|
|
|
30
32
|
def base_name
|
|
31
|
-
x = 1 # fix for MRI's local scope optimization bug DO NOT REMOVE!
|
|
32
33
|
@base_name ||= self.class.name.split('::').last
|
|
33
34
|
end
|
|
34
35
|
|
data/lib/god/contact.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module God
|
|
2
4
|
class Contact
|
|
3
5
|
include Configurable
|
|
@@ -26,7 +28,7 @@ module God
|
|
|
26
28
|
end
|
|
27
29
|
|
|
28
30
|
def arg(name)
|
|
29
|
-
instance_variable_get("@#{name}") || self.class.instance_variable_get("@#{name}")
|
|
31
|
+
instance_variable_get(:"@#{name}") || self.class.instance_variable_get(:"@#{name}")
|
|
30
32
|
end
|
|
31
33
|
|
|
32
34
|
# Normalize the given notify specification into canonical form.
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Send a notice to Airbrake (https://airbrake.io).
|
|
2
4
|
#
|
|
3
5
|
# apikey - The String API key.
|
|
4
6
|
|
|
5
|
-
CONTACT_DEPS[:airbrake] = ['airbrake']
|
|
6
7
|
CONTACT_DEPS[:airbrake].each do |d|
|
|
7
8
|
require d
|
|
8
9
|
end
|
data/lib/god/contacts/email.rb
CHANGED
data/lib/god/contacts/slack.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# Send a message to a Slack channel
|
|
2
4
|
#
|
|
3
5
|
# account - The name of your Slack account (visible in URL, e.g. foo.slack.com)
|
|
@@ -9,7 +11,6 @@
|
|
|
9
11
|
require 'net/http'
|
|
10
12
|
require 'uri'
|
|
11
13
|
|
|
12
|
-
CONTACT_DEPS[:slack] = ['json']
|
|
13
14
|
CONTACT_DEPS[:slack].each do |d|
|
|
14
15
|
require d
|
|
15
16
|
end
|
data/lib/god/contacts/webhook.rb
CHANGED
data/lib/god/driver.rb
CHANGED
data/lib/god/errors.rb
CHANGED
data/lib/god/event_handler.rb
CHANGED
data/lib/god/logger.rb
CHANGED
data/lib/god/metric.rb
CHANGED
data/lib/god/process.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module God
|
|
2
4
|
class Process
|
|
3
5
|
WRITES_PID = [:start, :restart].freeze
|
|
@@ -251,7 +253,7 @@ module God
|
|
|
251
253
|
$stdout.reopen(w)
|
|
252
254
|
r.close
|
|
253
255
|
pid = self.spawn(command)
|
|
254
|
-
puts pid
|
|
256
|
+
puts pid # send pid back to forker
|
|
255
257
|
exit!(0)
|
|
256
258
|
end
|
|
257
259
|
|
data/lib/god/registry.rb
CHANGED
data/lib/god/simple_logger.rb
CHANGED
data/lib/god/socket.rb
CHANGED
data/lib/god/sugar.rb
CHANGED
data/lib/god/sys_logger.rb
CHANGED
data/lib/god/system/process.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module God
|
|
2
4
|
module System
|
|
3
5
|
class SlashProcPoller < PortablePoller
|
|
@@ -5,8 +7,8 @@ module God
|
|
|
5
7
|
@@hertz = 100
|
|
6
8
|
@@total_mem = nil
|
|
7
9
|
|
|
8
|
-
MEMINFO_PATH = '/proc/meminfo'
|
|
9
|
-
UPTIME_PATH = '/proc/uptime'
|
|
10
|
+
MEMINFO_PATH = '/proc/meminfo'
|
|
11
|
+
UPTIME_PATH = '/proc/uptime'
|
|
10
12
|
|
|
11
13
|
REQUIRED_PATHS = [MEMINFO_PATH, UPTIME_PATH].freeze
|
|
12
14
|
|
data/lib/god/task.rb
CHANGED
data/lib/god/timeline.rb
CHANGED
data/lib/god/trigger.rb
CHANGED
data/lib/god/version.rb
CHANGED
data/lib/god/watch.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'etc'
|
|
2
4
|
require 'forwardable'
|
|
3
5
|
|
|
@@ -282,7 +284,7 @@ module God
|
|
|
282
284
|
before_items = behaviors
|
|
283
285
|
before_items += [condition] if condition
|
|
284
286
|
before_items.each do |b|
|
|
285
|
-
info = b.send("before_#{action}")
|
|
287
|
+
info = b.send(:"before_#{action}")
|
|
286
288
|
if info
|
|
287
289
|
msg = "#{name} before_#{action}: #{info} (#{b.base_name})"
|
|
288
290
|
applog(self, :info, msg)
|
|
@@ -302,7 +304,7 @@ module God
|
|
|
302
304
|
after_items = behaviors
|
|
303
305
|
after_items += [condition] if condition
|
|
304
306
|
after_items.each do |b|
|
|
305
|
-
info = b.send("after_#{action}")
|
|
307
|
+
info = b.send(:"after_#{action}")
|
|
306
308
|
if info
|
|
307
309
|
msg = "#{name} after_#{action}: #{info} (#{b.base_name})"
|
|
308
310
|
applog(self, :info, msg)
|
data/lib/god.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# Bail out before loading anything unless this flag is set.
|
|
2
4
|
#
|
|
3
5
|
# We are doing this to guard against bundler autoloading because there is
|
|
@@ -60,7 +62,11 @@ if $load_god
|
|
|
60
62
|
require 'god/cli/version'
|
|
61
63
|
require 'god/cli/command'
|
|
62
64
|
|
|
63
|
-
CONTACT_DEPS = {
|
|
65
|
+
CONTACT_DEPS = {
|
|
66
|
+
webhook: ['json'],
|
|
67
|
+
slack: ['json'],
|
|
68
|
+
airbrake: ['airbrake']
|
|
69
|
+
}.freeze
|
|
64
70
|
CONTACT_LOAD_SUCCESS = {}
|
|
65
71
|
|
|
66
72
|
def load_contact(name)
|
|
@@ -71,16 +77,10 @@ if $load_god
|
|
|
71
77
|
end
|
|
72
78
|
|
|
73
79
|
require 'god/contact'
|
|
74
|
-
load_contact(:campfire)
|
|
75
80
|
load_contact(:email)
|
|
76
|
-
load_contact(:prowl)
|
|
77
|
-
load_contact(:scout)
|
|
78
|
-
load_contact(:statsd)
|
|
79
|
-
load_contact(:twitter)
|
|
80
81
|
load_contact(:webhook)
|
|
81
82
|
load_contact(:airbrake)
|
|
82
83
|
load_contact(:slack)
|
|
83
|
-
load_contact(:sensu)
|
|
84
84
|
|
|
85
85
|
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), *%w[.. ext god])
|
|
86
86
|
|
|
@@ -124,7 +124,7 @@ if $load_god
|
|
|
124
124
|
class Module
|
|
125
125
|
def safe_attr_accessor(*args)
|
|
126
126
|
args.each do |arg|
|
|
127
|
-
define_method("#{arg}="
|
|
127
|
+
define_method(:"#{arg}=") do |other|
|
|
128
128
|
abort "God.#{arg} must be set before any Tasks are defined" if !running && inited
|
|
129
129
|
|
|
130
130
|
if running && inited
|
|
@@ -132,11 +132,11 @@ if $load_god
|
|
|
132
132
|
return
|
|
133
133
|
end
|
|
134
134
|
|
|
135
|
-
instance_variable_set("@#{arg}"
|
|
135
|
+
instance_variable_set(:"@#{arg}", other)
|
|
136
136
|
end
|
|
137
137
|
|
|
138
138
|
define_method(arg) do
|
|
139
|
-
instance_variable_get("@#{arg}"
|
|
139
|
+
instance_variable_get(:"@#{arg}")
|
|
140
140
|
end
|
|
141
141
|
end
|
|
142
142
|
end
|
|
@@ -168,7 +168,7 @@ if $load_god
|
|
|
168
168
|
STOP_TIMEOUT_DEFAULT = 10
|
|
169
169
|
|
|
170
170
|
# The default String signal to send for the stop command.
|
|
171
|
-
STOP_SIGNAL_DEFAULT = 'TERM'
|
|
171
|
+
STOP_SIGNAL_DEFAULT = 'TERM'
|
|
172
172
|
|
|
173
173
|
class << self
|
|
174
174
|
# user configurable
|
|
@@ -461,7 +461,7 @@ if $load_god
|
|
|
461
461
|
# Returns true on success, false if all tasks could not be stopped within 10
|
|
462
462
|
# seconds
|
|
463
463
|
def self.stop_all
|
|
464
|
-
watches.sort.each do |_name, w|
|
|
464
|
+
watches.sort.each do |(_name, w)|
|
|
465
465
|
Thread.new do
|
|
466
466
|
w.action(:stop)
|
|
467
467
|
w.unmonitor if w.state != :unmonitored
|
|
@@ -553,7 +553,7 @@ if $load_god
|
|
|
553
553
|
# from the system (if 'remove' or 'stop' was
|
|
554
554
|
# specified as the action).
|
|
555
555
|
def self.running_load(code, filename, action = nil)
|
|
556
|
-
|
|
556
|
+
error_message = +''
|
|
557
557
|
loaded_watches = []
|
|
558
558
|
unloaded_watches = []
|
|
559
559
|
jobs = []
|
|
@@ -598,17 +598,17 @@ if $load_god
|
|
|
598
598
|
LOG.finish_capture
|
|
599
599
|
rescue Exception => e
|
|
600
600
|
# Don't ever let running_load take down god.
|
|
601
|
-
|
|
601
|
+
error_message << LOG.finish_capture
|
|
602
602
|
|
|
603
603
|
unless e.instance_of?(SystemExit)
|
|
604
|
-
|
|
605
|
-
|
|
604
|
+
error_message << e.message << "\n"
|
|
605
|
+
error_message << e.backtrace.join("\n")
|
|
606
606
|
end
|
|
607
607
|
end
|
|
608
608
|
|
|
609
609
|
jobs.each(&:join)
|
|
610
610
|
|
|
611
|
-
[loaded_watches,
|
|
611
|
+
[loaded_watches, error_message, unloaded_watches]
|
|
612
612
|
end
|
|
613
613
|
|
|
614
614
|
# Load the given file(s) according to the given glob.
|
metadata
CHANGED
|
@@ -1,18 +1,46 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: resurrected_god
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tom Preston-Werner
|
|
8
8
|
- Kevin Clark
|
|
9
9
|
- Eric Lindvall
|
|
10
10
|
- mishina2228
|
|
11
|
-
autorequire:
|
|
11
|
+
autorequire:
|
|
12
12
|
bindir: bin
|
|
13
13
|
cert_chain: []
|
|
14
|
-
date:
|
|
15
|
-
dependencies:
|
|
14
|
+
date: 2023-12-29 00:00:00.000000000 Z
|
|
15
|
+
dependencies:
|
|
16
|
+
- !ruby/object:Gem::Dependency
|
|
17
|
+
name: drb
|
|
18
|
+
requirement: !ruby/object:Gem::Requirement
|
|
19
|
+
requirements:
|
|
20
|
+
- - "~>"
|
|
21
|
+
- !ruby/object:Gem::Version
|
|
22
|
+
version: '2.0'
|
|
23
|
+
type: :runtime
|
|
24
|
+
prerelease: false
|
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
26
|
+
requirements:
|
|
27
|
+
- - "~>"
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: '2.0'
|
|
30
|
+
- !ruby/object:Gem::Dependency
|
|
31
|
+
name: syslog
|
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
|
33
|
+
requirements:
|
|
34
|
+
- - "~>"
|
|
35
|
+
- !ruby/object:Gem::Version
|
|
36
|
+
version: '0.1'
|
|
37
|
+
type: :runtime
|
|
38
|
+
prerelease: false
|
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
40
|
+
requirements:
|
|
41
|
+
- - "~>"
|
|
42
|
+
- !ruby/object:Gem::Version
|
|
43
|
+
version: '0.1'
|
|
16
44
|
description: An easy to configure, easy to extend monitoring framework written in
|
|
17
45
|
Ruby.
|
|
18
46
|
email:
|
|
@@ -22,8 +50,7 @@ executables:
|
|
|
22
50
|
- god
|
|
23
51
|
extensions:
|
|
24
52
|
- ext/god/extconf.rb
|
|
25
|
-
extra_rdoc_files:
|
|
26
|
-
- README.md
|
|
53
|
+
extra_rdoc_files: []
|
|
27
54
|
files:
|
|
28
55
|
- History.md
|
|
29
56
|
- LICENSE
|
|
@@ -59,14 +86,8 @@ files:
|
|
|
59
86
|
- lib/god/configurable.rb
|
|
60
87
|
- lib/god/contact.rb
|
|
61
88
|
- lib/god/contacts/airbrake.rb
|
|
62
|
-
- lib/god/contacts/campfire.rb
|
|
63
89
|
- lib/god/contacts/email.rb
|
|
64
|
-
- lib/god/contacts/prowl.rb
|
|
65
|
-
- lib/god/contacts/scout.rb
|
|
66
|
-
- lib/god/contacts/sensu.rb
|
|
67
90
|
- lib/god/contacts/slack.rb
|
|
68
|
-
- lib/god/contacts/statsd.rb
|
|
69
|
-
- lib/god/contacts/twitter.rb
|
|
70
91
|
- lib/god/contacts/webhook.rb
|
|
71
92
|
- lib/god/driver.rb
|
|
72
93
|
- lib/god/errors.rb
|
|
@@ -98,10 +119,9 @@ metadata:
|
|
|
98
119
|
changelog_uri: https://github.com/mishina2228/resurrected_god/blob/master/History.md
|
|
99
120
|
homepage_uri: https://github.com/mishina2228/resurrected_god
|
|
100
121
|
rubygems_mfa_required: 'true'
|
|
101
|
-
source_code_uri: https://github.com/mishina2228/resurrected_god/tree/v1.
|
|
102
|
-
post_install_message:
|
|
103
|
-
rdoc_options:
|
|
104
|
-
- "--charset=UTF-8"
|
|
122
|
+
source_code_uri: https://github.com/mishina2228/resurrected_god/tree/v1.1.1
|
|
123
|
+
post_install_message:
|
|
124
|
+
rdoc_options: []
|
|
105
125
|
require_paths:
|
|
106
126
|
- lib
|
|
107
127
|
- ext
|
|
@@ -116,8 +136,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
116
136
|
- !ruby/object:Gem::Version
|
|
117
137
|
version: '0'
|
|
118
138
|
requirements: []
|
|
119
|
-
rubygems_version: 3.
|
|
120
|
-
signing_key:
|
|
139
|
+
rubygems_version: 3.4.10
|
|
140
|
+
signing_key:
|
|
121
141
|
specification_version: 4
|
|
122
142
|
summary: Process monitoring framework.
|
|
123
143
|
test_files: []
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
# Send a notice to a Campfire room (http://campfirenow.com).
|
|
2
|
-
#
|
|
3
|
-
# subdomain - The String subdomain of the Campfire account. If your URL is
|
|
4
|
-
# "foo.campfirenow.com" then your subdomain is "foo".
|
|
5
|
-
# token - The String token used for authentication.
|
|
6
|
-
# room - The String room name to which the message should be sent.
|
|
7
|
-
# ssl - A Boolean determining whether or not to use SSL
|
|
8
|
-
# (default: false).
|
|
9
|
-
|
|
10
|
-
require 'net/http'
|
|
11
|
-
require 'net/https'
|
|
12
|
-
|
|
13
|
-
CONTACT_DEPS[:campfire] = ['json']
|
|
14
|
-
CONTACT_DEPS[:campfire].each do |d|
|
|
15
|
-
require d
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
module Marshmallow
|
|
19
|
-
class Connection
|
|
20
|
-
def initialize(options)
|
|
21
|
-
raise 'Required option :subdomain not set.' unless options[:subdomain]
|
|
22
|
-
raise 'Required option :token not set.' unless options[:token]
|
|
23
|
-
|
|
24
|
-
@options = options
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def base_url
|
|
28
|
-
scheme = @options[:ssl] ? 'https' : 'http'
|
|
29
|
-
subdomain = @options[:subdomain]
|
|
30
|
-
"#{scheme}://#{subdomain}.campfirenow.com"
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def find_room_id_by_name(room)
|
|
34
|
-
url = URI.parse("#{base_url}/rooms.json")
|
|
35
|
-
|
|
36
|
-
http = Net::HTTP.new(url.host, url.port)
|
|
37
|
-
http.use_ssl = true if @options[:ssl]
|
|
38
|
-
|
|
39
|
-
req = Net::HTTP::Get.new(url.path)
|
|
40
|
-
req.basic_auth(@options[:token], 'X')
|
|
41
|
-
|
|
42
|
-
res = http.request(req)
|
|
43
|
-
case res
|
|
44
|
-
when Net::HTTPSuccess
|
|
45
|
-
rooms = JSON.parse(res.body)
|
|
46
|
-
room = rooms['rooms'].select { |x| x['name'] == room }
|
|
47
|
-
rooms.empty? ? nil : room.first['id']
|
|
48
|
-
else
|
|
49
|
-
raise res.error!
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def speak(room, message)
|
|
54
|
-
room_id = find_room_id_by_name(room)
|
|
55
|
-
raise "No such room: #{room}." unless room_id
|
|
56
|
-
|
|
57
|
-
url = URI.parse("#{base_url}/room/#{room_id}/speak.json")
|
|
58
|
-
|
|
59
|
-
http = Net::HTTP.new(url.host, url.port)
|
|
60
|
-
http.use_ssl = true if @options[:ssl]
|
|
61
|
-
|
|
62
|
-
req = Net::HTTP::Post.new(url.path)
|
|
63
|
-
req.basic_auth(@options[:token], 'X')
|
|
64
|
-
req.set_content_type('application/json')
|
|
65
|
-
req.body = { 'message' => { 'body' => message } }.to_json
|
|
66
|
-
|
|
67
|
-
res = http.request(req)
|
|
68
|
-
case res
|
|
69
|
-
when Net::HTTPSuccess
|
|
70
|
-
true
|
|
71
|
-
else
|
|
72
|
-
raise res.error!
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
module God
|
|
79
|
-
module Contacts
|
|
80
|
-
class Campfire < Contact
|
|
81
|
-
class << self
|
|
82
|
-
attr_accessor :subdomain, :token, :room, :ssl, :format
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
self.ssl = false
|
|
86
|
-
|
|
87
|
-
self.format = lambda do |message, time, _priority, _category, host|
|
|
88
|
-
"[#{time.strftime('%H:%M:%S')}] #{host} - #{message}"
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
attr_accessor :subdomain, :token, :room, :ssl
|
|
92
|
-
|
|
93
|
-
def valid?
|
|
94
|
-
valid = true
|
|
95
|
-
valid &= complain("Attribute 'subdomain' must be specified", self) unless arg(:subdomain)
|
|
96
|
-
valid &= complain("Attribute 'token' must be specified", self) unless arg(:token)
|
|
97
|
-
valid &= complain("Attribute 'room' must be specified", self) unless arg(:room)
|
|
98
|
-
valid
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def notify(message, time, priority, category, host)
|
|
102
|
-
body = Campfire.format.call(message, time, priority, category, host)
|
|
103
|
-
|
|
104
|
-
conn = Marshmallow::Connection.new(
|
|
105
|
-
subdomain: arg(:subdomain),
|
|
106
|
-
token: arg(:token),
|
|
107
|
-
ssl: arg(:ssl)
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
conn.speak(arg(:room), body)
|
|
111
|
-
|
|
112
|
-
self.info = "notified campfire: #{arg(:subdomain)}"
|
|
113
|
-
rescue Object => e
|
|
114
|
-
applog(nil, :info, "failed to notify campfire: #{e.message}")
|
|
115
|
-
applog(nil, :debug, e.backtrace.join("\n"))
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
end
|
|
119
|
-
end
|
data/lib/god/contacts/prowl.rb
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
# Send a notice to Prowl (http://prowl.weks.net/).
|
|
2
|
-
#
|
|
3
|
-
# apikey - The String API key.
|
|
4
|
-
|
|
5
|
-
CONTACT_DEPS[:prowl] = ['prowly']
|
|
6
|
-
CONTACT_DEPS[:prowl].each do |d|
|
|
7
|
-
require d
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
module God
|
|
11
|
-
module Contacts
|
|
12
|
-
class Prowl < Contact
|
|
13
|
-
class << self
|
|
14
|
-
attr_accessor :apikey
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def valid?
|
|
18
|
-
valid = true
|
|
19
|
-
valid &= complain("Attribute 'apikey' must be specified", self) if apikey.nil?
|
|
20
|
-
valid
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
attr_accessor :apikey
|
|
24
|
-
|
|
25
|
-
def notify(message, time, priority, category, host)
|
|
26
|
-
result = Prowly.notify do |n|
|
|
27
|
-
n.apikey = arg(:apikey)
|
|
28
|
-
n.priority = map_priority(priority.to_i)
|
|
29
|
-
n.application = category || 'God'
|
|
30
|
-
n.event = "on #{host}"
|
|
31
|
-
n.description = "#{message} at #{time}"
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
self.info = if result.succeeded?
|
|
35
|
-
"sent prowl notification to #{name}"
|
|
36
|
-
else
|
|
37
|
-
"failed to send prowl notification to #{name}: #{result.message}"
|
|
38
|
-
end
|
|
39
|
-
rescue Object => e
|
|
40
|
-
applog(nil, :info, "failed to send prowl notification to #{name}: #{e.message}")
|
|
41
|
-
applog(nil, :debug, e.backtrace.join("\n"))
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def map_priority(priority)
|
|
45
|
-
case priority
|
|
46
|
-
when 1 then Prowly::Notification::Priority::EMERGENCY
|
|
47
|
-
when 2 then Prowly::Notification::Priority::HIGH
|
|
48
|
-
when 3 then Prowly::Notification::Priority::NORMAL
|
|
49
|
-
when 4 then Prowly::Notification::Priority::MODERATE
|
|
50
|
-
when 5 then Prowly::Notification::Priority::VERY_LOW
|
|
51
|
-
else Prowly::Notification::Priority::NORMAL
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
data/lib/god/contacts/scout.rb
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
# Send a notice to Scout (http://scoutapp.com/).
|
|
2
|
-
#
|
|
3
|
-
# client_key - The String client key.
|
|
4
|
-
# plugin_id - The String plugin id.
|
|
5
|
-
|
|
6
|
-
require 'net/http'
|
|
7
|
-
require 'uri'
|
|
8
|
-
|
|
9
|
-
module God
|
|
10
|
-
module Contacts
|
|
11
|
-
class Scout < Contact
|
|
12
|
-
class << self
|
|
13
|
-
attr_accessor :client_key, :plugin_id, :format
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
self.format = lambda do |message, priority, category, host|
|
|
17
|
-
text = "Message: #{message}\n"
|
|
18
|
-
text += "Host: #{host}\n" if host
|
|
19
|
-
text += "Priority: #{priority}\n" if priority
|
|
20
|
-
text += "Category: #{category}\n" if category
|
|
21
|
-
return text
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
attr_accessor :client_key, :plugin_id
|
|
25
|
-
|
|
26
|
-
def valid?
|
|
27
|
-
valid = true
|
|
28
|
-
valid &= complain("Attribute 'client_key' must be specified", self) unless arg(:client_key)
|
|
29
|
-
valid &= complain("Attribute 'plugin_id' must be specified", self) unless arg(:plugin_id)
|
|
30
|
-
valid
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def notify(message, _time, priority, category, host)
|
|
34
|
-
data = {
|
|
35
|
-
:client_key => arg(:client_key),
|
|
36
|
-
:plugin_id => arg(:plugin_id),
|
|
37
|
-
:format => 'xml',
|
|
38
|
-
'alert[subject]' => message,
|
|
39
|
-
'alert[body]' => Scout.format.call(message, priority, category, host)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
uri = URI.parse('http://scoutapp.com/alerts/create')
|
|
43
|
-
Net::HTTP.post_form(uri, data)
|
|
44
|
-
|
|
45
|
-
self.info = "sent scout alert to plugin ##{plugin_id}"
|
|
46
|
-
rescue => e
|
|
47
|
-
applog(nil, :info, "failed to send scout alert to plugin ##{plugin_id}: #{e.message}")
|
|
48
|
-
applog(nil, :debug, e.backtrace.join("\n"))
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
data/lib/god/contacts/sensu.rb
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
2
|
-
# Send a notice to a SENSU client socket, port 3030 on 'localhost' only.
|
|
3
|
-
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
4
|
-
# [mandatory]
|
|
5
|
-
# check_name - a unique check name
|
|
6
|
-
#
|
|
7
|
-
# [optional]
|
|
8
|
-
# status_code - status codes used are 0 for OK, 1 for WARNING, 2 for CRITICAL, and 3 or greater to indicate UNKNOWN or CUSTOM.
|
|
9
|
-
# handler - default handler
|
|
10
|
-
#
|
|
11
|
-
|
|
12
|
-
CONTACT_DEPS[:sensu] = ['json']
|
|
13
|
-
CONTACT_DEPS[:sensu].each do |d|
|
|
14
|
-
require d
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
module God
|
|
18
|
-
module Contacts
|
|
19
|
-
class Sensu < Contact
|
|
20
|
-
class << self
|
|
21
|
-
attr_accessor :check_name, :status_code, :handler, :host, :port
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
self.status_code = 2
|
|
25
|
-
self.handler = 'default'
|
|
26
|
-
self.host = 'localhost'
|
|
27
|
-
self.port = 3030
|
|
28
|
-
|
|
29
|
-
def valid?
|
|
30
|
-
valid = true
|
|
31
|
-
valid &= complain("Attribute 'check_name' must be specified", self) unless arg(:check_name)
|
|
32
|
-
valid
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
attr_accessor :check_name, :status_code, :handler, :host, :port
|
|
36
|
-
|
|
37
|
-
def sensu_client_socket(msg)
|
|
38
|
-
u = UDPSocket.new
|
|
39
|
-
u.send("#{msg}\n", 0, arg(:host).nil? ? host : arg(:host), arg(:port).nil? ? port : arg(:port))
|
|
40
|
-
u.close
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def notify(message, time, priority, category, host)
|
|
44
|
-
data = {
|
|
45
|
-
category: category,
|
|
46
|
-
message: message,
|
|
47
|
-
priority: priority,
|
|
48
|
-
host: host,
|
|
49
|
-
time: time
|
|
50
|
-
}
|
|
51
|
-
parcel = {
|
|
52
|
-
'name' => arg(:check_name),
|
|
53
|
-
'status' => arg(:status_code).nil? ? status_code : arg(:status_code),
|
|
54
|
-
'output' => data.to_json,
|
|
55
|
-
'handler' => arg(:handler).empty? ? handler : arg(:handler),
|
|
56
|
-
'executed' => Time.now.to_i
|
|
57
|
-
}
|
|
58
|
-
sensu_client_socket parcel.to_json
|
|
59
|
-
self.info = "notified sensu: #{arg(:check_name)}"
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
end
|
data/lib/god/contacts/statsd.rb
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Send a notice to statsd
|
|
4
|
-
#
|
|
5
|
-
# host - statsd host
|
|
6
|
-
# port - statsd port (optional)
|
|
7
|
-
|
|
8
|
-
require 'statsd-ruby'
|
|
9
|
-
|
|
10
|
-
module God
|
|
11
|
-
module Contacts
|
|
12
|
-
class Statsd < Contact
|
|
13
|
-
class << self
|
|
14
|
-
attr_accessor :host, :port
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
attr_accessor :host, :port
|
|
18
|
-
|
|
19
|
-
def valid?
|
|
20
|
-
valid = true
|
|
21
|
-
valid &= complain("Attribute 'statsd_host' must be specified", self) unless arg(:host)
|
|
22
|
-
valid
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def notify(message, _time, _priority, _category, hostname)
|
|
26
|
-
statsd = ::Statsd.new host, (port ? port.to_i : 8125) # 8125 is the default statsd port
|
|
27
|
-
|
|
28
|
-
hostname = hostname.tr('.', '_')
|
|
29
|
-
app = message.gsub(/([^\s]*).*/, '\1')
|
|
30
|
-
|
|
31
|
-
[
|
|
32
|
-
'cpu out of bounds',
|
|
33
|
-
'memory out of bounds',
|
|
34
|
-
'process is flapping'
|
|
35
|
-
].each do |event_type|
|
|
36
|
-
statsd.increment "god.#{event_type.gsub(/\s/, '_')}.#{hostname}.#{app}" if message.include? event_type
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
self.info = 'sent statsd alert'
|
|
40
|
-
rescue => e
|
|
41
|
-
applog(nil, :info, "failed to send statsd alert: #{e.message}")
|
|
42
|
-
applog(nil, :debug, e.backtrace.join("\n"))
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
data/lib/god/contacts/twitter.rb
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
# Send a notice to a Twitter account (http://twitter.com/).
|
|
2
|
-
#
|
|
3
|
-
# consumer_token - The String OAuth consumer token (defaults to God's
|
|
4
|
-
# existing consumer token).
|
|
5
|
-
# consumer_secret - The String OAuth consumer secret (defaults to God's
|
|
6
|
-
# existing consumer secret).
|
|
7
|
-
# access_token - The String OAuth access token.
|
|
8
|
-
# access_secret - The String OAuth access secret.
|
|
9
|
-
|
|
10
|
-
CONTACT_DEPS[:twitter] = ['twitter']
|
|
11
|
-
CONTACT_DEPS[:twitter].each do |d|
|
|
12
|
-
require d
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
module God
|
|
16
|
-
module Contacts
|
|
17
|
-
class Twitter < Contact
|
|
18
|
-
class << self
|
|
19
|
-
attr_accessor :consumer_token, :consumer_secret,
|
|
20
|
-
:access_token, :access_secret
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
self.consumer_token = 'gOhjax6s0L3mLeaTtBWPw'
|
|
24
|
-
self.consumer_secret = 'yz4gpAVXJHKxvsGK85tEyzQJ7o2FEy27H1KEWL75jfA'
|
|
25
|
-
|
|
26
|
-
def valid?
|
|
27
|
-
valid = true
|
|
28
|
-
valid &= complain("Attribute 'consumer_token' must be specified", self) unless arg(:consumer_token)
|
|
29
|
-
valid &= complain("Attribute 'consumer_secret' must be specified", self) unless arg(:consumer_secret)
|
|
30
|
-
valid &= complain("Attribute 'access_token' must be specified", self) unless arg(:access_token)
|
|
31
|
-
valid &= complain("Attribute 'access_secret' must be specified", self) unless arg(:access_secret)
|
|
32
|
-
valid
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
attr_accessor :consumer_token, :consumer_secret,
|
|
36
|
-
:access_token, :access_secret
|
|
37
|
-
|
|
38
|
-
def notify(message, _time, _priority, _category, _host)
|
|
39
|
-
oauth = ::Twitter::OAuth.new(arg(:consumer_token), arg(:consumer_secret))
|
|
40
|
-
oauth.authorize_from_access(arg(:access_token), arg(:access_secret))
|
|
41
|
-
|
|
42
|
-
::Twitter::Base.new(oauth).update(message)
|
|
43
|
-
|
|
44
|
-
self.info = 'sent twitter update'
|
|
45
|
-
rescue => e
|
|
46
|
-
applog(nil, :info, "failed to send twitter update: #{e.message}")
|
|
47
|
-
applog(nil, :debug, e.backtrace.join("\n"))
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
end
|