fluentd 1.8.1-x86-mingw32 → 1.9.0-x86-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/.gitlab-ci.yml +14 -58
- data/.travis.yml +2 -17
- data/CHANGELOG.md +39 -0
- data/Gemfile +1 -4
- data/README.md +2 -6
- data/fluentd.gemspec +6 -6
- data/lib/fluent/command/cat.rb +1 -3
- data/lib/fluent/command/plugin_generator.rb +2 -1
- data/lib/fluent/config.rb +19 -0
- data/lib/fluent/config/literal_parser.rb +13 -8
- data/lib/fluent/config/v1_parser.rb +5 -3
- data/lib/fluent/engine.rb +60 -9
- data/lib/fluent/ext_monitor_require.rb +28 -0
- data/lib/fluent/load.rb +1 -1
- data/lib/fluent/msgpack_factory.rb +16 -4
- data/lib/fluent/plugin/base.rb +5 -0
- data/lib/fluent/plugin/buf_file.rb +10 -6
- data/lib/fluent/plugin/buf_file_single.rb +10 -6
- data/lib/fluent/plugin/buffer.rb +40 -22
- data/lib/fluent/plugin/buffer/chunk.rb +1 -1
- data/lib/fluent/plugin/in_http.rb +9 -9
- data/lib/fluent/plugin/in_tail.rb +8 -6
- data/lib/fluent/plugin/out_http.rb +2 -2
- data/lib/fluent/plugin/output.rb +2 -2
- data/lib/fluent/plugin/parser.rb +6 -0
- data/lib/fluent/plugin_helper/http_server.rb +0 -1
- data/lib/fluent/plugin_helper/record_accessor.rb +0 -8
- data/lib/fluent/plugin_helper/server.rb +6 -21
- data/lib/fluent/plugin_id.rb +9 -4
- data/lib/fluent/static_config_analysis.rb +194 -0
- data/lib/fluent/supervisor.rb +103 -28
- data/lib/fluent/system_config.rb +2 -1
- data/lib/fluent/test/driver/base.rb +4 -3
- data/lib/fluent/variable_store.rb +40 -0
- data/lib/fluent/version.rb +1 -1
- data/test/config/test_config_parser.rb +19 -16
- data/test/config/test_system_config.rb +6 -4
- data/test/plugin/test_in_exec.rb +9 -9
- data/test/plugin/test_in_forward.rb +10 -11
- data/test/plugin/test_in_http.rb +35 -3
- data/test/plugin/test_in_object_space.rb +3 -7
- data/test/plugin/test_out_exec_filter.rb +28 -45
- data/test/plugin/test_out_forward.rb +2 -2
- data/test/plugin/test_out_http.rb +8 -2
- data/test/plugin/test_output.rb +3 -3
- data/test/plugin/test_output_as_buffered.rb +1 -1
- data/test/plugin/test_output_as_buffered_overflow.rb +1 -1
- data/test/plugin/test_output_as_buffered_secondary.rb +2 -2
- data/test/plugin_helper/test_child_process.rb +45 -56
- data/test/plugin_helper/test_server.rb +13 -0
- data/test/plugin_helper/test_timer.rb +11 -13
- data/test/test_config.rb +27 -5
- data/test/test_engine.rb +203 -0
- data/test/test_output.rb +2 -2
- data/test/test_static_config_analysis.rb +177 -0
- data/test/test_supervisor.rb +18 -80
- data/test/test_test_drivers.rb +4 -3
- data/test/test_variable_store.rb +65 -0
- metadata +40 -27
- data/.gitlab/cicd-template.yaml +0 -10
- data/Vagrantfile +0 -17
@@ -0,0 +1,28 @@
|
|
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
|
+
# To avoid duplicated requirements, extract this logic as file.
|
18
|
+
|
19
|
+
if Gem::Version.create(RUBY_VERSION) >= Gem::Version.create('2.7.0')
|
20
|
+
require 'monitor'
|
21
|
+
else
|
22
|
+
begin
|
23
|
+
# monitor_ext is bundled since ruby 2.7.0
|
24
|
+
require 'ext_monitor'
|
25
|
+
rescue LoadError => _
|
26
|
+
require 'monitor'
|
27
|
+
end
|
28
|
+
end
|
data/lib/fluent/load.rb
CHANGED
@@ -2,7 +2,6 @@ require 'thread'
|
|
2
2
|
require 'socket'
|
3
3
|
require 'fcntl'
|
4
4
|
require 'time'
|
5
|
-
require 'monitor'
|
6
5
|
require 'stringio'
|
7
6
|
require 'fileutils'
|
8
7
|
require 'json'
|
@@ -33,3 +32,4 @@ require 'fluent/input'
|
|
33
32
|
require 'fluent/output'
|
34
33
|
require 'fluent/filter'
|
35
34
|
require 'fluent/match'
|
35
|
+
require 'fluent/ext_monitor_require'
|
@@ -44,8 +44,8 @@ module Fluent
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
def self.engine_factory
|
48
|
-
@@engine_factory || factory
|
47
|
+
def self.engine_factory(enable_time_support: false)
|
48
|
+
@@engine_factory || factory(enable_time_support: enable_time_support)
|
49
49
|
end
|
50
50
|
|
51
51
|
def self.msgpack_packer(*args)
|
@@ -56,9 +56,15 @@ module Fluent
|
|
56
56
|
engine_factory.unpacker(*args)
|
57
57
|
end
|
58
58
|
|
59
|
-
def self.factory
|
59
|
+
def self.factory(enable_time_support: false)
|
60
60
|
factory = MessagePack::Factory.new
|
61
61
|
factory.register_type(Fluent::EventTime::TYPE, Fluent::EventTime)
|
62
|
+
if enable_time_support
|
63
|
+
factory.register_type(
|
64
|
+
MessagePack::Timestamp::TYPE, Time,
|
65
|
+
packer: MessagePack::Time::Packer,
|
66
|
+
unpacker: MessagePack::Time::Unpacker)
|
67
|
+
end
|
62
68
|
factory
|
63
69
|
end
|
64
70
|
|
@@ -70,9 +76,15 @@ module Fluent
|
|
70
76
|
factory.unpacker(*args)
|
71
77
|
end
|
72
78
|
|
73
|
-
def self.init
|
79
|
+
def self.init(enable_time_support: false)
|
74
80
|
factory = MessagePack::Factory.new
|
75
81
|
factory.register_type(Fluent::EventTime::TYPE, Fluent::EventTime)
|
82
|
+
if enable_time_support
|
83
|
+
factory.register_type(
|
84
|
+
MessagePack::Timestamp::TYPE, Time,
|
85
|
+
packer: MessagePack::Time::Packer,
|
86
|
+
unpacker: MessagePack::Time::Unpacker)
|
87
|
+
end
|
76
88
|
@@engine_factory = factory
|
77
89
|
end
|
78
90
|
|
data/lib/fluent/plugin/base.rb
CHANGED
@@ -187,6 +187,11 @@ module Fluent
|
|
187
187
|
# https://github.com/ruby/ruby/blob/trunk/gc.c#L788
|
188
188
|
"#<%s:%014x>" % [self.class.name, '0x%014x' % (__id__ << 1)]
|
189
189
|
end
|
190
|
+
|
191
|
+
def reloadable_plugin?
|
192
|
+
# Engine can't capture all class variables. so it's forbbiden to use class variables in each plugins if enabling reload.
|
193
|
+
self.class.class_variables.empty?
|
194
|
+
end
|
190
195
|
end
|
191
196
|
end
|
192
197
|
end
|
@@ -19,6 +19,7 @@ require 'fileutils'
|
|
19
19
|
require 'fluent/plugin/buffer'
|
20
20
|
require 'fluent/plugin/buffer/file_chunk'
|
21
21
|
require 'fluent/system_config'
|
22
|
+
require 'fluent/variable_store'
|
22
23
|
|
23
24
|
module Fluent
|
24
25
|
module Plugin
|
@@ -43,19 +44,20 @@ module Fluent
|
|
43
44
|
config_param :file_permission, :string, default: nil # '0644'
|
44
45
|
config_param :dir_permission, :string, default: nil # '0755'
|
45
46
|
|
46
|
-
@@buffer_paths = {}
|
47
|
-
|
48
47
|
def initialize
|
49
48
|
super
|
50
49
|
@symlink_path = nil
|
51
50
|
@multi_workers_available = false
|
52
51
|
@additional_resume_path = nil
|
53
52
|
@buffer_path = nil
|
53
|
+
@variable_store = nil
|
54
54
|
end
|
55
55
|
|
56
56
|
def configure(conf)
|
57
57
|
super
|
58
58
|
|
59
|
+
@variable_store = Fluent::VariableStore.fetch_or_build(:buf_file)
|
60
|
+
|
59
61
|
multi_workers_configured = owner.system_config.workers > 1 ? true : false
|
60
62
|
|
61
63
|
using_plugin_root_dir = false
|
@@ -69,13 +71,13 @@ module Fluent
|
|
69
71
|
end
|
70
72
|
|
71
73
|
type_of_owner = Plugin.lookup_type_from_class(@_owner.class)
|
72
|
-
if
|
73
|
-
type_using_this_path =
|
74
|
+
if @variable_store.has_key?(@path) && !called_in_test?
|
75
|
+
type_using_this_path = @variable_store[@path]
|
74
76
|
raise ConfigError, "Other '#{type_using_this_path}' plugin already use same buffer path: type = #{type_of_owner}, buffer path = #{@path}"
|
75
77
|
end
|
76
78
|
|
77
79
|
@buffer_path = @path
|
78
|
-
|
80
|
+
@variable_store[@buffer_path] = type_of_owner
|
79
81
|
|
80
82
|
specified_directory_exists = File.exist?(@path) && File.directory?(@path)
|
81
83
|
unexisting_path_for_directory = !File.exist?(@path) && !@path.include?('.*')
|
@@ -125,7 +127,9 @@ module Fluent
|
|
125
127
|
end
|
126
128
|
|
127
129
|
def stop
|
128
|
-
|
130
|
+
if @variable_store
|
131
|
+
@variable_store.delete(@buffer_path)
|
132
|
+
end
|
129
133
|
|
130
134
|
super
|
131
135
|
end
|
@@ -19,6 +19,7 @@ require 'fileutils'
|
|
19
19
|
require 'fluent/plugin/buffer'
|
20
20
|
require 'fluent/plugin/buffer/file_single_chunk'
|
21
21
|
require 'fluent/system_config'
|
22
|
+
require 'fluent/variable_store'
|
22
23
|
|
23
24
|
module Fluent
|
24
25
|
module Plugin
|
@@ -48,18 +49,19 @@ module Fluent
|
|
48
49
|
desc 'The permission of chunk directory. If no specified, <system> setting or 0755 is used'
|
49
50
|
config_param :dir_permission, :string, default: nil
|
50
51
|
|
51
|
-
@@buffer_paths = {}
|
52
|
-
|
53
52
|
def initialize
|
54
53
|
super
|
55
54
|
|
56
55
|
@multi_workers_available = false
|
57
56
|
@additional_resume_path = nil
|
57
|
+
@variable_store = nil
|
58
58
|
end
|
59
59
|
|
60
60
|
def configure(conf)
|
61
61
|
super
|
62
62
|
|
63
|
+
@variable_store = Fluent::VariableStore.fetch_or_build(:buf_file_single)
|
64
|
+
|
63
65
|
if @chunk_format == :auto
|
64
66
|
@chunk_format = owner.formatted_to_msgpack_binary? ? :msgpack : :text
|
65
67
|
end
|
@@ -117,12 +119,12 @@ module Fluent
|
|
117
119
|
end
|
118
120
|
|
119
121
|
type_of_owner = Plugin.lookup_type_from_class(@_owner.class)
|
120
|
-
if
|
121
|
-
type_using_this_path =
|
122
|
+
if @variable_store.has_key?(@path) && !called_in_test?
|
123
|
+
type_using_this_path = @variable_store[@path]
|
122
124
|
raise Fluent::ConfigError, "Other '#{type_using_this_path}' plugin already uses same buffer path: type = #{type_of_owner}, buffer path = #{@path}"
|
123
125
|
end
|
124
126
|
|
125
|
-
|
127
|
+
@variable_store[@path] = type_of_owner
|
126
128
|
@dir_permission = if @dir_permission
|
127
129
|
@dir_permission.to_i(8)
|
128
130
|
else
|
@@ -145,7 +147,9 @@ module Fluent
|
|
145
147
|
end
|
146
148
|
|
147
149
|
def stop
|
148
|
-
|
150
|
+
if @variable_store
|
151
|
+
@variable_store.delete(@path)
|
152
|
+
end
|
149
153
|
|
150
154
|
super
|
151
155
|
end
|
data/lib/fluent/plugin/buffer.rb
CHANGED
@@ -17,8 +17,7 @@
|
|
17
17
|
require 'fluent/plugin/base'
|
18
18
|
require 'fluent/plugin/owned_by_mixin'
|
19
19
|
require 'fluent/unique_id'
|
20
|
-
|
21
|
-
require 'monitor'
|
20
|
+
require 'fluent/ext_monitor_require'
|
22
21
|
|
23
22
|
module Fluent
|
24
23
|
module Plugin
|
@@ -139,9 +138,12 @@ module Fluent
|
|
139
138
|
# Actually this overhead is very small but this class is generated *per chunk* (and used in hash object).
|
140
139
|
# This means that this class is one of the most called object in Fluentd.
|
141
140
|
# See https://github.com/fluent/fluentd/pull/2560
|
141
|
+
# But, this optimization has a side effect on Windows due to differing object_id.
|
142
|
+
# This difference causes flood of buffer files.
|
143
|
+
# So, this optimization should be enabled on non-Windows platform.
|
142
144
|
def hash
|
143
145
|
timekey.object_id
|
144
|
-
end
|
146
|
+
end unless Fluent.windows?
|
145
147
|
end
|
146
148
|
|
147
149
|
# for tests
|
@@ -266,10 +268,10 @@ module Fluent
|
|
266
268
|
|
267
269
|
log.on_trace { log.trace "writing events into buffer", instance: self.object_id, metadata_size: metadata_and_data.size }
|
268
270
|
|
269
|
-
staged_bytesize = 0
|
270
271
|
operated_chunks = []
|
271
272
|
unstaged_chunks = {} # metadata => [chunk, chunk, ...]
|
272
273
|
chunks_to_enqueue = []
|
274
|
+
staged_bytesizes_by_chunk = {}
|
273
275
|
|
274
276
|
begin
|
275
277
|
# sort metadata to get lock of chunks in same order with other threads
|
@@ -279,7 +281,13 @@ module Fluent
|
|
279
281
|
chunk.mon_enter # add lock to prevent to be committed/rollbacked from other threads
|
280
282
|
operated_chunks << chunk
|
281
283
|
if chunk.staged?
|
282
|
-
|
284
|
+
#
|
285
|
+
# https://github.com/fluent/fluentd/issues/2712
|
286
|
+
# write_once is supposed to write to a chunk only once
|
287
|
+
# but this block **may** run multiple times from write_step_by_step and previous write may be rollbacked
|
288
|
+
# So we should be counting the stage_size only for the last successful write
|
289
|
+
#
|
290
|
+
staged_bytesizes_by_chunk[chunk] = adding_bytesize
|
283
291
|
elsif chunk.unstaged?
|
284
292
|
unstaged_chunks[metadata] ||= []
|
285
293
|
unstaged_chunks[metadata] << chunk
|
@@ -326,27 +334,37 @@ module Fluent
|
|
326
334
|
|
327
335
|
# All locks about chunks are released.
|
328
336
|
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
337
|
+
#
|
338
|
+
# Now update the stage, stage_size with proper locking
|
339
|
+
# FIX FOR stage_size miscomputation - https://github.com/fluent/fluentd/issues/2712
|
340
|
+
#
|
341
|
+
staged_bytesizes_by_chunk.each do |chunk, bytesize|
|
342
|
+
chunk.synchronize do
|
343
|
+
synchronize { @stage_size += bytesize }
|
344
|
+
log.on_trace { log.trace { "chunk #{chunk.path} size_added: #{bytesize} new_size: #{chunk.bytesize}" } }
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
chunks_to_enqueue.each do |c|
|
349
|
+
if c.staged? && (enqueue || chunk_size_full?(c))
|
350
|
+
m = c.metadata
|
351
|
+
enqueue_chunk(m)
|
352
|
+
if unstaged_chunks[m]
|
353
|
+
u = unstaged_chunks[m].pop
|
354
|
+
u.synchronize do
|
339
355
|
if u.unstaged? && !chunk_size_full?(u)
|
340
|
-
|
341
|
-
|
356
|
+
synchronize {
|
357
|
+
@stage[m] = u.staged!
|
358
|
+
@stage_size += u.bytesize
|
359
|
+
}
|
342
360
|
end
|
343
361
|
end
|
344
|
-
elsif c.unstaged?
|
345
|
-
enqueue_unstaged_chunk(c)
|
346
|
-
else
|
347
|
-
# previously staged chunk is already enqueued, closed or purged.
|
348
|
-
# no problem.
|
349
362
|
end
|
363
|
+
elsif c.unstaged?
|
364
|
+
enqueue_unstaged_chunk(c)
|
365
|
+
else
|
366
|
+
# previously staged chunk is already enqueued, closed or purged.
|
367
|
+
# no problem.
|
350
368
|
end
|
351
369
|
end
|
352
370
|
|
@@ -331,29 +331,29 @@ module Fluent::Plugin
|
|
331
331
|
headers.each_pair {|k,v|
|
332
332
|
@env["HTTP_#{k.gsub('-','_').upcase}"] = v
|
333
333
|
case k
|
334
|
-
when /
|
334
|
+
when /\AExpect\z/i
|
335
335
|
expect = v
|
336
|
-
when
|
336
|
+
when /\AContent-Length\Z/i
|
337
337
|
size = v.to_i
|
338
|
-
when
|
338
|
+
when /\AContent-Type\Z/i
|
339
339
|
@content_type = v
|
340
|
-
when
|
340
|
+
when /\AContent-Encoding\Z/i
|
341
341
|
@content_encoding = v
|
342
|
-
when /
|
342
|
+
when /\AConnection\Z/i
|
343
343
|
if v =~ /close/i
|
344
344
|
@keep_alive = false
|
345
345
|
elsif v =~ /Keep-alive/i
|
346
346
|
@keep_alive = true
|
347
347
|
end
|
348
|
-
when /
|
348
|
+
when /\AOrigin\Z/i
|
349
349
|
@origin = v
|
350
|
-
when
|
350
|
+
when /\AX-Forwarded-For\Z/i
|
351
351
|
# For multiple X-Forwarded-For headers. Use first header value.
|
352
352
|
v = v.first if v.is_a?(Array)
|
353
353
|
@remote_addr = v.split(",").first
|
354
|
-
when
|
354
|
+
when /\AAccess-Control-Request-Method\Z/i
|
355
355
|
@access_control_request_method = v
|
356
|
-
when
|
356
|
+
when /\AAccess-Control-Request-Headers\Z/i
|
357
357
|
@access_control_request_headers = v
|
358
358
|
end
|
359
359
|
}
|
@@ -21,6 +21,7 @@ require 'fluent/config/error'
|
|
21
21
|
require 'fluent/event'
|
22
22
|
require 'fluent/plugin/buffer'
|
23
23
|
require 'fluent/plugin/parser_multiline'
|
24
|
+
require 'fluent/variable_store'
|
24
25
|
|
25
26
|
if Fluent.windows?
|
26
27
|
require_relative 'file_wrapper'
|
@@ -105,9 +106,8 @@ module Fluent::Plugin
|
|
105
106
|
|
106
107
|
attr_reader :paths
|
107
108
|
|
108
|
-
@@pos_file_paths = {}
|
109
|
-
|
110
109
|
def configure(conf)
|
110
|
+
@variable_store = Fluent::VariableStore.fetch_or_build(:in_tail)
|
111
111
|
compat_parameters_convert(conf, :parser)
|
112
112
|
parser_config = conf.elements('parse').first
|
113
113
|
unless parser_config
|
@@ -139,11 +139,11 @@ module Fluent::Plugin
|
|
139
139
|
|
140
140
|
# TODO: Use plugin_root_dir and storage plugin to store positions if available
|
141
141
|
if @pos_file
|
142
|
-
if
|
143
|
-
plugin_id_using_this_path =
|
142
|
+
if @variable_store.key?(@pos_file) && !called_in_test?
|
143
|
+
plugin_id_using_this_path = @variable_store[@pos_file]
|
144
144
|
raise Fluent::ConfigError, "Other 'in_tail' plugin already use same pos_file path: plugin_id = #{plugin_id_using_this_path}, pos_file path = #{@pos_file}"
|
145
145
|
end
|
146
|
-
|
146
|
+
@variable_store[@pos_file] = self.plugin_id
|
147
147
|
else
|
148
148
|
$log.warn "'pos_file PATH' parameter is not set to a 'tail' source."
|
149
149
|
$log.warn "this parameter is highly recommended to save the position to resume tailing."
|
@@ -212,7 +212,9 @@ module Fluent::Plugin
|
|
212
212
|
end
|
213
213
|
|
214
214
|
def stop
|
215
|
-
|
215
|
+
if @variable_store
|
216
|
+
@variable_store.delete(@pos_file)
|
217
|
+
end
|
216
218
|
|
217
219
|
super
|
218
220
|
end
|
@@ -212,9 +212,9 @@ module Fluent::Plugin
|
|
212
212
|
end
|
213
213
|
|
214
214
|
if res.is_a?(Net::HTTPSuccess)
|
215
|
-
log.debug { "#{res.code} #{res.message}#{res.body}" }
|
215
|
+
log.debug { "#{res.code} #{res.message.rstrip}#{res.body.lstrip}" }
|
216
216
|
else
|
217
|
-
msg = "#{res.code} #{res.message}#{res.body}"
|
217
|
+
msg = "#{res.code} #{res.message.rstrip} #{res.body.lstrip}"
|
218
218
|
|
219
219
|
if @retryable_response_codes.include?(res.code.to_i)
|
220
220
|
raise RetryableResponse, msg
|
data/lib/fluent/plugin/output.rb
CHANGED
@@ -25,9 +25,9 @@ require 'fluent/plugin_helper'
|
|
25
25
|
require 'fluent/timezone'
|
26
26
|
require 'fluent/unique_id'
|
27
27
|
require 'fluent/clock'
|
28
|
+
require 'fluent/ext_monitor_require'
|
28
29
|
|
29
30
|
require 'time'
|
30
|
-
require 'monitor'
|
31
31
|
|
32
32
|
module Fluent
|
33
33
|
module Plugin
|
@@ -387,7 +387,7 @@ module Fluent
|
|
387
387
|
@secondary.acts_as_secondary(self)
|
388
388
|
@secondary.configure(secondary_conf)
|
389
389
|
if (self.class != @secondary.class) && (@custom_format || @secondary.implement?(:custom_format))
|
390
|
-
log.warn "secondary
|
390
|
+
log.warn "Use different plugin for secondary. Check the plugin works with primary like secondary_file", primary: self.class.to_s, secondary: @secondary.class.to_s
|
391
391
|
end
|
392
392
|
else
|
393
393
|
@secondary = nil
|