riemann-tools 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'fog'
4
+ require 'date'
5
+
6
+ require File.expand_path('../../lib/riemann/tools', __FILE__)
7
+
8
+ $0 = __FILE__ # Let's not expose our AWS keys in the process list
9
+
10
+ class Riemann::Tools::AWS
11
+ include Riemann::Tools
12
+
13
+ opt :access_key, "AWS access key", :type => String
14
+ opt :secret_key, "Secret access key", :type => String
15
+ opt :region, "AWS region", :type => String, :default => 'eu-west-1'
16
+
17
+ opt :retirement_critical, "Number of days before retirement. Defaults to 2", :default => 2
18
+ opt :event_warning, "Number of days before event. Defaults to nil (i.e. when the event appears)", :default => nil
19
+
20
+ def initialize
21
+ @compute = Fog::Compute.new(:aws_access_key_id => opts[:access_key],
22
+ :aws_secret_access_key => opts[:secret_key],
23
+ :region => opts[:region],
24
+ :provider => 'AWS')
25
+ end
26
+
27
+ def tick
28
+ instance_status = @compute.describe_instance_status.body["instanceStatusSet"]
29
+ status = instance_status.inject({}) do |acc,i|
30
+ acc[i.delete("instanceId")] = i
31
+ acc
32
+ end
33
+
34
+ hosts = @compute.servers.select { |s| s.state == "running" }.
35
+ inject([status, {}]) do |(status, acc), host|
36
+ acc[host.private_dns_name] = status.delete(host.id); [status, acc]
37
+ end[1]
38
+
39
+ hosts.each do |host, status|
40
+ status['eventsSet'].each do |event|
41
+ before, after = ['notBefore', 'notAfter'].map { |k| Date.parse event[k].to_s if event[k] }
42
+
43
+ ev = {:host => host,
44
+ :service => "aws_instance_status",
45
+ :description => "#{event['code']}\n\nstart #{event['notBefore']}\nend #{event['notAfter']}\n\n#{event['description']}",
46
+ :state => "ok",
47
+ :ttl => 300}
48
+
49
+ ev2 = if (event['code'] == 'instance-retirement') and
50
+ Date.today >= before-opts[:retirement_critical]
51
+ {:state => "critical"}
52
+ elsif opts[:event_warning] and Date.today >= before-opts[:event_warning]
53
+ {:state => "warning"}
54
+ else
55
+ {:state => "warning"}
56
+ end
57
+
58
+ report ev.merge(ev2)
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ Riemann::Tools::AWS.run
data/bin/riemann-bench CHANGED
@@ -3,6 +3,7 @@
3
3
  # Connects to a server (first arg) and populates it with a constant stream of
4
4
  # events for testing.
5
5
 
6
+ require 'rubygems'
6
7
  require 'riemann/client'
7
8
  require 'pp'
8
9
 
@@ -13,7 +14,7 @@ class Riemann::Bench
13
14
  @hosts = %w(a b c d e f g h i j)
14
15
  @services = %w(test1 test2 test3 foo bar baz xyzzy attack cat treat)
15
16
  @states = {}
16
- @client = Riemann::Client.new(host: (ARGV.first || 'localhost'))
17
+ @client = Riemann::Client.new(:host => (ARGV.first || 'localhost'))
17
18
  end
18
19
 
19
20
  def evolve(state)
@@ -30,11 +31,11 @@ class Riemann::Bench
30
31
  end
31
32
 
32
33
  {
33
- metric: m,
34
- state: s,
35
- host: state[:host],
36
- service: state[:service],
37
- description: "at #{Time.now}"
34
+ :metric => m,
35
+ :state => s,
36
+ :host => state[:host],
37
+ :service => state[:service],
38
+ :description => "at #{Time.now}"
38
39
  }
39
40
  end
40
41
 
@@ -56,11 +57,11 @@ class Riemann::Bench
56
57
  def start
57
58
  hosts.product(services).each do |host, service|
58
59
  states[[host, service]] = {
59
- metric: 0.5,
60
- state: 'ok',
61
- description: "Starting up",
62
- host: host,
63
- service: service
60
+ :metric => 0.5,
61
+ :state => 'ok',
62
+ :description => "Starting up",
63
+ :host => host,
64
+ :service => service
64
65
  }
65
66
  end
66
67
  end
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path('../../lib/riemann/tools', __FILE__)
4
+
5
+ class Riemann::Tools::FreeSWITCH
6
+ include Riemann::Tools
7
+
8
+ def tick
9
+
10
+ #determine how many current calls I have according to FreeSWITCH
11
+ fs_calls = %x[fs_cli -x "show calls count"| grep -Po '^\\d+']
12
+
13
+ #determine how many current channels I have according to FreeSWITCH
14
+ fs_channels = %x[fs_cli -x "show channels count"| grep -Po '^\\d+']
15
+
16
+ #submit them to riemann
17
+ report(
18
+ :service => "FreeSWITCH current calls",
19
+ :metric => fs_calls.to_i,
20
+ :state => "info"
21
+ )
22
+
23
+ report(
24
+ :service => "FreeSWITCH current channels",
25
+ :metric => fs_channels.to_i,
26
+ :state => "info"
27
+ )
28
+ end
29
+ end
30
+
31
+ Riemann::Tools::FreeSWITCH.run
data/bin/riemann-health CHANGED
@@ -15,6 +15,7 @@ class Riemann::Tools::Health
15
15
  opt :load_critical, "Load critical threshold (load average / core)", :default => 8
16
16
  opt :memory_warning, "Memory warning threshold (fraction of RAM)", :default => 0.85
17
17
  opt :memory_critical, "Memory critical threshold (fraction of RAM)", :default => 0.95
18
+ opt :checks, "A list of checks to run.", :type => :strings, :default => ['cpu', 'load', 'memory', 'disk']
18
19
 
19
20
  def initialize
20
21
  @limits = {
@@ -45,9 +46,23 @@ class Riemann::Tools::Health
45
46
  @load = method :linux_load
46
47
  @memory = method :linux_memory
47
48
  end
49
+
50
+ opts[:checks].each do |check|
51
+ case check
52
+ when "disk"
53
+ @disk_enabled = true
54
+ when "load"
55
+ @load_enabled = true
56
+ when "cpu"
57
+ @cpu_enabled = true
58
+ when "memory"
59
+ @memory_enabled = true
60
+ end
61
+ end
48
62
  end
49
63
 
50
64
  def alert(service, state, metric, description)
65
+ puts service
51
66
  report(
52
67
  :service => service.to_s,
53
68
  :state => state.to_s,
@@ -238,10 +253,18 @@ class Riemann::Tools::Health
238
253
  end
239
254
 
240
255
  def tick
241
- @cpu.call
242
- @memory.call
243
- @disk.call
244
- @load.call
256
+ if @cpu_enabled
257
+ @cpu.call
258
+ end
259
+ if @memory_enabled
260
+ @memory.call
261
+ end
262
+ if @disk_enabled
263
+ @disk.call
264
+ end
265
+ if @load_enabled
266
+ @load.call
267
+ end
245
268
  end
246
269
  end
247
270
 
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Gathers nginx status stub statistics and submits them to Riemann.
4
+ # See http://wiki.nginx.org/HttpStubStatusModule for configuring Nginx appropriately
5
+
6
+ require File.expand_path('../../lib/riemann/tools', __FILE__)
7
+
8
+ class Riemann::Tools::NginxStatus
9
+ include Riemann::Tools
10
+ require 'net/http'
11
+ require 'uri'
12
+
13
+ opt :uri, "Nginx Stub Status URI", :default => 'http://localhost:8080/nginx_status'
14
+ opt :checks, "Which metrics to report.", :type => :strings, :default => %w{active accepted handled requests reading writing waiting}
15
+ opt :active_warning, "Active connections warning threshold", :default => 0
16
+ opt :active_critical, "Active connections critical threshold", :default => 0
17
+ opt :reading_warning, "Reading connections warning threshold", :default => 0
18
+ opt :reading_critical, "Reading connections critical threshold", :default => 0
19
+ opt :writing_warning, "Writing connections warning threshold", :default => 0
20
+ opt :writing_critical, "Writing connections critical threshold", :default => 0
21
+ opt :waiting_warning, "Waiting connections warning threshold", :default => 0
22
+ opt :waiting_critical, "Waiting connections critical threshold", :default => 0
23
+
24
+ def initialize
25
+ @uri = URI.parse(opts[:uri])
26
+
27
+ # sample response:
28
+ #
29
+ # Active connections: 1
30
+ # server accepts handled requests
31
+ # 39 39 39
32
+ # Reading: 0 Writing: 1 Waiting: 0
33
+ @keys = %w{active accepted handled requests reading writing waiting}
34
+ @re = /Active connections: (\d+) \n.+\n (\d+) (\d+) (\d+) \nReading: (\d+) Writing: (\d+) Waiting: (\d+)/m
35
+ end
36
+
37
+ def state(key, value)
38
+ if opts.has_key? "#{key}_critical".to_sym
39
+ critical_threshold = opts["#{key}_critical".to_sym]
40
+ return 'critical' if critical_threshold > 0 and value >= critical_threshold
41
+ end
42
+
43
+ if opts.has_key? "#{key}_warning".to_sym
44
+ warning_threshold = opts["#{key}_warning".to_sym]
45
+ return 'warning' if warning_threshold > 0 and value >= warning_threshold
46
+ end
47
+
48
+ return 'ok'
49
+ end
50
+
51
+ def tick
52
+ response = Net::HTTP.get(@uri)
53
+ values = @re.match(response).to_a[1,7].map { |v| v.to_i }
54
+
55
+ @keys.zip(values).each do |key, value|
56
+ report({
57
+ :service => "nginx #{key}",
58
+ :metric => value,
59
+ :state => state(key, value),
60
+ :tags => ['nginx']
61
+ })
62
+ end
63
+ end
64
+ end
65
+
66
+ Riemann::Tools::NginxStatus.run
data/bin/riemann-redis CHANGED
@@ -11,21 +11,47 @@ class Riemann::Tools::Redis
11
11
  opt :redis_host, "Redis hostname", :default => 'localhost'
12
12
  opt :redis_port, "Redis port", :default => 6379
13
13
  opt :redis_password, "Redis password", :default => ''
14
+ opt :redis_url, "Redis URL", :default => ''
15
+ opt :redis_socket, "Redis socket", :default => ''
16
+ opt :redis_section, "Redis INFO section", :default => 'default'
17
+
18
+ STRING_VALUES = %w{ redis_version redis_git_sha1 redis_mode os
19
+ multiplexing_api gcc_version run_id used_memory_human
20
+ used_memory_peak_human mem_allocator
21
+ rdb_last_bgsave_status aof_last_bgrewrite_status role }
14
22
 
15
23
  def initialize
16
- @redis = ::Redis.new(:host => opts[:redis_host], :port => opts[:redis_port])
24
+ options = if opts[:redis_url] != ''
25
+ { :url => opts[:redis_url] }
26
+ elsif opts[:redis_socket] != ''
27
+ { :path => opts[:redis_socket] }
28
+ else
29
+ { :host => opts[:redis_host], :port => opts[:redis_port] }
30
+ end
31
+ @redis = ::Redis.new(options)
17
32
  @redis.auth(opts[:redis_password]) unless opts[:redis_password] == ''
33
+ @section = opts[:redis_section]
18
34
  end
19
35
 
20
36
  def tick
21
- @redis.info.each do |property, value|
22
- report(
37
+ @redis.info(@section).each do |property, value|
38
+ data = {
23
39
  :host => opts[:redis_host],
24
40
  :service => "redis #{property}",
25
41
  :metric => value.to_f,
26
42
  :state => 'ok',
27
43
  :tags => ['redis']
28
- )
44
+ }
45
+
46
+ if STRING_VALUES.include?(property) || property.match(/^db\d+/)
47
+ if %w{ rdb_last_bgsave_status aof_last_bgrewrite_status }.include?(property)
48
+ data[:state] = value
49
+ else
50
+ data[:description] = value
51
+ end
52
+ end
53
+
54
+ report(data)
29
55
  end
30
56
  end
31
57
 
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Gathers Redis SLOWLOG statistics and submits them to Riemann.
4
+
5
+ require File.expand_path('../../lib/riemann/tools', __FILE__)
6
+
7
+ class Riemann::Tools::RedisSlowlog
8
+ include Riemann::Tools
9
+ require 'redis'
10
+
11
+ opt :redis_url, "Redis URL", :default => 'redis://127.0.0.1:6379/'
12
+ opt :redis_password, "Redis password", :default => ''
13
+ opt :slowlog_len, "Number of SLOWLOG entries to get", :default => 10
14
+ opt :slowlog_reset, "Reset SLOWLOG after querying it", :default => false
15
+
16
+ def initialize
17
+ @redis = ::Redis.new(url: opts[:redis_url])
18
+
19
+ @slowlog_len = opts[:slowlog_len]
20
+ @slowlog_reset = opts[:slowlog_reset]
21
+
22
+ @redis.auth(opts[:redis_password]) unless opts[:redis_password] == ''
23
+ end
24
+
25
+ def tick
26
+ @redis.slowlog("GET", @slowlog_len).each do |id, timestamp, us, cmd|
27
+ data = {
28
+ :host => @redis.client.host,
29
+ :service => "redis",
30
+ :time => timestamp,
31
+ :metric => us.to_f,
32
+ :state => 'warning',
33
+ :tags => ['redis', 'slowlog'],
34
+ :description => cmd.inspect
35
+ }
36
+ report(data)
37
+ end
38
+
39
+ @redis.slowlog("RESET") if @slowlog_reset
40
+ end
41
+
42
+ end
43
+
44
+ Riemann::Tools::RedisSlowlog.run
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path('../../lib/riemann/tools', __FILE__)
4
+
5
+ class Riemann::Tools::Resmon
6
+ include Riemann::Tools
7
+ require 'nokogiri'
8
+ require 'faraday'
9
+
10
+ opt :resmon_hostfile, 'File with hostnames running Resmon (one URI per line)', type: :string
11
+ opt :read_timeout, 'Faraday read timeout', type: :int, default: 2
12
+ opt :open_timeout, 'Faraday open timeout', type: :int, default: 1
13
+
14
+ def initialize
15
+ @hosts = File.read(options[:resmon_hostfile]).split("\n")
16
+ super
17
+ end
18
+
19
+ def safe_get(uri)
20
+ # Handle connection timeouts
21
+ response = nil
22
+ begin
23
+ connection = Faraday.new(uri)
24
+ response = connection.get do |req|
25
+ req.options[:timeout] = options[:read_timeout]
26
+ req.options[:open_timeout] = options[:open_timeout]
27
+ end
28
+ rescue => e
29
+ report(:host => uri.host,
30
+ :service => "resmon",
31
+ :state => "critical",
32
+ :description => "HTTP connection error: #{e.class} - #{e.message}"
33
+ )
34
+ end
35
+ response
36
+ end
37
+
38
+ def tick
39
+ @hosts.each do |host|
40
+ uri = URI(host)
41
+
42
+ response = safe_get(uri)
43
+ next if response.nil?
44
+
45
+ # Handle non-200 responses
46
+ if response.status != 200
47
+ report(:host => uri.host,
48
+ :service => "resmon",
49
+ :state => "critical",
50
+ :description => "HTTP connection error: #{response.status} - #{response.body}"
51
+ )
52
+ next
53
+ else
54
+ doc = Nokogiri::XML(response.body)
55
+ end
56
+
57
+ doc.xpath('//ResmonResults/ResmonResult').each do |result|
58
+ timestamp = result.xpath('last_update').first.text
59
+ result.xpath('metric').each do |metric|
60
+ hash = {
61
+ host: uri.host,
62
+ service: "#{result.attributes['module'].value}`#{result.attributes['service'].value}`#{metric.attributes['name'].value}",
63
+ time: timestamp.to_i
64
+ }
65
+
66
+ case metric.attributes['type'].value
67
+ when /[iIlLn]/
68
+ hash[:metric] = metric.text
69
+ when 's'
70
+ hash[:description] = metric.text
71
+ when '0'
72
+ raise 'dunno what 0 is yet'
73
+ end
74
+
75
+ report(hash)
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ Riemann::Tools::Resmon.run
data/bin/riemann-riak CHANGED
@@ -15,6 +15,7 @@ class Riemann::Tools::Riak
15
15
  opt :stats_port, "Riak HTTP port for stats", :default => 8098
16
16
  opt :stats_path, "Riak HTTP stats path", :default => '/stats'
17
17
  opt :node_name, "Riak erlang node name", :default => "riak@#{Socket.gethostname}"
18
+ opt :cookie, "Riak cookie to use", :default => "riak"
18
19
 
19
20
  opt :get_50_warning, "FSM 50% get time warning threshold (ms)", :default => 1000
20
21
  opt :put_50_warning, "FSM 50% put time warning threshold (ms)", :default => 1000
@@ -26,7 +27,7 @@ class Riemann::Tools::Riak
26
27
  def initialize
27
28
  @escript = true
28
29
  @riakadmin = true
29
- @httpstats = true
30
+ @httpstatus = true
30
31
 
31
32
  if `which escript` =~ /^\s*$/
32
33
  @escript = false
@@ -45,6 +46,11 @@ class Riemann::Tools::Riak
45
46
  @httpstatus = false
46
47
  end
47
48
  end
49
+ # we're going to override the emulator setting to allow users to
50
+ # dynamically input the cookie
51
+ # this is done only once - hopefully it doesn't get overridden.
52
+ ENV['ERL_AFLAGS'] = "-setcookie #{opts[:cookie]}"
53
+
48
54
  end
49
55
 
50
56
  def check_ring
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env escript
2
- %%! -name riakstatuscheck@127.0.0.1 -setcookie riak -hidden
2
+ %%! -name riakstatuscheck@127.0.0.1 -hidden
3
3
 
4
4
  main([]) -> main(["riak@127.0.0.1"]);
5
5
  main([Node]) ->
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env escript
2
- %%! -name riakstatuscheck@127.0.0.1 -setcookie riak -hidden
2
+ %%! -name riakstatuscheck@127.0.0.1 -hidden
3
3
 
4
4
  main([]) -> main(["riak@127.0.0.1"]);
5
5
  main([Node]) ->
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: riemann-tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-20 00:00:00.000000000 Z
12
+ date: 2013-04-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: riemann-client
@@ -18,7 +18,7 @@ dependencies:
18
18
  requirements:
19
19
  - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
- version: 0.0.8
21
+ version: 0.2.1
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
- version: 0.0.8
29
+ version: 0.2.1
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: trollop
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -91,11 +91,63 @@ dependencies:
91
91
  - - ! '>='
92
92
  - !ruby/object:Gem::Version
93
93
  version: 3.0.2
94
+ - !ruby/object:Gem::Dependency
95
+ name: fog
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: 1.4.0
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: 1.4.0
110
+ - !ruby/object:Gem::Dependency
111
+ name: faraday
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: 0.8.5
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: 0.8.5
126
+ - !ruby/object:Gem::Dependency
127
+ name: nokogiri
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: 1.5.6
134
+ type: :runtime
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: 1.5.6
94
142
  description:
95
143
  email: aphyr@aphyr.com
96
144
  executables:
145
+ - riemann-aws-status
97
146
  - riemann-munin
147
+ - riemann-resmon
148
+ - riemann-redis-slowlog
98
149
  - riemann-bench
150
+ - riemann-freeswitch
99
151
  - riemann-riak
100
152
  - riemann-health
101
153
  - riemann-memcached
@@ -105,6 +157,7 @@ executables:
105
157
  - riemann-riak-ring
106
158
  - riemann-cloudant
107
159
  - riemann-kvminstances
160
+ - riemann-nginx-status
108
161
  - riemann-kvminstance
109
162
  - riemann-net
110
163
  - riemann-redis
@@ -112,9 +165,11 @@ extensions: []
112
165
  extra_rdoc_files: []
113
166
  files:
114
167
  - lib/riemann/tools.rb
168
+ - bin/riemann-aws-status
115
169
  - bin/riemann-bench
116
170
  - bin/riemann-cloudant
117
171
  - bin/riemann-diskstats
172
+ - bin/riemann-freeswitch
118
173
  - bin/riemann-haproxy
119
174
  - bin/riemann-health
120
175
  - bin/riemann-kvminstance
@@ -122,7 +177,10 @@ files:
122
177
  - bin/riemann-memcached
123
178
  - bin/riemann-munin
124
179
  - bin/riemann-net
180
+ - bin/riemann-nginx-status
125
181
  - bin/riemann-redis
182
+ - bin/riemann-redis-slowlog
183
+ - bin/riemann-resmon
126
184
  - bin/riemann-riak
127
185
  - bin/riemann-riak-keys
128
186
  - bin/riemann-riak-ring