fluent-plugin-numeric-counter 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |gem|
4
4
  gem.name = "fluent-plugin-numeric-counter"
5
- gem.version = "0.1.1"
5
+ gem.version = "0.2.0"
6
6
  gem.authors = ["TAGOMORI Satoshi"]
7
7
  gem.email = ["tagomoris@gmail.com"]
8
8
  gem.description = %q{Counts messages, with specified key and numeric value in specified range}
@@ -105,11 +105,12 @@ class Fluent::NumericCounterOutput < Fluent::Output
105
105
 
106
106
  def count_initialized(keys=nil)
107
107
  # counts['tag'][pattern_index_num] = count
108
+ # counts['tag'][-1] = sum
108
109
  if @aggregate == :all
109
- {'all' => Array.new(@patterns.length){|i| 0}}
110
+ {'all' => Array.new(@patterns.length + 1){|i| 0}}
110
111
  elsif keys
111
112
  values = Array.new(keys.length){|i|
112
- Array.new(@patterns.length){|j| 0 }
113
+ Array.new(@patterns.length + 1){|j| 0 }
113
114
  }
114
115
  Hash[[keys, values].transpose]
115
116
  else
@@ -123,10 +124,13 @@ class Fluent::NumericCounterOutput < Fluent::Output
123
124
  end
124
125
 
125
126
  @mutex.synchronize {
126
- @counts[tag] ||= [0] * @patterns.length
127
+ @counts[tag] ||= [0] * (@patterns.length + 1)
128
+ sum = 0
127
129
  counts.each_with_index do |count, i|
130
+ sum += count
128
131
  @counts[tag][i] += count
129
132
  end
133
+ @counts[tag][-1] += sum
130
134
  }
131
135
  end
132
136
 
@@ -139,11 +143,11 @@ class Fluent::NumericCounterOutput < Fluent::Output
139
143
 
140
144
  def generate_fields(step, target_counts, attr_prefix, output)
141
145
  sum = if @outcast_unmatched
142
- target_counts[1..-1].inject(:+)
146
+ target_counts[1..-2].inject(:+)
143
147
  else
144
- target_counts.inject(:+)
148
+ target_counts[-1]
145
149
  end
146
- messages = sum + (@outcast_unmatched ? target_counts[0] : 0)
150
+ messages = target_counts.delete_at(-1)
147
151
 
148
152
  target_counts.each_with_index do |count,i|
149
153
  name = @patterns[i][1]
@@ -185,12 +189,12 @@ class Fluent::NumericCounterOutput < Fluent::Output
185
189
  end
186
190
 
187
191
  def flush(step) # returns one message
188
- flushed,@counts = @counts,count_initialized(@counts.keys.dup)
192
+ flushed,@counts = @counts,count_initialized(@counts.keys.dup.select{|k| @counts[k][-1] > 0})
189
193
  generate_output(flushed, step)
190
194
  end
191
195
 
192
196
  def flush_per_tags(step) # returns map of tag - message
193
- flushed,@counts = @counts,count_initialized(@counts.keys.dup)
197
+ flushed,@counts = @counts,count_initialized(@counts.keys.dup.select{|k| @counts[k][-1] > 0})
194
198
  generate_output_per_tags(flushed, step)
195
199
  end
196
200
 
@@ -201,7 +205,10 @@ class Fluent::NumericCounterOutput < Fluent::Output
201
205
  Fluent::Engine.emit(@tag_prefix_string + tag, time, message)
202
206
  end
203
207
  else
204
- Fluent::Engine.emit(@tag, Fluent::Engine.now, flush(step))
208
+ message = flush(step)
209
+ if message.keys.size > 0
210
+ Fluent::Engine.emit(@tag, Fluent::Engine.now, message)
211
+ end
205
212
  end
206
213
  end
207
214
 
@@ -119,11 +119,11 @@ class NumericCounterOutputTest < Test::Unit::TestCase
119
119
  assert_nil d.instance.counts['test.input']
120
120
 
121
121
  d.instance.countups('test.input', [0, 0, 0, 0])
122
- assert_equal [0,0,0,0], d.instance.counts['test.input']
122
+ assert_equal [0,0,0,0,0], d.instance.counts['test.input']
123
123
  d.instance.countups('test.input', [1, 1, 1, 0])
124
- assert_equal [1,1,1,0], d.instance.counts['test.input']
124
+ assert_equal [1,1,1,0,3], d.instance.counts['test.input']
125
125
  d.instance.countups('test.input', [0, 5, 1, 0])
126
- assert_equal [1,6,2,0], d.instance.counts['test.input']
126
+ assert_equal [1,6,2,0,9], d.instance.counts['test.input']
127
127
  end
128
128
 
129
129
  def test_generate_output
@@ -132,7 +132,7 @@ class NumericCounterOutputTest < Test::Unit::TestCase
132
132
  # pattern2 u1s 100000 1000000
133
133
  # pattern3 u3s 1000000 3000000
134
134
 
135
- r1 = d.instance.generate_output({'test.input' => [60,240,180,120], 'test.input2' => [0,600,0,0]}, 60)
135
+ r1 = d.instance.generate_output({'test.input' => [60,240,180,120,600], 'test.input2' => [0,600,0,0,600]}, 60)
136
136
  assert_equal 60, r1['input_unmatched_count']
137
137
  assert_equal 1.0, r1['input_unmatched_rate']
138
138
  assert_equal 10.0, r1['input_unmatched_percentage']
@@ -163,7 +163,7 @@ class NumericCounterOutputTest < Test::Unit::TestCase
163
163
 
164
164
  d = create_driver(CONFIG + "\n output_messages yes \n")
165
165
 
166
- r1 = d.instance.generate_output({'test.input' => [60,240,180,120], 'test.input2' => [0,600,0,0]}, 60)
166
+ r1 = d.instance.generate_output({'test.input' => [60,240,180,120,600], 'test.input2' => [0,600,0,0,600]}, 60)
167
167
  assert_equal 600, r1['input_messages']
168
168
  assert_equal 600, r1['input2_messages']
169
169
 
@@ -174,7 +174,7 @@ class NumericCounterOutputTest < Test::Unit::TestCase
174
174
  outcast_unmatched yes
175
175
  output_messages true
176
176
  ]
177
- r2 = d.instance.generate_output({'all' => [60,240]}, 60)
177
+ r2 = d.instance.generate_output({'all' => [60,240,300]}, 60)
178
178
  assert_equal 60, r2['unmatched_count']
179
179
  assert_equal 1.0, r2['unmatched_rate']
180
180
  assert_nil r2['unmatched_percentage']
@@ -190,7 +190,7 @@ class NumericCounterOutputTest < Test::Unit::TestCase
190
190
  # pattern2 u1s 100000 1000000
191
191
  # pattern3 u3s 1000000 3000000
192
192
 
193
- r1 = d.instance.generate_output_per_tags({'test.input' => [60,240,180,120], 'test.input2' => [0,600,0,0]}, 60)
193
+ r1 = d.instance.generate_output_per_tags({'test.input' => [60,240,180,120,600], 'test.input2' => [0,600,0,0,600]}, 60)
194
194
  assert_equal 2, r1.keys.size
195
195
 
196
196
  r = r1['input']
@@ -225,7 +225,7 @@ class NumericCounterOutputTest < Test::Unit::TestCase
225
225
 
226
226
  d = create_driver(CONFIG_OUTPUT_PER_TAG)
227
227
 
228
- r1 = d.instance.generate_output_per_tags({'test.input' => [60,240,180,120], 'test.input2' => [0,600,0,0]}, 60)
228
+ r1 = d.instance.generate_output_per_tags({'test.input' => [60,240,180,120,600], 'test.input2' => [0,600,0,0,600]}, 60)
229
229
  assert_equal 600, r1['input']['messages']
230
230
  assert_equal 600, r1['input2']['messages']
231
231
 
@@ -236,7 +236,7 @@ class NumericCounterOutputTest < Test::Unit::TestCase
236
236
  outcast_unmatched yes
237
237
  output_messages true
238
238
  ]
239
- r2 = d.instance.generate_output_per_tags({'all' => [60,240]}, 60)
239
+ r2 = d.instance.generate_output_per_tags({'all' => [60,240,300]}, 60)
240
240
  assert_equal 60, r2['all']['unmatched_count']
241
241
  assert_equal 1.0, r2['all']['unmatched_rate']
242
242
  assert_nil r2['all']['unmatched_percentage']
@@ -409,4 +409,91 @@ class NumericCounterOutputTest < Test::Unit::TestCase
409
409
  assert_equal 20, r['unmatched_percentage']
410
410
  assert_equal 300, r['messages']
411
411
  end
412
+
413
+ def test_zero_tags
414
+ fields = ['unmatched','u100ms','u1s','u3s'].map{|k| 'tag1_' + k}.map{|p|
415
+ ['count', 'rate', 'percentage'].map{|a| p + '_' + a}
416
+ }.flatten
417
+ fields_without_percentage = ['unmatched','u100ms','u1s','u3s'].map{|k| 'tag1_' + k}.map{|p|
418
+ ['count', 'rate'].map{|a| p + '_' + a}
419
+ }.flatten
420
+
421
+ d = create_driver(CONFIG, 'test.tag1')
422
+ # CONFIG = %[
423
+ # count_interval 60
424
+ # aggregate tag
425
+ # input_tag_remove_prefix test
426
+ # count_key target
427
+ # pattern1 u100ms 0 100000
428
+ # pattern2 u1s 100000 1000000
429
+ # pattern3 u3s 1000000 3000000
430
+ # ]
431
+ d.run do
432
+ 60.times do
433
+ d.emit({'target' => '50000'})
434
+ d.emit({'target' => '100000'})
435
+ d.emit({'target' => '100001'})
436
+ d.emit({'target' => '0.0'})
437
+ d.emit({'target' => '-1'})
438
+ end
439
+ end
440
+ d.instance.flush_emit(60)
441
+ assert_equal 1, d.emits.size
442
+ r1 = d.emits[0][2]
443
+ assert_equal fields, r1.keys
444
+
445
+ d.instance.flush_emit(60)
446
+ assert_equal 2, d.emits.size # +1
447
+ r2 = d.emits[1][2]
448
+ assert_equal fields_without_percentage, r2.keys
449
+ assert_equal [0]*8, r2.values
450
+
451
+ d.instance.flush_emit(60)
452
+ assert_equal 2, d.emits.size # +0
453
+ end
454
+
455
+ def test_zero_tags_per_tag
456
+ fields = (['unmatched','u100ms','u1s','u3s'].map{|p|
457
+ ['count', 'rate', 'percentage'].map{|a| p + '_' + a}
458
+ }.flatten + ['messages']).sort
459
+ fields_without_percentage = (['unmatched','u100ms','u1s','u3s'].map{|p|
460
+ ['count', 'rate'].map{|a| p + '_' + a}
461
+ }.flatten + ['messages']).sort
462
+
463
+ d = create_driver(CONFIG_OUTPUT_PER_TAG, 'test.tag1')
464
+ # CONFIG_OUTPUT_PER_TAG = %[
465
+ # count_interval 60
466
+ # aggregate tag
467
+ # output_per_tag true
468
+ # tag_prefix n
469
+ # input_tag_remove_prefix test
470
+ # count_key target
471
+ # pattern1 u100ms 0 100000
472
+ # pattern2 u1s 100000 1000000
473
+ # pattern3 u3s 1000000 3000000
474
+ # output_messages true
475
+ # ]
476
+ d.run do
477
+ 60.times do
478
+ d.emit({'target' => '50000'})
479
+ d.emit({'target' => '100000'})
480
+ d.emit({'target' => '100001'})
481
+ d.emit({'target' => '0.0'})
482
+ d.emit({'target' => '-1'})
483
+ end
484
+ end
485
+ d.instance.flush_emit(60)
486
+ assert_equal 1, d.emits.size
487
+ r1 = d.emits[0][2]
488
+ assert_equal fields, r1.keys.sort
489
+
490
+ d.instance.flush_emit(60)
491
+ assert_equal 2, d.emits.size # +1
492
+ r2 = d.emits[1][2]
493
+ assert_equal fields_without_percentage, r2.keys.sort
494
+ assert_equal [0]*9, r2.values # (_count, _rate) x4 + messages
495
+
496
+ d.instance.flush_emit(60)
497
+ assert_equal 2, d.emits.size # +0
498
+ end
412
499
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-numeric-counter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: