fluent-plugin-numeric-counter 0.1.0 → 0.1.1
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.
- data/README.md +52 -0
- data/fluent-plugin-numeric-counter.gemspec +2 -1
- data/lib/fluent/plugin/out_numeric_counter.rb +59 -34
- data/test/plugin/test_out_numeric_counter.rb +222 -0
- metadata +18 -2
    
        data/README.md
    CHANGED
    
    | @@ -61,6 +61,58 @@ Size specifier (like 10k, 5M, 103g) available as 1024\*\*1, 1024\*\*2, 1024\*\*3 | |
| 61 61 |  | 
| 62 62 | 
             
            You can try to use negative numbers, and floating point numbers.... (not tested enough).
         | 
| 63 63 |  | 
| 64 | 
            +
            With 'output\_per\_tag' option and 'tag\_prefix', we get one result message for one tag:
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                <match accesslog.{foo,bar}>
         | 
| 67 | 
            +
                  type numeric_counter
         | 
| 68 | 
            +
                  unit hour
         | 
| 69 | 
            +
                  aggregate tag
         | 
| 70 | 
            +
                  count_key bytes
         | 
| 71 | 
            +
                  output_per_tag yes
         | 
| 72 | 
            +
                  tag_prefix byteslog
         | 
| 73 | 
            +
                  input_tag_remove_prefix accesslog
         | 
| 74 | 
            +
                  
         | 
| 75 | 
            +
                  pattern1 SMALL    0 1k
         | 
| 76 | 
            +
                  pattern2 MIDDLE  1k 1m
         | 
| 77 | 
            +
                  pattern3 LARGE   1m 10m
         | 
| 78 | 
            +
                  pattern4 HUGE   10m 1g
         | 
| 79 | 
            +
                  pattern5 XXXX    1g
         | 
| 80 | 
            +
                </match>
         | 
| 81 | 
            +
                # => tag: 'byteslog.foo' and 'byteslog.bar'
         | 
| 82 | 
            +
                #    message: {'SMALL_count' => 100, ... }
         | 
| 83 | 
            +
             | 
| 84 | 
            +
            And you can get tested messages count with 'output\_messages' option:
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                <match accesslog.{foo,bar}>
         | 
| 87 | 
            +
                  type numeric_counter
         | 
| 88 | 
            +
                  unit hour
         | 
| 89 | 
            +
                  aggregate tag
         | 
| 90 | 
            +
                  count_key bytes
         | 
| 91 | 
            +
                  input_tag_remove_prefix accesslog
         | 
| 92 | 
            +
                  output_messages yes
         | 
| 93 | 
            +
                  
         | 
| 94 | 
            +
                  pattern1 SMALL    0 1k
         | 
| 95 | 
            +
                  pattern2 LARGE   1k
         | 
| 96 | 
            +
                </match>
         | 
| 97 | 
            +
                # => tag: 'numcount'
         | 
| 98 | 
            +
                #    message: {'foo_messages' => xxx, 'bar_messages' => yyy, 'foo_SMALL_count' => 100, ... }
         | 
| 99 | 
            +
                
         | 
| 100 | 
            +
                <match accesslog.{foo,bar}>
         | 
| 101 | 
            +
                  type numeric_counter
         | 
| 102 | 
            +
                  unit hour
         | 
| 103 | 
            +
                  aggregate tag
         | 
| 104 | 
            +
                  count_key bytes
         | 
| 105 | 
            +
                  output_per_tag yes
         | 
| 106 | 
            +
                  tag_prefix num
         | 
| 107 | 
            +
                  input_tag_remove_prefix accesslog
         | 
| 108 | 
            +
                  output_messages yes
         | 
| 109 | 
            +
                  
         | 
| 110 | 
            +
                  pattern1 SMALL    0 1k
         | 
| 111 | 
            +
                  pattern2 LARGE   1k
         | 
| 112 | 
            +
                </match>
         | 
| 113 | 
            +
                # => tag: 'num.foo' or 'num.bar'
         | 
| 114 | 
            +
                #    message: {'messages' => xxx, 'SMALL_count' => 100, ... }
         | 
| 115 | 
            +
             | 
| 64 116 | 
             
            ## TODO
         | 
| 65 117 |  | 
| 66 118 | 
             
            * more tests
         | 
| @@ -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. | 
| 5 | 
            +
              gem.version       = "0.1.1"
         | 
| 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}
         | 
| @@ -14,6 +14,7 @@ Gem::Specification.new do |gem| | |
| 14 14 | 
             
              gem.test_files    = gem.files.grep(%r{^(test|spec|features)/})
         | 
| 15 15 | 
             
              gem.require_paths = ["lib"]
         | 
| 16 16 |  | 
| 17 | 
            +
              gem.add_development_dependency "rake"
         | 
| 17 18 | 
             
              gem.add_development_dependency "fluentd"
         | 
| 18 19 | 
             
              gem.add_runtime_dependency "fluentd"
         | 
| 19 20 | 
             
            end
         | 
| @@ -5,11 +5,14 @@ class Fluent::NumericCounterOutput < Fluent::Output | |
| 5 5 |  | 
| 6 6 | 
             
              config_param :count_interval, :time, :default => 60
         | 
| 7 7 | 
             
              config_param :unit, :string, :default => nil
         | 
| 8 | 
            +
              config_param :output_per_tag, :bool, :default => false
         | 
| 8 9 | 
             
              config_param :aggregate, :string, :default => 'tag'
         | 
| 9 10 | 
             
              config_param :tag, :string, :default => 'numcount'
         | 
| 11 | 
            +
              config_param :tag_prefix, :string, :default => nil
         | 
| 10 12 | 
             
              config_param :input_tag_remove_prefix, :string, :default => nil
         | 
| 11 13 | 
             
              config_param :count_key, :string
         | 
| 12 14 | 
             
              config_param :outcast_unmatched, :bool, :default => false
         | 
| 15 | 
            +
              config_param :output_messages, :bool, :default => false
         | 
| 13 16 |  | 
| 14 17 | 
             
              # pattern0 reserved as unmatched counts
         | 
| 15 18 | 
             
              config_param :pattern1, :string # string: NAME LOW HIGH
         | 
| @@ -20,8 +23,6 @@ class Fluent::NumericCounterOutput < Fluent::Output | |
| 20 23 |  | 
| 21 24 | 
             
              attr_accessor :counts, :last_checked
         | 
| 22 25 |  | 
| 23 | 
            -
              # for test
         | 
| 24 | 
            -
              # attr_accessor :count_interval, :unit, :aggregate, :tag, :input_tag_remove_prefix, :count_key, :outcast_unmatched
         | 
| 25 26 | 
             
              attr_accessor :patterns
         | 
| 26 27 |  | 
| 27 28 | 
             
              def parse_num(str)
         | 
| @@ -77,6 +78,11 @@ class Fluent::NumericCounterOutput < Fluent::Output | |
| 77 78 | 
             
                  raise Fluent::ConfigError, "unspecified high threshold allowed only in last pattern" if high.nil? and index != @patterns.length - 1
         | 
| 78 79 | 
             
                end
         | 
| 79 80 |  | 
| 81 | 
            +
                if @output_per_tag
         | 
| 82 | 
            +
                  raise Fluent::ConfigError, "tag_prefix must be specified with output_per_tag" unless @tag_prefix
         | 
| 83 | 
            +
                  @tag_prefix_string = @tag_prefix + '.'
         | 
| 84 | 
            +
                end
         | 
| 85 | 
            +
             | 
| 80 86 | 
             
                if @input_tag_remove_prefix
         | 
| 81 87 | 
             
                  @removed_prefix_string = @input_tag_remove_prefix + '.'
         | 
| 82 88 | 
             
                  @removed_length = @removed_prefix_string.length
         | 
| @@ -131,53 +137,72 @@ class Fluent::NumericCounterOutput < Fluent::Output | |
| 131 137 | 
             
                tag
         | 
| 132 138 | 
             
              end
         | 
| 133 139 |  | 
| 140 | 
            +
              def generate_fields(step, target_counts, attr_prefix, output)
         | 
| 141 | 
            +
                sum = if @outcast_unmatched
         | 
| 142 | 
            +
                        target_counts[1..-1].inject(:+)
         | 
| 143 | 
            +
                      else
         | 
| 144 | 
            +
                        target_counts.inject(:+)
         | 
| 145 | 
            +
                      end
         | 
| 146 | 
            +
                messages = sum + (@outcast_unmatched ? target_counts[0] : 0)
         | 
| 147 | 
            +
             | 
| 148 | 
            +
                target_counts.each_with_index do |count,i|
         | 
| 149 | 
            +
                  name = @patterns[i][1]
         | 
| 150 | 
            +
                  output[attr_prefix + name + '_count'] = count
         | 
| 151 | 
            +
                  output[attr_prefix + name + '_rate'] = ((count * 100.0) / (1.00 * step)).floor / 100.0
         | 
| 152 | 
            +
                  unless i == 0 and @outcast_unmatched
         | 
| 153 | 
            +
                    output[attr_prefix + name + '_percentage'] = count * 100.0 / (1.00 * sum) if sum > 0
         | 
| 154 | 
            +
                  end
         | 
| 155 | 
            +
                  if @output_messages
         | 
| 156 | 
            +
                    output[attr_prefix + 'messages'] = messages
         | 
| 157 | 
            +
                  end
         | 
| 158 | 
            +
                end
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                output    
         | 
| 161 | 
            +
              end
         | 
| 162 | 
            +
             | 
| 134 163 | 
             
              def generate_output(counts, step)
         | 
| 164 | 
            +
                if @aggregate == :all
         | 
| 165 | 
            +
                  return generate_fields(step, counts['all'], '', {})
         | 
| 166 | 
            +
                end
         | 
| 167 | 
            +
             | 
| 135 168 | 
             
                output = {}
         | 
| 169 | 
            +
                counts.keys.each do |tag|
         | 
| 170 | 
            +
                  generate_fields(step, counts[tag], stripped_tag(tag) + '_', output)
         | 
| 171 | 
            +
                end
         | 
| 172 | 
            +
                output
         | 
| 173 | 
            +
              end
         | 
| 136 174 |  | 
| 175 | 
            +
              def generate_output_per_tags(counts, step)
         | 
| 137 176 | 
             
                if @aggregate == :all
         | 
| 138 | 
            -
                   | 
| 139 | 
            -
                  sum = if @outcast_unmatched
         | 
| 140 | 
            -
                          counts['all'][1..-1].inject(:+)
         | 
| 141 | 
            -
                        else
         | 
| 142 | 
            -
                          counts['all'].inject(:+)
         | 
| 143 | 
            -
                        end
         | 
| 144 | 
            -
                  counts['all'].each_with_index do |count,i|
         | 
| 145 | 
            -
                    name = @patterns[i][1]
         | 
| 146 | 
            -
                    output[name + '_count'] = count
         | 
| 147 | 
            -
                    output[name + '_rate'] = ((count * 100.0) / (1.00 * step)).floor / 100.0
         | 
| 148 | 
            -
                    unless i == 0 and @outcast_unmatched
         | 
| 149 | 
            -
                      output[name + '_percentage'] = count * 100.0 / (1.00 * sum) if sum > 0
         | 
| 150 | 
            -
                    end
         | 
| 151 | 
            -
                  end
         | 
| 152 | 
            -
                  return output
         | 
| 177 | 
            +
                  return {'all' => generate_fields(step, counts['all'], '', {})}
         | 
| 153 178 | 
             
                end
         | 
| 154 179 |  | 
| 180 | 
            +
                output_pairs = {}
         | 
| 155 181 | 
             
                counts.keys.each do |tag|
         | 
| 156 | 
            -
                   | 
| 157 | 
            -
                  sum = if @outcast_unmatched
         | 
| 158 | 
            -
                          counts[tag][1..-1].inject(:+)
         | 
| 159 | 
            -
                        else
         | 
| 160 | 
            -
                          counts[tag].inject(:+)
         | 
| 161 | 
            -
                        end
         | 
| 162 | 
            -
                  counts[tag].each_with_index do |count,i|
         | 
| 163 | 
            -
                    name = @patterns[i][1]
         | 
| 164 | 
            -
                    output[t + '_' + name + '_count'] = count
         | 
| 165 | 
            -
                    output[t + '_' + name + '_rate'] = ((count * 100.0) / (1.00 * step)).floor / 100.0
         | 
| 166 | 
            -
                    unless i == 0 and @outcast_unmatched
         | 
| 167 | 
            -
                      output[t + '_' + name + '_percentage'] = count * 100.0 / (1.00 * sum) if sum > 0
         | 
| 168 | 
            -
                    end
         | 
| 169 | 
            -
                  end
         | 
| 182 | 
            +
                  output_pairs[stripped_tag(tag)] = generate_fields(step, counts[tag], '', {})
         | 
| 170 183 | 
             
                end
         | 
| 171 | 
            -
                 | 
| 184 | 
            +
                output_pairs
         | 
| 172 185 | 
             
              end
         | 
| 173 186 |  | 
| 174 | 
            -
              def flush(step)
         | 
| 187 | 
            +
              def flush(step) # returns one message
         | 
| 175 188 | 
             
                flushed,@counts = @counts,count_initialized(@counts.keys.dup)
         | 
| 176 189 | 
             
                generate_output(flushed, step)
         | 
| 177 190 | 
             
              end
         | 
| 178 191 |  | 
| 192 | 
            +
              def flush_per_tags(step) # returns map of tag - message
         | 
| 193 | 
            +
                flushed,@counts = @counts,count_initialized(@counts.keys.dup)
         | 
| 194 | 
            +
                generate_output_per_tags(flushed, step)
         | 
| 195 | 
            +
              end
         | 
| 196 | 
            +
             | 
| 179 197 | 
             
              def flush_emit(step)
         | 
| 180 | 
            -
                 | 
| 198 | 
            +
                if @output_per_tag
         | 
| 199 | 
            +
                  time = Fluent::Engine.now
         | 
| 200 | 
            +
                  flush_per_tags(step).each do |tag,message|
         | 
| 201 | 
            +
                    Fluent::Engine.emit(@tag_prefix_string + tag, time, message)
         | 
| 202 | 
            +
                  end
         | 
| 203 | 
            +
                else
         | 
| 204 | 
            +
                  Fluent::Engine.emit(@tag, Fluent::Engine.now, flush(step))
         | 
| 205 | 
            +
                end
         | 
| 181 206 | 
             
              end
         | 
| 182 207 |  | 
| 183 208 | 
             
              def start_watch
         | 
| @@ -15,6 +15,19 @@ class NumericCounterOutputTest < Test::Unit::TestCase | |
| 15 15 | 
             
                pattern3 u3s 1000000 3000000
         | 
| 16 16 | 
             
              ]
         | 
| 17 17 |  | 
| 18 | 
            +
              CONFIG_OUTPUT_PER_TAG = %[
         | 
| 19 | 
            +
                count_interval 60
         | 
| 20 | 
            +
                aggregate tag
         | 
| 21 | 
            +
                output_per_tag true
         | 
| 22 | 
            +
                tag_prefix n
         | 
| 23 | 
            +
                input_tag_remove_prefix test
         | 
| 24 | 
            +
                count_key target
         | 
| 25 | 
            +
                pattern1 u100ms 0 100000
         | 
| 26 | 
            +
                pattern2 u1s 100000 1000000
         | 
| 27 | 
            +
                pattern3 u3s 1000000 3000000
         | 
| 28 | 
            +
                output_messages true
         | 
| 29 | 
            +
              ]
         | 
| 30 | 
            +
             | 
| 18 31 | 
             
              def create_driver(conf=CONFIG, tag='test')
         | 
| 19 32 | 
             
                Fluent::Test::OutputTestDriver.new(Fluent::NumericCounterOutput, tag).configure(conf)
         | 
| 20 33 | 
             
              end
         | 
| @@ -42,14 +55,63 @@ class NumericCounterOutputTest < Test::Unit::TestCase | |
| 42 55 | 
             
                assert_nil d.instance.input_tag_remove_prefix
         | 
| 43 56 | 
             
                assert_equal false, d.instance.outcast_unmatched
         | 
| 44 57 | 
             
                assert_equal [[0, 'unmatched', nil, nil], [1, 'smallnum', 0.1, 200], [2, 'subnum', -500, -1]], d.instance.patterns
         | 
| 58 | 
            +
                assert_equal false, d.instance.output_per_tag
         | 
| 59 | 
            +
                assert_equal false, d.instance.output_messages
         | 
| 45 60 |  | 
| 46 61 | 
             
                d = create_driver %[
         | 
| 47 62 | 
             
                  count_key key1
         | 
| 48 63 | 
             
                  pattern1 x 0.1 10
         | 
| 49 64 | 
             
                  pattern2 y 10 11
         | 
| 50 65 | 
             
                  pattern3 z 11
         | 
| 66 | 
            +
                  output_messages yes
         | 
| 51 67 | 
             
                ]
         | 
| 52 68 | 
             
                assert_equal [[0, 'unmatched', nil, nil], [1, 'x', 0.1, 10], [2, 'y', 10, 11], [3, 'z', 11, nil]], d.instance.patterns
         | 
| 69 | 
            +
                assert_equal true, d.instance.output_messages
         | 
| 70 | 
            +
              end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
              def test_configure_output_per_tag
         | 
| 73 | 
            +
                d = create_driver %[
         | 
| 74 | 
            +
                  count_key field1
         | 
| 75 | 
            +
                  pattern1 smallnum 0.1 200
         | 
| 76 | 
            +
                  pattern2 subnum   -500 -1
         | 
| 77 | 
            +
                  output_per_tag yes
         | 
| 78 | 
            +
                  tag_prefix numcount
         | 
| 79 | 
            +
                ]
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                assert_equal 60, d.instance.count_interval
         | 
| 82 | 
            +
                assert_equal :tag, d.instance.aggregate
         | 
| 83 | 
            +
                assert_equal 'numcount', d.instance.tag
         | 
| 84 | 
            +
                assert_nil d.instance.input_tag_remove_prefix
         | 
| 85 | 
            +
                assert_equal false, d.instance.outcast_unmatched
         | 
| 86 | 
            +
                assert_equal [[0, 'unmatched', nil, nil], [1, 'smallnum', 0.1, 200], [2, 'subnum', -500, -1]], d.instance.patterns
         | 
| 87 | 
            +
                assert_equal true, d.instance.output_per_tag
         | 
| 88 | 
            +
                assert_equal 'numcount', d.instance.tag_prefix
         | 
| 89 | 
            +
                assert_equal false, d.instance.output_messages
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                d = create_driver %[
         | 
| 92 | 
            +
                  count_key key1
         | 
| 93 | 
            +
                  pattern1 x 0.1 10
         | 
| 94 | 
            +
                  pattern2 y 10 11
         | 
| 95 | 
            +
                  pattern3 z 11
         | 
| 96 | 
            +
                  output_per_tag yes
         | 
| 97 | 
            +
                  tag_prefix n
         | 
| 98 | 
            +
                  output_messages yes
         | 
| 99 | 
            +
                ]
         | 
| 100 | 
            +
                assert_equal [[0, 'unmatched', nil, nil], [1, 'x', 0.1, 10], [2, 'y', 10, 11], [3, 'z', 11, nil]], d.instance.patterns
         | 
| 101 | 
            +
                assert_equal true, d.instance.output_per_tag
         | 
| 102 | 
            +
                assert_equal 'n', d.instance.tag_prefix
         | 
| 103 | 
            +
                assert_equal true, d.instance.output_messages
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                x_config = %[
         | 
| 106 | 
            +
                  count_key key1
         | 
| 107 | 
            +
                  pattern1 x 0.1 10
         | 
| 108 | 
            +
                  pattern2 y 10 11
         | 
| 109 | 
            +
                  pattern3 z 11
         | 
| 110 | 
            +
                  output_per_tag yes
         | 
| 111 | 
            +
                ]
         | 
| 112 | 
            +
                assert_raise(Fluent::ConfigError) {
         | 
| 113 | 
            +
                  d = create_driver(x_config)
         | 
| 114 | 
            +
                }
         | 
| 53 115 | 
             
              end
         | 
| 54 116 |  | 
| 55 117 | 
             
              def test_countups
         | 
| @@ -83,6 +145,7 @@ class NumericCounterOutputTest < Test::Unit::TestCase | |
| 83 145 | 
             
                assert_equal  120, r1['input_u3s_count']
         | 
| 84 146 | 
             
                assert_equal  2.0, r1['input_u3s_rate']
         | 
| 85 147 | 
             
                assert_equal 20.0, r1['input_u3s_percentage']
         | 
| 148 | 
            +
                assert_nil r1['input_messages']
         | 
| 86 149 |  | 
| 87 150 | 
             
                assert_equal    0, r1['input2_unmatched_count']
         | 
| 88 151 | 
             
                assert_equal  0.0, r1['input2_unmatched_rate']
         | 
| @@ -96,12 +159,20 @@ class NumericCounterOutputTest < Test::Unit::TestCase | |
| 96 159 | 
             
                assert_equal    0, r1['input2_u3s_count']
         | 
| 97 160 | 
             
                assert_equal  0.0, r1['input2_u3s_rate']
         | 
| 98 161 | 
             
                assert_equal  0.0, r1['input2_u3s_percentage']
         | 
| 162 | 
            +
                assert_nil r1['input2_messages']
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                d = create_driver(CONFIG + "\n output_messages yes \n")
         | 
| 165 | 
            +
             | 
| 166 | 
            +
                r1 = d.instance.generate_output({'test.input' => [60,240,180,120], 'test.input2' => [0,600,0,0]}, 60)
         | 
| 167 | 
            +
                assert_equal 600, r1['input_messages']
         | 
| 168 | 
            +
                assert_equal 600, r1['input2_messages']
         | 
| 99 169 |  | 
| 100 170 | 
             
                d = create_driver %[
         | 
| 101 171 | 
             
                  aggregate all
         | 
| 102 172 | 
             
                  count_key f1
         | 
| 103 173 | 
             
                  pattern1 good 1 2
         | 
| 104 174 | 
             
                  outcast_unmatched yes
         | 
| 175 | 
            +
                  output_messages true
         | 
| 105 176 | 
             
                ]
         | 
| 106 177 | 
             
                r2 = d.instance.generate_output({'all' => [60,240]}, 60)
         | 
| 107 178 | 
             
                assert_equal  60, r2['unmatched_count']
         | 
| @@ -110,6 +181,69 @@ class NumericCounterOutputTest < Test::Unit::TestCase | |
| 110 181 | 
             
                assert_equal 240, r2['good_count']
         | 
| 111 182 | 
             
                assert_equal 4.0, r2['good_rate']
         | 
| 112 183 | 
             
                assert_equal 100.0, r2['good_percentage']
         | 
| 184 | 
            +
                assert_equal 300, r2['messages']
         | 
| 185 | 
            +
              end
         | 
| 186 | 
            +
             | 
| 187 | 
            +
              def test_generate_output_per_tag
         | 
| 188 | 
            +
                d = create_driver(CONFIG_OUTPUT_PER_TAG + "\n output_messages false \n")
         | 
| 189 | 
            +
                # pattern1 u100ms 0 100000
         | 
| 190 | 
            +
                # pattern2 u1s 100000 1000000
         | 
| 191 | 
            +
                # pattern3 u3s 1000000 3000000
         | 
| 192 | 
            +
             | 
| 193 | 
            +
                r1 = d.instance.generate_output_per_tags({'test.input' => [60,240,180,120], 'test.input2' => [0,600,0,0]}, 60)
         | 
| 194 | 
            +
                assert_equal 2, r1.keys.size
         | 
| 195 | 
            +
             | 
| 196 | 
            +
                r = r1['input']
         | 
| 197 | 
            +
                assert_equal   60, r['unmatched_count']
         | 
| 198 | 
            +
                assert_equal  1.0, r['unmatched_rate']
         | 
| 199 | 
            +
                assert_equal 10.0, r['unmatched_percentage']
         | 
| 200 | 
            +
                assert_equal  240, r['u100ms_count']
         | 
| 201 | 
            +
                assert_equal  4.0, r['u100ms_rate']
         | 
| 202 | 
            +
                assert_equal 40.0, r['u100ms_percentage']
         | 
| 203 | 
            +
                assert_equal  180, r['u1s_count']
         | 
| 204 | 
            +
                assert_equal  3.0, r['u1s_rate']
         | 
| 205 | 
            +
                assert_equal 30.0, r['u1s_percentage']
         | 
| 206 | 
            +
                assert_equal  120, r['u3s_count']
         | 
| 207 | 
            +
                assert_equal  2.0, r['u3s_rate']
         | 
| 208 | 
            +
                assert_equal 20.0, r['u3s_percentage']
         | 
| 209 | 
            +
                assert_nil r['messages']
         | 
| 210 | 
            +
             | 
| 211 | 
            +
                r = r1['input2']
         | 
| 212 | 
            +
                assert_equal    0, r['unmatched_count']
         | 
| 213 | 
            +
                assert_equal  0.0, r['unmatched_rate']
         | 
| 214 | 
            +
                assert_equal  0.0, r['unmatched_percentage']
         | 
| 215 | 
            +
                assert_equal  600, r['u100ms_count']
         | 
| 216 | 
            +
                assert_equal 10.0, r['u100ms_rate']
         | 
| 217 | 
            +
                assert_equal 100.0, r['u100ms_percentage']
         | 
| 218 | 
            +
                assert_equal    0, r['u1s_count']
         | 
| 219 | 
            +
                assert_equal  0.0, r['u1s_rate']
         | 
| 220 | 
            +
                assert_equal  0.0, r['u1s_percentage']
         | 
| 221 | 
            +
                assert_equal    0, r['u3s_count']
         | 
| 222 | 
            +
                assert_equal  0.0, r['u3s_rate']
         | 
| 223 | 
            +
                assert_equal  0.0, r['u3s_percentage']
         | 
| 224 | 
            +
                assert_nil r['messages']
         | 
| 225 | 
            +
             | 
| 226 | 
            +
                d = create_driver(CONFIG_OUTPUT_PER_TAG)
         | 
| 227 | 
            +
             | 
| 228 | 
            +
                r1 = d.instance.generate_output_per_tags({'test.input' => [60,240,180,120], 'test.input2' => [0,600,0,0]}, 60)
         | 
| 229 | 
            +
                assert_equal 600, r1['input']['messages']
         | 
| 230 | 
            +
                assert_equal 600, r1['input2']['messages']
         | 
| 231 | 
            +
             | 
| 232 | 
            +
                d = create_driver %[
         | 
| 233 | 
            +
                  aggregate all
         | 
| 234 | 
            +
                  count_key f1
         | 
| 235 | 
            +
                  pattern1 good 1 2
         | 
| 236 | 
            +
                  outcast_unmatched yes
         | 
| 237 | 
            +
                  output_messages true
         | 
| 238 | 
            +
                ]
         | 
| 239 | 
            +
                r2 = d.instance.generate_output_per_tags({'all' => [60,240]}, 60)
         | 
| 240 | 
            +
                assert_equal  60, r2['all']['unmatched_count']
         | 
| 241 | 
            +
                assert_equal 1.0, r2['all']['unmatched_rate']
         | 
| 242 | 
            +
                assert_nil r2['all']['unmatched_percentage']
         | 
| 243 | 
            +
                assert_equal 240, r2['all']['good_count']
         | 
| 244 | 
            +
                assert_equal 4.0, r2['all']['good_rate']
         | 
| 245 | 
            +
                assert_equal 100.0, r2['all']['good_percentage']
         | 
| 246 | 
            +
                assert_equal 300, r2['all']['messages']
         | 
| 113 247 | 
             
              end
         | 
| 114 248 |  | 
| 115 249 | 
             
              def test_pattern_num
         | 
| @@ -186,5 +320,93 @@ class NumericCounterOutputTest < Test::Unit::TestCase | |
| 186 320 | 
             
                assert_equal 60, r['tag1_unmatched_count']
         | 
| 187 321 | 
             
                assert_equal 1.0, r['tag1_unmatched_rate']
         | 
| 188 322 | 
             
                assert_equal 20, r['tag1_unmatched_percentage']
         | 
| 323 | 
            +
             | 
| 324 | 
            +
                d = create_driver(CONFIG, 'test.tag1')
         | 
| 325 | 
            +
                d.run do
         | 
| 326 | 
            +
                  60.times do
         | 
| 327 | 
            +
                    d.emit({'target' =>  '50000'})
         | 
| 328 | 
            +
                    d.emit({'target' => '100000'})
         | 
| 329 | 
            +
                    d.emit({'target' => '100001'})
         | 
| 330 | 
            +
                    d.emit({'target' => '0.0'})
         | 
| 331 | 
            +
                    d.emit({'target' => '-1'})
         | 
| 332 | 
            +
                  end
         | 
| 333 | 
            +
                end
         | 
| 334 | 
            +
                d.instance.flush_emit(60)
         | 
| 335 | 
            +
                emits = d.emits
         | 
| 336 | 
            +
                assert_equal 1, emits.length
         | 
| 337 | 
            +
                data = emits[0]
         | 
| 338 | 
            +
                assert_equal 'numcount', data[0] # tag
         | 
| 339 | 
            +
                r = data[2] # message
         | 
| 340 | 
            +
                assert_equal 120, r['tag1_u100ms_count']
         | 
| 341 | 
            +
                assert_equal 2.0, r['tag1_u100ms_rate']
         | 
| 342 | 
            +
                assert_equal 40.0, r['tag1_u100ms_percentage']
         | 
| 343 | 
            +
                assert_equal 120, r['tag1_u1s_count']
         | 
| 344 | 
            +
                assert_equal 2.0, r['tag1_u1s_rate']
         | 
| 345 | 
            +
                assert_equal 40, r['tag1_u1s_percentage']
         | 
| 346 | 
            +
                assert_equal 0, r['tag1_u3s_count']
         | 
| 347 | 
            +
                assert_equal 0, r['tag1_u3s_rate']
         | 
| 348 | 
            +
                assert_equal 0, r['tag1_u3s_percentage']
         | 
| 349 | 
            +
                assert_equal 60, r['tag1_unmatched_count']
         | 
| 350 | 
            +
                assert_equal 1.0, r['tag1_unmatched_rate']
         | 
| 351 | 
            +
                assert_equal 20, r['tag1_unmatched_percentage']
         | 
| 352 | 
            +
              end
         | 
| 353 | 
            +
             | 
| 354 | 
            +
              def test_emit_output_per_tag
         | 
| 355 | 
            +
                d = create_driver(CONFIG_OUTPUT_PER_TAG, 'test.tag1')
         | 
| 356 | 
            +
                d.run do
         | 
| 357 | 
            +
                  60.times do
         | 
| 358 | 
            +
                    d.emit({'target' =>  '50000'})
         | 
| 359 | 
            +
                    d.emit({'target' => '100000'})
         | 
| 360 | 
            +
                    d.emit({'target' => '100001'})
         | 
| 361 | 
            +
                    d.emit({'target' => '0.0'})
         | 
| 362 | 
            +
                    d.emit({'target' => '-1'})
         | 
| 363 | 
            +
                  end
         | 
| 364 | 
            +
                end
         | 
| 365 | 
            +
                r = d.instance.flush_per_tags(60)
         | 
| 366 | 
            +
                assert_equal 1, r.keys.size
         | 
| 367 | 
            +
                r1 = r['tag1']
         | 
| 368 | 
            +
                assert_equal 120, r1['u100ms_count']
         | 
| 369 | 
            +
                assert_equal 2.0, r1['u100ms_rate']
         | 
| 370 | 
            +
                assert_equal 40.0, r1['u100ms_percentage']
         | 
| 371 | 
            +
                assert_equal 120, r1['u1s_count']
         | 
| 372 | 
            +
                assert_equal 2.0, r1['u1s_rate']
         | 
| 373 | 
            +
                assert_equal 40, r1['u1s_percentage']
         | 
| 374 | 
            +
                assert_equal 0, r1['u3s_count']
         | 
| 375 | 
            +
                assert_equal 0, r1['u3s_rate']
         | 
| 376 | 
            +
                assert_equal 0, r1['u3s_percentage']
         | 
| 377 | 
            +
                assert_equal 60, r1['unmatched_count']
         | 
| 378 | 
            +
                assert_equal 1.0, r1['unmatched_rate']
         | 
| 379 | 
            +
                assert_equal 20, r1['unmatched_percentage']
         | 
| 380 | 
            +
                assert_equal 300, r1['messages']
         | 
| 381 | 
            +
             | 
| 382 | 
            +
                d = create_driver(CONFIG_OUTPUT_PER_TAG, 'test.tag1')
         | 
| 383 | 
            +
                d.run do
         | 
| 384 | 
            +
                  60.times do
         | 
| 385 | 
            +
                    d.emit({'target' =>  '50000'})
         | 
| 386 | 
            +
                    d.emit({'target' => '100000'})
         | 
| 387 | 
            +
                    d.emit({'target' => '100001'})
         | 
| 388 | 
            +
                    d.emit({'target' => '0.0'})
         | 
| 389 | 
            +
                    d.emit({'target' => '-1'})
         | 
| 390 | 
            +
                  end
         | 
| 391 | 
            +
                end
         | 
| 392 | 
            +
                d.instance.flush_emit(60)
         | 
| 393 | 
            +
                emits = d.emits
         | 
| 394 | 
            +
                assert_equal 1, emits.length
         | 
| 395 | 
            +
                data = emits[0]
         | 
| 396 | 
            +
                assert_equal 'n.tag1', data[0] # tag
         | 
| 397 | 
            +
                r = data[2] # message
         | 
| 398 | 
            +
                assert_equal 120, r['u100ms_count']
         | 
| 399 | 
            +
                assert_equal 2.0, r['u100ms_rate']
         | 
| 400 | 
            +
                assert_equal 40.0, r['u100ms_percentage']
         | 
| 401 | 
            +
                assert_equal 120, r['u1s_count']
         | 
| 402 | 
            +
                assert_equal 2.0, r['u1s_rate']
         | 
| 403 | 
            +
                assert_equal 40, r['u1s_percentage']
         | 
| 404 | 
            +
                assert_equal 0, r['u3s_count']
         | 
| 405 | 
            +
                assert_equal 0, r['u3s_rate']
         | 
| 406 | 
            +
                assert_equal 0, r['u3s_percentage']
         | 
| 407 | 
            +
                assert_equal 60, r['unmatched_count']
         | 
| 408 | 
            +
                assert_equal 1.0, r['unmatched_rate']
         | 
| 409 | 
            +
                assert_equal 20, r['unmatched_percentage']
         | 
| 410 | 
            +
                assert_equal 300, r['messages']
         | 
| 189 411 | 
             
              end
         | 
| 190 412 | 
             
            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. | 
| 4 | 
            +
              version: 0.1.1
         | 
| 5 5 | 
             
              prerelease: 
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors:
         | 
| @@ -9,8 +9,24 @@ authors: | |
| 9 9 | 
             
            autorequire: 
         | 
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date: 2012- | 
| 12 | 
            +
            date: 2012-08-08 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 15 | 
            +
              name: rake
         | 
| 16 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 17 | 
            +
                none: false
         | 
| 18 | 
            +
                requirements:
         | 
| 19 | 
            +
                - - ! '>='
         | 
| 20 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 21 | 
            +
                    version: '0'
         | 
| 22 | 
            +
              type: :development
         | 
| 23 | 
            +
              prerelease: false
         | 
| 24 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 25 | 
            +
                none: false
         | 
| 26 | 
            +
                requirements:
         | 
| 27 | 
            +
                - - ! '>='
         | 
| 28 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 29 | 
            +
                    version: '0'
         | 
| 14 30 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 31 | 
             
              name: fluentd
         | 
| 16 32 | 
             
              requirement: !ruby/object:Gem::Requirement
         |