fluentd 0.14.12 → 0.14.13
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/CONTRIBUTING.md +2 -0
- data/ChangeLog +33 -0
- data/bin/fluent-plugin-config-format +5 -0
- data/bin/fluent-plugin-generate +5 -0
- data/lib/fluent/command/plugin_config_formatter.rb +258 -0
- data/lib/fluent/command/plugin_generator.rb +301 -0
- data/lib/fluent/compat/detach_process_mixin.rb +25 -0
- data/lib/fluent/compat/filter.rb +1 -1
- data/lib/fluent/compat/input.rb +1 -0
- data/lib/fluent/compat/output.rb +8 -5
- data/lib/fluent/config/configure_proxy.rb +31 -8
- data/lib/fluent/configurable.rb +2 -2
- data/lib/fluent/output.rb +3 -0
- data/lib/fluent/plugin/buffer/file_chunk.rb +52 -11
- data/lib/fluent/plugin/filter.rb +1 -1
- data/lib/fluent/plugin/filter_record_transformer.rb +5 -1
- data/lib/fluent/plugin/in_tail.rb +13 -6
- data/lib/fluent/plugin/input.rb +1 -1
- data/lib/fluent/plugin/output.rb +26 -6
- data/lib/fluent/plugin/parser_apache.rb +1 -1
- data/lib/fluent/plugin/parser_apache_error.rb +1 -1
- data/lib/fluent/plugin/parser_multiline.rb +1 -0
- data/lib/fluent/plugin/parser_nginx.rb +1 -1
- data/lib/fluent/plugin/parser_regexp.rb +18 -0
- data/lib/fluent/plugin_helper.rb +19 -1
- data/lib/fluent/plugin_helper/retry_state.rb +40 -16
- data/lib/fluent/process.rb +22 -0
- data/lib/fluent/supervisor.rb +2 -21
- data/lib/fluent/test/helpers.rb +14 -0
- data/lib/fluent/version.rb +1 -1
- data/templates/new_gem/Gemfile +3 -0
- data/templates/new_gem/README.md.erb +43 -0
- data/templates/new_gem/Rakefile +13 -0
- data/templates/new_gem/fluent-plugin.gemspec.erb +27 -0
- data/templates/new_gem/lib/fluent/plugin/filter.rb.erb +14 -0
- data/templates/new_gem/lib/fluent/plugin/formatter.rb.erb +14 -0
- data/templates/new_gem/lib/fluent/plugin/input.rb.erb +11 -0
- data/templates/new_gem/lib/fluent/plugin/output.rb.erb +11 -0
- data/templates/new_gem/lib/fluent/plugin/parser.rb.erb +15 -0
- data/templates/new_gem/test/helper.rb.erb +8 -0
- data/templates/new_gem/test/plugin/test_filter.rb.erb +18 -0
- data/templates/new_gem/test/plugin/test_formatter.rb.erb +18 -0
- data/templates/new_gem/test/plugin/test_input.rb.erb +18 -0
- data/templates/new_gem/test/plugin/test_output.rb.erb +18 -0
- data/templates/new_gem/test/plugin/test_parser.rb.erb +18 -0
- data/templates/plugin_config_formatter/param.md-compact.erb +25 -0
- data/templates/plugin_config_formatter/param.md.erb +34 -0
- data/templates/plugin_config_formatter/section.md.erb +12 -0
- data/test/command/test_binlog_reader.rb +0 -9
- data/test/command/test_plugin_config_formatter.rb +275 -0
- data/test/command/test_plugin_generator.rb +66 -0
- data/test/config/test_configure_proxy.rb +89 -45
- data/test/plugin/data/log/foo/bar2 +0 -0
- data/test/plugin/test_in_tail.rb +97 -8
- data/test/plugin/test_output.rb +18 -0
- data/test/plugin/test_output_as_buffered.rb +35 -0
- data/test/plugin_helper/test_compat_parameters.rb +2 -0
- data/test/plugin_helper/test_retry_state.rb +23 -0
- data/test/test_output.rb +5 -0
- data/test/test_process.rb +14 -0
- metadata +37 -3
@@ -0,0 +1,25 @@
|
|
1
|
+
#
|
2
|
+
# Fluentd
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
module Fluent
|
18
|
+
module Compat
|
19
|
+
module DetachProcessMixin
|
20
|
+
end
|
21
|
+
|
22
|
+
module DetachMultiProcessMixin
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/fluent/compat/filter.rb
CHANGED
data/lib/fluent/compat/input.rb
CHANGED
data/lib/fluent/compat/output.rb
CHANGED
@@ -15,6 +15,7 @@
|
|
15
15
|
#
|
16
16
|
|
17
17
|
require 'fluent/plugin'
|
18
|
+
require 'fluent/plugin/buffer'
|
18
19
|
require 'fluent/plugin/output'
|
19
20
|
require 'fluent/plugin/bare_output'
|
20
21
|
require 'fluent/compat/call_super_mixin'
|
@@ -26,6 +27,7 @@ require 'fluent/compat/record_filter_mixin'
|
|
26
27
|
require 'fluent/compat/output_chain'
|
27
28
|
require 'fluent/timezone'
|
28
29
|
require 'fluent/mixin'
|
30
|
+
require 'fluent/process'
|
29
31
|
require 'fluent/event'
|
30
32
|
|
31
33
|
require 'fluent/plugin_helper/compat_parameters'
|
@@ -35,6 +37,7 @@ require 'time'
|
|
35
37
|
module Fluent
|
36
38
|
module Compat
|
37
39
|
NULL_OUTPUT_CHAIN = NullOutputChain.instance
|
40
|
+
BufferQueueLimitError = ::Fluent::Plugin::Buffer::BufferOverflowError
|
38
41
|
|
39
42
|
module CompatOutputUtils
|
40
43
|
def self.buffer_section(conf)
|
@@ -146,7 +149,7 @@ module Fluent
|
|
146
149
|
class Output < Fluent::Plugin::Output
|
147
150
|
# TODO: warn when deprecated
|
148
151
|
|
149
|
-
|
152
|
+
helpers_internal :event_emitter, :inject
|
150
153
|
|
151
154
|
def support_in_v12_style?(feature)
|
152
155
|
case feature
|
@@ -202,7 +205,7 @@ module Fluent
|
|
202
205
|
class MultiOutput < Fluent::Plugin::BareOutput
|
203
206
|
# TODO: warn when deprecated
|
204
207
|
|
205
|
-
|
208
|
+
helpers_internal :event_emitter
|
206
209
|
|
207
210
|
def process(tag, es)
|
208
211
|
emit(tag, es, NULL_OUTPUT_CHAIN)
|
@@ -212,7 +215,7 @@ module Fluent
|
|
212
215
|
class BufferedOutput < Fluent::Plugin::Output
|
213
216
|
# TODO: warn when deprecated
|
214
217
|
|
215
|
-
|
218
|
+
helpers_internal :event_emitter, :inject
|
216
219
|
|
217
220
|
def support_in_v12_style?(feature)
|
218
221
|
case feature
|
@@ -422,7 +425,7 @@ module Fluent
|
|
422
425
|
class ObjectBufferedOutput < Fluent::Plugin::Output
|
423
426
|
# TODO: warn when deprecated
|
424
427
|
|
425
|
-
|
428
|
+
helpers_internal :event_emitter, :inject
|
426
429
|
|
427
430
|
# This plugin cannot inherit BufferedOutput because #configure sets chunk_key 'tag'
|
428
431
|
# to flush chunks per tags, but BufferedOutput#configure doesn't allow setting chunk_key
|
@@ -559,7 +562,7 @@ module Fluent
|
|
559
562
|
class TimeSlicedOutput < Fluent::Plugin::Output
|
560
563
|
# TODO: warn when deprecated
|
561
564
|
|
562
|
-
|
565
|
+
helpers_internal :event_emitter, :inject
|
563
566
|
|
564
567
|
def support_in_v12_style?(feature)
|
565
568
|
case feature
|
@@ -368,16 +368,40 @@ module Fluent
|
|
368
368
|
name
|
369
369
|
end
|
370
370
|
|
371
|
-
def
|
372
|
-
dumped_config =
|
373
|
-
indent = " " * level
|
371
|
+
def dump_config_definition
|
372
|
+
dumped_config = {}
|
374
373
|
@params.each do |name, config|
|
375
|
-
dumped_config
|
376
|
-
dumped_config
|
377
|
-
dumped_config
|
374
|
+
dumped_config[name] = config[1]
|
375
|
+
dumped_config[name][:required] = !@defaults.key?(name)
|
376
|
+
dumped_config[name][:default] = @defaults[name] if @defaults.key?(name)
|
377
|
+
dumped_config[name][:desc] = @descriptions[name] if @descriptions.key?(name)
|
378
|
+
end
|
379
|
+
# Overwrite by config_set_default
|
380
|
+
@defaults.each do |name, value|
|
381
|
+
if @params.key?(name)
|
382
|
+
dumped_config[name][:default] = value
|
383
|
+
else
|
384
|
+
dumped_config[name] = { default: value }
|
385
|
+
end
|
386
|
+
end
|
387
|
+
# Overwrite by config_set_desc
|
388
|
+
@descriptions.each do |name, value|
|
389
|
+
if @params.key?(name)
|
390
|
+
dumped_config[name][:desc] = value
|
391
|
+
else
|
392
|
+
dumped_config[name] = { desc: value }
|
393
|
+
end
|
378
394
|
end
|
379
395
|
@sections.each do |section_name, sub_proxy|
|
380
|
-
dumped_config
|
396
|
+
if dumped_config.key?(section_name)
|
397
|
+
dumped_config[section_name].update(sub_proxy.dump_config_definition)
|
398
|
+
else
|
399
|
+
dumped_config[section_name] = sub_proxy.dump_config_definition
|
400
|
+
dumped_config[section_name][:required] = sub_proxy.required?
|
401
|
+
dumped_config[section_name][:multi] = sub_proxy.multi?
|
402
|
+
dumped_config[section_name][:alias] = sub_proxy.alias
|
403
|
+
dumped_config[section_name][:section] = true
|
404
|
+
end
|
381
405
|
end
|
382
406
|
dumped_config
|
383
407
|
end
|
@@ -392,4 +416,3 @@ module Fluent
|
|
392
416
|
end
|
393
417
|
end
|
394
418
|
end
|
395
|
-
|
data/lib/fluent/configurable.rb
CHANGED
@@ -192,8 +192,8 @@ module Fluent
|
|
192
192
|
configurables.map{ |a| a.configure_proxy(a.name || a.object_id.to_s) }.reduce(:merge)
|
193
193
|
end
|
194
194
|
|
195
|
-
def
|
196
|
-
configure_proxy_map[self.to_s].
|
195
|
+
def dump_config_definition
|
196
|
+
configure_proxy_map[self.to_s].dump_config_definition
|
197
197
|
end
|
198
198
|
end
|
199
199
|
end
|
data/lib/fluent/output.rb
CHANGED
@@ -23,4 +23,7 @@ module Fluent
|
|
23
23
|
ObjectBufferedOutput = Fluent::Compat::ObjectBufferedOutput
|
24
24
|
TimeSlicedOutput = Fluent::Compat::TimeSlicedOutput
|
25
25
|
MultiOutput = Fluent::Compat::MultiOutput
|
26
|
+
|
27
|
+
# Some input plugins refer BufferQueueLimitError for throttling
|
28
|
+
BufferQueueLimitError = Fluent::Compat::BufferQueueLimitError
|
26
29
|
end
|
@@ -106,10 +106,37 @@ module Fluent
|
|
106
106
|
|
107
107
|
write_metadata(update: false) # re-write metadata w/ finalized records
|
108
108
|
|
109
|
-
|
110
|
-
|
109
|
+
begin
|
110
|
+
file_rename(@chunk, @path, new_chunk_path, ->(new_io) { @chunk = new_io })
|
111
|
+
rescue => e
|
112
|
+
begin
|
113
|
+
file_rename(@chunk, new_chunk_path, @path, ->(new_io) { @chunk = new_io }) if File.exist?(new_chunk_path)
|
114
|
+
rescue => re
|
115
|
+
# In this point, restore buffer state is hard because previous `file_rename` failed by resource problem.
|
116
|
+
# Retry is one possible approach but it may cause livelock under limited resources or high load environment.
|
117
|
+
# So we ignore such errors for now and log better message instead.
|
118
|
+
# "Too many open files" should be fixed by proper buffer configuration and system setting.
|
119
|
+
raise "can't enqueue buffer file and failed to restore. This may causes inconsistent state: path = #{@path}, error = '#{e}', retry error = '#{re}'"
|
120
|
+
else
|
121
|
+
raise "can't enqueue buffer file: path = #{@path}, error = '#{e}'"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
begin
|
126
|
+
file_rename(@meta, @meta_path, new_meta_path, ->(new_io) { @meta = new_io })
|
127
|
+
rescue => e
|
128
|
+
begin
|
129
|
+
file_rename(@chunk, new_chunk_path, @path, ->(new_io) { @chunk = new_io }) if File.exist?(new_chunk_path)
|
130
|
+
file_rename(@meta, new_meta_path, @meta_path, ->(new_io) { @meta = new_io }) if File.exist?(new_meta_path)
|
131
|
+
rescue => re
|
132
|
+
# See above
|
133
|
+
raise "can't enqueue buffer metadata and failed to restore. This may causes inconsistent state: path = #{@meta_path}, error = '#{e}', retry error = '#{re}'"
|
134
|
+
else
|
135
|
+
raise "can't enqueue buffer metadata: path = #{@meta_path}, error = '#{e}'"
|
136
|
+
end
|
137
|
+
end
|
111
138
|
|
112
|
-
|
139
|
+
@path = new_chunk_path
|
113
140
|
@meta_path = new_meta_path
|
114
141
|
|
115
142
|
super
|
@@ -242,14 +269,28 @@ module Fluent
|
|
242
269
|
def create_new_chunk(path, perm)
|
243
270
|
@path = self.class.generate_stage_chunk_path(path, @unique_id)
|
244
271
|
@meta_path = @path + '.meta'
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
272
|
+
begin
|
273
|
+
@chunk = File.open(@path, 'wb+', perm)
|
274
|
+
@chunk.set_encoding(Encoding::ASCII_8BIT)
|
275
|
+
@chunk.sync = true
|
276
|
+
@chunk.binmode
|
277
|
+
rescue => e
|
278
|
+
# Here assumes "Too many open files" like recoverable error so raising BufferOverflowError.
|
279
|
+
# If other cases are possible, we will change erorr handling with proper classes.
|
280
|
+
raise BufferOverflowError, "can't create buffer file for #{path}. Stop creating buffer files: error = #{e}"
|
281
|
+
end
|
282
|
+
begin
|
283
|
+
@meta = File.open(@meta_path, 'wb', perm)
|
284
|
+
@meta.set_encoding(Encoding::ASCII_8BIT)
|
285
|
+
@meta.sync = true
|
286
|
+
@meta.binmode
|
287
|
+
rescue => e
|
288
|
+
# This case is easier than enqueued!. Just removing pre-create buffer file
|
289
|
+
@chunk.close rescue nil
|
290
|
+
File.unlink(@path) rescue nil
|
291
|
+
# Same as @chunk case. See above
|
292
|
+
raise BufferOverflowError, "can't create buffer metadata for #{path}. Stop creating buffer files: error = #{e}"
|
293
|
+
end
|
253
294
|
|
254
295
|
@state = :unstaged
|
255
296
|
@bytesize = 0
|
data/lib/fluent/plugin/filter.rb
CHANGED
@@ -308,10 +308,14 @@ module Fluent::Plugin
|
|
308
308
|
raise "failed to expand `#{str}` : error = #{e}"
|
309
309
|
end
|
310
310
|
|
311
|
-
class CleanroomExpander
|
311
|
+
class CleanroomExpander
|
312
312
|
def expand(__str_to_eval__, tag, time, record, tag_parts, tag_prefix, tag_suffix, hostname)
|
313
313
|
instance_eval(__str_to_eval__)
|
314
314
|
end
|
315
|
+
|
316
|
+
(Object.instance_methods).each do |m|
|
317
|
+
undef_method m unless m.to_s =~ /^__|respond_to_missing\?|object_id|public_methods|instance_eval|method_missing|define_singleton_method|respond_to\?|new_ostruct_member/
|
318
|
+
end
|
315
319
|
end
|
316
320
|
end
|
317
321
|
end
|
@@ -77,6 +77,8 @@ module Fluent::Plugin
|
|
77
77
|
config_param :path_key, :string, default: nil
|
78
78
|
desc 'Open and close the file on every update instead of leaving it open until it gets rotated.'
|
79
79
|
config_param :open_on_every_update, :bool, default: false
|
80
|
+
desc 'Limit the watching files that the modification time is within the specified time range (when use \'*\' in path).'
|
81
|
+
config_param :limit_recently_modified, :time, default: nil
|
80
82
|
|
81
83
|
attr_reader :paths
|
82
84
|
|
@@ -163,7 +165,8 @@ module Fluent::Plugin
|
|
163
165
|
end
|
164
166
|
|
165
167
|
def shutdown
|
166
|
-
|
168
|
+
# during shutdown phase, don't close io. It should be done in close after all threads are stopped. See close.
|
169
|
+
stop_watchers(@tails.keys, immediate: true, remove_watcher: false)
|
167
170
|
@pf_file.close if @pf_file
|
168
171
|
|
169
172
|
super
|
@@ -184,8 +187,12 @@ module Fluent::Plugin
|
|
184
187
|
path = date.strftime(path)
|
185
188
|
if path.include?('*')
|
186
189
|
paths += Dir.glob(path).select { |p|
|
187
|
-
if File.readable?(p)
|
188
|
-
|
190
|
+
if File.readable?(p) && !File.directory?(p)
|
191
|
+
if @limit_recently_modified && File.mtime(p) < (date - @limit_recently_modified)
|
192
|
+
false
|
193
|
+
else
|
194
|
+
true
|
195
|
+
end
|
189
196
|
else
|
190
197
|
log.warn "#{p} unreadable. It is excluded and would be examined next time."
|
191
198
|
false
|
@@ -211,7 +218,7 @@ module Fluent::Plugin
|
|
211
218
|
unwatched = existence_paths - target_paths
|
212
219
|
added = target_paths - existence_paths
|
213
220
|
|
214
|
-
stop_watchers(unwatched, false, true) unless unwatched.empty?
|
221
|
+
stop_watchers(unwatched, immediate: false, unwatched: true) unless unwatched.empty?
|
215
222
|
start_watchers(added) unless added.empty?
|
216
223
|
end
|
217
224
|
|
@@ -243,9 +250,9 @@ module Fluent::Plugin
|
|
243
250
|
}
|
244
251
|
end
|
245
252
|
|
246
|
-
def stop_watchers(paths, immediate
|
253
|
+
def stop_watchers(paths, immediate: false, unwatched: false, remove_watcher: true)
|
247
254
|
paths.each { |path|
|
248
|
-
tw = @tails[path]
|
255
|
+
tw = remove_watcher ? @tails.delete(path) : @tails[path]
|
249
256
|
if tw
|
250
257
|
tw.unwatched = unwatched
|
251
258
|
if immediate
|
data/lib/fluent/plugin/input.rb
CHANGED
data/lib/fluent/plugin/output.rb
CHANGED
@@ -33,7 +33,7 @@ module Fluent
|
|
33
33
|
include PluginHelper::Mixin
|
34
34
|
include UniqueId::Mixin
|
35
35
|
|
36
|
-
|
36
|
+
helpers_internal :thread, :retry_state
|
37
37
|
|
38
38
|
CHUNK_KEY_PATTERN = /^[-_.@a-zA-Z0-9]+$/
|
39
39
|
CHUNK_KEY_PLACEHOLDER_PATTERN = /\$\{[-_.@a-zA-Z0-9]+\}/
|
@@ -229,6 +229,7 @@ module Fluent
|
|
229
229
|
end
|
230
230
|
|
231
231
|
has_buffer_section = (conf.elements(name: 'buffer').size > 0)
|
232
|
+
has_flush_interval = conf.has_key?('flush_interval')
|
232
233
|
|
233
234
|
super
|
234
235
|
|
@@ -290,7 +291,12 @@ module Fluent
|
|
290
291
|
|
291
292
|
@flush_mode = @buffer_config.flush_mode
|
292
293
|
if @flush_mode == :default
|
293
|
-
|
294
|
+
if has_flush_interval
|
295
|
+
log.info "'flush_interval' is configured at out side of <buffer>. 'flush_mode' is set to 'interval' to keep existing behaviour"
|
296
|
+
@flush_mode = :interval
|
297
|
+
else
|
298
|
+
@flush_mode = (@chunk_key_time ? :lazy : :interval)
|
299
|
+
end
|
294
300
|
end
|
295
301
|
|
296
302
|
buffer_type = @buffer_config[:@type]
|
@@ -310,6 +316,14 @@ module Fluent
|
|
310
316
|
log.warn "'flush_at_shutdown' is false, and buffer plugin '#{buf_type}' is not persistent buffer."
|
311
317
|
log.warn "your configuration will lose buffered data at shutdown. please confirm your configuration again."
|
312
318
|
end
|
319
|
+
|
320
|
+
if (@flush_mode != :interval) && buffer_conf.has_key?('flush_interval')
|
321
|
+
if buffer_conf.has_key?('flush_mode')
|
322
|
+
raise Fluent::ConfigError, "'flush_interval' can't be specified when 'flush_mode' is not 'interval' explicitly: '#{@flush_mode}'"
|
323
|
+
else
|
324
|
+
log.warn "'flush_interval' is ignored because default 'flush_mode' is not 'interval': '#{@flush_mode}'"
|
325
|
+
end
|
326
|
+
end
|
313
327
|
end
|
314
328
|
|
315
329
|
if @secondary_config
|
@@ -850,8 +864,11 @@ module Fluent
|
|
850
864
|
es.each do |time, record|
|
851
865
|
meta = metadata(tag, time, record)
|
852
866
|
meta_and_data[meta] ||= []
|
853
|
-
|
854
|
-
|
867
|
+
res = format(tag, time, record)
|
868
|
+
if res
|
869
|
+
meta_and_data[meta] << res
|
870
|
+
records += 1
|
871
|
+
end
|
855
872
|
end
|
856
873
|
write_guard do
|
857
874
|
@buffer.write(meta_and_data, enqueue: enqueue)
|
@@ -885,8 +902,11 @@ module Fluent
|
|
885
902
|
records = 0
|
886
903
|
data = []
|
887
904
|
es.each do |time, record|
|
888
|
-
|
889
|
-
|
905
|
+
res = format(tag, time, record)
|
906
|
+
if res
|
907
|
+
data << res
|
908
|
+
records += 1
|
909
|
+
end
|
890
910
|
end
|
891
911
|
else
|
892
912
|
format_proc = generate_format_proc
|