fluentd 0.10.50 → 0.10.51
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/.travis.yml +2 -2
- data/CONTRIBUTING.md +34 -0
- data/ChangeLog +11 -0
- data/README.md +3 -3
- data/Rakefile +3 -0
- data/fluent.conf +1 -0
- data/lib/fluent/config.rb +10 -15
- data/lib/fluent/config/parser.rb +0 -7
- data/lib/fluent/config/v1_parser.rb +0 -6
- data/lib/fluent/engine.rb +10 -14
- data/lib/fluent/formatter.rb +1 -2
- data/lib/fluent/log.rb +13 -9
- data/lib/fluent/parser.rb +130 -9
- data/lib/fluent/plugin/in_stream.rb +0 -28
- data/lib/fluent/plugin/in_syslog.rb +28 -100
- data/lib/fluent/plugin/in_tail.rb +6 -5
- data/lib/fluent/plugin/in_tcp.rb +15 -0
- data/lib/fluent/plugin/in_udp.rb +17 -0
- data/lib/fluent/plugin/socket_util.rb +119 -0
- data/lib/fluent/supervisor.rb +52 -10
- data/lib/fluent/test/base.rb +2 -2
- data/lib/fluent/version.rb +1 -1
- data/spec/config/config_parser_spec.rb +7 -1
- data/test/plugin/test_in_http.rb +3 -3
- data/test/plugin/test_in_stream.rb +0 -24
- data/test/plugin/test_in_syslog.rb +22 -1
- data/test/plugin/test_in_tail.rb +60 -19
- data/test/plugin/test_in_tcp.rb +88 -0
- data/test/plugin/test_in_udp.rb +104 -0
- data/test/plugin/test_out_exec.rb +4 -4
- data/test/plugin/test_out_file.rb +19 -0
- data/test/test_config.rb +9 -2
- data/test/test_formatter.rb +8 -4
- data/test/test_parser.rb +175 -2
- metadata +9 -2
data/lib/fluent/test/base.rb
CHANGED
@@ -39,11 +39,11 @@ module Fluent
|
|
39
39
|
|
40
40
|
attr_reader :instance, :config
|
41
41
|
|
42
|
-
def configure(str)
|
42
|
+
def configure(str, use_v1 = false)
|
43
43
|
if str.is_a?(Fluent::Config::Element)
|
44
44
|
@config = str
|
45
45
|
else
|
46
|
-
@config = Config.parse(str, "(test)")
|
46
|
+
@config = Config.parse(str, "(test)", "(test_dir)", use_v1)
|
47
47
|
end
|
48
48
|
@instance.configure(@config)
|
49
49
|
self
|
data/lib/fluent/version.rb
CHANGED
@@ -8,6 +8,12 @@ require "fluent/config/v1_parser"
|
|
8
8
|
describe Fluent::Config::V1Parser do
|
9
9
|
include_context 'config_helper'
|
10
10
|
|
11
|
+
def read_config(path)
|
12
|
+
path = File.expand_path(path)
|
13
|
+
data = File.read(path)
|
14
|
+
Fluent::Config::V1Parser.parse(data, File.basename(path), File.dirname(path))
|
15
|
+
end
|
16
|
+
|
11
17
|
def parse_text(text)
|
12
18
|
basepath = File.expand_path(File.dirname(__FILE__) + '/../../')
|
13
19
|
Fluent::Config::V1Parser.parse(text, '(test)', basepath, nil)
|
@@ -238,7 +244,7 @@ describe Fluent::Config::V1Parser do
|
|
238
244
|
|
239
245
|
it 'parses @include / include correctly' do
|
240
246
|
prepare_config
|
241
|
-
c =
|
247
|
+
c = read_config("#{TMP_DIR}/config_test_1.conf")
|
242
248
|
expect(c['k1']).to eq('root_config')
|
243
249
|
expect(c['k2']).to eq('relative_path_include')
|
244
250
|
expect(c['k3']).to eq('relative_include_in_included_file')
|
data/test/plugin/test_in_http.rb
CHANGED
@@ -10,13 +10,13 @@ class HttpInputTest < Test::Unit::TestCase
|
|
10
10
|
PORT = unused_port
|
11
11
|
CONFIG = %[
|
12
12
|
port #{PORT}
|
13
|
-
bind 127.0.0.1
|
13
|
+
bind "127.0.0.1"
|
14
14
|
body_size_limit 10m
|
15
15
|
keepalive_timeout 5
|
16
16
|
]
|
17
17
|
|
18
18
|
def create_driver(conf=CONFIG)
|
19
|
-
Fluent::Test::InputTestDriver.new(Fluent::HttpInput).configure(conf)
|
19
|
+
Fluent::Test::InputTestDriver.new(Fluent::HttpInput).configure(conf, true)
|
20
20
|
end
|
21
21
|
|
22
22
|
def test_configure
|
@@ -157,7 +157,7 @@ class HttpInputTest < Test::Unit::TestCase
|
|
157
157
|
|
158
158
|
def test_with_regexp
|
159
159
|
d = create_driver(CONFIG + %[
|
160
|
-
format /^(?<field_1
|
160
|
+
format /^(?<field_1>\\\\d+):(?<field_2>\\\\w+)$/
|
161
161
|
types field_1:integer
|
162
162
|
])
|
163
163
|
|
@@ -105,30 +105,6 @@ module StreamInputTest
|
|
105
105
|
end
|
106
106
|
end
|
107
107
|
|
108
|
-
class TcpInputTest < Test::Unit::TestCase
|
109
|
-
include StreamInputTest
|
110
|
-
|
111
|
-
PORT = unused_port
|
112
|
-
CONFIG = %[
|
113
|
-
port #{PORT}
|
114
|
-
bind 127.0.0.1
|
115
|
-
]
|
116
|
-
|
117
|
-
def create_driver(conf=CONFIG)
|
118
|
-
super(Fluent::TcpInput, conf)
|
119
|
-
end
|
120
|
-
|
121
|
-
def test_configure
|
122
|
-
d = create_driver
|
123
|
-
assert_equal PORT, d.instance.port
|
124
|
-
assert_equal '127.0.0.1', d.instance.bind
|
125
|
-
end
|
126
|
-
|
127
|
-
def connect
|
128
|
-
TCPSocket.new('127.0.0.1', PORT)
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
108
|
class UnixInputTest < Test::Unit::TestCase
|
133
109
|
include StreamInputTest
|
134
110
|
|
@@ -111,6 +111,26 @@ class SyslogInputTest < Test::Unit::TestCase
|
|
111
111
|
compare_test_result(d.emits, tests)
|
112
112
|
end
|
113
113
|
|
114
|
+
def test_msg_size_with_json_format
|
115
|
+
d = create_driver([CONFIG, 'format json'].join("\n"))
|
116
|
+
time = Time.parse('2013-09-18 12:00:00 +0900').to_i
|
117
|
+
tests = ['Hello!', 'Syslog!'].map { |msg|
|
118
|
+
event = {'time' => time, 'message' => msg}
|
119
|
+
{'msg' => '<6>' + event.to_json + "\n", 'expected' => msg}
|
120
|
+
}
|
121
|
+
|
122
|
+
d.run do
|
123
|
+
u = UDPSocket.new
|
124
|
+
u.connect('127.0.0.1', PORT)
|
125
|
+
tests.each {|test|
|
126
|
+
u.send(test['msg'], 0)
|
127
|
+
}
|
128
|
+
sleep 1
|
129
|
+
end
|
130
|
+
|
131
|
+
compare_test_result(d.emits, tests)
|
132
|
+
end
|
133
|
+
|
114
134
|
def create_test_case
|
115
135
|
# actual syslog message has "\n"
|
116
136
|
[
|
@@ -120,7 +140,8 @@ class SyslogInputTest < Test::Unit::TestCase
|
|
120
140
|
end
|
121
141
|
|
122
142
|
def compare_test_result(emits, tests)
|
123
|
-
emits.each_index {|i|
|
143
|
+
emits.each_index { |i|
|
144
|
+
assert_equal('syslog.kern.info', emits[0][0]) # <6> means kern.info
|
124
145
|
assert_equal(tests[i]['expected'], emits[i][2]['message'])
|
125
146
|
}
|
126
147
|
end
|
data/test/plugin/test_in_tail.rb
CHANGED
@@ -95,7 +95,7 @@ class TailInputTest < Test::Unit::TestCase
|
|
95
95
|
|
96
96
|
def test_rotate_file
|
97
97
|
emits = sub_test_rotate_file(SINGLE_LINE_CONFIG)
|
98
|
-
|
98
|
+
assert_equal(4, emits.length)
|
99
99
|
assert_equal({"message" => "test3"}, emits[0][2])
|
100
100
|
assert_equal({"message" => "test4"}, emits[1][2])
|
101
101
|
assert_equal({"message" => "test5"}, emits[2][2])
|
@@ -104,7 +104,7 @@ class TailInputTest < Test::Unit::TestCase
|
|
104
104
|
|
105
105
|
def test_rotate_file_with_read_from_head
|
106
106
|
emits = sub_test_rotate_file(CONFIG_READ_FROM_HEAD + SINGLE_LINE_CONFIG)
|
107
|
-
|
107
|
+
assert_equal(6, emits.length)
|
108
108
|
assert_equal({"message" => "test1"}, emits[0][2])
|
109
109
|
assert_equal({"message" => "test2"}, emits[1][2])
|
110
110
|
assert_equal({"message" => "test3"}, emits[2][2])
|
@@ -113,32 +113,71 @@ class TailInputTest < Test::Unit::TestCase
|
|
113
113
|
assert_equal({"message" => "test6"}, emits[5][2])
|
114
114
|
end
|
115
115
|
|
116
|
-
def
|
117
|
-
|
118
|
-
|
119
|
-
|
116
|
+
def test_rotate_file_with_write_old
|
117
|
+
emits = sub_test_rotate_file(SINGLE_LINE_CONFIG) { |rotated_file|
|
118
|
+
File.open("#{TMP_DIR}/tail.txt", "w") { |f| }
|
119
|
+
rotated_file.puts "test7"
|
120
|
+
rotated_file.puts "test8"
|
121
|
+
rotated_file.flush
|
122
|
+
|
123
|
+
sleep 1
|
124
|
+
File.open("#{TMP_DIR}/tail.txt", "a") { |f|
|
125
|
+
f.puts "test5"
|
126
|
+
f.puts "test6"
|
127
|
+
}
|
120
128
|
}
|
129
|
+
assert_equal(6, emits.length)
|
130
|
+
assert_equal({"message" => "test3"}, emits[0][2])
|
131
|
+
assert_equal({"message" => "test4"}, emits[1][2])
|
132
|
+
assert_equal({"message" => "test7"}, emits[2][2])
|
133
|
+
assert_equal({"message" => "test8"}, emits[3][2])
|
134
|
+
assert_equal({"message" => "test5"}, emits[4][2])
|
135
|
+
assert_equal({"message" => "test6"}, emits[5][2])
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_rotate_file_with_write_old_and_no_new_file
|
139
|
+
emits = sub_test_rotate_file(SINGLE_LINE_CONFIG) { |rotated_file|
|
140
|
+
rotated_file.puts "test7"
|
141
|
+
rotated_file.puts "test8"
|
142
|
+
rotated_file.flush
|
143
|
+
}
|
144
|
+
assert_equal(4, emits.length)
|
145
|
+
assert_equal({"message" => "test3"}, emits[0][2])
|
146
|
+
assert_equal({"message" => "test4"}, emits[1][2])
|
147
|
+
assert_equal({"message" => "test7"}, emits[2][2])
|
148
|
+
assert_equal({"message" => "test8"}, emits[3][2])
|
149
|
+
end
|
150
|
+
|
151
|
+
def sub_test_rotate_file(config = nil)
|
152
|
+
file = File.open("#{TMP_DIR}/tail.txt", "w")
|
153
|
+
file.puts "test1"
|
154
|
+
file.puts "test2"
|
155
|
+
file.flush
|
156
|
+
|
121
157
|
d = create_driver(config)
|
122
158
|
d.run do
|
123
159
|
sleep 1
|
124
160
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
}
|
161
|
+
file.puts "test3"
|
162
|
+
file.puts "test4"
|
163
|
+
file.flush
|
129
164
|
sleep 1
|
130
165
|
|
131
166
|
FileUtils.mv("#{TMP_DIR}/tail.txt", "#{TMP_DIR}/tail2.txt")
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
167
|
+
if block_given?
|
168
|
+
yield file
|
169
|
+
sleep 1
|
170
|
+
else
|
171
|
+
sleep 1
|
172
|
+
File.open("#{TMP_DIR}/tail.txt", "w") { |f| }
|
173
|
+
sleep 1
|
136
174
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
175
|
+
File.open("#{TMP_DIR}/tail.txt", "a") { |f|
|
176
|
+
f.puts "test5"
|
177
|
+
f.puts "test6"
|
178
|
+
}
|
179
|
+
sleep 1
|
180
|
+
end
|
142
181
|
end
|
143
182
|
|
144
183
|
d.run do
|
@@ -146,6 +185,8 @@ class TailInputTest < Test::Unit::TestCase
|
|
146
185
|
end
|
147
186
|
|
148
187
|
d.emits
|
188
|
+
ensure
|
189
|
+
file.close
|
149
190
|
end
|
150
191
|
|
151
192
|
def test_lf
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'fluent/test'
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
class TcpInputTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
Fluent::Test.setup
|
7
|
+
end
|
8
|
+
|
9
|
+
PORT = unused_port
|
10
|
+
BASE_CONFIG = %[
|
11
|
+
port #{PORT}
|
12
|
+
tag tcp
|
13
|
+
]
|
14
|
+
CONFIG = BASE_CONFIG + %[
|
15
|
+
bind 127.0.0.1
|
16
|
+
format none
|
17
|
+
]
|
18
|
+
IPv6_CONFIG = BASE_CONFIG + %[
|
19
|
+
bind ::1
|
20
|
+
format none
|
21
|
+
]
|
22
|
+
|
23
|
+
def create_driver(conf)
|
24
|
+
Fluent::Test::InputTestDriver.new(Fluent::TcpInput).configure(conf)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_configure
|
28
|
+
configs = {'127.0.0.1' => CONFIG}
|
29
|
+
configs.merge!('::1' => IPv6_CONFIG) if ipv6_enabled?
|
30
|
+
|
31
|
+
configs.each_pair { |k, v|
|
32
|
+
d = create_driver(v)
|
33
|
+
assert_equal PORT, d.instance.port
|
34
|
+
assert_equal k, d.instance.bind
|
35
|
+
assert_equal "\n", d.instance.delimiter
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
{
|
40
|
+
'none' => [
|
41
|
+
{'msg' => "tcptest1\n", 'expected' => 'tcptest1'},
|
42
|
+
{'msg' => "tcptest2\n", 'expected' => 'tcptest2'},
|
43
|
+
],
|
44
|
+
'json' => [
|
45
|
+
{'msg' => {'k' => 123, 'message' => 'tcptest1'}.to_json + "\n", 'expected' => 'tcptest1'},
|
46
|
+
{'msg' => {'k' => 'tcptest2', 'message' => 456}.to_json + "\n", 'expected' => 456},
|
47
|
+
]
|
48
|
+
}.each { |format, test_cases|
|
49
|
+
define_method("test_msg_size_#{format}") do
|
50
|
+
d = create_driver(BASE_CONFIG + "format #{format}")
|
51
|
+
tests = test_cases
|
52
|
+
|
53
|
+
d.run do
|
54
|
+
tests.each {|test|
|
55
|
+
TCPSocket.open('127.0.0.1', PORT) do |s|
|
56
|
+
s.send(test['msg'], 0)
|
57
|
+
end
|
58
|
+
}
|
59
|
+
sleep 1
|
60
|
+
end
|
61
|
+
|
62
|
+
compare_test_result(d.emits, tests)
|
63
|
+
end
|
64
|
+
|
65
|
+
define_method("test_msg_size_with_same_connection_#{format}") do
|
66
|
+
d = create_driver(BASE_CONFIG + "format #{format}")
|
67
|
+
tests = test_cases
|
68
|
+
|
69
|
+
d.run do
|
70
|
+
TCPSocket.open('127.0.0.1', PORT) do |s|
|
71
|
+
tests.each {|test|
|
72
|
+
s.send(test['msg'], 0)
|
73
|
+
}
|
74
|
+
end
|
75
|
+
sleep 1
|
76
|
+
end
|
77
|
+
|
78
|
+
compare_test_result(d.emits, tests)
|
79
|
+
end
|
80
|
+
}
|
81
|
+
|
82
|
+
def compare_test_result(emits, tests)
|
83
|
+
assert_equal(2, emits.size)
|
84
|
+
emits.each_index {|i|
|
85
|
+
assert_equal(tests[i]['expected'], emits[i][2]['message'])
|
86
|
+
}
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'fluent/test'
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
class UdpInputTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
Fluent::Test.setup
|
7
|
+
end
|
8
|
+
|
9
|
+
PORT = unused_port
|
10
|
+
BASE_CONFIG = %[
|
11
|
+
port #{PORT}
|
12
|
+
tag udp
|
13
|
+
]
|
14
|
+
CONFIG = BASE_CONFIG + %!
|
15
|
+
bind 127.0.0.1
|
16
|
+
format /^\\[(?<time>[^\\]]*)\\] (?<message>.*)/
|
17
|
+
!
|
18
|
+
IPv6_CONFIG = BASE_CONFIG + %!
|
19
|
+
bind ::1
|
20
|
+
format /^\\[(?<time>[^\\]]*)\\] (?<message>.*)/
|
21
|
+
!
|
22
|
+
|
23
|
+
def create_driver(conf)
|
24
|
+
Fluent::Test::InputTestDriver.new(Fluent::UdpInput).configure(conf)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_configure
|
28
|
+
configs = {'127.0.0.1' => CONFIG}
|
29
|
+
configs.merge!('::1' => IPv6_CONFIG) if ipv6_enabled?
|
30
|
+
|
31
|
+
configs.each_pair { |k, v|
|
32
|
+
d = create_driver(v)
|
33
|
+
assert_equal PORT, d.instance.port
|
34
|
+
assert_equal k, d.instance.bind
|
35
|
+
assert_equal 4096, d.instance.body_size_limit
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_time_format
|
40
|
+
configs = {'127.0.0.1' => CONFIG}
|
41
|
+
configs.merge!('::1' => IPv6_CONFIG) if ipv6_enabled?
|
42
|
+
|
43
|
+
configs.each_pair { |k, v|
|
44
|
+
d = create_driver(v)
|
45
|
+
|
46
|
+
tests = [
|
47
|
+
{'msg' => '[Sep 11 00:00:00] localhost logger: foo', 'expected' => Time.strptime('Sep 11 00:00:00', '%b %d %H:%M:%S').to_i},
|
48
|
+
{'msg' => '[Sep 1 00:00:00] localhost logger: foo', 'expected' => Time.strptime('Sep 1 00:00:00', '%b %d %H:%M:%S').to_i},
|
49
|
+
]
|
50
|
+
|
51
|
+
d.run do
|
52
|
+
u = Fluent::SocketUtil.create_udp_socket(k)
|
53
|
+
u.connect(k, PORT)
|
54
|
+
tests.each {|test|
|
55
|
+
u.send(test['msg'], 0)
|
56
|
+
}
|
57
|
+
sleep 1
|
58
|
+
end
|
59
|
+
|
60
|
+
emits = d.emits
|
61
|
+
emits.each_index {|i|
|
62
|
+
assert_equal(tests[i]['expected'], emits[i][1])
|
63
|
+
}
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
{
|
68
|
+
'none' => [
|
69
|
+
{'msg' => "tcptest1\n", 'expected' => 'tcptest1'},
|
70
|
+
{'msg' => "tcptest2\n", 'expected' => 'tcptest2'},
|
71
|
+
],
|
72
|
+
'json' => [
|
73
|
+
{'msg' => {'k' => 123, 'message' => 'tcptest1'}.to_json + "\n", 'expected' => 'tcptest1'},
|
74
|
+
{'msg' => {'k' => 'tcptest2', 'message' => 456}.to_json + "\n", 'expected' => 456},
|
75
|
+
],
|
76
|
+
'/^\\[(?<time>[^\\]]*)\\] (?<message>.*)/' => [
|
77
|
+
{'msg' => '[Sep 10 00:00:00] localhost: ' + 'x' * 100 + "\n", 'expected' => 'localhost: ' + 'x' * 100},
|
78
|
+
{'msg' => '[Sep 10 00:00:00] localhost: ' + 'x' * 1024 + "\n", 'expected' => 'localhost: ' + 'x' * 1024},
|
79
|
+
]
|
80
|
+
}.each { |format, test_cases|
|
81
|
+
define_method("test_msg_size_#{format[0] == '/' ? 'regexp' : format}") do
|
82
|
+
d = create_driver(BASE_CONFIG + "format #{format}")
|
83
|
+
tests = test_cases
|
84
|
+
|
85
|
+
d.run do
|
86
|
+
u = UDPSocket.new
|
87
|
+
u.connect('127.0.0.1', PORT)
|
88
|
+
tests.each { |test|
|
89
|
+
u.send(test['msg'], 0)
|
90
|
+
}
|
91
|
+
sleep 1
|
92
|
+
end
|
93
|
+
|
94
|
+
compare_test_result(d.emits, tests)
|
95
|
+
end
|
96
|
+
}
|
97
|
+
|
98
|
+
def compare_test_result(emits, tests)
|
99
|
+
assert_equal(2, emits.size)
|
100
|
+
emits.each_index {|i|
|
101
|
+
assert_equal(tests[i]['expected'], emits[i][2]['message'])
|
102
|
+
}
|
103
|
+
end
|
104
|
+
end
|
@@ -16,15 +16,15 @@ class ExecOutputTest < Test::Unit::TestCase
|
|
16
16
|
localtime
|
17
17
|
]
|
18
18
|
TSV_CONFIG = %[
|
19
|
-
keys time,tag,k1
|
20
|
-
tag_key tag
|
21
|
-
time_key time
|
19
|
+
keys "time,tag,k1"
|
20
|
+
tag_key "tag"
|
21
|
+
time_key "time"
|
22
22
|
time_format %Y-%m-%d %H:%M:%S
|
23
23
|
]
|
24
24
|
|
25
25
|
def create_driver(conf = TSV_CONFIG)
|
26
26
|
config = CONFIG + conf
|
27
|
-
Fluent::Test::TimeSlicedOutputTestDriver.new(Fluent::ExecOutput).configure(config)
|
27
|
+
Fluent::Test::TimeSlicedOutputTestDriver.new(Fluent::ExecOutput).configure(config, true)
|
28
28
|
end
|
29
29
|
|
30
30
|
def create_test_case
|