fluent-plugin-forest 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,25 @@
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
+ # For TextMate, emacs, vim
19
+ *.tmproj
20
+ tmtags
21
+ *~
22
+ \#*
23
+ .\#*
24
+ *.swp
25
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-plugin-forest.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -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.
data/README.md ADDED
@@ -0,0 +1,103 @@
1
+ # fluent-plugin-forest
2
+
3
+ ## Component
4
+
5
+ ### ForestOutput
6
+
7
+ ForestOutput creates sub plugin instance of a output plugin dynamically per tag, from template configurations.
8
+ In template configurations, you can write configuration lines for overall tags by <template>, and for specified tags by <case TAG_PATTERN>, and you can use \_\_TAG\_\_ placeholder at anywhere in <template> and <case>.
9
+
10
+ This plugin helps you if you are writing very long configurations by copy&paste with a little little diff for many tags.
11
+
12
+ You SHOULD NOT use ForestOutput for tags increasing infinitly.
13
+
14
+ ## Configuration
15
+
16
+ ### ForestOutput
17
+
18
+ If you are writing long long configurations like below:
19
+
20
+ <match service.blog>
21
+ type file
22
+ time_slice_format %Y%m%d%H
23
+ compress yes
24
+ path /var/log/blog.*.log
25
+ </match>
26
+ <match service.portal>
27
+ type file
28
+ time_slice_format %Y%m%d%H
29
+ compress yes
30
+ path /var/log/portal.*.log
31
+ </match>
32
+ <match service.news>
33
+ type file
34
+ time_slice_format %Y%m%d%H
35
+ compress yes
36
+ path /var/log/news.*.log
37
+ </match>
38
+ <match service.sns>
39
+ type file
40
+ time_slice_format %Y%m%d%H
41
+ compress yes
42
+ path /var/log/sns.*.log
43
+ </match>
44
+ # ...
45
+
46
+ You can write configuration with ForestOutput like below:
47
+
48
+ <match service.*>
49
+ type forest
50
+ subtype file
51
+ remove_prefix service
52
+ <template>
53
+ time_slice_format %Y%m%d%H
54
+ compress yes
55
+ path /var/log/__TAG__.*.log
56
+ </template>
57
+ </match>
58
+
59
+ If you want to place logs /var/archive for `service.search.**` without compression, `case` directive is useful:
60
+
61
+ <match service.*>
62
+ type forest
63
+ subtype file
64
+ remove_prefix service
65
+ <template>
66
+ time_slice_format %Y%m%d%H
67
+ </template>
68
+ <case search.**>
69
+ compress no
70
+ path /var/archive/__TAG__.*.log
71
+ </case>
72
+ <case *>
73
+ compress yes
74
+ path /var/log/__TAG__.*.log
75
+ </case>
76
+ </match>
77
+
78
+ `case` configuration overwrites `template` configuration, so you can also write like this:
79
+
80
+ <match service.*>
81
+ type forest
82
+ subtype file
83
+ remove_prefix service
84
+ <template>
85
+ time_slice_format %Y%m%d%H
86
+ compress yes
87
+ path /var/log/__TAG__.*.log
88
+ </template>
89
+ <case search.**>
90
+ compress no
91
+ path /var/archive/__TAG__.*.log
92
+ </case>
93
+ </match>
94
+
95
+ ## TODO
96
+
97
+ * consider what to do next
98
+ * patches welcome!
99
+
100
+ ## Copyright
101
+
102
+ Copyright:: Copyright (c) 2012- TAGOMORI Satoshi (tagomoris)
103
+ License:: Apache License, Version 2.0
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rake/testtask'
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << 'lib' << 'test'
7
+ test.pattern = 'test/**/test_*.rb'
8
+ test.verbose = true
9
+ end
10
+
11
+ task :default => :test
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+ Gem::Specification.new do |gem|
3
+ gem.name = "fluent-plugin-forest"
4
+ gem.version = "0.1.0"
5
+ gem.authors = ["TAGOMORI Satoshi"]
6
+ gem.email = ["tagomoris@gmail.com"]
7
+ gem.description = %q{create sub-plugin dynamically per tags, with template configuration and parameters}
8
+ gem.summary = %q{plugin to create output plugin instances per tags dynamically}
9
+ gem.homepage = "https://github.com/tagomoris/fluent-plugin-forest"
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.require_paths = ["lib"]
15
+
16
+ gem.add_development_dependency "fluentd"
17
+ gem.add_runtime_dependency "fluentd"
18
+ end
@@ -0,0 +1,120 @@
1
+ class Fluent::ForestOutput < Fluent::Output
2
+ Fluent::Plugin.register_output('forest', self)
3
+
4
+ config_param :subtype, :string
5
+ config_param :remove_prefix, :string, :default => nil
6
+ config_param :add_prefix, :string, :default => nil
7
+
8
+ def configure(conf)
9
+ super
10
+
11
+ if @remove_prefix
12
+ @removed_prefix_string = @remove_prefix + '.'
13
+ @removed_length = @removed_prefix_string.length
14
+ end
15
+ if @add_prefix
16
+ @added_prefix_string = @add_prefix + '.'
17
+ end
18
+
19
+ @mapping = {} # tag => output
20
+ @mutex = Mutex.new
21
+
22
+ @template = nil
23
+ @parameter = nil
24
+ @cases = []
25
+
26
+ conf.elements.each do |element|
27
+ element.keys.each do |k|
28
+ # read and throw away to supress unread configuration warning
29
+ element[k]
30
+ end
31
+ case element.name
32
+ when 'template'
33
+ @template = element
34
+ when 'case'
35
+ matcher = Fluent::GlobMatchPattern.new(element.arg)
36
+ @cases.push([matcher, element])
37
+ end
38
+ end
39
+
40
+ self
41
+ end
42
+
43
+ def shutdown
44
+ super
45
+ @mapping.values.each do |output|
46
+ output.shutdown
47
+ end
48
+ end
49
+
50
+ def parameter(tag, e)
51
+ pairs = {}
52
+ e.each do |k,v|
53
+ pairs[k] = v.gsub('__TAG__', tag)
54
+ end
55
+ Fluent::Config::Element.new('instance', '', pairs, [])
56
+ end
57
+
58
+ def spec(tag)
59
+ conf = Fluent::Config::Element.new('instance', '', {}, [])
60
+ conf = parameter(tag, @template) + conf if @template # a + b -> b.merge(a) (see: fluentd/lib/fluent/config.rb)
61
+ @cases.each do |m,e|
62
+ if m.match(tag)
63
+ conf = parameter(tag, e) + conf
64
+ break
65
+ end
66
+ end
67
+ conf
68
+ end
69
+
70
+ def plant(tag)
71
+ output = nil
72
+ begin
73
+ @mutex.synchronize {
74
+ output = @mapping[tag]
75
+ unless output
76
+ output = Fluent::Plugin.new_output(@subtype)
77
+ output.configure(spec(tag))
78
+ output.start
79
+ @mapping[tag] = output
80
+ end
81
+ }
82
+ $log.info "out_forest plants new output: #{@subtype} for tag '#{tag}'"
83
+ rescue Fluent::ConfigError => e
84
+ $log.error "failed to configure sub output #{@subtype}: #{e.message}"
85
+ $log.error e.backtrace.join("\n")
86
+ $log.error "Cannot output messages with tag '#{tag}'"
87
+ output = nil
88
+ rescue StandardError => e
89
+ $log.error "failed to configure/start sub output #{@subtype}: #{e.message}"
90
+ $log.error e.backtrace.join("\n")
91
+ $log.error "Cannot output messages with tag '#{tag}'"
92
+ output = nil
93
+ end
94
+ output
95
+ end
96
+
97
+ def emit(tag, es, chain)
98
+ if @remove_prefix and
99
+ ( (tag.start_with?(@removed_prefix_string) and tag.length > @removed_length) or tag == @remove_prefix)
100
+ tag = tag[@removed_length..-1]
101
+ end
102
+ if @add_prefix
103
+ tag = if tag.length > 0
104
+ @added_prefix_string + tag
105
+ else
106
+ @add_prefix
107
+ end
108
+ end
109
+
110
+ output = @mapping[tag]
111
+ unless output
112
+ output = plant(tag)
113
+ end
114
+ if output
115
+ output.emit(tag, es, chain)
116
+ else
117
+ chain.next
118
+ end
119
+ end
120
+ 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_forest'
26
+
27
+ class Test::Unit::TestCase
28
+ end
@@ -0,0 +1,43 @@
1
+ class Fluent::ForestTestOutput < Fluent::Output
2
+ Fluent::Plugin.register_output('forest_test', self)
3
+
4
+ config_param :key_name, :string, :default => 'msg'
5
+ config_param :tag
6
+ config_param :prefix, :string, :default => ''
7
+ config_param :suffix, :string, :default => ''
8
+ config_param :tagfield, :string, :default => nil
9
+
10
+ attr_accessor :started, :stopped
11
+
12
+ def configure(conf)
13
+ super
14
+
15
+ if @tag == 'raise.error'
16
+ raise Fluent::ConfigError, "specified to raise.error"
17
+ end
18
+ end
19
+
20
+ def start
21
+ super
22
+ @started = true
23
+ end
24
+
25
+ def shutdown
26
+ super
27
+ @stopped = true
28
+ end
29
+
30
+ def emit(tag, es, chain)
31
+ es.each {|time, record|
32
+ r = record.merge({@key_name => @prefix + record[@key_name] + @suffix})
33
+ unless @started
34
+ r = r.merge({'not_started' => true})
35
+ end
36
+ if @tagfield
37
+ r[@tagfield] = tag
38
+ end
39
+ Fluent::Engine.emit(@tag, time, r)
40
+ }
41
+ chain.next
42
+ end
43
+ end
@@ -0,0 +1,181 @@
1
+ require 'helper'
2
+ require_relative '../output/out_forest_test'
3
+
4
+ class ForestOutputTest < Test::Unit::TestCase
5
+ def setup
6
+ Fluent::Test.setup
7
+ end
8
+
9
+ CONFIG = %[
10
+ subtype forest_test
11
+ remove_prefix test
12
+ <template>
13
+ key_name f
14
+ suffix !
15
+ tag out.__TAG__
16
+ </template>
17
+ <case foo.bar>
18
+ prefix p1:
19
+ </case>
20
+ <case foo.*>
21
+ prefix p2:
22
+ </case>
23
+ <case bar.**>
24
+ prefix p3:
25
+ </case>
26
+ <case *>
27
+ prefix p4:
28
+ </case>
29
+ ]
30
+
31
+ def create_driver(conf = CONFIG, tag='test.default')
32
+ Fluent::Test::OutputTestDriver.new(Fluent::ForestOutput, tag).configure(conf)
33
+ end
34
+
35
+ def test_configure
36
+ assert_nothing_raised { d = create_driver }
37
+ end
38
+
39
+ def test_spec
40
+ d = create_driver %[
41
+ subtype hoge
42
+ <template>
43
+ keyx xxxxxx
44
+ keyy yyyyyy.__TAG__
45
+ alt_key a
46
+ </template>
47
+ <case xx>
48
+ keyz z1
49
+ alt_key b
50
+ </case>
51
+ <case yy.**>
52
+ keyz z2
53
+ alt_key c
54
+ </case>
55
+ <case *>
56
+ keyz z3
57
+ alt_key d.__TAG__
58
+ </case>
59
+ ]
60
+ conf = d.instance.spec('xx')
61
+ assert_equal 'xxxxxx', conf['keyx']
62
+ assert_equal 'yyyyyy.xx', conf['keyy']
63
+ assert_equal 'z1', conf['keyz']
64
+ assert_equal 'b', conf['alt_key']
65
+
66
+ conf = d.instance.spec('yy')
67
+ assert_equal 'xxxxxx', conf['keyx']
68
+ assert_equal 'yyyyyy.yy', conf['keyy']
69
+ assert_equal 'z2', conf['keyz']
70
+ assert_equal 'c', conf['alt_key']
71
+
72
+ conf = d.instance.spec('yy.3')
73
+ assert_equal 'xxxxxx', conf['keyx']
74
+ assert_equal 'yyyyyy.yy.3', conf['keyy']
75
+ assert_equal 'z2', conf['keyz']
76
+ assert_equal 'c', conf['alt_key']
77
+
78
+ conf = d.instance.spec('zz')
79
+ assert_equal 'xxxxxx', conf['keyx']
80
+ assert_equal 'yyyyyy.zz', conf['keyy']
81
+ assert_equal 'z3', conf['keyz']
82
+ assert_equal 'd.zz', conf['alt_key']
83
+ end
84
+
85
+ def test_faild_plant
86
+ d = create_driver
87
+ time = Time.parse("2012-01-02 13:14:15").to_i
88
+ d.tag = 'test.xxxxxx'; d.run { d.emit({'f' => "message 1"}, time) }
89
+ emits = d.emits
90
+ assert_equal 1, emits.length
91
+
92
+ d = create_driver %[
93
+ subtype forest_test
94
+ remove_prefix test
95
+ <template>
96
+ key_name f
97
+ suffix !
98
+ tag __TAG__
99
+ </template>
100
+ <case foo.bar>
101
+ prefix p1:
102
+ </case>
103
+ <case foo.*>
104
+ prefix p2:
105
+ </case>
106
+ <case bar.**>
107
+ prefix p3:
108
+ </case>
109
+ <case *>
110
+ prefix p4:
111
+ </case>
112
+ ]
113
+ time = Time.parse("2012-01-02 13:14:15").to_i
114
+ d.tag = 'test.raise.error'; d.run { d.emit({'f' => "message 1"}, time) }
115
+ emits = d.emits
116
+ assert_equal 0, emits.length
117
+ end
118
+
119
+ def test_emit
120
+ d = create_driver
121
+ time = Time.parse("2012-01-02 13:14:15").to_i
122
+ d.tag = 'test.first'; d.run { d.emit({'f' => "message 1"}, time) }
123
+ d.tag = 'test.second'; d.run { d.emit({'f' => "message 2"}, time) }
124
+ d.tag = 'test.foo.bar'; d.run { d.emit({'f' => "message 3"}, time) }
125
+ d.tag = 'test.foo.baz'; d.run { d.emit({'f' => "message 4"}, time) }
126
+ d.tag = 'test.bar'; d.run { d.emit({'f' => "message 5"}, time) }
127
+ d.tag = 'test.baz'; d.run { d.emit({'f' => "message 6"}, time) }
128
+ d.tag = 'test.foo.bar'; d.run { d.emit({'f' => "message 7"}, time) }
129
+ d.tag = 'test.bar'; d.run { d.emit({'f' => "message 8"}, time) }
130
+
131
+ emits = d.emits
132
+
133
+ e = emits[0]
134
+ assert_equal 'out.first', e[0]
135
+ assert_equal time, e[1]
136
+ assert_equal "p4:message 1!", e[2]['f']
137
+ assert_nil e[2]['not_started']
138
+
139
+ e = emits[1]
140
+ assert_equal 'out.second', e[0]
141
+ assert_equal time, e[1]
142
+ assert_equal "p4:message 2!", e[2]['f']
143
+ assert_nil e[2]['not_started']
144
+
145
+ e = emits[2]
146
+ assert_equal 'out.foo.bar', e[0]
147
+ assert_equal time, e[1]
148
+ assert_equal "p1:message 3!", e[2]['f']
149
+ assert_nil e[2]['not_started']
150
+
151
+ e = emits[3]
152
+ assert_equal 'out.foo.baz', e[0]
153
+ assert_equal time, e[1]
154
+ assert_equal "p2:message 4!", e[2]['f']
155
+ assert_nil e[2]['not_started']
156
+
157
+ e = emits[4]
158
+ assert_equal 'out.bar', e[0]
159
+ assert_equal time, e[1]
160
+ assert_equal "p3:message 5!", e[2]['f']
161
+ assert_nil e[2]['not_started']
162
+
163
+ e = emits[5]
164
+ assert_equal 'out.baz', e[0]
165
+ assert_equal time, e[1]
166
+ assert_equal "p4:message 6!", e[2]['f']
167
+ assert_nil e[2]['not_started']
168
+
169
+ e = emits[6]
170
+ assert_equal 'out.foo.bar', e[0]
171
+ assert_equal time, e[1]
172
+ assert_equal "p1:message 7!", e[2]['f']
173
+ assert_nil e[2]['not_started']
174
+
175
+ e = emits[7]
176
+ assert_equal 'out.bar', e[0]
177
+ assert_equal time, e[1]
178
+ assert_equal "p3:message 8!", e[2]['f']
179
+ assert_nil e[2]['not_started']
180
+ end
181
+ end
@@ -0,0 +1,103 @@
1
+ require 'helper'
2
+ require_relative '../output/out_forest_test'
3
+
4
+ class ForestTestOutputTest < Test::Unit::TestCase
5
+ def setup
6
+ Fluent::Test.setup
7
+ end
8
+
9
+ CONFIG = %[
10
+ tag foo.bar
11
+ tagfield ttt
12
+ prefix fixed:
13
+ suffix :end
14
+ ]
15
+
16
+ def create_driver(conf = CONFIG, tag='test')
17
+ Fluent::Test::OutputTestDriver.new(Fluent::ForestTestOutput, tag).configure(conf)
18
+ end
19
+
20
+ def test_configure
21
+ d = create_driver
22
+ assert_equal 'foo.bar', d.instance.tag
23
+ assert_equal 'fixed:', d.instance.prefix
24
+ assert_equal ':end', d.instance.suffix
25
+ end
26
+
27
+ def test_emit
28
+ d = create_driver
29
+ time = Time.parse("2012-01-02 13:14:15").to_i
30
+ d.run do
31
+ d.emit({'msg' => 'xyz 123', 'alt' => 'aaa bbb ccc'}, time)
32
+ d.emit({'msg' => 'xyz 456', 'alt' => 'aaa bbb ccc ddd'}, time)
33
+ end
34
+ emits = d.emits
35
+ assert_equal 2, emits.length
36
+
37
+ assert_equal 'foo.bar', emits[0][0]
38
+ assert_equal time, emits[0][1]
39
+ assert_equal 'fixed:xyz 123:end', emits[0][2]['msg']
40
+ assert_equal 'aaa bbb ccc', emits[0][2]['alt']
41
+ assert_equal 'test', emits[0][2]['ttt']
42
+
43
+ assert_equal 'foo.bar', emits[1][0]
44
+ assert_equal time, emits[1][1]
45
+ assert_equal 'fixed:xyz 456:end', emits[1][2]['msg']
46
+ assert_equal 'aaa bbb ccc ddd', emits[1][2]['alt']
47
+ assert_equal 'test', emits[1][2]['ttt']
48
+ end
49
+
50
+ def test_emit
51
+ d = create_driver
52
+ time = Time.parse("2012-01-02 13:14:15").to_i
53
+ d.run do
54
+ d.emit({'msg' => 'xyz 123', 'alt' => 'aaa bbb ccc'}, time)
55
+ d.tag = 'test2'
56
+ d.emit({'msg' => 'xyz 456', 'alt' => 'aaa bbb ccc ddd'}, time)
57
+ end
58
+ emits = d.emits
59
+ assert_equal 2, emits.length
60
+
61
+ assert_equal 'foo.bar', emits[0][0]
62
+ assert_equal time, emits[0][1]
63
+ assert_equal 'fixed:xyz 123:end', emits[0][2]['msg']
64
+ assert_equal 'aaa bbb ccc', emits[0][2]['alt']
65
+ assert_equal 'test', emits[0][2]['ttt']
66
+ assert_nil emits[0][2]['not_started']
67
+
68
+ assert_equal 'foo.bar', emits[1][0]
69
+ assert_equal time, emits[1][1]
70
+ assert_equal 'fixed:xyz 456:end', emits[1][2]['msg']
71
+ assert_equal 'aaa bbb ccc ddd', emits[1][2]['alt']
72
+ assert_equal 'test2', emits[1][2]['ttt']
73
+ assert_nil emits[1][2]['not_started']
74
+ end
75
+
76
+ def test_emit2
77
+ d = create_driver
78
+ time = Time.parse("2012-01-02 13:14:15").to_i
79
+ d.run do
80
+ d.emit({'msg' => 'xyz 123', 'alt' => 'aaa bbb ccc'}, time)
81
+ end
82
+ d.tag = 'test2'
83
+ d.run do
84
+ d.emit({'msg' => 'xyz 456', 'alt' => 'aaa bbb ccc ddd'}, time)
85
+ end
86
+ emits = d.emits
87
+ assert_equal 2, emits.length
88
+
89
+ assert_equal 'foo.bar', emits[0][0]
90
+ assert_equal time, emits[0][1]
91
+ assert_equal 'fixed:xyz 123:end', emits[0][2]['msg']
92
+ assert_equal 'aaa bbb ccc', emits[0][2]['alt']
93
+ assert_equal 'test', emits[0][2]['ttt']
94
+ assert_nil emits[0][2]['not_started']
95
+
96
+ assert_equal 'foo.bar', emits[1][0]
97
+ assert_equal time, emits[1][1]
98
+ assert_equal 'fixed:xyz 456:end', emits[1][2]['msg']
99
+ assert_equal 'aaa bbb ccc ddd', emits[1][2]['alt']
100
+ assert_equal 'test2', emits[1][2]['ttt']
101
+ assert_nil emits[1][2]['not_started']
102
+ end
103
+ end
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-forest
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-04-10 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: create sub-plugin dynamically per tags, with template configuration and
47
+ parameters
48
+ email:
49
+ - tagomoris@gmail.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - .gitignore
55
+ - Gemfile
56
+ - LICENSE.txt
57
+ - README.md
58
+ - Rakefile
59
+ - fluent-plugin-forest.gemspec
60
+ - lib/fluent/plugin/out_forest.rb
61
+ - test/helper.rb
62
+ - test/output/out_forest_test.rb
63
+ - test/plugin/test_out_forest.rb
64
+ - test/plugin/test_out_forest_test.rb
65
+ homepage: https://github.com/tagomoris/fluent-plugin-forest
66
+ licenses: []
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 1.8.21
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: plugin to create output plugin instances per tags dynamically
89
+ test_files:
90
+ - test/helper.rb
91
+ - test/output/out_forest_test.rb
92
+ - test/plugin/test_out_forest.rb
93
+ - test/plugin/test_out_forest_test.rb