riemann-tools 0.1.1 → 0.1.2

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