qnotifier 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|