riemann-tools 1.2.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fa8ed5841e8d5c02ee08180af284269ca1382e174a2dfd98b28de23227a44f61
4
- data.tar.gz: 3ec31579be24a493017091aaa928b6cbd091c2d578a7d577d868ac2857e7be3d
3
+ metadata.gz: ce2307f0dfeaad07e9b904c5f0edf2b0d7a586507c94e8ffb2ff9e3ccf6b3c6f
4
+ data.tar.gz: 8178becee10569b018dfdb54693cfa9e5c5a61dfe62ecdec7ca257004e2365ff
5
5
  SHA512:
6
- metadata.gz: a5554c62f5ce95494f5ed677ccd6933224121c9d227bc9318ec54bed380e0635f1140fbfc5cf8cd3e2ecc919fc267c12f8fb8c47da58345925c69c6d19c82a51
7
- data.tar.gz: a1e3a370c5a325eb6acd59c1ad23fb3efcde20f8ff467d75a84c1e52e1f7cd2cd3102d5045bb11bfd43a43f12b01c0823c2b08f6fa75fd1e33ae50818ffa0e02
6
+ metadata.gz: 7588c24abd5c87eb95ced867cc23350697ef893463e939a47c481518209a386c2b0a56e93e9d470e2fe1d9d0a78fa01d5b8d0e3f6af265d014072a00cf44570d
7
+ data.tar.gz: 54bd9df700e67ee112e856e6104018bac1ad54444533186cdd2425416fa2ab9a0939c5bfd7de5446045d4813c9a8fac5e34db9d997ea841c9665ae97f7224b95
data/.gitignore CHANGED
@@ -5,4 +5,4 @@ pkg/
5
5
  .DS_Store
6
6
  .*.swp
7
7
  *.log
8
- lib/riemann/tools/uptime_parser.tab.rb
8
+ lib/riemann/tools/*_parser.tab.rb
data/.rubocop.yml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  AllCops:
3
3
  Exclude:
4
- - lib/riemann/tools/uptime_parser.tab.rb
4
+ - lib/riemann/tools/*_parser.tab.rb
5
5
  - vendor/bundle/**/*
6
6
  Gemspec/RequiredRubyVersion:
7
7
  Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,5 +1,53 @@
1
1
  # Changelog
2
2
 
3
+ ## [v1.5.0](https://github.com/riemann/riemann-tools/tree/v1.5.0) (2022-09-08)
4
+
5
+ [Full Changelog](https://github.com/riemann/riemann-tools/compare/v1.4.0...v1.5.0)
6
+
7
+ **Implemented enhancements:**
8
+
9
+ - Improve error reporting on parse error [\#242](https://github.com/riemann/riemann-tools/pull/242) ([smortex](https://github.com/smortex))
10
+
11
+ **Fixed bugs:**
12
+
13
+ - Fix `riemann-haproxy` HTTP response processing [\#243](https://github.com/riemann/riemann-tools/pull/243) ([ahoetker-deca](https://github.com/ahoetker-deca))
14
+ - Fix `riemann-md` parsing of mdstat when device is being checked [\#241](https://github.com/riemann/riemann-tools/pull/241) ([smortex](https://github.com/smortex))
15
+
16
+ ## [v1.4.0](https://github.com/riemann/riemann-tools/tree/v1.4.0) (2022-08-30)
17
+
18
+ [Full Changelog](https://github.com/riemann/riemann-tools/compare/v1.3.0...v1.4.0)
19
+
20
+ **Implemented enhancements:**
21
+
22
+ - Improve zpool state reporting [\#239](https://github.com/riemann/riemann-tools/pull/239) ([smortex](https://github.com/smortex))
23
+
24
+ **Fixed bugs:**
25
+
26
+ - Fix zpool/md informational messages reporting [\#238](https://github.com/riemann/riemann-tools/pull/238) ([smortex](https://github.com/smortex))
27
+ - Fix detection of degraded zpool [\#237](https://github.com/riemann/riemann-tools/pull/237) ([smortex](https://github.com/smortex))
28
+
29
+ ## [v1.3.0](https://github.com/riemann/riemann-tools/tree/v1.3.0) (2022-08-29)
30
+
31
+ [Full Changelog](https://github.com/riemann/riemann-tools/compare/v1.2.0...v1.3.0)
32
+
33
+ **Implemented enhancements:**
34
+
35
+ - Add support for configuration file to riemann-wrapper [\#235](https://github.com/riemann/riemann-tools/pull/235) ([smortex](https://github.com/smortex))
36
+ - Add `riemann-md` to monitor Linux RAID/md health [\#232](https://github.com/riemann/riemann-tools/pull/232) ([smortex](https://github.com/smortex))
37
+ - Add `riemann-zpool` to monitor zpool health [\#231](https://github.com/riemann/riemann-tools/pull/231) ([smortex](https://github.com/smortex))
38
+
39
+ **Fixed bugs:**
40
+
41
+ - Fix race condition in riemann-wrapper [\#233](https://github.com/riemann/riemann-tools/pull/233) ([smortex](https://github.com/smortex))
42
+
43
+ **Closed issues:**
44
+
45
+ - There is some kind of race condition in riemann-wrapper [\#230](https://github.com/riemann/riemann-tools/issues/230)
46
+
47
+ **Merged pull requests:**
48
+
49
+ - Stop riemann-wrapper if a tool raise an error [\#234](https://github.com/riemann/riemann-tools/pull/234) ([smortex](https://github.com/smortex))
50
+
3
51
  ## [v1.2.0](https://github.com/riemann/riemann-tools/tree/v1.2.0) (2022-08-17)
4
52
 
5
53
  [Full Changelog](https://github.com/riemann/riemann-tools/compare/v1.1.1...v1.2.0)
data/Rakefile CHANGED
@@ -22,8 +22,15 @@ end
22
22
 
23
23
  task build: :gen_parser
24
24
 
25
- desc 'Generate the uptime parser'
26
- task gen_parser: 'lib/riemann/tools/uptime_parser.tab.rb'
25
+ desc 'Generate parsers'
26
+ task gen_parser: [
27
+ 'lib/riemann/tools/mdstat_parser.tab.rb',
28
+ 'lib/riemann/tools/uptime_parser.tab.rb',
29
+ ]
30
+
31
+ file 'lib/riemann/tools/mdstat_parser.tab.rb' => 'lib/riemann/tools/mdstat_parser.y' do
32
+ sh 'racc -S lib/riemann/tools/mdstat_parser.y'
33
+ end
27
34
 
28
35
  file 'lib/riemann/tools/uptime_parser.tab.rb' => 'lib/riemann/tools/uptime_parser.y' do
29
36
  sh 'racc -S lib/riemann/tools/uptime_parser.y'
data/bin/riemann-md ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ Process.setproctitle($PROGRAM_NAME)
5
+
6
+ require 'riemann/tools/md'
7
+
8
+ Riemann::Tools::Md.run
data/bin/riemann-wrapper CHANGED
@@ -27,9 +27,10 @@ def read_flags(argv)
27
27
  res
28
28
  end
29
29
 
30
- if ARGV.empty?
30
+ def usage
31
31
  warn <<~USAGE
32
32
  usage: riemann-wrapper [common options] -- tool1 [tool1 options] [-- tool2 [tool2 options] ...]
33
+ riemann-wrapper /path/to/configuration/file.yml
33
34
 
34
35
  Run multiple Riemann tools in a single process. A single connection to
35
36
  riemann is maintained and shared for all tools, the connection flags should
@@ -47,16 +48,53 @@ if ARGV.empty?
47
48
  fd --tag=fd -- \\
48
49
  health --tag=health -- \\
49
50
  ntp --tag=ntp
51
+
52
+ 3. Same as above example, but using a configuration file (more verbose but
53
+ easier to handle when running riemann-wrapper manually of managing it
54
+ with a Configuration Management system):
55
+
56
+ cat > config.yml << EOT
57
+ ---
58
+ options: --host riemann.example.com --tcp
59
+ tools:
60
+ - name: fd
61
+ options: --tag=fd
62
+ - name: health
63
+ options: --tag=health
64
+ - name: ntp
65
+ options: --tag=ntp
66
+ EOT
67
+ riemann-wrapper config.yml
50
68
  USAGE
51
69
  exit 1
52
70
  end
53
71
 
72
+ usage if ARGV.empty?
73
+
74
+ if ARGV.size == 1
75
+ unless File.readable?(ARGV[0])
76
+ warn "Cannot open file for reading: #{ARGV[0]}"
77
+ usage
78
+ end
79
+
80
+ require 'yaml'
81
+ config = YAML.safe_load(File.read(ARGV[0]))
82
+
83
+ commandline = config['options']
84
+ config['tools'].each { |tool| commandline << " -- #{tool['name']} #{tool['options']}" }
85
+
86
+ ARGV.replace(commandline.split)
87
+ end
88
+
54
89
  argv = ARGV.dup
55
90
 
56
91
  common_argv = read_flags(argv)
57
92
 
58
93
  threads = []
59
94
 
95
+ # Terminate the whole process is some thread fail
96
+ Thread.abort_on_exception = true
97
+
60
98
  while argv.any?
61
99
  tool = argv.shift
62
100
  tool_argv = read_flags(argv)
@@ -69,7 +107,7 @@ while argv.any?
69
107
  # Force evaluation of options. This rely on ARGV and needs to be done before
70
108
  # we launch multiple threads which compete to read information from there.
71
109
  instance.options
72
- threads << Thread.new { instance.run }
110
+ threads << Thread.new(instance, &:run)
73
111
  end
74
112
 
75
113
  threads.each(&:join)
data/bin/riemann-zpool ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ Process.setproctitle($PROGRAM_NAME)
5
+
6
+ require 'riemann/tools/zpool'
7
+
8
+ Riemann::Tools::Zpool.run
@@ -44,7 +44,7 @@ module Riemann
44
44
  def csv
45
45
  http = ::Net::HTTP.new(@uri.host, @uri.port)
46
46
  http.use_ssl = true if @uri.scheme == 'https'
47
- http.start do |h|
47
+ res = http.start do |h|
48
48
  get = ::Net::HTTP::Get.new(@uri.request_uri)
49
49
  unless @uri.userinfo.nil?
50
50
  userinfo = @uri.userinfo.split(':')
@@ -52,7 +52,7 @@ module Riemann
52
52
  end
53
53
  h.request get
54
54
  end
55
- CSV.parse(http.body.split('# ')[1], { headers: true })
55
+ CSV.parse(res.body.split('# ')[1], { headers: true })
56
56
  end
57
57
  end
58
58
  end
@@ -103,6 +103,8 @@ module Riemann
103
103
  @swap_enabled = true
104
104
  end
105
105
  end
106
+
107
+ invalidate_cache
106
108
  end
107
109
 
108
110
  def alert(service, state, metric, description)
@@ -139,6 +141,8 @@ module Riemann
139
141
  end
140
142
 
141
143
  def report_uptime(uptime)
144
+ return unless uptime
145
+
142
146
  description = uptime_to_human(uptime)
143
147
 
144
148
  if uptime < @limits[:uptime][:critical]
@@ -262,6 +266,13 @@ module Riemann
262
266
 
263
267
  def uptime
264
268
  @cached_data[:uptime] ||= uptime_parser.parse(`uptime`)
269
+ rescue Racc::ParseError => e
270
+ report(
271
+ service: 'uptime',
272
+ description: "Error parsing uptime: #{e.message}",
273
+ state: 'critical',
274
+ )
275
+ @cached_data[:uptime] = {}
265
276
  end
266
277
 
267
278
  def bsd_load
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'riemann/tools'
4
+ require 'riemann/tools/mdstat_parser.tab'
5
+
6
+ module Riemann
7
+ module Tools
8
+ class Md
9
+ include Riemann::Tools
10
+
11
+ def mdstat_parser
12
+ @mdstat_parser ||= MdstatParser.new
13
+ end
14
+
15
+ def tick
16
+ status = File.read('/proc/mdstat')
17
+ res = mdstat_parser.parse(status)
18
+
19
+ state = res.values.all? { |value| value =~ /\AU+\z/ } ? 'ok' : 'critical'
20
+
21
+ report(
22
+ service: 'mdstat',
23
+ description: status,
24
+ state: state,
25
+ )
26
+ rescue Racc::ParseError => e
27
+ report(
28
+ service: 'mdstat',
29
+ description: "Error parsing mdstat: #{e.message}",
30
+ state: 'critical',
31
+ )
32
+ rescue Errno::ENOENT => e
33
+ report(
34
+ service: 'mdstat',
35
+ description: e.message,
36
+ state: 'critical',
37
+ )
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,371 @@
1
+ #
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by Racc 1.6.0
4
+ # from Racc grammar file "".
5
+ #
6
+
7
+ require 'racc/parser.rb'
8
+
9
+
10
+ require 'strscan'
11
+
12
+ require 'riemann/tools/utils'
13
+
14
+ module Riemann
15
+ module Tools
16
+ class MdstatParser < Racc::Parser
17
+
18
+ module_eval(<<'...end mdstat_parser.y/module_eval...', 'mdstat_parser.y', 49)
19
+
20
+ def parse(text)
21
+ s = Utils::StringTokenizer.new(text)
22
+
23
+ until s.eos? do
24
+ case
25
+ when s.scan(/\n/) then s.push_token(nil)
26
+ when s.scan(/\s+/) then s.push_token(nil)
27
+
28
+ when s.scan(/\[=*>.*\]/) then s.push_token(:PROGRESS)
29
+ when s.scan(/%/) then s.push_token('%')
30
+ when s.scan(/,/) then s.push_token(',')
31
+ when s.scan(/:/) then s.push_token(':')
32
+ when s.scan(/</) then s.push_token('<')
33
+ when s.scan(/=/) then s.push_token('=')
34
+ when s.scan(/>/) then s.push_token('>')
35
+ when s.scan(/\(/) then s.push_token('(')
36
+ when s.scan(/\)/) then s.push_token(')')
37
+ when s.scan(/\./) then s.push_token('.')
38
+ when s.scan(/\//) then s.push_token('/')
39
+ when s.scan(/\[/) then s.push_token('[')
40
+ when s.scan(/]/) then s.push_token(']')
41
+ when s.scan(/algorithm/) then s.push_token(:ALGORITHM)
42
+ when s.scan(/bitmap/) then s.push_token(:BITMAP)
43
+ when s.scan(/blocks/) then s.push_token(:BLOCKS)
44
+ when s.scan(/check/) then s.push_token(:CHECK)
45
+ when s.scan(/chunk/) then s.push_token(:CHUNK)
46
+ when s.scan(/finish/) then s.push_token(:FINISH)
47
+ when s.scan(/level/) then s.push_token(:LEVEL)
48
+ when s.scan(/min/) then s.push_token(:MIN)
49
+ when s.scan(/pages/) then s.push_token(:PAGES)
50
+ when s.scan(/(raid([014-6]|10)|linear|multipath|faulty)\b/) then s.push_token(:PERSONALITY)
51
+ when s.scan(/Personalities/) then s.push_token(:PERSONALITIES)
52
+ when s.scan(/recovery/) then s.push_token(:RECOVERY)
53
+ when s.scan(/reshape/) then s.push_token(:RESHAPE)
54
+ when s.scan(/resync/) then s.push_token(:RESYNC)
55
+ when s.scan(/speed/) then s.push_token(:SPEED)
56
+ when s.scan(/super/) then s.push_token(:SUPER)
57
+ when s.scan(/unused devices/) then s.push_token(:UNUSED_DEVICES)
58
+ when s.scan(/K\/sec/) then s.push_token(:SPEED_UNIT)
59
+ when s.scan(/KB/) then s.push_token(:BYTE_UNIT)
60
+ when s.scan(/k/) then s.push_token(:UNIT)
61
+ when s.scan(/\d+\.\d+/) then s.push_token(:FLOAT, s.matched.to_f)
62
+ when s.scan(/\d+/) then s.push_token(:INTEGER, s.matched.to_i)
63
+ when s.scan(/F\b/) then s.push_token(:FAILED)
64
+ when s.scan(/\w+/) then s.push_token(:IDENTIFIER)
65
+ else
66
+ s.unexpected_token
67
+ end
68
+ end
69
+
70
+ @tokens = s.tokens
71
+
72
+ do_parse
73
+ end
74
+
75
+ def next_token
76
+ @tokens.shift
77
+ end
78
+
79
+ def on_error(error_token_id, error_value, value_stack)
80
+ raise(Racc::ParseError, "parse error on value \"#{error_value[:value]}\" (#{token_to_str(error_token_id)}) on line #{error_value[:lineno]}:\n#{error_value[:line]}\n#{' ' * error_value[:pos]}^#{'~' * (error_value[:value].to_s.length - 1)}")
81
+ end
82
+ ...end mdstat_parser.y/module_eval...
83
+ ##### State transition tables begin ###
84
+
85
+ racc_action_table = [
86
+ 10, 13, 14, 60, 10, 29, 3, 4, 6, 7,
87
+ 15, 16, 17, 18, 19, 11, 61, 62, 63, 20,
88
+ 21, 22, 23, 24, 10, 27, 28, 31, 32, 33,
89
+ 35, 37, 38, 39, 40, 41, 42, 43, 44, 45,
90
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 56,
91
+ 58, 64, 65, 66, 67, 68, 69, 70, 71, 72,
92
+ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
93
+ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92 ]
94
+
95
+ racc_action_check = [
96
+ 5, 10, 10, 56, 25, 25, 0, 1, 3, 4,
97
+ 11, 12, 13, 14, 15, 5, 56, 56, 56, 16,
98
+ 17, 18, 19, 20, 21, 22, 23, 27, 29, 31,
99
+ 32, 34, 35, 36, 37, 39, 40, 41, 42, 43,
100
+ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
101
+ 55, 58, 59, 64, 65, 66, 67, 68, 69, 70,
102
+ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
103
+ 81, 82, 83, 84, 85, 86, 87, 89, 90, 91 ]
104
+
105
+ racc_action_pointer = [
106
+ -10, 7, nil, -19, 9, -11, nil, nil, nil, nil,
107
+ -26, -17, -17, 1, 1, -22, 2, 3, -8, 11,
108
+ -6, 13, -6, -11, nil, -7, nil, 19, nil, 24,
109
+ nil, -3, 6, nil, 18, 22, 5, 22, nil, 23,
110
+ 3, 7, 26, 27, 15, 12, 35, 15, 11, 34,
111
+ 44, 18, 36, 31, nil, 47, -3, nil, 24, 18,
112
+ nil, nil, nil, nil, 41, 44, 25, 21, 45, 27,
113
+ 44, 48, 33, 32, 51, 52, 60, 34, 38, 59,
114
+ 36, 36, 59, 62, 68, 60, 68, 54, nil, 43,
115
+ 66, 56, nil ]
116
+
117
+ racc_action_default = [
118
+ -25, -25, -6, -25, -25, -25, -4, 93, -1, -5,
119
+ -25, -25, -2, -25, -25, -25, -25, -25, -25, -25,
120
+ -25, -25, -11, -25, -3, -25, -9, -25, -24, -25,
121
+ -8, -25, -13, -10, -15, -25, -25, -25, -12, -25,
122
+ -25, -25, -25, -25, -25, -25, -25, -25, -25, -25,
123
+ -25, -25, -25, -19, -14, -17, -25, -7, -25, -25,
124
+ -20, -21, -22, -23, -25, -25, -25, -25, -25, -25,
125
+ -25, -25, -25, -25, -25, -25, -25, -25, -25, -25,
126
+ -25, -25, -25, -25, -25, -25, -25, -25, -16, -25,
127
+ -25, -25, -18 ]
128
+
129
+ racc_goto_table = [
130
+ 9, 1, 2, 5, 8, 12, 25, 34, 36, 55,
131
+ 57, 59, nil, nil, nil, nil, 26, nil, nil, nil,
132
+ 30 ]
133
+
134
+ racc_goto_check = [
135
+ 6, 1, 2, 3, 4, 5, 7, 8, 9, 10,
136
+ 11, 12, nil, nil, nil, nil, 6, nil, nil, nil,
137
+ 6 ]
138
+
139
+ racc_goto_pointer = [
140
+ nil, 1, 2, 1, -1, -1, -5, -15, -25, -26,
141
+ -44, -45, -45 ]
142
+
143
+ racc_goto_default = [
144
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
145
+ nil, nil, nil ]
146
+
147
+ racc_reduce_table = [
148
+ 0, 0, :racc_error,
149
+ 3, 39, :_reduce_1,
150
+ 3, 40, :_reduce_none,
151
+ 4, 43, :_reduce_none,
152
+ 0, 43, :_reduce_none,
153
+ 2, 41, :_reduce_5,
154
+ 0, 41, :_reduce_6,
155
+ 19, 44, :_reduce_7,
156
+ 2, 45, :_reduce_none,
157
+ 1, 45, :_reduce_none,
158
+ 7, 44, :_reduce_none,
159
+ 4, 44, :_reduce_none,
160
+ 2, 46, :_reduce_none,
161
+ 0, 46, :_reduce_none,
162
+ 9, 47, :_reduce_none,
163
+ 0, 47, :_reduce_none,
164
+ 14, 49, :_reduce_none,
165
+ 0, 49, :_reduce_none,
166
+ 18, 48, :_reduce_none,
167
+ 0, 48, :_reduce_none,
168
+ 1, 50, :_reduce_none,
169
+ 1, 50, :_reduce_none,
170
+ 1, 50, :_reduce_none,
171
+ 1, 50, :_reduce_none,
172
+ 5, 42, :_reduce_none ]
173
+
174
+ racc_reduce_n = 25
175
+
176
+ racc_shift_n = 93
177
+
178
+ racc_token_table = {
179
+ false => 0,
180
+ :error => 1,
181
+ :ALGORITHM => 2,
182
+ :BITMAP => 3,
183
+ :BLOCKS => 4,
184
+ :BYTE_UNIT => 5,
185
+ :CHECK => 6,
186
+ :CHUNK => 7,
187
+ :FAILED => 8,
188
+ :FINISH => 9,
189
+ :FLOAT => 10,
190
+ :IDENTIFIER => 11,
191
+ :INTEGER => 12,
192
+ :LEVEL => 13,
193
+ :MIN => 14,
194
+ :PAGES => 15,
195
+ :PERSONALITIES => 16,
196
+ :PERSONALITY => 17,
197
+ :PROGRESS => 18,
198
+ :RECOVERY => 19,
199
+ :RESHAPE => 20,
200
+ :RESYNC => 21,
201
+ :SPEED => 22,
202
+ :SPEED_UNIT => 23,
203
+ :SUPER => 24,
204
+ :UNIT => 25,
205
+ :UNUSED_DEVICES => 26,
206
+ ":" => 27,
207
+ "[" => 28,
208
+ "]" => 29,
209
+ "/" => 30,
210
+ "(" => 31,
211
+ ")" => 32,
212
+ "," => 33,
213
+ "=" => 34,
214
+ "%" => 35,
215
+ "<" => 36,
216
+ ">" => 37 }
217
+
218
+ racc_nt_base = 38
219
+
220
+ racc_use_result_var = true
221
+
222
+ Racc_arg = [
223
+ racc_action_table,
224
+ racc_action_check,
225
+ racc_action_default,
226
+ racc_action_pointer,
227
+ racc_goto_table,
228
+ racc_goto_check,
229
+ racc_goto_default,
230
+ racc_goto_pointer,
231
+ racc_nt_base,
232
+ racc_reduce_table,
233
+ racc_token_table,
234
+ racc_shift_n,
235
+ racc_reduce_n,
236
+ racc_use_result_var ]
237
+
238
+ Racc_token_to_s_table = [
239
+ "$end",
240
+ "error",
241
+ "ALGORITHM",
242
+ "BITMAP",
243
+ "BLOCKS",
244
+ "BYTE_UNIT",
245
+ "CHECK",
246
+ "CHUNK",
247
+ "FAILED",
248
+ "FINISH",
249
+ "FLOAT",
250
+ "IDENTIFIER",
251
+ "INTEGER",
252
+ "LEVEL",
253
+ "MIN",
254
+ "PAGES",
255
+ "PERSONALITIES",
256
+ "PERSONALITY",
257
+ "PROGRESS",
258
+ "RECOVERY",
259
+ "RESHAPE",
260
+ "RESYNC",
261
+ "SPEED",
262
+ "SPEED_UNIT",
263
+ "SUPER",
264
+ "UNIT",
265
+ "UNUSED_DEVICES",
266
+ "\":\"",
267
+ "\"[\"",
268
+ "\"]\"",
269
+ "\"/\"",
270
+ "\"(\"",
271
+ "\")\"",
272
+ "\",\"",
273
+ "\"=\"",
274
+ "\"%\"",
275
+ "\"<\"",
276
+ "\">\"",
277
+ "$start",
278
+ "target",
279
+ "personalities",
280
+ "devices",
281
+ "unused_devices",
282
+ "list_of_personalities",
283
+ "device",
284
+ "list_of_devices",
285
+ "super",
286
+ "level",
287
+ "progress",
288
+ "bitmap",
289
+ "progress_action" ]
290
+
291
+ Racc_debug_parser = false
292
+
293
+ ##### State transition tables end #####
294
+
295
+ # reduce 0 omitted
296
+
297
+ module_eval(<<'.,.,', 'mdstat_parser.y', 3)
298
+ def _reduce_1(val, _values, result)
299
+ result = val[1]
300
+ result
301
+ end
302
+ .,.,
303
+
304
+ # reduce 2 omitted
305
+
306
+ # reduce 3 omitted
307
+
308
+ # reduce 4 omitted
309
+
310
+ module_eval(<<'.,.,', 'mdstat_parser.y', 10)
311
+ def _reduce_5(val, _values, result)
312
+ result = val[0].merge(val[1])
313
+ result
314
+ end
315
+ .,.,
316
+
317
+ module_eval(<<'.,.,', 'mdstat_parser.y', 11)
318
+ def _reduce_6(val, _values, result)
319
+ result = {}
320
+ result
321
+ end
322
+ .,.,
323
+
324
+ module_eval(<<'.,.,', 'mdstat_parser.y', 13)
325
+ def _reduce_7(val, _values, result)
326
+ result = { val[0][:value] => val[15][:value] }
327
+ result
328
+ end
329
+ .,.,
330
+
331
+ # reduce 8 omitted
332
+
333
+ # reduce 9 omitted
334
+
335
+ # reduce 10 omitted
336
+
337
+ # reduce 11 omitted
338
+
339
+ # reduce 12 omitted
340
+
341
+ # reduce 13 omitted
342
+
343
+ # reduce 14 omitted
344
+
345
+ # reduce 15 omitted
346
+
347
+ # reduce 16 omitted
348
+
349
+ # reduce 17 omitted
350
+
351
+ # reduce 18 omitted
352
+
353
+ # reduce 19 omitted
354
+
355
+ # reduce 20 omitted
356
+
357
+ # reduce 21 omitted
358
+
359
+ # reduce 22 omitted
360
+
361
+ # reduce 23 omitted
362
+
363
+ # reduce 24 omitted
364
+
365
+ def _reduce_none(val, _values, result)
366
+ val[0]
367
+ end
368
+
369
+ end # class MdstatParser
370
+ end # module Tools
371
+ end # module Riemann
@@ -9,45 +9,52 @@ require 'racc/parser.rb'
9
9
 
10
10
  require 'strscan'
11
11
 
12
+ require 'riemann/tools/utils'
13
+
12
14
  module Riemann
13
15
  module Tools
14
16
  class UptimeParser < Racc::Parser
15
17
 
16
- module_eval(<<'...end uptime_parser.y/module_eval...', 'uptime_parser.y', 43)
18
+ module_eval(<<'...end uptime_parser.y/module_eval...', 'uptime_parser.y', 45)
17
19
 
18
20
  def parse(text)
19
- s = StringScanner.new(text)
20
- @tokens = []
21
+ s = Utils::StringTokenizer.new(text)
21
22
 
22
23
  until s.eos? do
23
24
  case
24
- when s.scan(/\n/) then # ignore
25
- when s.scan(/\s+/) then # ignore
26
-
27
- when s.scan(/:/) then @tokens << [':', s.matched]
28
- when s.scan(/,/) then @tokens << [',', s.matched]
29
- when s.scan(/\d+[,.]\d+/) then @tokens << [:FLOAT, s.matched.sub(',', '.').to_f]
30
- when s.scan(/\d+/) then @tokens << [:INTEGER, s.matched.to_i]
31
- when s.scan(/AM/) then @tokens << [:AM, s.matched]
32
- when s.scan(/PM/) then @tokens << [:PM, s.matched]
33
- when s.scan(/up/) then @tokens << [:UP, s.matched]
34
- when s.scan(/days?/) then @tokens << [:DAYS, s.matched]
35
- when s.scan(/hrs?/) then @tokens << [:HRS, s.matched]
36
- when s.scan(/mins?/) then @tokens << [:MINS, s.matched]
37
- when s.scan(/secs?/) then @tokens << [:SECS, s.matched]
38
- when s.scan(/users?/) then @tokens << [:USERS, s.matched]
39
- when s.scan(/load averages?:/) then @tokens << [:LOAD_AVERAGES, s.matched]
25
+ when s.scan(/\n/) then s.push_token(nil)
26
+ when s.scan(/\s+/) then s.push_token(nil)
27
+
28
+ when s.scan(/:/) then s.push_token(':')
29
+ when s.scan(/,/) then s.push_token(',')
30
+ when s.scan(/\d+[,.]\d+/) then s.push_token(:FLOAT, s.matched.sub(',', '.').to_f)
31
+ when s.scan(/\d+/) then s.push_token(:INTEGER, s.matched.to_i)
32
+ when s.scan(/AM/) then s.push_token(:AM)
33
+ when s.scan(/PM/) then s.push_token(:PM)
34
+ when s.scan(/up/) then s.push_token(:UP)
35
+ when s.scan(/days?/) then s.push_token(:DAYS)
36
+ when s.scan(/hrs?/) then s.push_token(:HRS)
37
+ when s.scan(/mins?/) then s.push_token(:MINS)
38
+ when s.scan(/secs?/) then s.push_token(:SECS)
39
+ when s.scan(/users?/) then s.push_token(:USERS)
40
+ when s.scan(/load averages?:/) then s.push_token(:LOAD_AVERAGES)
40
41
  else
41
- raise s.rest
42
+ raise s.unexpected_token
42
43
  end
43
44
  end
44
45
 
46
+ @tokens = s.tokens
47
+
45
48
  do_parse
46
49
  end
47
50
 
48
51
  def next_token
49
52
  @tokens.shift
50
53
  end
54
+
55
+ def on_error(error_token_id, error_value, value_stack)
56
+ raise(Racc::ParseError, "parse error on value \"#{error_value[:value]}\" (#{token_to_str(error_token_id)}) on line #{error_value[:lineno]}:\n#{error_value[:line]}\n#{' ' * error_value[:pos]}^#{'~' * (error_value[:value].to_s.length - 1)}")
57
+ end
51
58
  ...end uptime_parser.y/module_eval...
52
59
  ##### State transition tables begin ###
53
60
 
@@ -113,7 +120,7 @@ racc_reduce_table = [
113
120
  2, 23, :_reduce_16,
114
121
  2, 24, :_reduce_17,
115
122
  2, 25, :_reduce_18,
116
- 2, 19, :_reduce_none,
123
+ 2, 19, :_reduce_19,
117
124
  4, 20, :_reduce_20,
118
125
  6, 20, :_reduce_21 ]
119
126
 
@@ -265,51 +272,56 @@ module_eval(<<'.,.,', 'uptime_parser.y', 18)
265
272
 
266
273
  module_eval(<<'.,.,', 'uptime_parser.y', 20)
267
274
  def _reduce_14(val, _values, result)
268
- result = val[0] * 86400
275
+ result = val[0][:value] * 86400
269
276
  result
270
277
  end
271
278
  .,.,
272
279
 
273
280
  module_eval(<<'.,.,', 'uptime_parser.y', 22)
274
281
  def _reduce_15(val, _values, result)
275
- result = val[0] * 3600 + val[2] * 60
282
+ result = val[0][:value] * 3600 + val[2][:value] * 60
276
283
  result
277
284
  end
278
285
  .,.,
279
286
 
280
287
  module_eval(<<'.,.,', 'uptime_parser.y', 24)
281
288
  def _reduce_16(val, _values, result)
282
- result = val[0] * 3600
289
+ result = val[0][:value] * 3600
283
290
  result
284
291
  end
285
292
  .,.,
286
293
 
287
294
  module_eval(<<'.,.,', 'uptime_parser.y', 26)
288
295
  def _reduce_17(val, _values, result)
289
- result = val[0] * 60
296
+ result = val[0][:value] * 60
290
297
  result
291
298
  end
292
299
  .,.,
293
300
 
294
301
  module_eval(<<'.,.,', 'uptime_parser.y', 28)
295
302
  def _reduce_18(val, _values, result)
296
- result = val[0]
303
+ result = val[0][:value]
297
304
  result
298
305
  end
299
306
  .,.,
300
307
 
301
- # reduce 19 omitted
308
+ module_eval(<<'.,.,', 'uptime_parser.y', 30)
309
+ def _reduce_19(val, _values, result)
310
+ result = val[0][:value]
311
+ result
312
+ end
313
+ .,.,
302
314
 
303
315
  module_eval(<<'.,.,', 'uptime_parser.y', 32)
304
316
  def _reduce_20(val, _values, result)
305
- result = { 1 => val[1], 5 => val[2], 15 => val[3] }
317
+ result = { 1 => val[1][:value], 5 => val[2][:value], 15 => val[3][:value] }
306
318
  result
307
319
  end
308
320
  .,.,
309
321
 
310
322
  module_eval(<<'.,.,', 'uptime_parser.y', 33)
311
323
  def _reduce_21(val, _values, result)
312
- result = { 1 => val[1], 5 => val[3], 15 => val[5] }
324
+ result = { 1 => val[1][:value], 5 => val[3][:value], 15 => val[5][:value] }
313
325
  result
314
326
  end
315
327
  .,.,
@@ -3,6 +3,54 @@
3
3
  module Riemann
4
4
  module Tools
5
5
  module Utils # :nodoc:
6
+ class StringTokenizer
7
+ attr_reader :tokens
8
+
9
+ def initialize(text)
10
+ @scanner = StringScanner.new(text)
11
+
12
+ @lineno = 1
13
+ @pos = 0
14
+ @line = next_line
15
+ @tokens = []
16
+ end
17
+
18
+ def scan(expression)
19
+ @scanner.scan(expression)
20
+ end
21
+
22
+ def eos?
23
+ @scanner.eos?
24
+ end
25
+
26
+ def matched
27
+ @scanner.matched
28
+ end
29
+
30
+ def next_line
31
+ (@scanner.check_until(/\n/) || @scanner.rest).chomp
32
+ end
33
+
34
+ def push_token(token, value = nil)
35
+ value ||= @scanner.matched
36
+
37
+ if value == "\n"
38
+ @lineno += 1
39
+ @line = next_line
40
+ @pos = pos = 0
41
+ else
42
+ pos = @pos
43
+ @pos += @scanner.matched.length
44
+ end
45
+
46
+ @tokens << [token, { value: value, line: @line, lineno: @lineno, pos: pos }] if token
47
+ end
48
+
49
+ def unexpected_token
50
+ raise(Racc::ParseError, "unexpected data on line #{@lineno}:\n#{@line}\n#{' ' * @pos}^")
51
+ end
52
+ end
53
+
6
54
  def reverse_numeric_sort_with_header(data, header: 1, count: 10)
7
55
  lines = data.chomp.split("\n")
8
56
  header = lines.shift(header)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Riemann
4
4
  module Tools # :nodoc:
5
- VERSION = '1.2.0'
5
+ VERSION = '1.5.0'
6
6
  end
7
7
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'open3'
4
+
5
+ require 'riemann/tools'
6
+
7
+ module Riemann
8
+ module Tools
9
+ class Zpool
10
+ include Riemann::Tools
11
+
12
+ def tick
13
+ output, status = Open3.capture2e('zpool status -x')
14
+
15
+ state = if status.success?
16
+ case output
17
+ when "all pools are healthy\n" then 'ok'
18
+ when /state: (DEGRADED|FAULTED)/ then 'critical'
19
+ else
20
+ 'warning'
21
+ end
22
+ else
23
+ 'critical'
24
+ end
25
+
26
+ report(
27
+ service: 'zpool health',
28
+ description: output,
29
+ state: state,
30
+ )
31
+ rescue Errno::ENOENT => e
32
+ report(
33
+ service: 'zpool health',
34
+ description: e.message,
35
+ state: 'critical',
36
+ )
37
+ end
38
+ end
39
+ end
40
+ end
@@ -24,8 +24,14 @@ Gem::Specification.new do |spec|
24
24
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
25
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
26
26
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } -
27
- ['lib/riemann/tools/uptime_parser.y'] +
28
- ['lib/riemann/tools/uptime_parser.tab.rb']
27
+ [
28
+ 'lib/riemann/tools/mdstat_parser.y',
29
+ 'lib/riemann/tools/uptime_parser.y',
30
+ ] +
31
+ [
32
+ 'lib/riemann/tools/mdstat_parser.tab.rb',
33
+ 'lib/riemann/tools/uptime_parser.tab.rb',
34
+ ]
29
35
  end
30
36
  spec.bindir = 'bin'
31
37
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: riemann-tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kyle Kingsbury
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-17 00:00:00.000000000 Z
11
+ date: 2022-09-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -172,6 +172,7 @@ executables:
172
172
  - riemann-haproxy
173
173
  - riemann-health
174
174
  - riemann-kvminstance
175
+ - riemann-md
175
176
  - riemann-memcached
176
177
  - riemann-net
177
178
  - riemann-nginx-status
@@ -181,6 +182,7 @@ executables:
181
182
  - riemann-varnish
182
183
  - riemann-wrapper
183
184
  - riemann-zookeeper
185
+ - riemann-zpool
184
186
  extensions: []
185
187
  extra_rdoc_files: []
186
188
  files:
@@ -212,6 +214,7 @@ files:
212
214
  - bin/riemann-haproxy
213
215
  - bin/riemann-health
214
216
  - bin/riemann-kvminstance
217
+ - bin/riemann-md
215
218
  - bin/riemann-memcached
216
219
  - bin/riemann-net
217
220
  - bin/riemann-nginx-status
@@ -221,6 +224,7 @@ files:
221
224
  - bin/riemann-varnish
222
225
  - bin/riemann-wrapper
223
226
  - bin/riemann-zookeeper
227
+ - bin/riemann-zpool
224
228
  - lib/riemann/tools.rb
225
229
  - lib/riemann/tools/apache_status.rb
226
230
  - lib/riemann/tools/bench.rb
@@ -234,6 +238,8 @@ files:
234
238
  - lib/riemann/tools/haproxy.rb
235
239
  - lib/riemann/tools/health.rb
236
240
  - lib/riemann/tools/kvm.rb
241
+ - lib/riemann/tools/md.rb
242
+ - lib/riemann/tools/mdstat_parser.tab.rb
237
243
  - lib/riemann/tools/memcached.rb
238
244
  - lib/riemann/tools/net.rb
239
245
  - lib/riemann/tools/nginx_status.rb
@@ -246,6 +252,7 @@ files:
246
252
  - lib/riemann/tools/varnish.rb
247
253
  - lib/riemann/tools/version.rb
248
254
  - lib/riemann/tools/zookeeper.rb
255
+ - lib/riemann/tools/zpool.rb
249
256
  - riemann-tools.gemspec
250
257
  - tools/riemann-aws/LICENSE
251
258
  - tools/riemann-aws/README.md