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 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