json-monitor 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,10 @@
1
+ JsonTail
2
+ ===========
3
+
4
+ To start json_tail in background:
5
+
6
+ $ ruby script/json_tail_control start
7
+
8
+ To kill json_tail:
9
+
10
+ $ ruby script/json_tail_control stop
data/TODO ADDED
@@ -0,0 +1,7 @@
1
+ - agregar excepciones para casi todo. servicios, couchdb, etc.
2
+ - validaciones, validaciones, validaciones
3
+ - agregar mas parsers
4
+ ** test all the fucking time
5
+ - ver cambio a couchrest
6
+ - ver el parser de suipit_app la consulta en especifico
7
+ - mejorar manejo de threads cuando se cierre json_tail abruptamente
data/bin/json_tail ADDED
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.dirname(__FILE__) + '/../lib/json_tail.rb'
4
+
5
+ options = {}
6
+
7
+ optparse = OptionParser.new do |opts|
8
+ # Set a banner, displayed at the top
9
+ # of the help screen.
10
+ opts.banner = "Usage: json_tail [config-file]"
11
+
12
+ opts.on("-h", "--help", "Display this screen") do
13
+ puts opts
14
+ exit
15
+ end
16
+
17
+ opts.on("-v", "--version", "Display version information") do
18
+ puts "json_tail " + JsonTail::VERSION + " by Metrik <info@metrik.cl> - http://www.metrik.cl"
19
+ exit
20
+ end
21
+
22
+ opts.on("-p", "--parsers", "List available parsers") do
23
+ puts "Supported Parsers [" + JsonTail::Parser::registry.keys.sort { |a,b| a.to_s <=> b.to_s }.collect { |p| ":#{p.to_s}" }.join(", ") + "]"
24
+ exit
25
+ end
26
+
27
+ opts.on("-n", "--new", "Initialize config specified with default options") do
28
+ puts "Not implemented yet. Sorry."
29
+ exit
30
+ end
31
+
32
+ end
33
+
34
+ begin
35
+ optparse.parse!(ARGV)
36
+ rescue OptionParser::ParseError => e
37
+ puts e
38
+ exit
39
+ end
40
+
41
+
42
+ file_json_tail = File.dirname(__FILE__) + '/../etc/services.yml'
43
+ file_couchdb = File.dirname(__FILE__) + '/../etc/couchdb.yml'
44
+
45
+ couchdb_config = JsonTail::Config.parse_yml(file_couchdb, 'couchdb')
46
+
47
+ @@couchdb_server = JsonTail::CouchServer.new(couchdb_config['host'], couchdb_config['port'], couchdb_config['database'],
48
+ couchdb_config['username'], couchdb_config['password'])
49
+
50
+ config = JsonTail::Config.parse_yml(file_json_tail, 'services')
51
+
52
+ engine = JsonTail::Engine.new(config)
53
+
54
+ engine.start
55
+
data/lib/json_tail.rb ADDED
@@ -0,0 +1,57 @@
1
+ # json_tail.rb - service monitoring - JSON and CouchDB
2
+ # Copyright 2009 Metrik <info@metrik.cl>
3
+ #
4
+ # Licensed under the General Public License v2 (see LICENSE)
5
+
6
+ module JsonTail
7
+ VERSION = '0.1.0'
8
+ end
9
+
10
+ begin
11
+ require 'rubygems'
12
+ rescue LoadError
13
+ puts "Missing gem rubygems. Note: please install from rubyforge."
14
+ exit
15
+ end
16
+
17
+ begin
18
+ require 'net/ssh'
19
+ rescue LoadError
20
+ puts "Missing gem net-ssh. Note: sudo gem install net-ssh"
21
+ exit
22
+ end
23
+
24
+ begin
25
+ require 'mysql'
26
+ rescue LoadError
27
+ puts "Missing gem mysql. Note: sudo gem install mysql"
28
+ exit
29
+ end
30
+
31
+ begin
32
+ require 'daemons'
33
+ rescue LoadError
34
+ puts "Missing gem daemons. Note: sudo gem install daemons"
35
+ exit
36
+ end
37
+
38
+ begin
39
+ require 'json'
40
+ rescue LoadError
41
+ puts "Missing gem json. Note: sudo gem install json"
42
+ exit
43
+ end
44
+
45
+
46
+ # loading extensions
47
+
48
+ Dir.glob(File.dirname(__FILE__) + "/../lib/json_tail/ext/*").each { |lib| require lib }
49
+
50
+ # loading libraries
51
+
52
+ libraries = ["config", "couchdb", "engine", "parser", "service"]
53
+ libraries.each { |lib| require File.dirname(__FILE__) + "/../lib/json_tail/#{lib}" }
54
+
55
+ Dir.glob(File.dirname(__FILE__) + "/../lib/json_tail/parsers/*").each { |lib| require lib }
56
+
57
+
@@ -0,0 +1,12 @@
1
+ module JsonTail
2
+ class Config
3
+ attr_reader :yaml
4
+
5
+ class << self
6
+ def parse_yml(file, hash = {})
7
+ @yaml = YAML::load(File.open(file))[hash]
8
+ end
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,50 @@
1
+ require 'net/http'
2
+
3
+ module JsonTail
4
+ class CouchServer
5
+ attr_reader :database
6
+
7
+ def initialize(host, port, database, username, password)
8
+ @host = host
9
+ @port = port
10
+ @database = database
11
+ @username = username
12
+ @password = password
13
+ end
14
+
15
+ def delete(uri)
16
+ send_request(Net::HTTP::Delete.new(uri))
17
+ end
18
+
19
+ def get(uri)
20
+ send_request(Net::HTTP::Get.new(uri))
21
+ end
22
+
23
+ def put(uri, json)
24
+ req = Net::HTTP::Put.new(uri)
25
+ req["content-type"] = "application/json"
26
+ req.body = json
27
+ send_request(req)
28
+ end
29
+
30
+ def post(uri, json)
31
+ req = Net::HTTP::Post.new(uri)
32
+ req["content-type"] = "application/json"
33
+ req.body = json
34
+ send_request(req)
35
+ end
36
+
37
+ def send_request(req)
38
+ begin
39
+ res = Net::HTTP.start(@host, @port) do |http|
40
+ req.basic_auth @username, @password
41
+ http.request(req)
42
+ end
43
+ rescue Errno::ECONNREFUSED => e
44
+ puts "couchdb: " + e
45
+ exit
46
+ end
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,21 @@
1
+ module JsonTail
2
+ class Engine
3
+ attr_reader :services
4
+
5
+ def initialize(config)
6
+ @services = []
7
+ config.each do |service|
8
+ @services << JsonTail::Service.new(service.shift, service.shift)
9
+ end
10
+ end
11
+
12
+ def start
13
+ thr = []
14
+ @services.each do |service|
15
+ thr << Thread.new { service.start }
16
+ end
17
+ thr.each { |t| t.join }
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,11 @@
1
+ # http://stackoverflow.com/questions/436159/how-to-get-all-subclasses
2
+ # thanks to Jorg W Mittag
3
+ # http://stackoverflow.com/users/2988/jorg-w-mittag
4
+
5
+ class Class
6
+ def subclasses
7
+ result = []
8
+ ObjectSpace.each_object(Class) { |klass| result << klass if klass < self }
9
+ result
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ # rails class::method - Inflector::underscore based on
2
+
3
+ class String
4
+ def underscore
5
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').gsub(/([a-z\d])([A-Z])/,'\1_\2').tr("-", "_").downcase
6
+ end
7
+ end
@@ -0,0 +1,22 @@
1
+ module JsonTail
2
+ class Parser
3
+ class << self
4
+
5
+ def report(parser, content = {})
6
+ @@couchdb_server.post(@@couchdb_server.database, JSON.generate({ "hostname" => `hostname`.chomp, "parser" => parser,
7
+ "timestamp" => Time.now.strftime("%Y-%m-%d %H:%M:%S"), "content" => content }))
8
+ end
9
+ end
10
+
11
+ def self::inherited(klass)
12
+ parser_name = klass.to_s.underscore
13
+ @registry ||= {}
14
+ @registry[ parser_name ] = klass
15
+ end
16
+
17
+ def self::registry
18
+ @registry
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,18 @@
1
+ # cada parser debiera tener un método parse() y
2
+ # otro build_report() que devuelva un objecto de clase Hash
3
+ # para que sea transformado a JSON después.
4
+
5
+ class DiskUsage < JsonTail::Parser
6
+
7
+ class << self
8
+
9
+ def build_report(options)
10
+ content = {}
11
+ dfh = "df | grep #{options['filesystem']}"
12
+ res_dfh = `#{dfh}`.split
13
+ content = { "disk_size" => res_dfh[1], "used" => res_dfh[2], "available" => res_dfh[3], "percentage_used" => res_dfh[4] }
14
+
15
+ report(options['parser'], content)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,24 @@
1
+ # cada parser debiera tener un método parse() y
2
+ # otro build_report() que devuelva un objecto de clase Hash
3
+ # para que sea transformado a JSON después.
4
+
5
+ class MemoryUsage < JsonTail::Parser
6
+
7
+ class << self
8
+
9
+ def build_report(options)
10
+ content = {}
11
+ total_mem = `free | grep Mem: | awk '{print $2}'`.chomp
12
+ total_mem_used = `free | grep buffers/cache: | awk '{print $3}'`.chomp
13
+ total_mem_avai = `free | grep Mem: | awk '{print $4}'`.chomp
14
+ res_swap_info = `free | grep Swap:`.split
15
+ total_swap = res_swap_info[1]
16
+ per_swap_used = (res_swap_info[2].to_i*100)/total_swap.to_i # percentage
17
+ per_swap_avai = (res_swap_info[3].to_i*100)/total_swap.to_i # percentage
18
+ content = { "total_mem" => total_mem, "total_mem_used" => total_mem_used, "total_mem_avai" => total_mem_avai, "total_swap" => total_swap,
19
+ "total_swap_used" => total_swap_used, "total_swap_avai" => total_swap_avai }
20
+
21
+ report(options['parser'], content)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,58 @@
1
+ # cada parser debiera tener un método parse() y
2
+ # otro build_report() que devuelva un objecto de clase Hash
3
+ # para que sea transformado a JSON después.
4
+
5
+ require 'file/tail'
6
+
7
+ class MysqlStatistics < JsonTail::Parser
8
+ attr_accessor :com_select, :com_insert, :com_delete, :com_update
9
+ ENTRIES = ["SELECT", "INSERT", "DELETE", "UPDATE"]
10
+
11
+ def initialize(filename)
12
+ @filename = filename
13
+ @com_select = 0
14
+ @com_insert = 0
15
+ @com_delete = 0
16
+ @com_update = 0
17
+ end
18
+
19
+ def start
20
+ File.open(@filename) do |log|
21
+ log.extend(File::Tail)
22
+ log.interval = 10
23
+ log.tail do |line|
24
+ ENTRIES.each do |e|
25
+ if line.include? e
26
+ case e
27
+ when "SELECT"
28
+ @com_select += 1
29
+ when "INSERT"
30
+ @com_insert += 1
31
+ when "DELETE"
32
+ @com_delete += 1
33
+ when "UPDATE"
34
+ @com_update += 1
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ def reset
43
+ @com_select = 0
44
+ @com_insert = 0
45
+ @com_delete = 0
46
+ @com_update = 0
47
+ end
48
+
49
+ class << self
50
+
51
+ def build_report(options)
52
+ mm = self.new(options['filename'])
53
+ content = { "com_select" => mm.com_select, "com_insert" => mm.com_insert, "com_delete" => mm.com_delete, "com_update" => mm.com_update }
54
+ report(options['parser'], content)
55
+ mm.start
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,34 @@
1
+ # cada parser debiera tener un método parse() y
2
+ # otro build_report() que devuelva un objecto de clase Hash
3
+ # para que sea transformado a JSON después.
4
+
5
+ require 'mysql'
6
+
7
+ class SuipitApp < JsonTail::Parser
8
+
9
+ class << self
10
+
11
+ def build_report(options)
12
+ previous_datetime = (Time.now.utc - options['delay']).strftime("%Y-%m-%d %H:%M:%S")
13
+ conn = Mysql.connect(options['host'], options['username'], options['password'], options['database'])
14
+
15
+ loop do
16
+ content = {}
17
+ current_datetime = Time.now.utc.strftime("%Y-%m-%d %H:%M:%S")
18
+ # mmm
19
+ query = %{SELECT (SELECT count(id) FROM mensajes WHERE created_at BETWEEN '#{previous_datetime}' AND '#{current_datetime}') as mensajes,
20
+ (SELECT count(id) FROM comentarios WHERE created_at BETWEEN '#{previous_datetime}' AND '#{current_datetime}') as comentarios,
21
+ (SELECT count(id) FROM archivos WHERE created_at BETWEEN '#{previous_datetime}' AND '#{current_datetime}') as archivos}
22
+ result = conn.query(query)
23
+ result.each do |row|
24
+ content = { "mensajes" => row[0], "comentarios" => row[1], "archivos" => row[2] }
25
+ end
26
+
27
+ report(options['parser'], content)
28
+ previous_datetime = current_datetime
29
+ sleep(options['interval'])
30
+ end
31
+ end
32
+ end
33
+ end
34
+
@@ -0,0 +1,17 @@
1
+ module JsonTail
2
+ class Service
3
+ attr_reader :name, :options
4
+
5
+ def initialize(name, options = {})
6
+ @name = name
7
+ @options = options
8
+ end
9
+
10
+ def start
11
+ loop do
12
+ JsonTail::Parser::registry[@options['parser']].build_report(@options)
13
+ sleep(@options['interval'])
14
+ end
15
+ end
16
+ end
17
+ end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: json-monitor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - "Luis Mancilla \xC3\x81vila"
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-12-28 00:00:00 -03:00
13
+ default_executable: json_tail
14
+ dependencies: []
15
+
16
+ description:
17
+ email: youremail@example.com
18
+ executables:
19
+ - json_tail
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ files:
25
+ - README
26
+ - TODO
27
+ - bin/json_tail
28
+ - lib/json_tail/parser.rb
29
+ - lib/json_tail/parsers/suipit_app.rb
30
+ - lib/json_tail/parsers/memory_usage.rb
31
+ - lib/json_tail/parsers/mysql-statistics.rb
32
+ - lib/json_tail/parsers/disk_usage.rb
33
+ - lib/json_tail/ext/class.rb
34
+ - lib/json_tail/ext/string.rb
35
+ - lib/json_tail/engine.rb
36
+ - lib/json_tail/config.rb
37
+ - lib/json_tail/couchdb.rb
38
+ - lib/json_tail/service.rb
39
+ - lib/json_tail.rb
40
+ has_rdoc: true
41
+ homepage: http://metrik.cl
42
+ licenses: []
43
+
44
+ post_install_message:
45
+ rdoc_options:
46
+ - --main
47
+ - README
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ requirements: []
63
+
64
+ rubyforge_project: json-monitor
65
+ rubygems_version: 1.3.5
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: Logs in Json to CouchDB
69
+ test_files: []
70
+