rubix 0.0.4 → 0.0.5
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/README.rdoc +117 -26
- data/VERSION +1 -1
- data/lib/rubix/examples/es_monitor.rb +11 -7
- data/lib/rubix/examples/hbase_monitor.rb +13 -6
- data/lib/rubix/examples/mongo_monitor.rb +18 -13
- metadata +4 -4
data/README.rdoc
CHANGED
@@ -22,6 +22,8 @@ few goals:
|
|
22
22
|
- Have as few dependencies as possible: the core classes only depend
|
23
23
|
on Ruby 1.8 standard library & +JSON+ and scripts additionally
|
24
24
|
depend on +Configliere+[http://github.com/mrflip/configliere].
|
25
|
+
|
26
|
+
- Play nicely with Chef[http://www.opscode.com/chef/]
|
25
27
|
|
26
28
|
There are a lot of other projects out there that connect Ruby to
|
27
29
|
Zabbix. Here's a quick list:
|
@@ -88,14 +90,21 @@ quietly for you:
|
|
88
90
|
|
89
91
|
response = Rubix.connection.request('host.get', 'filter' => { 'host' => 'My Zabbix Host' })
|
90
92
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
93
|
+
case
|
94
|
+
when response.has_data?
|
95
|
+
# Response is a success and "has data" -- it's not empty. This
|
96
|
+
# means we found our host.
|
97
|
+
puts response.result
|
98
|
+
#=> [{"hostid"=>"10017"}]
|
99
|
+
when response.success?
|
100
|
+
# Response was succssful but doesn't "have data" -- it's empty, no
|
101
|
+
# such host!
|
102
|
+
puts "No such host"
|
103
|
+
else
|
104
|
+
# Response was an error. Uh oh!
|
105
|
+
puts response.error_message
|
106
|
+
end
|
107
|
+
|
99
108
|
=== On the command line
|
100
109
|
|
101
110
|
Rubix comes with a command line utility +zabbix_api+ which lets you
|
@@ -105,7 +114,7 @@ issue these sorts of requests directly on the command line.
|
|
105
114
|
[{"hostid"=>"10017"}]
|
106
115
|
|
107
116
|
+zabbix_api+ lets you specify the credentials and will pretty-print
|
108
|
-
responses for you.
|
117
|
+
responses for you. Try <tt>zabbix_api --help</tt> for more details.
|
109
118
|
|
110
119
|
== ORM
|
111
120
|
|
@@ -119,33 +128,31 @@ complete with host groups, templates, applications, and so on.
|
|
119
128
|
Rubix.connect('http://localhost/api_jsonrpc.php', 'admin', 'zabbix')
|
120
129
|
|
121
130
|
# Ensure the host group we want exists.
|
122
|
-
host_group = Rubix::HostGroup.
|
123
|
-
host_group.create unless host_group.exists?
|
131
|
+
host_group = Rubix::HostGroup.find_or_create(:name => "My Zabbix Hosts")
|
124
132
|
|
125
133
|
# Now the template -- created templates are empty by default!
|
126
134
|
template = Rubix::Template.new(:name => "Template_Some_Service")
|
127
|
-
template.
|
135
|
+
template.save
|
128
136
|
|
129
137
|
# Now the host.
|
130
138
|
host = Rubix::Host.new(:name => "My Host", :ip => '123.123.123.123', :templates => [template], :host_groups => [host_group])
|
131
|
-
|
132
|
-
host.register
|
139
|
+
host.save
|
133
140
|
|
134
141
|
# Now for the application
|
135
142
|
app = Rubix::Application.new(:name => 'Some App', :host => host)
|
136
|
-
app.
|
143
|
+
app.save
|
137
144
|
|
138
145
|
# Now the item
|
139
146
|
item = Rubix::Item.new(:host => host, :key => 'foo.bar.baz', :description => "Some Item", :value_type => :unsigned_int, :applications => [app])
|
140
|
-
item.
|
147
|
+
item.save
|
141
148
|
|
142
|
-
You can also +update
|
143
|
-
resources.
|
149
|
+
You can also +update+ and +destroy+ resources.
|
144
150
|
|
145
|
-
Only host groups, templates, hosts, applications,
|
146
|
-
available at present. Other Zabbix resources (actions,
|
147
|
-
events, maps, users, &c.) can be similarly wrapped, they just
|
148
|
-
been because we don't use them as much as we use these
|
151
|
+
Only host groups, templates, hosts, applications, user macros, and
|
152
|
+
items are available at present. Other Zabbix resources (actions,
|
153
|
+
alerts, events, maps, users, &c.) can be similarly wrapped, they just
|
154
|
+
haven't been yet because we don't use them as much as we use these
|
155
|
+
core resources.
|
149
156
|
|
150
157
|
== Sender
|
151
158
|
|
@@ -165,9 +172,9 @@ data one line at a time from any of these sources and uses the
|
|
165
172
|
|
166
173
|
Here's an example of starting +zabbix_pipe+ and sending some data onto
|
167
174
|
Zabbix. (Credentials and addresses for the Zabbix server and the
|
168
|
-
Zabbix API can all be customized;
|
175
|
+
Zabbix API can all be customized; see the <tt>--help</tt> option.)
|
169
176
|
|
170
|
-
# Send one data point
|
177
|
+
# Send one data point -- this is tab separated!
|
171
178
|
$ echo "foo.bar.baz 123" | zabbix_pipe --host='My Zabbix Host'
|
172
179
|
# Send a bunch of data points in a file
|
173
180
|
$ cat my_data.tsv | zabbix_pipe --host='My Zabbix Host'
|
@@ -254,9 +261,93 @@ itself.
|
|
254
261
|
|
255
262
|
A good pattern is to set up a production pipe (in <tt>--fast</tt>)
|
256
263
|
mode at <tt>/dev/zabbix</tt> and to do all development/deployment with
|
257
|
-
a separate
|
264
|
+
a separate instance of +zabbix_pipe+. Once development/deployment is
|
258
265
|
complete and all hosts, groups, templates, applications, and items
|
259
|
-
have been created, switch to
|
266
|
+
have been created, switch to writing all data in "production mode"
|
267
|
+
using the <tt>--fast</tt> pipe at <tt>/dev/zabbix</tt>.
|
260
268
|
|
261
269
|
== Monitors
|
262
270
|
|
271
|
+
Rubix also comes with some classes that make it easy to write simple
|
272
|
+
monitors. The output of these monitors should match the expected
|
273
|
+
input format of +zabbix_pipe+. This way they can be chained together.
|
274
|
+
Here's an example of a simple monitor that calculates the currently
|
275
|
+
used memory in bytes.
|
276
|
+
|
277
|
+
# in memory_monitor.rb
|
278
|
+
require 'rubix'
|
279
|
+
|
280
|
+
class MemoryMonitor < Rubix::Monitor
|
281
|
+
def measure
|
282
|
+
write do |data|
|
283
|
+
mem_used = `free | tail -n+2 | head -n1`.chomp.split[2].to_i
|
284
|
+
data << [['mem.used', mem_used]]
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
MemoryMonitor.run if $0 == __FILE__
|
290
|
+
|
291
|
+
The file <tt>memory_monitor.rb</tt> can now be run on the command line in
|
292
|
+
various ways:
|
293
|
+
|
294
|
+
# Write the output to STDOUT
|
295
|
+
$ ruby memory_monitor.rb
|
296
|
+
'mem.used' 11595908
|
297
|
+
|
298
|
+
# Loop every 30 seconds
|
299
|
+
$ ruby memory_monitor.rb --loop=30
|
300
|
+
|
301
|
+
'mem.used' 11595760
|
302
|
+
'mem.used' 11595800
|
303
|
+
'mem.used' 11596016
|
304
|
+
'mem.used' 11596008
|
305
|
+
|
306
|
+
It can be piped into a running +zabbix_pipe+:
|
307
|
+
|
308
|
+
$ ruby memory_monitor.rb --loop=30 > /dev/zabbix &
|
309
|
+
|
310
|
+
=== Monitors with Chef
|
311
|
+
|
312
|
+
It's useful to be able to monitor resources defined in
|
313
|
+
Chef[http://www.opscode.com/chef/] and so Rubix comes with a
|
314
|
+
+ChefMonitor+ class.
|
315
|
+
|
316
|
+
# in webserver_monitor.rb
|
317
|
+
require 'rubix'
|
318
|
+
require 'net/http'
|
319
|
+
require 'uri'
|
320
|
+
|
321
|
+
class WebserverMonitor < Rubix::ChefMonitor
|
322
|
+
|
323
|
+
def webserver
|
324
|
+
@webserver ||= chef_node_from_node_name('my_webserver')
|
325
|
+
end
|
326
|
+
|
327
|
+
def uri
|
328
|
+
URI.parse("http://#{webserver['ec2']['public_hostname']}")
|
329
|
+
end
|
330
|
+
|
331
|
+
def measure
|
332
|
+
begin
|
333
|
+
if Net::HTTP.get_response(uri).code.to_i == 200
|
334
|
+
availability = 1
|
335
|
+
else
|
336
|
+
availability = 0
|
337
|
+
end
|
338
|
+
rescue => e
|
339
|
+
availability = 0
|
340
|
+
end
|
341
|
+
write do |data|
|
342
|
+
data << ([['webserver.available', availability]])
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
WebserverMonitor.run if $0 == __FILE__
|
348
|
+
|
349
|
+
To run this monitor you'll have to pass in credentials used to authenticate with Chef:
|
350
|
+
|
351
|
+
$ sudo ruby webserver_monitor.rb --chef_server_url=http://api.opscode.com/organizations/my_company --chef_node_name=this_node --chef_client_key=/etc/chef/client.pem --loop=30 > /dev/zabbix
|
352
|
+
|
353
|
+
Make sure you can read the file at <tt>/etc/chef/client.pem</tt>!
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.5
|
@@ -9,11 +9,15 @@ require 'open-uri'
|
|
9
9
|
class ESMonitor < Rubix::ClusterMonitor
|
10
10
|
|
11
11
|
# Hostgroup for any hosts that needs to be created.
|
12
|
-
|
12
|
+
CLUSTER_HOSTGROUPS = 'Elasticsearch clusters'
|
13
13
|
|
14
14
|
# Templates for any hosts that need to be created.
|
15
15
|
CLUSTER_TEMPLATES = 'Template_Elasticsearch_Cluster'
|
16
16
|
NODE_TEMPLATES = 'Template_Elasticsearch_Node'
|
17
|
+
|
18
|
+
# Applications for new items
|
19
|
+
CLUSTER_APPLICATIONS = '_cluster'
|
20
|
+
NODE_APPLICATIONS = 'Elasticsearch'
|
17
21
|
|
18
22
|
def node_query
|
19
23
|
'provides_service:*-elasticsearch'
|
@@ -45,9 +49,9 @@ class ESMonitor < Rubix::ClusterMonitor
|
|
45
49
|
end
|
46
50
|
write({
|
47
51
|
:hostname => "#{cluster_name}-elasticsearch",
|
48
|
-
:
|
52
|
+
:hostgroup => self.class::CLUSTER_HOSTGROUPS
|
49
53
|
:templates => self.class::CLUSTER_TEMPLATES,
|
50
|
-
:
|
54
|
+
:application => self.class::CLUSTER_APPLICATIONS
|
51
55
|
}) do |d|
|
52
56
|
d << ['status', cluster_health['status'] ]
|
53
57
|
d << ['nodes.total', cluster_health['number_of_nodes'] ]
|
@@ -70,9 +74,9 @@ class ESMonitor < Rubix::ClusterMonitor
|
|
70
74
|
index_data['indices'].each_pair do |index_name, index_data|
|
71
75
|
write({
|
72
76
|
:hostname => "#{cluster_name}-elasticsearch",
|
73
|
-
:
|
77
|
+
:hostgroup => self.class::CLUStER_HOSTGROUP,
|
74
78
|
:templates => self.class::CLUSTER_TEMPLATES,
|
75
|
-
:
|
79
|
+
:appliation => index_name
|
76
80
|
}) do |d|
|
77
81
|
d << ["#{index_name}.size", index_data["index"]["size_in_bytes"] ]
|
78
82
|
d << ["#{index_name}.docs.num", index_data["docs"]["num_docs"] ]
|
@@ -102,8 +106,8 @@ class ESMonitor < Rubix::ClusterMonitor
|
|
102
106
|
next unless node_name
|
103
107
|
write({
|
104
108
|
:hostname => node_name,
|
105
|
-
:
|
106
|
-
:
|
109
|
+
:templates => self.class::NODE_TEMPLATES,
|
110
|
+
:application => self.class::NODE_APPLICATIONS
|
107
111
|
}) do |d|
|
108
112
|
# concurrency
|
109
113
|
d << ['es.jvm.threads.count', stats['jvm']['threads']['count'] ]
|
@@ -1,18 +1,25 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
3
|
+
RUBIX_ROOT = File.expand_path('../../../../lib', __FILE__)
|
4
|
+
$: << RUBIX_ROOT unless $:.include?(RUBIX_ROOT)
|
5
|
+
|
6
|
+
require 'rubix'
|
4
7
|
require 'net/http'
|
5
8
|
require 'crack'
|
6
9
|
|
7
|
-
class HBaseMonitor <
|
10
|
+
class HBaseMonitor < Rubix::ClusterMonitor
|
8
11
|
|
9
12
|
# Hostgroups for clusters & hosts that need to be created.
|
10
|
-
|
13
|
+
CLUSTER_HOSTGROUPS = 'HBase clusters'
|
11
14
|
|
12
15
|
# Templates for any hosts that need to be created.
|
13
16
|
CLUSTER_TEMPLATES = 'Template_HBase_Cluster'
|
14
17
|
NODE_TEMPLATES = 'Template_HBase_Node'
|
15
18
|
|
19
|
+
# Applications for items that are written
|
20
|
+
CLUSTER_APPLICATIONS = '_cluster'
|
21
|
+
NODE_APPLICATIONS = "Hbase"
|
22
|
+
|
16
23
|
def matching_chef_nodes
|
17
24
|
Chef::Search::Query.new.search('node', 'provides_service:*hbase-stargate AND facet_name:alpha')
|
18
25
|
end
|
@@ -45,8 +52,8 @@ class HBaseMonitor < ZabbixClusterMonitor
|
|
45
52
|
|
46
53
|
write({
|
47
54
|
:hostname => "#{cluster_name}-hbase",
|
48
|
-
:
|
49
|
-
:
|
55
|
+
:hostgroup => self.class::CLUSTER_HOSTGROUPS,
|
56
|
+
:application => self.class::CLUSTER_APPLICATIONS,
|
50
57
|
:templates => self.class::CLUSTER_TEMPLATES
|
51
58
|
}) do |d|
|
52
59
|
d << ['requests', cluster_status['requests']]
|
@@ -72,7 +79,7 @@ class HBaseMonitor < ZabbixClusterMonitor
|
|
72
79
|
next unless node_name
|
73
80
|
write({
|
74
81
|
:hostname => node_name,
|
75
|
-
:application =>
|
82
|
+
:application => self.class::NODE_APPLICATIONS,
|
76
83
|
:templates => self.class::NODE_TEMPLATES
|
77
84
|
}) do |d|
|
78
85
|
d << ['hbase.regions', (live_node['Region'] || []).size]
|
@@ -1,17 +1,23 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
3
|
+
RUBIX_ROOT = File.expand_path('../../../../lib', __FILE__)
|
4
|
+
$: << RUBIX_ROOT unless $:.include?(RUBIX_ROOT)
|
5
|
+
|
6
|
+
require 'rubix'
|
4
7
|
require 'open-uri'
|
5
8
|
require 'set'
|
6
9
|
require 'mongo'
|
7
10
|
|
8
|
-
class MongoMonitor <
|
11
|
+
class MongoMonitor < Rubix::ClusterMonitor
|
9
12
|
|
10
13
|
# Hostgroup for any hosts that needs to be created.
|
11
|
-
|
14
|
+
CLUSTER_HOSTGROUPS = 'MongoDB clusters'
|
12
15
|
|
13
16
|
# Templates for any hosts that need to be created.
|
14
|
-
|
17
|
+
CLUSTER_TEMPLATES = 'Template_MongoDB'
|
18
|
+
|
19
|
+
# Applications
|
20
|
+
CLUSTER_APPLICATIONS = '_cluster'
|
15
21
|
|
16
22
|
# Names of database to ignore when we find them.
|
17
23
|
IGNORED_DATABASES = %w[db test admin local].to_set
|
@@ -44,12 +50,11 @@ class MongoMonitor < ZabbixClusterMonitor
|
|
44
50
|
initial = db.command(command) ; sleep 1.0 ; final = db.command(command)
|
45
51
|
return false unless initial && final
|
46
52
|
dt = final['localTime'].to_f - initial['localTime'].to_f
|
47
|
-
|
48
53
|
write({
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
54
|
+
:hostname => "#{cluster_name}-mongodb",
|
55
|
+
:hostgroup => self.class::CLUSTER_HOSTGROUPS,
|
56
|
+
:templates => self.class::CLUSTER_TEMPLATES,
|
57
|
+
:application => self.class::CLUSTER_APPLICATIONS
|
53
58
|
}) do |d|
|
54
59
|
|
55
60
|
# operations
|
@@ -102,10 +107,10 @@ class MongoMonitor < ZabbixClusterMonitor
|
|
102
107
|
stats = connection.db(database_name).stats()
|
103
108
|
|
104
109
|
write({
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
110
|
+
:hostname => "#{cluster_name}-mongodb",
|
111
|
+
:hostgroup => self.class::CLUSTER_HOSTGROUPS,
|
112
|
+
:templates => self.class::CLUSTER_TEMPLATES,
|
113
|
+
:application => database_name
|
109
114
|
}) do |d|
|
110
115
|
d << ["#{database_name}.collections", stats["collections"] ]
|
111
116
|
d << ["#{database_name}.objects.count", stats["objects"] ]
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubix
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 5
|
10
|
+
version: 0.0.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Dhruv Bansal
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-11-
|
18
|
+
date: 2011-11-22 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: rspec
|