fluentd 1.16.11-x86-mingw32 → 1.17.0-x86-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/DISCUSSION_TEMPLATE/q-a-japanese.yml +50 -0
- data/.github/DISCUSSION_TEMPLATE/q-a.yml +47 -0
- data/.github/workflows/test-ruby-head.yml +31 -0
- data/.github/workflows/test.yml +6 -38
- data/CHANGELOG.md +33 -122
- data/README.md +4 -1
- data/Rakefile +1 -1
- data/SECURITY.md +4 -6
- data/fluentd.gemspec +5 -11
- data/lib/fluent/command/binlog_reader.rb +1 -1
- data/lib/fluent/command/fluentd.rb +1 -1
- data/lib/fluent/compat/formatter.rb +0 -6
- data/lib/fluent/config/configure_proxy.rb +2 -2
- data/lib/fluent/config/parser.rb +3 -15
- data/lib/fluent/config/types.rb +1 -1
- data/lib/fluent/config/v1_parser.rb +1 -1
- data/lib/fluent/config/yaml_parser/parser.rb +0 -4
- data/lib/fluent/configurable.rb +2 -2
- data/lib/fluent/counter/mutex_hash.rb +1 -1
- data/lib/fluent/fluent_log_event_router.rb +0 -2
- data/lib/fluent/plugin/buf_file.rb +1 -1
- data/lib/fluent/plugin/buffer/file_chunk.rb +1 -1
- data/lib/fluent/plugin/buffer/file_single_chunk.rb +2 -3
- data/lib/fluent/plugin/filter_parser.rb +26 -8
- data/lib/fluent/plugin/formatter_csv.rb +4 -18
- data/lib/fluent/plugin/in_http.rb +17 -52
- data/lib/fluent/plugin/in_tail.rb +35 -3
- data/lib/fluent/plugin/out_file.rb +0 -8
- data/lib/fluent/plugin/out_forward.rb +0 -10
- data/lib/fluent/plugin/out_http.rb +125 -13
- data/lib/fluent/plugin/owned_by_mixin.rb +0 -1
- data/lib/fluent/plugin/parser_json.rb +34 -9
- data/lib/fluent/plugin/parser_msgpack.rb +24 -3
- data/lib/fluent/plugin_helper/metrics.rb +2 -2
- data/lib/fluent/plugin_helper/server.rb +1 -4
- data/lib/fluent/registry.rb +6 -6
- data/lib/fluent/supervisor.rb +3 -3
- data/lib/fluent/test/output_test.rb +1 -1
- data/lib/fluent/test.rb +2 -5
- data/lib/fluent/unique_id.rb +1 -1
- data/lib/fluent/version.rb +1 -1
- data/lib/fluent/winsvc.rb +8 -38
- data/test/command/test_cat.rb +2 -2
- data/test/command/test_fluentd.rb +11 -58
- data/test/config/test_dsl.rb +1 -8
- data/test/config/test_element.rb +2 -2
- data/test/config/test_plugin_configuration.rb +6 -6
- data/test/helper.rb +7 -27
- data/test/log/test_console_adapter.rb +10 -3
- data/test/plugin/data/log_numeric/01.log +0 -0
- data/test/plugin/data/log_numeric/02.log +0 -0
- data/test/plugin/data/log_numeric/12.log +0 -0
- data/test/plugin/data/log_numeric/14.log +0 -0
- data/test/plugin/in_tail/test_io_handler.rb +14 -13
- data/test/plugin/in_tail/test_position_file.rb +7 -6
- data/test/plugin/out_forward/test_ack_handler.rb +3 -3
- data/test/plugin/out_forward/test_socket_cache.rb +3 -3
- data/test/plugin/test_buffer.rb +2 -2
- data/test/plugin/test_filter_grep.rb +1 -1
- data/test/plugin/test_filter_stdout.rb +4 -4
- data/test/plugin/test_formatter_hash.rb +2 -2
- data/test/plugin/test_in_forward.rb +1 -2
- data/test/plugin/test_in_http.rb +23 -1
- data/test/plugin/test_in_monitor_agent.rb +6 -6
- data/test/plugin/test_in_object_space.rb +0 -4
- data/test/plugin/test_in_syslog.rb +18 -25
- data/test/plugin/test_in_tail.rb +153 -5
- data/test/plugin/test_in_tcp.rb +1 -1
- data/test/plugin/test_in_udp.rb +10 -16
- data/test/plugin/test_out_exec_filter.rb +7 -12
- data/test/plugin/test_out_file.rb +2 -22
- data/test/plugin/test_out_forward.rb +37 -61
- data/test/plugin/test_out_http.rb +128 -0
- data/test/plugin/test_out_stdout.rb +3 -3
- data/test/plugin/test_out_stream.rb +1 -1
- data/test/plugin/test_output.rb +1 -1
- data/test/plugin/test_output_as_buffered.rb +2 -2
- data/test/plugin/test_output_as_buffered_retries.rb +2 -2
- data/test/plugin/test_owned_by.rb +0 -1
- data/test/plugin/test_parser_csv.rb +1 -1
- data/test/plugin/test_parser_json.rb +106 -31
- data/test/plugin/test_parser_msgpack.rb +127 -0
- data/test/plugin/test_storage.rb +0 -1
- data/test/plugin_helper/test_http_server_helper.rb +1 -1
- data/test/plugin_helper/test_server.rb +41 -83
- data/test/plugin_helper/test_socket.rb +1 -1
- data/test/test_config.rb +0 -6
- data/test/test_configdsl.rb +1 -8
- data/test/test_event_router.rb +2 -2
- data/test/test_plugin_helper.rb +1 -1
- data/test/test_supervisor.rb +21 -32
- data/test/test_tls.rb +1 -1
- metadata +66 -52
- data/test/scripts/windows_service_test.ps1 +0 -73
|
@@ -130,7 +130,7 @@ class FileOutputTest < Test::Unit::TestCase
|
|
|
130
130
|
'path' => "#{TMP_DIR}/${tag}/${type}/conf_test.%Y%m%d.%H%M.log",
|
|
131
131
|
'add_path_suffix' => 'false',
|
|
132
132
|
'append' => "true",
|
|
133
|
-
'symlink_path' => "#{TMP_DIR}
|
|
133
|
+
'symlink_path' => "#{TMP_DIR}/conf_test.current.log",
|
|
134
134
|
'compress' => 'gzip',
|
|
135
135
|
'recompress' => 'true',
|
|
136
136
|
}, [
|
|
@@ -183,26 +183,6 @@ class FileOutputTest < Test::Unit::TestCase
|
|
|
183
183
|
Fluent::Test::Driver::Output.new(Fluent::Plugin::NullOutput).configure(conf)
|
|
184
184
|
end
|
|
185
185
|
end
|
|
186
|
-
|
|
187
|
-
test 'warning for symlink_path not including correct placeholders corresponding to chunk keys' do
|
|
188
|
-
omit "Windows doesn't support symlink" if Fluent.windows?
|
|
189
|
-
conf = config_element('match', '**', {
|
|
190
|
-
'path' => "#{TMP_DIR}/${tag}/${key1}/${key2}/conf_test.%Y%m%d.%H%M.log",
|
|
191
|
-
'symlink_path' => "#{TMP_DIR}/conf_test.current.log",
|
|
192
|
-
}, [
|
|
193
|
-
config_element('buffer', 'time,tag,key1,key2', {
|
|
194
|
-
'@type' => 'file',
|
|
195
|
-
'timekey' => '1d',
|
|
196
|
-
'path' => "#{TMP_DIR}/buf_conf_test",
|
|
197
|
-
}),
|
|
198
|
-
])
|
|
199
|
-
assert_nothing_raised do
|
|
200
|
-
d = create_driver(conf)
|
|
201
|
-
assert do
|
|
202
|
-
d.logs.count { |log| log.include?("multiple chunks are competing for a single symlink_path") } == 2
|
|
203
|
-
end
|
|
204
|
-
end
|
|
205
|
-
end
|
|
206
186
|
end
|
|
207
187
|
|
|
208
188
|
sub_test_case 'fully configured output' do
|
|
@@ -334,7 +314,7 @@ class FileOutputTest < Test::Unit::TestCase
|
|
|
334
314
|
assert_equal r5, d.formatted[4]
|
|
335
315
|
|
|
336
316
|
read_gunzip = ->(path){
|
|
337
|
-
File.open(path
|
|
317
|
+
File.open(path){ |fio|
|
|
338
318
|
Zlib::GzipReader.new(StringIO.new(fio.read)).read
|
|
339
319
|
}
|
|
340
320
|
}
|
|
@@ -12,8 +12,7 @@ class ForwardOutputTest < Test::Unit::TestCase
|
|
|
12
12
|
FileUtils.rm_rf(TMP_DIR)
|
|
13
13
|
FileUtils.mkdir_p(TMP_DIR)
|
|
14
14
|
@d = nil
|
|
15
|
-
|
|
16
|
-
@target_port = unused_port(protocol: :all)
|
|
15
|
+
@target_port = unused_port
|
|
17
16
|
end
|
|
18
17
|
|
|
19
18
|
def teardown
|
|
@@ -178,42 +177,6 @@ EOL
|
|
|
178
177
|
assert{ logs.any?{|log| log.include?(expected_log) && log.include?(expected_detail) } }
|
|
179
178
|
end
|
|
180
179
|
|
|
181
|
-
sub_test_case 'configure compress' do
|
|
182
|
-
data('default', ['', :text])
|
|
183
|
-
data('gzip', ['compress gzip', :gzip])
|
|
184
|
-
test 'should be applied' do |(option, expected)|
|
|
185
|
-
@d = d = create_driver(config + option)
|
|
186
|
-
node = d.instance.nodes.first
|
|
187
|
-
|
|
188
|
-
assert_equal(
|
|
189
|
-
[expected, expected],
|
|
190
|
-
[d.instance.compress, node.instance_variable_get(:@compress)]
|
|
191
|
-
)
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
# TODO add tests that we cannot configure the different compress type between owner and buffer except for :text
|
|
195
|
-
data('gzip', ['compress gzip', :text, :gzip])
|
|
196
|
-
test 'can configure buffer compress separately when owner uses :text' do |(buffer_option, expected_owner_compress, expected_buffer_compress)|
|
|
197
|
-
@d = d = create_driver(config + %[
|
|
198
|
-
<buffer>
|
|
199
|
-
type memory
|
|
200
|
-
#{buffer_option}
|
|
201
|
-
</buffer>
|
|
202
|
-
])
|
|
203
|
-
node = d.instance.nodes.first
|
|
204
|
-
|
|
205
|
-
assert_equal(
|
|
206
|
-
[expected_owner_compress, expected_owner_compress, expected_buffer_compress],
|
|
207
|
-
[d.instance.compress, node.instance_variable_get(:@compress), d.instance.buffer.compress],
|
|
208
|
-
)
|
|
209
|
-
|
|
210
|
-
log_message = "buffer is compressed. If you also want to save the bandwidth of a network, Add `compress` configuration in <match>"
|
|
211
|
-
assert do
|
|
212
|
-
d.logs.any? { |log| log.include?(log_message) }
|
|
213
|
-
end
|
|
214
|
-
end
|
|
215
|
-
end
|
|
216
|
-
|
|
217
180
|
data('CA cert' => 'tls_ca_cert_path',
|
|
218
181
|
'non CA cert' => 'tls_cert_path')
|
|
219
182
|
test 'configure tls_cert_path/tls_ca_cert_path' do |param|
|
|
@@ -362,6 +325,40 @@ EOL
|
|
|
362
325
|
assert_equal 1234, d.instance.discovery_manager.services[0].port
|
|
363
326
|
end
|
|
364
327
|
|
|
328
|
+
test 'compress_default_value' do
|
|
329
|
+
@d = d = create_driver
|
|
330
|
+
assert_equal :text, d.instance.compress
|
|
331
|
+
|
|
332
|
+
node = d.instance.nodes.first
|
|
333
|
+
assert_equal :text, node.instance_variable_get(:@compress)
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
test 'set_compress_is_gzip' do
|
|
337
|
+
@d = d = create_driver(config + %[compress gzip])
|
|
338
|
+
assert_equal :gzip, d.instance.compress
|
|
339
|
+
assert_equal :gzip, d.instance.buffer.compress
|
|
340
|
+
|
|
341
|
+
node = d.instance.nodes.first
|
|
342
|
+
assert_equal :gzip, node.instance_variable_get(:@compress)
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
test 'set_compress_is_gzip_in_buffer_section' do
|
|
346
|
+
mock = flexmock($log)
|
|
347
|
+
mock.should_receive(:log).with("buffer is compressed. If you also want to save the bandwidth of a network, Add `compress` configuration in <match>")
|
|
348
|
+
|
|
349
|
+
@d = d = create_driver(config + %[
|
|
350
|
+
<buffer>
|
|
351
|
+
type memory
|
|
352
|
+
compress gzip
|
|
353
|
+
</buffer>
|
|
354
|
+
])
|
|
355
|
+
assert_equal :text, d.instance.compress
|
|
356
|
+
assert_equal :gzip, d.instance.buffer.compress
|
|
357
|
+
|
|
358
|
+
node = d.instance.nodes.first
|
|
359
|
+
assert_equal :text, node.instance_variable_get(:@compress)
|
|
360
|
+
end
|
|
361
|
+
|
|
365
362
|
test 'phi_failure_detector disabled' do
|
|
366
363
|
@d = d = create_driver(config + %[phi_failure_detector false \n phi_threshold 0])
|
|
367
364
|
node = d.instance.nodes.first
|
|
@@ -613,6 +610,7 @@ EOL
|
|
|
613
610
|
|
|
614
611
|
@d = d = create_driver(config + %[
|
|
615
612
|
require_ack_response true
|
|
613
|
+
ack_response_timeout 1s
|
|
616
614
|
<buffer tag>
|
|
617
615
|
flush_mode immediate
|
|
618
616
|
retry_type periodic
|
|
@@ -660,6 +658,7 @@ EOL
|
|
|
660
658
|
|
|
661
659
|
@d = d = create_driver(config + %[
|
|
662
660
|
require_ack_response true
|
|
661
|
+
ack_response_timeout 10s
|
|
663
662
|
<buffer tag>
|
|
664
663
|
flush_mode immediate
|
|
665
664
|
retry_type periodic
|
|
@@ -1347,27 +1346,4 @@ EOL
|
|
|
1347
1346
|
end
|
|
1348
1347
|
end
|
|
1349
1348
|
end
|
|
1350
|
-
|
|
1351
|
-
test 'establish_connection_timeout' do
|
|
1352
|
-
@d = d = create_driver(%[
|
|
1353
|
-
hard_timeout 1
|
|
1354
|
-
<server>
|
|
1355
|
-
host #{TARGET_HOST}
|
|
1356
|
-
port #{@target_port}
|
|
1357
|
-
</server>
|
|
1358
|
-
])
|
|
1359
|
-
|
|
1360
|
-
node = d.instance.nodes.first
|
|
1361
|
-
mock_sock = flexmock('socket')
|
|
1362
|
-
mock_sock.should_receive(:read_nonblock).with(512).and_return('').at_least.once
|
|
1363
|
-
|
|
1364
|
-
ri = Fluent::Plugin::ForwardOutput::ConnectionManager::RequestInfo.new(:helo)
|
|
1365
|
-
|
|
1366
|
-
assert_true node.available?
|
|
1367
|
-
node.establish_connection(mock_sock, ri)
|
|
1368
|
-
assert_false node.available?
|
|
1369
|
-
|
|
1370
|
-
logs = d.logs
|
|
1371
|
-
assert{ logs.any?{|log| log.include?('handshake timeout after 1.0s') } }
|
|
1372
|
-
end
|
|
1373
1349
|
end
|
|
@@ -7,6 +7,7 @@ require 'webrick/https'
|
|
|
7
7
|
require 'net/http'
|
|
8
8
|
require 'uri'
|
|
9
9
|
require 'json'
|
|
10
|
+
require 'aws-sdk-core'
|
|
10
11
|
|
|
11
12
|
# WEBrick's ProcHandler doesn't handle PUT by default
|
|
12
13
|
module WEBrick::HTTPServlet
|
|
@@ -390,6 +391,97 @@ class HTTPOutputTest < Test::Unit::TestCase
|
|
|
390
391
|
end
|
|
391
392
|
end
|
|
392
393
|
|
|
394
|
+
|
|
395
|
+
sub_test_case 'aws sigv4 auth' do
|
|
396
|
+
setup do
|
|
397
|
+
@@fake_aws_credentials = Aws::Credentials.new(
|
|
398
|
+
'fakeaccess',
|
|
399
|
+
'fakesecret',
|
|
400
|
+
'fake session token'
|
|
401
|
+
)
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
def server_port
|
|
405
|
+
19883
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
def test_aws_sigv4_sts_role_arn
|
|
409
|
+
stub(Aws::AssumeRoleCredentials).new do |credentials_provider|
|
|
410
|
+
stub(credentials_provider).credentials {
|
|
411
|
+
@@fake_aws_credentials
|
|
412
|
+
}
|
|
413
|
+
credentials_provider
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
d = create_driver(config + %[
|
|
417
|
+
<auth>
|
|
418
|
+
method aws_sigv4
|
|
419
|
+
aws_service someservice
|
|
420
|
+
aws_region my-region-1
|
|
421
|
+
aws_role_arn arn:aws:iam::123456789012:role/MyRole
|
|
422
|
+
</auth>
|
|
423
|
+
])
|
|
424
|
+
d.run(default_tag: 'test.http') do
|
|
425
|
+
test_events.each { |event|
|
|
426
|
+
d.feed(event)
|
|
427
|
+
}
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
result = @@result
|
|
431
|
+
assert_equal 'POST', result.method
|
|
432
|
+
assert_equal 'application/x-ndjson', result.content_type
|
|
433
|
+
assert_equal test_events, result.data
|
|
434
|
+
assert_not_empty result.headers
|
|
435
|
+
assert_not_nil result.headers['authorization']
|
|
436
|
+
assert_match /AWS4-HMAC-SHA256 Credential=[a-zA-Z0-9]*\/\d+\/my-region-1\/someservice\/aws4_request/, result.headers['authorization']
|
|
437
|
+
assert_match /SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date;x-amz-security-token/, result.headers['authorization']
|
|
438
|
+
assert_equal @@fake_aws_credentials.session_token, result.headers['x-amz-security-token']
|
|
439
|
+
assert_not_nil result.headers['x-amz-content-sha256']
|
|
440
|
+
assert_not_empty result.headers['x-amz-content-sha256']
|
|
441
|
+
assert_not_nil result.headers['x-amz-security-token']
|
|
442
|
+
assert_not_empty result.headers['x-amz-security-token']
|
|
443
|
+
assert_not_nil result.headers['x-amz-date']
|
|
444
|
+
assert_not_empty result.headers['x-amz-date']
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
def test_aws_sigv4_no_role
|
|
448
|
+
stub(Aws::CredentialProviderChain).new do |provider_chain|
|
|
449
|
+
stub(provider_chain).resolve {
|
|
450
|
+
@@fake_aws_credentials
|
|
451
|
+
}
|
|
452
|
+
provider_chain
|
|
453
|
+
end
|
|
454
|
+
d = create_driver(config + %[
|
|
455
|
+
<auth>
|
|
456
|
+
method aws_sigv4
|
|
457
|
+
aws_service someservice
|
|
458
|
+
aws_region my-region-1
|
|
459
|
+
</auth>
|
|
460
|
+
])
|
|
461
|
+
d.run(default_tag: 'test.http') do
|
|
462
|
+
test_events.each { |event|
|
|
463
|
+
d.feed(event)
|
|
464
|
+
}
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
result = @@result
|
|
468
|
+
assert_equal 'POST', result.method
|
|
469
|
+
assert_equal 'application/x-ndjson', result.content_type
|
|
470
|
+
assert_equal test_events, result.data
|
|
471
|
+
assert_not_empty result.headers
|
|
472
|
+
assert_not_nil result.headers['authorization']
|
|
473
|
+
assert_match /AWS4-HMAC-SHA256 Credential=[a-zA-Z0-9]*\/\d+\/my-region-1\/someservice\/aws4_request/, result.headers['authorization']
|
|
474
|
+
assert_match /SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date;x-amz-security-token/, result.headers['authorization']
|
|
475
|
+
assert_equal @@fake_aws_credentials.session_token, result.headers['x-amz-security-token']
|
|
476
|
+
assert_not_nil result.headers['x-amz-content-sha256']
|
|
477
|
+
assert_not_empty result.headers['x-amz-content-sha256']
|
|
478
|
+
assert_not_nil result.headers['x-amz-security-token']
|
|
479
|
+
assert_not_empty result.headers['x-amz-security-token']
|
|
480
|
+
assert_not_nil result.headers['x-amz-date']
|
|
481
|
+
assert_not_empty result.headers['x-amz-date']
|
|
482
|
+
end
|
|
483
|
+
end
|
|
484
|
+
|
|
393
485
|
sub_test_case 'HTTPS' do
|
|
394
486
|
def server_port
|
|
395
487
|
19882
|
|
@@ -426,4 +518,40 @@ class HTTPOutputTest < Test::Unit::TestCase
|
|
|
426
518
|
assert_not_empty result.headers
|
|
427
519
|
end
|
|
428
520
|
end
|
|
521
|
+
|
|
522
|
+
sub_test_case 'connection_reuse' do
|
|
523
|
+
def server_port
|
|
524
|
+
19883
|
|
525
|
+
end
|
|
526
|
+
|
|
527
|
+
def test_connection_recreation
|
|
528
|
+
d = create_driver(%[
|
|
529
|
+
endpoint http://127.0.0.1:#{server_port}/test
|
|
530
|
+
reuse_connections true
|
|
531
|
+
])
|
|
532
|
+
|
|
533
|
+
d.run(default_tag: 'test.http', shutdown: false) do
|
|
534
|
+
d.feed(test_events[0])
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
data = @@result.data
|
|
538
|
+
|
|
539
|
+
# Restart server to simulate connection loss
|
|
540
|
+
@@http_server_thread.kill
|
|
541
|
+
@@http_server_thread.join
|
|
542
|
+
@@http_server_thread = Thread.new do
|
|
543
|
+
run_http_server
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
d.run(default_tag: 'test.http') do
|
|
547
|
+
d.feed(test_events[1])
|
|
548
|
+
end
|
|
549
|
+
|
|
550
|
+
result = @@result
|
|
551
|
+
assert_equal 'POST', result.method
|
|
552
|
+
assert_equal 'application/x-ndjson', result.content_type
|
|
553
|
+
assert_equal test_events, data.concat(result.data)
|
|
554
|
+
assert_not_empty result.headers
|
|
555
|
+
end
|
|
556
|
+
end
|
|
429
557
|
end
|
|
@@ -95,11 +95,11 @@ class StdoutOutputTest < Test::Unit::TestCase
|
|
|
95
95
|
d.feed(time, {'test' => 'test2'})
|
|
96
96
|
end
|
|
97
97
|
end
|
|
98
|
-
assert_equal "#{Time.at(time).localtime.strftime(TIME_FORMAT)} test: {\"test\"=>\"test2\"}\n", out
|
|
98
|
+
assert_equal "#{Time.at(time).localtime.strftime(TIME_FORMAT)} test: {\"test\"=>\"test2\"}\n", out
|
|
99
99
|
|
|
100
100
|
# NOTE: Float::NAN is not jsonable, but hash string can output it.
|
|
101
101
|
out = capture_log { d.feed('test', time, {'test' => Float::NAN}) }
|
|
102
|
-
assert_equal "#{Time.at(time).localtime.strftime(TIME_FORMAT)} test: {\"test\"=>NaN}\n", out
|
|
102
|
+
assert_equal "#{Time.at(time).localtime.strftime(TIME_FORMAT)} test: {\"test\"=>NaN}\n", out
|
|
103
103
|
end
|
|
104
104
|
end
|
|
105
105
|
|
|
@@ -171,7 +171,7 @@ class StdoutOutputTest < Test::Unit::TestCase
|
|
|
171
171
|
end
|
|
172
172
|
end
|
|
173
173
|
|
|
174
|
-
assert_equal "#{Time.at(time).localtime.strftime(TIME_FORMAT)} test: {\"test\"=>\"test\"}\n", out
|
|
174
|
+
assert_equal "#{Time.at(time).localtime.strftime(TIME_FORMAT)} test: {\"test\"=>\"test\"}\n", out
|
|
175
175
|
end
|
|
176
176
|
end
|
|
177
177
|
end
|
data/test/plugin/test_output.rb
CHANGED
|
@@ -1111,7 +1111,7 @@ class OutputTest < Test::Unit::TestCase
|
|
|
1111
1111
|
config: config_element(
|
|
1112
1112
|
"ROOT", "", {},
|
|
1113
1113
|
[
|
|
1114
|
-
config_element("buffer", "", {}),
|
|
1114
|
+
config_element("buffer", "", {}),
|
|
1115
1115
|
config_element("secondary", "", {"@type" => "test", "name" => "test"}),
|
|
1116
1116
|
]
|
|
1117
1117
|
),
|
|
@@ -1343,7 +1343,6 @@ class BufferedOutputTest < Test::Unit::TestCase
|
|
|
1343
1343
|
hash = {
|
|
1344
1344
|
'flush_interval' => 10,
|
|
1345
1345
|
'flush_thread_count' => 1,
|
|
1346
|
-
'flush_thread_interval' => 0.1,
|
|
1347
1346
|
'flush_thread_burst_interval' => 0.1,
|
|
1348
1347
|
'chunk_limit_size' => 1024,
|
|
1349
1348
|
}
|
|
@@ -1446,7 +1445,7 @@ class BufferedOutputTest < Test::Unit::TestCase
|
|
|
1446
1445
|
|
|
1447
1446
|
assert{ @i.buffer.stage.size == 3 }
|
|
1448
1447
|
|
|
1449
|
-
# to trigger try_flush with
|
|
1448
|
+
# to trigger try_flush with flush_thread_burst_interval
|
|
1450
1449
|
Timecop.freeze( Time.parse('2016-04-13 14:04:11 +0900') )
|
|
1451
1450
|
@i.enqueue_thread_wait
|
|
1452
1451
|
Timecop.freeze( Time.parse('2016-04-13 14:04:12 +0900') )
|
|
@@ -1455,6 +1454,7 @@ class BufferedOutputTest < Test::Unit::TestCase
|
|
|
1455
1454
|
@i.enqueue_thread_wait
|
|
1456
1455
|
Timecop.freeze( Time.parse('2016-04-13 14:04:14 +0900') )
|
|
1457
1456
|
@i.enqueue_thread_wait
|
|
1457
|
+
@i.flush_thread_wakeup
|
|
1458
1458
|
|
|
1459
1459
|
assert{ @i.buffer.stage.size == 0 }
|
|
1460
1460
|
|
|
@@ -941,7 +941,7 @@ class BufferedOutputRetryTest < Test::Unit::TestCase
|
|
|
941
941
|
@i.enqueue_thread_wait
|
|
942
942
|
|
|
943
943
|
@i.flush_thread_wakeup
|
|
944
|
-
waiting(4){ Thread.pass until @i.write_count > 0
|
|
944
|
+
waiting(4){ Thread.pass until @i.write_count > 0 }
|
|
945
945
|
waiting(4) do
|
|
946
946
|
state = @i.instance_variable_get(:@output_flush_threads).first
|
|
947
947
|
state.thread.status == 'sleep'
|
|
@@ -953,7 +953,7 @@ class BufferedOutputRetryTest < Test::Unit::TestCase
|
|
|
953
953
|
now = @i.next_flush_time
|
|
954
954
|
Timecop.freeze( now )
|
|
955
955
|
@i.flush_thread_wakeup
|
|
956
|
-
waiting(4){ Thread.pass until @i.write_count > 1
|
|
956
|
+
waiting(4){ Thread.pass until @i.write_count > 1 }
|
|
957
957
|
waiting(4) do
|
|
958
958
|
state = @i.instance_variable_get(:@output_flush_threads).first
|
|
959
959
|
state.thread.status == 'sleep'
|
|
@@ -26,7 +26,6 @@ class OwnedByMixinTest < Test::Unit::TestCase
|
|
|
26
26
|
|
|
27
27
|
assert_equal parent.object_id, child.owner.object_id
|
|
28
28
|
|
|
29
|
-
assert child.instance_eval{ @_plugin_id_configured }
|
|
30
29
|
assert_equal 'my_parent_id', child.instance_eval{ @_plugin_id }
|
|
31
30
|
|
|
32
31
|
assert_equal Fluent::Log::LEVEL_TRACE, child.log.level
|
|
@@ -164,7 +164,7 @@ class CSVParserTest < ::Test::Unit::TestCase
|
|
|
164
164
|
text = 'a"b,"a"""c"'
|
|
165
165
|
assert_raise(CSV::MalformedCSVError) {
|
|
166
166
|
normal.instance.parse(text) { |t, r| }
|
|
167
|
-
}
|
|
167
|
+
}
|
|
168
168
|
assert_nothing_raised {
|
|
169
169
|
# generate broken record
|
|
170
170
|
fast.instance.parse(text) { |t, r| }
|
|
@@ -8,37 +8,6 @@ class JsonParserTest < ::Test::Unit::TestCase
|
|
|
8
8
|
@parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin::JSONParser)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
sub_test_case "configure_json_parser" do
|
|
12
|
-
data("oj", [:oj, [Oj.method(:load), Oj::ParseError]])
|
|
13
|
-
data("json", [:json, [JSON.method(:load), JSON::ParserError]])
|
|
14
|
-
data("yajl", [:yajl, [Yajl.method(:load), Yajl::ParseError]])
|
|
15
|
-
def test_return_each_loader((input, expected_return))
|
|
16
|
-
result = @parser.instance.configure_json_parser(input)
|
|
17
|
-
assert_equal expected_return, result
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def test_raise_exception_for_unknown_input
|
|
21
|
-
assert_raise RuntimeError do
|
|
22
|
-
@parser.instance.configure_json_parser(:unknown)
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def test_fall_back_oj_to_yajl_if_oj_not_available
|
|
27
|
-
stub(Fluent::OjOptions).available? { false }
|
|
28
|
-
|
|
29
|
-
result = @parser.instance.configure_json_parser(:oj)
|
|
30
|
-
|
|
31
|
-
assert_equal [Yajl.method(:load), Yajl::ParseError], result
|
|
32
|
-
logs = @parser.logs.collect do |log|
|
|
33
|
-
log.gsub(/\A\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]\d{4} /, "")
|
|
34
|
-
end
|
|
35
|
-
assert_equal(
|
|
36
|
-
["[info]: Oj is not installed, and failing back to Yajl for json parser\n"],
|
|
37
|
-
logs
|
|
38
|
-
)
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
11
|
data('oj' => 'oj', 'yajl' => 'yajl')
|
|
43
12
|
def test_parse(data)
|
|
44
13
|
@parser.configure('json_parser' => data)
|
|
@@ -166,4 +135,110 @@ class JsonParserTest < ::Test::Unit::TestCase
|
|
|
166
135
|
end
|
|
167
136
|
end
|
|
168
137
|
end
|
|
138
|
+
|
|
139
|
+
sub_test_case "various record pattern" do
|
|
140
|
+
data("Only string", { record: '"message"', expected: [nil] }, keep: true)
|
|
141
|
+
data("Only string without quotation", { record: "message", expected: [nil] }, keep: true)
|
|
142
|
+
data("Only number", { record: "0", expected: [nil] }, keep: true)
|
|
143
|
+
data(
|
|
144
|
+
"Array of Hash",
|
|
145
|
+
{
|
|
146
|
+
record: '[{"k1": 1}, {"k2": 2}]',
|
|
147
|
+
expected: [{"k1" => 1}, {"k2" => 2}]
|
|
148
|
+
},
|
|
149
|
+
keep: true,
|
|
150
|
+
)
|
|
151
|
+
data(
|
|
152
|
+
"Array of both Hash and invalid",
|
|
153
|
+
{
|
|
154
|
+
record: '[{"k1": 1}, "string", {"k2": 2}, 0]',
|
|
155
|
+
expected: [{"k1" => 1}, nil, {"k2" => 2}, nil]
|
|
156
|
+
},
|
|
157
|
+
keep: true,
|
|
158
|
+
)
|
|
159
|
+
data(
|
|
160
|
+
"Array of all invalid",
|
|
161
|
+
{
|
|
162
|
+
record: '["string", 0, [{"k": 0}]]',
|
|
163
|
+
expected: [nil, nil, nil]
|
|
164
|
+
},
|
|
165
|
+
keep: true,
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
def test_oj(data)
|
|
169
|
+
parsed_records = []
|
|
170
|
+
@parser.configure("json_parser" => "oj")
|
|
171
|
+
@parser.instance.parse(data[:record]) { |time, record|
|
|
172
|
+
parsed_records.append(record)
|
|
173
|
+
}
|
|
174
|
+
assert_equal(data[:expected], parsed_records)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def test_yajl(data)
|
|
178
|
+
parsed_records = []
|
|
179
|
+
@parser.configure("json_parser" => "yajl")
|
|
180
|
+
@parser.instance.parse(data[:record]) { |time, record|
|
|
181
|
+
parsed_records.append(record)
|
|
182
|
+
}
|
|
183
|
+
assert_equal(data[:expected], parsed_records)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def test_json(json)
|
|
187
|
+
parsed_records = []
|
|
188
|
+
@parser.configure("json_parser" => "json")
|
|
189
|
+
@parser.instance.parse(data[:record]) { |time, record|
|
|
190
|
+
parsed_records.append(record)
|
|
191
|
+
}
|
|
192
|
+
assert_equal(data[:expected], parsed_records)
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# This becomes NoMethodError if a non-Hash object is passed to convert_values.
|
|
197
|
+
# https://github.com/fluent/fluentd/issues/4100
|
|
198
|
+
sub_test_case "execute_convert_values with null_empty_string" do
|
|
199
|
+
data("Only string", { record: '"message"', expected: [nil] }, keep: true)
|
|
200
|
+
data(
|
|
201
|
+
"Hash",
|
|
202
|
+
{
|
|
203
|
+
record: '{"k1": 1, "k2": ""}',
|
|
204
|
+
expected: [{"k1" => 1, "k2" => nil}]
|
|
205
|
+
},
|
|
206
|
+
keep: true,
|
|
207
|
+
)
|
|
208
|
+
data(
|
|
209
|
+
"Array of Hash",
|
|
210
|
+
{
|
|
211
|
+
record: '[{"k1": 1}, {"k2": ""}]',
|
|
212
|
+
expected: [{"k1" => 1}, {"k2" => nil}]
|
|
213
|
+
},
|
|
214
|
+
keep: true,
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
def test_oj(data)
|
|
218
|
+
parsed_records = []
|
|
219
|
+
@parser.configure("json_parser" => "oj", "null_empty_string" => true)
|
|
220
|
+
@parser.instance.parse(data[:record]) { |time, record|
|
|
221
|
+
parsed_records.append(record)
|
|
222
|
+
}
|
|
223
|
+
assert_equal(data[:expected], parsed_records)
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def test_yajl(data)
|
|
227
|
+
parsed_records = []
|
|
228
|
+
@parser.configure("json_parser" => "yajl", "null_empty_string" => true)
|
|
229
|
+
@parser.instance.parse(data[:record]) { |time, record|
|
|
230
|
+
parsed_records.append(record)
|
|
231
|
+
}
|
|
232
|
+
assert_equal(data[:expected], parsed_records)
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def test_json(json)
|
|
236
|
+
parsed_records = []
|
|
237
|
+
@parser.configure("json_parser" => "json", "null_empty_string" => true)
|
|
238
|
+
@parser.instance.parse(data[:record]) { |time, record|
|
|
239
|
+
parsed_records.append(record)
|
|
240
|
+
}
|
|
241
|
+
assert_equal(data[:expected], parsed_records)
|
|
242
|
+
end
|
|
243
|
+
end
|
|
169
244
|
end
|