fluentd 0.12.7 → 0.12.8
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 +18 -0
- data/lib/fluent/config/configure_proxy.rb +54 -2
- data/lib/fluent/config/literal_parser.rb +1 -1
- data/lib/fluent/output.rb +8 -8
- data/lib/fluent/plugin/filter_record_transformer.rb +1 -1
- data/lib/fluent/plugin/out_forward.rb +6 -4
- data/lib/fluent/version.rb +1 -1
- data/test/config/test_configurable.rb +124 -2
- data/test/config/test_literal_parser.rb +2 -0
- data/test/plugin/test_filter_record_transformer.rb +30 -0
- data/test/plugin/test_out_forward.rb +49 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 67639a7dc51e74c0269b78897487a90bd0acf29b
|
4
|
+
data.tar.gz: 43fd091c294a06a0d88eea360a7efd5b215d5577
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1357f9b5a372172f9e6441dafdb106d8fa2e6756d3bb23c54b0d16c1e8888fc97e75b5ebbf94aac7ae589d48d42af6b08968653de0309cc8a9efe6b2a9ade81d
|
7
|
+
data.tar.gz: 00d88127b76af84ba10b1830c0be4861047a571cb953dfd63c7887d145ca8752fb8a4a978b586159918356ee57f6b7b00190295d9a6509467bd41791e8b63dfb
|
data/ChangeLog
CHANGED
@@ -1,5 +1,23 @@
|
|
1
1
|
# v0.12
|
2
2
|
|
3
|
+
## Release 0.12.8 - 2015/04/22
|
4
|
+
|
5
|
+
### New features / Enhancement
|
6
|
+
|
7
|
+
* output: Support millisecond for try_flush_interval and queued_chunk_flush_interval
|
8
|
+
https://github.com/fluent/fluentd/pull/568
|
9
|
+
* filter_record_transformer: Support fields which start with @
|
10
|
+
https://github.com/fluent/fluentd/pull/574
|
11
|
+
* config: Add final attribute to prevent config overwritten by subclass
|
12
|
+
https://github.com/fluent/fluentd/pull/583
|
13
|
+
|
14
|
+
### Bug fixes
|
15
|
+
|
16
|
+
* config: fix embedded code parsing
|
17
|
+
https://github.com/fluent/fluentd/pull/564
|
18
|
+
* out_forward: Resend chunks on dropped connection when wait ACK
|
19
|
+
https://github.com/fluent/fluentd/pull/580
|
20
|
+
|
3
21
|
## Release 0.12.7 - 2015/03/22
|
4
22
|
|
5
23
|
### New features / Enhancement
|
@@ -17,7 +17,7 @@
|
|
17
17
|
module Fluent
|
18
18
|
module Config
|
19
19
|
class ConfigureProxy
|
20
|
-
attr_accessor :name, :param_name, :required, :multi, :alias, :argument, :params, :defaults, :sections
|
20
|
+
attr_accessor :name, :final, :param_name, :required, :multi, :alias, :argument, :params, :defaults, :sections
|
21
21
|
# config_param :desc, :string, :default => '....'
|
22
22
|
# config_set_default :buffer_type, :memory
|
23
23
|
#
|
@@ -38,6 +38,7 @@ module Fluent
|
|
38
38
|
|
39
39
|
def initialize(name, opts = {})
|
40
40
|
@name = name.to_sym
|
41
|
+
@final = opts.fetch(:final, false)
|
41
42
|
|
42
43
|
@param_name = (opts[:param_name] || @name).to_sym
|
43
44
|
@required = opts[:required]
|
@@ -58,7 +59,13 @@ module Fluent
|
|
58
59
|
@multi.nil? ? true : @multi
|
59
60
|
end
|
60
61
|
|
62
|
+
def final?
|
63
|
+
@final
|
64
|
+
end
|
65
|
+
|
61
66
|
def merge(other) # self is base class, other is subclass
|
67
|
+
return merge_for_finalized(other) if self.final?
|
68
|
+
|
62
69
|
options = {
|
63
70
|
param_name: other.param_name,
|
64
71
|
required: (other.required.nil? ? self.required : other.required),
|
@@ -69,7 +76,52 @@ module Fluent
|
|
69
76
|
merged.argument = other.argument || self.argument
|
70
77
|
merged.params = self.params.merge(other.params)
|
71
78
|
merged.defaults = self.defaults.merge(other.defaults)
|
72
|
-
merged.sections =
|
79
|
+
merged.sections = {}
|
80
|
+
(self.sections.keys + other.sections.keys).uniq.each do |section_key|
|
81
|
+
self_section = self.sections[section_key]
|
82
|
+
other_section = other.sections[section_key]
|
83
|
+
merged_section = if self_section && other_section
|
84
|
+
self_section.merge(other_section)
|
85
|
+
elsif self_section || other_section
|
86
|
+
self_section || other_section
|
87
|
+
else
|
88
|
+
raise "BUG: both of self and other section are nil"
|
89
|
+
end
|
90
|
+
merged.sections[section_key] = merged_section
|
91
|
+
end
|
92
|
+
|
93
|
+
merged
|
94
|
+
end
|
95
|
+
|
96
|
+
def merge_for_finalized(other)
|
97
|
+
# list what subclass can do for finalized section
|
98
|
+
# * overwrite param_name to escape duplicated name of instance variable
|
99
|
+
# * append params/defaults/sections which are missing in superclass
|
100
|
+
|
101
|
+
options = {
|
102
|
+
param_name: other.param_name,
|
103
|
+
required: (self.required.nil? ? other.required : self.required),
|
104
|
+
multi: (self.multi.nil? ? other.multi : self.multi),
|
105
|
+
final: true,
|
106
|
+
}
|
107
|
+
merged = self.class.new(other.name, options)
|
108
|
+
|
109
|
+
merged.argument = self.argument || other.argument
|
110
|
+
merged.params = other.params.merge(self.params)
|
111
|
+
merged.defaults = other.defaults.merge(self.defaults)
|
112
|
+
merged.sections = {}
|
113
|
+
(self.sections.keys + other.sections.keys).uniq.each do |section_key|
|
114
|
+
self_section = self.sections[section_key]
|
115
|
+
other_section = other.sections[section_key]
|
116
|
+
merged_section = if self_section && other_section
|
117
|
+
other_section.merge(self_section)
|
118
|
+
elsif self_section || other_section
|
119
|
+
self_section || other_section
|
120
|
+
else
|
121
|
+
raise "BUG: both of self and other section are nil"
|
122
|
+
end
|
123
|
+
merged.sections[section_key] = merged_section
|
124
|
+
end
|
73
125
|
|
74
126
|
merged
|
75
127
|
end
|
data/lib/fluent/output.rb
CHANGED
@@ -98,7 +98,7 @@ module Fluent
|
|
98
98
|
def initialize(output)
|
99
99
|
@output = output
|
100
100
|
@finish = false
|
101
|
-
@next_time =
|
101
|
+
@next_time = Time.now.to_f + 1.0
|
102
102
|
end
|
103
103
|
|
104
104
|
def configure(conf)
|
@@ -132,7 +132,7 @@ module Fluent
|
|
132
132
|
@mutex.lock
|
133
133
|
begin
|
134
134
|
until @finish
|
135
|
-
time =
|
135
|
+
time = Time.now.to_f
|
136
136
|
|
137
137
|
if @next_time <= time
|
138
138
|
@mutex.unlock
|
@@ -141,7 +141,7 @@ module Fluent
|
|
141
141
|
ensure
|
142
142
|
@mutex.lock
|
143
143
|
end
|
144
|
-
next_wait = @next_time -
|
144
|
+
next_wait = @next_time - Time.now.to_f
|
145
145
|
else
|
146
146
|
next_wait = @next_time - time
|
147
147
|
end
|
@@ -231,7 +231,7 @@ module Fluent
|
|
231
231
|
end
|
232
232
|
|
233
233
|
def start
|
234
|
-
@next_flush_time =
|
234
|
+
@next_flush_time = Time.now.to_f + @flush_interval
|
235
235
|
@buffer.start
|
236
236
|
@secondary.start if @secondary
|
237
237
|
@writers.each {|writer| writer.start }
|
@@ -280,10 +280,10 @@ module Fluent
|
|
280
280
|
end
|
281
281
|
|
282
282
|
def try_flush
|
283
|
-
time =
|
283
|
+
time = Time.now.to_f
|
284
284
|
|
285
285
|
empty = @buffer.queue_size == 0
|
286
|
-
if empty && @next_flush_time < (now =
|
286
|
+
if empty && @next_flush_time < (now = Time.now.to_f)
|
287
287
|
@buffer.synchronize do
|
288
288
|
if @next_flush_time < now
|
289
289
|
enqueue_buffer
|
@@ -330,7 +330,7 @@ module Fluent
|
|
330
330
|
end
|
331
331
|
|
332
332
|
if has_next
|
333
|
-
return
|
333
|
+
return Time.now.to_f + @queued_chunk_flush_interval
|
334
334
|
else
|
335
335
|
return time + @try_flush_interval
|
336
336
|
end
|
@@ -385,7 +385,7 @@ module Fluent
|
|
385
385
|
|
386
386
|
def force_flush
|
387
387
|
@num_errors_lock.synchronize do
|
388
|
-
@next_retry_time =
|
388
|
+
@next_retry_time = Time.now.to_f - 1
|
389
389
|
end
|
390
390
|
enqueue_buffer(true)
|
391
391
|
submit_flush
|
@@ -179,7 +179,7 @@ module Fluent
|
|
179
179
|
end
|
180
180
|
|
181
181
|
def expand(str)
|
182
|
-
str.gsub(/(\${[
|
182
|
+
str.gsub(/(\${[^}]+}|__[A-Z_]+__)/) {
|
183
183
|
log.warn "unknown placeholder `#{$1}` found" unless @placeholders.include?($1)
|
184
184
|
@placeholders[$1]
|
185
185
|
}
|
@@ -298,10 +298,12 @@ module Fluent
|
|
298
298
|
raw_data = sock.recv(1024)
|
299
299
|
|
300
300
|
# When connection is closed by remote host, socket is ready to read and #recv returns an empty string that means EOF.
|
301
|
-
#
|
302
|
-
|
303
|
-
|
304
|
-
|
301
|
+
# If this happens we assume the data wasn't delivered and retry it.
|
302
|
+
if raw_data.empty?
|
303
|
+
@log.warn "node #{node.host}:#{node.port} closed the connection. regard it as unavailable."
|
304
|
+
node.disable!
|
305
|
+
raise ForwardOutputConnectionClosedError, "node #{node.host}:#{node.port} closed connection"
|
306
|
+
else
|
305
307
|
# Serialization type of the response is same as sent data.
|
306
308
|
res = MessagePack.unpack(raw_data)
|
307
309
|
|
data/lib/fluent/version.rb
CHANGED
@@ -100,14 +100,45 @@ module ConfigurableSpec
|
|
100
100
|
|
101
101
|
config_param :name, :string, alias: :fullname
|
102
102
|
config_param :bool, :bool, alias: :flag
|
103
|
-
config_section :detail, required:
|
104
|
-
config_param :address, :string
|
103
|
+
config_section :detail, required: false, multi: false, alias: "information" do
|
104
|
+
config_param :address, :string, default: "x"
|
105
105
|
end
|
106
106
|
|
107
107
|
def get_all
|
108
108
|
[@name, @detail]
|
109
109
|
end
|
110
110
|
end
|
111
|
+
|
112
|
+
class Example2 < Example1
|
113
|
+
config_section :detail, required: true, multi: false, alias: "information2" do
|
114
|
+
config_param :address, :string, default: "y"
|
115
|
+
config_param :phone_no, :string
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
class Example3
|
120
|
+
include Fluent::Configurable
|
121
|
+
|
122
|
+
config_param :age, :integer, default: 10
|
123
|
+
|
124
|
+
config_section :appendix, required: true, multi: false, final: true do
|
125
|
+
config_param :type, :string
|
126
|
+
config_param :name, :string, default: "x"
|
127
|
+
end
|
128
|
+
|
129
|
+
def get_all
|
130
|
+
[@name, @detail]
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
class Example4 < Example3
|
135
|
+
config_param :age, :integer, default: 20
|
136
|
+
|
137
|
+
config_section :appendix, required: false, multi: false, final: false do
|
138
|
+
config_param :name, :string, default: "y"
|
139
|
+
config_param :age, :integer, default: 10
|
140
|
+
end
|
141
|
+
end
|
111
142
|
end
|
112
143
|
|
113
144
|
module Fluent::Config
|
@@ -493,6 +524,97 @@ module Fluent::Config
|
|
493
524
|
assert_false(ex5.boolvalue)
|
494
525
|
end
|
495
526
|
end
|
527
|
+
|
528
|
+
sub_test_case '.config_section' do
|
529
|
+
def e(name, arg = '', attrs = {}, elements = [])
|
530
|
+
attrs_str_keys = {}
|
531
|
+
attrs.each{|key, value| attrs_str_keys[key.to_s] = value }
|
532
|
+
Fluent::Config::Element.new(name, arg, attrs_str_keys, elements)
|
533
|
+
end
|
534
|
+
|
535
|
+
test 'subclass configuration spec can overwrite superclass specs' do
|
536
|
+
# conf0 = e('ROOT', '', {}, [])
|
537
|
+
|
538
|
+
conf1 = e('ROOT', '', {
|
539
|
+
'name' => 'tagomoris',
|
540
|
+
'bool' => true,
|
541
|
+
},
|
542
|
+
)
|
543
|
+
# <detail> section is required by overwriting of Example2 config_section spec
|
544
|
+
assert_nothing_raised { ConfigurableSpec::Example1.new.configure(conf1) }
|
545
|
+
assert_raise(Fluent::ConfigError.new("'<detail>' sections are required")) { ConfigurableSpec::Example2.new.configure(conf1) }
|
546
|
+
|
547
|
+
conf2 = e('ROOT', '', {
|
548
|
+
'name' => 'tagomoris',
|
549
|
+
'bool' => true,
|
550
|
+
},
|
551
|
+
[e('detail', '', { 'phone_no' => "+81-00-0000-0000" }, [])],
|
552
|
+
)
|
553
|
+
# <detail> address </detail> default is overwritten by Example2
|
554
|
+
assert_nothing_raised { ConfigurableSpec::Example1.new.configure(conf2) }
|
555
|
+
assert_nothing_raised { ConfigurableSpec::Example2.new.configure(conf2) }
|
556
|
+
ex1 = ConfigurableSpec::Example1.new.configure(conf2)
|
557
|
+
assert_equal "x", ex1.detail.address
|
558
|
+
ex2 = ConfigurableSpec::Example2.new.configure(conf2)
|
559
|
+
assert_equal "y", ex2.detail.address
|
560
|
+
|
561
|
+
conf3 = e('ROOT', '', {
|
562
|
+
'name' => 'tagomoris',
|
563
|
+
'bool' => true,
|
564
|
+
},
|
565
|
+
[e('detail', '', { 'address' => "Chiyoda Tokyo Japan" }, [])],
|
566
|
+
)
|
567
|
+
# <detail> phone_no </detail> is required by Example2 config_param spec
|
568
|
+
assert_nothing_raised { ConfigurableSpec::Example1.new.configure(conf3) }
|
569
|
+
assert_raise(Fluent::ConfigError.new("'phone_no' parameter is required, in section detail")) { ConfigurableSpec::Example2.new.configure(conf3) }
|
570
|
+
|
571
|
+
conf4 = e('ROOT', '', {
|
572
|
+
'name' => 'tagomoris',
|
573
|
+
'bool' => true,
|
574
|
+
},
|
575
|
+
[e('detail', '', { 'address' => "Chiyoda Tokyo Japan", 'phone_no' => '+81-00-0000-0000' }, [])],
|
576
|
+
)
|
577
|
+
assert_nothing_raised { ConfigurableSpec::Example1.new.configure(conf4) } # phone_no is not used
|
578
|
+
assert_nothing_raised { ConfigurableSpec::Example2.new.configure(conf4) }
|
579
|
+
|
580
|
+
ex2 = ConfigurableSpec::Example2.new.configure(conf4)
|
581
|
+
assert_equal "Chiyoda Tokyo Japan", ex2.detail.address
|
582
|
+
assert_equal "+81-00-0000-0000", ex2.detail.phone_no
|
583
|
+
end
|
584
|
+
|
585
|
+
test 'adds only config_param definitions into configuration without overwriting existing finalized configuration elements' do
|
586
|
+
|
587
|
+
conf1 = e('ROOT', '', {}, [])
|
588
|
+
# <appendix> is required by Example3 and its not be overwritten by Example4
|
589
|
+
assert_raise(Fluent::ConfigError.new("'<appendix>' sections are required")) { ConfigurableSpec::Example3.new.configure(conf1) }
|
590
|
+
assert_raise(Fluent::ConfigError.new("'<appendix>' sections are required")) { ConfigurableSpec::Example4.new.configure(conf1) }
|
591
|
+
|
592
|
+
conf2 = e('ROOT', '', {
|
593
|
+
},
|
594
|
+
[e('appendix', '', {'type' => '1'}, [])],
|
595
|
+
)
|
596
|
+
# default value of age is overwritten by Example4, because root proxy is not finalized
|
597
|
+
ex3 = ConfigurableSpec::Example3.new.configure(conf2)
|
598
|
+
assert_equal 10, ex3.age
|
599
|
+
assert_equal '1', ex3.appendix.type
|
600
|
+
ex4 = ConfigurableSpec::Example4.new.configure(conf2)
|
601
|
+
assert_equal 20, ex4.age
|
602
|
+
assert_equal '1', ex4.appendix.type
|
603
|
+
|
604
|
+
conf3 = e('ROOT', '', {},
|
605
|
+
[e('appendix', '', {'type' => '2'}, [])],
|
606
|
+
)
|
607
|
+
# default value of <appendix> name </appendix> cannot be overwritten because it is finalized
|
608
|
+
ex3 = ConfigurableSpec::Example3.new.configure(conf2)
|
609
|
+
assert_equal 10, ex3.age
|
610
|
+
assert_equal '1', ex3.appendix.type
|
611
|
+
ex4 = ConfigurableSpec::Example4.new.configure(conf2)
|
612
|
+
assert_equal 20, ex4.age
|
613
|
+
assert_equal '1', ex4.appendix.type
|
614
|
+
# <appendix> age </appendix> can be added because it is missing in superclass spec
|
615
|
+
assert_equal 10, ex4.appendix.age
|
616
|
+
end
|
617
|
+
end
|
496
618
|
end
|
497
619
|
|
498
620
|
sub_test_case 'class defined with config_param/config_section having :alias' do
|
@@ -228,6 +228,8 @@ module Fluent::Config
|
|
228
228
|
test('"#{"}"}"') { assert_text_parsed_as("}", '"#{"}"}"') }
|
229
229
|
test('"#{#}"') { assert_parse_error('"#{#}"') } # error in embedded ruby code
|
230
230
|
test("\"\#{\n=begin\n}\"") { assert_parse_error("\"\#{\n=begin\n}\"") } # error in embedded ruby code
|
231
|
+
test('"#{v1}foo#{v2}"') { assert_text_parsed_as("#{v1}foo#{v2}", '"#{v1}foo#{v2}"') }
|
232
|
+
test('"#{1+1}foo#{2+2}bar"') { assert_text_parsed_as("#{1+1}foo#{2+2}bar", '"#{1+1}foo#{2+2}bar"') }
|
231
233
|
end
|
232
234
|
|
233
235
|
sub_test_case 'array parsing' do
|
@@ -343,5 +343,35 @@ class RecordTransformerFilterTest < Test::Unit::TestCase
|
|
343
343
|
assert_nil(r['message'])
|
344
344
|
end
|
345
345
|
end
|
346
|
+
|
347
|
+
test 'expand fields starting with @ (enable_ruby no)' do
|
348
|
+
config = %[
|
349
|
+
enable_ruby no
|
350
|
+
<record>
|
351
|
+
foo ${@timestamp}
|
352
|
+
</record>
|
353
|
+
]
|
354
|
+
d = create_driver(config)
|
355
|
+
message = {"@timestamp" => "foo"}
|
356
|
+
es = d.run { d.emit(message, @time) }.filtered
|
357
|
+
es.each do |t, r|
|
358
|
+
assert_equal(message["@timestamp"], r['foo'])
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
test 'expand fields starting with @ (enable_ruby yes)' do
|
363
|
+
config = %[
|
364
|
+
enable_ruby yes
|
365
|
+
<record>
|
366
|
+
foo ${__send__("@timestamp")}
|
367
|
+
</record>
|
368
|
+
]
|
369
|
+
d = create_driver(config)
|
370
|
+
message = {"@timestamp" => "foo"}
|
371
|
+
es = d.run { d.emit(message, @time) }.filtered
|
372
|
+
es.each do |t, r|
|
373
|
+
assert_equal(message["@timestamp"], r['foo'])
|
374
|
+
end
|
375
|
+
end
|
346
376
|
end
|
347
377
|
end
|
@@ -186,6 +186,7 @@ class ForwardOutputTest < Test::Unit::TestCase
|
|
186
186
|
end
|
187
187
|
|
188
188
|
def test_require_a_node_not_supporting_responses_to_respond_with_ack
|
189
|
+
# in_forward, that doesn't support ack feature, and keep connection alive
|
189
190
|
target_input_driver = create_target_input_driver
|
190
191
|
|
191
192
|
d = create_driver(CONFIG + %[
|
@@ -203,6 +204,7 @@ class ForwardOutputTest < Test::Unit::TestCase
|
|
203
204
|
d.register_run_post_condition do
|
204
205
|
d.instance.responses.length == 1
|
205
206
|
end
|
207
|
+
d.run_timeout = 2
|
206
208
|
|
207
209
|
target_input_driver.run do
|
208
210
|
d.run do
|
@@ -223,7 +225,48 @@ class ForwardOutputTest < Test::Unit::TestCase
|
|
223
225
|
assert_equal 1, d.instance.exceptions.size
|
224
226
|
end
|
225
227
|
|
226
|
-
|
228
|
+
# bdf1f4f104c00a791aa94dc20087fe2011e1fd83
|
229
|
+
def test_require_a_node_not_supporting_responses_2_to_respond_with_ack
|
230
|
+
# in_forward, that doesn't support ack feature, and disconnect immediately
|
231
|
+
target_input_driver = create_target_input_driver(false, true)
|
232
|
+
|
233
|
+
d = create_driver(CONFIG + %[
|
234
|
+
flush_interval 1s
|
235
|
+
require_ack_response true
|
236
|
+
ack_response_timeout 5s
|
237
|
+
])
|
238
|
+
|
239
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
240
|
+
|
241
|
+
records = [
|
242
|
+
{"a" => 1},
|
243
|
+
{"a" => 2}
|
244
|
+
]
|
245
|
+
d.register_run_post_condition do
|
246
|
+
d.instance.responses.length == 1
|
247
|
+
end
|
248
|
+
d.run_timeout = 2
|
249
|
+
|
250
|
+
target_input_driver.run do
|
251
|
+
d.run do
|
252
|
+
records.each do |record|
|
253
|
+
d.emit record, time
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
emits = target_input_driver.emits
|
259
|
+
assert_equal ['test', time, records[0]], emits[0]
|
260
|
+
assert_equal ['test', time, records[1]], emits[1]
|
261
|
+
|
262
|
+
assert_equal 0, d.instance.responses.size
|
263
|
+
assert_equal 1, d.instance.exceptions.size # send_data() fails and to be retried
|
264
|
+
|
265
|
+
node = d.instance.nodes.first
|
266
|
+
assert_equal false, node.available # node is regarded as unavailable when unexpected EOF
|
267
|
+
end
|
268
|
+
|
269
|
+
def create_target_input_driver(do_respond=false, disconnect=false, conf=TARGET_CONFIG)
|
227
270
|
require 'fluent/plugin/in_forward'
|
228
271
|
|
229
272
|
DummyEngineDriver.new(Fluent::ForwardInput) {
|
@@ -265,9 +308,13 @@ class ForwardOutputTest < Test::Unit::TestCase
|
|
265
308
|
# chunk_counter is reset to zero only after all the data have been received and successfully deserialized.
|
266
309
|
break if handler.chunk_counter == 0
|
267
310
|
end
|
311
|
+
if disconnect
|
312
|
+
handler.close
|
313
|
+
sock = nil
|
314
|
+
end
|
268
315
|
sleep # wait for connection to be closed by client
|
269
316
|
ensure
|
270
|
-
sock.close
|
317
|
+
sock.close if sock
|
271
318
|
end
|
272
319
|
end
|
273
320
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluentd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.12.
|
4
|
+
version: 0.12.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sadayuki Furuhashi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-04-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: msgpack
|