zabbix_nudge 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE +201 -0
- data/README.md +4 -0
- data/Rakefile +8 -0
- data/bin/zabbix_nudge +20 -0
- data/bin/zabbix_nudge_jmx +25 -0
- data/bin/zabbix_nudged +11 -0
- data/examples/tomcat_template.xml +1279 -0
- data/lib/zabbix_nudge.rb +79 -0
- data/lib/zabbix_nudge/jmx.rb +61 -0
- data/lib/zabbix_nudge/jmx_cli.rb +54 -0
- data/lib/zabbix_nudge/nudge_cli.rb +74 -0
- data/lib/zabbix_nudge/version.rb +3 -0
- data/spec/fixtures/cms_perm_response.txt +7 -0
- data/spec/fixtures/tomcat_template.xml +92 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/zabbix_nudge_spec.rb +32 -0
- data/zabbix_nudge.gemspec +37 -0
- metadata +264 -0
data/lib/zabbix_nudge.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require "zabbix_nudge/version"
|
2
|
+
require "active_support/core_ext/string/inflections.rb"
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'yajl/json_gem'
|
5
|
+
require 'zabbix'
|
6
|
+
require "socket"
|
7
|
+
require "zabbix_nudge/jmx"
|
8
|
+
|
9
|
+
module ZabbixNudge
|
10
|
+
|
11
|
+
def self.root
|
12
|
+
@root ="#{File.expand_path('../..',__FILE__)}"
|
13
|
+
end
|
14
|
+
|
15
|
+
class Nudge
|
16
|
+
def initialize(templates, options = {} )
|
17
|
+
options[:zabbix_server_name] = 'localhost' unless options[:zabbix_server_name]
|
18
|
+
options[:zabbix_server_port] = '10051' unless options[:zabbix_server_port]
|
19
|
+
options[:sender_hostname] = Socket.gethostname unless options[:sender_hostname]
|
20
|
+
|
21
|
+
@options = options
|
22
|
+
@templates = template_files(templates)
|
23
|
+
@items = template_items(@templates)
|
24
|
+
end
|
25
|
+
|
26
|
+
def template_files(templates)
|
27
|
+
template_files = []
|
28
|
+
template_files = Dir.glob(File.join(templates,'*.xml')) if !templates.is_a?(Array) && File.directory?(templates)
|
29
|
+
template_files = templates.map{ |template| template if File.exist?(template) }.compact if templates.is_a?(Array)
|
30
|
+
template_files = [templates] if !templates.is_a?(Array) && File.exist?(templates) && !File.directory?(templates)
|
31
|
+
template_files
|
32
|
+
end
|
33
|
+
|
34
|
+
def template_items(templates)
|
35
|
+
parsed_items = Hash.new
|
36
|
+
|
37
|
+
templates.each do |template|
|
38
|
+
template_items = Nokogiri::XML(File.open(template))
|
39
|
+
items = template_items.xpath('//item').map {|item| item.attributes['key'].text}.compact
|
40
|
+
items.each do |item|
|
41
|
+
parts = item.match(/([^\[]+)\[([^\]]+)/)
|
42
|
+
unless parts.nil?
|
43
|
+
key = parts[1].underscore.to_sym
|
44
|
+
attributes = parts[2]
|
45
|
+
(parsed_items[key]) ? parsed_items[key] << attributes : parsed_items[key] = [attributes]
|
46
|
+
else
|
47
|
+
puts "not evaluating: "+item
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
parsed_items
|
52
|
+
end
|
53
|
+
|
54
|
+
def send(items = :all)
|
55
|
+
|
56
|
+
return if @items.nil?
|
57
|
+
|
58
|
+
|
59
|
+
pushers = ( items == :all) ? ( @items.keys.map{ |key| "ZabbixNudge::#{key.to_s.camelize}".constantize }) : ["ZabbixNudge::#{items.camelize}".constantize]
|
60
|
+
|
61
|
+
processed_items = Hash.new
|
62
|
+
|
63
|
+
pushers.map do |pusher|
|
64
|
+
pusher_key = pusher.to_s.demodulize.underscore.to_sym
|
65
|
+
processed_items.update pusher.new(@items[pusher_key],@options[pusher_key]).send(:processed_items)
|
66
|
+
end
|
67
|
+
|
68
|
+
zbx = Zabbix::Sender::Buffer.new :host => @options[:zabbix_server_name], :port => @options[:zabbix_server_port]
|
69
|
+
|
70
|
+
processed_items.each do |key,value|
|
71
|
+
zbx.append key, value, :host => @options[:sender_hostname]
|
72
|
+
end
|
73
|
+
zbx.flush
|
74
|
+
|
75
|
+
processed_items
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
module ZabbixNudge
|
4
|
+
|
5
|
+
class Jmx
|
6
|
+
|
7
|
+
include HTTParty
|
8
|
+
base_uri 'http://localhost:8080'
|
9
|
+
format :json
|
10
|
+
|
11
|
+
def initialize(items=[] ,options={})
|
12
|
+
self.class.base_uri options[:base_uri] if options[:base_uri]
|
13
|
+
@payload = Array.new
|
14
|
+
@items = items
|
15
|
+
@items.each do |item| mbean,attribute,path = item.split(';')
|
16
|
+
tokens = { "mbean" => mbean, "attribute" => attribute, "type" => "READ"}
|
17
|
+
tokens["path"] = path if path
|
18
|
+
@payload << tokens
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# http://www.jolokia.org/reference/html/protocol.html#search
|
23
|
+
|
24
|
+
def search(mbean,config={})
|
25
|
+
self.class.post('/jolokia', :body => { "type" => "SEARCH", "mbean" => mbean, "config" => config}.to_json)
|
26
|
+
end
|
27
|
+
|
28
|
+
# http://www.jolokia.org/reference/html/protocol.html#list
|
29
|
+
# use options = { "maxDepth" => 2} to limit depth
|
30
|
+
|
31
|
+
def list(path,config={})
|
32
|
+
self.class.post('/jolokia', :body => { "type" => "LIST", "path" => path, "config" => config}.to_json)
|
33
|
+
end
|
34
|
+
|
35
|
+
def read(mbean,attribute,path=nil,config={})
|
36
|
+
payload = { "type" => "READ", "mbean" => mbean, "attribute" => attribute}
|
37
|
+
payload["path"] = path if path
|
38
|
+
payload["config"] = config if config.length > 0
|
39
|
+
ap payload.to_json
|
40
|
+
self.class.post('/jolokia', :body => payload.to_json, :timeout => 5)
|
41
|
+
end
|
42
|
+
|
43
|
+
def version
|
44
|
+
self.class.post('/jolokia', :body => { "type" => "VERSION"}.to_json)
|
45
|
+
end
|
46
|
+
|
47
|
+
def processed_items
|
48
|
+
data = self.class.post('/jolokia', :body => @payload.to_json, :timeout => 5) rescue nil
|
49
|
+
result = Hash.new
|
50
|
+
data.each{|datum| result[result_key(datum)] = datum['value'] if datum['request']} if data
|
51
|
+
result
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def result_key(datum)
|
57
|
+
"#{self.class.to_s.demodulize.underscore}[#{datum['request']['mbean']};#{datum['request']['attribute']};#{datum['request']['path']}]"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'mixlib/cli'
|
2
|
+
|
3
|
+
module ZabbixNudge
|
4
|
+
class NudgeCLI
|
5
|
+
include Mixlib::CLI
|
6
|
+
|
7
|
+
option :jmx__base_uri,
|
8
|
+
:long => "--jmx_base_uri uri",
|
9
|
+
:description => "The jmx base uri"
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
class JmxCLI
|
14
|
+
include Mixlib::CLI
|
15
|
+
|
16
|
+
option :base_uri,
|
17
|
+
:short => "-b uri",
|
18
|
+
:default => "localhost:8080",
|
19
|
+
:long => "--base_uri uri",
|
20
|
+
:description => "The jmx base uri"
|
21
|
+
|
22
|
+
option :command,
|
23
|
+
:short => "-o command",
|
24
|
+
:default => "read",
|
25
|
+
:long => "--command action",
|
26
|
+
:description => "The command to perform",
|
27
|
+
:proc => Proc.new { |o| o.to_sym }
|
28
|
+
|
29
|
+
option :mbean,
|
30
|
+
:short => "-m mbean",
|
31
|
+
:long => "--mbean mbean",
|
32
|
+
:description => "The name of the mbean e.g. java.lang:type=Memory (needed for read command)"
|
33
|
+
|
34
|
+
option :attribute,
|
35
|
+
:short => "-a attribute",
|
36
|
+
:long => "--attribute attribute",
|
37
|
+
:description => "The name of the action e.g. HeapMemoryUsage (needed for read command)"
|
38
|
+
|
39
|
+
option :path,
|
40
|
+
:short => "-p path",
|
41
|
+
:long => "--path path",
|
42
|
+
:description => "The name of the path e.g. used (needed for read and list command)"
|
43
|
+
|
44
|
+
option :help,
|
45
|
+
:short => "-h",
|
46
|
+
:long => "--help",
|
47
|
+
:description => "Show this message",
|
48
|
+
:on => :tail,
|
49
|
+
:boolean => true,
|
50
|
+
:show_options => true,
|
51
|
+
:exit => 0
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'mixlib/cli'
|
2
|
+
require 'socket'
|
3
|
+
|
4
|
+
module ZabbixNudge
|
5
|
+
class NudgeCLI
|
6
|
+
include Mixlib::CLI
|
7
|
+
include Socket
|
8
|
+
|
9
|
+
option :config_file,
|
10
|
+
:short => "-c CONFIG",
|
11
|
+
:long => "--config CONFIG",
|
12
|
+
:default => '/etc/zabbix-nudge/config.rb',
|
13
|
+
:description => "The configuration file to use"
|
14
|
+
|
15
|
+
option :templates,
|
16
|
+
:short => "-t FILE",
|
17
|
+
:long => "--template FILE",
|
18
|
+
:default => File.join(ZabbixNudge.root,"examples"),
|
19
|
+
:description => "The template file(s) to use, can be a file a comma separated list of files or a directory",
|
20
|
+
:proc => Proc.new { |t| (t =~ /,/) ? t.split(',') : t }
|
21
|
+
|
22
|
+
option :zabbix_server_name,
|
23
|
+
:short => "-z SERVER",
|
24
|
+
:long => "--zabbix-server SERVER",
|
25
|
+
:default => 'localhost',
|
26
|
+
:description => "Hostname or IP address of Zabbix Server. Default is localhost"
|
27
|
+
|
28
|
+
option :zabbix_server_port,
|
29
|
+
:short => "-p SERVER PORT",
|
30
|
+
:long => "--port SERVER PORT",
|
31
|
+
:default => '10051',
|
32
|
+
:description => "Specify port number of server trapper running on the server. Default is 10051"
|
33
|
+
|
34
|
+
option :sender_hostname,
|
35
|
+
:short => "-s HOST",
|
36
|
+
:long => "--host HOSTNAME",
|
37
|
+
:default => Socket.gethostname,
|
38
|
+
:description => "Specify host name. Default is current hostname"
|
39
|
+
|
40
|
+
option :jolokia_hostname,
|
41
|
+
:short => "-P JHOSTNAME",
|
42
|
+
:long => "--jolokiahostname JHOSTNAME",
|
43
|
+
:default => "localhost",
|
44
|
+
:description => "Specify jolokia hostname. Default is localhost"
|
45
|
+
|
46
|
+
option :jolokia_port,
|
47
|
+
:short => "-P JPORT",
|
48
|
+
:long => "--jolokiaport JPORT",
|
49
|
+
:default => "8080",
|
50
|
+
:description => "Specify jolokia port. Default is 8080."
|
51
|
+
|
52
|
+
option :log_level,
|
53
|
+
:short => "-l LEVEL",
|
54
|
+
:long => "--log_level LEVEL",
|
55
|
+
:description => "Set the log level (debug, info, warn, error, fatal)",
|
56
|
+
:proc => Proc.new { |l| l.to_sym }
|
57
|
+
|
58
|
+
option :show_send_values,
|
59
|
+
:short => "-v",
|
60
|
+
:long => "--show_send_values",
|
61
|
+
:description => "shows what values got send to zabbix",
|
62
|
+
:boolean => true
|
63
|
+
|
64
|
+
option :help,
|
65
|
+
:short => "-h",
|
66
|
+
:long => "--help",
|
67
|
+
:description => "Show this message",
|
68
|
+
:on => :tail,
|
69
|
+
:boolean => true,
|
70
|
+
:show_options => true,
|
71
|
+
:exit => 0
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
HTTP/1.1 200 OK
|
2
|
+
Server: Apache-Coyote/1.1
|
3
|
+
Content-Type: text/plain;charset=utf-8
|
4
|
+
Content-Length: 512
|
5
|
+
Date: Wed, 15 Jun 2011 15:17:12 GMT
|
6
|
+
|
7
|
+
[{"timestamp":1308151032,"status":200,"request":{"mbean":"java.lang:name=CMS Perm Gen,type=MemoryPool","path":"committed","attribute":"Usage","type":"read"},"value":31518720},{"timestamp":1308151032,"status":200,"request":{"mbean":"java.lang:name=CMS Perm Gen,type=MemoryPool","path":"max","attribute":"Usage","type":"read"},"value":67108864},{"timestamp":1308151032,"status":200,"request":{"mbean":"java.lang:name=CMS Perm Gen,type=MemoryPool","path":"used","attribute":"Usage","type":"read"},"value":18890360}]
|
@@ -0,0 +1,92 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<zabbix_export version="1.0" date="22.12.07" time="03.42">
|
3
|
+
<hosts>
|
4
|
+
<host name="Template_Tomcat">
|
5
|
+
<proxy_hostid>0</proxy_hostid>
|
6
|
+
<useip>0</useip>
|
7
|
+
<dns/>
|
8
|
+
<ip>0.0.0.0</ip>
|
9
|
+
<port>0</port>
|
10
|
+
<status>3</status>
|
11
|
+
<groups>
|
12
|
+
<group>Templates</group>
|
13
|
+
<group>Web Server</group>
|
14
|
+
</groups>
|
15
|
+
<items>
|
16
|
+
<item type="7" key="jmx[java.lang:name=CMS Perm Gen,type=MemoryPool;Usage;committed]" value_type="3">
|
17
|
+
<description>memorypool cms perm gen committed</description>
|
18
|
+
<delay>30</delay>
|
19
|
+
<history>90</history>
|
20
|
+
<trends>365</trends>
|
21
|
+
<units>B</units>
|
22
|
+
<formula>1</formula>
|
23
|
+
<snmp_community>public</snmp_community>
|
24
|
+
<snmp_oid>interfaces.ifTable.ifEntry.ifInOctets.1</snmp_oid>
|
25
|
+
<snmp_port>161</snmp_port>
|
26
|
+
</item>
|
27
|
+
<item type="7" key="jmx[java.lang:name=CMS Perm Gen,type=MemoryPool;Usage;max]" value_type="3">
|
28
|
+
<description>memorypool cms perm gen max</description>
|
29
|
+
<delay>3600</delay>
|
30
|
+
<history>90</history>
|
31
|
+
<trends>365</trends>
|
32
|
+
<units>B</units>
|
33
|
+
<formula>1</formula>
|
34
|
+
<snmp_community>public</snmp_community>
|
35
|
+
<snmp_oid>interfaces.ifTable.ifEntry.ifInOctets.1</snmp_oid>
|
36
|
+
<snmp_port>161</snmp_port>
|
37
|
+
</item>
|
38
|
+
<item type="7" key="jmx[java.lang:name=CMS Perm Gen,type=MemoryPool;Usage;used]" value_type="3">
|
39
|
+
<description>memorypool cms perm gen used</description>
|
40
|
+
<delay>30</delay>
|
41
|
+
<history>90</history>
|
42
|
+
<trends>365</trends>
|
43
|
+
<units>B</units>
|
44
|
+
<formula>1</formula>
|
45
|
+
<snmp_community>public</snmp_community>
|
46
|
+
<snmp_oid>interfaces.ifTable.ifEntry.ifInOctets.1</snmp_oid>
|
47
|
+
<snmp_port>161</snmp_port>
|
48
|
+
</item>
|
49
|
+
</items>
|
50
|
+
<triggers/>
|
51
|
+
<graphs>
|
52
|
+
<graph name="memorypool cms perm gen" width="900" height="200">
|
53
|
+
<show_work_period>1</show_work_period>
|
54
|
+
<show_triggers>1</show_triggers>
|
55
|
+
<ymin_type>0</ymin_type>
|
56
|
+
<ymax_type>0</ymax_type>
|
57
|
+
<ymin_item_key></ymin_item_key>
|
58
|
+
<ymax_item_key></ymax_item_key>
|
59
|
+
<show_work_period>0</show_work_period>
|
60
|
+
<show_triggers>0</show_triggers>
|
61
|
+
<graphtype>1</graphtype>
|
62
|
+
<yaxismin>0.0000</yaxismin>
|
63
|
+
<yaxismax>100.0000</yaxismax>
|
64
|
+
<show_legend>0</show_legend>
|
65
|
+
<show_3d>0</show_3d>
|
66
|
+
<percent_left>0.0000</percent_left>
|
67
|
+
<percent_right>0.0000</percent_right>
|
68
|
+
<graph_elements>
|
69
|
+
<graph_element item="{HOSTNAME}:jmx[java.lang:name=CMS Perm Gen,type=MemoryPool;Usage;committed]">
|
70
|
+
<color>000099</color>
|
71
|
+
<yaxisside>1</yaxisside>
|
72
|
+
<calc_fnc>2</calc_fnc>
|
73
|
+
<periods_cnt>5</periods_cnt>
|
74
|
+
</graph_element>
|
75
|
+
<graph_element item="{HOSTNAME}:jmx[java.lang:name=CMS Perm Gen,type=MemoryPool;Usage;max]">
|
76
|
+
<color>990000</color>
|
77
|
+
<yaxisside>1</yaxisside>
|
78
|
+
<calc_fnc>2</calc_fnc>
|
79
|
+
<periods_cnt>5</periods_cnt>
|
80
|
+
</graph_element>
|
81
|
+
<graph_element item="{HOSTNAME}:jmx[java.lang:name=CMS Perm Gen,type=MemoryPool;Usage;used]">
|
82
|
+
<color>009900</color>
|
83
|
+
<yaxisside>1</yaxisside>
|
84
|
+
<calc_fnc>2</calc_fnc>
|
85
|
+
<periods_cnt>5</periods_cnt>
|
86
|
+
</graph_element>
|
87
|
+
</graph_elements>
|
88
|
+
</graph>
|
89
|
+
</graphs>
|
90
|
+
</host>
|
91
|
+
</hosts>
|
92
|
+
</zabbix_export>
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
$: << File.join(File.dirname(__FILE__), "/../lib")
|
4
|
+
require 'zabbix_nudge'
|
5
|
+
require 'fakeweb'
|
6
|
+
|
7
|
+
FakeWeb.allow_net_connect = false
|
8
|
+
|
9
|
+
def fixture_file(filename)
|
10
|
+
return '' if filename == ''
|
11
|
+
file_path = File.expand_path(File.dirname(__FILE__) + '/fixtures/' + filename)
|
12
|
+
File.read(file_path)
|
13
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), "/spec_helper")
|
4
|
+
require 'ap'
|
5
|
+
|
6
|
+
describe ZabbixNudge::Nudge do
|
7
|
+
|
8
|
+
context 'Initialization' do
|
9
|
+
|
10
|
+
FakeWeb.register_uri(:post, "http://localhost:4568/jolokia", :response => fixture_file("cms_perm_response.txt"))
|
11
|
+
|
12
|
+
it 'should accept a template file' do
|
13
|
+
@m = ZabbixNudge::Nudge.new(File.join(File.dirname(__FILE__), 'fixtures/tomcat_template.xml'),:jmx => {:base_uri => "http://localhost:4568"})
|
14
|
+
@m.send.should == {"jmx[java.lang:name=CMS Perm Gen,type=MemoryPool;Usage;max]"=>67108864, "jmx[java.lang:name=CMS Perm Gen,type=MemoryPool;Usage;used]"=>18890360, "jmx[java.lang:name=CMS Perm Gen,type=MemoryPool;Usage;committed]"=>31518720}
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'process items' do
|
21
|
+
|
22
|
+
|
23
|
+
before(:each) do
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should get the title" do
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
$:.push File.expand_path("../lib", __FILE__)
|
4
|
+
require "zabbix_nudge/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "zabbix_nudge"
|
8
|
+
s.version = ZabbixNudge::VERSION
|
9
|
+
s.authors = ["Myroslav Rys"]
|
10
|
+
s.email = ["stonevil@gmail.com"]
|
11
|
+
s.homepage = "http://www.stone.org.ua"
|
12
|
+
s.license = 'GPL'
|
13
|
+
|
14
|
+
s.summary = %q{Collect metrics from different sources and push (nudge) data to Zabbix}
|
15
|
+
s.description = %q{zabbix-nudge is a gem to collect metrics from different sources, parse zabbix templates and push (nudge) the data to zabbix proxy or server}
|
16
|
+
|
17
|
+
s.rubyforge_project = "zabbix-nudge"
|
18
|
+
|
19
|
+
s.files = `git ls-files`.split("\n")
|
20
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
21
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
22
|
+
s.require_paths = ["lib"]
|
23
|
+
|
24
|
+
s.add_dependency 'nokogiri', '~> 1.4.4'
|
25
|
+
s.add_dependency 'zabbix', '~> 0.3.0'
|
26
|
+
s.add_dependency 'httparty', '~> 0.7.8'
|
27
|
+
s.add_dependency 'activesupport', '~> 3.0.8'
|
28
|
+
s.add_dependency "i18n", "~> 0.6.0"
|
29
|
+
s.add_dependency 'yajl-ruby', '~> 0.8.2'
|
30
|
+
s.add_dependency "awesome_print", "~> 0.4.0"
|
31
|
+
s.add_dependency "mixlib-cli", "~> 1.2.0"
|
32
|
+
s.add_dependency "daemons", "~> 1.1.9"
|
33
|
+
|
34
|
+
s.add_development_dependency 'rspec', '~> 2.6.0'
|
35
|
+
s.add_development_dependency 'fakeweb', '~> 1.3.0'
|
36
|
+
|
37
|
+
end
|