fluent-plugin-suppress 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *~
19
+ .#*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-plugin-suppress.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2012 FUJIWARA Shunichiro
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.
data/README.rdoc ADDED
@@ -0,0 +1,52 @@
1
+ = fluent-plugin-suppress
2
+
3
+ == Component
4
+
5
+ === SuppressOutout
6
+
7
+ Fluentd plugin to suppress same messages.
8
+
9
+ == Configuration
10
+
11
+ === SuppressOutput
12
+
13
+ fluentd.conf
14
+
15
+ <match foo.**>
16
+ type suppress
17
+ interval 10
18
+ num 2
19
+ attr_keys host,message
20
+ add_tag_prefix sp.
21
+ </match>
22
+
23
+ In [interval] sec, [num] messages which grouped by attr_keys value, add tag prefix "sp" and pass. Other messages will be removed.
24
+
25
+ Input messages:
26
+
27
+ 2012-11-22T11:22:33 foo.info {"id":1,"host":"web01","message":"error!!"}
28
+ 2012-11-22T11:22:34 foo.info {"id":2,"host":"web01","message":"error!!"}
29
+ * 2012-11-22T11:22:35 foo.info {"id":3,"host":"web01","message":"error!!"}
30
+ * 2012-11-22T11:22:36 foo.info {"id":4,"host":"web01","message":"error!!"}
31
+ 2012-11-22T11:22:37 foo.info {"id":5,"host":"app01","message":"error!!"}
32
+ * 2012-11-22T11:22:38 foo.info {"id":6,"host":"web01","message":"error!!"}
33
+ * 2012-11-22T11:22:39 foo.info {"id":7,"host":"web01","message":"error!!"}
34
+ * 2012-11-22T11:22:40 foo.info {"id":8,"host":"web01","message":"error!!"}
35
+ 2012-11-22T11:22:45 foo.info {"id":9,"host":"web01","message":"error!!"}
36
+ (* = suppressed)
37
+
38
+ Output messages:
39
+
40
+ 2012-11-22T11:22:33 sp.foo.info {"id":1,"host":"web01","message":"error!!"}
41
+ 2012-11-22T11:22:34 sp.foo.info {"id":2,"host":"web01","message":"error!!"}
42
+ 2012-11-22T11:22:37 sp.foo.info {"id":5,"host":"app01","message":"error!!"}
43
+ 2012-11-22T11:22:45 sp.foo.info {"id":9,"host":"web01","message":"error!!"}
44
+
45
+ == TODO
46
+
47
+ - patches welcome!
48
+
49
+ == Copyright
50
+
51
+ Copyright:: Copyright (c) 2012- FUJIWARA Shunichiro
52
+ License:: Apache License, Version 2.0
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+ # -*- mode:ruby -*-
3
+ require "bundler/gem_tasks"
4
+
5
+ require 'rake/testtask'
6
+ Rake::TestTask.new(:test) do |test|
7
+ test.libs << 'lib' << 'test'
8
+ test.pattern = 'test/**/test_*.rb'
9
+ test.verbose = true
10
+ end
11
+
12
+ task :default => :test
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # -*- mode:ruby -*-
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["FUJIWARA Shunichiro"]
6
+ gem.email = ["fujiwara.shunichiro@gmail.com"]
7
+ gem.description = %q{Fluentd plugin to suppress same messages}
8
+ gem.summary = %q{Fluentd plugin to suppress same messages}
9
+ gem.homepage = "https://github.com/fujiwara/fluent-plugin-suppress"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "fluent-plugin-suppress"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = "0.0.1"
17
+
18
+ gem.add_development_dependency "fluentd"
19
+ gem.add_runtime_dependency "fluentd"
20
+ end
@@ -0,0 +1,65 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Fluent
3
+ class SuppressOutput < Output
4
+ Fluent::Plugin.register_output('suppress', self)
5
+
6
+ include Fluent::HandleTagNameMixin
7
+
8
+ config_param :attr_keys, :string, :default => nil
9
+ config_param :num, :integer, :default => 3
10
+ config_param :interval, :integer, :default => 300
11
+
12
+ def configure(conf)
13
+ super
14
+
15
+ unless @attr_keys
16
+ raise ConfigError, "out_suppress: attr_keys is required."
17
+ end
18
+
19
+ if ( !@remove_tag_prefix and !@remove_tag_suffix and !@add_tag_prefix and !@add_tag_suffix )
20
+ raise ConfigError, "out_suppress: Set remove_tag_prefix, remove_tag_suffix, add_tag_prefix or add_tag_suffix."
21
+ end
22
+
23
+ @keys = @attr_keys.split(/ *, */)
24
+ @slots = {}
25
+ end
26
+
27
+ def start
28
+ super
29
+ end
30
+
31
+ def shutdown
32
+ super
33
+ end
34
+
35
+ def emit(tag, es, chain)
36
+ es.each do |time, record|
37
+ key = @keys.map{|k| record[k]}.join("\0")
38
+ key = tag + "\0" + key
39
+ slot = @slots[key] ||= []
40
+
41
+ # expire old records time
42
+ expired = time.to_f - @interval
43
+ while slot.first and slot.first <= expired
44
+ slot.shift
45
+ end
46
+
47
+ if slot.length >= @num
48
+ $log.debug "suppressed record: #{record.to_json}"
49
+ break
50
+ end
51
+
52
+ slot.push(time.to_f)
53
+ _tag = tag.clone
54
+ filter_record(_tag, time, record)
55
+ if tag != _tag
56
+ Engine.emit(_tag, time, record)
57
+ else
58
+ $log.warn "Drop record #{record} tag '#{tag}' was not replaced. Can't emit record, cause infinity looping. Set remove_tag_prefix, remove_tag_suffix, add_tag_prefix or add_tag_suffix correctly."
59
+ end
60
+ end
61
+
62
+ chain.next
63
+ end
64
+ end
65
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,28 @@
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
+
12
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
13
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
14
+ require 'fluent/test'
15
+ unless ENV.has_key?('VERBOSE')
16
+ nulllogger = Object.new
17
+ nulllogger.instance_eval {|obj|
18
+ def method_missing(method, *args)
19
+ # pass
20
+ end
21
+ }
22
+ $log = nulllogger
23
+ end
24
+
25
+ require 'fluent/plugin/out_suppress'
26
+
27
+ class Test::Unit::TestCase
28
+ end
@@ -0,0 +1,43 @@
1
+ require 'helper'
2
+
3
+ class SuppressOutputTest < Test::Unit::TestCase
4
+ def setup
5
+ Fluent::Test.setup
6
+ end
7
+
8
+ CONFIG = %[
9
+ interval 10
10
+ num 2
11
+ attr_keys host, message
12
+ add_tag_prefix sp.
13
+ ]
14
+
15
+ def create_driver(conf = CONFIG, tag='test.info')
16
+ Fluent::Test::OutputTestDriver.new(Fluent::SuppressOutput, tag).configure(conf)
17
+ end
18
+
19
+ def test_emit
20
+ d = create_driver
21
+
22
+ time = Time.parse("2012-11-22 11:22:33 UTC").to_i
23
+ d.run do
24
+ d.emit({"id" => 1, "host" => "web01", "message" => "error!!"}, time + 1)
25
+ d.emit({"id" => 2, "host" => "web01", "message" => "error!!"}, time + 2)
26
+ d.emit({"id" => 3, "host" => "web01", "message" => "error!!"}, time + 3)
27
+ d.emit({"id" => 4, "host" => "web01", "message" => "error!!"}, time + 4)
28
+ d.emit({"id" => 5, "host" => "app01", "message" => "error!!"}, time + 4)
29
+ d.emit({"id" => 6, "host" => "web01", "message" => "error!!"}, time + 12)
30
+ d.emit({"id" => 7, "host" => "web01", "message" => "error!!"}, time + 13)
31
+ d.emit({"id" => 8, "host" => "web01", "message" => "error!!"}, time + 14)
32
+ end
33
+
34
+ emits = d.emits
35
+ assert_equal 5, emits.length
36
+ assert_equal ["sp.test.info", time + 1, {"id"=>1, "host"=>"web01", "message"=>"error!!"}], emits[0]
37
+ assert_equal ["sp.test.info", time + 2, {"id"=>2, "host"=>"web01", "message"=>"error!!"}], emits[1]
38
+ assert_equal ["sp.test.info", time + 4, {"id"=>5, "host"=>"app01", "message"=>"error!!"}], emits[2]
39
+ assert_equal ["sp.test.info", time + 12, {"id"=>6, "host"=>"web01", "message"=>"error!!"}], emits[3]
40
+ assert_equal ["sp.test.info", time + 13, {"id"=>7, "host"=>"web01", "message"=>"error!!"}], emits[4]
41
+
42
+ end
43
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-suppress
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - FUJIWARA Shunichiro
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-22 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: fluentd
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'
30
+ - !ruby/object:Gem::Dependency
31
+ name: fluentd
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: Fluentd plugin to suppress same messages
47
+ email:
48
+ - fujiwara.shunichiro@gmail.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .gitignore
54
+ - Gemfile
55
+ - LICENSE
56
+ - README.rdoc
57
+ - Rakefile
58
+ - fluent-plugin-supress.gemspec
59
+ - lib/fluent/plugin/out_suppress.rb
60
+ - test/helper.rb
61
+ - test/plugin/test_out_suppress.rb
62
+ homepage: https://github.com/fujiwara/fluent-plugin-suppress
63
+ licenses: []
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ! '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ! '>='
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ requirements: []
81
+ rubyforge_project:
82
+ rubygems_version: 1.8.23
83
+ signing_key:
84
+ specification_version: 3
85
+ summary: Fluentd plugin to suppress same messages
86
+ test_files:
87
+ - test/helper.rb
88
+ - test/plugin/test_out_suppress.rb