qnotifier 0.6.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/Manifest +21 -0
- data/Rakefile +15 -0
- data/bin/qnotifier +6 -0
- data/config/qnotifier_config.yml +112 -0
- data/gem-public_cert.pem +20 -0
- data/lib/command.rb +59 -0
- data/lib/plugin.rb +122 -0
- data/lib/qnotifier.rb +190 -0
- data/lib/storage.rb +50 -0
- data/lib/web_service.rb +132 -0
- data/plugins/apache.rb +13 -0
- data/plugins/iostat.rb +13 -0
- data/plugins/mysql.rb +13 -0
- data/plugins/network.rb +13 -0
- data/plugins/nginx.rb +13 -0
- data/plugins/passenger.rb +13 -0
- data/plugins/processes.rb +13 -0
- data/plugins/rails.rb +48 -0
- data/plugins/ruby.rb +27 -0
- data/plugins/system.rb +158 -0
- data/plugins/urls.rb +13 -0
- data/qnotifier.gemspec +53 -0
- data.tar.gz.sig +0 -0
- metadata +164 -0
- metadata.gz.sig +0 -0
data/Manifest
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Manifest
|
2
|
+
Rakefile
|
3
|
+
bin/qnotifier
|
4
|
+
config/qnotifier_config.yml
|
5
|
+
gem-public_cert.pem
|
6
|
+
lib/command.rb
|
7
|
+
lib/plugin.rb
|
8
|
+
lib/qnotifier.rb
|
9
|
+
lib/storage.rb
|
10
|
+
lib/web_service.rb
|
11
|
+
plugins/apache.rb
|
12
|
+
plugins/iostat.rb
|
13
|
+
plugins/mysql.rb
|
14
|
+
plugins/network.rb
|
15
|
+
plugins/nginx.rb
|
16
|
+
plugins/passenger.rb
|
17
|
+
plugins/processes.rb
|
18
|
+
plugins/rails.rb
|
19
|
+
plugins/ruby.rb
|
20
|
+
plugins/system.rb
|
21
|
+
plugins/urls.rb
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'echoe'
|
4
|
+
|
5
|
+
Echoe.new('qnotifier', '0.6.0') do |p|
|
6
|
+
p.description = "The server side agent for the QNotifier monitoring system"
|
7
|
+
p.url = "http://qnotifier.com/qnotifier_gem"
|
8
|
+
p.author = "Gersham Meharg"
|
9
|
+
p.email = "gersham@qnotifier.com"
|
10
|
+
p.ignore_pattern = ["var/*"]
|
11
|
+
p.runtime_dependencies = ["rest-client >=1.4.2", "json >=1.2.3", "elif >=0.1.0"]
|
12
|
+
p.development_dependencies = ["rest-client >=1.4.2", "json >=1.2.3", "elif >=0.1.0"]
|
13
|
+
p.executable_pattern = ["bin/*"]
|
14
|
+
p.install_message = "Qnotifier installed, please register by running 'qnotifier -r CODE' in order to register this server."
|
15
|
+
end
|
data/bin/qnotifier
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
# qnotifier_config.yml file
|
2
|
+
---
|
3
|
+
#
|
4
|
+
# This is the configuration file for the Qnotifier Agent
|
5
|
+
# It should live in /etc/qnotifier.config
|
6
|
+
#
|
7
|
+
# Note that this file is YML formatted, please respect the indents
|
8
|
+
#
|
9
|
+
|
10
|
+
#
|
11
|
+
# General Settings
|
12
|
+
#
|
13
|
+
|
14
|
+
# Whether to resend alerts
|
15
|
+
resend_alerts: true
|
16
|
+
# resend_alert_time: Resend alerts every X seconds
|
17
|
+
resend_alert_time: 1 #14400 # Four hours
|
18
|
+
|
19
|
+
# alert_email_address: if this is defined any alerts will be copied to this email address
|
20
|
+
# Note that is in addition to the Qnotifier notifications
|
21
|
+
#alert_email_address: user@domain.com
|
22
|
+
|
23
|
+
#
|
24
|
+
# PLUGINS
|
25
|
+
#
|
26
|
+
|
27
|
+
# Where to look for user generated plugins
|
28
|
+
# To add your own plugin subclass the Qnotifier::Plugin class and put this in to this directory
|
29
|
+
# You may add configuration parameters here based on the name of your plugin class
|
30
|
+
plugin_directory: "/var/qnotifier"
|
31
|
+
|
32
|
+
# The System Plugin must be enabled, this gives basic stats like load average, disk use, memory, etc
|
33
|
+
System:
|
34
|
+
# use_load: either one_minute, five_minute or fifteen_minutes
|
35
|
+
use_load: five_minute
|
36
|
+
# normalize_load: whether to divide the reported load by the number of CPUs in the system
|
37
|
+
normalize_load: true
|
38
|
+
# Alert if the CPU is above this percent usage, 0 disables
|
39
|
+
alert_cpu_threshold: 10
|
40
|
+
# Alert if the memory is above this percent usage, 0 disables
|
41
|
+
alert_memory_threshold: 10
|
42
|
+
# Alert if the memory is above this percent usage, 0 disables
|
43
|
+
alert_load_threshold: 1.0
|
44
|
+
# Alert if the memory is above this percent usage, 0 disables
|
45
|
+
alert_disk_threshold: 90
|
46
|
+
# Partitions which to monitor for free disk space
|
47
|
+
partitions:
|
48
|
+
- "/"
|
49
|
+
|
50
|
+
# The Apache built-in plugin
|
51
|
+
Apache:
|
52
|
+
# Enabled, set to either true or false
|
53
|
+
enabled: false
|
54
|
+
monitor_url: "http://localhost/foo"
|
55
|
+
username: "username"
|
56
|
+
password: "password"
|
57
|
+
|
58
|
+
# The IOStat built-in plugin
|
59
|
+
Iostat:
|
60
|
+
# Enabled, set to either true or false
|
61
|
+
enabled: false
|
62
|
+
|
63
|
+
# The MySQL built-in plugin
|
64
|
+
Mysql:
|
65
|
+
# Enabled, set to either true or false
|
66
|
+
enabled: false
|
67
|
+
username: "username"
|
68
|
+
password: "password"
|
69
|
+
|
70
|
+
# The Network Interface built-in plugin
|
71
|
+
Network:
|
72
|
+
# Enabled, set to either true or false
|
73
|
+
enabled: false
|
74
|
+
interfaces:
|
75
|
+
- eth0
|
76
|
+
|
77
|
+
# The Nginx built-in plugin
|
78
|
+
Nginx:
|
79
|
+
# Enabled, set to either true or false
|
80
|
+
enabled: false
|
81
|
+
username: "username"
|
82
|
+
password: "password"
|
83
|
+
|
84
|
+
# The Passenger Phusion built-in plugin
|
85
|
+
Passenger:
|
86
|
+
# Enabled, set to either true or false
|
87
|
+
enabled: false
|
88
|
+
|
89
|
+
# The Process List built-in plugin
|
90
|
+
Processes:
|
91
|
+
# Enabled, set to either true or false
|
92
|
+
enabled: false
|
93
|
+
|
94
|
+
# The Rails built-in plugin
|
95
|
+
Rails:
|
96
|
+
# Enabled, set to either true or false
|
97
|
+
enabled: false
|
98
|
+
log_file: "/var/www/rails/log/production.log"
|
99
|
+
|
100
|
+
# The Ruby built-in plugin
|
101
|
+
Ruby:
|
102
|
+
enabled: true
|
103
|
+
list_gems: true
|
104
|
+
|
105
|
+
#
|
106
|
+
# Other settings that you generally will not need to modify
|
107
|
+
#
|
108
|
+
|
109
|
+
# The API End Point in which to send our pings
|
110
|
+
#api_endpoint: "http://ping.qnotifier.com"
|
111
|
+
api_endpoint: "http://localhost:4567"
|
112
|
+
|
data/gem-public_cert.pem
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIDODCCAiCgAwIBAgIBADANBgkqhkiG9w0BAQUFADBCMRAwDgYDVQQDDAdnZXJz
|
3
|
+
aGFtMRkwFwYKCZImiZPyLGQBGRYJcW5vdGlmaWVyMRMwEQYKCZImiZPyLGQBGRYD
|
4
|
+
Y29tMB4XDTEwMDMxNzE4MjAwOFoXDTExMDMxNzE4MjAwOFowQjEQMA4GA1UEAwwH
|
5
|
+
Z2Vyc2hhbTEZMBcGCgmSJomT8ixkARkWCXFub3RpZmllcjETMBEGCgmSJomT8ixk
|
6
|
+
ARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMS8vIaSE0eA
|
7
|
+
DfL3OqRwmY+b3ueQ+cfm2nxU1J+TE7yFFGiv+bk4z4YMtHtbqsGxlmL4HZKW7Ur/
|
8
|
+
RrS7+d+fVTskoRC7t9g6mRoww/4+fTgmX25g7YLe4vuiSBkBeBMXBt5Vd3ombU9F
|
9
|
+
b0CrguX2a2ffYxnF/RlrXnhsU2VywZry+qz1NJglaCa+qb0S0W3BnvoB8T+MxNOM
|
10
|
+
7feKF/HvWRCM7DdHyqXqHFqMBIWJlCC7MFV4kQVW/a8b49VC5Dgmz6QVWcPqQ8cl
|
11
|
+
GK35UW+1WZXRB5Mhv5HBAQQqzLut46pxbUJ3qIpibtp1ltgyu81ZIRAwKIWx0YNv
|
12
|
+
lP5V85hTZ1ECAwEAAaM5MDcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUn3O2jt+12CmU
|
13
|
+
t1GEK8NZRNRbzqwwCwYDVR0PBAQDAgSwMA0GCSqGSIb3DQEBBQUAA4IBAQBb5gk8
|
14
|
+
OyfuloScbz/oHOopNmSc+o/s/5MvyrslPYDZA0WGR/63Q4Wl6l/tFFPwuAZH1KAI
|
15
|
+
MtLf7mVDdijHQf3Q6e+DicNRRQrl1w3s2m4PHyPiFUmXULzWHbMc3OK4LdM+1f5q
|
16
|
+
oZvsRrAAz6esBChxfdpuNCsP9Eu3j9MIWHy4KPTNuqOFyI+p3YVW2+SHeN4gBCyV
|
17
|
+
b7VZHIY+1kKjmMYXPeG9xlXaxLABhS1iN66tAyg66l6u6vuLt5Rdh1RUIY534Edq
|
18
|
+
ciUZJrPp/am/m0FtGWggbAohDKjiKRL0E6OCFQ7wSCTUPKoB9MbIJkKSGFo6ExWe
|
19
|
+
wu7A8rLN6CU0SfWf
|
20
|
+
-----END CERTIFICATE-----
|
data/lib/command.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "optparse"
|
3
|
+
require "qnotifier"
|
4
|
+
|
5
|
+
module Qnotifier
|
6
|
+
class Command
|
7
|
+
|
8
|
+
def self.parse_options(argv)
|
9
|
+
options = {}
|
10
|
+
|
11
|
+
op = OptionParser.new do |opts|
|
12
|
+
|
13
|
+
opts.banner = "\nQnotifier is an agent for the Qnotifer server reporting and alerting system"
|
14
|
+
opts.separator "See http://qnotifier.com for details."
|
15
|
+
opts.separator "\nUsage:"
|
16
|
+
|
17
|
+
opts.on("-r", "--register CODE", String, "Register agent with code.") do |register_code|
|
18
|
+
qnotifier = Qnotifier::Process.new
|
19
|
+
qnotifier.debug = true if @debug
|
20
|
+
qnotifier.register(register_code)
|
21
|
+
exit
|
22
|
+
end
|
23
|
+
opts.on("-v", "--version", "Displays the agent version") do |version|
|
24
|
+
puts "Qnotifier Agent Version: #{Qnotifier::VERSION}"
|
25
|
+
exit
|
26
|
+
end
|
27
|
+
opts.on("-d", "--debug", "Run in debug mode") do |debug|
|
28
|
+
@debug = true
|
29
|
+
end
|
30
|
+
opts.on("-h", "--help", "Shows this help") do
|
31
|
+
puts opts
|
32
|
+
exit
|
33
|
+
end
|
34
|
+
opts.separator "\n"
|
35
|
+
end
|
36
|
+
|
37
|
+
begin
|
38
|
+
op.parse!(argv)
|
39
|
+
@usage = op.to_s
|
40
|
+
rescue OptionParser::InvalidOption
|
41
|
+
puts op
|
42
|
+
exit
|
43
|
+
rescue OptionParser::MissingArgument
|
44
|
+
puts op
|
45
|
+
exit
|
46
|
+
end
|
47
|
+
options
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.run(argv)
|
51
|
+
argv.push("--help") if argv.first == 'help'
|
52
|
+
options = parse_options(argv)
|
53
|
+
qnotifier = Qnotifier::Process.new
|
54
|
+
qnotifier.debug = true if @debug
|
55
|
+
qnotifier.run
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
data/lib/plugin.rb
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "storage"
|
3
|
+
|
4
|
+
# Subclass this to create a new plugin
|
5
|
+
# Note that plugins only get 30 seconds to run and do their thing
|
6
|
+
module Qnotifier
|
7
|
+
class Plugin
|
8
|
+
|
9
|
+
attr_accessor :reports
|
10
|
+
attr_accessor :alerts
|
11
|
+
attr_accessor :stats
|
12
|
+
attr_accessor :config
|
13
|
+
attr_accessor :alert_count
|
14
|
+
|
15
|
+
# The run method, do not override
|
16
|
+
def run
|
17
|
+
@class_name = self.class.to_s.split("::").last
|
18
|
+
@alert_count = 0
|
19
|
+
|
20
|
+
# Read the options from the global config and mix them in to the defaults for this plugin
|
21
|
+
if @config[@class_name]
|
22
|
+
@options = @defaults.update(@config[@class_name])
|
23
|
+
else
|
24
|
+
@options = @defaults
|
25
|
+
end
|
26
|
+
|
27
|
+
# Only run this plugin if it's enabled
|
28
|
+
return unless @options["enabled"]
|
29
|
+
|
30
|
+
Qnotifier.log.debug("Plugin #{@class_name} running")
|
31
|
+
main
|
32
|
+
end
|
33
|
+
|
34
|
+
# You'll need to override this in your subclass
|
35
|
+
def main
|
36
|
+
Qnotifier.log.error("You must implement the main method in the plugin: #{self.class.name}")
|
37
|
+
end
|
38
|
+
|
39
|
+
# Log something to console
|
40
|
+
# Log levels: log.info, log.warn, log.error, log.fatal, log.unknown
|
41
|
+
def log
|
42
|
+
return Qnotifier.log
|
43
|
+
end
|
44
|
+
|
45
|
+
# Alert is an alert to the adminstrators that something requires looking at
|
46
|
+
# Severity should usually be 3
|
47
|
+
def alert(name, message, severity = 3)
|
48
|
+
@alerts = {@class_name => []} unless @alerts
|
49
|
+
@alert_count += 1
|
50
|
+
# Only send the alert if we haven't already
|
51
|
+
if Qnotifier::Storage.get("AlertTime_#{@class_name}-#{name}")
|
52
|
+
# Check to see if we need to resend the alert
|
53
|
+
if @config["resend_alerts"] and Qnotifier::Storage.get("AlertTime_#{@class_name}-#{name}") < Time.now - @config["resend_alert_time"]
|
54
|
+
add_alert(name, message, severity)
|
55
|
+
else
|
56
|
+
Qnotifier.log.debug("Already sent alert: #{message}")
|
57
|
+
end
|
58
|
+
else
|
59
|
+
add_alert(name, message, severity)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Add the alert to the outbound queue
|
64
|
+
def add_alert(name, message, severity)
|
65
|
+
|
66
|
+
if severity == 1 # emergency
|
67
|
+
log.fatal message
|
68
|
+
elsif severity == 2 # critical
|
69
|
+
log.error message
|
70
|
+
elsif severity == 3 # alert
|
71
|
+
log.error message
|
72
|
+
elsif severity == 4 # error
|
73
|
+
log.error message
|
74
|
+
elsif severity == 5 # warn
|
75
|
+
log.warn message
|
76
|
+
elsif severity == 6 # clear
|
77
|
+
log.info message
|
78
|
+
end
|
79
|
+
data = [name, message, severity]
|
80
|
+
@alerts[@class_name].push(data)
|
81
|
+
Qnotifier::Storage.put("AlertTime_#{@class_name}-#{name}", Time.now)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Alert is no longer needed as the value has crossed back over the threshold value
|
85
|
+
def reset_alert(name, message)
|
86
|
+
@alerts = {@class_name => []} unless @alerts
|
87
|
+
if Qnotifier::Storage.get("AlertTime_#{@class_name}-#{name}")
|
88
|
+
log.warn message
|
89
|
+
Qnotifier::Storage.delete("AlertTime_#{@class_name}-#{name}")
|
90
|
+
data = [name, message, 6] # Clear
|
91
|
+
@alerts[@class_name].push(data)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Report is an ongoing data point for graphing and realtime reporting for this server
|
96
|
+
def report(key, value)
|
97
|
+
@reports = {@class_name => []} unless @reports
|
98
|
+
@reports[@class_name].push([key, value])
|
99
|
+
end
|
100
|
+
|
101
|
+
# Stat is a one time statistic about this server, it doesn't get tracked and graphed
|
102
|
+
def stat(key, value)
|
103
|
+
@stats = {@class_name => {}} unless @stats
|
104
|
+
@stats[@class_name].merge!(key => value.to_s)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Store this value for later retrieval
|
108
|
+
def put(key, value)
|
109
|
+
Qnotifier::Storage.put(key, value)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Retrieve this value
|
113
|
+
def get(key)
|
114
|
+
Qnotifier::Storage.get(key)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Delete the value
|
118
|
+
def delete(key)
|
119
|
+
Qnotifier::Storage.delete(key)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
data/lib/qnotifier.rb
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "yaml"
|
3
|
+
require "timeout"
|
4
|
+
require "logger"
|
5
|
+
require "plugin"
|
6
|
+
require "web_service"
|
7
|
+
require "storage"
|
8
|
+
|
9
|
+
module Qnotifier
|
10
|
+
VERSION = "0.7.0".freeze
|
11
|
+
|
12
|
+
def self.log
|
13
|
+
unless @logger
|
14
|
+
begin
|
15
|
+
@logger = Logger.new("/var/log/qnotifier.log","monthly")
|
16
|
+
rescue Exception => e
|
17
|
+
puts "Error starting logging - using stdout (#{e.message})"
|
18
|
+
@logger = Logger.new($stdout)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
return @logger
|
22
|
+
end
|
23
|
+
|
24
|
+
class Process
|
25
|
+
|
26
|
+
attr_accessor :debug
|
27
|
+
|
28
|
+
def initialize
|
29
|
+
Qnotifier::Storage.restore
|
30
|
+
|
31
|
+
@alerts = {}
|
32
|
+
@reports = {}
|
33
|
+
@stats = {}
|
34
|
+
@alert_count = 0
|
35
|
+
end
|
36
|
+
|
37
|
+
def start_logging
|
38
|
+
# Logging
|
39
|
+
if @debug
|
40
|
+
puts "Starting in debug mode"
|
41
|
+
Qnotifier.log.level = Logger::DEBUG
|
42
|
+
else
|
43
|
+
Qnotifier.log.level = Logger::INFO
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def run
|
48
|
+
start_logging
|
49
|
+
load_config
|
50
|
+
|
51
|
+
last_run = Qnotifier::Storage.get("last_run")
|
52
|
+
|
53
|
+
if Qnotifier::Storage.get("server_disabled_pings")
|
54
|
+
Qnotifier.log.fatal "Disabled by the Qnotifer API, please re-register (qnotifier --register key) this agent to enable. Exiting."
|
55
|
+
exit
|
56
|
+
end
|
57
|
+
|
58
|
+
# Start up
|
59
|
+
Qnotifier.log.info "Running#{", last run: #{last_run}" if last_run}"
|
60
|
+
Qnotifier::Storage.put("last_run", Time.now) unless @debug
|
61
|
+
unless @debug
|
62
|
+
if last_run and (Time.now - last_run) < 120
|
63
|
+
message = "Starting too frequently, please run every 5 minutes (use debug mode to override)\nLast start up: #{last_run}"
|
64
|
+
puts message
|
65
|
+
Qnotifier.log.fatal message
|
66
|
+
exit
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
unless @config["api_key"]
|
71
|
+
error_message = "Missing API Key, please register this agent first."
|
72
|
+
puts error_message
|
73
|
+
Qnotifier.log.fatal error_message
|
74
|
+
exit
|
75
|
+
end
|
76
|
+
|
77
|
+
# Load the built in plugins
|
78
|
+
Dir[File.dirname(__FILE__) + '/../plugins/*.rb'].each do |file|
|
79
|
+
process_plugin_file(file)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Load the user plugins
|
83
|
+
Dir[@config["plugin_directory"] + '/*.rb'].each do |file|
|
84
|
+
process_plugin_file(file)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Send the alerts, reports and stats to the API
|
88
|
+
webservice = Qnotifier::WebService.new
|
89
|
+
webservice.config = @config
|
90
|
+
webservice.send_alerts(@alerts)
|
91
|
+
webservice.send_reports_stats(@reports, @stats, @alert_count)
|
92
|
+
|
93
|
+
Qnotifier::Storage.save
|
94
|
+
|
95
|
+
# Done, clean up and save
|
96
|
+
Qnotifier::Storage.save
|
97
|
+
end
|
98
|
+
|
99
|
+
def process_plugin_file(file)
|
100
|
+
return unless file =~ /\.rb/
|
101
|
+
require file
|
102
|
+
class_name = "Qnotifier::#{File.basename(file, ".rb").split(/[^a-z0-9]/i).map{|w| w.capitalize}.join}"
|
103
|
+
begin
|
104
|
+
plugin = eval(class_name).new
|
105
|
+
rescue
|
106
|
+
Qnotifier.log.error "Couldn't process the plugin file #{file}"
|
107
|
+
return
|
108
|
+
end
|
109
|
+
plugin.config = @config
|
110
|
+
unless plugin.class.superclass.name == "Qnotifier::Plugin"
|
111
|
+
Qnotifier.log.fatal "Attempted to load a non Qnotifier::Plugin plugin subclass at #{file} - make sure this directory only includes Qnotifier::Plugin subclasses"
|
112
|
+
return
|
113
|
+
end
|
114
|
+
begin
|
115
|
+
Timeout.timeout 30 do
|
116
|
+
plugin.run
|
117
|
+
end
|
118
|
+
rescue RuntimeError => e
|
119
|
+
Qnotifier.log.error "#{class_name} Plugin Error: #{e.message}"
|
120
|
+
rescue Errno::ENOENT => e
|
121
|
+
Qnotifier.log.error "#{class_name} Plugin Error: #{e.message}"
|
122
|
+
end
|
123
|
+
@alerts.merge!(plugin.alerts) if plugin.alerts
|
124
|
+
@reports.merge!(plugin.reports) if plugin.reports
|
125
|
+
@stats.merge!(plugin.stats) if plugin.stats
|
126
|
+
@alert_count += plugin.alert_count
|
127
|
+
end
|
128
|
+
|
129
|
+
def register(code)
|
130
|
+
|
131
|
+
start_logging
|
132
|
+
load_config
|
133
|
+
|
134
|
+
if @config["api_key"]
|
135
|
+
Qnotifier.log.error "Server already registered. You should not keep registering the server, you only need to do this once."
|
136
|
+
end
|
137
|
+
|
138
|
+
webservice = Qnotifier::WebService.new
|
139
|
+
webservice.config = @config
|
140
|
+
api_key = webservice.register_server(code)
|
141
|
+
|
142
|
+
save_api_key(api_key)
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
def save_api_key(api_key)
|
147
|
+
return unless api_key
|
148
|
+
@config["api_key"] = api_key
|
149
|
+
begin
|
150
|
+
File.open(File.dirname(__FILE__) + "/../var/api_key", 'w') {|f| f.write(api_key) }
|
151
|
+
rescue Exception => e
|
152
|
+
Qnotifier.log.fatal "Can't save API Key #{e.message}"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def load_config
|
157
|
+
|
158
|
+
# Make the var dir if it doesn't exist
|
159
|
+
var_dir = File.dirname(__FILE__) + "/../var"
|
160
|
+
FileUtils.mkdir_p var_dir
|
161
|
+
|
162
|
+
# Load from /etc/qnotifier_config.yml if the file is there
|
163
|
+
begin
|
164
|
+
@config = YAML::load(File.open('/etc/qnotifier_config.yml'))
|
165
|
+
rescue Exception => e
|
166
|
+
Qnotifier.log.error "Can't open /etc/qnotifier_config.yml (loading default config and copying it to /etc/qnotifier_config.yml)"
|
167
|
+
begin
|
168
|
+
default_config_file = File.dirname(__FILE__) + "/../config/qnotifier_config.yml"
|
169
|
+
@config = YAML::load(File.open(default_config_file))
|
170
|
+
`cp #{default_config_file} /etc/qnotifier_config.yml`
|
171
|
+
rescue Exception => e
|
172
|
+
Qnotifier.log.fatal "Can't open default config #{e.message}"
|
173
|
+
exit
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
unless @config["api_key"]
|
178
|
+
begin
|
179
|
+
api_key_file = File.open(File.dirname(__FILE__) + "/../var/api_key")
|
180
|
+
while (line = api_key_file.readline)
|
181
|
+
@config["api_key"] = line
|
182
|
+
end
|
183
|
+
rescue EOFError
|
184
|
+
rescue Exception => e
|
185
|
+
Qnotifier.log.debug "Can't get API key, have you registered?"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
data/lib/storage.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env
|
2
|
+
require "yaml"
|
3
|
+
|
4
|
+
module Qnotifier
|
5
|
+
class Storage
|
6
|
+
|
7
|
+
@@stored_variables = {}
|
8
|
+
@@restored = false
|
9
|
+
|
10
|
+
def self.restore
|
11
|
+
begin
|
12
|
+
saved_variables = File.dirname(__FILE__) + "/../var/saved_variables.yml"
|
13
|
+
@@stored_variables = YAML::load(File.open(saved_variables))
|
14
|
+
rescue Exception => e
|
15
|
+
Qnotifier.log.debug "Error loading stored variables file. #{e.message}"
|
16
|
+
end
|
17
|
+
@@restored = true
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.get(key)
|
21
|
+
restore unless @@restored
|
22
|
+
if @@stored_variables[key]
|
23
|
+
return @@stored_variables[key]
|
24
|
+
else
|
25
|
+
return nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.put(key, value)
|
30
|
+
restore unless @@restored
|
31
|
+
@@stored_variables[key] = value
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.delete(key)
|
35
|
+
restore unless @@restored
|
36
|
+
@@stored_variables.delete(key)
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.save
|
40
|
+
begin
|
41
|
+
saved_variables = File.dirname(__FILE__) + "/../var/saved_variables.yml"
|
42
|
+
File.open(saved_variables, "w") do |f|
|
43
|
+
f.write(YAML::dump(@@stored_variables))
|
44
|
+
end
|
45
|
+
rescue Exception => e
|
46
|
+
Qnotifier.log.error "Error saving stored variables file. #{e.message}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/web_service.rb
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rest_client'
|
3
|
+
require 'json'
|
4
|
+
require "storage"
|
5
|
+
|
6
|
+
module Qnotifier
|
7
|
+
class WebService
|
8
|
+
|
9
|
+
attr_accessor :config
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
|
13
|
+
RestClient.proxy = ENV['http_proxy']
|
14
|
+
end
|
15
|
+
|
16
|
+
def send_alerts(alerts)
|
17
|
+
|
18
|
+
return if alerts.empty?
|
19
|
+
Qnotifier.log.debug "Sending #{alerts.count} alerts"
|
20
|
+
|
21
|
+
# Hostname
|
22
|
+
unless @config["hostname"]
|
23
|
+
@hostname = `hostname`.strip
|
24
|
+
else
|
25
|
+
@hostname = @config["hostname"]
|
26
|
+
end
|
27
|
+
|
28
|
+
message = {"api_key" => @config["api_key"],
|
29
|
+
"api_version" => "1.0",
|
30
|
+
"agent_version" => Qnotifier::VERSION,
|
31
|
+
"hostname" => @hostname,
|
32
|
+
"alerts" => alerts}.to_json
|
33
|
+
|
34
|
+
begin
|
35
|
+
resource = RestClient::Resource.new(@config["api_endpoint"],
|
36
|
+
:timeout => 30,
|
37
|
+
:headers => { :user_agent => "Qnotifier-#{Qnotifier::VERSION}" })
|
38
|
+
response = resource["/send_alert"].post(message, :content_type => 'application/json')
|
39
|
+
|
40
|
+
if response.code == 200
|
41
|
+
Qnotifier.log.debug "Server Response: HTTP #{response.code} #{response.body}"
|
42
|
+
else
|
43
|
+
Qnotifier.log.warn "Server Response: HTTP #{response.code} #{response.body}"
|
44
|
+
end
|
45
|
+
|
46
|
+
rescue Exception => e
|
47
|
+
Qnotifier.log.error "Sending Alerts: Can't connect to #{@config["api_endpoint"]} - #{e.message}"
|
48
|
+
if e.message == "HTTP status code 402"
|
49
|
+
# The server doesn't want to hear from us any more, disable pinging
|
50
|
+
Qnotifier::Storage.put("server_disabled_pings", Time.now)
|
51
|
+
Qnotifier.log.error "Server has asked us to disable pings"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def send_reports_stats(reports, stats, alert_count)
|
57
|
+
|
58
|
+
return if reports.empty? and stats.empty?
|
59
|
+
Qnotifier.log.debug "Sending Reports and Stats"
|
60
|
+
|
61
|
+
# Hostname
|
62
|
+
unless @config["hostname"]
|
63
|
+
@hostname = `hostname`.strip
|
64
|
+
else
|
65
|
+
@hostname = @config["hostname"]
|
66
|
+
end
|
67
|
+
|
68
|
+
message = {"api_key" => @config["api_key"],
|
69
|
+
"api_version" => "1.0",
|
70
|
+
"agent_version" => Qnotifier::VERSION,
|
71
|
+
"hostname" => @hostname,
|
72
|
+
"stats" => stats,
|
73
|
+
"alert_count" => alert_count,
|
74
|
+
"reports" => reports}.to_json
|
75
|
+
|
76
|
+
begin
|
77
|
+
resource = RestClient::Resource.new(@config["api_endpoint"],
|
78
|
+
:timeout => 30,
|
79
|
+
:headers => { :user_agent => "Qnotifier-#{Qnotifier::VERSION}" })
|
80
|
+
response = resource["/update_server"].post(message, :content_type => 'application/json')
|
81
|
+
|
82
|
+
if response.code == 200
|
83
|
+
Qnotifier.log.debug "Server Response: HTTP #{response.code} #{response.body}"
|
84
|
+
else
|
85
|
+
Qnotifier.log.warn "Server Response: HTTP #{response.code} #{response.body}"
|
86
|
+
end
|
87
|
+
|
88
|
+
rescue Exception => e
|
89
|
+
Qnotifier.log.error "Sending Reports/Stats: Can't connect to #{@config["api_endpoint"]} - #{e.message}"
|
90
|
+
if e.message == "HTTP status code 402"
|
91
|
+
# The server doesn't want to hear from us any more, disable pinging
|
92
|
+
Qnotifier::Storage.put("server_disabled_pings", Time.now)
|
93
|
+
Qnotifier.log.error "Server has asked us to disable pings"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def register_server(temp_key)
|
99
|
+
return if temp_key.empty?
|
100
|
+
Qnotifier.log.info "Registering Server"
|
101
|
+
|
102
|
+
message = {"temp_key" => temp_key, "hostname" => `hostname`.strip}.to_json
|
103
|
+
|
104
|
+
begin
|
105
|
+
resource = RestClient::Resource.new(@config["api_endpoint"],
|
106
|
+
:timeout => 30,
|
107
|
+
:headers => { :user_agent => "Qnotifier-#{Qnotifier::VERSION}" })
|
108
|
+
response = resource["/register_server"].post(message, :content_type => 'application/json')
|
109
|
+
|
110
|
+
if response.code == 200 and response.body
|
111
|
+
Qnotifier.log.debug "Registration Request Response: HTTP #{response.code} #{response.body}"
|
112
|
+
puts "OK, the server has been successfully registered."
|
113
|
+
puts "You now need to call this script from cron every 5 minutes, add to root's crontab (sudo crontab -e):"
|
114
|
+
puts "*/5 * * * * qnotifier"
|
115
|
+
return response.body
|
116
|
+
else
|
117
|
+
Qnotifier.log.warn "Registration Request Response: HTTP #{response.code} #{response.body}"
|
118
|
+
end
|
119
|
+
|
120
|
+
rescue Exception => e
|
121
|
+
if e.message == "Bad Request"
|
122
|
+
puts "Can\'t find that key to register the server, please check it and try again. The key may have expired."
|
123
|
+
Qnotifier.log.error "Can\'t find that key to register the server, please check it and try again. The key may have expired."
|
124
|
+
else
|
125
|
+
Qnotifier.log.error "Registering Server: Can't connect to #{@config["api_endpoint"]} - #{e.message}"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
return nil
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
data/plugins/apache.rb
ADDED
data/plugins/iostat.rb
ADDED
data/plugins/mysql.rb
ADDED
data/plugins/network.rb
ADDED
data/plugins/nginx.rb
ADDED
data/plugins/rails.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "elif"
|
3
|
+
|
4
|
+
module Qnotifier
|
5
|
+
class Rails < Qnotifier::Plugin
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@defaults = {
|
9
|
+
:rails_log_file => "/var/www/rails/log/production.log"
|
10
|
+
}
|
11
|
+
patch_elif
|
12
|
+
end
|
13
|
+
|
14
|
+
def main
|
15
|
+
puts "here"
|
16
|
+
#log_file = read_backwards_to_timestamp(@options[:rails_log_file], last_summary)
|
17
|
+
end
|
18
|
+
|
19
|
+
def patch_elif
|
20
|
+
if Elif::VERSION < "0.2.0"
|
21
|
+
Elif.send(:define_method, :pos) do
|
22
|
+
@current_pos +
|
23
|
+
@line_buffer.inject(0) { |bytes, line| bytes + line.size }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def read_backwards_to_timestamp(path, timestamp)
|
29
|
+
start = nil
|
30
|
+
Elif.open(path) do |elif|
|
31
|
+
elif.each do |line|
|
32
|
+
if line =~ /\AProcessing .+ at (\d+-\d+-\d+ \d+:\d+:\d+)\)/
|
33
|
+
time_of_request = Time.parse($1)
|
34
|
+
if time_of_request < timestamp
|
35
|
+
break
|
36
|
+
else
|
37
|
+
start = elif.pos
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
file = open(path)
|
44
|
+
file.seek(start) if start
|
45
|
+
file
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/plugins/ruby.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
module Qnotifier
|
3
|
+
class Ruby < Qnotifier::Plugin
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@defaults = {
|
7
|
+
}
|
8
|
+
end
|
9
|
+
|
10
|
+
def main
|
11
|
+
# Ruby Info
|
12
|
+
ruby_info = [RUBY_VERSION, RUBY_RELEASE_DATE, RUBY_PATCHLEVEL, RUBY_PLATFORM]
|
13
|
+
stat("Ruby", "ruby %s (%s patchlevel %s) [%s]" % ruby_info)
|
14
|
+
|
15
|
+
# Gems
|
16
|
+
gem_list = `gem list`.split("\n")
|
17
|
+
gems = []
|
18
|
+
if gem_list
|
19
|
+
for line in gem_list
|
20
|
+
next if line.match(/^[\*\n]/)
|
21
|
+
gems << line.strip
|
22
|
+
end
|
23
|
+
stat("Gems", gems.join(", "))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/plugins/system.rb
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
module Qnotifier
|
3
|
+
class System < Qnotifier::Plugin
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@defaults = {
|
7
|
+
"enabled" => true,
|
8
|
+
"use_load" => "five_minute",
|
9
|
+
"normalize_load" => true,
|
10
|
+
"alert_cpu_threshold" => 0,
|
11
|
+
"alert_memory_threshold" => 0,
|
12
|
+
"alert_load_threshold" => 2.0,
|
13
|
+
"alert_disk_threshold" => 0,
|
14
|
+
"partitions" => ["/"]
|
15
|
+
}
|
16
|
+
count_cpus
|
17
|
+
end
|
18
|
+
|
19
|
+
def main
|
20
|
+
|
21
|
+
# Uptime, Users and Load Average
|
22
|
+
uptime = `uptime`.strip
|
23
|
+
if uptime
|
24
|
+
if uptime =~ /load average(s*): ([\d.]+)(,*) ([\d.]+)(,*) ([\d.]+)\Z/
|
25
|
+
load_one_minute = $2.to_f
|
26
|
+
load_five_minute = $4.to_f
|
27
|
+
load_fifteen_minute = $6.to_f
|
28
|
+
|
29
|
+
if @options["normalize_load"]
|
30
|
+
load_one_minute = load_one_minute / @cpu_count
|
31
|
+
load_five_minute = load_five_minute / @cpu_count
|
32
|
+
load_fifteen_minute = load_fifteen_minute / @cpu_count
|
33
|
+
end
|
34
|
+
|
35
|
+
case @options["use_load"]
|
36
|
+
when "one_minute"
|
37
|
+
load_average = load_one_minute
|
38
|
+
when "five_minute"
|
39
|
+
load_average = load_one_minute
|
40
|
+
else
|
41
|
+
load_average = load_one_minute
|
42
|
+
end
|
43
|
+
|
44
|
+
report("Load", load_average)
|
45
|
+
stat("Load", load_average)
|
46
|
+
|
47
|
+
if @options["alert_load_threshold"] != 0 and load_average >= @options["alert_load_threshold"]
|
48
|
+
alert("load", "Load is at #{load_average} #{"(normalized)" if @options[:normalize_load]}")
|
49
|
+
else
|
50
|
+
reset_alert("load", "Load is now #{load_average}")
|
51
|
+
end
|
52
|
+
|
53
|
+
else
|
54
|
+
raise "Unable to parse load averages"
|
55
|
+
end
|
56
|
+
|
57
|
+
stat("Uptime", uptime)
|
58
|
+
end
|
59
|
+
|
60
|
+
# CPU
|
61
|
+
vmstat = `vmstat | tail -1`
|
62
|
+
if vmstat
|
63
|
+
vmstat = vmstat.split
|
64
|
+
if vmstat.size == 16
|
65
|
+
|
66
|
+
cpu = "User: #{vmstat[12].to_i}%, System: #{vmstat[13].to_i}%, Idle: #{vmstat[14].to_i}%, Wait: #{vmstat[15].to_i}%"
|
67
|
+
cpu_percent = (100 - vmstat[14].to_i)
|
68
|
+
|
69
|
+
stat("CPU", cpu)
|
70
|
+
report("CPU %", cpu_percent)
|
71
|
+
|
72
|
+
if @options["alert_cpu_threshold"] != 0 and cpu_percent >= @options["alert_cpu_threshold"]
|
73
|
+
alert("cpu", "CPU is at #{cpu_percent}%")
|
74
|
+
else
|
75
|
+
reset_alert("cpu", "CPU is now #{cpu_percent}%")
|
76
|
+
end
|
77
|
+
|
78
|
+
else
|
79
|
+
raise "Can't parse vmstat"
|
80
|
+
end
|
81
|
+
else
|
82
|
+
raise "Can't run vmstat, is it installed/supported?"
|
83
|
+
end
|
84
|
+
|
85
|
+
# Disk
|
86
|
+
df = `df -Phl`
|
87
|
+
if df
|
88
|
+
df = df.split("\n")
|
89
|
+
for partition in @options["partitions"]
|
90
|
+
for line in df
|
91
|
+
if line =~ /#{partition}$/
|
92
|
+
items = line.split
|
93
|
+
|
94
|
+
disk = "Used: #{items[-2]} (#{items[-4]}), #{items[-3]} free"
|
95
|
+
stat("Disk #{partition}", disk) if partition == "/"
|
96
|
+
report("Disk #{partition} %", items[-2].delete("%").to_i)
|
97
|
+
|
98
|
+
if @options["alert_disk_threshold"] != 0 and items[-2].delete("%").to_i >= @options["alert_disk_threshold"]
|
99
|
+
alert("partition-#{partition}", "Partition #{partition} is at #{items[-2]}")
|
100
|
+
else
|
101
|
+
reset_alert("partition-#{partition}", "Partition #{partition} is now #{items[-2]}")
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
else
|
107
|
+
raise "Can't run df -Phl"
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
# Uname
|
112
|
+
stat("Uname", `uname -srm`.strip)
|
113
|
+
|
114
|
+
# Memory
|
115
|
+
meminfo = {}
|
116
|
+
`cat /proc/meminfo`.each_line do |line|
|
117
|
+
_, key, value = *line.match(/^(\w+):\s+(\d+)\s/)
|
118
|
+
meminfo[key] = value.to_i
|
119
|
+
end
|
120
|
+
|
121
|
+
memory = {}
|
122
|
+
unless meminfo.empty?
|
123
|
+
memory["Free"] = meminfo['MemFree'] / 1024
|
124
|
+
memory["Total"] = meminfo['MemTotal'] / 1024
|
125
|
+
memory_percent = ((memory["Total"] - memory["Free"]) / memory["Total"] * 100).to_i
|
126
|
+
memory["Percent"] = memory_percent
|
127
|
+
|
128
|
+
stat("Memory", "Free: #{memory["Free"]}M, Total: #{memory["Total"]}M")
|
129
|
+
report("Memory %", memory_percent)
|
130
|
+
|
131
|
+
if @options["alert_memory_threshold"] != 0 and memory_percent >= @options["alert_memory_threshold"]
|
132
|
+
alert("memory", "Memory is at #{memory_percent}%")
|
133
|
+
else
|
134
|
+
reset_alert("memory", "Memory is now #{memory_percent}%")
|
135
|
+
end
|
136
|
+
else
|
137
|
+
raise "Can't get memory information from /proc/meminfo (is it supported by this OS?)"
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
|
144
|
+
def count_cpus
|
145
|
+
if get("cpu_count")
|
146
|
+
@cpu_count = get("cpu_count")
|
147
|
+
else
|
148
|
+
cpu_count = `cat /proc/cpuinfo | grep "model name" | wc -l`.to_i
|
149
|
+
if cpu_count != 0
|
150
|
+
@cpu_count = cpu_count
|
151
|
+
else
|
152
|
+
@cpu_count = 1
|
153
|
+
end
|
154
|
+
put("cpu_count", @cpu_count)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
data/plugins/urls.rb
ADDED
data/qnotifier.gemspec
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{qnotifier}
|
5
|
+
s.version = "0.6.2"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Gersham Meharg"]
|
9
|
+
s.date = %q{2010-03-17}
|
10
|
+
s.default_executable = %q{qnotifier}
|
11
|
+
s.description = %q{The server side agent for the QNotifier monitoring system. This software will monitor local Linux system parameters and upload them to the Qnotifier servers where users can use iPhone/iPad applications to view those stats and recevie alerts.}
|
12
|
+
s.email = %q{gersham@qnotifier.com}
|
13
|
+
s.executables = ["qnotifier"]
|
14
|
+
s.extra_rdoc_files = ["bin/qnotifier", "lib/command.rb", "lib/plugin.rb", "lib/qnotifier.rb", "lib/storage.rb", "lib/web_service.rb"]
|
15
|
+
s.files = ["Manifest", "Rakefile", "bin/qnotifier", "config/qnotifier_config.yml", "gem-public_cert.pem", "lib/command.rb", "lib/plugin.rb", "lib/qnotifier.rb", "lib/storage.rb", "lib/web_service.rb", "plugins/apache.rb", "plugins/iostat.rb", "plugins/mysql.rb", "plugins/network.rb", "plugins/nginx.rb", "plugins/passenger.rb", "plugins/processes.rb", "plugins/rails.rb", "plugins/ruby.rb", "plugins/system.rb", "plugins/urls.rb", "qnotifier.gemspec"]
|
16
|
+
s.homepage = %q{http://qnotifier.com/qnotifier_gem}
|
17
|
+
s.post_install_message = %q{Qnotifier installed, please register by running 'qnotifier -r CODE' in order to register this server.}
|
18
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Qnotifier"]
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
s.rubyforge_project = %q{qnotifier}
|
21
|
+
s.rubygems_version = %q{1.3.5}
|
22
|
+
s.summary = %q{The server side agent for the QNotifier monitoring system}
|
23
|
+
s.signing_key = "/Users/gersham/Sources/qanix-documents/qnotifier-gem-private_key.pem"
|
24
|
+
s.cert_chain = ['gem-public_cert.pem']
|
25
|
+
|
26
|
+
if s.respond_to? :specification_version then
|
27
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
28
|
+
s.specification_version = 3
|
29
|
+
|
30
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
31
|
+
s.add_runtime_dependency(%q<rest-client>, [">= 1.4.2"])
|
32
|
+
s.add_runtime_dependency(%q<json>, [">= 1.2.3"])
|
33
|
+
s.add_runtime_dependency(%q<elif>, [">= 0.1.0"])
|
34
|
+
s.add_development_dependency(%q<rest-client>, [">= 1.4.2"])
|
35
|
+
s.add_development_dependency(%q<json>, [">= 1.2.3"])
|
36
|
+
s.add_development_dependency(%q<elif>, [">= 0.1.0"])
|
37
|
+
else
|
38
|
+
s.add_dependency(%q<rest-client>, [">= 1.4.2"])
|
39
|
+
s.add_dependency(%q<json>, [">= 1.2.3"])
|
40
|
+
s.add_dependency(%q<elif>, [">= 0.1.0"])
|
41
|
+
s.add_dependency(%q<rest-client>, [">= 1.4.2"])
|
42
|
+
s.add_dependency(%q<json>, [">= 1.2.3"])
|
43
|
+
s.add_dependency(%q<elif>, [">= 0.1.0"])
|
44
|
+
end
|
45
|
+
else
|
46
|
+
s.add_dependency(%q<rest-client>, [">= 1.4.2"])
|
47
|
+
s.add_dependency(%q<json>, [">= 1.2.3"])
|
48
|
+
s.add_dependency(%q<elif>, [">= 0.1.0"])
|
49
|
+
s.add_dependency(%q<rest-client>, [">= 1.4.2"])
|
50
|
+
s.add_dependency(%q<json>, [">= 1.2.3"])
|
51
|
+
s.add_dependency(%q<elif>, [">= 0.1.0"])
|
52
|
+
end
|
53
|
+
end
|
data.tar.gz.sig
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: qnotifier
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.6.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gersham Meharg
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain:
|
11
|
+
- |
|
12
|
+
-----BEGIN CERTIFICATE-----
|
13
|
+
MIIDODCCAiCgAwIBAgIBADANBgkqhkiG9w0BAQUFADBCMRAwDgYDVQQDDAdnZXJz
|
14
|
+
aGFtMRkwFwYKCZImiZPyLGQBGRYJcW5vdGlmaWVyMRMwEQYKCZImiZPyLGQBGRYD
|
15
|
+
Y29tMB4XDTEwMDMxNzE4MjAwOFoXDTExMDMxNzE4MjAwOFowQjEQMA4GA1UEAwwH
|
16
|
+
Z2Vyc2hhbTEZMBcGCgmSJomT8ixkARkWCXFub3RpZmllcjETMBEGCgmSJomT8ixk
|
17
|
+
ARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMS8vIaSE0eA
|
18
|
+
DfL3OqRwmY+b3ueQ+cfm2nxU1J+TE7yFFGiv+bk4z4YMtHtbqsGxlmL4HZKW7Ur/
|
19
|
+
RrS7+d+fVTskoRC7t9g6mRoww/4+fTgmX25g7YLe4vuiSBkBeBMXBt5Vd3ombU9F
|
20
|
+
b0CrguX2a2ffYxnF/RlrXnhsU2VywZry+qz1NJglaCa+qb0S0W3BnvoB8T+MxNOM
|
21
|
+
7feKF/HvWRCM7DdHyqXqHFqMBIWJlCC7MFV4kQVW/a8b49VC5Dgmz6QVWcPqQ8cl
|
22
|
+
GK35UW+1WZXRB5Mhv5HBAQQqzLut46pxbUJ3qIpibtp1ltgyu81ZIRAwKIWx0YNv
|
23
|
+
lP5V85hTZ1ECAwEAAaM5MDcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUn3O2jt+12CmU
|
24
|
+
t1GEK8NZRNRbzqwwCwYDVR0PBAQDAgSwMA0GCSqGSIb3DQEBBQUAA4IBAQBb5gk8
|
25
|
+
OyfuloScbz/oHOopNmSc+o/s/5MvyrslPYDZA0WGR/63Q4Wl6l/tFFPwuAZH1KAI
|
26
|
+
MtLf7mVDdijHQf3Q6e+DicNRRQrl1w3s2m4PHyPiFUmXULzWHbMc3OK4LdM+1f5q
|
27
|
+
oZvsRrAAz6esBChxfdpuNCsP9Eu3j9MIWHy4KPTNuqOFyI+p3YVW2+SHeN4gBCyV
|
28
|
+
b7VZHIY+1kKjmMYXPeG9xlXaxLABhS1iN66tAyg66l6u6vuLt5Rdh1RUIY534Edq
|
29
|
+
ciUZJrPp/am/m0FtGWggbAohDKjiKRL0E6OCFQ7wSCTUPKoB9MbIJkKSGFo6ExWe
|
30
|
+
wu7A8rLN6CU0SfWf
|
31
|
+
-----END CERTIFICATE-----
|
32
|
+
|
33
|
+
date: 2010-03-17 00:00:00 -07:00
|
34
|
+
default_executable: qnotifier
|
35
|
+
dependencies:
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rest-client
|
38
|
+
type: :runtime
|
39
|
+
version_requirement:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: 1.4.2
|
45
|
+
version:
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: json
|
48
|
+
type: :runtime
|
49
|
+
version_requirement:
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.2.3
|
55
|
+
version:
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: elif
|
58
|
+
type: :runtime
|
59
|
+
version_requirement:
|
60
|
+
version_requirements: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 0.1.0
|
65
|
+
version:
|
66
|
+
- !ruby/object:Gem::Dependency
|
67
|
+
name: rest-client
|
68
|
+
type: :development
|
69
|
+
version_requirement:
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 1.4.2
|
75
|
+
version:
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
name: json
|
78
|
+
type: :development
|
79
|
+
version_requirement:
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: 1.2.3
|
85
|
+
version:
|
86
|
+
- !ruby/object:Gem::Dependency
|
87
|
+
name: elif
|
88
|
+
type: :development
|
89
|
+
version_requirement:
|
90
|
+
version_requirements: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: 0.1.0
|
95
|
+
version:
|
96
|
+
description: The server side agent for the QNotifier monitoring system. This software will monitor local Linux system parameters and upload them to the Qnotifier servers where users can use iPhone/iPad applications to view those stats and recevie alerts.
|
97
|
+
email: gersham@qnotifier.com
|
98
|
+
executables:
|
99
|
+
- qnotifier
|
100
|
+
extensions: []
|
101
|
+
|
102
|
+
extra_rdoc_files:
|
103
|
+
- bin/qnotifier
|
104
|
+
- lib/command.rb
|
105
|
+
- lib/plugin.rb
|
106
|
+
- lib/qnotifier.rb
|
107
|
+
- lib/storage.rb
|
108
|
+
- lib/web_service.rb
|
109
|
+
files:
|
110
|
+
- Manifest
|
111
|
+
- Rakefile
|
112
|
+
- bin/qnotifier
|
113
|
+
- config/qnotifier_config.yml
|
114
|
+
- gem-public_cert.pem
|
115
|
+
- lib/command.rb
|
116
|
+
- lib/plugin.rb
|
117
|
+
- lib/qnotifier.rb
|
118
|
+
- lib/storage.rb
|
119
|
+
- lib/web_service.rb
|
120
|
+
- plugins/apache.rb
|
121
|
+
- plugins/iostat.rb
|
122
|
+
- plugins/mysql.rb
|
123
|
+
- plugins/network.rb
|
124
|
+
- plugins/nginx.rb
|
125
|
+
- plugins/passenger.rb
|
126
|
+
- plugins/processes.rb
|
127
|
+
- plugins/rails.rb
|
128
|
+
- plugins/ruby.rb
|
129
|
+
- plugins/system.rb
|
130
|
+
- plugins/urls.rb
|
131
|
+
- qnotifier.gemspec
|
132
|
+
has_rdoc: true
|
133
|
+
homepage: http://qnotifier.com/qnotifier_gem
|
134
|
+
licenses: []
|
135
|
+
|
136
|
+
post_install_message: Qnotifier installed, please register by running 'qnotifier -r CODE' in order to register this server.
|
137
|
+
rdoc_options:
|
138
|
+
- --line-numbers
|
139
|
+
- --inline-source
|
140
|
+
- --title
|
141
|
+
- Qnotifier
|
142
|
+
require_paths:
|
143
|
+
- lib
|
144
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
145
|
+
requirements:
|
146
|
+
- - ">="
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: "0"
|
149
|
+
version:
|
150
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
151
|
+
requirements:
|
152
|
+
- - ">="
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: "1.2"
|
155
|
+
version:
|
156
|
+
requirements: []
|
157
|
+
|
158
|
+
rubyforge_project: qnotifier
|
159
|
+
rubygems_version: 1.3.5
|
160
|
+
signing_key:
|
161
|
+
specification_version: 3
|
162
|
+
summary: The server side agent for the QNotifier monitoring system
|
163
|
+
test_files: []
|
164
|
+
|
metadata.gz.sig
ADDED
Binary file
|