fluent-plugin-numeric-monitor 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f0e34e02fb3c60ee05565ff9e7ed9c31bbf1f677
4
+ data.tar.gz: b74595ed3a9194bb3da3f21d8d47749b97059bcd
5
+ SHA512:
6
+ metadata.gz: 9031f88688412a012a965d9240639e51c65716bcc5248085c8bdff1e85bcde52b8b12d3703df11442464427a5b9c1459c26d8bfec907a60ec18fdfe62d72e21f
7
+ data.tar.gz: 9ee81f7dfbe2483631df14dbea7553cced143f62c5631d23c25386cc1dcd6c669aa7b92fd59870b23a1c380090293031d44a9c6a9ee9c68ca2e71c22c8d8e31b
data/README.md CHANGED
@@ -26,6 +26,54 @@ Output messages like:
26
26
 
27
27
  {"min":3012,"max":913243,"avg":100123.51,"percentile_90":154390,"percentile_95":223110,"num":50012}
28
28
 
29
+
30
+ ## Parameters
31
+
32
+ * monitor\_key (required)
33
+
34
+ The key to monitor in the event record.
35
+
36
+ * percentiles
37
+
38
+ Activate the percentile monitoring. Must be specified between `1` and `99` by integer separeted by , (comma).
39
+
40
+ * tag
41
+
42
+ The output tag. Default is `monitor`.
43
+
44
+ * tag\_prefix
45
+
46
+ The prefix string which will be added to the input tag. `output_per_tag yes` must be specified together.
47
+
48
+ * input\_tag\_remove\_prefix
49
+
50
+ The prefix string which will be removed from the input tag.
51
+
52
+ * count\_interval
53
+
54
+ The interval time to monitor in seconds. Default is `60`.
55
+
56
+ * unit
57
+
58
+ The interval time to monitor specified an unit (either of `minute`, `hour`, or `day`).
59
+ Use either of `count_interval` or `unit`.
60
+
61
+ * aggregate
62
+
63
+ Calculate in each input `tag` separetely, or `all` records in a mass. Default is `tag`
64
+
65
+ * ouput\_per\_tag
66
+
67
+ Emit for each input tag. `tag_prefix` must be specified together. Default is `no`.
68
+
69
+ * output\_key\_prefix
70
+
71
+ The prefix string which will be added to the output key.
72
+
73
+ * samples\_limit
74
+
75
+ The limit number of sampling. Default is `1000000`.
76
+
29
77
  ## TODO
30
78
 
31
79
  * more tests
@@ -1,7 +1,7 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  Gem::Specification.new do |gem|
3
3
  gem.name = "fluent-plugin-numeric-monitor"
4
- gem.version = "0.1.4"
4
+ gem.version = "0.1.5"
5
5
  gem.authors = ["TAGOMORI Satoshi"]
6
6
  gem.email = ["tagomoris@gmail.com"]
7
7
  gem.description = %q{Fluentd plugin to calculate min/max/avg/Xpercentile values, and emit these data as message}
@@ -6,7 +6,9 @@ class Fluent::NumericMonitorOutput < Fluent::Output
6
6
  config_param :count_interval, :time, :default => 60
7
7
  config_param :unit, :string, :default => nil
8
8
  config_param :tag, :string, :default => 'monitor'
9
+ config_param :tag_prefix, :string, :default => nil
9
10
 
11
+ config_param :output_per_tag, :bool, :default => false
10
12
  config_param :aggregate, :default => 'tag' do |val|
11
13
  case val
12
14
  when 'tag' then :tag
@@ -17,6 +19,7 @@ class Fluent::NumericMonitorOutput < Fluent::Output
17
19
  end
18
20
  config_param :input_tag_remove_prefix, :string, :default => nil
19
21
  config_param :monitor_key, :string
22
+ config_param :output_key_prefix, :string, :default => nil
20
23
  config_param :percentiles, :default => nil do |val|
21
24
  values = val.split(",").map(&:to_i)
22
25
  if values.select{|i| i < 1 or i > 99 }.size > 0
@@ -46,6 +49,16 @@ class Fluent::NumericMonitorOutput < Fluent::Output
46
49
  @removed_prefix_string = @input_tag_remove_prefix + '.'
47
50
  @removed_length = @removed_prefix_string.length
48
51
  end
52
+
53
+ @key_prefix_string = ''
54
+ if @output_key_prefix
55
+ @key_prefix_string = @output_key_prefix + '_'
56
+ end
57
+
58
+ if (@output_per_tag || @tag_prefix) && (!@output_per_tag || !@tag_prefix)
59
+ raise Fluent::ConfigError, 'Specify both of output_per_tag and tag_prefix'
60
+ end
61
+ @tag_prefix_string = @tag_prefix + '.' if @output_per_tag
49
62
 
50
63
  @count = count_initialized
51
64
  @mutex = Mutex.new
@@ -106,42 +119,46 @@ class Fluent::NumericMonitorOutput < Fluent::Output
106
119
  tag
107
120
  end
108
121
 
109
- def generate_output(count)
110
- output = {}
111
- if @aggregate == :all
112
- c = count['all']
113
- if c[:num] then output['num'] = c[:num] end
114
- if c[:min] then output['min'] = c[:min] end
115
- if c[:max] then output['max'] = c[:max] end
116
- if c[:num] > 0 then output['avg'] = (c[:sum] * 100.0 / (c[:num] * 1.0)).round / 100.0 end
117
- if @percentiles
118
- sorted = c[:sample].sort
119
- @percentiles.each do |p|
120
- i = (c[:num] * p / 100).floor
121
- if i > 0
122
- i -= 1
123
- end
124
- output["percentile_#{p}"] = sorted[i]
122
+ def generate_fields(count, key_prefix = '', output = {})
123
+ output[key_prefix + 'num'] = count[:num] if count[:num]
124
+ output[key_prefix + 'min'] = count[:min] if count[:min]
125
+ output[key_prefix + 'max'] = count[:max] if count[:max]
126
+ output[key_prefix + 'avg'] = (count[:sum] / (count[:num] * 1.0)) if count[:num] > 0
127
+ if @percentiles
128
+ sorted = count[:sample].sort
129
+ @percentiles.each do |p|
130
+ i = (count[:num] * p / 100).floor
131
+ if i > 0
132
+ i -= 1
125
133
  end
134
+ output[key_prefix + "percentile_#{p}"] = sorted[i]
126
135
  end
127
- return output
128
136
  end
137
+ output
138
+ end
129
139
 
130
- count.keys.each do |tag|
131
- t = stripped_tag(tag)
132
- c = count[tag]
133
- if c[:num] then output[t + '_num'] = c[:num] end
134
- if c[:min] then output[t + '_min'] = c[:min] end
135
- if c[:max] then output[t + '_max'] = c[:max] end
136
- if c[:num] > 0 then output[t + '_avg'] = (c[:sum] * 100.0 / (c[:num] * 1.0)).round / 100.0 end
137
- if @percentiles
138
- sorted = c[:sample].sort
139
- @percentiles.each do |p|
140
- i = (c[:num] * p / 100).floor
141
- if i > 0
142
- i -= 1
143
- end
144
- output[t + "_percentile_#{p}"] = sorted[i]
140
+ def generate_output(count)
141
+ if @aggregate == :all
142
+ if @output_per_tag
143
+ # tag_prefix_all: { 'key_prefix_min' => -10, 'key_prefix_max' => 10, ... } }
144
+ output = {'all' => generate_fields(count['all'], @key_prefix_string)}
145
+ else
146
+ # tag: { 'key_prefix_min' => -10, 'key_prefix_max' => 10, ... }
147
+ output = generate_fields(count['all'], @key_prefix_string)
148
+ end
149
+ else
150
+ output = {}
151
+ if @output_per_tag
152
+ # tag_prefix_tag1: { 'key_prefix_min' => -10, 'key_prefix_max' => 10, ... }
153
+ # tag_prefix_tag2: { 'key_prefix_min' => -10, 'key_prefix_max' => 10, ... }
154
+ count.keys.each do |tag|
155
+ output[stripped_tag(tag)] = generate_fields(count[tag], @key_prefix_string)
156
+ end
157
+ else
158
+ # tag: { 'key_prefix_tag1_min' => -10, 'key_prefix_tag1_max' => 10, ..., 'key_prefix_tag2_min' => -10, 'key_prefix_tag2_max' => 10, ... }
159
+ count.keys.each do |tag|
160
+ key_prefix = @key_prefix_string + stripped_tag(tag) + '_'
161
+ generate_fields(count[tag], key_prefix, output)
145
162
  end
146
163
  end
147
164
  end
@@ -154,7 +171,14 @@ class Fluent::NumericMonitorOutput < Fluent::Output
154
171
  end
155
172
 
156
173
  def flush_emit
157
- Fluent::Engine.emit(@tag, Fluent::Engine.now, flush)
174
+ if @output_per_tag
175
+ time = Fluent::Engine.now
176
+ flush.each do |tag, message|
177
+ Fluent::Engine.emit(@tag_prefix_string + tag, time, message)
178
+ end
179
+ else
180
+ Fluent::Engine.emit(@tag, Fluent::Engine.now, flush)
181
+ end
158
182
  end
159
183
 
160
184
  def countups(tag, min, max, sum, num, sample)
@@ -18,6 +18,19 @@ class NumericMonitorOutputTest < Test::Unit::TestCase
18
18
  end
19
19
 
20
20
  def test_configure
21
+ assert_raise(Fluent::ConfigError) {
22
+ d = create_driver('')
23
+ }
24
+ assert_raise(Fluent::ConfigError) {
25
+ d = create_driver CONFIG + %[
26
+ output_per_tag true
27
+ ]
28
+ }
29
+ assert_raise(Fluent::ConfigError) {
30
+ d = create_driver CONFIG + %[
31
+ tag_prefix prefix
32
+ ]
33
+ }
21
34
  #TODO
22
35
  end
23
36
 
@@ -115,4 +128,228 @@ class NumericMonitorOutputTest < Test::Unit::TestCase
115
128
  assert_equal 2, r['test_avg']
116
129
  assert_equal 3, r['test_num']
117
130
  end
131
+
132
+ def test_output_per_tag
133
+ d = create_driver(CONFIG + %[
134
+ aggregate tag
135
+ output_per_tag true
136
+ tag_prefix tag_prefix
137
+ ], 'tag')
138
+ d.run do
139
+ d.tag = 'tag1'
140
+ d.emit({'field1' => 1})
141
+ d.emit({'field1' => 2})
142
+ d.emit({'field1' => 3})
143
+ d.tag = 'tag2'
144
+ d.emit({'field1' => 1})
145
+ d.emit({'field1' => 2})
146
+ d.emit({'field1' => 3})
147
+ end
148
+ d.instance.flush_emit
149
+ assert_equal 2, d.emits.size
150
+ tag, r = d.emits[0][0], d.emits[0][2]
151
+ assert_equal 'tag_prefix.tag1', tag
152
+ assert_equal 1, r['min']
153
+ assert_equal 3, r['max']
154
+ assert_equal 2, r['avg']
155
+ assert_equal 3, r['num']
156
+ tag, r = d.emits[1][0], d.emits[1][2]
157
+ assert_equal 'tag_prefix.tag2', tag
158
+ assert_equal 1, r['min']
159
+ assert_equal 3, r['max']
160
+ assert_equal 2, r['avg']
161
+ assert_equal 3, r['num']
162
+
163
+ d = create_driver(CONFIG + %[
164
+ aggregate tag
165
+ output_per_tag false
166
+ tag output_tag
167
+ ], 'tag')
168
+ d.run do
169
+ d.tag = 'tag1'
170
+ d.emit({'field1' => 1})
171
+ d.emit({'field1' => 2})
172
+ d.emit({'field1' => 3})
173
+ d.tag = 'tag2'
174
+ d.emit({'field1' => 1})
175
+ d.emit({'field1' => 2})
176
+ d.emit({'field1' => 3})
177
+ end
178
+ d.instance.flush_emit
179
+ assert_equal 1, d.emits.size
180
+ tag, r = d.emits[0][0], d.emits[0][2]
181
+ assert_equal 'output_tag', tag
182
+ assert_equal 1, r['tag1_min']
183
+ assert_equal 3, r['tag1_max']
184
+ assert_equal 2, r['tag1_avg']
185
+ assert_equal 3, r['tag1_num']
186
+ assert_equal 1, r['tag2_min']
187
+ assert_equal 3, r['tag2_max']
188
+ assert_equal 2, r['tag2_avg']
189
+ assert_equal 3, r['tag2_num']
190
+
191
+ d = create_driver(CONFIG + %[
192
+ aggregate all
193
+ output_per_tag true
194
+ tag_prefix tag_prefix
195
+ ], 'tag')
196
+ d.run do
197
+ d.tag = 'tag1'
198
+ d.emit({'field1' => 1})
199
+ d.emit({'field1' => 2})
200
+ d.emit({'field1' => 3})
201
+ d.tag = 'tag2'
202
+ d.emit({'field1' => 1})
203
+ d.emit({'field1' => 2})
204
+ d.emit({'field1' => 3})
205
+ end
206
+ d.instance.flush_emit
207
+ assert_equal 1, d.emits.size
208
+ tag = d.emits[0][0]
209
+ r = d.emits[0][2]
210
+ assert_equal 'tag_prefix.all', tag
211
+ assert_equal 1, r['min']
212
+ assert_equal 3, r['max']
213
+ assert_equal 2, r['avg']
214
+ assert_equal 6, r['num']
215
+
216
+ d = create_driver(CONFIG + %[
217
+ aggregate all
218
+ output_per_tag false
219
+ tag output_tag
220
+ ], 'tag')
221
+ d.run do
222
+ d.tag = 'tag1'
223
+ d.emit({'field1' => 1})
224
+ d.emit({'field1' => 2})
225
+ d.emit({'field1' => 3})
226
+ d.tag = 'tag2'
227
+ d.emit({'field1' => 1})
228
+ d.emit({'field1' => 2})
229
+ d.emit({'field1' => 3})
230
+ end
231
+ d.instance.flush_emit
232
+ assert_equal 1, d.emits.size
233
+ tag = d.emits[0][0]
234
+ r = d.emits[0][2]
235
+ assert_equal 'output_tag', tag
236
+ assert_equal 1, r['min']
237
+ assert_equal 3, r['max']
238
+ assert_equal 2, r['avg']
239
+ assert_equal 6, r['num']
240
+ end
241
+
242
+ def test_output_key_prefix
243
+ d = create_driver(CONFIG + %[
244
+ aggregate tag
245
+ output_per_tag true
246
+ tag_prefix tag_prefix
247
+ output_key_prefix key_prefix
248
+ ], 'tag')
249
+ d.run do
250
+ d.tag = 'tag1'
251
+ d.emit({'field1' => 1})
252
+ d.emit({'field1' => 2})
253
+ d.emit({'field1' => 3})
254
+ d.tag = 'tag2'
255
+ d.emit({'field1' => 1})
256
+ d.emit({'field1' => 2})
257
+ d.emit({'field1' => 3})
258
+ end
259
+ d.instance.flush_emit
260
+ assert_equal 2, d.emits.size
261
+ tag, r = d.emits[0][0], d.emits[0][2]
262
+ assert_equal 'tag_prefix.tag1', tag
263
+ assert_equal 1, r['key_prefix_min']
264
+ assert_equal 3, r['key_prefix_max']
265
+ assert_equal 2, r['key_prefix_avg']
266
+ assert_equal 3, r['key_prefix_num']
267
+ tag, r = d.emits[1][0], d.emits[1][2]
268
+ assert_equal 'tag_prefix.tag2', tag
269
+ assert_equal 1, r['key_prefix_min']
270
+ assert_equal 3, r['key_prefix_max']
271
+ assert_equal 2, r['key_prefix_avg']
272
+ assert_equal 3, r['key_prefix_num']
273
+
274
+ d = create_driver(CONFIG + %[
275
+ aggregate tag
276
+ output_per_tag false
277
+ tag output_tag
278
+ output_key_prefix key_prefix
279
+ ], 'tag')
280
+ d.run do
281
+ d.tag = 'tag1'
282
+ d.emit({'field1' => 1})
283
+ d.emit({'field1' => 2})
284
+ d.emit({'field1' => 3})
285
+ d.tag = 'tag2'
286
+ d.emit({'field1' => 1})
287
+ d.emit({'field1' => 2})
288
+ d.emit({'field1' => 3})
289
+ end
290
+ d.instance.flush_emit
291
+ assert_equal 1, d.emits.size
292
+ tag, r = d.emits[0][0], d.emits[0][2]
293
+ assert_equal 'output_tag', tag
294
+ assert_equal 1, r['key_prefix_tag1_min']
295
+ assert_equal 3, r['key_prefix_tag1_max']
296
+ assert_equal 2, r['key_prefix_tag1_avg']
297
+ assert_equal 3, r['key_prefix_tag1_num']
298
+ assert_equal 1, r['key_prefix_tag2_min']
299
+ assert_equal 3, r['key_prefix_tag2_max']
300
+ assert_equal 2, r['key_prefix_tag2_avg']
301
+ assert_equal 3, r['key_prefix_tag2_num']
302
+
303
+ d = create_driver(CONFIG + %[
304
+ aggregate all
305
+ output_per_tag true
306
+ tag_prefix tag_prefix
307
+ output_key_prefix key_prefix
308
+ ], 'tag')
309
+ d.run do
310
+ d.tag = 'tag1'
311
+ d.emit({'field1' => 1})
312
+ d.emit({'field1' => 2})
313
+ d.emit({'field1' => 3})
314
+ d.tag = 'tag2'
315
+ d.emit({'field1' => 1})
316
+ d.emit({'field1' => 2})
317
+ d.emit({'field1' => 3})
318
+ end
319
+ d.instance.flush_emit
320
+ assert_equal 1, d.emits.size
321
+ tag = d.emits[0][0]
322
+ r = d.emits[0][2]
323
+ assert_equal 'tag_prefix.all', tag
324
+ assert_equal 1, r['key_prefix_min']
325
+ assert_equal 3, r['key_prefix_max']
326
+ assert_equal 2, r['key_prefix_avg']
327
+ assert_equal 6, r['key_prefix_num']
328
+
329
+ d = create_driver(CONFIG + %[
330
+ aggregate all
331
+ output_per_tag false
332
+ tag output_tag
333
+ output_key_prefix key_prefix
334
+ ], 'tag')
335
+ d.run do
336
+ d.tag = 'tag1'
337
+ d.emit({'field1' => 1})
338
+ d.emit({'field1' => 2})
339
+ d.emit({'field1' => 3})
340
+ d.tag = 'tag2'
341
+ d.emit({'field1' => 1})
342
+ d.emit({'field1' => 2})
343
+ d.emit({'field1' => 3})
344
+ end
345
+ d.instance.flush_emit
346
+ assert_equal 1, d.emits.size
347
+ tag = d.emits[0][0]
348
+ r = d.emits[0][2]
349
+ assert_equal 'output_tag', tag
350
+ assert_equal 1, r['key_prefix_min']
351
+ assert_equal 3, r['key_prefix_max']
352
+ assert_equal 2, r['key_prefix_avg']
353
+ assert_equal 6, r['key_prefix_num']
354
+ end
118
355
  end
metadata CHANGED
@@ -1,46 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-numeric-monitor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
5
- prerelease:
4
+ version: 0.1.5
6
5
  platform: ruby
7
6
  authors:
8
7
  - TAGOMORI Satoshi
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-04-08 00:00:00.000000000 Z
11
+ date: 2013-06-07 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rake
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: fluentd
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - '>='
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - '>='
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
41
  description: Fluentd plugin to calculate min/max/avg/Xpercentile values, and emit
@@ -62,27 +57,26 @@ files:
62
57
  - test/plugin/test_out_numeric_monitor.rb
63
58
  homepage: https://github.com/tagomoris/fluent-plugin-numeric-monitor
64
59
  licenses: []
60
+ metadata: {}
65
61
  post_install_message:
66
62
  rdoc_options: []
67
63
  require_paths:
68
64
  - lib
69
65
  required_ruby_version: !ruby/object:Gem::Requirement
70
- none: false
71
66
  requirements:
72
- - - ! '>='
67
+ - - '>='
73
68
  - !ruby/object:Gem::Version
74
69
  version: '0'
75
70
  required_rubygems_version: !ruby/object:Gem::Requirement
76
- none: false
77
71
  requirements:
78
- - - ! '>='
72
+ - - '>='
79
73
  - !ruby/object:Gem::Version
80
74
  version: '0'
81
75
  requirements: []
82
76
  rubyforge_project:
83
- rubygems_version: 1.8.23
77
+ rubygems_version: 2.0.2
84
78
  signing_key:
85
- specification_version: 3
79
+ specification_version: 4
86
80
  summary: Fluentd plugin to calculate min/max/avg/Xpercentile values
87
81
  test_files:
88
82
  - test/helper.rb