fluentd 0.14.17-x64-mingw32 → 1.3.1-x64-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/.travis.yml +16 -5
- data/ADOPTERS.md +5 -0
- data/{ChangeLog → CHANGELOG.md} +495 -6
- data/CONTRIBUTING.md +5 -2
- data/GOVERNANCE.md +55 -0
- data/LICENSE +202 -0
- data/MAINTAINERS.md +7 -5
- data/README.md +17 -10
- data/bin/fluent-ca-generate +6 -0
- data/example/counter.conf +18 -0
- data/example/secondary_file.conf +3 -2
- data/fluentd.gemspec +3 -3
- data/lib/fluent/agent.rb +1 -1
- data/lib/fluent/command/binlog_reader.rb +11 -2
- data/lib/fluent/command/ca_generate.rb +181 -0
- data/lib/fluent/command/cat.rb +28 -15
- data/lib/fluent/command/debug.rb +4 -4
- data/lib/fluent/command/fluentd.rb +2 -2
- data/lib/fluent/command/plugin_config_formatter.rb +24 -2
- data/lib/fluent/command/plugin_generator.rb +26 -8
- data/lib/fluent/config/configure_proxy.rb +7 -1
- data/lib/fluent/config/dsl.rb +8 -5
- data/lib/fluent/config/element.rb +5 -0
- data/lib/fluent/config/literal_parser.rb +7 -1
- data/lib/fluent/config/types.rb +28 -2
- data/lib/fluent/config/v1_parser.rb +1 -2
- data/lib/fluent/configurable.rb +1 -0
- data/lib/fluent/counter.rb +23 -0
- data/lib/fluent/counter/base_socket.rb +46 -0
- data/lib/fluent/counter/client.rb +297 -0
- data/lib/fluent/counter/error.rb +86 -0
- data/lib/fluent/counter/mutex_hash.rb +163 -0
- data/lib/fluent/counter/server.rb +273 -0
- data/lib/fluent/counter/store.rb +205 -0
- data/lib/fluent/counter/validator.rb +145 -0
- data/lib/fluent/env.rb +1 -0
- data/lib/fluent/event_router.rb +1 -1
- data/lib/fluent/log.rb +119 -29
- data/lib/fluent/plugin/base.rb +12 -0
- data/lib/fluent/plugin/buf_file.rb +20 -16
- data/lib/fluent/plugin/buffer.rb +130 -32
- data/lib/fluent/plugin/buffer/file_chunk.rb +23 -4
- data/lib/fluent/plugin/compressable.rb +1 -1
- data/lib/fluent/plugin/filter_grep.rb +135 -21
- data/lib/fluent/plugin/filter_parser.rb +13 -2
- data/lib/fluent/plugin/filter_record_transformer.rb +16 -14
- data/lib/fluent/plugin/formatter_stdout.rb +3 -2
- data/lib/fluent/plugin/formatter_tsv.rb +5 -1
- data/lib/fluent/plugin/in_debug_agent.rb +8 -1
- data/lib/fluent/plugin/in_forward.rb +1 -1
- data/lib/fluent/plugin/in_http.rb +84 -3
- data/lib/fluent/plugin/in_monitor_agent.rb +7 -1
- data/lib/fluent/plugin/in_syslog.rb +31 -10
- data/lib/fluent/plugin/in_tail.rb +142 -53
- data/lib/fluent/plugin/in_tcp.rb +5 -6
- data/lib/fluent/plugin/in_udp.rb +6 -2
- data/lib/fluent/plugin/in_unix.rb +1 -1
- data/lib/fluent/plugin/multi_output.rb +1 -0
- data/lib/fluent/plugin/out_copy.rb +25 -2
- data/lib/fluent/plugin/out_file.rb +26 -7
- data/lib/fluent/plugin/out_forward.rb +81 -42
- data/lib/fluent/plugin/out_secondary_file.rb +2 -2
- data/lib/fluent/plugin/out_stdout.rb +0 -1
- data/lib/fluent/plugin/out_stream.rb +1 -1
- data/lib/fluent/plugin/output.rb +221 -57
- data/lib/fluent/plugin/parser_apache.rb +1 -1
- data/lib/fluent/plugin/parser_apache2.rb +5 -1
- data/lib/fluent/plugin/parser_apache_error.rb +1 -1
- data/lib/fluent/plugin/parser_json.rb +10 -3
- data/lib/fluent/plugin/parser_ltsv.rb +7 -0
- data/lib/fluent/plugin/parser_multiline.rb +2 -1
- data/lib/fluent/plugin/parser_nginx.rb +1 -1
- data/lib/fluent/plugin/parser_none.rb +1 -0
- data/lib/fluent/plugin/parser_regexp.rb +15 -14
- data/lib/fluent/plugin/parser_syslog.rb +9 -5
- data/lib/fluent/plugin_helper.rb +2 -0
- data/lib/fluent/plugin_helper/cert_option.rb +28 -9
- data/lib/fluent/plugin_helper/compat_parameters.rb +3 -1
- data/lib/fluent/plugin_helper/counter.rb +51 -0
- data/lib/fluent/plugin_helper/event_loop.rb +9 -0
- data/lib/fluent/plugin_helper/record_accessor.rb +210 -0
- data/lib/fluent/plugin_helper/retry_state.rb +15 -7
- data/lib/fluent/plugin_helper/server.rb +87 -25
- data/lib/fluent/plugin_helper/socket_option.rb +5 -2
- data/lib/fluent/plugin_helper/timer.rb +8 -7
- data/lib/fluent/root_agent.rb +18 -9
- data/lib/fluent/supervisor.rb +63 -23
- data/lib/fluent/system_config.rb +30 -2
- data/lib/fluent/test/helpers.rb +1 -1
- data/lib/fluent/time.rb +15 -7
- data/lib/fluent/timezone.rb +26 -2
- data/lib/fluent/version.rb +1 -1
- data/templates/new_gem/README.md.erb +2 -2
- data/templates/new_gem/lib/fluent/plugin/filter.rb.erb +1 -1
- data/templates/new_gem/lib/fluent/plugin/input.rb.erb +1 -1
- data/templates/new_gem/lib/fluent/plugin/output.rb.erb +1 -1
- data/templates/new_gem/lib/fluent/plugin/parser.rb.erb +4 -4
- data/test/command/test_ca_generate.rb +70 -0
- data/test/command/test_fluentd.rb +2 -2
- data/test/command/test_plugin_config_formatter.rb +8 -7
- data/test/command/test_plugin_generator.rb +65 -39
- data/test/config/test_config_parser.rb +7 -2
- data/test/config/test_configurable.rb +7 -2
- data/test/config/test_configure_proxy.rb +41 -3
- data/test/config/test_dsl.rb +10 -10
- data/test/config/test_element.rb +10 -0
- data/test/config/test_literal_parser.rb +8 -0
- data/test/config/test_plugin_configuration.rb +56 -0
- data/test/config/test_system_config.rb +19 -1
- data/test/config/test_types.rb +37 -0
- data/test/counter/test_client.rb +559 -0
- data/test/counter/test_error.rb +44 -0
- data/test/counter/test_mutex_hash.rb +179 -0
- data/test/counter/test_server.rb +589 -0
- data/test/counter/test_store.rb +258 -0
- data/test/counter/test_validator.rb +137 -0
- data/test/plugin/test_buf_file.rb +124 -0
- data/test/plugin/test_buffer.rb +3 -2
- data/test/plugin/test_filter_grep.rb +580 -2
- data/test/plugin/test_filter_parser.rb +33 -2
- data/test/plugin/test_filter_record_transformer.rb +22 -1
- data/test/plugin/test_formatter_ltsv.rb +3 -0
- data/test/plugin/test_formatter_tsv.rb +68 -0
- data/test/plugin/test_in_debug_agent.rb +21 -0
- data/test/plugin/test_in_exec.rb +3 -5
- data/test/plugin/test_in_http.rb +178 -0
- data/test/plugin/test_in_monitor_agent.rb +1 -1
- data/test/plugin/test_in_syslog.rb +64 -0
- data/test/plugin/test_in_tail.rb +116 -6
- data/test/plugin/test_in_tcp.rb +21 -0
- data/test/plugin/test_in_udp.rb +78 -0
- data/test/plugin/test_metadata.rb +89 -0
- data/test/plugin/test_out_copy.rb +31 -0
- data/test/plugin/test_out_file.rb +108 -2
- data/test/plugin/test_out_forward.rb +195 -2
- data/test/plugin/test_out_secondary_file.rb +14 -0
- data/test/plugin/test_output.rb +159 -45
- data/test/plugin/test_output_as_buffered.rb +19 -0
- data/test/plugin/test_output_as_buffered_backup.rb +307 -0
- data/test/plugin/test_output_as_buffered_retries.rb +70 -0
- data/test/plugin/test_output_as_buffered_secondary.rb +1 -1
- data/test/plugin/test_parser_apache2.rb +1 -0
- data/test/plugin/test_parser_labeled_tsv.rb +17 -0
- data/test/plugin/test_parser_nginx.rb +40 -0
- data/test/plugin/test_parser_regexp.rb +6 -7
- data/test/plugin/test_parser_syslog.rb +155 -5
- data/test/plugin_helper/test_child_process.rb +4 -4
- data/test/plugin_helper/test_compat_parameters.rb +22 -0
- data/test/plugin_helper/test_record_accessor.rb +197 -0
- data/test/plugin_helper/test_retry_state.rb +20 -0
- data/test/plugin_helper/test_server.rb +30 -2
- data/test/test_config.rb +3 -3
- data/test/test_configdsl.rb +2 -2
- data/test/test_log.rb +51 -1
- data/test/test_root_agent.rb +33 -0
- data/test/test_supervisor.rb +105 -0
- metadata +68 -8
- data/COPYING +0 -14
@@ -219,6 +219,24 @@ class BufferedOutputTest < Test::Unit::TestCase
|
|
219
219
|
Timecop.return
|
220
220
|
end
|
221
221
|
|
222
|
+
test 'queued_chunks_limit_size is same as flush_thread_count by default' do
|
223
|
+
hash = {'flush_thread_count' => 4}
|
224
|
+
i = create_output
|
225
|
+
i.register(:prefer_buffered_processing) { true }
|
226
|
+
i.configure(config_element('ROOT', '', {}, [config_element('buffer','tag',hash)]))
|
227
|
+
|
228
|
+
assert_equal 4, i.buffer.queued_chunks_limit_size
|
229
|
+
end
|
230
|
+
|
231
|
+
test 'prefer queued_chunks_limit_size parameter than flush_thread_count' do
|
232
|
+
hash = {'flush_thread_count' => 4, 'queued_chunks_limit_size' => 2}
|
233
|
+
i = create_output
|
234
|
+
i.register(:prefer_buffered_processing) { true }
|
235
|
+
i.configure(config_element('ROOT', '', {}, [config_element('buffer','tag',hash)]))
|
236
|
+
|
237
|
+
assert_equal 2, i.buffer.queued_chunks_limit_size
|
238
|
+
end
|
239
|
+
|
222
240
|
sub_test_case 'chunk feature in #write for output plugins' do
|
223
241
|
setup do
|
224
242
|
@stored_global_logger = $log
|
@@ -1064,6 +1082,7 @@ class BufferedOutputTest < Test::Unit::TestCase
|
|
1064
1082
|
'flush_thread_count' => 1,
|
1065
1083
|
'flush_thread_burst_interval' => 0.1,
|
1066
1084
|
'chunk_limit_size' => 1024,
|
1085
|
+
'queued_chunks_limit_size' => 100
|
1067
1086
|
}
|
1068
1087
|
@i = create_output(:buffered)
|
1069
1088
|
@i.configure(config_element('ROOT','',{},[config_element('buffer',chunk_key,hash)]))
|
@@ -0,0 +1,307 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
require 'fluent/plugin/output'
|
3
|
+
require 'fluent/plugin/buffer'
|
4
|
+
require 'fluent/event'
|
5
|
+
require 'fluent/error'
|
6
|
+
|
7
|
+
require 'json'
|
8
|
+
require 'time'
|
9
|
+
require 'timeout'
|
10
|
+
require 'timecop'
|
11
|
+
|
12
|
+
|
13
|
+
class BufferedOutputBackupTest < Test::Unit::TestCase
|
14
|
+
class BareOutput < Fluent::Plugin::Output
|
15
|
+
def register(name, &block)
|
16
|
+
instance_variable_set("@#{name}", block)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
class DummyOutput < BareOutput
|
20
|
+
def initialize
|
21
|
+
super
|
22
|
+
@process = nil
|
23
|
+
@format = nil
|
24
|
+
@write = nil
|
25
|
+
@try_write = nil
|
26
|
+
end
|
27
|
+
def prefer_buffered_processing
|
28
|
+
true
|
29
|
+
end
|
30
|
+
def prefer_delayed_commit
|
31
|
+
false
|
32
|
+
end
|
33
|
+
def process(tag, es)
|
34
|
+
@process ? @process.call(tag, es) : nil
|
35
|
+
end
|
36
|
+
def format(tag, time, record)
|
37
|
+
[tag, time.to_i, record].to_json + "\n"
|
38
|
+
end
|
39
|
+
def write(chunk)
|
40
|
+
@write ? @write.call(chunk) : nil
|
41
|
+
end
|
42
|
+
def try_write(chunk)
|
43
|
+
@try_write ? @try_write.call(chunk) : nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
class DummyOutputForSecondary < BareOutput
|
47
|
+
def initialize
|
48
|
+
super
|
49
|
+
@process = nil
|
50
|
+
@format = nil
|
51
|
+
@write = nil
|
52
|
+
@try_write = nil
|
53
|
+
end
|
54
|
+
def prefer_buffered_processing
|
55
|
+
true
|
56
|
+
end
|
57
|
+
def prefer_delayed_commit
|
58
|
+
false
|
59
|
+
end
|
60
|
+
def process(tag, es)
|
61
|
+
@process ? @process.call(tag, es) : nil
|
62
|
+
end
|
63
|
+
def format(tag, time, record)
|
64
|
+
[tag, time.to_i, record].to_json + "\n"
|
65
|
+
end
|
66
|
+
def write(chunk)
|
67
|
+
@write ? @write.call(chunk) : nil
|
68
|
+
end
|
69
|
+
def try_write(chunk)
|
70
|
+
@try_write ? @try_write.call(chunk) : nil
|
71
|
+
end
|
72
|
+
end
|
73
|
+
class DummyAsyncOutputForSecondary < BareOutput
|
74
|
+
def initialize
|
75
|
+
super
|
76
|
+
@process = nil
|
77
|
+
@format = nil
|
78
|
+
@write = nil
|
79
|
+
@try_write = nil
|
80
|
+
end
|
81
|
+
def prefer_buffered_processing
|
82
|
+
true
|
83
|
+
end
|
84
|
+
def prefer_delayed_commit
|
85
|
+
true
|
86
|
+
end
|
87
|
+
def process(tag, es)
|
88
|
+
@process ? @process.call(tag, es) : nil
|
89
|
+
end
|
90
|
+
def format(tag, time, record)
|
91
|
+
[tag, time.to_i, record].to_json + "\n"
|
92
|
+
end
|
93
|
+
def write(chunk)
|
94
|
+
@write ? @write.call(chunk) : nil
|
95
|
+
end
|
96
|
+
def try_write(chunk)
|
97
|
+
@try_write ? @try_write.call(chunk) : nil
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
TMP_DIR = File.expand_path(File.dirname(__FILE__) + "/../tmp/bu#{ENV['TEST_ENV_NUMBER']}")
|
102
|
+
|
103
|
+
def create_output
|
104
|
+
DummyOutput.new
|
105
|
+
end
|
106
|
+
def create_metadata(timekey: nil, tag: nil, variables: nil)
|
107
|
+
Fluent::Plugin::Buffer::Metadata.new(timekey, tag, variables)
|
108
|
+
end
|
109
|
+
def waiting(seconds)
|
110
|
+
begin
|
111
|
+
Timeout.timeout(seconds) do
|
112
|
+
yield
|
113
|
+
end
|
114
|
+
rescue Timeout::Error
|
115
|
+
STDERR.print(*@i.log.out.logs)
|
116
|
+
raise
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def dummy_event_stream
|
121
|
+
Fluent::ArrayEventStream.new([
|
122
|
+
[ event_time('2016-04-13 18:33:00'), {"name" => "moris", "age" => 36, "message" => "data1"} ],
|
123
|
+
[ event_time('2016-04-13 18:33:13'), {"name" => "moris", "age" => 36, "message" => "data2"} ],
|
124
|
+
[ event_time('2016-04-13 18:33:32'), {"name" => "moris", "age" => 36, "message" => "data3"} ],
|
125
|
+
])
|
126
|
+
end
|
127
|
+
|
128
|
+
setup do
|
129
|
+
@i = create_output
|
130
|
+
FileUtils.rm_rf(TMP_DIR)
|
131
|
+
FileUtils.mkdir_p(TMP_DIR)
|
132
|
+
|
133
|
+
Fluent::Plugin.register_output('backup_output', DummyOutput)
|
134
|
+
Fluent::Plugin.register_output('backup_output2', DummyOutputForSecondary)
|
135
|
+
Fluent::Plugin.register_output('backup_async_output', DummyAsyncOutputForSecondary)
|
136
|
+
end
|
137
|
+
|
138
|
+
teardown do
|
139
|
+
if @i
|
140
|
+
@i.stop unless @i.stopped?
|
141
|
+
@i.before_shutdown unless @i.before_shutdown?
|
142
|
+
@i.shutdown unless @i.shutdown?
|
143
|
+
@i.after_shutdown unless @i.after_shutdown?
|
144
|
+
@i.close unless @i.closed?
|
145
|
+
@i.terminate unless @i.terminated?
|
146
|
+
end
|
147
|
+
Timecop.return
|
148
|
+
end
|
149
|
+
|
150
|
+
sub_test_case 'buffered output for broken chunks' do
|
151
|
+
def flush_chunks
|
152
|
+
@i.start
|
153
|
+
@i.after_start
|
154
|
+
|
155
|
+
@i.interrupt_flushes
|
156
|
+
|
157
|
+
now = Time.parse('2016-04-13 18:33:30 -0700')
|
158
|
+
Timecop.freeze(now)
|
159
|
+
@i.emit_events("test.tag.1", dummy_event_stream())
|
160
|
+
now = Time.parse('2016-04-13 18:33:32 -0700')
|
161
|
+
Timecop.freeze(now)
|
162
|
+
|
163
|
+
@i.enqueue_thread_wait
|
164
|
+
@i.flush_thread_wakeup
|
165
|
+
waiting(4) { Thread.pass until @i.write_count > 0 }
|
166
|
+
|
167
|
+
assert { @i.write_count > 0 }
|
168
|
+
Timecop.freeze(now)
|
169
|
+
@i.flush_thread_wakeup
|
170
|
+
end
|
171
|
+
|
172
|
+
def wait_flush(target_file)
|
173
|
+
waiting(5) {
|
174
|
+
target_dir = File.join(File.dirname(target_file), "*")
|
175
|
+
while Dir.glob(target_dir).size.zero?
|
176
|
+
end
|
177
|
+
}
|
178
|
+
end
|
179
|
+
|
180
|
+
test 'backup chunk without secondary' do
|
181
|
+
Fluent::SystemConfig.overwrite_system_config('root_dir' => TMP_DIR) do
|
182
|
+
id = 'backup_test'
|
183
|
+
hash = {
|
184
|
+
'flush_interval' => 1,
|
185
|
+
'flush_thread_burst_interval' => 0.1,
|
186
|
+
}
|
187
|
+
chunk_id = nil
|
188
|
+
@i.configure(config_element('ROOT', '', {'@id' => id}, [config_element('buffer', 'tag', hash)]))
|
189
|
+
@i.register(:write) { |chunk|
|
190
|
+
chunk_id = chunk.unique_id;
|
191
|
+
raise Fluent::UnrecoverableError, "yay, your #write must fail"
|
192
|
+
}
|
193
|
+
|
194
|
+
flush_chunks
|
195
|
+
|
196
|
+
target = "#{TMP_DIR}/backup/worker0/#{id}/#{@i.dump_unique_id_hex(chunk_id)}.log"
|
197
|
+
wait_flush(target)
|
198
|
+
assert_true File.exist?(target)
|
199
|
+
logs = @i.log.out.logs
|
200
|
+
assert { logs.any? { |l| l.include?("got unrecoverable error in primary and no secondary") } }
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
test 'backup chunk with same type secondary' do
|
205
|
+
Fluent::SystemConfig.overwrite_system_config('root_dir' => TMP_DIR) do
|
206
|
+
id = 'backup_test_with_same_secondary'
|
207
|
+
hash = {
|
208
|
+
'flush_interval' => 1,
|
209
|
+
'flush_thread_burst_interval' => 0.1,
|
210
|
+
}
|
211
|
+
chunk_id = nil
|
212
|
+
secconf = config_element('secondary','',{'@type' => 'backup_output'})
|
213
|
+
@i.configure(config_element('ROOT', '', {'@id' => id}, [config_element('buffer', 'tag', hash), secconf]))
|
214
|
+
@i.register(:write) { |chunk|
|
215
|
+
chunk_id = chunk.unique_id;
|
216
|
+
raise Fluent::UnrecoverableError, "yay, your #write must fail"
|
217
|
+
}
|
218
|
+
|
219
|
+
flush_chunks
|
220
|
+
|
221
|
+
target = "#{TMP_DIR}/backup/worker0/#{id}/#{@i.dump_unique_id_hex(chunk_id)}.log"
|
222
|
+
wait_flush(target)
|
223
|
+
assert_true File.exist?(target)
|
224
|
+
logs = @i.log.out.logs
|
225
|
+
assert { logs.any? { |l| l.include?("got unrecoverable error in primary and secondary type is same as primary") } }
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
test 'backup chunk with different type secondary' do
|
230
|
+
Fluent::SystemConfig.overwrite_system_config('root_dir' => TMP_DIR) do
|
231
|
+
id = 'backup_test_with_diff_secondary'
|
232
|
+
hash = {
|
233
|
+
'flush_interval' => 1,
|
234
|
+
'flush_thread_burst_interval' => 0.1,
|
235
|
+
}
|
236
|
+
chunk_id = nil
|
237
|
+
secconf = config_element('secondary','',{'@type' => 'backup_output2'})
|
238
|
+
@i.configure(config_element('ROOT', '', {'@id' => id}, [config_element('buffer', 'tag', hash), secconf]))
|
239
|
+
@i.register(:write) { |chunk|
|
240
|
+
chunk_id = chunk.unique_id;
|
241
|
+
raise Fluent::UnrecoverableError, "yay, your #write must fail"
|
242
|
+
}
|
243
|
+
@i.secondary.register(:write) { |chunk|
|
244
|
+
raise Fluent::UnrecoverableError, "yay, your secondary #write must fail"
|
245
|
+
}
|
246
|
+
|
247
|
+
flush_chunks
|
248
|
+
|
249
|
+
target = "#{TMP_DIR}/backup/worker0/#{id}/#{@i.dump_unique_id_hex(chunk_id)}.log"
|
250
|
+
wait_flush(target)
|
251
|
+
assert_true File.exist?(target)
|
252
|
+
logs = @i.log.out.logs
|
253
|
+
assert { logs.any? { |l| l.include?("got unrecoverable error in primary. Skip retry and flush chunk to secondary") } }
|
254
|
+
assert { logs.any? { |l| l.include?("got an error in secondary for unrecoverable error") } }
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
test 'backup chunk with async secondary' do
|
259
|
+
Fluent::SystemConfig.overwrite_system_config('root_dir' => TMP_DIR) do
|
260
|
+
id = 'backup_test_with_diff_secondary'
|
261
|
+
hash = {
|
262
|
+
'flush_interval' => 1,
|
263
|
+
'flush_thread_burst_interval' => 0.1,
|
264
|
+
}
|
265
|
+
chunk_id = nil
|
266
|
+
secconf = config_element('secondary','',{'@type' => 'backup_async_output'})
|
267
|
+
@i.configure(config_element('ROOT', '', {'@id' => id}, [config_element('buffer', 'tag', hash), secconf]))
|
268
|
+
@i.register(:write) { |chunk|
|
269
|
+
chunk_id = chunk.unique_id;
|
270
|
+
raise Fluent::UnrecoverableError, "yay, your #write must fail"
|
271
|
+
}
|
272
|
+
|
273
|
+
flush_chunks
|
274
|
+
|
275
|
+
target = "#{TMP_DIR}/backup/worker0/#{id}/#{@i.dump_unique_id_hex(chunk_id)}.log"
|
276
|
+
wait_flush(target)
|
277
|
+
assert_true File.exist?(target)
|
278
|
+
logs = @i.log.out.logs
|
279
|
+
assert { logs.any? { |l| l.include?("got unrecoverable error in primary and secondary is async output") } }
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
test 'chunk is thrown away when disable_chunk_backup is true' do
|
284
|
+
Fluent::SystemConfig.overwrite_system_config('root_dir' => TMP_DIR) do
|
285
|
+
id = 'backup_test'
|
286
|
+
hash = {
|
287
|
+
'flush_interval' => 1,
|
288
|
+
'flush_thread_burst_interval' => 0.1,
|
289
|
+
'disable_chunk_backup' => true
|
290
|
+
}
|
291
|
+
chunk_id = nil
|
292
|
+
@i.configure(config_element('ROOT', '', {'@id' => id}, [config_element('buffer', 'tag', hash)]))
|
293
|
+
@i.register(:write) { |chunk|
|
294
|
+
chunk_id = chunk.unique_id;
|
295
|
+
raise Fluent::UnrecoverableError, "yay, your #write must fail"
|
296
|
+
}
|
297
|
+
|
298
|
+
flush_chunks
|
299
|
+
|
300
|
+
target = "#{TMP_DIR}/backup/worker0/#{id}/#{@i.dump_unique_id_hex(chunk_id)}.log"
|
301
|
+
assert_false File.exist?(target)
|
302
|
+
logs = @i.log.out.logs
|
303
|
+
assert { logs.any? { |l| l.include?("disable_chunk_backup is true") } }
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
@@ -123,6 +123,7 @@ class BufferedOutputRetryTest < Test::Unit::TestCase
|
|
123
123
|
'flush_interval' => 1,
|
124
124
|
'flush_thread_burst_interval' => 0.1,
|
125
125
|
'retry_randomize' => false,
|
126
|
+
'queued_chunks_limit_size' => 100
|
126
127
|
}
|
127
128
|
@i.configure(config_element('ROOT','',{},[config_element('buffer',chunk_key,hash)]))
|
128
129
|
@i.register(:prefer_buffered_processing){ true }
|
@@ -252,6 +253,7 @@ class BufferedOutputRetryTest < Test::Unit::TestCase
|
|
252
253
|
'flush_thread_burst_interval' => 0.1,
|
253
254
|
'retry_randomize' => false,
|
254
255
|
'retry_timeout' => 3600,
|
256
|
+
'queued_chunks_limit_size' => 100
|
255
257
|
}
|
256
258
|
@i.configure(config_element('ROOT','',{},[config_element('buffer',chunk_key,hash)]))
|
257
259
|
@i.register(:prefer_buffered_processing){ true }
|
@@ -342,6 +344,7 @@ class BufferedOutputRetryTest < Test::Unit::TestCase
|
|
342
344
|
'flush_thread_burst_interval' => 0.1,
|
343
345
|
'retry_randomize' => false,
|
344
346
|
'retry_max_times' => 10,
|
347
|
+
'queued_chunks_limit_size' => 100
|
345
348
|
}
|
346
349
|
@i.configure(config_element('ROOT','',{},[config_element('buffer',chunk_key,hash)]))
|
347
350
|
@i.register(:prefer_buffered_processing){ true }
|
@@ -412,6 +415,68 @@ class BufferedOutputRetryTest < Test::Unit::TestCase
|
|
412
415
|
assert{ @i.buffer.stage.size == 1 }
|
413
416
|
assert{ chunks.all?{|c| c.empty? } }
|
414
417
|
end
|
418
|
+
|
419
|
+
test 'output plugin limits queued chunks via queued_chunks_limit_size' do
|
420
|
+
chunk_key = 'tag'
|
421
|
+
hash = {
|
422
|
+
'flush_interval' => 1,
|
423
|
+
'flush_thread_burst_interval' => 0.1,
|
424
|
+
'retry_randomize' => false,
|
425
|
+
'retry_max_times' => 7,
|
426
|
+
'queued_chunks_limit_size' => 2,
|
427
|
+
}
|
428
|
+
@i.configure(config_element('ROOT','',{},[config_element('buffer',chunk_key,hash)]))
|
429
|
+
@i.register(:prefer_buffered_processing) { true }
|
430
|
+
@i.register(:format) { |tag,time,record| [tag,time.to_i,record].to_json + "\n" }
|
431
|
+
@i.register(:write) { |chunk| raise "yay, your #write must fail" }
|
432
|
+
@i.start
|
433
|
+
@i.after_start
|
434
|
+
|
435
|
+
@i.interrupt_flushes
|
436
|
+
|
437
|
+
now = Time.parse('2016-04-13 18:33:30 -0700')
|
438
|
+
Timecop.freeze(now)
|
439
|
+
|
440
|
+
@i.emit_events("test.tag.1", dummy_event_stream())
|
441
|
+
|
442
|
+
now = Time.parse('2016-04-13 18:33:31 -0700')
|
443
|
+
Timecop.freeze(now)
|
444
|
+
|
445
|
+
@i.emit_events("test.tag.2", dummy_event_stream())
|
446
|
+
|
447
|
+
@i.enqueue_thread_wait
|
448
|
+
@i.flush_thread_wakeup
|
449
|
+
waiting(4) { Thread.pass until @i.write_count > 0 && @i.num_errors > 0 }
|
450
|
+
|
451
|
+
assert { @i.buffer.queue.size > 0 }
|
452
|
+
assert { @i.buffer.queue.first.metadata.tag == 'test.tag.1' }
|
453
|
+
|
454
|
+
assert { @i.write_count > 0 }
|
455
|
+
assert { @i.num_errors > 0 }
|
456
|
+
|
457
|
+
prev_write_count = @i.write_count
|
458
|
+
prev_num_errors = @i.num_errors
|
459
|
+
|
460
|
+
chunks = @i.buffer.queue.dup
|
461
|
+
|
462
|
+
20.times do |i| # large times enough
|
463
|
+
now = @i.next_flush_time
|
464
|
+
|
465
|
+
Timecop.freeze(now)
|
466
|
+
@i.enqueue_thread_wait
|
467
|
+
@i.flush_thread_wakeup
|
468
|
+
waiting(4) { Thread.pass until @i.write_count > prev_write_count && @i.num_errors > prev_num_errors }
|
469
|
+
|
470
|
+
@i.emit_events("test.tag.1", dummy_event_stream())
|
471
|
+
assert { @i.buffer.queue.size <= 2 }
|
472
|
+
assert { @i.buffer.stage.size == 1 } # all new data is stored into staged chunk
|
473
|
+
|
474
|
+
break if @i.buffer.queue.size == 0
|
475
|
+
|
476
|
+
prev_write_count = @i.write_count
|
477
|
+
prev_num_errors = @i.num_errors
|
478
|
+
end
|
479
|
+
end
|
415
480
|
end
|
416
481
|
|
417
482
|
sub_test_case 'bufferd output for retries with periodical retry' do
|
@@ -423,6 +488,7 @@ class BufferedOutputRetryTest < Test::Unit::TestCase
|
|
423
488
|
'retry_type' => :periodic,
|
424
489
|
'retry_wait' => 3,
|
425
490
|
'retry_randomize' => false,
|
491
|
+
'queued_chunks_limit_size' => 100
|
426
492
|
}
|
427
493
|
@i.configure(config_element('ROOT','',{},[config_element('buffer',chunk_key,hash)]))
|
428
494
|
@i.register(:prefer_buffered_processing){ true }
|
@@ -469,6 +535,7 @@ class BufferedOutputRetryTest < Test::Unit::TestCase
|
|
469
535
|
'retry_wait' => 30,
|
470
536
|
'retry_randomize' => false,
|
471
537
|
'retry_timeout' => 120,
|
538
|
+
'queued_chunks_limit_size' => 100
|
472
539
|
}
|
473
540
|
@i.configure(config_element('ROOT','',{},[config_element('buffer',chunk_key,hash)]))
|
474
541
|
@i.register(:prefer_buffered_processing){ true }
|
@@ -564,6 +631,7 @@ class BufferedOutputRetryTest < Test::Unit::TestCase
|
|
564
631
|
'retry_wait' => 3,
|
565
632
|
'retry_randomize' => false,
|
566
633
|
'retry_max_times' => 10,
|
634
|
+
'queued_chunks_limit_size' => 100
|
567
635
|
}
|
568
636
|
@i.configure(config_element('ROOT','',{},[config_element('buffer',chunk_key,hash)]))
|
569
637
|
@i.register(:prefer_buffered_processing){ true }
|
@@ -662,6 +730,7 @@ class BufferedOutputRetryTest < Test::Unit::TestCase
|
|
662
730
|
'retry_randomize' => false,
|
663
731
|
'retry_timeout' => 3600,
|
664
732
|
'retry_max_times' => 10,
|
733
|
+
'queued_chunks_limit_size' => 100
|
665
734
|
}
|
666
735
|
@i.configure(config_element('ROOT','',{},[config_element('buffer',chunk_key,hash)]))
|
667
736
|
@i.register(:prefer_buffered_processing){ true }
|
@@ -733,6 +802,7 @@ class BufferedOutputRetryTest < Test::Unit::TestCase
|
|
733
802
|
'retry_wait' => 30,
|
734
803
|
'retry_timeout' => 360,
|
735
804
|
'retry_max_times' => 10,
|
805
|
+
'queued_chunks_limit_size' => 100
|
736
806
|
}
|
737
807
|
@i.configure(config_element('ROOT','',{},[config_element('buffer',chunk_key,hash)]))
|
738
808
|
@i.register(:prefer_buffered_processing){ true }
|