rubix 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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
- # We can check for errors, whether they are non-200 responses or 200
92
- responses with a Zabbix API error.
93
- puts response.error_message unless response.success?
94
-
95
- # See the result
96
- puts response.result
97
- #=> [{"hostid"=>"10017"}]
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.new(:name => "My Zabbix Hosts")
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.create unless template.exists?
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
- # 'register' means the same as 'create unless exist' above...
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.register
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.register
147
+ item.save
141
148
 
142
- You can also +update+, +destroy+ or +unregister+ ('destroy if exists')
143
- resources.
149
+ You can also +update+ and +destroy+ resources.
144
150
 
145
- Only host groups, templates, hosts, applications, and items are
146
- available at present. Other Zabbix resources (actions, alerts,
147
- events, maps, users, &c.) can be similarly wrapped, they just haven't
148
- been because we don't use them as much as we use these core resources.
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; try the <tt>--help</tt> option.)
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 copy of +zabbix_pipe+. Once development/deployment is
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 using production mode.
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.4
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
- HOSTGROUP = 'Elasticsearch clusters'
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
- :application => "_cluster",
52
+ :hostgroup => self.class::CLUSTER_HOSTGROUPS
49
53
  :templates => self.class::CLUSTER_TEMPLATES,
50
- :hostgroup => self.class::HOSTGROUP
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
- :appliation => index_name,
77
+ :hostgroup => self.class::CLUStER_HOSTGROUP,
74
78
  :templates => self.class::CLUSTER_TEMPLATES,
75
- :hostgroup => self.class::HOSTGROUP
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
- :application => "Elasticsearch",
106
- :templates => self.class::NODE_TEMPLATES
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
- require 'zabbix_cluster_monitor'
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 < ZabbixClusterMonitor
10
+ class HBaseMonitor < Rubix::ClusterMonitor
8
11
 
9
12
  # Hostgroups for clusters & hosts that need to be created.
10
- CLUSTER_HOSTGROUP = 'HBase clusters'
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
- :application => '_cluster',
49
- :hostgroup => 'HBase Clusters',
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 => "HBase",
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
- require 'zabbix_cluster_monitor'
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 < ZabbixClusterMonitor
11
+ class MongoMonitor < Rubix::ClusterMonitor
9
12
 
10
13
  # Hostgroup for any hosts that needs to be created.
11
- HOSTGROUP = 'MongoDB clusters'
14
+ CLUSTER_HOSTGROUPS = 'MongoDB clusters'
12
15
 
13
16
  # Templates for any hosts that need to be created.
14
- TEMPLATES = 'Template_MongoDB'
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
- :hostname => "#{cluster_name}-mongodb",
50
- :application => '_cluster',
51
- :hostgroup => self.class::HOSTGROUP,
52
- :templates => self.class::TEMPLATES
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
- :hostname => "#{cluster_name}-mongodb",
106
- :application => database_name,
107
- :hostgroup => self.class::HOSTGROUP,
108
- :templates => self.class::TEMPLATES
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: 23
4
+ hash: 21
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 4
10
- version: 0.0.4
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-21 00:00:00 Z
18
+ date: 2011-11-22 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: rspec