fluentd 0.14.0 → 0.14.1
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/example/copy_roundrobin.conf +39 -0
- data/example/filter_stdout.conf +5 -5
- data/example/in_forward.conf +2 -2
- data/example/in_http.conf +2 -2
- data/example/in_syslog.conf +2 -2
- data/example/in_tail.conf +2 -2
- data/example/in_tcp.conf +2 -2
- data/example/in_udp.conf +2 -2
- data/example/out_buffered_null.conf +32 -0
- data/example/out_copy.conf +4 -4
- data/example/out_file.conf +2 -2
- data/example/out_forward.conf +2 -2
- data/example/v0_12_filter.conf +8 -8
- data/fluentd.gemspec +1 -1
- data/lib/fluent/command/fluentd.rb +6 -1
- data/lib/fluent/compat/handle_tag_name_mixin.rb +53 -0
- data/lib/fluent/compat/input.rb +1 -0
- data/lib/fluent/compat/output.rb +1 -0
- data/lib/fluent/compat/record_filter_mixin.rb +34 -0
- data/lib/fluent/compat/set_tag_key_mixin.rb +50 -0
- data/lib/fluent/compat/set_time_key_mixin.rb +69 -0
- data/lib/fluent/compat/type_converter.rb +90 -0
- data/lib/fluent/config/configure_proxy.rb +24 -4
- data/lib/fluent/config/dsl.rb +18 -1
- data/lib/fluent/config/v1_parser.rb +3 -2
- data/lib/fluent/configurable.rb +1 -1
- data/lib/fluent/event.rb +37 -9
- data/lib/fluent/mixin.rb +12 -286
- data/lib/fluent/plugin/buffer.rb +2 -2
- data/lib/fluent/plugin/in_dummy.rb +5 -1
- data/lib/fluent/plugin/in_gc_stat.rb +7 -37
- data/lib/fluent/plugin/in_http.rb +2 -0
- data/lib/fluent/plugin/{in_stream.rb → in_unix.rb} +0 -0
- data/lib/fluent/plugin/out_buffered_stdout.rb +60 -0
- data/lib/fluent/plugin/out_copy.rb +8 -51
- data/lib/fluent/plugin/out_null.rb +5 -5
- data/lib/fluent/plugin/out_relabel.rb +5 -5
- data/lib/fluent/plugin/out_roundrobin.rb +13 -40
- data/lib/fluent/plugin/output.rb +9 -0
- data/lib/fluent/plugin_helper.rb +2 -0
- data/lib/fluent/plugin_helper/formatter.rb +138 -0
- data/lib/fluent/plugin_helper/inject.rb +112 -0
- data/lib/fluent/plugin_helper/parser.rb +138 -0
- data/lib/fluent/plugin_helper/storage.rb +64 -50
- data/lib/fluent/process.rb +6 -1
- data/lib/fluent/registry.rb +1 -1
- data/lib/fluent/supervisor.rb +20 -2
- data/lib/fluent/test.rb +30 -5
- data/lib/fluent/test/base.rb +2 -66
- data/lib/fluent/test/driver/base.rb +3 -0
- data/lib/fluent/test/driver/base_owned.rb +106 -0
- data/lib/fluent/test/driver/formatter.rb +30 -0
- data/lib/fluent/test/driver/multi_output.rb +52 -0
- data/lib/fluent/test/driver/owner.rb +32 -0
- data/lib/fluent/test/driver/parser.rb +30 -0
- data/lib/fluent/test/helpers.rb +54 -0
- data/lib/fluent/test/log.rb +73 -0
- data/lib/fluent/time.rb +71 -0
- data/lib/fluent/version.rb +1 -1
- data/test/compat/test_parser.rb +82 -0
- data/test/config/test_configure_proxy.rb +15 -0
- data/test/config/test_dsl.rb +180 -2
- data/test/helper.rb +2 -24
- data/test/plugin/test_in_gc_stat.rb +6 -6
- data/test/plugin/test_in_http.rb +49 -32
- data/test/plugin/{test_in_stream.rb → test_in_unix.rb} +1 -1
- data/test/plugin/test_out_buffered_stdout.rb +108 -0
- data/test/plugin/test_out_copy.rb +88 -127
- data/test/plugin/test_out_null.rb +29 -0
- data/test/plugin/test_out_relabel.rb +28 -0
- data/test/plugin/test_out_roundrobin.rb +35 -29
- data/test/plugin/test_out_stdout.rb +4 -4
- data/test/plugin/test_output_as_buffered.rb +51 -0
- data/test/plugin/test_output_as_buffered_secondary.rb +13 -0
- data/test/plugin/test_parser_apache.rb +38 -0
- data/test/plugin/test_parser_apache2.rb +38 -0
- data/test/plugin/test_parser_apache_error.rb +40 -0
- data/test/plugin/test_parser_base.rb +32 -0
- data/test/plugin/test_parser_csv.rb +94 -0
- data/test/plugin/test_parser_json.rb +107 -0
- data/test/plugin/test_parser_labeled_tsv.rb +129 -0
- data/test/plugin/test_parser_multiline.rb +100 -0
- data/test/plugin/test_parser_nginx.rb +42 -0
- data/test/plugin/test_parser_none.rb +53 -0
- data/test/plugin/test_parser_regexp.rb +110 -0
- data/test/plugin/test_parser_syslog.rb +66 -0
- data/test/plugin/test_parser_time.rb +46 -0
- data/test/plugin/test_parser_tsv.rb +125 -0
- data/test/plugin_helper/test_child_process.rb +11 -2
- data/test/plugin_helper/test_formatter.rb +212 -0
- data/test/plugin_helper/test_inject.rb +388 -0
- data/test/plugin_helper/test_parser.rb +223 -0
- data/test/plugin_helper/test_retry_state.rb +40 -40
- data/test/plugin_helper/test_storage.rb +77 -10
- data/test/scripts/fluent/plugin/out_test.rb +22 -17
- data/test/scripts/fluent/plugin/out_test2.rb +80 -0
- data/test/test_event.rb +57 -0
- data/test/test_formatter.rb +0 -178
- data/test/test_output.rb +2 -152
- data/test/test_root_agent.rb +3 -2
- data/test/test_supervisor.rb +93 -26
- data/test/test_time_formatter.rb +186 -0
- metadata +69 -7
- data/test/test_parser.rb +0 -1087
@@ -0,0 +1,53 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
require 'fluent/test/driver/parser'
|
3
|
+
require 'fluent/plugin/parser'
|
4
|
+
|
5
|
+
class NoneParserTest < ::Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
Fluent::Test.setup
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_config_params
|
11
|
+
parser = Fluent::Test::Driver::Parser.new(Fluent::TextParser::NoneParser)
|
12
|
+
parser.configure({})
|
13
|
+
assert_equal "message", parser.instance.message_key
|
14
|
+
|
15
|
+
parser.configure('message_key' => 'foobar')
|
16
|
+
assert_equal "foobar", parser.instance.message_key
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_parse
|
20
|
+
parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin.new_parser('none'))
|
21
|
+
parser.configure({})
|
22
|
+
parser.instance.parse('log message!') { |time, record|
|
23
|
+
assert_equal({'message' => 'log message!'}, record)
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_parse_with_message_key
|
28
|
+
parser = Fluent::Test::Driver::Parser.new(Fluent::TextParser::NoneParser)
|
29
|
+
parser.configure('message_key' => 'foobar')
|
30
|
+
parser.instance.parse('log message!') { |time, record|
|
31
|
+
assert_equal({'foobar' => 'log message!'}, record)
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_parse_without_default_time
|
36
|
+
time_at_start = Time.now.to_i
|
37
|
+
|
38
|
+
parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin.new_parser('none'))
|
39
|
+
parser.configure({})
|
40
|
+
parser.instance.parse('log message!') { |time, record|
|
41
|
+
assert time && time >= time_at_start, "parser puts current time without time input"
|
42
|
+
assert_equal({'message' => 'log message!'}, record)
|
43
|
+
}
|
44
|
+
|
45
|
+
parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin.new_parser('none'))
|
46
|
+
parser.instance.estimate_current_event = false
|
47
|
+
parser.configure({})
|
48
|
+
parser.instance.parse('log message!') { |time, record|
|
49
|
+
assert_equal({'message' => 'log message!'}, record)
|
50
|
+
assert_nil time, "parser returns nil w/o time if configured so"
|
51
|
+
}
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
require 'fluent/test/driver/parser'
|
3
|
+
require 'fluent/plugin/parser'
|
4
|
+
|
5
|
+
class RegexpParserTest < ::Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
Fluent::Test.setup
|
8
|
+
end
|
9
|
+
|
10
|
+
def internal_test_case(parser)
|
11
|
+
text = '192.168.0.1 - - [28/Feb/2013:12:00:00 +0900] [14/Feb/2013:12:00:00 +0900] "true /,/user HTTP/1.1" 200 777'
|
12
|
+
parser.parse(text) { |time, record|
|
13
|
+
assert_equal(event_time('28/Feb/2013:12:00:00 +0900', format: '%d/%b/%Y:%H:%M:%S %z'), time)
|
14
|
+
assert_equal({
|
15
|
+
'user' => '-',
|
16
|
+
'flag' => true,
|
17
|
+
'code' => 200.0,
|
18
|
+
'size' => 777,
|
19
|
+
'date' => event_time('14/Feb/2013:12:00:00 +0900', format: '%d/%b/%Y:%H:%M:%S %z'),
|
20
|
+
'host' => '192.168.0.1',
|
21
|
+
'path' => ['/', '/user']
|
22
|
+
}, record)
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_parse_with_typed
|
27
|
+
# Use Regexp.new instead of // literal to avoid different parser behaviour in 1.9 and 2.0
|
28
|
+
internal_test_case(Fluent::Plugin::RegexpParser.new(Regexp.new(%q!^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] \[(?<date>[^\]]*)\] "(?<flag>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)$!), 'time_format'=>"%d/%b/%Y:%H:%M:%S %z", 'types'=>'user:string,date:time:%d/%b/%Y:%H:%M:%S %z,flag:bool,path:array,code:float,size:integer'))
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_parse_with_configure
|
32
|
+
# Specify conf by configure method instaed of intializer
|
33
|
+
regexp = Regexp.new(%q!^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] \[(?<date>[^\]]*)\] "(?<flag>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)$!)
|
34
|
+
parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin::RegexpParser.new(regexp))
|
35
|
+
parser.configure('time_format'=>"%d/%b/%Y:%H:%M:%S %z", 'types'=>'user:string,date:time:%d/%b/%Y:%H:%M:%S %z,flag:bool,path:array,code:float,size:integer')
|
36
|
+
internal_test_case(parser.instance)
|
37
|
+
assert_equal(regexp, parser.instance.patterns['format'])
|
38
|
+
assert_equal("%d/%b/%Y:%H:%M:%S %z", parser.instance.patterns['time_format'])
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_parse_with_typed_and_name_separator
|
42
|
+
internal_test_case(Fluent::Test::Driver::Parser.new(Fluent::Plugin::RegexpParser.new(Regexp.new(%q!^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] \[(?<date>[^\]]*)\] "(?<flag>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)$!), 'time_format'=>"%d/%b/%Y:%H:%M:%S %z", 'types'=>'user|string,date|time|%d/%b/%Y:%H:%M:%S %z,flag|bool,path|array,code|float,size|integer', 'types_label_delimiter'=>'|')).instance)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_parse_with_time_key
|
46
|
+
parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin::RegexpParser.new(/(?<logtime>[^\]]*)/))
|
47
|
+
parser.instance.configure(
|
48
|
+
'time_format'=>"%Y-%m-%d %H:%M:%S %z",
|
49
|
+
'time_key'=>'logtime',
|
50
|
+
)
|
51
|
+
text = '2013-02-28 12:00:00 +0900'
|
52
|
+
parser.instance.parse(text) do |time, record|
|
53
|
+
assert_equal Fluent::EventTime.parse(text), time
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_parse_without_time
|
58
|
+
time_at_start = Time.now.to_i
|
59
|
+
text = "tagomori_satoshi tagomoris 34\n"
|
60
|
+
|
61
|
+
parser = Fluent::Plugin::RegexpParser.new(Regexp.new(%q!^(?<name>[^ ]*) (?<user>[^ ]*) (?<age>\d*)$!))
|
62
|
+
parser.configure('types'=>'name:string,user:string,age:integer')
|
63
|
+
|
64
|
+
parser.parse(text) { |time, record|
|
65
|
+
assert time && time >= time_at_start, "parser puts current time without time input"
|
66
|
+
assert_equal "tagomori_satoshi", record["name"]
|
67
|
+
assert_equal "tagomoris", record["user"]
|
68
|
+
assert_equal 34, record["age"]
|
69
|
+
}
|
70
|
+
|
71
|
+
parser2 = Fluent::Test::Driver::Parser.new(Fluent::Plugin::RegexpParser.new(Regexp.new(%q!^(?<name>[^ ]*) (?<user>[^ ]*) (?<age>\d*)$!)))
|
72
|
+
parser2.configure('types'=>'name:string,user:string,age:integer')
|
73
|
+
parser2.instance.estimate_current_event = false
|
74
|
+
|
75
|
+
parser2.instance.parse(text) { |time, record|
|
76
|
+
assert_equal "tagomori_satoshi", record["name"]
|
77
|
+
assert_equal "tagomoris", record["user"]
|
78
|
+
assert_equal 34, record["age"]
|
79
|
+
|
80
|
+
assert_nil time, "parser returns nil if configured so"
|
81
|
+
}
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_parse_with_keep_time_key
|
85
|
+
parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin::RegexpParser.new(
|
86
|
+
Regexp.new(%q!(?<time>.*)!),
|
87
|
+
'time_format'=>"%d/%b/%Y:%H:%M:%S %z",
|
88
|
+
'keep_time_key'=>'true',
|
89
|
+
)
|
90
|
+
)
|
91
|
+
text = '28/Feb/2013:12:00:00 +0900'
|
92
|
+
parser.instance.parse(text) do |time, record|
|
93
|
+
assert_equal text, record['time']
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_parse_with_keep_time_key_with_typecast
|
98
|
+
parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin::RegexpParser.new(
|
99
|
+
Regexp.new(%q!(?<time>.*)!),
|
100
|
+
'time_format'=>"%d/%b/%Y:%H:%M:%S %z",
|
101
|
+
'keep_time_key'=>'true',
|
102
|
+
'types'=>'time:time:%d/%b/%Y:%H:%M:%S %z',
|
103
|
+
)
|
104
|
+
)
|
105
|
+
text = '28/Feb/2013:12:00:00 +0900'
|
106
|
+
parser.instance.parse(text) do |time, record|
|
107
|
+
assert_equal 1362020400, record['time']
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
require 'fluent/test/driver/parser'
|
3
|
+
require 'fluent/plugin/parser'
|
4
|
+
|
5
|
+
class SyslogParserTest < ::Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
Fluent::Test.setup
|
8
|
+
@parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin::SyslogParser)
|
9
|
+
@expected = {
|
10
|
+
'host' => '192.168.0.1',
|
11
|
+
'ident' => 'fluentd',
|
12
|
+
'pid' => '11111',
|
13
|
+
'message' => '[error] Syslog test'
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_parse
|
18
|
+
@parser.configure({})
|
19
|
+
@parser.instance.parse('Feb 28 12:00:00 192.168.0.1 fluentd[11111]: [error] Syslog test') { |time, record|
|
20
|
+
assert_equal(event_time('Feb 28 12:00:00', format: '%b %d %H:%M:%S'), time)
|
21
|
+
assert_equal(@expected, record)
|
22
|
+
}
|
23
|
+
assert_equal(Fluent::Plugin::SyslogParser::REGEXP, @parser.instance.patterns['format'])
|
24
|
+
assert_equal("%b %d %H:%M:%S", @parser.instance.patterns['time_format'])
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_parse_with_time_format
|
28
|
+
@parser.configure('time_format' => '%b %d %M:%S:%H')
|
29
|
+
@parser.instance.parse('Feb 28 00:00:12 192.168.0.1 fluentd[11111]: [error] Syslog test') { |time, record|
|
30
|
+
assert_equal(event_time('Feb 28 12:00:00', format: '%b %d %H:%M:%S'), time)
|
31
|
+
assert_equal(@expected, record)
|
32
|
+
}
|
33
|
+
assert_equal('%b %d %M:%S:%H', @parser.instance.patterns['time_format'])
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_parse_with_priority
|
37
|
+
@parser.configure('with_priority' => true)
|
38
|
+
@parser.instance.parse('<6>Feb 28 12:00:00 192.168.0.1 fluentd[11111]: [error] Syslog test') { |time, record|
|
39
|
+
assert_equal(event_time('Feb 28 12:00:00', format: '%b %d %H:%M:%S'), time)
|
40
|
+
assert_equal(@expected.merge('pri' => 6), record)
|
41
|
+
}
|
42
|
+
assert_equal(Fluent::Plugin::SyslogParser::REGEXP_WITH_PRI, @parser.instance.patterns['format'])
|
43
|
+
assert_equal("%b %d %H:%M:%S", @parser.instance.patterns['time_format'])
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_parse_without_colon
|
47
|
+
@parser.configure({})
|
48
|
+
@parser.instance.parse('Feb 28 12:00:00 192.168.0.1 fluentd[11111] [error] Syslog test') { |time, record|
|
49
|
+
assert_equal(event_time('Feb 28 12:00:00', format: '%b %d %H:%M:%S'), time)
|
50
|
+
assert_equal(@expected, record)
|
51
|
+
}
|
52
|
+
assert_equal(Fluent::Plugin::SyslogParser::REGEXP, @parser.instance.patterns['format'])
|
53
|
+
assert_equal("%b %d %H:%M:%S", @parser.instance.patterns['time_format'])
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_parse_with_keep_time_key
|
57
|
+
@parser.configure(
|
58
|
+
'time_format' => '%b %d %M:%S:%H',
|
59
|
+
'keep_time_key'=>'true',
|
60
|
+
)
|
61
|
+
text = 'Feb 28 00:00:12 192.168.0.1 fluentd[11111]: [error] Syslog test'
|
62
|
+
@parser.instance.parse(text) do |time, record|
|
63
|
+
assert_equal "Feb 28 00:00:12", record['time']
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
require 'fluent/test/driver/parser'
|
3
|
+
require 'fluent/plugin/parser'
|
4
|
+
|
5
|
+
class TimeParserTest < ::Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
Fluent::Test.setup
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_call_with_parse
|
11
|
+
parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin::Parser::TimeParser.new(nil))
|
12
|
+
|
13
|
+
assert(parser.instance.parse('2013-09-18 12:00:00 +0900').is_a?(Fluent::EventTime))
|
14
|
+
|
15
|
+
time = event_time('2013-09-18 12:00:00 +0900')
|
16
|
+
assert_equal(time, parser.instance.parse('2013-09-18 12:00:00 +0900'))
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_parse_with_strptime
|
20
|
+
parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin::Parser::TimeParser.new('%d/%b/%Y:%H:%M:%S %z'))
|
21
|
+
|
22
|
+
assert(parser.instance.parse('28/Feb/2013:12:00:00 +0900').is_a?(Fluent::EventTime))
|
23
|
+
|
24
|
+
time = event_time('28/Feb/2013:12:00:00 +0900', format: '%d/%b/%Y:%H:%M:%S %z')
|
25
|
+
assert_equal(time, parser.instance.parse('28/Feb/2013:12:00:00 +0900'))
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_parse_nsec_with_strptime
|
29
|
+
parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin::Parser::TimeParser.new('%d/%b/%Y:%H:%M:%S:%N %z'))
|
30
|
+
|
31
|
+
assert(parser.instance.parse('28/Feb/2013:12:00:00:123456789 +0900').is_a?(Fluent::EventTime))
|
32
|
+
|
33
|
+
time = event_time('28/Feb/2013:12:00:00:123456789 +0900', format: '%d/%b/%Y:%H:%M:%S:%N %z')
|
34
|
+
assert_equal_event_time(time, parser.instance.parse('28/Feb/2013:12:00:00:123456789 +0900'))
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_parse_with_invalid_argument
|
38
|
+
parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin::Parser::TimeParser.new(nil))
|
39
|
+
|
40
|
+
[[], {}, nil, true, 10000, //, ->{}, '', :symbol].each { |v|
|
41
|
+
assert_raise Fluent::ParserError do
|
42
|
+
parser.instance.parse(v)
|
43
|
+
end
|
44
|
+
}
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
require 'fluent/test/driver/parser'
|
3
|
+
require 'fluent/plugin/parser'
|
4
|
+
|
5
|
+
class TSVParserTest < ::Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
Fluent::Test.setup
|
8
|
+
end
|
9
|
+
|
10
|
+
data('array param' => '["a","b"]', 'string param' => 'a,b')
|
11
|
+
def test_config_params(param)
|
12
|
+
parser = Fluent::Test::Driver::Parser.new(Fluent::TextParser::TSVParser)
|
13
|
+
|
14
|
+
assert_equal "\t", parser.instance.delimiter
|
15
|
+
|
16
|
+
parser.configure(
|
17
|
+
'keys' => param,
|
18
|
+
'delimiter' => ',',
|
19
|
+
)
|
20
|
+
|
21
|
+
assert_equal ['a', 'b'], parser.instance.keys
|
22
|
+
assert_equal ",", parser.instance.delimiter
|
23
|
+
end
|
24
|
+
|
25
|
+
data('array param' => '["time","a","b"]', 'string param' => 'time,a,b')
|
26
|
+
def test_parse(param)
|
27
|
+
parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin::TSVParser)
|
28
|
+
parser.configure('keys' => param, 'time_key' => 'time')
|
29
|
+
parser.instance.parse("2013/02/28 12:00:00\t192.168.0.1\t111") { |time, record|
|
30
|
+
assert_equal(event_time('2013/02/28 12:00:00', format: '%Y/%m/%d %H:%M:%S'), time)
|
31
|
+
assert_equal({
|
32
|
+
'a' => '192.168.0.1',
|
33
|
+
'b' => '111',
|
34
|
+
}, record)
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_parse_with_time
|
39
|
+
time_at_start = Time.now.to_i
|
40
|
+
|
41
|
+
parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin::TSVParser)
|
42
|
+
parser.configure('keys' => 'a,b')
|
43
|
+
parser.instance.parse("192.168.0.1\t111") { |time, record|
|
44
|
+
assert time && time >= time_at_start, "parser puts current time without time input"
|
45
|
+
assert_equal({
|
46
|
+
'a' => '192.168.0.1',
|
47
|
+
'b' => '111',
|
48
|
+
}, record)
|
49
|
+
}
|
50
|
+
|
51
|
+
parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin::TSVParser)
|
52
|
+
parser.instance.estimate_current_event = false
|
53
|
+
parser.configure('keys' => 'a,b', 'time_key' => 'time')
|
54
|
+
parser.instance.parse("192.168.0.1\t111") { |time, record|
|
55
|
+
assert_equal({
|
56
|
+
'a' => '192.168.0.1',
|
57
|
+
'b' => '111',
|
58
|
+
}, record)
|
59
|
+
assert_nil time, "parser returns nil w/o time and if configured so"
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
data(
|
64
|
+
'left blank column' => ["\t@\t@", {"1" => "","2" => "@","3" => "@"}],
|
65
|
+
'center blank column' => ["@\t\t@", {"1" => "@","2" => "","3" => "@"}],
|
66
|
+
'right blank column' => ["@\t@\t", {"1" => "@","2" => "@","3" => ""}],
|
67
|
+
'2 right blank columns' => ["@\t\t", {"1" => "@","2" => "","3" => ""}],
|
68
|
+
'left blank columns' => ["\t\t@", {"1" => "","2" => "","3" => "@"}],
|
69
|
+
'all blank columns' => ["\t\t", {"1" => "","2" => "","3" => ""}])
|
70
|
+
def test_black_column(data)
|
71
|
+
line, expected = data
|
72
|
+
|
73
|
+
parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin::TSVParser)
|
74
|
+
parser.configure('keys' => '1,2,3')
|
75
|
+
parser.instance.parse(line) { |time, record|
|
76
|
+
assert_equal(expected, record)
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_parse_with_keep_time_key
|
81
|
+
parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin::TSVParser)
|
82
|
+
parser.configure(
|
83
|
+
'keys'=>'time',
|
84
|
+
'time_key'=>'time',
|
85
|
+
'time_format'=>"%d/%b/%Y:%H:%M:%S %z",
|
86
|
+
'keep_time_key'=>'true',
|
87
|
+
)
|
88
|
+
text = '28/Feb/2013:12:00:00 +0900'
|
89
|
+
parser.instance.parse(text) do |time, record|
|
90
|
+
assert_equal text, record['time']
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
data('array param' => '["a","b","c","d","e","f"]', 'string param' => 'a,b,c,d,e,f')
|
95
|
+
def test_parse_with_null_value_pattern
|
96
|
+
parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin::TSVParser)
|
97
|
+
parser.configure(
|
98
|
+
'keys'=>param,
|
99
|
+
'time_key'=>'time',
|
100
|
+
'null_value_pattern'=>'^(-|null|NULL)$'
|
101
|
+
)
|
102
|
+
parser.instance.parse("-\tnull\tNULL\t\t--\tnuLL") do |time, record|
|
103
|
+
assert_nil record['a']
|
104
|
+
assert_nil record['b']
|
105
|
+
assert_nil record['c']
|
106
|
+
assert_equal record['d'], ''
|
107
|
+
assert_equal record['e'], '--'
|
108
|
+
assert_equal record['f'], 'nuLL'
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
data('array param' => '["a","b"]', 'string param' => 'a,b')
|
113
|
+
def test_parse_with_null_empty_string
|
114
|
+
parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin::TSVParser)
|
115
|
+
parser.configure(
|
116
|
+
'keys'=>param,
|
117
|
+
'time_key'=>'time',
|
118
|
+
'null_empty_string'=>true
|
119
|
+
)
|
120
|
+
parser.instance.parse("\t ") do |time, record|
|
121
|
+
assert_nil record['a']
|
122
|
+
assert_equal record['b'], ' '
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -312,6 +312,14 @@ class ChildProcessTest < Test::Unit::TestCase
|
|
312
312
|
ary = []
|
313
313
|
arguments = ["-e", "10.times{ puts 'okay'; STDOUT.flush rescue nil; sleep #{TEST_WAIT_INTERVAL_FOR_LOOP} }"] # 0.5 * 10
|
314
314
|
Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
|
315
|
+
assert_equal [], @d.log.out.logs
|
316
|
+
@d.log.out.singleton_class.module_eval do
|
317
|
+
define_method(:write){|message|
|
318
|
+
raise "boo" if message.include?('test: {"test":"test"}') || message.include?('test: {"test"=>"test"}')
|
319
|
+
@logs.push message
|
320
|
+
}
|
321
|
+
end
|
322
|
+
|
315
323
|
@d.child_process_execute(:t7, "ruby", arguments: arguments, interval: 2, immediate: true, mode: [:read]) do |io|
|
316
324
|
ary << io.read.split("\n").map(&:chomp).join
|
317
325
|
end
|
@@ -319,8 +327,9 @@ class ChildProcessTest < Test::Unit::TestCase
|
|
319
327
|
assert_equal 1, @d._child_process_processes.size
|
320
328
|
@d.stop
|
321
329
|
warn_msg = '[warn]: previous child process is still running. skipped. title=:t7 command="ruby" arguments=["-e", "10.times{ puts \'okay\'; STDOUT.flush rescue nil; sleep 0.5 }"] interval=2 parallel=false' + "\n"
|
322
|
-
|
323
|
-
assert{
|
330
|
+
logs = @d.log.out.logs
|
331
|
+
assert{ logs.first.end_with?(warn_msg) }
|
332
|
+
assert{ logs.all?{|line| line.end_with?(warn_msg) } }
|
324
333
|
@d.shutdown; @d.close; @d.terminate
|
325
334
|
assert_equal [], @d.log.out.logs
|
326
335
|
end
|
@@ -0,0 +1,212 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
require 'fluent/plugin_helper/formatter'
|
3
|
+
require 'fluent/plugin/base'
|
4
|
+
|
5
|
+
class FormatterHelperTest < Test::Unit::TestCase
|
6
|
+
class ExampleFormatter < Fluent::Plugin::Formatter
|
7
|
+
Fluent::Plugin.register_formatter('example', self)
|
8
|
+
def format(tag, time, record)
|
9
|
+
"#{tag},#{time.to_i},#{record.keys.sort.join(',')}" # hey, you miss values! :P
|
10
|
+
end
|
11
|
+
end
|
12
|
+
class Example2Formatter < Fluent::Plugin::Formatter
|
13
|
+
Fluent::Plugin.register_formatter('example2', self)
|
14
|
+
def format(tag, time, record)
|
15
|
+
"#{tag},#{time.to_i},#{record.values.sort.join(',')}" # key...
|
16
|
+
end
|
17
|
+
end
|
18
|
+
class Dummy < Fluent::Plugin::TestBase
|
19
|
+
helpers :formatter
|
20
|
+
end
|
21
|
+
|
22
|
+
setup do
|
23
|
+
@d = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
teardown do
|
27
|
+
if @d
|
28
|
+
@d.stop unless @d.stopped?
|
29
|
+
@d.shutdown unless @d.shutdown?
|
30
|
+
@d.close unless @d.closed?
|
31
|
+
@d.terminate unless @d.terminated?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
test 'can be initialized without any formatters at first' do
|
36
|
+
d = Dummy.new
|
37
|
+
assert_equal 0, d._formatters.size
|
38
|
+
end
|
39
|
+
|
40
|
+
test 'can be configured without format sections' do
|
41
|
+
d = Dummy.new
|
42
|
+
assert_nothing_raised do
|
43
|
+
d.configure(config_element())
|
44
|
+
end
|
45
|
+
assert_equal 0, d._formatters.size
|
46
|
+
end
|
47
|
+
|
48
|
+
test 'can be configured with a format section' do
|
49
|
+
d = Dummy.new
|
50
|
+
conf = config_element('ROOT', '', {}, [
|
51
|
+
config_element('format', '', {'@type' => 'example'})
|
52
|
+
])
|
53
|
+
assert_nothing_raised do
|
54
|
+
d.configure(conf)
|
55
|
+
end
|
56
|
+
assert_equal 1, d._formatters.size
|
57
|
+
assert{ d._formatters.values.all?{ |formatter| !formatter.started? } }
|
58
|
+
end
|
59
|
+
|
60
|
+
test 'can be configured with 2 or more format sections with different usages with each other' do
|
61
|
+
d = Dummy.new
|
62
|
+
conf = config_element('ROOT', '', {}, [
|
63
|
+
config_element('format', 'default', {'@type' => 'example'}),
|
64
|
+
config_element('format', 'extra', {'@type' => 'example2'}),
|
65
|
+
])
|
66
|
+
assert_nothing_raised do
|
67
|
+
d.configure(conf)
|
68
|
+
end
|
69
|
+
assert_equal 2, d._formatters.size
|
70
|
+
assert{ d._formatters.values.all?{ |formatter| !formatter.started? } }
|
71
|
+
end
|
72
|
+
|
73
|
+
test 'cannot be configured with 2 format sections with same usage' do
|
74
|
+
d = Dummy.new
|
75
|
+
conf = config_element('ROOT', '', {}, [
|
76
|
+
config_element('format', 'default', {'@type' => 'example'}),
|
77
|
+
config_element('format', 'extra', {'@type' => 'example2'}),
|
78
|
+
config_element('format', 'extra', {'@type' => 'example2'}),
|
79
|
+
])
|
80
|
+
assert_raises Fluent::ConfigError do
|
81
|
+
d.configure(conf)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
test 'creates a format plugin instance which is already configured without usage' do
|
86
|
+
@d = d = Dummy.new
|
87
|
+
conf = config_element('ROOT', '', {}, [
|
88
|
+
config_element('format', '', {'@type' => 'example'})
|
89
|
+
])
|
90
|
+
d.configure(conf)
|
91
|
+
d.start
|
92
|
+
|
93
|
+
formatter = d.formatter_create
|
94
|
+
assert{ formatter.is_a? ExampleFormatter }
|
95
|
+
assert formatter.started?
|
96
|
+
end
|
97
|
+
|
98
|
+
test 'creates a formatter plugin instance which is already configured with usage' do
|
99
|
+
@d = d = Dummy.new
|
100
|
+
conf = config_element('ROOT', '', {}, [
|
101
|
+
config_element('format', 'mydata', {'@type' => 'example'})
|
102
|
+
])
|
103
|
+
d.configure(conf)
|
104
|
+
d.start
|
105
|
+
|
106
|
+
formatter = d.formatter_create(usage: 'mydata')
|
107
|
+
assert{ formatter.is_a? ExampleFormatter }
|
108
|
+
assert formatter.started?
|
109
|
+
end
|
110
|
+
|
111
|
+
test 'creates a formatter plugin without configurations' do
|
112
|
+
@d = d = Dummy.new
|
113
|
+
d.configure(config_element())
|
114
|
+
d.start
|
115
|
+
|
116
|
+
formatter = d.formatter_create(usage: 'mydata', type: 'example', conf: config_element('format', 'mydata'))
|
117
|
+
assert{ formatter.is_a? ExampleFormatter }
|
118
|
+
assert formatter.started?
|
119
|
+
end
|
120
|
+
|
121
|
+
test 'creates 2 or more formatter plugin instances' do
|
122
|
+
@d = d = Dummy.new
|
123
|
+
conf = config_element('ROOT', '', {}, [
|
124
|
+
config_element('format', 'mydata', {'@type' => 'example'}),
|
125
|
+
config_element('format', 'secret', {'@type' => 'example2'})
|
126
|
+
])
|
127
|
+
d.configure(conf)
|
128
|
+
d.start
|
129
|
+
|
130
|
+
p1 = d.formatter_create(usage: 'mydata')
|
131
|
+
p2 = d.formatter_create(usage: 'secret')
|
132
|
+
assert{ p1.is_a? ExampleFormatter }
|
133
|
+
assert p1.started?
|
134
|
+
assert{ p2.is_a? Example2Formatter }
|
135
|
+
assert p2.started?
|
136
|
+
end
|
137
|
+
|
138
|
+
test 'calls lifecycle methods for all plugin instances via owner plugin' do
|
139
|
+
@d = d = Dummy.new
|
140
|
+
conf = config_element('ROOT', '', {}, [ config_element('format', '', {'@type' => 'example'}), config_element('format', 'e2', {'@type' => 'example'}) ])
|
141
|
+
d.configure(conf)
|
142
|
+
d.start
|
143
|
+
|
144
|
+
i1 = d.formatter_create(usage: '')
|
145
|
+
i2 = d.formatter_create(usage: 'e2')
|
146
|
+
i3 = d.formatter_create(usage: 'e3', type: 'example2')
|
147
|
+
|
148
|
+
assert i1.started?
|
149
|
+
assert i2.started?
|
150
|
+
assert i3.started?
|
151
|
+
|
152
|
+
assert !i1.stopped?
|
153
|
+
assert !i2.stopped?
|
154
|
+
assert !i3.stopped?
|
155
|
+
|
156
|
+
d.stop
|
157
|
+
|
158
|
+
assert i1.stopped?
|
159
|
+
assert i2.stopped?
|
160
|
+
assert i3.stopped?
|
161
|
+
|
162
|
+
assert !i1.before_shutdown?
|
163
|
+
assert !i2.before_shutdown?
|
164
|
+
assert !i3.before_shutdown?
|
165
|
+
|
166
|
+
d.before_shutdown
|
167
|
+
|
168
|
+
assert i1.before_shutdown?
|
169
|
+
assert i2.before_shutdown?
|
170
|
+
assert i3.before_shutdown?
|
171
|
+
|
172
|
+
assert !i1.shutdown?
|
173
|
+
assert !i2.shutdown?
|
174
|
+
assert !i3.shutdown?
|
175
|
+
|
176
|
+
d.shutdown
|
177
|
+
|
178
|
+
assert i1.shutdown?
|
179
|
+
assert i2.shutdown?
|
180
|
+
assert i3.shutdown?
|
181
|
+
|
182
|
+
assert !i1.after_shutdown?
|
183
|
+
assert !i2.after_shutdown?
|
184
|
+
assert !i3.after_shutdown?
|
185
|
+
|
186
|
+
d.after_shutdown
|
187
|
+
|
188
|
+
assert i1.after_shutdown?
|
189
|
+
assert i2.after_shutdown?
|
190
|
+
assert i3.after_shutdown?
|
191
|
+
|
192
|
+
assert !i1.closed?
|
193
|
+
assert !i2.closed?
|
194
|
+
assert !i3.closed?
|
195
|
+
|
196
|
+
d.close
|
197
|
+
|
198
|
+
assert i1.closed?
|
199
|
+
assert i2.closed?
|
200
|
+
assert i3.closed?
|
201
|
+
|
202
|
+
assert !i1.terminated?
|
203
|
+
assert !i2.terminated?
|
204
|
+
assert !i3.terminated?
|
205
|
+
|
206
|
+
d.terminate
|
207
|
+
|
208
|
+
assert i1.terminated?
|
209
|
+
assert i2.terminated?
|
210
|
+
assert i3.terminated?
|
211
|
+
end
|
212
|
+
end
|