fluentd 0.12.28 → 0.12.29
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of fluentd might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/ChangeLog +19 -708
- data/Rakefile +1 -1
- data/lib/fluent/agent.rb +1 -0
- data/lib/fluent/config/configure_proxy.rb +24 -3
- data/lib/fluent/config/error.rb +3 -0
- data/lib/fluent/config/section.rb +15 -0
- data/lib/fluent/plugin/filter_parser.rb +107 -0
- data/lib/fluent/plugin/filter_record_transformer.rb +3 -1
- data/lib/fluent/plugin/in_tail.rb +37 -9
- data/lib/fluent/plugin/out_forward.rb +2 -4
- data/lib/fluent/root_agent.rb +1 -1
- data/lib/fluent/version.rb +1 -1
- data/test/config/test_configurable.rb +89 -0
- data/test/config/test_types.rb +7 -3
- data/test/plugin/test_filter_parser.rb +719 -0
- data/test/plugin/test_filter_record_transformer.rb +18 -4
- data/test/plugin/test_in_tail.rb +73 -0
- data/test/test_root_agent.rb +42 -0
- metadata +5 -2
data/test/config/test_types.rb
CHANGED
@@ -72,9 +72,9 @@ class TestConfigTypes < ::Test::Unit::TestCase
|
|
72
72
|
assert_equal :val, Config::ENUM_TYPE.call('val', {list: [:val, :value, :v]})
|
73
73
|
assert_equal :v, Config::ENUM_TYPE.call('v', {list: [:val, :value, :v]})
|
74
74
|
assert_equal :value, Config::ENUM_TYPE.call('value', {list: [:val, :value, :v]})
|
75
|
-
assert_raises(Fluent::ConfigError){ Config::ENUM_TYPE.call('x', {list: [:val, :value, :v]}) }
|
76
|
-
assert_raises(RuntimeError){ Config::ENUM_TYPE.call('val', {}) }
|
77
|
-
assert_raises(RuntimeError){ Config::ENUM_TYPE.call('val', {list: ["val", "value", "v"]}) }
|
75
|
+
assert_raises(Fluent::ConfigError.new("valid options are val,value,v but got x")){ Config::ENUM_TYPE.call('x', {list: [:val, :value, :v]}) }
|
76
|
+
assert_raises(RuntimeError.new("Plugin BUG: config type 'enum' requires :list of symbols")){ Config::ENUM_TYPE.call('val', {}) }
|
77
|
+
assert_raises(RuntimeError.new("Plugin BUG: config type 'enum' requires :list of symbols")){ Config::ENUM_TYPE.call('val', {list: ["val", "value", "v"]}) }
|
78
78
|
end
|
79
79
|
|
80
80
|
test 'integer' do
|
@@ -138,6 +138,8 @@ class TestConfigTypes < ::Test::Unit::TestCase
|
|
138
138
|
|
139
139
|
assert_equal({"x"=>1,"y"=>60,"z"=>3600}, Config::HASH_TYPE.call('{"x":"1s","y":"1m","z":"1h"}', {value_type: :time}))
|
140
140
|
assert_equal({"x"=>1,"y"=>60,"z"=>3600}, Config::HASH_TYPE.call('x:1s,y:1m,z:1h', {value_type: :time}))
|
141
|
+
|
142
|
+
assert_raise(RuntimeError.new("unknown type in REFORMAT: foo")){ Config::HASH_TYPE.call("x:1,y:2", {value_type: :foo}) }
|
141
143
|
end
|
142
144
|
|
143
145
|
test 'array' do
|
@@ -162,6 +164,8 @@ class TestConfigTypes < ::Test::Unit::TestCase
|
|
162
164
|
}
|
163
165
|
assert_equal(["1","2"], Config::ARRAY_TYPE.call('["1","2"]', array_options))
|
164
166
|
assert_equal(["3"], Config::ARRAY_TYPE.call('["3"]', array_options))
|
167
|
+
|
168
|
+
assert_raise(RuntimeError.new("unknown type in REFORMAT: foo")){ Config::ARRAY_TYPE.call("1,2", {value_type: :foo}) }
|
165
169
|
end
|
166
170
|
end
|
167
171
|
end
|
@@ -0,0 +1,719 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
require 'timecop'
|
3
|
+
require 'fluent/plugin/filter_parser'
|
4
|
+
|
5
|
+
class ParserFilterTest < Test::Unit::TestCase
|
6
|
+
setup do
|
7
|
+
Fluent::Test.setup
|
8
|
+
@time = Time.parse("2012-01-02 13:14:15")
|
9
|
+
Timecop.freeze(@time)
|
10
|
+
end
|
11
|
+
|
12
|
+
teardown do
|
13
|
+
Timecop.return
|
14
|
+
end
|
15
|
+
|
16
|
+
CONFIG = %[
|
17
|
+
key_name message
|
18
|
+
format /^(?<x>.)(?<y>.) (?<time>.+)$/
|
19
|
+
time_format %Y%m%d%H%M%S
|
20
|
+
reserve_data true
|
21
|
+
]
|
22
|
+
|
23
|
+
def create_driver(conf=CONFIG,tag='test')
|
24
|
+
Fluent::Test::FilterTestDriver.new(Fluent::ParserFilter, tag).configure(conf)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_configure
|
28
|
+
assert_raise(Fluent::ConfigError) {
|
29
|
+
d = create_driver('')
|
30
|
+
}
|
31
|
+
assert_raise(Fluent::ConfigError) {
|
32
|
+
d = create_driver %[
|
33
|
+
format unknown_format_that_will_never_be_implemented
|
34
|
+
key_name foo
|
35
|
+
]
|
36
|
+
}
|
37
|
+
assert_nothing_raised {
|
38
|
+
d = create_driver %[
|
39
|
+
format /(?<x>.)/
|
40
|
+
key_name foo
|
41
|
+
]
|
42
|
+
}
|
43
|
+
assert_nothing_raised {
|
44
|
+
d = create_driver %[
|
45
|
+
format /(?<x>.)/
|
46
|
+
key_name foo
|
47
|
+
]
|
48
|
+
}
|
49
|
+
assert_nothing_raised {
|
50
|
+
d = create_driver %[
|
51
|
+
format /(?<x>.)/
|
52
|
+
key_name foo
|
53
|
+
]
|
54
|
+
}
|
55
|
+
assert_nothing_raised {
|
56
|
+
d = create_driver %[
|
57
|
+
format /(?<x>.)/
|
58
|
+
key_name foo
|
59
|
+
]
|
60
|
+
}
|
61
|
+
assert_nothing_raised {
|
62
|
+
d = create_driver %[
|
63
|
+
format json
|
64
|
+
key_name foo
|
65
|
+
]
|
66
|
+
}
|
67
|
+
assert_nothing_raised {
|
68
|
+
d = create_driver %[
|
69
|
+
format ltsv
|
70
|
+
key_name foo
|
71
|
+
]
|
72
|
+
}
|
73
|
+
assert_nothing_raised {
|
74
|
+
d = create_driver %[
|
75
|
+
format /^col1=(?<col1>.+) col2=(?<col2>.+)$/
|
76
|
+
key_name message
|
77
|
+
suppress_parse_error_log true
|
78
|
+
]
|
79
|
+
}
|
80
|
+
assert_nothing_raised {
|
81
|
+
d = create_driver %[
|
82
|
+
format /^col1=(?<col1>.+) col2=(?<col2>.+)$/
|
83
|
+
key_name message
|
84
|
+
suppress_parse_error_log false
|
85
|
+
]
|
86
|
+
}
|
87
|
+
d = create_driver %[
|
88
|
+
key_name foo
|
89
|
+
format /(?<x>.)/
|
90
|
+
]
|
91
|
+
assert_equal false, d.instance.reserve_data
|
92
|
+
end
|
93
|
+
|
94
|
+
# CONFIG = %[
|
95
|
+
# remove_prefix test
|
96
|
+
# add_prefix parsed
|
97
|
+
# key_name message
|
98
|
+
# format /^(?<x>.)(?<y>.) (?<time>.+)$/
|
99
|
+
# time_format %Y%m%d%H%M%S
|
100
|
+
# reserve_data true
|
101
|
+
# ]
|
102
|
+
def test_filter
|
103
|
+
d1 = create_driver(CONFIG, 'test.no.change')
|
104
|
+
time = @time.to_i
|
105
|
+
d1.run do
|
106
|
+
d1.filter({'message' => '12 20120402182059'}, time)
|
107
|
+
d1.filter({'message' => '34 20120402182100'}, time)
|
108
|
+
d1.filter({'message' => '56 20120402182100'}, time)
|
109
|
+
d1.filter({'message' => '78 20120402182101'}, time)
|
110
|
+
d1.filter({'message' => '90 20120402182100'}, time)
|
111
|
+
end
|
112
|
+
filtered = d1.filtered_as_array
|
113
|
+
assert_equal 5, filtered.length
|
114
|
+
|
115
|
+
first = filtered[0]
|
116
|
+
assert_equal 'test.no.change', first[0]
|
117
|
+
assert_equal Time.parse("2012-04-02 18:20:59").to_i, first[1]
|
118
|
+
assert_equal '1', first[2]['x']
|
119
|
+
assert_equal '2', first[2]['y']
|
120
|
+
assert_equal '12 20120402182059', first[2]['message']
|
121
|
+
|
122
|
+
second = filtered[1]
|
123
|
+
assert_equal 'test.no.change', second[0]
|
124
|
+
assert_equal Time.parse("2012-04-02 18:21:00").to_i, second[1]
|
125
|
+
assert_equal '3', second[2]['x']
|
126
|
+
assert_equal '4', second[2]['y']
|
127
|
+
|
128
|
+
third = filtered[2]
|
129
|
+
assert_equal 'test.no.change', third[0]
|
130
|
+
assert_equal Time.parse("2012-04-02 18:21:00").to_i, third[1]
|
131
|
+
assert_equal '5', third[2]['x']
|
132
|
+
assert_equal '6', third[2]['y']
|
133
|
+
|
134
|
+
fourth = filtered[3]
|
135
|
+
assert_equal 'test.no.change', fourth[0]
|
136
|
+
assert_equal Time.parse("2012-04-02 18:21:01").to_i, fourth[1]
|
137
|
+
assert_equal '7', fourth[2]['x']
|
138
|
+
assert_equal '8', fourth[2]['y']
|
139
|
+
|
140
|
+
fifth = filtered[4]
|
141
|
+
assert_equal 'test.no.change', fifth[0]
|
142
|
+
assert_equal Time.parse("2012-04-02 18:21:00").to_i, fifth[1]
|
143
|
+
assert_equal '9', fifth[2]['x']
|
144
|
+
assert_equal '0', fifth[2]['y']
|
145
|
+
|
146
|
+
d2 = create_driver(%[
|
147
|
+
tag parsed
|
148
|
+
key_name data
|
149
|
+
format /^(?<x>.)(?<y>.) (?<t>.+)$/
|
150
|
+
], 'test.no.change')
|
151
|
+
time = @time.to_i
|
152
|
+
d2.run do
|
153
|
+
d2.filter({'data' => '12 20120402182059'}, time)
|
154
|
+
d2.filter({'data' => '34 20120402182100'}, time)
|
155
|
+
end
|
156
|
+
filtered = d2.filtered_as_array
|
157
|
+
assert_equal 2, filtered.length
|
158
|
+
|
159
|
+
first = filtered[0]
|
160
|
+
assert_equal 'test.no.change', first[0]
|
161
|
+
assert_equal time, first[1]
|
162
|
+
assert_nil first[2]['data']
|
163
|
+
assert_equal '1', first[2]['x']
|
164
|
+
assert_equal '2', first[2]['y']
|
165
|
+
assert_equal '20120402182059', first[2]['t']
|
166
|
+
|
167
|
+
second = filtered[1]
|
168
|
+
assert_equal 'test.no.change', second[0]
|
169
|
+
assert_equal time, second[1]
|
170
|
+
assert_nil second[2]['data']
|
171
|
+
assert_equal '3', second[2]['x']
|
172
|
+
assert_equal '4', second[2]['y']
|
173
|
+
assert_equal '20120402182100', second[2]['t']
|
174
|
+
|
175
|
+
d3 = create_driver(%[
|
176
|
+
tag parsed
|
177
|
+
key_name data
|
178
|
+
format /^(?<x>[0-9])(?<y>[0-9]) (?<t>.+)$/
|
179
|
+
], 'test.no.change')
|
180
|
+
time = @time.to_i
|
181
|
+
d3.run do
|
182
|
+
d3.filter({'data' => '12 20120402182059'}, time)
|
183
|
+
d3.filter({'data' => '34 20120402182100'}, time)
|
184
|
+
d3.filter({'data' => 'xy 20120402182101'}, time)
|
185
|
+
end
|
186
|
+
filtered = d3.filtered_as_array
|
187
|
+
assert_equal 2, filtered.length
|
188
|
+
|
189
|
+
d3x = create_driver(%[
|
190
|
+
tag parsed
|
191
|
+
key_name data
|
192
|
+
format /^(?<x>\\d)(?<y>\\d) (?<t>.+)$/
|
193
|
+
reserve_data yes
|
194
|
+
], 'test.no.change')
|
195
|
+
time = @time.to_i
|
196
|
+
d3x.run do
|
197
|
+
d3x.filter({'data' => '12 20120402182059'}, time)
|
198
|
+
d3x.filter({'data' => '34 20120402182100'}, time)
|
199
|
+
d3x.filter({'data' => 'xy 20120402182101'}, time)
|
200
|
+
end
|
201
|
+
filtered = d3x.filtered_as_array
|
202
|
+
assert_equal 3, filtered.length
|
203
|
+
|
204
|
+
d4 = create_driver(%[
|
205
|
+
tag parsed
|
206
|
+
key_name data
|
207
|
+
format json
|
208
|
+
], 'test.no.change')
|
209
|
+
time = @time.to_i
|
210
|
+
d4.run do
|
211
|
+
d4.filter({'data' => '{"xxx":"first","yyy":"second"}', 'xxx' => 'x', 'yyy' => 'y'}, time)
|
212
|
+
d4.filter({'data' => 'foobar', 'xxx' => 'x', 'yyy' => 'y'}, time)
|
213
|
+
end
|
214
|
+
filtered = d4.filtered_as_array
|
215
|
+
assert_equal 1, filtered.length
|
216
|
+
|
217
|
+
d4x = create_driver(%[
|
218
|
+
tag parsed
|
219
|
+
key_name data
|
220
|
+
format json
|
221
|
+
reserve_data yes
|
222
|
+
], 'test.no.change')
|
223
|
+
time = @time.to_i
|
224
|
+
d4x.run do
|
225
|
+
d4x.filter({'data' => '{"xxx":"first","yyy":"second"}', 'xxx' => 'x', 'yyy' => 'y'}, time)
|
226
|
+
d4x.filter({'data' => 'foobar', 'xxx' => 'x', 'yyy' => 'y'}, time)
|
227
|
+
end
|
228
|
+
filtered = d4x.filtered_as_array
|
229
|
+
assert_equal 2, filtered.length
|
230
|
+
|
231
|
+
first = filtered[0]
|
232
|
+
assert_equal 'test.no.change', first[0]
|
233
|
+
assert_equal time, first[1]
|
234
|
+
assert_equal '{"xxx":"first","yyy":"second"}', first[2]['data']
|
235
|
+
assert_equal 'first', first[2]['xxx']
|
236
|
+
assert_equal 'second', first[2]['yyy']
|
237
|
+
|
238
|
+
second = filtered[1]
|
239
|
+
assert_equal 'test.no.change', second[0]
|
240
|
+
assert_equal time, second[1]
|
241
|
+
assert_equal 'foobar', second[2]['data']
|
242
|
+
assert_equal 'x', second[2]['xxx']
|
243
|
+
assert_equal 'y', second[2]['yyy']
|
244
|
+
end
|
245
|
+
|
246
|
+
CONFIG_LTSV = %[
|
247
|
+
format ltsv
|
248
|
+
key_name data
|
249
|
+
]
|
250
|
+
def test_filter_ltsv
|
251
|
+
d = create_driver(CONFIG_LTSV, 'test.no.change')
|
252
|
+
time = @time.to_i
|
253
|
+
d.run do
|
254
|
+
d.filter({'data' => "xxx:first\tyyy:second", 'xxx' => 'x', 'yyy' => 'y'}, time)
|
255
|
+
d.filter({'data' => "xxx:first\tyyy:second2", 'xxx' => 'x', 'yyy' => 'y'}, time)
|
256
|
+
end
|
257
|
+
filtered = d.filtered_as_array
|
258
|
+
assert_equal 2, filtered.length
|
259
|
+
|
260
|
+
first = filtered[0]
|
261
|
+
assert_equal 'test.no.change', first[0]
|
262
|
+
assert_equal time, first[1]
|
263
|
+
assert_nil first[2]['data']
|
264
|
+
assert_equal 'first', first[2]['xxx']
|
265
|
+
assert_equal 'second', first[2]['yyy']
|
266
|
+
|
267
|
+
second = filtered[1]
|
268
|
+
assert_equal 'test.no.change', second[0]
|
269
|
+
assert_equal time, second[1]
|
270
|
+
assert_nil first[2]['data']
|
271
|
+
assert_equal 'first', second[2]['xxx']
|
272
|
+
assert_equal 'second2', second[2]['yyy']
|
273
|
+
|
274
|
+
d = create_driver(CONFIG_LTSV + %[
|
275
|
+
reserve_data yes
|
276
|
+
], 'test.no.change')
|
277
|
+
time = @time.to_i
|
278
|
+
d.run do
|
279
|
+
d.filter({'data' => "xxx:first\tyyy:second", 'xxx' => 'x', 'yyy' => 'y'}, time)
|
280
|
+
d.filter({'data' => "xxx:first\tyyy:second2", 'xxx' => 'x', 'yyy' => 'y'}, time)
|
281
|
+
end
|
282
|
+
filtered = d.filtered_as_array
|
283
|
+
assert_equal 2, filtered.length
|
284
|
+
|
285
|
+
first = filtered[0]
|
286
|
+
assert_equal 'test.no.change', first[0]
|
287
|
+
assert_equal time, first[1]
|
288
|
+
assert_equal "xxx:first\tyyy:second", first[2]['data']
|
289
|
+
assert_equal 'first', first[2]['xxx']
|
290
|
+
assert_equal 'second', first[2]['yyy']
|
291
|
+
|
292
|
+
second = filtered[1]
|
293
|
+
assert_equal 'test.no.change', second[0]
|
294
|
+
assert_equal time, second[1]
|
295
|
+
assert_equal "xxx:first\tyyy:second", first[2]['data']
|
296
|
+
assert_equal 'first', second[2]['xxx']
|
297
|
+
assert_equal 'second2', second[2]['yyy']
|
298
|
+
|
299
|
+
# convert types
|
300
|
+
d = create_driver(CONFIG_LTSV + %[
|
301
|
+
types i:integer,s:string,f:float,b:bool
|
302
|
+
], 'test.no.change')
|
303
|
+
time = @time.to_i
|
304
|
+
d.run do
|
305
|
+
d.filter({'data' => "i:1\ts:2\tf:3\tb:true\tx:123"}, time)
|
306
|
+
end
|
307
|
+
filtered = d.filtered_as_array
|
308
|
+
assert_equal 1, filtered.length
|
309
|
+
|
310
|
+
first = filtered[0]
|
311
|
+
assert_equal 'test.no.change', first[0]
|
312
|
+
assert_equal time, first[1]
|
313
|
+
assert_equal 1, first[2]['i']
|
314
|
+
assert_equal '2', first[2]['s']
|
315
|
+
assert_equal 3.0, first[2]['f']
|
316
|
+
assert_equal true, first[2]['b']
|
317
|
+
assert_equal '123', first[2]['x']
|
318
|
+
end
|
319
|
+
|
320
|
+
CONFIG_TSV = %[
|
321
|
+
format tsv
|
322
|
+
key_name data
|
323
|
+
keys key1,key2,key3
|
324
|
+
]
|
325
|
+
def test_filter_tsv
|
326
|
+
d = create_driver(CONFIG_TSV, 'test.no.change')
|
327
|
+
time = @time.to_i
|
328
|
+
d.run do
|
329
|
+
d.filter({'data' => "value1\tvalue2\tvalueThree", 'xxx' => 'x', 'yyy' => 'y'}, time)
|
330
|
+
end
|
331
|
+
filtered = d.filtered_as_array
|
332
|
+
assert_equal 1, filtered.length
|
333
|
+
|
334
|
+
first = filtered[0]
|
335
|
+
assert_equal 'test.no.change', first[0]
|
336
|
+
assert_equal time, first[1]
|
337
|
+
assert_nil first[2]['data']
|
338
|
+
assert_equal 'value1', first[2]['key1']
|
339
|
+
assert_equal 'value2', first[2]['key2']
|
340
|
+
assert_equal 'valueThree', first[2]['key3']
|
341
|
+
end
|
342
|
+
|
343
|
+
CONFIG_CSV = %[
|
344
|
+
format csv
|
345
|
+
key_name data
|
346
|
+
keys key1,key2,key3
|
347
|
+
]
|
348
|
+
def test_filter_csv
|
349
|
+
d = create_driver(CONFIG_CSV, 'test.no.change')
|
350
|
+
time = @time.to_i
|
351
|
+
d.run do
|
352
|
+
d.filter({'data' => 'value1,"value2","value""ThreeYes!"', 'xxx' => 'x', 'yyy' => 'y'}, time)
|
353
|
+
end
|
354
|
+
filtered = d.filtered_as_array
|
355
|
+
assert_equal 1, filtered.length
|
356
|
+
|
357
|
+
first = filtered[0]
|
358
|
+
assert_equal 'test.no.change', first[0]
|
359
|
+
assert_equal time, first[1]
|
360
|
+
assert_nil first[2]['data']
|
361
|
+
assert_equal 'value1', first[2]['key1']
|
362
|
+
assert_equal 'value2', first[2]['key2']
|
363
|
+
assert_equal 'value"ThreeYes!', first[2]['key3']
|
364
|
+
end
|
365
|
+
|
366
|
+
CONFIG_HASH_VALUE_FIELD = %[
|
367
|
+
format json
|
368
|
+
key_name data
|
369
|
+
hash_value_field parsed
|
370
|
+
]
|
371
|
+
CONFIG_HASH_VALUE_FIELD_RESERVE_DATA = %[
|
372
|
+
format json
|
373
|
+
key_name data
|
374
|
+
reserve_data yes
|
375
|
+
hash_value_field parsed
|
376
|
+
]
|
377
|
+
CONFIG_HASH_VALUE_FIELD_WITH_INJECT_KEY_PREFIX = %[
|
378
|
+
format json
|
379
|
+
key_name data
|
380
|
+
hash_value_field parsed
|
381
|
+
inject_key_prefix data.
|
382
|
+
]
|
383
|
+
def test_filter_inject_hash_value_field
|
384
|
+
original = {'data' => '{"xxx":"first","yyy":"second"}', 'xxx' => 'x', 'yyy' => 'y'}
|
385
|
+
|
386
|
+
d = create_driver(CONFIG_HASH_VALUE_FIELD, 'test.no.change')
|
387
|
+
time = @time.to_i
|
388
|
+
d.run do
|
389
|
+
d.filter(original, time)
|
390
|
+
end
|
391
|
+
filtered = d.filtered_as_array
|
392
|
+
assert_equal 1, filtered.length
|
393
|
+
|
394
|
+
first = filtered[0]
|
395
|
+
assert_equal 'test.no.change', first[0]
|
396
|
+
assert_equal time, first[1]
|
397
|
+
|
398
|
+
record = first[2]
|
399
|
+
assert_equal 1, record.keys.size
|
400
|
+
assert_equal({"xxx"=>"first","yyy"=>"second"}, record['parsed'])
|
401
|
+
|
402
|
+
d = create_driver(CONFIG_HASH_VALUE_FIELD_RESERVE_DATA, 'test.no.change')
|
403
|
+
time = @time.to_i
|
404
|
+
d.run do
|
405
|
+
d.filter(original, time)
|
406
|
+
end
|
407
|
+
filtered = d.filtered_as_array
|
408
|
+
assert_equal 1, filtered.length
|
409
|
+
|
410
|
+
first = filtered[0]
|
411
|
+
assert_equal 'test.no.change', first[0]
|
412
|
+
assert_equal time, first[1]
|
413
|
+
|
414
|
+
record = first[2]
|
415
|
+
assert_equal 4, record.keys.size
|
416
|
+
assert_equal original['data'], record['data']
|
417
|
+
assert_equal original['xxx'], record['xxx']
|
418
|
+
assert_equal original['yyy'], record['yyy']
|
419
|
+
assert_equal({"xxx"=>"first","yyy"=>"second"}, record['parsed'])
|
420
|
+
|
421
|
+
d = create_driver(CONFIG_HASH_VALUE_FIELD_WITH_INJECT_KEY_PREFIX, 'test.no.change')
|
422
|
+
time = @time.to_i
|
423
|
+
d.run do
|
424
|
+
d.filter(original, time)
|
425
|
+
end
|
426
|
+
filtered = d.filtered_as_array
|
427
|
+
assert_equal 1, filtered.length
|
428
|
+
|
429
|
+
first = filtered[0]
|
430
|
+
assert_equal 'test.no.change', first[0]
|
431
|
+
assert_equal time, first[1]
|
432
|
+
|
433
|
+
record = first[2]
|
434
|
+
assert_equal 1, record.keys.size
|
435
|
+
assert_equal({"data.xxx"=>"first","data.yyy"=>"second"}, record['parsed'])
|
436
|
+
end
|
437
|
+
|
438
|
+
CONFIG_DONT_PARSE_TIME = %[
|
439
|
+
key_name data
|
440
|
+
format json
|
441
|
+
time_parse no
|
442
|
+
]
|
443
|
+
def test_time_should_be_reserved
|
444
|
+
t = Time.now.to_i
|
445
|
+
d = create_driver(CONFIG_DONT_PARSE_TIME, 'test.no.change')
|
446
|
+
|
447
|
+
d.run do
|
448
|
+
d.filter({'data' => '{"time":1383190430, "f1":"v1"}'}, t)
|
449
|
+
d.filter({'data' => '{"time":"1383190430", "f1":"v1"}'}, t)
|
450
|
+
d.filter({'data' => '{"time":"2013-10-31 12:34:03 +0900", "f1":"v1"}'}, t)
|
451
|
+
end
|
452
|
+
filtered = d.filtered_as_array
|
453
|
+
assert_equal 3, filtered.length
|
454
|
+
|
455
|
+
assert_equal 'test.no.change', filtered[0][0]
|
456
|
+
assert_equal 'v1', filtered[0][2]['f1']
|
457
|
+
assert_equal 1383190430, filtered[0][2]['time']
|
458
|
+
assert_equal t, filtered[0][1]
|
459
|
+
|
460
|
+
assert_equal 'test.no.change', filtered[1][0]
|
461
|
+
assert_equal 'v1', filtered[1][2]['f1']
|
462
|
+
assert_equal "1383190430", filtered[1][2]['time']
|
463
|
+
assert_equal t, filtered[1][1]
|
464
|
+
|
465
|
+
assert_equal 'test.no.change', filtered[2][0]
|
466
|
+
assert_equal 'v1', filtered[2][2]['f1']
|
467
|
+
assert_equal '2013-10-31 12:34:03 +0900', filtered[2][2]['time']
|
468
|
+
assert_equal t, filtered[2][1]
|
469
|
+
end
|
470
|
+
|
471
|
+
CONFIG_INVALID_TIME_VALUE = %[
|
472
|
+
remove_prefix test
|
473
|
+
key_name data
|
474
|
+
format json
|
475
|
+
] # 'time' is implicit @time_key
|
476
|
+
def test_filter_invalid_time_data
|
477
|
+
# should not raise errors
|
478
|
+
t = Time.now.to_i
|
479
|
+
d = create_driver(CONFIG_INVALID_TIME_VALUE, 'test.no.change')
|
480
|
+
assert_nothing_raised {
|
481
|
+
d.run do
|
482
|
+
d.filter({'data' => '{"time":[], "f1":"v1"}'}, t)
|
483
|
+
d.filter({'data' => '{"time":"thisisnottime", "f1":"v1"}'}, t)
|
484
|
+
end
|
485
|
+
}
|
486
|
+
filtered = d.filtered_as_array
|
487
|
+
assert_equal 1, filtered.length
|
488
|
+
|
489
|
+
assert_equal 'test.no.change', filtered[0][0]
|
490
|
+
assert_equal 0, filtered[0][1]
|
491
|
+
assert_equal 'v1', filtered[0][2]['f1']
|
492
|
+
assert_equal 0, filtered[0][2]['time'].to_i
|
493
|
+
end
|
494
|
+
|
495
|
+
# REGEXP = /^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$/
|
496
|
+
|
497
|
+
CONFIG_NOT_REPLACE = %[
|
498
|
+
remove_prefix test
|
499
|
+
key_name data
|
500
|
+
format /^(?<message>.*)$/
|
501
|
+
]
|
502
|
+
CONFIG_INVALID_BYTE = CONFIG_NOT_REPLACE + %[
|
503
|
+
replace_invalid_sequence true
|
504
|
+
]
|
505
|
+
def test_filter_invalid_byte
|
506
|
+
invalid_utf8 = "\xff".force_encoding('UTF-8')
|
507
|
+
|
508
|
+
d = create_driver(CONFIG_NOT_REPLACE, 'test.no.change')
|
509
|
+
assert_raise(ArgumentError) {
|
510
|
+
d.run do
|
511
|
+
d.filter({'data' => invalid_utf8}, Time.now.to_i)
|
512
|
+
end
|
513
|
+
}
|
514
|
+
|
515
|
+
d = create_driver(CONFIG_INVALID_BYTE, 'test.in')
|
516
|
+
assert_nothing_raised {
|
517
|
+
d.run do
|
518
|
+
d.emit({'data' => invalid_utf8}, Time.now.to_i)
|
519
|
+
end
|
520
|
+
}
|
521
|
+
filtered = d.filtered_as_array
|
522
|
+
assert_equal 1, filtered.length
|
523
|
+
assert_nil filtered[0][2]['data']
|
524
|
+
assert_equal '?'.force_encoding('UTF-8'), filtered[0][2]['message']
|
525
|
+
|
526
|
+
d = create_driver(CONFIG_INVALID_BYTE + %[
|
527
|
+
reserve_data yes
|
528
|
+
], 'test.no.change')
|
529
|
+
assert_nothing_raised {
|
530
|
+
d.run do
|
531
|
+
d.filter({'data' => invalid_utf8}, Time.now.to_i)
|
532
|
+
end
|
533
|
+
}
|
534
|
+
filtered = d.filtered_as_array
|
535
|
+
assert_equal 1, filtered.length
|
536
|
+
assert_equal invalid_utf8, filtered[0][2]['data']
|
537
|
+
assert_equal '?'.force_encoding('UTF-8'), filtered[0][2]['message']
|
538
|
+
|
539
|
+
invalid_ascii = "\xff".force_encoding('US-ASCII')
|
540
|
+
d = create_driver(CONFIG_INVALID_BYTE, 'test.no.change')
|
541
|
+
assert_nothing_raised {
|
542
|
+
d.run do
|
543
|
+
d.filter({'data' => invalid_ascii}, Time.now.to_i)
|
544
|
+
end
|
545
|
+
}
|
546
|
+
filtered = d.filtered_as_array
|
547
|
+
assert_equal 1, filtered.length
|
548
|
+
assert_nil filtered[0][2]['data']
|
549
|
+
assert_equal '?'.force_encoding('US-ASCII'), filtered[0][2]['message']
|
550
|
+
end
|
551
|
+
|
552
|
+
CONFIG_NOT_IGNORE = %[
|
553
|
+
remove_prefix test
|
554
|
+
key_name data
|
555
|
+
format json
|
556
|
+
hash_value_field parsed
|
557
|
+
]
|
558
|
+
CONFIG_IGNORE = CONFIG_NOT_IGNORE + %[
|
559
|
+
ignore_key_not_exist true
|
560
|
+
]
|
561
|
+
CONFIG_PASS_SAME_RECORD = CONFIG_IGNORE + %[
|
562
|
+
reserve_data true
|
563
|
+
]
|
564
|
+
def test_filter_key_not_exist
|
565
|
+
d = create_driver(CONFIG_NOT_IGNORE, 'test.no.ignore')
|
566
|
+
assert_nothing_raised {
|
567
|
+
d.run do
|
568
|
+
d.filter({'foo' => 'bar'}, Time.now.to_i)
|
569
|
+
end
|
570
|
+
}
|
571
|
+
assert_match /data does not exist/, d.instance.log.out.logs.first
|
572
|
+
|
573
|
+
d = create_driver(CONFIG_IGNORE, 'test.ignore')
|
574
|
+
assert_nothing_raised {
|
575
|
+
d.run do
|
576
|
+
d.filter({'foo' => 'bar'}, Time.now.to_i)
|
577
|
+
end
|
578
|
+
}
|
579
|
+
assert_not_match /data does not exist/, d.instance.log.out.logs.first
|
580
|
+
|
581
|
+
d = create_driver(CONFIG_PASS_SAME_RECORD, 'test.pass_same_record')
|
582
|
+
assert_nothing_raised {
|
583
|
+
d.run do
|
584
|
+
d.filter({'foo' => 'bar'}, Time.now.to_i)
|
585
|
+
end
|
586
|
+
}
|
587
|
+
filtered = d.filtered_as_array
|
588
|
+
assert_equal 1, filtered.length
|
589
|
+
assert_nil filtered[0][2]['data']
|
590
|
+
assert_equal 'bar', filtered[0][2]['foo']
|
591
|
+
end
|
592
|
+
|
593
|
+
# suppress_parse_error_log test
|
594
|
+
CONFIG_DISABELED_SUPPRESS_PARSE_ERROR_LOG = %[
|
595
|
+
tag hogelog
|
596
|
+
format /^col1=(?<col1>.+) col2=(?<col2>.+)$/
|
597
|
+
key_name message
|
598
|
+
suppress_parse_error_log false
|
599
|
+
]
|
600
|
+
CONFIG_ENABELED_SUPPRESS_PARSE_ERROR_LOG = %[
|
601
|
+
tag hogelog
|
602
|
+
format /^col1=(?<col1>.+) col2=(?<col2>.+)$/
|
603
|
+
key_name message
|
604
|
+
suppress_parse_error_log true
|
605
|
+
]
|
606
|
+
CONFIG_DEFAULT_SUPPRESS_PARSE_ERROR_LOG = %[
|
607
|
+
tag hogelog
|
608
|
+
format /^col1=(?<col1>.+) col2=(?<col2>.+)$/
|
609
|
+
key_name message
|
610
|
+
]
|
611
|
+
|
612
|
+
INVALID_MESSAGE = 'foo bar'
|
613
|
+
VALID_MESSAGE = 'col1=foo col2=bar'
|
614
|
+
|
615
|
+
# if call warn() raise exception
|
616
|
+
class DummyLoggerWarnedException < StandardError; end
|
617
|
+
class DummyLogger
|
618
|
+
def reset
|
619
|
+
end
|
620
|
+
def warn(message)
|
621
|
+
raise DummyLoggerWarnedException
|
622
|
+
end
|
623
|
+
end
|
624
|
+
|
625
|
+
def swap_logger(instance)
|
626
|
+
raise "use with block" unless block_given?
|
627
|
+
dummy = DummyLogger.new
|
628
|
+
saved_logger = instance.log
|
629
|
+
instance.log = dummy
|
630
|
+
restore = lambda{ instance.log = saved_logger }
|
631
|
+
|
632
|
+
yield
|
633
|
+
|
634
|
+
restore.call
|
635
|
+
end
|
636
|
+
|
637
|
+
def test_parser_error_warning
|
638
|
+
d = create_driver(CONFIG_INVALID_TIME_VALUE, 'test.no.change')
|
639
|
+
swap_logger(d.instance) do
|
640
|
+
assert_raise(DummyLoggerWarnedException) {
|
641
|
+
d.run do
|
642
|
+
d.filter({'data' => '{"time":[], "f1":"v1"}'}, Time.now.to_i)
|
643
|
+
end
|
644
|
+
}
|
645
|
+
end
|
646
|
+
end
|
647
|
+
|
648
|
+
class DefaultSuppressParseErrorLogTest < self
|
649
|
+
def setup
|
650
|
+
# default(disabled) 'suppress_parse_error_log' is not specify
|
651
|
+
@d = create_driver(CONFIG_DEFAULT_SUPPRESS_PARSE_ERROR_LOG, 'test.no.change')
|
652
|
+
end
|
653
|
+
|
654
|
+
def test_raise_exception
|
655
|
+
swap_logger(@d.instance) do
|
656
|
+
assert_raise(DummyLoggerWarnedException) {
|
657
|
+
@d.run do
|
658
|
+
@d.filter({'message' => INVALID_MESSAGE}, Time.now.to_i)
|
659
|
+
end
|
660
|
+
}
|
661
|
+
end
|
662
|
+
end
|
663
|
+
|
664
|
+
def test_nothing_raised
|
665
|
+
swap_logger(@d.instance) do
|
666
|
+
assert_nothing_raised {
|
667
|
+
@d.run do
|
668
|
+
@d.filter({'message' => VALID_MESSAGE}, Time.now.to_i)
|
669
|
+
end
|
670
|
+
}
|
671
|
+
end
|
672
|
+
end
|
673
|
+
end
|
674
|
+
|
675
|
+
class DisabledSuppressParseErrorLogTest < self
|
676
|
+
def setup
|
677
|
+
# disabled 'suppress_parse_error_log'
|
678
|
+
@d = create_driver(CONFIG_DISABELED_SUPPRESS_PARSE_ERROR_LOG, 'test.no.change')
|
679
|
+
end
|
680
|
+
|
681
|
+
def test_raise_exception
|
682
|
+
swap_logger(@d.instance) do
|
683
|
+
assert_raise(DummyLoggerWarnedException) {
|
684
|
+
@d.run do
|
685
|
+
@d.filter({'message' => INVALID_MESSAGE}, Time.now.to_i)
|
686
|
+
end
|
687
|
+
}
|
688
|
+
end
|
689
|
+
end
|
690
|
+
|
691
|
+
def test_nothing_raised
|
692
|
+
swap_logger(@d.instance) do
|
693
|
+
assert_nothing_raised {
|
694
|
+
@d.run do
|
695
|
+
@d.filter({'message' => VALID_MESSAGE}, Time.now.to_i)
|
696
|
+
end
|
697
|
+
}
|
698
|
+
end
|
699
|
+
end
|
700
|
+
end
|
701
|
+
|
702
|
+
class EnabledSuppressParseErrorLogTest < self
|
703
|
+
def setup
|
704
|
+
# enabled 'suppress_parse_error_log'
|
705
|
+
@d = create_driver(CONFIG_ENABELED_SUPPRESS_PARSE_ERROR_LOG, 'test.no.change')
|
706
|
+
end
|
707
|
+
|
708
|
+
def test_nothing_raised
|
709
|
+
swap_logger(@d.instance) do
|
710
|
+
assert_nothing_raised {
|
711
|
+
@d.run do
|
712
|
+
@d.filter({'message' => INVALID_MESSAGE}, Time.now.to_i)
|
713
|
+
@d.filter({'message' => VALID_MESSAGE}, Time.now.to_i)
|
714
|
+
end
|
715
|
+
}
|
716
|
+
end
|
717
|
+
end
|
718
|
+
end
|
719
|
+
end
|