fluent-plugin-forest 0.1.4 → 0.2.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.
- checksums.yaml +4 -4
- data/README.md +51 -1
- data/fluent-plugin-forest.gemspec +1 -1
- data/lib/fluent/plugin/out_forest.rb +28 -7
- data/test/plugin/test_out_forest.rb +155 -6
- data/test/plugin/test_out_forest_test.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8de96a623bfa6608e043f68ca1dbd0549ed4d315
|
4
|
+
data.tar.gz: e34249c2332e2520d75aba897b852045db5ce983
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64f32283a2f2cde11e07ce690ed810b492990ee9a48b7a18e91bb643b31140dec89991d9f924998ce0152505df703466adaf01d6bc8f2562c679ff20f7d4aa86
|
7
|
+
data.tar.gz: 35aa6d7e0c3e8dd8df00387569d60a6a583a66511fb0bdaa9fea9d04bba75f9b2742450b39c367f9d0dab1d164083125e99a6144c49fa8cf6165265a15ef2e45
|
data/README.md
CHANGED
@@ -98,9 +98,59 @@ If you want to place logs /var/archive for `service.search.**` as filename with
|
|
98
98
|
</case>
|
99
99
|
</match>
|
100
100
|
|
101
|
+
Version 0.2.0 or later, subsections adding/overwriting are supported. About the case below, three `<store>` subsections are defined for `search.**` pattern.
|
102
|
+
|
103
|
+
<match service.*>
|
104
|
+
type forest
|
105
|
+
subtype copy
|
106
|
+
<template>
|
107
|
+
<store>
|
108
|
+
type file
|
109
|
+
path /path/to/copy1
|
110
|
+
</store>
|
111
|
+
<store>
|
112
|
+
type file
|
113
|
+
path /path/to/copy2
|
114
|
+
</store>
|
115
|
+
</template>
|
116
|
+
<case search.**>
|
117
|
+
<store>
|
118
|
+
type file
|
119
|
+
path /path/to/copy3
|
120
|
+
</store>
|
121
|
+
</case>
|
122
|
+
</match>
|
123
|
+
|
124
|
+
Subsections with same arguments will be overwritten. See this example:
|
125
|
+
|
126
|
+
<match service.*>
|
127
|
+
type forest
|
128
|
+
subtype route
|
129
|
+
<template>
|
130
|
+
<route {search,admin}.a>
|
131
|
+
add_prefix first
|
132
|
+
</route>
|
133
|
+
<route {search,admin}.b>
|
134
|
+
add_prefix second
|
135
|
+
</route>
|
136
|
+
<route {search,admin}.c>
|
137
|
+
add_prefix third
|
138
|
+
</route>
|
139
|
+
<route {search,admin}.*>
|
140
|
+
add_prefix extra
|
141
|
+
</route>
|
142
|
+
</template>
|
143
|
+
<case admin.*>
|
144
|
+
<route {search,admin}.*>
|
145
|
+
add_prefix other
|
146
|
+
</route>
|
147
|
+
</case>
|
148
|
+
</match>
|
149
|
+
|
150
|
+
In this case, `<route {search,admin}.*>` subsection will be overwritten to add prefix 'other' for tag `service.admin.*`.
|
151
|
+
|
101
152
|
## TODO
|
102
153
|
|
103
|
-
* consider what to do next
|
104
154
|
* patches welcome!
|
105
155
|
|
106
156
|
## Copyright
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
Gem::Specification.new do |gem|
|
3
3
|
gem.name = "fluent-plugin-forest"
|
4
|
-
gem.version = "0.
|
4
|
+
gem.version = "0.2.0"
|
5
5
|
gem.authors = ["TAGOMORI Satoshi"]
|
6
6
|
gem.email = ["tagomoris@gmail.com"]
|
7
7
|
gem.description = %q{create sub-plugin dynamically per tags, with template configuration and parameters}
|
@@ -28,10 +28,9 @@ class Fluent::ForestOutput < Fluent::MultiOutput
|
|
28
28
|
@cases = []
|
29
29
|
|
30
30
|
conf.elements.each do |element|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|
31
|
+
# read and throw away to supress unread configuration warning
|
32
|
+
touch_recursive(element)
|
33
|
+
|
35
34
|
case element.name
|
36
35
|
when 'template'
|
37
36
|
@template = element
|
@@ -44,6 +43,15 @@ class Fluent::ForestOutput < Fluent::MultiOutput
|
|
44
43
|
self
|
45
44
|
end
|
46
45
|
|
46
|
+
def touch_recursive(e)
|
47
|
+
e.keys.each do |k|
|
48
|
+
e[k]
|
49
|
+
end
|
50
|
+
e.elements.each do |child|
|
51
|
+
touch_recursive(child)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
47
55
|
def shutdown
|
48
56
|
super
|
49
57
|
@mapping.values.each do |output|
|
@@ -51,12 +59,15 @@ class Fluent::ForestOutput < Fluent::MultiOutput
|
|
51
59
|
end
|
52
60
|
end
|
53
61
|
|
54
|
-
def parameter(tag, e)
|
62
|
+
def parameter(tag, e, name = 'instance', arg = '')
|
55
63
|
pairs = {}
|
56
64
|
e.each do |k,v|
|
57
65
|
pairs[k] = v.gsub('__TAG__', tag).gsub('${tag}', tag).gsub('__HOSTNAME__', @hostname).gsub('${hostname}', @hostname)
|
58
66
|
end
|
59
|
-
|
67
|
+
elements = e.elements.map do |child|
|
68
|
+
parameter(tag, child, child.name, child.arg)
|
69
|
+
end
|
70
|
+
Fluent::Config::Element.new(name, arg, pairs, elements)
|
60
71
|
end
|
61
72
|
|
62
73
|
def spec(tag)
|
@@ -64,7 +75,17 @@ class Fluent::ForestOutput < Fluent::MultiOutput
|
|
64
75
|
conf = parameter(tag, @template) + conf if @template # a + b -> b.merge(a) (see: fluentd/lib/fluent/config.rb)
|
65
76
|
@cases.each do |m,e|
|
66
77
|
if m.match(tag)
|
67
|
-
|
78
|
+
matched_case = parameter(tag, e)
|
79
|
+
|
80
|
+
matched_case.elements.each { |case_child|
|
81
|
+
unless case_child.arg.empty?
|
82
|
+
conf.elements.delete_if { |conf_child|
|
83
|
+
conf_child.name == case_child.name && conf_child.arg == case_child.arg
|
84
|
+
}
|
85
|
+
end
|
86
|
+
}
|
87
|
+
|
88
|
+
conf = matched_case + conf
|
68
89
|
break
|
69
90
|
end
|
70
91
|
end
|
@@ -12,7 +12,7 @@ remove_prefix test
|
|
12
12
|
<template>
|
13
13
|
key_name f
|
14
14
|
suffix !
|
15
|
-
tag out.__TAG__
|
15
|
+
tag out.__TAG__
|
16
16
|
</template>
|
17
17
|
<case foo.bar>
|
18
18
|
prefix p1:
|
@@ -62,7 +62,7 @@ subtype hoge
|
|
62
62
|
assert_equal 'yyyyyy.xx', conf['keyy']
|
63
63
|
assert_equal 'z1', conf['keyz']
|
64
64
|
assert_equal 'b', conf['alt_key']
|
65
|
-
|
65
|
+
|
66
66
|
conf = d.instance.spec('yy')
|
67
67
|
assert_equal 'xxxxxx', conf['keyx']
|
68
68
|
assert_equal 'yyyyyy.yy', conf['keyy']
|
@@ -82,6 +82,155 @@ subtype hoge
|
|
82
82
|
assert_equal 'd.zz', conf['alt_key']
|
83
83
|
end
|
84
84
|
|
85
|
+
NESTED_CONF = %[
|
86
|
+
subtype hoge
|
87
|
+
<template>
|
88
|
+
keyx xxxxxx
|
89
|
+
keyy yyyyyy.__TAG__
|
90
|
+
alt_key a
|
91
|
+
<tagx>
|
92
|
+
key xxx
|
93
|
+
</tagx>
|
94
|
+
<tagy>
|
95
|
+
key yyy.__TAG__
|
96
|
+
</tagy>
|
97
|
+
<tag_with attr.foo>
|
98
|
+
key bar
|
99
|
+
</tag_with>
|
100
|
+
<tag_with attr.foo>
|
101
|
+
key dup
|
102
|
+
</tag_with>
|
103
|
+
<tag_with attr.foo>
|
104
|
+
key dupdup
|
105
|
+
</tag_with>
|
106
|
+
</template>
|
107
|
+
<case xx>
|
108
|
+
keyz z1
|
109
|
+
alt_key b
|
110
|
+
</case>
|
111
|
+
<case yy.**>
|
112
|
+
keyz z2
|
113
|
+
alt_key c
|
114
|
+
<tagx>
|
115
|
+
key not_overwrite
|
116
|
+
</tagx>
|
117
|
+
<tag_with attr.foo>
|
118
|
+
key overwrite
|
119
|
+
</tag_with>
|
120
|
+
<tag_with attr.foo>
|
121
|
+
key overwrite_dup
|
122
|
+
</tag_with>
|
123
|
+
</case>
|
124
|
+
<case *>
|
125
|
+
keyz z3
|
126
|
+
alt_key d.__TAG__
|
127
|
+
<tagz>
|
128
|
+
<tagw>
|
129
|
+
key www
|
130
|
+
</tagw>
|
131
|
+
</tagz>
|
132
|
+
<tag_with attr.*>
|
133
|
+
key not_overwrite
|
134
|
+
</tag_with>
|
135
|
+
</case>
|
136
|
+
]
|
137
|
+
|
138
|
+
def test_spec_nested_overwrite_attributes_only
|
139
|
+
d = create_driver NESTED_CONF
|
140
|
+
conf = d.instance.spec('xx')
|
141
|
+
assert_equal 'xxxxxx', conf['keyx']
|
142
|
+
assert_equal 'yyyyyy.xx', conf['keyy']
|
143
|
+
assert_equal 'z1', conf['keyz']
|
144
|
+
assert_equal 'b', conf['alt_key']
|
145
|
+
|
146
|
+
assert_equal 5, conf.elements.size
|
147
|
+
|
148
|
+
assert_equal 'tagx', conf.elements[0].name
|
149
|
+
assert_equal 'xxx', conf.elements[0]['key']
|
150
|
+
|
151
|
+
assert_equal 'tagy', conf.elements[1].name
|
152
|
+
assert_equal 'yyy.xx', conf.elements[1]['key']
|
153
|
+
|
154
|
+
assert_equal 'tag_with', conf.elements[2].name
|
155
|
+
assert_equal 'attr.foo', conf.elements[2].arg
|
156
|
+
assert_equal 'bar', conf.elements[2]['key']
|
157
|
+
|
158
|
+
assert_equal 'tag_with', conf.elements[3].name
|
159
|
+
assert_equal 'attr.foo', conf.elements[3].arg
|
160
|
+
assert_equal 'dup', conf.elements[3]['key']
|
161
|
+
|
162
|
+
assert_equal 'tag_with', conf.elements[4].name
|
163
|
+
assert_equal 'attr.foo', conf.elements[4].arg
|
164
|
+
assert_equal 'dupdup', conf.elements[4]['key']
|
165
|
+
end
|
166
|
+
def test_spec_nested_overwrite_subsections_with_arg
|
167
|
+
d = create_driver NESTED_CONF
|
168
|
+
conf = d.instance.spec('yy')
|
169
|
+
|
170
|
+
assert_equal 'xxxxxx', conf['keyx']
|
171
|
+
assert_equal 'yyyyyy.yy', conf['keyy']
|
172
|
+
assert_equal 'z2', conf['keyz']
|
173
|
+
assert_equal 'c', conf['alt_key']
|
174
|
+
|
175
|
+
assert_equal 5, conf.elements.size
|
176
|
+
|
177
|
+
assert_equal 'tagx', conf.elements[0].name
|
178
|
+
assert_equal 'not_overwrite', conf.elements[0]['key']
|
179
|
+
|
180
|
+
assert_equal 'tag_with', conf.elements[1].name
|
181
|
+
assert_equal 'attr.foo', conf.elements[1].arg
|
182
|
+
assert_equal 'overwrite', conf.elements[1]['key']
|
183
|
+
|
184
|
+
assert_equal 'tag_with', conf.elements[2].name
|
185
|
+
assert_equal 'attr.foo', conf.elements[2].arg
|
186
|
+
assert_equal 'overwrite_dup', conf.elements[2]['key']
|
187
|
+
|
188
|
+
assert_equal 'tagx', conf.elements[3].name
|
189
|
+
assert_equal 'xxx', conf.elements[3]['key']
|
190
|
+
|
191
|
+
assert_equal 'tagy', conf.elements[4].name
|
192
|
+
assert_equal 'yyy.yy', conf.elements[4]['key']
|
193
|
+
end
|
194
|
+
|
195
|
+
def test_spec_nested_subsections_added
|
196
|
+
d = create_driver NESTED_CONF
|
197
|
+
conf = d.instance.spec('zz')
|
198
|
+
|
199
|
+
assert_equal 'xxxxxx', conf['keyx']
|
200
|
+
assert_equal 'yyyyyy.zz', conf['keyy']
|
201
|
+
assert_equal 'z3', conf['keyz']
|
202
|
+
assert_equal 'd.zz', conf['alt_key']
|
203
|
+
|
204
|
+
assert_equal 7, conf.elements.size
|
205
|
+
|
206
|
+
assert_equal 'tagz', conf.elements[0].name
|
207
|
+
assert_equal 1, conf.elements[0].elements.size
|
208
|
+
assert_equal 'tagw', conf.elements[0].elements[0].name
|
209
|
+
assert_equal 'www', conf.elements[0].elements[0]['key']
|
210
|
+
|
211
|
+
assert_equal 'tag_with', conf.elements[1].name
|
212
|
+
assert_equal 'attr.*', conf.elements[1].arg
|
213
|
+
assert_equal 'not_overwrite', conf.elements[1]['key']
|
214
|
+
|
215
|
+
assert_equal 'tagx', conf.elements[2].name
|
216
|
+
assert_equal 'xxx', conf.elements[2]['key']
|
217
|
+
|
218
|
+
assert_equal 'tagy', conf.elements[3].name
|
219
|
+
assert_equal 'yyy.zz', conf.elements[3]['key']
|
220
|
+
|
221
|
+
assert_equal 'tag_with', conf.elements[4].name
|
222
|
+
assert_equal 'attr.foo', conf.elements[4].arg
|
223
|
+
assert_equal 'bar', conf.elements[4]['key']
|
224
|
+
|
225
|
+
assert_equal 'tag_with', conf.elements[5].name
|
226
|
+
assert_equal 'attr.foo', conf.elements[5].arg
|
227
|
+
assert_equal 'dup', conf.elements[5]['key']
|
228
|
+
|
229
|
+
assert_equal 'tag_with', conf.elements[6].name
|
230
|
+
assert_equal 'attr.foo', conf.elements[6].arg
|
231
|
+
assert_equal 'dupdup', conf.elements[6]['key']
|
232
|
+
end
|
233
|
+
|
85
234
|
def test_spec_hostname
|
86
235
|
d = create_driver %[
|
87
236
|
subtype hoge
|
@@ -109,7 +258,7 @@ hostname somehost.local
|
|
109
258
|
assert_equal 'yyyyyy.xx', conf['keyy']
|
110
259
|
assert_equal 'z1', conf['keyz']
|
111
260
|
assert_equal 'b', conf['alt_key']
|
112
|
-
|
261
|
+
|
113
262
|
conf = d.instance.spec('yy')
|
114
263
|
assert_equal 'xxxxxx.somehost.local', conf['keyx']
|
115
264
|
assert_equal 'yyyyyy.yy', conf['keyy']
|
@@ -156,7 +305,7 @@ subtype hoge
|
|
156
305
|
assert_equal 'yyyyyy.xx', conf['keyy']
|
157
306
|
assert_equal 'z1', conf['keyz']
|
158
307
|
assert_equal 'b', conf['alt_key']
|
159
|
-
|
308
|
+
|
160
309
|
conf = d.instance.spec('yy')
|
161
310
|
assert_equal 'xxxxxx.' + hostname, conf['keyx']
|
162
311
|
assert_equal 'yyyyyy.yy', conf['keyy']
|
@@ -189,7 +338,7 @@ remove_prefix test
|
|
189
338
|
<template>
|
190
339
|
key_name f
|
191
340
|
suffix !
|
192
|
-
tag __TAG__
|
341
|
+
tag __TAG__
|
193
342
|
</template>
|
194
343
|
<case foo.bar>
|
195
344
|
prefix p1:
|
@@ -229,7 +378,7 @@ remove_prefix test
|
|
229
378
|
assert_equal time, e[1]
|
230
379
|
assert_equal "p4:message 1!", e[2]['f']
|
231
380
|
assert_nil e[2]['not_started']
|
232
|
-
|
381
|
+
|
233
382
|
e = emits[1]
|
234
383
|
assert_equal 'out.second', e[0]
|
235
384
|
assert_equal time, e[1]
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-forest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- TAGOMORI Satoshi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-08-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -76,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
76
76
|
version: '0'
|
77
77
|
requirements: []
|
78
78
|
rubyforge_project:
|
79
|
-
rubygems_version: 2.0.
|
79
|
+
rubygems_version: 2.0.2
|
80
80
|
signing_key:
|
81
81
|
specification_version: 4
|
82
82
|
summary: plugin to create output plugin instances per tags dynamically
|
@@ -85,3 +85,4 @@ test_files:
|
|
85
85
|
- test/output/out_forest_test.rb
|
86
86
|
- test/plugin/test_out_forest.rb
|
87
87
|
- test/plugin/test_out_forest_test.rb
|
88
|
+
has_rdoc:
|