fluent-plugin-sampling-filter 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/AUTHORS ADDED
@@ -0,0 +1 @@
1
+ TAGOMORI Satoshi <tagomoris _at_ gmail.com>
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "shoulda", ">= 0"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.6.4"
12
+ gem "simplecov", ">= 0"
13
+ gem "rdoc"
14
+ end
15
+
16
+ gem "fluentd"
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2012- TAGOMORI Satoshi
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
@@ -0,0 +1,50 @@
1
+ = fluent-plugin-sampling-filter
2
+
3
+ == Component
4
+
5
+ === SamplingFilterOutput
6
+
7
+ Do sampling from matching messages to analyse and report messages behavior, and emit sampled messages with modified tag.
8
+
9
+ - sampling rate per tags, or for all
10
+ - remove_prefix of tags for input messages, and add_prefix of tags for output(sampled) messages
11
+
12
+ == Configuration
13
+
14
+ === SamplingFilterOutput
15
+
16
+ Pickup 1/10 messages about each tags(default: 'sample_unit tag'), and add tag prefix 'sampled'.
17
+
18
+ <match **>
19
+ type sampling_filter
20
+ interval 10
21
+ add_prefix sampled
22
+ </match>
23
+
24
+ <match sampled.**>
25
+ # output configurations where to send sampled messages
26
+ </match>
27
+
28
+ Pickup 1/100 messages of all matched messages, and modify tags from input.** to output.**
29
+
30
+ <match input.**>
31
+ type sampling_filter
32
+ interval 100
33
+ sample_unit all
34
+ remove_prefix input
35
+ add_prefix output
36
+ </match>
37
+
38
+ <match sampled.**>
39
+ # output configurations where to send sampled messages
40
+ </match>
41
+
42
+ == TODO
43
+
44
+ - consider what to do next
45
+ - patches welcome!
46
+
47
+ == Copyright
48
+
49
+ Copyright:: Copyright (c) 2012- TAGOMORI Satoshi (tagomoris)
50
+ License:: Apache License, Version 2.0
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "fluent-plugin-sampling-filter"
18
+ gem.homepage = "http://github.com/tagomoris/fluent-plugin-sampling-filter"
19
+ # gem.license = "MIT"
20
+ gem.summary = %Q{fluentd plugin to pickup sample data from matched massages}
21
+ gem.description = %Q{fluentd plugin to pickup sample data from matched massages}
22
+ gem.email = "tagomoris@gmail.com"
23
+ gem.authors = ["TAGOMORI Satoshi"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ # require 'rcov/rcovtask'
36
+ # Rcov::RcovTask.new do |test|
37
+ # test.libs << 'test'
38
+ # test.pattern = 'test/**/test_*.rb'
39
+ # test.verbose = true
40
+ # test.rcov_opts << '--exclude "gems/*"'
41
+ # end
42
+
43
+ task :default => :test
44
+
45
+ require 'rdoc/task'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "fluent-plugin-sampling-filter #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,64 @@
1
+ class Fluent::SamplingFilterOutput < Fluent::Output
2
+ Fluent::Plugin.register_output('sampling_filter', self)
3
+
4
+ config_param :interval, :integer
5
+ config_param :sample_unit, :string, :default => 'tag'
6
+ config_param :remove_prefix, :string, :default => nil
7
+ config_param :add_prefix, :string, :default => 'sampled'
8
+
9
+ def configure(conf)
10
+ super
11
+
12
+ if @remove_prefix
13
+ @removed_prefix_string = @remove_prefix + '.'
14
+ @removed_length = @removed_prefix_string.length
15
+ end
16
+ @added_prefix_string = @add_prefix + '.'
17
+
18
+ @sample_unit = case @sample_unit
19
+ when 'tag'
20
+ :tag
21
+ when 'all'
22
+ :all
23
+ else
24
+ raise Fluent::ConfigError, "sample_unit allows only 'tag' or 'all'"
25
+ end
26
+ @counts = {}
27
+ end
28
+
29
+ def emit_sampled(tag, time_record_pairs)
30
+ if @remove_prefix and
31
+ ( (tag.start_with?(@removed_prefix_string) and tag.length > @removed_length) or tag == @remove_prefix)
32
+ tag = tag[@removed_length..-1]
33
+ end
34
+ tag = if tag.length > 0
35
+ @added_prefix_string + tag
36
+ else
37
+ @add_prefix
38
+ end
39
+
40
+ time_record_pairs.each {|t,r|
41
+ Fluent::Engine.emit(tag, t, r)
42
+ }
43
+ end
44
+
45
+ def emit(tag, es, chain)
46
+ t = if @sample_unit == :all
47
+ 'all'
48
+ else
49
+ tag
50
+ end
51
+ @counts[t] ||= 0
52
+ pairs = []
53
+ es.each {|time,record|
54
+ @counts[t] += 1
55
+ if @counts[t] == @interval
56
+ pairs.push [time, record]
57
+ @counts[t] = 0
58
+ end
59
+ }
60
+ emit_sampled(tag, pairs)
61
+
62
+ chain.next
63
+ end
64
+ end
@@ -0,0 +1,19 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ require 'shoulda'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'fluent/test'
16
+ require 'fluent/plugin/out_sampling_filter'
17
+
18
+ class Test::Unit::TestCase
19
+ end
@@ -0,0 +1,100 @@
1
+ require 'helper'
2
+
3
+ class SamplingFilterOutputTest < Test::Unit::TestCase
4
+ def setup
5
+ Fluent::Test.setup
6
+ end
7
+
8
+ CONFIG = %[
9
+ interval 10
10
+ sample_unit tag
11
+ remove_prefix input
12
+ add_prefix sampled
13
+ ]
14
+
15
+ def create_driver(conf=CONFIG,tag='test')
16
+ Fluent::Test::OutputTestDriver.new(Fluent::SamplingFilterOutput, tag).configure(conf)
17
+ end
18
+
19
+ def test_configure
20
+ assert_raise(Fluent::ConfigError) {
21
+ d = create_driver('')
22
+ }
23
+ d = create_driver %[
24
+ interval 5
25
+ ]
26
+
27
+ assert_equal 5, d.instance.interval
28
+ assert_equal :tag, d.instance.sample_unit
29
+ assert_nil d.instance.remove_prefix
30
+ assert_equal 'sampled', d.instance.add_prefix
31
+
32
+ d = create_driver %[
33
+ interval 1000
34
+ sample_unit all
35
+ remove_prefix test
36
+ add_prefix output
37
+ ]
38
+ assert_equal 1000, d.instance.interval
39
+ assert_equal :all, d.instance.sample_unit
40
+ assert_equal 'test', d.instance.remove_prefix
41
+ assert_equal 'output', d.instance.add_prefix
42
+ end
43
+
44
+ # CONFIG = %[
45
+ # interval 10
46
+ # sample_unit tag
47
+ # remove_prefix input
48
+ # add_prefix sampled
49
+ # ]
50
+ def test_emit
51
+ d1 = create_driver(CONFIG, 'input.hoge1')
52
+ time = Time.parse("2012-01-02 13:14:15").to_i
53
+ d1.run do
54
+ d1.emit({'field1' => 'record1', 'field2' => 1})
55
+ d1.emit({'field1' => 'record2', 'field2' => 2})
56
+ d1.emit({'field1' => 'record3', 'field2' => 3})
57
+ d1.emit({'field1' => 'record4', 'field2' => 4})
58
+ d1.emit({'field1' => 'record5', 'field2' => 5})
59
+ d1.emit({'field1' => 'record6', 'field2' => 6})
60
+ d1.emit({'field1' => 'record7', 'field2' => 7})
61
+ d1.emit({'field1' => 'record8', 'field2' => 8})
62
+ d1.emit({'field1' => 'record9', 'field2' => 9})
63
+ d1.emit({'field1' => 'record10', 'field2' => 10})
64
+ d1.emit({'field1' => 'record11', 'field2' => 11})
65
+ d1.emit({'field1' => 'record12', 'field2' => 12})
66
+ end
67
+ emits = d1.emits
68
+ assert_equal 1, emits.length
69
+ assert_equal 'sampled.hoge1', emits[0][0] # tag
70
+ assert_equal 'record10', emits[0][2]['field1']
71
+ assert_equal 10, emits[0][2]['field2']
72
+
73
+ d2 = create_driver(%[
74
+ interval 3
75
+ ], 'input.hoge2')
76
+ time = Time.parse("2012-01-02 13:14:15").to_i
77
+ d2.run do
78
+ d2.emit({'field1' => 'record1', 'field2' => 1})
79
+ d2.emit({'field1' => 'record2', 'field2' => 2})
80
+ d2.emit({'field1' => 'record3', 'field2' => 3})
81
+ d2.emit({'field1' => 'record4', 'field2' => 4})
82
+ d2.emit({'field1' => 'record5', 'field2' => 5})
83
+ d2.emit({'field1' => 'record6', 'field2' => 6})
84
+ d2.emit({'field1' => 'record7', 'field2' => 7})
85
+ d2.emit({'field1' => 'record8', 'field2' => 8})
86
+ d2.emit({'field1' => 'record9', 'field2' => 9})
87
+ d2.emit({'field1' => 'record10', 'field2' => 10})
88
+ d2.emit({'field1' => 'record11', 'field2' => 11})
89
+ d2.emit({'field1' => 'record12', 'field2' => 12})
90
+ end
91
+ emits = d2.emits
92
+ assert_equal 4, emits.length
93
+ assert_equal 'sampled.input.hoge2', emits[0][0] # tag
94
+
95
+ assert_equal 'record3', emits[0][2]['field1']
96
+ assert_equal 'record6', emits[1][2]['field1']
97
+ assert_equal 'record9', emits[2][2]['field1']
98
+ assert_equal 'record12', emits[3][2]['field1']
99
+ end
100
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-sampling-filter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - TAGOMORI Satoshi
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-02-23 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: fluentd
16
+ requirement: &2154789280 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2154789280
25
+ - !ruby/object:Gem::Dependency
26
+ name: shoulda
27
+ requirement: &2154788800 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *2154788800
36
+ - !ruby/object:Gem::Dependency
37
+ name: bundler
38
+ requirement: &2154788320 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 1.0.0
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *2154788320
47
+ - !ruby/object:Gem::Dependency
48
+ name: jeweler
49
+ requirement: &2154787840 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 1.6.4
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *2154787840
58
+ - !ruby/object:Gem::Dependency
59
+ name: simplecov
60
+ requirement: &2154787360 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *2154787360
69
+ - !ruby/object:Gem::Dependency
70
+ name: rdoc
71
+ requirement: &2154786880 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *2154786880
80
+ description: fluentd plugin to pickup sample data from matched massages
81
+ email: tagomoris@gmail.com
82
+ executables: []
83
+ extensions: []
84
+ extra_rdoc_files:
85
+ - LICENSE.txt
86
+ - README.rdoc
87
+ files:
88
+ - .document
89
+ - AUTHORS
90
+ - Gemfile
91
+ - LICENSE.txt
92
+ - README.rdoc
93
+ - Rakefile
94
+ - VERSION
95
+ - lib/fluent/plugin/out_sampling_filter.rb
96
+ - test/helper.rb
97
+ - test/plugin/test_out_sampling_filter.rb
98
+ homepage: http://github.com/tagomoris/fluent-plugin-sampling-filter
99
+ licenses: []
100
+ post_install_message:
101
+ rdoc_options: []
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ segments:
111
+ - 0
112
+ hash: 3531476844839040291
113
+ required_rubygems_version: !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ! '>='
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ requirements: []
120
+ rubyforge_project:
121
+ rubygems_version: 1.8.6
122
+ signing_key:
123
+ specification_version: 3
124
+ summary: fluentd plugin to pickup sample data from matched massages
125
+ test_files: []