fluentd 0.14.5-x86-mingw32 → 0.14.7-x86-mingw32
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 +55 -0
- data/bin/fluent-binlog-reader +7 -0
- data/example/in_dummy_with_compression.conf +23 -0
- data/lib/fluent/agent.rb +8 -12
- data/lib/fluent/command/binlog_reader.rb +234 -0
- data/lib/fluent/command/fluentd.rb +17 -1
- data/lib/fluent/compat/file_util.rb +1 -1
- data/lib/fluent/compat/output.rb +5 -1
- data/lib/fluent/config/configure_proxy.rb +18 -3
- data/lib/fluent/config/element.rb +1 -1
- data/lib/fluent/config/section.rb +1 -1
- data/lib/fluent/config/v1_parser.rb +1 -1
- data/lib/fluent/env.rb +1 -0
- data/lib/fluent/event.rb +49 -2
- data/lib/fluent/event_router.rb +6 -2
- data/lib/fluent/label.rb +8 -0
- data/lib/fluent/log.rb +30 -1
- data/lib/fluent/plugin.rb +1 -1
- data/lib/fluent/plugin/base.rb +3 -0
- data/lib/fluent/plugin/buf_file.rb +2 -2
- data/lib/fluent/plugin/buf_memory.rb +1 -1
- data/lib/fluent/plugin/buffer.rb +12 -2
- data/lib/fluent/plugin/buffer/chunk.rb +68 -7
- data/lib/fluent/plugin/buffer/file_chunk.rb +4 -4
- data/lib/fluent/plugin/buffer/memory_chunk.rb +4 -4
- data/lib/fluent/plugin/compressable.rb +91 -0
- data/lib/fluent/plugin/filter_grep.rb +4 -4
- data/lib/fluent/plugin/formatter.rb +2 -2
- data/lib/fluent/plugin/formatter_json.rb +2 -1
- data/lib/fluent/plugin/formatter_out_file.rb +3 -30
- data/lib/fluent/plugin/in_forward.rb +6 -5
- data/lib/fluent/plugin/in_monitor_agent.rb +7 -21
- data/lib/fluent/plugin/in_syslog.rb +1 -1
- data/lib/fluent/plugin/in_tail.rb +11 -2
- data/lib/fluent/plugin/multi_output.rb +63 -3
- data/lib/fluent/plugin/out_exec.rb +1 -1
- data/lib/fluent/plugin/out_file.rb +5 -1
- data/lib/fluent/plugin/out_forward.rb +17 -5
- data/lib/fluent/plugin/out_stdout.rb +2 -1
- data/lib/fluent/plugin/output.rb +205 -19
- data/lib/fluent/plugin/parser.rb +5 -49
- data/lib/fluent/plugin/parser_apache2.rb +1 -1
- data/lib/fluent/plugin/parser_json.rb +4 -4
- data/lib/fluent/plugin/parser_multiline.rb +5 -5
- data/lib/fluent/plugin/parser_regexp.rb +1 -2
- data/lib/fluent/plugin/parser_syslog.rb +2 -2
- data/lib/fluent/plugin/storage_local.rb +2 -1
- data/lib/fluent/plugin_helper.rb +1 -0
- data/lib/fluent/plugin_helper/compat_parameters.rb +39 -21
- data/lib/fluent/plugin_helper/extract.rb +92 -0
- data/lib/fluent/plugin_helper/inject.rb +10 -12
- data/lib/fluent/plugin_helper/thread.rb +23 -3
- data/lib/fluent/registry.rb +1 -1
- data/lib/fluent/root_agent.rb +2 -1
- data/lib/fluent/supervisor.rb +28 -8
- data/lib/fluent/test/base.rb +0 -7
- data/lib/fluent/test/driver/base.rb +1 -0
- data/lib/fluent/test/driver/output.rb +3 -0
- data/lib/fluent/test/helpers.rb +18 -0
- data/lib/fluent/test/input_test.rb +4 -2
- data/lib/fluent/test/log.rb +3 -1
- data/lib/fluent/time.rb +232 -1
- data/lib/fluent/timezone.rb +1 -1
- data/lib/fluent/version.rb +1 -1
- data/test/command/test_binlog_reader.rb +351 -0
- data/test/config/test_config_parser.rb +6 -0
- data/test/config/test_configurable.rb +47 -1
- data/test/helper.rb +0 -1
- data/test/plugin/test_buffer.rb +22 -2
- data/test/plugin/test_buffer_chunk.rb +34 -4
- data/test/plugin/test_buffer_file_chunk.rb +73 -0
- data/test/plugin/test_buffer_memory_chunk.rb +73 -0
- data/test/plugin/test_compressable.rb +81 -0
- data/test/plugin/test_formatter_json.rb +14 -1
- data/test/plugin/test_in_forward.rb +67 -3
- data/test/plugin/test_in_monitor_agent.rb +17 -1
- data/test/plugin/test_in_tail.rb +8 -8
- data/test/plugin/test_out_file.rb +0 -8
- data/test/plugin/test_out_forward.rb +85 -0
- data/test/plugin/test_out_secondary_file.rb +20 -12
- data/test/plugin/test_out_stdout.rb +11 -10
- data/test/plugin/test_output.rb +234 -0
- data/test/plugin/test_output_as_buffered.rb +223 -0
- data/test/plugin/test_output_as_buffered_compress.rb +165 -0
- data/test/plugin/test_parser_json.rb +8 -0
- data/test/plugin/test_parser_regexp.rb +1 -1
- data/test/plugin_helper/test_child_process.rb +2 -2
- data/test/plugin_helper/test_extract.rb +195 -0
- data/test/plugin_helper/test_inject.rb +0 -7
- data/test/scripts/fluent/plugin/formatter1/formatter_test1.rb +7 -0
- data/test/scripts/fluent/plugin/formatter2/formatter_test2.rb +7 -0
- data/test/test_event.rb +186 -0
- data/test/test_event_router.rb +1 -1
- data/test/test_formatter.rb +0 -7
- data/test/test_log.rb +121 -0
- data/test/test_plugin_classes.rb +62 -0
- data/test/test_root_agent.rb +125 -0
- data/test/test_supervisor.rb +25 -2
- data/test/test_time_formatter.rb +103 -7
- data/test/test_time_parser.rb +211 -0
- metadata +22 -4
- data/test/plugin/test_parser_time.rb +0 -46
@@ -55,6 +55,19 @@ class MonitorAgentInputTest < Test::Unit::TestCase
|
|
55
55
|
@id test_out
|
56
56
|
</match>
|
57
57
|
</label>
|
58
|
+
<label @copy>
|
59
|
+
<match **>
|
60
|
+
@type copy
|
61
|
+
<store>
|
62
|
+
@type test_out
|
63
|
+
@id copy_out_1
|
64
|
+
</store>
|
65
|
+
<store>
|
66
|
+
@type test_out
|
67
|
+
@id copy_out_2
|
68
|
+
</store>
|
69
|
+
</match>
|
70
|
+
</label>
|
58
71
|
<label @ERROR>
|
59
72
|
<match>
|
60
73
|
@type null
|
@@ -153,7 +166,10 @@ EOC
|
|
153
166
|
assert_equal([FluentTest::FluentTestInput,
|
154
167
|
Fluent::Plugin::RelabelOutput,
|
155
168
|
FluentTest::FluentTestFilter,
|
156
|
-
FluentTest::FluentTestOutput,
|
169
|
+
FluentTest::FluentTestOutput, # in label @test
|
170
|
+
Fluent::Plugin::CopyOutput,
|
171
|
+
FluentTest::FluentTestOutput, # in label @copy 1
|
172
|
+
FluentTest::FluentTestOutput, # in label @copy 2
|
157
173
|
Fluent::Plugin::NullOutput], plugins)
|
158
174
|
end
|
159
175
|
|
data/test/plugin/test_in_tail.rb
CHANGED
@@ -5,6 +5,7 @@ require 'fluent/plugin/buffer'
|
|
5
5
|
require 'fluent/system_config'
|
6
6
|
require 'net/http'
|
7
7
|
require 'flexmock/test_unit'
|
8
|
+
require 'timecop'
|
8
9
|
|
9
10
|
class TailInputTest < Test::Unit::TestCase
|
10
11
|
include FlexMock::TestCase
|
@@ -401,7 +402,7 @@ class TailInputTest < Test::Unit::TestCase
|
|
401
402
|
|
402
403
|
d = create_driver
|
403
404
|
|
404
|
-
d.run do
|
405
|
+
d.run(expect_emits: 1) do
|
405
406
|
File.open("#{TMP_DIR}/tail.txt", "ab") {|f|
|
406
407
|
f.print "test3"
|
407
408
|
}
|
@@ -410,7 +411,6 @@ class TailInputTest < Test::Unit::TestCase
|
|
410
411
|
File.open("#{TMP_DIR}/tail.txt", "ab") {|f|
|
411
412
|
f.puts "test4"
|
412
413
|
}
|
413
|
-
sleep 1
|
414
414
|
end
|
415
415
|
|
416
416
|
events = d.events
|
@@ -766,9 +766,7 @@ class TailInputTest < Test::Unit::TestCase
|
|
766
766
|
@loop = Coolio::Loop.new
|
767
767
|
end
|
768
768
|
|
769
|
-
|
770
|
-
timeclass.should_receive(:now).with_no_args.and_return(Time.new(2010, 1, 2, 3, 4, 5), Time.new(2010, 1, 2, 3, 4, 6), Time.new(2010, 1, 2, 3, 4, 7))
|
771
|
-
|
769
|
+
Timecop.freeze(2010, 1, 2, 3, 4, 5) do
|
772
770
|
flexstub(Fluent::Plugin::TailInput::TailWatcher) do |watcherclass|
|
773
771
|
EX_PATHS.each do |path|
|
774
772
|
watcherclass.should_receive(:new).with(path, EX_RORATE_WAIT, Fluent::Plugin::TailInput::FilePositionEntry, any, true, true, 1000, any, any, any).once.and_return do
|
@@ -781,11 +779,13 @@ class TailInputTest < Test::Unit::TestCase
|
|
781
779
|
end
|
782
780
|
plugin.refresh_watchers
|
783
781
|
end
|
782
|
+
end
|
784
783
|
|
785
|
-
|
786
|
-
|
787
|
-
|
784
|
+
plugin.instance_eval do
|
785
|
+
@tails['test/plugin/data/2010/01/20100102-030405.log'].should_receive(:close).zero_or_more_times
|
786
|
+
end
|
788
787
|
|
788
|
+
Timecop.freeze(2010, 1, 2, 3, 4, 6) do
|
789
789
|
flexstub(Fluent::Plugin::TailInput::TailWatcher) do |watcherclass|
|
790
790
|
watcherclass.should_receive(:new).with('test/plugin/data/2010/01/20100102-030406.log', EX_RORATE_WAIT, Fluent::Plugin::TailInput::FilePositionEntry, any, true, true, 1000, any, any, any).once.and_return do
|
791
791
|
flexmock('TailWatcher') do |watcher|
|
@@ -24,14 +24,6 @@ class FileOutputTest < Test::Unit::TestCase
|
|
24
24
|
Fluent::Test::TimeSlicedOutputTestDriver.new(Fluent::FileOutput).configure(conf)
|
25
25
|
end
|
26
26
|
|
27
|
-
def with_timezone(timezone = 'UTC', &block)
|
28
|
-
old = ENV['TZ']
|
29
|
-
ENV['TZ'] = timezone
|
30
|
-
output = yield
|
31
|
-
ENV['TZ'] = old
|
32
|
-
output
|
33
|
-
end
|
34
|
-
|
35
27
|
def test_configure
|
36
28
|
d = create_driver %[
|
37
29
|
path test_path
|
@@ -2,6 +2,7 @@ require_relative '../helper'
|
|
2
2
|
require 'fluent/test'
|
3
3
|
require 'fluent/test/startup_shutdown'
|
4
4
|
require 'fluent/plugin/out_forward'
|
5
|
+
require 'flexmock/test_unit'
|
5
6
|
|
6
7
|
class ForwardOutputTest < Test::Unit::TestCase
|
7
8
|
extend Fluent::Test::StartupShutdown
|
@@ -107,6 +108,40 @@ class ForwardOutputTest < Test::Unit::TestCase
|
|
107
108
|
end
|
108
109
|
end
|
109
110
|
|
111
|
+
def test_compress_default_value
|
112
|
+
d = create_driver
|
113
|
+
assert_equal :text, d.instance.compress
|
114
|
+
|
115
|
+
node = d.instance.nodes.first
|
116
|
+
assert_equal :text, node.instance_variable_get(:@compress)
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_set_compress_is_gzip
|
120
|
+
d = create_driver(CONFIG + %[compress gzip])
|
121
|
+
assert_equal :gzip, d.instance.compress
|
122
|
+
assert_equal :gzip, d.instance.buffer.compress
|
123
|
+
|
124
|
+
node = d.instance.nodes.first
|
125
|
+
assert_equal :gzip, node.instance_variable_get(:@compress)
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_set_compress_is_gzip_in_buffer_section
|
129
|
+
mock = flexmock($log)
|
130
|
+
mock.should_receive(:log).with("buffer is compressed. If you also want to save the bandwidth of a network, Add `compress` configuration in <match>")
|
131
|
+
|
132
|
+
d = create_driver(CONFIG + %[
|
133
|
+
<buffer>
|
134
|
+
type memory
|
135
|
+
compress gzip
|
136
|
+
</buffer>
|
137
|
+
])
|
138
|
+
assert_equal :text, d.instance.compress
|
139
|
+
assert_equal :gzip, d.instance.buffer.compress
|
140
|
+
|
141
|
+
node = d.instance.nodes.first
|
142
|
+
assert_equal :text, node.instance_variable_get(:@compress)
|
143
|
+
end
|
144
|
+
|
110
145
|
def test_phi_failure_detector
|
111
146
|
d = create_driver(CONFIG + %[phi_failure_detector false \n phi_threshold 0])
|
112
147
|
node = d.instance.nodes.first
|
@@ -202,6 +237,40 @@ class ForwardOutputTest < Test::Unit::TestCase
|
|
202
237
|
assert_empty d.instance.exceptions
|
203
238
|
end
|
204
239
|
|
240
|
+
def test_send_comprssed_message_pack_stream_if_compress_is_gzip
|
241
|
+
target_input_driver = create_target_input_driver
|
242
|
+
|
243
|
+
d = create_driver(CONFIG + %[
|
244
|
+
flush_interval 1s
|
245
|
+
compress gzip
|
246
|
+
])
|
247
|
+
|
248
|
+
time = event_time('2011-01-02 13:14:15 UTC')
|
249
|
+
|
250
|
+
records = [
|
251
|
+
{"a" => 1},
|
252
|
+
{"a" => 2}
|
253
|
+
]
|
254
|
+
d.register_run_post_condition do
|
255
|
+
d.instance.responses.length == 1
|
256
|
+
end
|
257
|
+
|
258
|
+
target_input_driver.run do
|
259
|
+
d.run do
|
260
|
+
records.each do |record|
|
261
|
+
d.emit record, time
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
event_streams = target_input_driver.event_streams
|
267
|
+
assert_true event_streams[0].is_a?(Fluent::CompressedMessagePackEventStream)
|
268
|
+
|
269
|
+
emits = target_input_driver.emits
|
270
|
+
assert_equal ['test', time, records[0]], emits[0]
|
271
|
+
assert_equal ['test', time, records[1]], emits[1]
|
272
|
+
end
|
273
|
+
|
205
274
|
def test_send_to_a_node_supporting_responses
|
206
275
|
target_input_driver = create_target_input_driver(response_stub: true)
|
207
276
|
|
@@ -529,4 +598,20 @@ class ForwardOutputTest < Test::Unit::TestCase
|
|
529
598
|
node.tick
|
530
599
|
assert_equal node.available, true
|
531
600
|
end
|
601
|
+
|
602
|
+
def test_heartbeat_type_udp
|
603
|
+
d = create_driver(CONFIG + "\nheartbeat_type udp")
|
604
|
+
|
605
|
+
d.instance.start
|
606
|
+
usock = d.instance.instance_variable_get(:@usock)
|
607
|
+
timer = d.instance.instance_variable_get(:@timer)
|
608
|
+
hb = d.instance.instance_variable_get(:@hb)
|
609
|
+
assert_equal UDPSocket, usock.class
|
610
|
+
assert_equal Fluent::ForwardOutput::HeartbeatRequestTimer, timer.class
|
611
|
+
assert_equal Fluent::ForwardOutput::HeartbeatHandler, hb.class
|
612
|
+
|
613
|
+
mock(usock).send("\0", 0, Socket.pack_sockaddr_in(TARGET_PORT, '127.0.0.1')).once
|
614
|
+
timer.disable # call send_heartbeat at just once
|
615
|
+
timer.on_timer
|
616
|
+
end
|
532
617
|
end
|
@@ -110,16 +110,19 @@ class FileOutputSecondaryTest < Test::Unit::TestCase
|
|
110
110
|
# Zlib::GzipReader has a bug of concatenated file: https://bugs.ruby-lang.org/issues/9790
|
111
111
|
# Following code from https://www.ruby-forum.com/topic/971591#979520
|
112
112
|
result = ""
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
113
|
+
waiting(10) do
|
114
|
+
# we can expect that GzipReader#read can wait unflushed raw data of `io` on disk
|
115
|
+
File.open(path, "rb") { |io|
|
116
|
+
loop do
|
117
|
+
gzr = Zlib::GzipReader.new(io)
|
118
|
+
result << gzr.read
|
119
|
+
unused = gzr.unused
|
120
|
+
gzr.finish
|
121
|
+
break if unused.nil?
|
122
|
+
io.pos -= unused.length
|
123
|
+
end
|
124
|
+
}
|
125
|
+
end
|
123
126
|
|
124
127
|
assert_equal expect, result
|
125
128
|
end
|
@@ -155,10 +158,15 @@ class FileOutputSecondaryTest < Test::Unit::TestCase
|
|
155
158
|
basename out_file_test
|
156
159
|
], @primary)
|
157
160
|
|
158
|
-
|
161
|
+
msgpack_binary = @es.to_msgpack_stream.force_encoding('ASCII-8BIT')
|
159
162
|
|
163
|
+
path = d.instance.write(@chunk)
|
160
164
|
assert_equal "#{TMP_DIR}/out_file_test.0", path
|
161
|
-
|
165
|
+
waiting(5) do
|
166
|
+
sleep 0.1 until File.stat(path).size == msgpack_binary.size
|
167
|
+
end
|
168
|
+
|
169
|
+
assert_equal File.read(path), msgpack_binary
|
162
170
|
end
|
163
171
|
|
164
172
|
test 'path should be incremental when append option is false' do
|
@@ -9,6 +9,7 @@ class StdoutOutputTest < Test::Unit::TestCase
|
|
9
9
|
|
10
10
|
CONFIG = %[
|
11
11
|
]
|
12
|
+
TIME_FORMAT = '%Y-%m-%d %H:%M:%S.%9N %z'
|
12
13
|
|
13
14
|
def create_driver(conf = CONFIG)
|
14
15
|
Fluent::Test::Driver::Output.new(Fluent::Plugin::StdoutOutput).configure(conf)
|
@@ -40,7 +41,7 @@ class StdoutOutputTest < Test::Unit::TestCase
|
|
40
41
|
d.feed(time, {'test' => 'test1'})
|
41
42
|
end
|
42
43
|
end
|
43
|
-
assert_equal "#{Time.at(time).localtime} test: {\"test\":\"test1\"}\n", out
|
44
|
+
assert_equal "#{Time.at(time).localtime.strftime(TIME_FORMAT)} test: {\"test\":\"test1\"}\n", out
|
44
45
|
end
|
45
46
|
|
46
47
|
data('oj' => 'oj', 'yajl' => 'yajl')
|
@@ -52,14 +53,14 @@ class StdoutOutputTest < Test::Unit::TestCase
|
|
52
53
|
d.feed(time, {'test' => 'test1'})
|
53
54
|
end
|
54
55
|
end
|
55
|
-
assert_equal "#{Time.at(time).localtime} test: {\"test\":\"test1\"}\n", out
|
56
|
+
assert_equal "#{Time.at(time).localtime.strftime(TIME_FORMAT)} test: {\"test\":\"test1\"}\n", out
|
56
57
|
|
57
58
|
if data == 'yajl'
|
58
59
|
# NOTE: Float::NAN is not jsonable
|
59
60
|
assert_raise(Yajl::EncodeError) { d.feed('test', time, {'test' => Float::NAN}) }
|
60
61
|
else
|
61
62
|
out = capture_log { d.feed('test', time, {'test' => Float::NAN}) }
|
62
|
-
assert_equal "#{Time.at(time).localtime} test: {\"test\":NaN}\n", out
|
63
|
+
assert_equal "#{Time.at(time).localtime.strftime(TIME_FORMAT)} test: {\"test\":NaN}\n", out
|
63
64
|
end
|
64
65
|
end
|
65
66
|
|
@@ -71,11 +72,11 @@ class StdoutOutputTest < Test::Unit::TestCase
|
|
71
72
|
d.feed(time, {'test' => 'test2'})
|
72
73
|
end
|
73
74
|
end
|
74
|
-
assert_equal "#{Time.at(time).localtime} test: {\"test\"=>\"test2\"}\n", out
|
75
|
+
assert_equal "#{Time.at(time).localtime.strftime(TIME_FORMAT)} test: {\"test\"=>\"test2\"}\n", out
|
75
76
|
|
76
77
|
# NOTE: Float::NAN is not jsonable, but hash string can output it.
|
77
78
|
out = capture_log { d.feed('test', time, {'test' => Float::NAN}) }
|
78
|
-
assert_equal "#{Time.at(time).localtime} test: {\"test\"=>NaN}\n", out
|
79
|
+
assert_equal "#{Time.at(time).localtime.strftime(TIME_FORMAT)} test: {\"test\"=>NaN}\n", out
|
79
80
|
end
|
80
81
|
end
|
81
82
|
|
@@ -113,7 +114,7 @@ class StdoutOutputTest < Test::Unit::TestCase
|
|
113
114
|
d.feed(time, {'test' => 'test'})
|
114
115
|
end
|
115
116
|
end
|
116
|
-
assert_equal "#{Time.at(time).localtime} test: {\"test\":\"test\"}\n", out
|
117
|
+
assert_equal "#{Time.at(time).localtime.strftime(TIME_FORMAT)} test: {\"test\":\"test\"}\n", out
|
117
118
|
end
|
118
119
|
end
|
119
120
|
|
@@ -128,7 +129,7 @@ class StdoutOutputTest < Test::Unit::TestCase
|
|
128
129
|
d.feed(time, {'test' => 'test'})
|
129
130
|
end
|
130
131
|
end
|
131
|
-
assert_equal "#{Time.at(time).localtime} test: {\"test\":\"test\"}\n", out
|
132
|
+
assert_equal "#{Time.at(time).localtime.strftime(TIME_FORMAT)} test: {\"test\":\"test\"}\n", out
|
132
133
|
end
|
133
134
|
|
134
135
|
data('oj' => 'oj', 'yajl' => 'yajl')
|
@@ -143,7 +144,7 @@ class StdoutOutputTest < Test::Unit::TestCase
|
|
143
144
|
end
|
144
145
|
end
|
145
146
|
|
146
|
-
assert_equal "#{Time.at(time).localtime} test: {\"test\":\"test\"}\n", out
|
147
|
+
assert_equal "#{Time.at(time).localtime.strftime(TIME_FORMAT)} test: {\"test\":\"test\"}\n", out
|
147
148
|
end
|
148
149
|
end
|
149
150
|
|
@@ -158,7 +159,7 @@ class StdoutOutputTest < Test::Unit::TestCase
|
|
158
159
|
end
|
159
160
|
end
|
160
161
|
|
161
|
-
assert_equal "#{Time.at(time).localtime} test: {\"test\"=>\"test\"}\n", out
|
162
|
+
assert_equal "#{Time.at(time).localtime.strftime(TIME_FORMAT)} test: {\"test\"=>\"test\"}\n", out
|
162
163
|
end
|
163
164
|
|
164
165
|
test '#try_write(asynchronous)' do
|
@@ -172,7 +173,7 @@ class StdoutOutputTest < Test::Unit::TestCase
|
|
172
173
|
end
|
173
174
|
end
|
174
175
|
|
175
|
-
assert_equal "#{Time.at(time).localtime} test: {\"test\"=>\"test\"}\n", out
|
176
|
+
assert_equal "#{Time.at(time).localtime.strftime(TIME_FORMAT)} test: {\"test\"=>\"test\"}\n", out
|
176
177
|
end
|
177
178
|
end
|
178
179
|
end
|
data/test/plugin/test_output.rb
CHANGED
@@ -287,6 +287,208 @@ class OutputTest < Test::Unit::TestCase
|
|
287
287
|
assert_equal "/mypath/2016/04/11/20-30/fluentd.test.output/////tail", @i.extract_placeholders(tmpl, m)
|
288
288
|
end
|
289
289
|
|
290
|
+
sub_test_case '#placeholder_validators' do
|
291
|
+
test 'returns validators for time, tag and keys when a template has placeholders even if plugin is not configured with these keys' do
|
292
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
|
293
|
+
validators = @i.placeholder_validators(:path, "/my/path/${tag}/${username}/file.%Y%m%d_%H%M.log")
|
294
|
+
assert_equal 3, validators.size
|
295
|
+
assert_equal 1, validators.select(&:time?).size
|
296
|
+
assert_equal 1, validators.select(&:tag?).size
|
297
|
+
assert_equal 1, validators.select(&:keys?).size
|
298
|
+
end
|
299
|
+
|
300
|
+
test 'returns validators for time, tag and keys when a plugin is configured with these keys even if a template does not have placeholders' do
|
301
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time,tag,username', {'timekey' => 60})]))
|
302
|
+
validators = @i.placeholder_validators(:path, "/my/path/file.log")
|
303
|
+
assert_equal 3, validators.size
|
304
|
+
assert_equal 1, validators.select(&:time?).size
|
305
|
+
assert_equal 1, validators.select(&:tag?).size
|
306
|
+
assert_equal 1, validators.select(&:keys?).size
|
307
|
+
end
|
308
|
+
|
309
|
+
test 'returns a validator for time if a template has timestamp placeholders' do
|
310
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
|
311
|
+
validators = @i.placeholder_validators(:path, "/my/path/file.%Y-%m-%d.log")
|
312
|
+
assert_equal 1, validators.size
|
313
|
+
assert_equal 1, validators.select(&:time?).size
|
314
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path' has timestamp placeholders, but chunk key 'time' is not configured") do
|
315
|
+
validators.first.validate!
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
test 'returns a validator for time if a plugin is configured with time key' do
|
320
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time', {'timekey' => '30'})]))
|
321
|
+
validators = @i.placeholder_validators(:path, "/my/path/to/file.log")
|
322
|
+
assert_equal 1, validators.size
|
323
|
+
assert_equal 1, validators.select(&:time?).size
|
324
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path' doesn't have timestamp placeholders for timekey 30") do
|
325
|
+
validators.first.validate!
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
test 'returns a validator for tag if a template has tag placeholders' do
|
330
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
|
331
|
+
validators = @i.placeholder_validators(:path, "/my/path/${tag}/file.log")
|
332
|
+
assert_equal 1, validators.size
|
333
|
+
assert_equal 1, validators.select(&:tag?).size
|
334
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path' has tag placeholders, but chunk key 'tag' is not configured") do
|
335
|
+
validators.first.validate!
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
test 'returns a validator for tag if a plugin is configured with tag key' do
|
340
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'tag')]))
|
341
|
+
validators = @i.placeholder_validators(:path, "/my/path/file.log")
|
342
|
+
assert_equal 1, validators.size
|
343
|
+
assert_equal 1, validators.select(&:tag?).size
|
344
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path' doesn't have tag placeholder") do
|
345
|
+
validators.first.validate!
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
test 'returns a validator for variable keys if a template has variable placeholders' do
|
350
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
|
351
|
+
validators = @i.placeholder_validators(:path, "/my/path/${username}/file.${group}.log")
|
352
|
+
assert_equal 1, validators.size
|
353
|
+
assert_equal 1, validators.select(&:keys?).size
|
354
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path' has placeholders, but chunk keys doesn't have keys group,username") do
|
355
|
+
validators.first.validate!
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
test 'returns a validator for variable keys if a plugin is configured with variable keys' do
|
360
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'username,group')]))
|
361
|
+
validators = @i.placeholder_validators(:path, "/my/path/file.log")
|
362
|
+
assert_equal 1, validators.size
|
363
|
+
assert_equal 1, validators.select(&:keys?).size
|
364
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path' doesn't have enough placeholders for keys group,username") do
|
365
|
+
validators.first.validate!
|
366
|
+
end
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
sub_test_case '#placeholder_validate!' do
|
371
|
+
test 'raises configuration error for a templace when timestamp placeholders exist but time key is missing' do
|
372
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
|
373
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path' has timestamp placeholders, but chunk key 'time' is not configured") do
|
374
|
+
@i.placeholder_validate!(:path, "/path/without/timestamp/file.%Y%m%d-%H%M.log")
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
test 'raises configuration error for a template without timestamp placeholders when timekey is configured' do
|
379
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time', {"timekey" => 180})]))
|
380
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path' doesn't have timestamp placeholders for timekey 180") do
|
381
|
+
@i.placeholder_validate!(:path, "/my/path/file.log")
|
382
|
+
end
|
383
|
+
assert_nothing_raised do
|
384
|
+
@i.placeholder_validate!(:path, "/my/path/%Y%m%d/file.%H%M.log")
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
test 'raises configuration error for a template with timestamp placeholders when plugin is configured more fine timekey' do
|
389
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time', {"timekey" => 180})]))
|
390
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path' doesn't have timestamp placeholder for hour('%H') for timekey 180") do
|
391
|
+
@i.placeholder_validate!(:path, "/my/path/file.%Y%m%d_%H.log")
|
392
|
+
end
|
393
|
+
assert_nothing_raised do
|
394
|
+
@i.placeholder_validate!(:path, "/my/path/file.%Y%m%d_%H%M.log")
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
test 'raises configuration error for a template when tag placeholders exist but tag key is missing' do
|
399
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
|
400
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path' has tag placeholders, but chunk key 'tag' is not configured") do
|
401
|
+
@i.placeholder_validate!(:path, "/my/path/${tag}/file.${tag[2]}.log")
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
test 'raises configuration error for a template without tag placeholders when tagkey is configured' do
|
406
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'tag')]))
|
407
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path' doesn't have tag placeholder") do
|
408
|
+
@i.placeholder_validate!(:path, "/my/path/file.log")
|
409
|
+
end
|
410
|
+
assert_nothing_raised do
|
411
|
+
@i.placeholder_validate!(:path, "/my/path/${tag}/file.${tag[2]}.log")
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
test 'raises configuration error for a template when variable key placeholders exist but chunk keys are missing' do
|
416
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
|
417
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path' has placeholders, but chunk keys doesn't have keys service,username") do
|
418
|
+
@i.placeholder_validate!(:path, "/my/path/${service}/file.${username}.log")
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
test 'raises configuration error for a template without variable key placeholders when chunk keys are configured' do
|
423
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'username,service')]))
|
424
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path' doesn't have enough placeholders for keys service,username") do
|
425
|
+
@i.placeholder_validate!(:path, "/my/path/file.log")
|
426
|
+
end
|
427
|
+
assert_nothing_raised do
|
428
|
+
@i.placeholder_validate!(:path, "/my/path/${service}/file.${username}.log")
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
432
|
+
test 'raise configuration error for a template and configuration with keys mismatch' do
|
433
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'username,service')]))
|
434
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path' doesn't have enough placeholders for keys service") do
|
435
|
+
@i.placeholder_validate!(:path, "/my/path/file.${username}.log")
|
436
|
+
end
|
437
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path' doesn't have enough placeholders for keys username") do
|
438
|
+
@i.placeholder_validate!(:path, "/my/path/${service}/file.log")
|
439
|
+
end
|
440
|
+
assert_nothing_raised do
|
441
|
+
@i.placeholder_validate!(:path, "/my/path/${service}/file.${username}.log")
|
442
|
+
end
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
446
|
+
test '#get_placeholders_time returns seconds,title and example placeholder for a template' do
|
447
|
+
s, t, e = @i.get_placeholders_time("/path/to/dir/yay")
|
448
|
+
assert_nil s
|
449
|
+
assert_nil t
|
450
|
+
assert_nil e
|
451
|
+
|
452
|
+
s, t, e = @i.get_placeholders_time("/path/to/%Y%m%d/yay")
|
453
|
+
assert_equal 86400, s
|
454
|
+
assert_equal :day, t
|
455
|
+
assert_equal '%d', e
|
456
|
+
s, t, e = @i.get_placeholders_time("my birthiday! at %F")
|
457
|
+
assert_equal 86400, s
|
458
|
+
assert_equal :day, t
|
459
|
+
assert_equal '%d', e
|
460
|
+
|
461
|
+
s, t, e = @i.get_placeholders_time("myfile.%Y-%m-%d_%H.log")
|
462
|
+
assert_equal 3600, s
|
463
|
+
assert_equal :hour, t
|
464
|
+
assert_equal '%H', e
|
465
|
+
|
466
|
+
s, t, e = @i.get_placeholders_time("part-%Y%m%d-%H%M.ts")
|
467
|
+
assert_equal 60, s
|
468
|
+
assert_equal :minute, t
|
469
|
+
assert_equal '%M', e
|
470
|
+
|
471
|
+
s, t, e = @i.get_placeholders_time("my first data at %F %T %z")
|
472
|
+
assert_equal 1, s
|
473
|
+
assert_equal :second, t
|
474
|
+
assert_equal '%S', e
|
475
|
+
end
|
476
|
+
|
477
|
+
test '#get_placeholders_tag returns a list of tag part position for a template' do
|
478
|
+
assert_equal [], @i.get_placeholders_tag("db.table")
|
479
|
+
assert_equal [], @i.get_placeholders_tag("db.table_${non_tag}")
|
480
|
+
assert_equal [-1], @i.get_placeholders_tag("table_${tag}")
|
481
|
+
assert_equal [0, 1], @i.get_placeholders_tag("db_${tag[0]}.table_${tag[1]}")
|
482
|
+
assert_equal [-1, 0], @i.get_placeholders_tag("/treedir/${tag[0]}/${tag}")
|
483
|
+
end
|
484
|
+
|
485
|
+
test '#get_placeholders_keys returns a list of keys for a template' do
|
486
|
+
assert_equal [], @i.get_placeholders_keys("/path/to/my/data/file.log")
|
487
|
+
assert_equal [], @i.get_placeholders_keys("/path/to/my/${tag}/file.log")
|
488
|
+
assert_equal ['key1', 'key2'], @i.get_placeholders_keys("/path/to/${key2}/${tag}/file.${key1}.log")
|
489
|
+
assert_equal ['.hidden', '0001', '@timestamp', 'a_key', 'my-domain'], @i.get_placeholders_keys("http://${my-domain}/${.hidden}/${0001}/${a_key}?timestamp=${@timestamp}")
|
490
|
+
end
|
491
|
+
|
290
492
|
test '#metadata returns object which contains tag/timekey/variables from records as specified in configuration' do
|
291
493
|
tag = 'test.output'
|
292
494
|
time = event_time('2016-04-12 15:31:23 -0700')
|
@@ -565,4 +767,36 @@ class OutputTest < Test::Unit::TestCase
|
|
565
767
|
@i.stop; @i.before_shutdown; @i.shutdown; @i.after_shutdown; @i.close; @i.terminate
|
566
768
|
end
|
567
769
|
end
|
770
|
+
|
771
|
+
sub_test_case '#generate_format_proc' do
|
772
|
+
test "when output doesn't have <buffer>" do
|
773
|
+
i = create_output(:sync)
|
774
|
+
i.configure(config_element('ROOT', '', {}, []))
|
775
|
+
assert_equal Fluent::Plugin::Output::FORMAT_MSGPACK_STREAM, i.generate_format_proc
|
776
|
+
end
|
777
|
+
|
778
|
+
test "when output doesn't have <buffer> and time_as_integer is true" do
|
779
|
+
i = create_output(:sync)
|
780
|
+
i.configure(config_element('ROOT', '', {'time_as_integer' => true}))
|
781
|
+
assert_equal Fluent::Plugin::Output::FORMAT_MSGPACK_STREAM_TIME_INT, i.generate_format_proc
|
782
|
+
end
|
783
|
+
|
784
|
+
test 'when output has <buffer> and compress is gzip' do
|
785
|
+
i = create_output(:buffered)
|
786
|
+
i.configure(config_element('ROOT', '', {}, [config_element('buffer', '', {'compress' => 'gzip'})]))
|
787
|
+
assert_equal Fluent::Plugin::Output::FORMAT_COMPRESSED_MSGPACK_STREAM, i.generate_format_proc
|
788
|
+
end
|
789
|
+
|
790
|
+
test 'when output has <buffer> and compress is gzip and time_as_integer is true' do
|
791
|
+
i = create_output(:buffered)
|
792
|
+
i.configure(config_element('ROOT', '', {'time_as_integer' => true}, [config_element('buffer', '', {'compress' => 'gzip'})]))
|
793
|
+
assert_equal Fluent::Plugin::Output::FORMAT_COMPRESSED_MSGPACK_STREAM_TIME_INT, i.generate_format_proc
|
794
|
+
end
|
795
|
+
|
796
|
+
test 'when output has <buffer> and compress is text' do
|
797
|
+
i = create_output(:buffered)
|
798
|
+
i.configure(config_element('ROOT', '', {}, [config_element('buffer', '', {'compress' => 'text'})]))
|
799
|
+
assert_equal Fluent::Plugin::Output::FORMAT_MSGPACK_STREAM, i.generate_format_proc
|
800
|
+
end
|
801
|
+
end
|
568
802
|
end
|