db_mon 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +91 -0
- data/Rakefile +2 -0
- data/bin/dbmon +9 -0
- data/db_mon.gemspec +23 -0
- data/lib/db_mon/monitor.rb +77 -0
- data/lib/db_mon/mysql_monitor.rb +15 -0
- data/lib/db_mon/pg_monitor.rb +18 -0
- data/lib/db_mon/runner.rb +29 -0
- data/lib/db_mon/version.rb +3 -0
- data/lib/db_mon.rb +21 -0
- metadata +89 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c7aec1564fd1a3250a73ff614f6faa8e72110576
|
4
|
+
data.tar.gz: c88966ae796c48ca953285e009978e7189e01edf
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cfa0df816c9bef767c7a6286fc8a623a34da83bc20de9793cab9de90f2be78b92ba3fc38e57c19a7e09082a59cb798480003724bd489a6ca62b481e514a6a2e5
|
7
|
+
data.tar.gz: c2218b2e5b11825bcc15e226a30d7c86a823a8fd8e9bfee870f28c495abdea0d830252f0b6a2e1facb0776b571023b1c0d2f4f865dc0e8664cf640b8a7efdff4
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Steve Lewis
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
# DBMon
|
2
|
+
|
3
|
+
DBMon is a simple database monitoring daemon that watches a given table for writes. If it doesn't detect a certain amount of writes within a specific period of time, it triggers an alert.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'dbmon'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install dbmon
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
The gem comes with a command-line utility, <code>dbmon</code>, that starts and stops the monitor in addition to other daemon tasks. To start the monitor, simply invoke the <code>dbmon start</code> command and point to your configuration file:
|
22
|
+
|
23
|
+
```
|
24
|
+
dbmon start -- -C /path/to_your/config.yml
|
25
|
+
```
|
26
|
+
|
27
|
+
This will invoke the script as a daemon, putting it in the background.
|
28
|
+
|
29
|
+
You can stop the monitor at any time by invoking <code>dbmon stop</code>
|
30
|
+
|
31
|
+
|
32
|
+
## Configuration
|
33
|
+
|
34
|
+
The configuration file for DBMon is a YAML file that allows you to specify many of the aspects of DBmon's behavior. An example config is below:
|
35
|
+
|
36
|
+
```
|
37
|
+
interval: 10
|
38
|
+
threshold: 1
|
39
|
+
adapter: 'pg'
|
40
|
+
database: 'is_development'
|
41
|
+
table: 'users'
|
42
|
+
username: 'stlewis'
|
43
|
+
password: 'dbpass'
|
44
|
+
notify: 'steve.lewis@moduspowered.com'
|
45
|
+
delivery_method: 'smtp'
|
46
|
+
|
47
|
+
```
|
48
|
+
|
49
|
+
The purpose of these options is described below:
|
50
|
+
|
51
|
+
**interval**
|
52
|
+
|
53
|
+
How often (in seconds) to check the table for new writes. DBMon will query the table in question for writes that occurred between NOW() and <code>interval</code> ago.
|
54
|
+
|
55
|
+
**threshold**
|
56
|
+
|
57
|
+
This is the minimum number of records that must have been added to the database within the interval specified to avoid triggering an alert.
|
58
|
+
|
59
|
+
**adapter**
|
60
|
+
|
61
|
+
The database adapter to use for making connections. Currently supported options are mysql2 and pg. Note that you must have either the mysql2 gem or the pg gem in order to use it as an adapter.
|
62
|
+
|
63
|
+
**database**
|
64
|
+
|
65
|
+
The name of the database to connect to.
|
66
|
+
|
67
|
+
**table**
|
68
|
+
|
69
|
+
The name of the table you want to monitor.
|
70
|
+
|
71
|
+
**username**
|
72
|
+
|
73
|
+
The database username
|
74
|
+
|
75
|
+
**password**
|
76
|
+
|
77
|
+
The database password
|
78
|
+
|
79
|
+
**notify**
|
80
|
+
|
81
|
+
The email address you would like to receive a notification when an alert is triggered.
|
82
|
+
|
83
|
+
**delivery_method**
|
84
|
+
|
85
|
+
This option is passed directly to the Mail gem, and determines how you would like messages delivered. The default is 'smtp', but if you would like to test email delivery, you can use 'test' as a value.
|
86
|
+
|
87
|
+
|
88
|
+
## TODO
|
89
|
+
|
90
|
+
* Make more options available for Mail configuration
|
91
|
+
* Monitoring for multiple tables
|
data/Rakefile
ADDED
data/bin/dbmon
ADDED
data/db_mon.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'db_mon/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "db_mon"
|
8
|
+
spec.version = DbMon::VERSION
|
9
|
+
spec.authors = ["Steve Lewis"]
|
10
|
+
spec.email = ["steve.lewis@moduspowered.com"]
|
11
|
+
spec.summary = %q{DBMon is a simple daemon that monitors writes to a database table.}
|
12
|
+
spec.description = %q{In many cases, one of the primary indicators of system and application health is whether or not a certain table is receiving a consistent number of writes over time. DBMon helps to monitor database tables, and sends alerts if it doesn't see enough writes over time.}
|
13
|
+
spec.homepage = "https://www.github.com/JJCOINCWEBDEV/db_mon"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'mail'
|
2
|
+
|
3
|
+
|
4
|
+
module DbMon
|
5
|
+
|
6
|
+
class Monitor
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
@interval = options['interval']
|
10
|
+
@threshold = options['threshold']
|
11
|
+
@database = options['database']
|
12
|
+
@username = options['username']
|
13
|
+
@password = options['password']
|
14
|
+
@table = options['table']
|
15
|
+
@notify = options['notify']
|
16
|
+
@time_column = options['time_column'] || 'created_at'
|
17
|
+
|
18
|
+
|
19
|
+
Mail.defaults do
|
20
|
+
delivery_method options['delivery_method'].to_sym
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
def monitor_table
|
26
|
+
while true
|
27
|
+
sleep @interval.to_i
|
28
|
+
result = query_table
|
29
|
+
|
30
|
+
unless result.count >= @threshold
|
31
|
+
send_alert_email
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def query_table
|
37
|
+
raise "Must be implemented on child classes"
|
38
|
+
end
|
39
|
+
|
40
|
+
def send_alert_email
|
41
|
+
table = @table
|
42
|
+
database = @database
|
43
|
+
threshold = @threshold
|
44
|
+
interval = @interval
|
45
|
+
notify = @notify
|
46
|
+
|
47
|
+
mail = Mail.deliver do
|
48
|
+
from 'database_monitor@modustools.com'
|
49
|
+
to notify
|
50
|
+
subject 'Database Monitor Alert'
|
51
|
+
|
52
|
+
html_part do
|
53
|
+
content_type 'text/html; charset=UTF-8'
|
54
|
+
body <<-EOM
|
55
|
+
<h2>Database Alert</h2>
|
56
|
+
|
57
|
+
<p>
|
58
|
+
The #{table} table on #{database} has had less than #{threshold} record(s)
|
59
|
+
added to it in the last #{interval} seconds. This may be an indication that
|
60
|
+
there is a problem with the service(s) responsible for creating these records.
|
61
|
+
</p>
|
62
|
+
<p>
|
63
|
+
#{interval} seconds is:
|
64
|
+
</p>
|
65
|
+
#{interval/60.0} minutes<br />
|
66
|
+
#{(interval/60.0)/60.0} hours<br />
|
67
|
+
#{((interval/60.0)/60.0)/24.0} days<br />
|
68
|
+
EOM
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
p
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'mysql2'
|
2
|
+
module DbMon
|
3
|
+
|
4
|
+
class MysqlMonitor < Monitor
|
5
|
+
def initialize(options)
|
6
|
+
super(options)
|
7
|
+
@connection = Mysql2::Client.new(host: 'localhost', username: @username, password: @password)
|
8
|
+
end
|
9
|
+
|
10
|
+
def query_table
|
11
|
+
return @connection.query("SELECT #{@time_column} FROM #{@table} WHERE #{@time_column} BETWEEN '#{@interval.seconds.ago}' AND '#{Time.now}' ORDER BY #{@time_column}")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'pg'
|
2
|
+
module DbMon
|
3
|
+
|
4
|
+
class PgMonitor < Monitor
|
5
|
+
|
6
|
+
def initialize(options)
|
7
|
+
super(options)
|
8
|
+
@connection = PG.connect(dbname: @database, user: @username, password: @password)
|
9
|
+
end
|
10
|
+
|
11
|
+
def query_table
|
12
|
+
@connection.exec("SELECT #{@time_column} FROM #{@table} WHERE #{@time_column} BETWEEN '#{Time.now - @interval}' AND '#{Time.now}' ORDER BY #{@time_column}").values
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative 'monitor'
|
2
|
+
|
3
|
+
module DbMon
|
4
|
+
|
5
|
+
class Runner
|
6
|
+
attr_reader :monitor
|
7
|
+
|
8
|
+
|
9
|
+
def initialize(options = {})
|
10
|
+
@monitor = nil
|
11
|
+
case options['adapter']
|
12
|
+
when 'mysql2'
|
13
|
+
require_relative 'mysql_monitor'
|
14
|
+
@monitor = MysqlMonitor.new(options)
|
15
|
+
when 'pg'
|
16
|
+
require_relative 'pg_monitor'
|
17
|
+
@monitor = PgMonitor.new(options)
|
18
|
+
when 'sqlite'
|
19
|
+
raise "SQLite Monitor not implemented"
|
20
|
+
@monitor = SqliteMonitor.new(options)
|
21
|
+
else
|
22
|
+
raise 'Unsupported Adapter'
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/lib/db_mon.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative "db_mon/version"
|
2
|
+
require_relative 'db_mon/runner'
|
3
|
+
|
4
|
+
module DbMon
|
5
|
+
end
|
6
|
+
|
7
|
+
|
8
|
+
options = {}
|
9
|
+
|
10
|
+
optparse = OptionParser.new do |opts|
|
11
|
+
opts.banner = "Usage: dbmon -C <path to config file>"
|
12
|
+
opts.on('-C', '--config FILE', 'Full path to configuration file') do |file|
|
13
|
+
options[:config_file] = file
|
14
|
+
end
|
15
|
+
end
|
16
|
+
optparse.parse!
|
17
|
+
|
18
|
+
raise "No config file provided" unless options[:config_file]
|
19
|
+
config = YAML::load(File.read(options[:config_file]))
|
20
|
+
monitor = DbMon::Runner.new(config).monitor
|
21
|
+
monitor.monitor_table
|
metadata
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: db_mon
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Steve Lewis
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-07-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: In many cases, one of the primary indicators of system and application
|
42
|
+
health is whether or not a certain table is receiving a consistent number of writes
|
43
|
+
over time. DBMon helps to monitor database tables, and sends alerts if it doesn't
|
44
|
+
see enough writes over time.
|
45
|
+
email:
|
46
|
+
- steve.lewis@moduspowered.com
|
47
|
+
executables:
|
48
|
+
- dbmon
|
49
|
+
extensions: []
|
50
|
+
extra_rdoc_files: []
|
51
|
+
files:
|
52
|
+
- .gitignore
|
53
|
+
- Gemfile
|
54
|
+
- LICENSE.txt
|
55
|
+
- README.md
|
56
|
+
- Rakefile
|
57
|
+
- bin/dbmon
|
58
|
+
- db_mon.gemspec
|
59
|
+
- lib/db_mon.rb
|
60
|
+
- lib/db_mon/monitor.rb
|
61
|
+
- lib/db_mon/mysql_monitor.rb
|
62
|
+
- lib/db_mon/pg_monitor.rb
|
63
|
+
- lib/db_mon/runner.rb
|
64
|
+
- lib/db_mon/version.rb
|
65
|
+
homepage: https://www.github.com/JJCOINCWEBDEV/db_mon
|
66
|
+
licenses:
|
67
|
+
- MIT
|
68
|
+
metadata: {}
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options: []
|
71
|
+
require_paths:
|
72
|
+
- lib
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
requirements: []
|
84
|
+
rubyforge_project:
|
85
|
+
rubygems_version: 2.0.3
|
86
|
+
signing_key:
|
87
|
+
specification_version: 4
|
88
|
+
summary: DBMon is a simple daemon that monitors writes to a database table.
|
89
|
+
test_files: []
|