fluentd 1.6.3 → 1.7.0
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/.drone.yml +35 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +2 -0
- data/CHANGELOG.md +58 -0
- data/README.md +5 -1
- data/fluentd.gemspec +1 -1
- data/lib/fluent/clock.rb +4 -0
- data/lib/fluent/compat/output.rb +3 -3
- data/lib/fluent/compat/socket_util.rb +1 -1
- data/lib/fluent/config/element.rb +3 -3
- data/lib/fluent/config/literal_parser.rb +1 -1
- data/lib/fluent/config/section.rb +4 -1
- data/lib/fluent/error.rb +4 -0
- data/lib/fluent/event.rb +28 -24
- data/lib/fluent/event_router.rb +2 -1
- data/lib/fluent/log.rb +1 -1
- data/lib/fluent/msgpack_factory.rb +8 -0
- data/lib/fluent/plugin/bare_output.rb +4 -4
- data/lib/fluent/plugin/buf_file_single.rb +211 -0
- data/lib/fluent/plugin/buffer.rb +62 -63
- data/lib/fluent/plugin/buffer/chunk.rb +21 -3
- data/lib/fluent/plugin/buffer/file_chunk.rb +37 -12
- data/lib/fluent/plugin/buffer/file_single_chunk.rb +314 -0
- data/lib/fluent/plugin/buffer/memory_chunk.rb +2 -1
- data/lib/fluent/plugin/compressable.rb +10 -6
- data/lib/fluent/plugin/filter_grep.rb +2 -2
- data/lib/fluent/plugin/formatter_csv.rb +10 -6
- data/lib/fluent/plugin/in_syslog.rb +10 -3
- data/lib/fluent/plugin/in_tail.rb +7 -2
- data/lib/fluent/plugin/in_tcp.rb +34 -7
- data/lib/fluent/plugin/multi_output.rb +4 -4
- data/lib/fluent/plugin/out_exec_filter.rb +1 -0
- data/lib/fluent/plugin/out_file.rb +13 -3
- data/lib/fluent/plugin/out_forward.rb +126 -588
- data/lib/fluent/plugin/out_forward/ack_handler.rb +161 -0
- data/lib/fluent/plugin/out_forward/connection_manager.rb +113 -0
- data/lib/fluent/plugin/out_forward/error.rb +28 -0
- data/lib/fluent/plugin/out_forward/failure_detector.rb +84 -0
- data/lib/fluent/plugin/out_forward/handshake_protocol.rb +121 -0
- data/lib/fluent/plugin/out_forward/load_balancer.rb +111 -0
- data/lib/fluent/plugin/out_forward/socket_cache.rb +138 -0
- data/lib/fluent/plugin/out_http.rb +231 -0
- data/lib/fluent/plugin/output.rb +29 -35
- data/lib/fluent/plugin/parser.rb +77 -0
- data/lib/fluent/plugin/parser_csv.rb +75 -0
- data/lib/fluent/plugin_helper/server.rb +1 -1
- data/lib/fluent/plugin_helper/thread.rb +1 -0
- data/lib/fluent/root_agent.rb +1 -1
- data/lib/fluent/time.rb +4 -2
- data/lib/fluent/timezone.rb +21 -7
- data/lib/fluent/version.rb +1 -1
- data/test/command/test_fluentd.rb +1 -1
- data/test/command/test_plugin_generator.rb +18 -2
- data/test/config/test_configurable.rb +78 -40
- data/test/counter/test_store.rb +1 -1
- data/test/helper.rb +1 -0
- data/test/helpers/process_extenstion.rb +33 -0
- data/test/plugin/out_forward/test_ack_handler.rb +101 -0
- data/test/plugin/out_forward/test_connection_manager.rb +145 -0
- data/test/plugin/out_forward/test_handshake_protocol.rb +103 -0
- data/test/plugin/out_forward/test_load_balancer.rb +60 -0
- data/test/plugin/out_forward/test_socket_cache.rb +139 -0
- data/test/plugin/test_buf_file.rb +118 -2
- data/test/plugin/test_buf_file_single.rb +734 -0
- data/test/plugin/test_buffer.rb +4 -48
- data/test/plugin/test_buffer_file_chunk.rb +19 -1
- data/test/plugin/test_buffer_file_single_chunk.rb +620 -0
- data/test/plugin/test_formatter_csv.rb +16 -0
- data/test/plugin/test_in_syslog.rb +56 -6
- data/test/plugin/test_in_tail.rb +1 -1
- data/test/plugin/test_in_tcp.rb +25 -0
- data/test/plugin/test_out_forward.rb +75 -201
- data/test/plugin/test_out_http.rb +352 -0
- data/test/plugin/test_output_as_buffered.rb +27 -24
- data/test/plugin/test_parser.rb +40 -0
- data/test/plugin/test_parser_csv.rb +83 -0
- data/test/plugin_helper/test_record_accessor.rb +1 -1
- data/test/test_time_formatter.rb +140 -121
- metadata +33 -4
data/lib/fluent/timezone.rb
CHANGED
@@ -18,6 +18,15 @@ require 'tzinfo'
|
|
18
18
|
|
19
19
|
require 'fluent/config/error'
|
20
20
|
|
21
|
+
# For v0.12. Will be removed after v2
|
22
|
+
module IntegerExt
|
23
|
+
refine Integer do
|
24
|
+
def to_time
|
25
|
+
Time.at(self)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
21
30
|
module Fluent
|
22
31
|
class Timezone
|
23
32
|
# [+-]HH:MM, [+-]HHMM, [+-]HH
|
@@ -84,6 +93,8 @@ module Fluent
|
|
84
93
|
end
|
85
94
|
end
|
86
95
|
|
96
|
+
using IntegerExt
|
97
|
+
|
87
98
|
# Create a formatter for a timezone and optionally a format.
|
88
99
|
#
|
89
100
|
# An Proc object is returned. If the given timezone is invalid,
|
@@ -100,15 +111,15 @@ module Fluent
|
|
100
111
|
case
|
101
112
|
when format.is_a?(String)
|
102
113
|
return Proc.new {|time|
|
103
|
-
|
114
|
+
time.to_time.localtime(offset).strftime(format)
|
104
115
|
}
|
105
116
|
when format.is_a?(Strftime)
|
106
117
|
return Proc.new {|time|
|
107
|
-
format.exec(
|
118
|
+
format.exec(time.to_time.localtime(offset))
|
108
119
|
}
|
109
120
|
else
|
110
121
|
return Proc.new {|time|
|
111
|
-
|
122
|
+
time.to_time.localtime(offset).iso8601
|
112
123
|
}
|
113
124
|
end
|
114
125
|
end
|
@@ -124,15 +135,18 @@ module Fluent
|
|
124
135
|
case
|
125
136
|
when format.is_a?(String)
|
126
137
|
return Proc.new {|time|
|
127
|
-
|
138
|
+
time = time.to_time
|
139
|
+
time.localtime(tz.period_for_utc(time).utc_total_offset).strftime(format)
|
128
140
|
}
|
129
141
|
when format.is_a?(Strftime)
|
130
142
|
return Proc.new {|time|
|
131
|
-
|
143
|
+
time = time.to_time
|
144
|
+
format.exec(time.localtime(tz.period_for_utc(time).utc_total_offset))
|
132
145
|
}
|
133
146
|
else
|
134
147
|
return Proc.new {|time|
|
135
|
-
|
148
|
+
time = time.to_time
|
149
|
+
time.localtime(tz.period_for_utc(time).utc_total_offset).iso8601
|
136
150
|
}
|
137
151
|
end
|
138
152
|
end
|
@@ -149,7 +163,7 @@ module Fluent
|
|
149
163
|
when NAME_PATTERN
|
150
164
|
tz = TZInfo::Timezone.get(timezone)
|
151
165
|
->(time) {
|
152
|
-
tz.period_for_utc(time).utc_total_offset
|
166
|
+
tz.period_for_utc(time.to_time).utc_total_offset
|
153
167
|
}
|
154
168
|
end
|
155
169
|
end
|
data/lib/fluent/version.rb
CHANGED
@@ -807,7 +807,7 @@ CONF
|
|
807
807
|
)
|
808
808
|
end
|
809
809
|
|
810
|
-
test 'success to start workers when configured plugins as a
|
810
|
+
test 'success to start workers when configured plugins as a children of MultiOutput only for specific worker do not support multi worker configuration' do
|
811
811
|
script = <<-EOC
|
812
812
|
require 'fluent/plugin/output'
|
813
813
|
module Fluent::Plugin
|
@@ -16,6 +16,14 @@ class TestFluentPluginGenerator < Test::Unit::TestCase
|
|
16
16
|
FileUtils.rm_rf(TEMP_DIR)
|
17
17
|
end
|
18
18
|
|
19
|
+
def stub_git_process(target)
|
20
|
+
stub(target).spawn do |cmd, arg1, arg2|
|
21
|
+
assert_equal %w[git init .], [cmd, arg1, arg2]
|
22
|
+
-1
|
23
|
+
end
|
24
|
+
stub(Process).wait { |pid| assert_equal(pid, -1) }
|
25
|
+
end
|
26
|
+
|
19
27
|
sub_test_case "generate plugin" do
|
20
28
|
data(input: ["input", "in"],
|
21
29
|
output: ["output", "out"],
|
@@ -23,8 +31,10 @@ class TestFluentPluginGenerator < Test::Unit::TestCase
|
|
23
31
|
parser: ["parser", "parser"],
|
24
32
|
formatter: ["formatter", "formatter"])
|
25
33
|
test "generate plugin" do |(type, part)|
|
34
|
+
generator = FluentPluginGenerator.new([type, "fake"])
|
35
|
+
stub_git_process(generator)
|
26
36
|
capture_stdout do
|
27
|
-
|
37
|
+
generator.call
|
28
38
|
end
|
29
39
|
plugin_base_dir = Pathname("fluent-plugin-fake")
|
30
40
|
assert { plugin_base_dir.directory? }
|
@@ -49,8 +59,10 @@ class TestFluentPluginGenerator < Test::Unit::TestCase
|
|
49
59
|
end
|
50
60
|
|
51
61
|
test "no license" do
|
62
|
+
generator = FluentPluginGenerator.new(["--no-license", "filter", "fake"])
|
63
|
+
stub_git_process(generator)
|
52
64
|
capture_stdout do
|
53
|
-
|
65
|
+
generator.call
|
54
66
|
end
|
55
67
|
assert { !Pathname("fluent-plugin-fake/LICENSE").exist? }
|
56
68
|
assert { Pathname("fluent-plugin-fake/Gemfile").exist? }
|
@@ -72,6 +84,8 @@ class TestFluentPluginGenerator < Test::Unit::TestCase
|
|
72
84
|
"dash" => ["rewrite-tag-filter", "rewrite_tag_filter"])
|
73
85
|
test "plugin_name" do |(name, plugin_name)|
|
74
86
|
generator = FluentPluginGenerator.new(["filter", name])
|
87
|
+
stub_git_process(generator)
|
88
|
+
stub(Process).wait { |pid| assert_equal(pid, -1) }
|
75
89
|
capture_stdout do
|
76
90
|
generator.call
|
77
91
|
end
|
@@ -83,6 +97,8 @@ class TestFluentPluginGenerator < Test::Unit::TestCase
|
|
83
97
|
"dash" => ["rewrite-tag-filter", "fluent-plugin-rewrite-tag-filter"])
|
84
98
|
test "gem_name" do |(name, gem_name)|
|
85
99
|
generator = FluentPluginGenerator.new(["output", name])
|
100
|
+
stub_git_process(generator)
|
101
|
+
stub(Process).wait { |pid| assert_equal(pid, -1) }
|
86
102
|
capture_stdout do
|
87
103
|
generator.call
|
88
104
|
end
|
@@ -152,7 +152,7 @@ module ConfigurableSpec
|
|
152
152
|
config_param :arrayvalue, :array
|
153
153
|
end
|
154
154
|
|
155
|
-
class
|
155
|
+
class ExampleWithAlias
|
156
156
|
include Fluent::Configurable
|
157
157
|
|
158
158
|
config_param :name, :string, alias: :fullname
|
@@ -166,22 +166,7 @@ module ConfigurableSpec
|
|
166
166
|
end
|
167
167
|
end
|
168
168
|
|
169
|
-
class
|
170
|
-
include Fluent::Configurable
|
171
|
-
|
172
|
-
config_param :age, :integer, default: 10
|
173
|
-
|
174
|
-
config_section :appendix, required: true, multi: false, final: true do
|
175
|
-
config_param :type, :string
|
176
|
-
config_param :name, :string, default: "x"
|
177
|
-
end
|
178
|
-
|
179
|
-
def get_all
|
180
|
-
[@name, @detail]
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
class Example5
|
169
|
+
class ExampleWithSecret
|
185
170
|
include Fluent::Configurable
|
186
171
|
|
187
172
|
config_param :normal_param, :string
|
@@ -193,17 +178,42 @@ module ConfigurableSpec
|
|
193
178
|
end
|
194
179
|
end
|
195
180
|
|
196
|
-
class
|
181
|
+
class ExampleWithDefaultHashAndArray
|
197
182
|
include Fluent::Configurable
|
198
183
|
config_param :obj1, :hash, default: {}
|
199
184
|
config_param :obj2, :array, default: []
|
200
185
|
end
|
201
186
|
|
202
|
-
class
|
187
|
+
class ExampleWithSkipAccessor
|
203
188
|
include Fluent::Configurable
|
204
189
|
config_param :name, :string, default: 'example7', skip_accessor: true
|
205
190
|
end
|
206
191
|
|
192
|
+
class ExampleWithCustomSection
|
193
|
+
include Fluent::Configurable
|
194
|
+
config_param :name_param, :string
|
195
|
+
config_section :normal_section do
|
196
|
+
config_param :normal_section_param, :string
|
197
|
+
end
|
198
|
+
|
199
|
+
class CustomSection
|
200
|
+
include Fluent::Configurable
|
201
|
+
config_param :custom_section_param, :string
|
202
|
+
end
|
203
|
+
|
204
|
+
class AnotherElement
|
205
|
+
include Fluent::Configurable
|
206
|
+
end
|
207
|
+
|
208
|
+
def configure(conf)
|
209
|
+
super
|
210
|
+
conf.elements.each do |e|
|
211
|
+
next if e.name != 'custom_section'
|
212
|
+
CustomSection.new.configure(e)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
207
217
|
module Overwrite
|
208
218
|
class Base
|
209
219
|
include Fluent::Configurable
|
@@ -564,12 +574,12 @@ module Fluent::Config
|
|
564
574
|
|
565
575
|
sub_test_case 'default values should be duplicated before touched in plugin code' do
|
566
576
|
test 'default object should be dupped for cases configured twice' do
|
567
|
-
x6a = ConfigurableSpec::
|
577
|
+
x6a = ConfigurableSpec::ExampleWithDefaultHashAndArray.new
|
568
578
|
assert_nothing_raised { x6a.configure(config_element("")) }
|
569
579
|
assert_equal({}, x6a.obj1)
|
570
580
|
assert_equal([], x6a.obj2)
|
571
581
|
|
572
|
-
x6b = ConfigurableSpec::
|
582
|
+
x6b = ConfigurableSpec::ExampleWithDefaultHashAndArray.new
|
573
583
|
assert_nothing_raised { x6b.configure(config_element("")) }
|
574
584
|
assert_equal({}, x6b.obj1)
|
575
585
|
assert_equal([], x6b.obj2)
|
@@ -577,7 +587,7 @@ module Fluent::Config
|
|
577
587
|
assert { x6a.obj1.object_id != x6b.obj1.object_id }
|
578
588
|
assert { x6a.obj2.object_id != x6b.obj2.object_id }
|
579
589
|
|
580
|
-
x6c = ConfigurableSpec::
|
590
|
+
x6c = ConfigurableSpec::ExampleWithDefaultHashAndArray.new
|
581
591
|
assert_nothing_raised { x6c.configure(config_element("")) }
|
582
592
|
assert_equal({}, x6c.obj1)
|
583
593
|
assert_equal([], x6c.obj2)
|
@@ -1184,7 +1194,7 @@ module Fluent::Config
|
|
1184
1194
|
sub_test_case 'class defined with config_param/config_section having :alias' do
|
1185
1195
|
sub_test_case '#initialize' do
|
1186
1196
|
test 'does not create methods for alias' do
|
1187
|
-
ex1 = ConfigurableSpec::
|
1197
|
+
ex1 = ConfigurableSpec::ExampleWithAlias.new
|
1188
1198
|
assert_nothing_raised { ex1.name }
|
1189
1199
|
assert_raise(NoMethodError) { ex1.fullname }
|
1190
1200
|
assert_nothing_raised { ex1.bool }
|
@@ -1196,7 +1206,7 @@ module Fluent::Config
|
|
1196
1206
|
|
1197
1207
|
sub_test_case '#configure' do
|
1198
1208
|
test 'provides accessible data for alias attribute keys' do
|
1199
|
-
ex1 = ConfigurableSpec::
|
1209
|
+
ex1 = ConfigurableSpec::ExampleWithAlias.new
|
1200
1210
|
conf = config_element('ROOT', '', {
|
1201
1211
|
"fullname" => "foo bar",
|
1202
1212
|
"bool" => false
|
@@ -1288,7 +1298,7 @@ module Fluent::Config
|
|
1288
1298
|
'secret_param' => 'secret'
|
1289
1299
|
},
|
1290
1300
|
[config_element('section', '', {'normal_param2' => 'normal', 'secret_param2' => 'secret'} )])
|
1291
|
-
@example = ConfigurableSpec::
|
1301
|
+
@example = ConfigurableSpec::ExampleWithSecret.new
|
1292
1302
|
@example.configure(@conf)
|
1293
1303
|
end
|
1294
1304
|
|
@@ -1311,20 +1321,6 @@ module Fluent::Config
|
|
1311
1321
|
}
|
1312
1322
|
end
|
1313
1323
|
|
1314
|
-
test 'get plugin name when found unknown section' do
|
1315
|
-
@conf = config_element('ROOT', '',
|
1316
|
-
{
|
1317
|
-
'normal_param' => 'normal',
|
1318
|
-
'secret_param' => 'secret'
|
1319
|
-
},
|
1320
|
-
[config_element('unknown', '', {'normal_param2' => 'normal', 'secret_param2' => 'secret'} )])
|
1321
|
-
@example = ConfigurableSpec::Example5.new
|
1322
|
-
@example.configure(@conf)
|
1323
|
-
@conf.elements.each { |e|
|
1324
|
-
assert_equal(['ROOT', nil], e.unused_in)
|
1325
|
-
}
|
1326
|
-
end
|
1327
|
-
|
1328
1324
|
def assert_secret_param(key, value)
|
1329
1325
|
case key
|
1330
1326
|
when 'normal_param', 'normal_param2'
|
@@ -1335,9 +1331,51 @@ module Fluent::Config
|
|
1335
1331
|
end
|
1336
1332
|
end
|
1337
1333
|
|
1334
|
+
sub_test_case 'unused section' do
|
1335
|
+
test 'get plugin name when found unknown section' do
|
1336
|
+
conf = config_element('ROOT', '',
|
1337
|
+
{
|
1338
|
+
'name_param' => 'name',
|
1339
|
+
},
|
1340
|
+
[config_element('unknown', '', {'name_param' => 'normal'} )])
|
1341
|
+
example = ConfigurableSpec::ExampleWithCustomSection.new
|
1342
|
+
example.configure(conf)
|
1343
|
+
conf.elements.each { |e|
|
1344
|
+
assert_equal(['ROOT', nil], e.unused_in)
|
1345
|
+
}
|
1346
|
+
end
|
1347
|
+
|
1348
|
+
test 'get an empty array when the section is defined without using config_section' do
|
1349
|
+
conf = config_element('ROOT', '',
|
1350
|
+
{
|
1351
|
+
'name_param' => 'name',
|
1352
|
+
},
|
1353
|
+
[config_element('custom_section', '', {'custom_section_param' => 'custom'} )])
|
1354
|
+
example = ConfigurableSpec::ExampleWithCustomSection.new
|
1355
|
+
example.configure(conf)
|
1356
|
+
conf.elements.each { |e|
|
1357
|
+
assert_equal([], e.unused_in)
|
1358
|
+
}
|
1359
|
+
end
|
1360
|
+
|
1361
|
+
test 'get an empty array when the configuration is used in another element without any sections' do
|
1362
|
+
conf = config_element('ROOT', '',
|
1363
|
+
{
|
1364
|
+
'name_param' => 'name',
|
1365
|
+
},
|
1366
|
+
[config_element('normal_section', '', {'normal_section_param' => 'normal'} )])
|
1367
|
+
example = ConfigurableSpec::ExampleWithCustomSection.new
|
1368
|
+
example.configure(conf)
|
1369
|
+
ConfigurableSpec::ExampleWithCustomSection::AnotherElement.new.configure(conf)
|
1370
|
+
conf.elements.each { |e|
|
1371
|
+
assert_equal([], e.unused_in)
|
1372
|
+
}
|
1373
|
+
end
|
1374
|
+
end
|
1375
|
+
|
1338
1376
|
sub_test_case ':skip_accessor option' do
|
1339
1377
|
test 'it does not create accessor methods for parameters' do
|
1340
|
-
@example = ConfigurableSpec::
|
1378
|
+
@example = ConfigurableSpec::ExampleWithSkipAccessor.new
|
1341
1379
|
@example.configure(config_element('ROOT'))
|
1342
1380
|
assert_equal 'example7', @example.instance_variable_get(:@name)
|
1343
1381
|
assert_raise NoMethodError.new("undefined method `name' for #{@example}") do
|
data/test/counter/test_store.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'timecop'
|
2
|
+
|
3
|
+
module Process
|
4
|
+
class << self
|
5
|
+
alias_method :clock_gettime_original, :clock_gettime
|
6
|
+
|
7
|
+
def clock_gettime(clock_id, unit = :float_second)
|
8
|
+
# now only support CLOCK_REALTIME
|
9
|
+
if Process::CLOCK_REALTIME == clock_id
|
10
|
+
t = Time.now
|
11
|
+
|
12
|
+
case unit
|
13
|
+
when :float_second
|
14
|
+
t.to_i + t.nsec / 1_000_000_000.0
|
15
|
+
when :float_millisecond
|
16
|
+
t.to_i * 1_000 + t.nsec / 1_000_000.0
|
17
|
+
when :float_microsecond
|
18
|
+
t.to_i * 1_000_000 + t.nsec / 1_000.0
|
19
|
+
when :second
|
20
|
+
t.to_i
|
21
|
+
when :millisecond
|
22
|
+
t.to_i * 1000 + t.nsec / 1_000_000
|
23
|
+
when :microsecond
|
24
|
+
t.to_i * 1_000_000 + t.nsec / 1_000
|
25
|
+
when :nanosecond
|
26
|
+
t.to_i * 1_000_000_000 + t.nsec
|
27
|
+
end
|
28
|
+
else
|
29
|
+
Process.clock_gettime_original(clock_id, unit)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require_relative '../../helper'
|
2
|
+
require 'fluent/test/driver/output'
|
3
|
+
require 'flexmock/test_unit'
|
4
|
+
|
5
|
+
require 'fluent/plugin/out_forward'
|
6
|
+
require 'fluent/plugin/out_forward/ack_handler'
|
7
|
+
|
8
|
+
class AckHandlerTest < Test::Unit::TestCase
|
9
|
+
data(
|
10
|
+
'chunk_id is matched' => [MessagePack.pack({ 'ack' => Base64.encode64('chunk_id 111') }), Fluent::Plugin::ForwardOutput::AckHandler::Result::SUCCESS],
|
11
|
+
'chunk_id is not matched' => [MessagePack.pack({ 'ack' => 'unmatched' }), Fluent::Plugin::ForwardOutput::AckHandler::Result::CHUNKID_UNMATCHED],
|
12
|
+
'chunk_id is empty' => ['', Fluent::Plugin::ForwardOutput::AckHandler::Result::FAILED],
|
13
|
+
)
|
14
|
+
test 'returns chunk_id, node, sock and result status' do |args|
|
15
|
+
receved, state = args
|
16
|
+
ack_handler = Fluent::Plugin::ForwardOutput::AckHandler.new(timeout: 10, log: $log, read_length: 100)
|
17
|
+
|
18
|
+
node = flexmock('node', host: '127.0.0.1', port: '1000') # for log
|
19
|
+
chunk_id = 'chunk_id 111'
|
20
|
+
ack = ack_handler.create_ack(chunk_id, node)
|
21
|
+
|
22
|
+
r, w = IO.pipe
|
23
|
+
begin
|
24
|
+
w.write(chunk_id)
|
25
|
+
mock(r).recv(anything) { |_| receved } # IO does not have recv
|
26
|
+
ack.enqueue(r)
|
27
|
+
|
28
|
+
a1 = a2 = a3 = a4 = nil
|
29
|
+
ack_handler.collect_response(1) do |cid, n, s, ret|
|
30
|
+
# This block is rescued by ack_handler so it needs to invoke assetion outside of this block
|
31
|
+
a1 = cid; a2 = n; a3 = s; a4 = ret
|
32
|
+
end
|
33
|
+
|
34
|
+
assert_equal chunk_id, a1
|
35
|
+
assert_equal node, a2
|
36
|
+
assert_equal r, a3
|
37
|
+
assert_equal state, a4
|
38
|
+
ensure
|
39
|
+
r.close rescue nil
|
40
|
+
w.close rescue nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
test 'returns nil if raise an error' do
|
45
|
+
ack_handler = Fluent::Plugin::ForwardOutput::AckHandler.new(timeout: 10, log: $log, read_length: 100)
|
46
|
+
|
47
|
+
node = flexmock('node', host: '127.0.0.1', port: '1000') # for log
|
48
|
+
chunk_id = 'chunk_id 111'
|
49
|
+
ack = ack_handler.create_ack(chunk_id, node)
|
50
|
+
|
51
|
+
r, w = IO.pipe
|
52
|
+
begin
|
53
|
+
w.write(chunk_id)
|
54
|
+
mock(r).recv(anything) { |_| raise 'unexpected error' } # IO does not have recv
|
55
|
+
ack.enqueue(r)
|
56
|
+
|
57
|
+
a1 = a2 = a3 = a4 = nil
|
58
|
+
ack_handler.collect_response(1) do |cid, n, s, ret|
|
59
|
+
# This block is rescued by ack_handler so it needs to invoke assetion outside of this block
|
60
|
+
a1 = cid; a2 = n; a3 = s; a4 = ret
|
61
|
+
end
|
62
|
+
|
63
|
+
assert_nil a1
|
64
|
+
assert_nil a2
|
65
|
+
assert_nil a3
|
66
|
+
assert_equal Fluent::Plugin::ForwardOutput::AckHandler::Result::FAILED, a4
|
67
|
+
ensure
|
68
|
+
r.close rescue nil
|
69
|
+
w.close rescue nil
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
test 'when ack is expired' do
|
74
|
+
ack_handler = Fluent::Plugin::ForwardOutput::AckHandler.new(timeout: 0, log: $log, read_length: 100)
|
75
|
+
|
76
|
+
node = flexmock('node', host: '127.0.0.1', port: '1000') # for log
|
77
|
+
chunk_id = 'chunk_id 111'
|
78
|
+
ack = ack_handler.create_ack(chunk_id, node)
|
79
|
+
|
80
|
+
r, w = IO.pipe
|
81
|
+
begin
|
82
|
+
w.write(chunk_id)
|
83
|
+
mock(r).recv(anything).never
|
84
|
+
ack.enqueue(r)
|
85
|
+
|
86
|
+
a1 = a2 = a3 = a4 = nil
|
87
|
+
ack_handler.collect_response(1) do |cid, n, s, ret|
|
88
|
+
# This block is rescued by ack_handler so it needs to invoke assetion outside of this block
|
89
|
+
a1 = cid; a2 = n; a3 = s; a4 = ret
|
90
|
+
end
|
91
|
+
|
92
|
+
assert_equal chunk_id, a1
|
93
|
+
assert_equal node, a2
|
94
|
+
assert_equal r, a3
|
95
|
+
assert_equal Fluent::Plugin::ForwardOutput::AckHandler::Result::FAILED, a4
|
96
|
+
ensure
|
97
|
+
r.close rescue nil
|
98
|
+
w.close rescue nil
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|