fluent-plugin-forest 0.1.0

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/.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