fluentd 1.7.4-x64-mingw32 → 1.8.0-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/.github/ISSUE_TEMPLATE/bug_report.md +0 -1
- data/.travis.yml +4 -0
- data/CHANGELOG.md +70 -0
- data/MAINTAINERS.md +1 -0
- data/example/out_forward_sd.conf +17 -0
- data/example/sd.yaml +8 -0
- data/fluentd.gemspec +1 -1
- data/lib/fluent/agent.rb +3 -1
- data/lib/fluent/command/cat.rb +1 -2
- data/lib/fluent/command/fluentd.rb +16 -8
- data/lib/fluent/compat/call_super_mixin.rb +9 -0
- data/lib/fluent/compat/exec_util.rb +1 -1
- data/lib/fluent/config/configure_proxy.rb +4 -4
- data/lib/fluent/config/element.rb +28 -15
- data/lib/fluent/config/error.rb +6 -0
- data/lib/fluent/config/literal_parser.rb +24 -2
- data/lib/fluent/config/section.rb +43 -6
- data/lib/fluent/config/types.rb +98 -26
- data/lib/fluent/configurable.rb +2 -2
- data/lib/fluent/counter/base_socket.rb +2 -4
- data/lib/fluent/engine.rb +41 -122
- data/lib/fluent/event.rb +5 -7
- data/lib/fluent/fluent_log_event_router.rb +141 -0
- data/lib/fluent/msgpack_factory.rb +19 -2
- data/lib/fluent/plugin.rb +10 -1
- data/lib/fluent/plugin/base.rb +2 -2
- data/lib/fluent/plugin/buf_file.rb +11 -7
- data/lib/fluent/plugin/buf_file_single.rb +8 -5
- data/lib/fluent/plugin/buffer/chunk.rb +1 -1
- data/lib/fluent/plugin/buffer/file_chunk.rb +4 -6
- data/lib/fluent/plugin/buffer/file_single_chunk.rb +3 -5
- data/lib/fluent/plugin/formatter_csv.rb +23 -1
- data/lib/fluent/plugin/formatter_stdout.rb +1 -1
- data/lib/fluent/plugin/in_forward.rb +1 -1
- data/lib/fluent/plugin/in_monitor_agent.rb +4 -2
- data/lib/fluent/plugin/in_tail.rb +6 -0
- data/lib/fluent/plugin/in_unix.rb +1 -1
- data/lib/fluent/plugin/out_forward.rb +77 -28
- data/lib/fluent/plugin/out_forward/ack_handler.rb +1 -1
- data/lib/fluent/plugin/out_forward/load_balancer.rb +5 -2
- data/lib/fluent/plugin/out_stream.rb +1 -1
- data/lib/fluent/plugin/output.rb +11 -3
- data/lib/fluent/plugin/parser.rb +1 -0
- data/lib/fluent/plugin/sd_file.rb +155 -0
- data/lib/fluent/plugin/sd_static.rb +58 -0
- data/lib/fluent/plugin/service_discovery.rb +80 -0
- data/lib/fluent/plugin_helper.rb +1 -0
- data/lib/fluent/plugin_helper/child_process.rb +3 -3
- data/lib/fluent/plugin_helper/compat_parameters.rb +11 -1
- data/lib/fluent/plugin_helper/extract.rb +1 -1
- data/lib/fluent/plugin_helper/inject.rb +1 -1
- data/lib/fluent/plugin_helper/record_accessor.rb +10 -19
- data/lib/fluent/plugin_helper/server.rb +8 -4
- data/lib/fluent/plugin_helper/service_discovery.rb +80 -0
- data/lib/fluent/plugin_helper/service_discovery/manager.rb +132 -0
- data/lib/fluent/plugin_helper/service_discovery/round_robin_balancer.rb +43 -0
- data/lib/fluent/plugin_id.rb +7 -0
- data/lib/fluent/root_agent.rb +7 -9
- data/lib/fluent/supervisor.rb +192 -211
- data/lib/fluent/system_config.rb +26 -52
- data/lib/fluent/test/driver/base_owned.rb +15 -2
- data/lib/fluent/time.rb +8 -6
- data/lib/fluent/version.rb +1 -1
- data/test/command/test_fluentd.rb +12 -7
- data/test/config/test_configurable.rb +154 -0
- data/test/config/test_element.rb +18 -0
- data/test/config/test_literal_parser.rb +4 -0
- data/test/config/test_system_config.rb +48 -91
- data/test/config/test_types.rb +293 -120
- data/test/counter/test_client.rb +8 -4
- data/test/plugin/data/sd_file/config +11 -0
- data/test/plugin/data/sd_file/config.json +17 -0
- data/test/plugin/data/sd_file/config.yaml +11 -0
- data/test/plugin/data/sd_file/config.yml +11 -0
- data/test/plugin/data/sd_file/invalid_config.yml +7 -0
- data/test/plugin/out_forward/test_handshake_protocol.rb +2 -2
- data/test/plugin/out_forward/test_load_balancer.rb +1 -1
- data/test/plugin/out_forward/test_socket_cache.rb +2 -2
- data/test/plugin/test_buf_file.rb +40 -0
- data/test/plugin/test_buf_file_single.rb +32 -0
- data/test/plugin/test_buffer_file_chunk.rb +0 -11
- data/test/plugin/test_buffer_file_single_chunk.rb +0 -10
- data/test/plugin/test_formatter_csv.rb +9 -0
- data/test/plugin/test_in_forward.rb +9 -9
- data/test/plugin/test_in_monitor_agent.rb +37 -10
- data/test/plugin/test_in_unix.rb +5 -5
- data/test/plugin/test_out_forward.rb +45 -1
- data/test/plugin/test_out_stdout.rb +36 -1
- data/test/plugin/test_out_stream.rb +3 -3
- data/test/plugin/test_output.rb +25 -1
- data/test/plugin/test_sd_file.rb +211 -0
- data/test/plugin_helper/service_discovery/test_manager.rb +93 -0
- data/test/plugin_helper/service_discovery/test_round_robin_balancer.rb +21 -0
- data/test/plugin_helper/test_server.rb +13 -0
- data/test/plugin_helper/test_service_discovery.rb +72 -0
- data/test/test_event.rb +15 -15
- data/test/test_fluent_log_event_router.rb +99 -0
- data/test/test_logger_initializer.rb +26 -0
- data/test/test_supervisor.rb +30 -59
- metadata +43 -6
data/lib/fluent/event.rb
CHANGED
@@ -20,7 +20,6 @@ require 'fluent/plugin/compressable'
|
|
20
20
|
module Fluent
|
21
21
|
class EventStream
|
22
22
|
include Enumerable
|
23
|
-
include MessagePackFactory::Mixin
|
24
23
|
include Fluent::Plugin::Compressable
|
25
24
|
|
26
25
|
# dup does deep copy for event stream
|
@@ -56,7 +55,7 @@ module Fluent
|
|
56
55
|
|
57
56
|
def to_msgpack_stream(time_int: false, packer: nil)
|
58
57
|
return to_msgpack_stream_forced_integer(packer: packer) if time_int
|
59
|
-
out = packer || msgpack_packer
|
58
|
+
out = packer || Fluent::MessagePackFactory.msgpack_packer
|
60
59
|
each {|time,record|
|
61
60
|
out.write([time,record])
|
62
61
|
}
|
@@ -69,7 +68,7 @@ module Fluent
|
|
69
68
|
end
|
70
69
|
|
71
70
|
def to_msgpack_stream_forced_integer(packer: nil)
|
72
|
-
out = packer || msgpack_packer
|
71
|
+
out = packer || Fluent::MessagePackFactory.msgpack_packer
|
73
72
|
each {|time,record|
|
74
73
|
out.write([time.to_i,record])
|
75
74
|
}
|
@@ -238,7 +237,7 @@ module Fluent
|
|
238
237
|
return if @unpacked_times && @unpacked_records
|
239
238
|
@unpacked_times = []
|
240
239
|
@unpacked_records = []
|
241
|
-
(unpacker || msgpack_unpacker).feed_each(@data) do |time, record|
|
240
|
+
(unpacker || Fluent::MessagePackFactory.msgpack_unpacker).feed_each(@data) do |time, record|
|
242
241
|
@unpacked_times << time
|
243
242
|
@unpacked_records << record
|
244
243
|
end
|
@@ -262,7 +261,7 @@ module Fluent
|
|
262
261
|
else
|
263
262
|
@unpacked_times = []
|
264
263
|
@unpacked_records = []
|
265
|
-
(unpacker || msgpack_unpacker).feed_each(@data) do |time, record|
|
264
|
+
(unpacker || Fluent::MessagePackFactory.msgpack_unpacker).feed_each(@data) do |time, record|
|
266
265
|
@unpacked_times << time
|
267
266
|
@unpacked_records << record
|
268
267
|
block.call(time, record)
|
@@ -319,12 +318,11 @@ module Fluent
|
|
319
318
|
end
|
320
319
|
|
321
320
|
module ChunkMessagePackEventStreamer
|
322
|
-
include MessagePackFactory::Mixin
|
323
321
|
# chunk.extend(ChunkEventStreamer)
|
324
322
|
# => chunk.each{|time, record| ... }
|
325
323
|
def each(unpacker: nil, &block)
|
326
324
|
open do |io|
|
327
|
-
(unpacker || msgpack_unpacker(io)).each(&block)
|
325
|
+
(unpacker || Fluent::MessagePackFactory.msgpack_unpacker(io)).each(&block)
|
328
326
|
end
|
329
327
|
nil
|
330
328
|
end
|
@@ -0,0 +1,141 @@
|
|
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
|
+
require 'fluent/log'
|
18
|
+
|
19
|
+
module Fluent
|
20
|
+
# DO NOT write any logic here
|
21
|
+
class NullFluentLogEventRouter
|
22
|
+
def start; end
|
23
|
+
|
24
|
+
def stop; end
|
25
|
+
|
26
|
+
def graceful_stop; end
|
27
|
+
|
28
|
+
def emit_event(_event); end
|
29
|
+
|
30
|
+
def emittable?
|
31
|
+
self.class != NullFluentLogEventRouter
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# This class is for handling fluentd's inner log
|
36
|
+
# e.g. <label @FLUNT_LOG> section and <match fluent.**> section
|
37
|
+
class FluentLogEventRouter < NullFluentLogEventRouter
|
38
|
+
# @param root_agent [Fluent::RootAgent]
|
39
|
+
def self.build(root_agent)
|
40
|
+
log_event_router = nil
|
41
|
+
|
42
|
+
begin
|
43
|
+
log_event_agent = root_agent.find_label(Fluent::Log::LOG_EVENT_LABEL)
|
44
|
+
log_event_router = log_event_agent.event_router
|
45
|
+
|
46
|
+
# suppress mismatched tags only for <label @FLUENT_LOG> label.
|
47
|
+
# it's not suppressed in default event router for non-log-event events
|
48
|
+
log_event_router.suppress_missing_match!
|
49
|
+
|
50
|
+
log_event_router = log_event_router
|
51
|
+
|
52
|
+
unmatched_tags = Fluent::Log.event_tags.select { |t| !log_event_router.match?(t) }
|
53
|
+
unless unmatched_tags.empty?
|
54
|
+
$log.warn "match for some tags of log events are not defined in @FLUENT_LOG label (to be ignored)", tags: unmatched_tags
|
55
|
+
end
|
56
|
+
|
57
|
+
rescue ArgumentError # ArgumentError "#{label_name} label not found"
|
58
|
+
# use default event router if <label @FLUENT_LOG> is missing in configuration
|
59
|
+
root_log_event_router = root_agent.event_router
|
60
|
+
event_tags = Fluent::Log.event_tags
|
61
|
+
if event_tags.any? { |t| root_log_event_router.match?(t) }
|
62
|
+
log_event_router = root_log_event_router
|
63
|
+
|
64
|
+
unmatched_tags = event_tags.select { |t| !log_event_router.match?(t) }
|
65
|
+
if unmatched_tags.empty?
|
66
|
+
$log.warn "define <match fluent.**> to capture fluentd logs in top level is deprecated. Use <label @FLUENT_LOG> instead"
|
67
|
+
else
|
68
|
+
matched_sections = (event_tags - unmatched_tags).map { |tag| "<match #{tag}>" }.join(', ')
|
69
|
+
$log.warn "define #{matched_sections} to capture fluentd logs in top level is deprecated. Use <label @FLUENT_LOG> instead"
|
70
|
+
$log.warn "match for some tags of log events are not defined in top level (to be ignored)", tags: unmatched_tags
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
if log_event_router
|
76
|
+
FluentLogEventRouter.new(log_event_router)
|
77
|
+
else
|
78
|
+
$log.debug('No fluent logger for internal event')
|
79
|
+
NullFluentLogEventRouter.new
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
STOP = :stop
|
84
|
+
GRACEFUL_STOP = :graceful_stop
|
85
|
+
|
86
|
+
# @param event_router [Fluent::EventRouter]
|
87
|
+
def initialize(event_router)
|
88
|
+
@event_router = event_router
|
89
|
+
@thread = nil
|
90
|
+
@graceful_stop = false
|
91
|
+
@event_queue = Queue.new
|
92
|
+
end
|
93
|
+
|
94
|
+
def start
|
95
|
+
@thread = Thread.new do
|
96
|
+
$log.disable_events(Thread.current)
|
97
|
+
|
98
|
+
loop do
|
99
|
+
event = @event_queue.pop
|
100
|
+
|
101
|
+
case event
|
102
|
+
when GRACEFUL_STOP
|
103
|
+
@graceful_stop = true
|
104
|
+
when STOP
|
105
|
+
break
|
106
|
+
else
|
107
|
+
begin
|
108
|
+
tag, time, record = event
|
109
|
+
@event_router.emit(tag, time, record)
|
110
|
+
rescue => e
|
111
|
+
# This $log.error doesn't emit log events, because of `$log.disable_events(Thread.current)` above
|
112
|
+
$log.error "failed to emit fluentd's log event", tag: tag, event: record, error: e
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
if @graceful_stop && @event_queue.empty?
|
117
|
+
break
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
@thread.abort_on_exception = true
|
123
|
+
end
|
124
|
+
|
125
|
+
def stop
|
126
|
+
@event_queue.push(STOP)
|
127
|
+
# there is no problem calling Thread#join multiple times.
|
128
|
+
@thread && @thread.join
|
129
|
+
end
|
130
|
+
|
131
|
+
def graceful_stop
|
132
|
+
# to make sure to emit all log events into router, before shutting down
|
133
|
+
@event_queue.push(GRACEFUL_STOP)
|
134
|
+
@thread && @thread.join
|
135
|
+
end
|
136
|
+
|
137
|
+
def emit_event(event)
|
138
|
+
@event_queue.push(event)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -23,15 +23,24 @@ module Fluent
|
|
23
23
|
|
24
24
|
module Mixin
|
25
25
|
def msgpack_factory
|
26
|
+
if $log
|
27
|
+
$log.warn('Deprecated method: this method is going to be deleted. Use Fluent::MessagePackFactory.engine_factory')
|
28
|
+
end
|
26
29
|
MessagePackFactory.engine_factory
|
27
30
|
end
|
28
31
|
|
29
32
|
def msgpack_packer(*args)
|
30
|
-
|
33
|
+
if $log
|
34
|
+
$log.warn('Deprecated method: this method is going to be deleted. Use Fluent::MessagePackFactory.msgpack_packer')
|
35
|
+
end
|
36
|
+
MessagePackFactory.msgpack_packer(*args)
|
31
37
|
end
|
32
38
|
|
33
39
|
def msgpack_unpacker(*args)
|
34
|
-
|
40
|
+
if $log
|
41
|
+
$log.warn('Deprecated method: this method is going to be deleted. Use Fluent::MessagePackFactory.msgpack_unpacker')
|
42
|
+
end
|
43
|
+
MessagePackFactory.msgpack_unpacker(*args)
|
35
44
|
end
|
36
45
|
end
|
37
46
|
|
@@ -39,6 +48,14 @@ module Fluent
|
|
39
48
|
@@engine_factory || factory
|
40
49
|
end
|
41
50
|
|
51
|
+
def self.msgpack_packer(*args)
|
52
|
+
engine_factory.packer(*args)
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.msgpack_unpacker(*args)
|
56
|
+
engine_factory.unpacker(*args)
|
57
|
+
end
|
58
|
+
|
42
59
|
def self.factory
|
43
60
|
factory = MessagePack::Factory.new
|
44
61
|
factory.register_type(Fluent::EventTime::TYPE, Fluent::EventTime)
|
data/lib/fluent/plugin.rb
CHANGED
@@ -35,8 +35,9 @@ module Fluent
|
|
35
35
|
PARSER_REGISTRY = Registry.new(:parser, 'fluent/plugin/parser_', dir_search_prefix: 'parser_')
|
36
36
|
FORMATTER_REGISTRY = Registry.new(:formatter, 'fluent/plugin/formatter_', dir_search_prefix: 'formatter_')
|
37
37
|
STORAGE_REGISTRY = Registry.new(:storage, 'fluent/plugin/storage_', dir_search_prefix: 'storage_')
|
38
|
+
SD_REGISTRY = Registry.new(:sd, 'fluent/plugin/sd_', dir_search_prefix: 'sd_')
|
38
39
|
|
39
|
-
REGISTRIES = [INPUT_REGISTRY, OUTPUT_REGISTRY, FILTER_REGISTRY, BUFFER_REGISTRY, PARSER_REGISTRY, FORMATTER_REGISTRY, STORAGE_REGISTRY]
|
40
|
+
REGISTRIES = [INPUT_REGISTRY, OUTPUT_REGISTRY, FILTER_REGISTRY, BUFFER_REGISTRY, PARSER_REGISTRY, FORMATTER_REGISTRY, STORAGE_REGISTRY, SD_REGISTRY]
|
40
41
|
|
41
42
|
def self.register_input(type, klass)
|
42
43
|
register_impl('input', INPUT_REGISTRY, type, klass)
|
@@ -54,6 +55,10 @@ module Fluent
|
|
54
55
|
register_impl('buffer', BUFFER_REGISTRY, type, klass)
|
55
56
|
end
|
56
57
|
|
58
|
+
def self.register_sd(type, klass)
|
59
|
+
register_impl('sd', SD_REGISTRY, type, klass)
|
60
|
+
end
|
61
|
+
|
57
62
|
def self.register_parser(type, klass_or_proc)
|
58
63
|
if klass_or_proc.is_a?(Regexp)
|
59
64
|
# This usage is not recommended for new API
|
@@ -112,6 +117,10 @@ module Fluent
|
|
112
117
|
new_impl('buffer', BUFFER_REGISTRY, type, parent)
|
113
118
|
end
|
114
119
|
|
120
|
+
def self.new_sd(type, parent: nil)
|
121
|
+
new_impl('sd', SD_REGISTRY, type, parent)
|
122
|
+
end
|
123
|
+
|
115
124
|
def self.new_parser(type, parent: nil)
|
116
125
|
if type[0] == '/' && type[-1] == '/'
|
117
126
|
# This usage is not recommended for new API... create RegexpParser directly
|
data/lib/fluent/plugin/base.rb
CHANGED
@@ -52,7 +52,7 @@ module Fluent
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def configure(conf)
|
55
|
-
if conf.respond_to?(:for_this_worker?) && conf.for_this_worker?
|
55
|
+
if Fluent::Engine.supervisor_mode || (conf.respond_to?(:for_this_worker?) && conf.for_this_worker?)
|
56
56
|
workers = if conf.target_worker_ids && !conf.target_worker_ids.empty?
|
57
57
|
conf.target_worker_ids.size
|
58
58
|
else
|
@@ -60,7 +60,7 @@ module Fluent
|
|
60
60
|
end
|
61
61
|
system_config_override(workers: workers)
|
62
62
|
end
|
63
|
-
super
|
63
|
+
super(conf, system_config.strict_config_value)
|
64
64
|
@_state ||= State.new(false, false, false, false, false, false, false, false, false)
|
65
65
|
@_state.configure = true
|
66
66
|
self
|
@@ -50,6 +50,7 @@ module Fluent
|
|
50
50
|
@symlink_path = nil
|
51
51
|
@multi_workers_available = false
|
52
52
|
@additional_resume_path = nil
|
53
|
+
@buffer_path = nil
|
53
54
|
end
|
54
55
|
|
55
56
|
def configure(conf)
|
@@ -73,7 +74,8 @@ module Fluent
|
|
73
74
|
raise ConfigError, "Other '#{type_using_this_path}' plugin already use same buffer path: type = #{type_of_owner}, buffer path = #{@path}"
|
74
75
|
end
|
75
76
|
|
76
|
-
|
77
|
+
@buffer_path = @path
|
78
|
+
@@buffer_paths[@buffer_path] = type_of_owner
|
77
79
|
|
78
80
|
specified_directory_exists = File.exist?(@path) && File.directory?(@path)
|
79
81
|
unexisting_path_for_directory = !File.exist?(@path) && !@path.include?('.*')
|
@@ -122,6 +124,12 @@ module Fluent
|
|
122
124
|
super
|
123
125
|
end
|
124
126
|
|
127
|
+
def stop
|
128
|
+
@@buffer_paths.delete(@buffer_path)
|
129
|
+
|
130
|
+
super
|
131
|
+
end
|
132
|
+
|
125
133
|
def persistent?
|
126
134
|
true
|
127
135
|
end
|
@@ -167,12 +175,8 @@ module Fluent
|
|
167
175
|
|
168
176
|
def generate_chunk(metadata)
|
169
177
|
# FileChunk generates real path with unique_id
|
170
|
-
|
171
|
-
|
172
|
-
else
|
173
|
-
chunk = Fluent::Plugin::Buffer::FileChunk.new(metadata, @path, :create, compress: @compress)
|
174
|
-
end
|
175
|
-
|
178
|
+
perm = @file_permission || system_config.file_permission
|
179
|
+
chunk = Fluent::Plugin::Buffer::FileChunk.new(metadata, @path, :create, perm: perm, compress: @compress)
|
176
180
|
log.debug "Created new chunk", chunk_id: dump_unique_id_hex(chunk.unique_id), metadata: metadata
|
177
181
|
|
178
182
|
return chunk
|
@@ -144,6 +144,12 @@ module Fluent
|
|
144
144
|
super
|
145
145
|
end
|
146
146
|
|
147
|
+
def stop
|
148
|
+
@@buffer_paths.delete(@path)
|
149
|
+
|
150
|
+
super
|
151
|
+
end
|
152
|
+
|
147
153
|
def persistent?
|
148
154
|
true
|
149
155
|
end
|
@@ -189,11 +195,8 @@ module Fluent
|
|
189
195
|
|
190
196
|
def generate_chunk(metadata)
|
191
197
|
# FileChunk generates real path with unique_id
|
192
|
-
|
193
|
-
|
194
|
-
else
|
195
|
-
chunk = Fluent::Plugin::Buffer::FileSingleChunk.new(metadata, @path, :create, @key_in_path, compress: @compress)
|
196
|
-
end
|
198
|
+
perm = @file_permission || system_config.file_permission
|
199
|
+
chunk = Fluent::Plugin::Buffer::FileSingleChunk.new(metadata, @path, :create, @key_in_path, perm: perm, compress: @compress)
|
197
200
|
|
198
201
|
log.debug "Created new chunk", chunk_id: dump_unique_id_hex(chunk.unique_id), metadata: metadata
|
199
202
|
|
@@ -37,15 +37,13 @@ module Fluent
|
|
37
37
|
# path_prefix: path prefix string, ended with '.'
|
38
38
|
# path_suffix: path suffix string, like '.log' (or any other user specified)
|
39
39
|
|
40
|
-
include SystemConfig::Mixin
|
41
|
-
include MessagePackFactory::Mixin
|
42
|
-
|
43
40
|
FILE_PERMISSION = 0644
|
44
41
|
|
45
42
|
attr_reader :path, :permission
|
46
43
|
|
47
|
-
def initialize(metadata, path, mode, perm:
|
44
|
+
def initialize(metadata, path, mode, perm: nil, compress: :text)
|
48
45
|
super(metadata, compress: compress)
|
46
|
+
perm ||= FILE_PERMISSION
|
49
47
|
@permission = perm.is_a?(String) ? perm.to_i(8) : perm
|
50
48
|
@bytesize = @size = @adding_bytes = @adding_size = 0
|
51
49
|
@meta = nil
|
@@ -221,7 +219,7 @@ module Fluent
|
|
221
219
|
|
222
220
|
unless data
|
223
221
|
# old type of restore
|
224
|
-
data = msgpack_unpacker(symbolize_keys: true).feed(bindata).read rescue {}
|
222
|
+
data = Fluent::MessagePackFactory.msgpack_unpacker(symbolize_keys: true).feed(bindata).read rescue {}
|
225
223
|
end
|
226
224
|
|
227
225
|
now = Fluent::Clock.real_now
|
@@ -403,7 +401,7 @@ module Fluent
|
|
403
401
|
if chunk.slice(0, 2) == BUFFER_HEADER
|
404
402
|
size = chunk.slice(2, 4).unpack('N').first
|
405
403
|
if size
|
406
|
-
return msgpack_unpacker(symbolize_keys: true).feed(chunk.slice(6, size)).read rescue nil
|
404
|
+
return Fluent::MessagePackFactory.msgpack_unpacker(symbolize_keys: true).feed(chunk.slice(6, size)).read rescue nil
|
407
405
|
end
|
408
406
|
end
|
409
407
|
|
@@ -29,9 +29,6 @@ module Fluent
|
|
29
29
|
## buffer chunk path : /path/to/directory/fsb.key.b513b61c9791029c2513b61c9791029c2.buf
|
30
30
|
## state: b/q - 'b'(on stage), 'q'(enqueued)
|
31
31
|
|
32
|
-
include SystemConfig::Mixin
|
33
|
-
include MessagePackFactory::Mixin
|
34
|
-
|
35
32
|
PATH_EXT = 'buf'
|
36
33
|
PATH_SUFFIX = ".#{PATH_EXT}"
|
37
34
|
PATH_REGEXP = /\.(b|q)([0-9a-f]+)\.#{PATH_EXT}*\Z/n # //n switch means explicit 'ASCII-8BIT' pattern
|
@@ -39,9 +36,10 @@ module Fluent
|
|
39
36
|
|
40
37
|
attr_reader :path, :permission
|
41
38
|
|
42
|
-
def initialize(metadata, path, mode, key, perm:
|
39
|
+
def initialize(metadata, path, mode, key, perm: FILE_PERMISSION, compress: :text)
|
43
40
|
super(metadata, compress: compress)
|
44
41
|
@key = key
|
42
|
+
perm ||= FILE_PERMISSION
|
45
43
|
@permission = perm.is_a?(String) ? perm.to_i(8) : perm
|
46
44
|
@bytesize = @size = @adding_bytes = @adding_size = 0
|
47
45
|
|
@@ -216,7 +214,7 @@ module Fluent
|
|
216
214
|
count = 0
|
217
215
|
File.open(@path, 'rb') { |f|
|
218
216
|
if chunk_format == :msgpack
|
219
|
-
msgpack_unpacker(f).each { |d| count += 1 }
|
217
|
+
Fluent::MessagePackFactory.msgpack_unpacker(f).each { |d| count += 1 }
|
220
218
|
else
|
221
219
|
f.each_line { |l| count += 1 }
|
222
220
|
end
|
@@ -14,6 +14,7 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
16
|
|
17
|
+
require 'fluent/plugin_helper'
|
17
18
|
require 'fluent/plugin/formatter'
|
18
19
|
require 'csv'
|
19
20
|
|
@@ -22,6 +23,9 @@ module Fluent
|
|
22
23
|
class CsvFormatter < Formatter
|
23
24
|
Plugin.register_formatter('csv', self)
|
24
25
|
|
26
|
+
include PluginHelper::Mixin
|
27
|
+
helpers :record_accessor
|
28
|
+
|
25
29
|
config_param :delimiter, default: ',' do |val|
|
26
30
|
['\t', 'TAB'].include?(val) ? "\t" : val
|
27
31
|
end
|
@@ -37,6 +41,14 @@ module Fluent
|
|
37
41
|
@fields = fields.select{|f| !f.empty? }
|
38
42
|
raise ConfigError, "empty value is specified in fields parameter" if @fields.empty?
|
39
43
|
|
44
|
+
if @fields.any? { |f| record_accessor_nested?(f) }
|
45
|
+
@accessors = @fields.map { |f| record_accessor_create(f) }
|
46
|
+
mformat = method(:format_with_nested_fields)
|
47
|
+
singleton_class.module_eval do
|
48
|
+
define_method(:format, mformat)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
40
52
|
@generate_opts = {col_sep: @delimiter, force_quotes: @force_quotes, headers: @fields,
|
41
53
|
row_sep: @add_newline ? :auto : "".force_encoding(Encoding::ASCII_8BIT)}
|
42
54
|
# Cache CSV object per thread to avoid internal state sharing
|
@@ -44,13 +56,23 @@ module Fluent
|
|
44
56
|
end
|
45
57
|
|
46
58
|
def format(tag, time, record)
|
47
|
-
csv = (@cache[Thread.current] ||= CSV.new("".force_encoding(Encoding::ASCII_8BIT),
|
59
|
+
csv = (@cache[Thread.current] ||= CSV.new("".force_encoding(Encoding::ASCII_8BIT), **@generate_opts))
|
48
60
|
line = (csv << record).string.dup
|
49
61
|
# Need manual cleanup because CSV writer doesn't provide such method.
|
50
62
|
csv.rewind
|
51
63
|
csv.truncate(0)
|
52
64
|
line
|
53
65
|
end
|
66
|
+
|
67
|
+
def format_with_nested_fields(tag, time, record)
|
68
|
+
csv = (@cache[Thread.current] ||= CSV.new("".force_encoding(Encoding::ASCII_8BIT), **@generate_opts))
|
69
|
+
values = @accessors.map { |a| a.call(record) }
|
70
|
+
line = (csv << values).string.dup
|
71
|
+
# Need manual cleanup because CSV writer doesn't provide such method.
|
72
|
+
csv.rewind
|
73
|
+
csv.truncate(0)
|
74
|
+
line
|
75
|
+
end
|
54
76
|
end
|
55
77
|
end
|
56
78
|
end
|