fluentd 0.14.11 → 0.14.12
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 +1 -5
- data/ChangeLog +54 -2
- data/example/in_dummy_blocks.conf +17 -0
- data/example/in_forward_tls.conf +14 -0
- data/example/in_forward_workers.conf +21 -0
- data/example/logevents.conf +25 -0
- data/example/out_forward_heartbeat_none.conf +16 -0
- data/example/out_forward_tls.conf +18 -0
- data/example/suppress_config_dump.conf +7 -0
- data/lib/fluent/agent.rb +3 -32
- data/lib/fluent/clock.rb +62 -0
- data/lib/fluent/command/fluentd.rb +12 -0
- data/lib/fluent/compat/input.rb +10 -1
- data/lib/fluent/compat/output.rb +40 -1
- data/lib/fluent/config/configure_proxy.rb +30 -7
- data/lib/fluent/config/section.rb +4 -0
- data/lib/fluent/config/types.rb +2 -2
- data/lib/fluent/configurable.rb +31 -5
- data/lib/fluent/engine.rb +61 -12
- data/lib/fluent/event_router.rb +6 -0
- data/lib/fluent/load.rb +0 -1
- data/lib/fluent/log.rb +118 -42
- data/lib/fluent/match.rb +37 -0
- data/lib/fluent/plugin.rb +25 -3
- data/lib/fluent/plugin/base.rb +4 -0
- data/lib/fluent/plugin/buf_file.rb +38 -14
- data/lib/fluent/plugin/buffer.rb +20 -20
- data/lib/fluent/plugin/buffer/file_chunk.rb +2 -2
- data/lib/fluent/plugin/compressable.rb +1 -0
- data/lib/fluent/plugin/filter_record_transformer.rb +3 -6
- data/lib/fluent/plugin/formatter_csv.rb +4 -1
- data/lib/fluent/plugin/formatter_hash.rb +5 -1
- data/lib/fluent/plugin/formatter_json.rb +10 -0
- data/lib/fluent/plugin/formatter_ltsv.rb +2 -1
- data/lib/fluent/plugin/in_dummy.rb +4 -0
- data/lib/fluent/plugin/in_exec.rb +4 -0
- data/lib/fluent/plugin/in_forward.rb +11 -3
- data/lib/fluent/plugin/in_gc_stat.rb +4 -0
- data/lib/fluent/plugin/in_http.rb +4 -0
- data/lib/fluent/plugin/in_monitor_agent.rb +29 -2
- data/lib/fluent/plugin/in_object_space.rb +4 -1
- data/lib/fluent/plugin/in_syslog.rb +4 -0
- data/lib/fluent/plugin/in_tail.rb +193 -116
- data/lib/fluent/plugin/in_tcp.rb +5 -1
- data/lib/fluent/plugin/in_udp.rb +4 -0
- data/lib/fluent/plugin/input.rb +4 -0
- data/lib/fluent/plugin/out_copy.rb +4 -0
- data/lib/fluent/plugin/out_exec.rb +4 -0
- data/lib/fluent/plugin/out_exec_filter.rb +4 -0
- data/lib/fluent/plugin/out_file.rb +70 -30
- data/lib/fluent/plugin/out_forward.rb +132 -28
- data/lib/fluent/plugin/out_null.rb +10 -0
- data/lib/fluent/plugin/out_relabel.rb +4 -0
- data/lib/fluent/plugin/out_roundrobin.rb +4 -0
- data/lib/fluent/plugin/out_secondary_file.rb +5 -0
- data/lib/fluent/plugin/out_stdout.rb +5 -0
- data/lib/fluent/plugin/output.rb +18 -9
- data/lib/fluent/plugin/storage_local.rb +25 -2
- data/lib/fluent/plugin_helper/cert_option.rb +159 -0
- data/lib/fluent/plugin_helper/child_process.rb +6 -6
- data/lib/fluent/plugin_helper/compat_parameters.rb +1 -1
- data/lib/fluent/plugin_helper/event_loop.rb +29 -4
- data/lib/fluent/plugin_helper/inject.rb +14 -1
- data/lib/fluent/plugin_helper/server.rb +275 -31
- data/lib/fluent/plugin_helper/socket.rb +144 -4
- data/lib/fluent/plugin_helper/socket_option.rb +2 -17
- data/lib/fluent/plugin_helper/storage.rb +7 -1
- data/lib/fluent/plugin_helper/thread.rb +16 -4
- data/lib/fluent/registry.rb +26 -9
- data/lib/fluent/root_agent.rb +7 -3
- data/lib/fluent/supervisor.rb +37 -15
- data/lib/fluent/system_config.rb +37 -10
- data/lib/fluent/test.rb +2 -0
- data/lib/fluent/test/driver/base.rb +24 -26
- data/lib/fluent/test/helpers.rb +21 -0
- data/lib/fluent/version.rb +1 -1
- data/test/command/test_fluentd.rb +274 -4
- data/test/config/test_configurable.rb +154 -0
- data/test/config/test_configure_proxy.rb +180 -1
- data/test/config/test_system_config.rb +10 -0
- data/test/config/test_types.rb +1 -0
- data/test/plugin/test_base.rb +4 -0
- data/test/plugin/test_buf_file.rb +241 -9
- data/test/plugin/test_buffer.rb +11 -11
- data/test/plugin/test_buffer_file_chunk.rb +6 -6
- data/test/plugin/test_compressable.rb +3 -0
- data/test/plugin/test_filter.rb +4 -0
- data/test/plugin/test_filter_record_transformer.rb +20 -0
- data/test/plugin/test_formatter_csv.rb +9 -0
- data/test/plugin/test_formatter_hash.rb +35 -0
- data/test/plugin/test_formatter_json.rb +8 -0
- data/test/plugin/test_formatter_ltsv.rb +7 -0
- data/test/plugin/test_in_dummy.rb +7 -3
- data/test/plugin/test_in_monitor_agent.rb +43 -5
- data/test/plugin/test_in_tail.rb +97 -4
- data/test/plugin/test_input.rb +4 -0
- data/test/plugin/test_out_file.rb +46 -7
- data/test/plugin/test_out_forward.rb +59 -7
- data/test/plugin/test_output.rb +10 -4
- data/test/plugin/test_output_as_buffered.rb +37 -25
- data/test/plugin/test_output_as_buffered_compress.rb +1 -1
- data/test/plugin/test_output_as_buffered_retries.rb +6 -6
- data/test/plugin/test_output_as_buffered_secondary.rb +91 -31
- data/test/plugin/test_storage_local.rb +40 -1
- data/test/plugin_helper/test_child_process.rb +29 -28
- data/test/plugin_helper/test_compat_parameters.rb +1 -1
- data/test/plugin_helper/test_inject.rb +27 -9
- data/test/plugin_helper/test_server.rb +822 -50
- data/test/plugin_helper/test_storage.rb +11 -0
- data/test/plugin_helper/test_timer.rb +1 -0
- data/test/test_clock.rb +164 -0
- data/test/test_log.rb +146 -15
- data/test/test_plugin.rb +251 -0
- data/test/test_supervisor.rb +65 -57
- data/test/test_test_drivers.rb +2 -2
- metadata +18 -7
- data/lib/fluent/process.rb +0 -504
- data/test/test_process.rb +0 -48
data/lib/fluent/match.rb
CHANGED
@@ -138,4 +138,41 @@ module Fluent
|
|
138
138
|
@patterns.any? {|pattern| pattern.match(str) }
|
139
139
|
end
|
140
140
|
end
|
141
|
+
|
142
|
+
class NoMatchMatch
|
143
|
+
def initialize(log)
|
144
|
+
@log = log
|
145
|
+
@count = 0
|
146
|
+
@warn_not_matched = true
|
147
|
+
end
|
148
|
+
|
149
|
+
def suppress_missing_match!
|
150
|
+
# for <label @FLUENT_LOG>
|
151
|
+
@warn_not_matched = false
|
152
|
+
end
|
153
|
+
|
154
|
+
def emit_events(tag, es)
|
155
|
+
return unless @warn_not_matched
|
156
|
+
# TODO use time instead of num of records
|
157
|
+
c = (@count += 1)
|
158
|
+
if c < 512
|
159
|
+
if Math.log(c) / Math.log(2) % 1.0 == 0
|
160
|
+
@log.warn "no patterns matched", tag: tag
|
161
|
+
return
|
162
|
+
end
|
163
|
+
else
|
164
|
+
if c % 512 == 0
|
165
|
+
@log.warn "no patterns matched", tag: tag
|
166
|
+
return
|
167
|
+
end
|
168
|
+
end
|
169
|
+
@log.on_trace { @log.trace "no patterns matched", tag: tag }
|
170
|
+
end
|
171
|
+
|
172
|
+
def start
|
173
|
+
end
|
174
|
+
|
175
|
+
def shutdown
|
176
|
+
end
|
177
|
+
end
|
141
178
|
end
|
data/lib/fluent/plugin.rb
CHANGED
@@ -113,12 +113,12 @@ module Fluent
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def self.new_parser(type, parent: nil)
|
116
|
-
require 'fluent/parser'
|
117
|
-
|
118
116
|
if type[0] == '/' && type[-1] == '/'
|
119
117
|
# This usage is not recommended for new API... create RegexpParser directly
|
120
118
|
require 'fluent/parser'
|
121
|
-
Fluent::TextParser.lookup(type)
|
119
|
+
impl = Fluent::TextParser.lookup(type)
|
120
|
+
impl.extend FeatureAvailabilityChecker
|
121
|
+
impl
|
122
122
|
else
|
123
123
|
new_impl('parser', PARSER_REGISTRY, type, parent)
|
124
124
|
end
|
@@ -155,7 +155,29 @@ module Fluent
|
|
155
155
|
if parent && impl.respond_to?("owner=")
|
156
156
|
impl.owner = parent
|
157
157
|
end
|
158
|
+
impl.extend FeatureAvailabilityChecker
|
158
159
|
impl
|
159
160
|
end
|
161
|
+
|
162
|
+
module FeatureAvailabilityChecker
|
163
|
+
def configure(conf)
|
164
|
+
super
|
165
|
+
|
166
|
+
# extend plugin instance by this module
|
167
|
+
# to run this check after all #configure methods of plugins and plugin helpers
|
168
|
+
sysconf = if self.respond_to?(:owner) && owner.respond_to?(:system_config)
|
169
|
+
owner.system_config
|
170
|
+
elsif self.respond_to?(:system_config)
|
171
|
+
self.system_config
|
172
|
+
else
|
173
|
+
nil
|
174
|
+
end
|
175
|
+
|
176
|
+
if sysconf && sysconf.workers > 1 && !self.multi_workers_ready?
|
177
|
+
type = Fluent::Plugin.lookup_type_from_class(self.class)
|
178
|
+
raise Fluent::ConfigError, "Plugin '#{type}' does not support multi workers configuration (#{self.class})"
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
160
182
|
end
|
161
183
|
end
|
data/lib/fluent/plugin/base.rb
CHANGED
@@ -46,14 +46,20 @@ module Fluent
|
|
46
46
|
def initialize
|
47
47
|
super
|
48
48
|
@symlink_path = nil
|
49
|
+
@multi_workers_available = false
|
50
|
+
@additional_resume_path = nil
|
49
51
|
end
|
50
52
|
|
51
53
|
def configure(conf)
|
52
54
|
super
|
53
55
|
|
56
|
+
multi_workers_configured = owner.system_config.workers > 1 ? true : false
|
57
|
+
|
58
|
+
using_plugin_root_dir = false
|
54
59
|
unless @path
|
55
60
|
if root_dir = owner.plugin_root_dir
|
56
61
|
@path = File.join(root_dir, 'buffer')
|
62
|
+
using_plugin_root_dir = true # plugin_root_dir path contains worker id
|
57
63
|
else
|
58
64
|
raise Fluent::ConfigError, "buffer path is not configured. specify 'path' in <buffer>"
|
59
65
|
end
|
@@ -67,33 +73,47 @@ module Fluent
|
|
67
73
|
|
68
74
|
@@buffer_paths[@path] = type_of_owner
|
69
75
|
|
70
|
-
|
71
|
-
|
76
|
+
specified_directory_exists = File.exist?(@path) && File.directory?(@path)
|
77
|
+
unexisting_path_for_directory = !File.exist?(@path) && !@path.include?('.*')
|
78
|
+
|
79
|
+
if specified_directory_exists || unexisting_path_for_directory # directory
|
80
|
+
if using_plugin_root_dir || !multi_workers_configured
|
72
81
|
@path = File.join(@path, 'buffer.*.log')
|
73
|
-
elsif File.basename(@path).include?('.*.')
|
74
|
-
# valid path (buffer.*.log will be ignored)
|
75
|
-
elsif File.basename(@path).end_with?('.*')
|
76
|
-
@path = @path + '.log'
|
77
82
|
else
|
78
|
-
|
79
|
-
|
83
|
+
@path = File.join(@path, "worker#{fluentd_worker_id}", 'buffer.*.log')
|
84
|
+
if fluentd_worker_id == 0
|
85
|
+
# worker 0 always checks unflushed buffer chunks to be resumed (might be created while non-multi-worker configuration)
|
86
|
+
@additional_resume_path = File.join(File.expand_path("../../", @path), 'buffer.*.log')
|
87
|
+
end
|
80
88
|
end
|
81
|
-
|
89
|
+
@multi_workers_available = true
|
90
|
+
else # specified path is file path
|
82
91
|
if File.basename(@path).include?('.*.')
|
83
|
-
# valid path
|
92
|
+
# valid file path
|
84
93
|
elsif File.basename(@path).end_with?('.*')
|
85
94
|
@path = @path + '.log'
|
86
95
|
else
|
87
|
-
#
|
88
|
-
@path =
|
96
|
+
# existing file will be ignored
|
97
|
+
@path = @path + '.*.log'
|
89
98
|
end
|
99
|
+
@multi_workers_available = false
|
90
100
|
end
|
91
101
|
|
92
|
-
|
102
|
+
if @dir_permission
|
103
|
+
@dir_permission = @dir_permission.to_i(8) if @dir_permission.is_a?(String)
|
104
|
+
else
|
93
105
|
@dir_permission = system_config.dir_permission || DIR_PERMISSION
|
94
106
|
end
|
95
107
|
end
|
96
108
|
|
109
|
+
# This method is called only when multi worker is configured
|
110
|
+
def multi_workers_ready?
|
111
|
+
unless @multi_workers_available
|
112
|
+
log.error "file buffer with multi workers should be configured to use directory 'path', or system root_dir and plugin id"
|
113
|
+
end
|
114
|
+
@multi_workers_available
|
115
|
+
end
|
116
|
+
|
97
117
|
def buffer_path_for_test?
|
98
118
|
caller_locations.each do |location|
|
99
119
|
# Thread::Backtrace::Location#path returns base filename or absolute path.
|
@@ -120,7 +140,11 @@ module Fluent
|
|
120
140
|
stage = {}
|
121
141
|
queue = []
|
122
142
|
|
123
|
-
|
143
|
+
patterns = [@path]
|
144
|
+
patterns.unshift @additional_resume_path if @additional_resume_path
|
145
|
+
Dir.glob(patterns) do |path|
|
146
|
+
next unless File.file?(path)
|
147
|
+
|
124
148
|
m = new_metadata() # this metadata will be overwritten by resuming .meta file content
|
125
149
|
# so it should not added into @metadata_list for now
|
126
150
|
mode = Fluent::Plugin::Buffer::FileChunk.assume_chunk_state(path)
|
data/lib/fluent/plugin/buffer.rb
CHANGED
@@ -47,10 +47,10 @@ module Fluent
|
|
47
47
|
|
48
48
|
# If user specify this value and (chunk_size * queue_length) is smaller than total_size,
|
49
49
|
# then total_size is automatically configured to that value
|
50
|
-
config_param :
|
50
|
+
config_param :queue_limit_length, :integer, default: nil
|
51
51
|
|
52
52
|
# optional new limitations
|
53
|
-
config_param :
|
53
|
+
config_param :chunk_limit_records, :integer, default: nil
|
54
54
|
|
55
55
|
# if chunk size (or records) is 95% or more after #write, then that chunk will be enqueued
|
56
56
|
config_param :chunk_full_threshold, :float, default: DEFAULT_CHUNK_FULL_THRESHOLD
|
@@ -73,8 +73,8 @@ module Fluent
|
|
73
73
|
|
74
74
|
@chunk_limit_size = nil
|
75
75
|
@total_limit_size = nil
|
76
|
-
@
|
77
|
-
@
|
76
|
+
@queue_limit_length = nil
|
77
|
+
@chunk_limit_records = nil
|
78
78
|
|
79
79
|
@stage = {} #=> Hash (metadata -> chunk) : not flushed yet
|
80
80
|
@queue = [] #=> Array (chunks) : already flushed (not written)
|
@@ -92,8 +92,8 @@ module Fluent
|
|
92
92
|
def configure(conf)
|
93
93
|
super
|
94
94
|
|
95
|
-
unless @
|
96
|
-
@total_limit_size = @chunk_limit_size * @
|
95
|
+
unless @queue_limit_length.nil?
|
96
|
+
@total_limit_size = @chunk_limit_size * @queue_limit_length
|
97
97
|
end
|
98
98
|
end
|
99
99
|
|
@@ -142,7 +142,7 @@ module Fluent
|
|
142
142
|
|
143
143
|
## TODO: for back pressure feature
|
144
144
|
# def used?(ratio)
|
145
|
-
# @
|
145
|
+
# @total_limit_size * ratio > @stage_size + @queue_size
|
146
146
|
# end
|
147
147
|
|
148
148
|
def resume
|
@@ -312,7 +312,7 @@ module Fluent
|
|
312
312
|
end
|
313
313
|
|
314
314
|
def enqueue_chunk(metadata)
|
315
|
-
log.
|
315
|
+
log.trace "enqueueing chunk", instance: self.object_id, metadata: metadata
|
316
316
|
synchronize do
|
317
317
|
chunk = @stage.delete(metadata)
|
318
318
|
return nil unless chunk
|
@@ -334,7 +334,7 @@ module Fluent
|
|
334
334
|
end
|
335
335
|
|
336
336
|
def enqueue_unstaged_chunk(chunk)
|
337
|
-
log.
|
337
|
+
log.trace "enqueueing unstaged chunk", instance: self.object_id, metadata: chunk.metadata
|
338
338
|
synchronize do
|
339
339
|
chunk.synchronize do
|
340
340
|
metadata = chunk.metadata
|
@@ -347,7 +347,7 @@ module Fluent
|
|
347
347
|
end
|
348
348
|
|
349
349
|
def enqueue_all
|
350
|
-
log.
|
350
|
+
log.trace "enqueueing all chunks in buffer", instance: self.object_id
|
351
351
|
synchronize do
|
352
352
|
if block_given?
|
353
353
|
@stage.keys.each do |metadata|
|
@@ -365,7 +365,7 @@ module Fluent
|
|
365
365
|
|
366
366
|
def dequeue_chunk
|
367
367
|
return nil if @queue.empty?
|
368
|
-
log.
|
368
|
+
log.trace "dequeueing a chunk", instance: self.object_id
|
369
369
|
synchronize do
|
370
370
|
chunk = @queue.shift
|
371
371
|
|
@@ -374,18 +374,18 @@ module Fluent
|
|
374
374
|
|
375
375
|
@dequeued[chunk.unique_id] = chunk
|
376
376
|
@queued_num[chunk.metadata] -= 1 # BUG if nil, 0 or subzero
|
377
|
-
log.
|
377
|
+
log.trace "chunk dequeued", instance: self.object_id, metadata: chunk.metadata
|
378
378
|
chunk
|
379
379
|
end
|
380
380
|
end
|
381
381
|
|
382
382
|
def takeback_chunk(chunk_id)
|
383
|
-
log.
|
383
|
+
log.trace "taking back a chunk", instance: self.object_id, chunk_id: dump_unique_id_hex(chunk_id)
|
384
384
|
synchronize do
|
385
385
|
chunk = @dequeued.delete(chunk_id)
|
386
386
|
return false unless chunk # already purged by other thread
|
387
387
|
@queue.unshift(chunk)
|
388
|
-
log.
|
388
|
+
log.trace "chunk taken back", instance: self.object_id, chunk_id: dump_unique_id_hex(chunk_id), metadata: chunk.metadata
|
389
389
|
@queued_num[chunk.metadata] += 1 # BUG if nil
|
390
390
|
end
|
391
391
|
true
|
@@ -397,7 +397,7 @@ module Fluent
|
|
397
397
|
return nil unless chunk # purged by other threads
|
398
398
|
|
399
399
|
metadata = chunk.metadata
|
400
|
-
log.
|
400
|
+
log.trace "purging a chunk", instance: self.object_id, chunk_id: dump_unique_id_hex(chunk_id), metadata: metadata
|
401
401
|
begin
|
402
402
|
bytesize = chunk.bytesize
|
403
403
|
chunk.purge
|
@@ -410,18 +410,18 @@ module Fluent
|
|
410
410
|
if metadata && !@stage[metadata] && (!@queued_num[metadata] || @queued_num[metadata] < 1)
|
411
411
|
@metadata_list.delete(metadata)
|
412
412
|
end
|
413
|
-
log.
|
413
|
+
log.trace "chunk purged", instance: self.object_id, chunk_id: dump_unique_id_hex(chunk_id), metadata: metadata
|
414
414
|
end
|
415
415
|
nil
|
416
416
|
end
|
417
417
|
|
418
418
|
def clear_queue!
|
419
|
-
log.
|
419
|
+
log.trace "clearing queue", instance: self.object_id
|
420
420
|
synchronize do
|
421
421
|
until @queue.empty?
|
422
422
|
begin
|
423
423
|
q = @queue.shift
|
424
|
-
log.
|
424
|
+
log.trace("purging a chunk in queue"){ {id: dump_unique_id_hex(chunk.unique_id), bytesize: chunk.bytesize, size: chunk.size} }
|
425
425
|
q.purge
|
426
426
|
rescue => e
|
427
427
|
log.error "unexpected error while clearing buffer queue", error_class: e.class, error: e
|
@@ -433,11 +433,11 @@ module Fluent
|
|
433
433
|
end
|
434
434
|
|
435
435
|
def chunk_size_over?(chunk)
|
436
|
-
chunk.bytesize > @chunk_limit_size || (@
|
436
|
+
chunk.bytesize > @chunk_limit_size || (@chunk_limit_records && chunk.size > @chunk_limit_records)
|
437
437
|
end
|
438
438
|
|
439
439
|
def chunk_size_full?(chunk)
|
440
|
-
chunk.bytesize >= @chunk_limit_size * @chunk_full_threshold || (@
|
440
|
+
chunk.bytesize >= @chunk_limit_size * @chunk_full_threshold || (@chunk_limit_records && chunk.size >= @chunk_limit_records * @chunk_full_threshold)
|
441
441
|
end
|
442
442
|
|
443
443
|
class ShouldRetry < StandardError; end
|
@@ -42,12 +42,12 @@ module Fluent
|
|
42
42
|
|
43
43
|
def initialize(metadata, path, mode, perm: system_config.file_permission || FILE_PERMISSION, compress: :text)
|
44
44
|
super(metadata, compress: compress)
|
45
|
-
@permission = perm
|
45
|
+
@permission = perm.is_a?(String) ? perm.to_i(8) : perm
|
46
46
|
@bytesize = @size = @adding_bytes = @adding_size = 0
|
47
47
|
@meta = nil
|
48
48
|
|
49
49
|
case mode
|
50
|
-
when :create then create_new_chunk(path,
|
50
|
+
when :create then create_new_chunk(path, @permission)
|
51
51
|
when :staged then load_existing_staged_chunk(path)
|
52
52
|
when :queued then load_existing_enqueued_chunk(path)
|
53
53
|
else
|
@@ -101,6 +101,8 @@ module Fluent::Plugin
|
|
101
101
|
if @renew_time_key && new_record.has_key?(@renew_time_key)
|
102
102
|
time = Fluent::EventTime.from_time(Time.at(new_record[@renew_time_key].to_f))
|
103
103
|
end
|
104
|
+
@remove_keys.each {|k| new_record.delete(k) } if @remove_keys
|
105
|
+
|
104
106
|
new_es.add(time, new_record)
|
105
107
|
rescue => e
|
106
108
|
router.emit_error_event(tag, time, record, e)
|
@@ -129,7 +131,6 @@ module Fluent::Plugin
|
|
129
131
|
new_record = @renew_record ? {} : record.dup
|
130
132
|
@keep_keys.each {|k| new_record[k] = record[k]} if @keep_keys and @renew_record
|
131
133
|
new_record.merge!(expand_placeholders(@map, placeholders))
|
132
|
-
@remove_keys.each {|k| new_record.delete(k) } if @remove_keys
|
133
134
|
|
134
135
|
new_record
|
135
136
|
end
|
@@ -307,14 +308,10 @@ module Fluent::Plugin
|
|
307
308
|
raise "failed to expand `#{str}` : error = #{e}"
|
308
309
|
end
|
309
310
|
|
310
|
-
class CleanroomExpander
|
311
|
+
class CleanroomExpander < BasicObject
|
311
312
|
def expand(__str_to_eval__, tag, time, record, tag_parts, tag_prefix, tag_suffix, hostname)
|
312
313
|
instance_eval(__str_to_eval__)
|
313
314
|
end
|
314
|
-
|
315
|
-
(Object.instance_methods).each do |m|
|
316
|
-
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/
|
317
|
-
end
|
318
315
|
end
|
319
316
|
end
|
320
317
|
end
|
@@ -29,6 +29,7 @@ module Fluent
|
|
29
29
|
# "array" looks good for type of :fields, but this implementation removes tailing comma
|
30
30
|
# TODO: Is it needed to support tailing comma?
|
31
31
|
config_param :fields, :array, value_type: :string
|
32
|
+
config_param :add_newline, :bool, default: true
|
32
33
|
|
33
34
|
def configure(conf)
|
34
35
|
super
|
@@ -42,7 +43,9 @@ module Fluent
|
|
42
43
|
row = @fields.map do |key|
|
43
44
|
record[key]
|
44
45
|
end
|
45
|
-
CSV.generate_line(row, @generate_opts)
|
46
|
+
line = CSV.generate_line(row, @generate_opts)
|
47
|
+
line.chomp! unless @add_newline
|
48
|
+
line
|
46
49
|
end
|
47
50
|
end
|
48
51
|
end
|
@@ -21,8 +21,12 @@ module Fluent
|
|
21
21
|
class HashFormatter < Formatter
|
22
22
|
Plugin.register_formatter('hash', self)
|
23
23
|
|
24
|
+
config_param :add_newline, :bool, default: true
|
25
|
+
|
24
26
|
def format(tag, time, record)
|
25
|
-
|
27
|
+
line = record.to_s
|
28
|
+
line << "\n".freeze if @add_newline
|
29
|
+
line
|
26
30
|
end
|
27
31
|
end
|
28
32
|
end
|
@@ -23,6 +23,7 @@ module Fluent
|
|
23
23
|
Plugin.register_formatter('json', self)
|
24
24
|
|
25
25
|
config_param :json_parser, :string, default: 'oj'
|
26
|
+
config_param :add_newline, :bool, default: true
|
26
27
|
|
27
28
|
def configure(conf)
|
28
29
|
super
|
@@ -35,11 +36,20 @@ module Fluent
|
|
35
36
|
rescue LoadError
|
36
37
|
@dump_proc = Yajl.method(:dump)
|
37
38
|
end
|
39
|
+
|
40
|
+
# format json is used on various highload environment, so re-define method to skip if check
|
41
|
+
unless @add_newline
|
42
|
+
define_singleton_method(:format, method(:format_without_nl))
|
43
|
+
end
|
38
44
|
end
|
39
45
|
|
40
46
|
def format(tag, time, record)
|
41
47
|
"#{@dump_proc.call(record)}\n"
|
42
48
|
end
|
49
|
+
|
50
|
+
def format_without_nl(tag, time, record)
|
51
|
+
@dump_proc.call(record)
|
52
|
+
end
|
43
53
|
end
|
44
54
|
end
|
45
55
|
end
|