fluentd 1.16.5-x86-mingw32 → 1.17.0-x86-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/DISCUSSION_TEMPLATE/q-a-japanese.yml +50 -0
- data/.github/DISCUSSION_TEMPLATE/q-a.yml +47 -0
- data/.github/workflows/test-ruby-head.yml +31 -0
- data/.github/workflows/test.yml +3 -3
- data/CHANGELOG.md +42 -0
- data/README.md +1 -1
- data/Rakefile +1 -1
- data/fluentd.gemspec +9 -1
- data/lib/fluent/command/binlog_reader.rb +1 -1
- data/lib/fluent/config/configure_proxy.rb +2 -2
- data/lib/fluent/config/types.rb +1 -1
- data/lib/fluent/configurable.rb +2 -2
- data/lib/fluent/counter/mutex_hash.rb +1 -1
- data/lib/fluent/fluent_log_event_router.rb +0 -2
- data/lib/fluent/plugin/buf_file.rb +1 -1
- data/lib/fluent/plugin/buffer/file_chunk.rb +1 -1
- data/lib/fluent/plugin/buffer/file_single_chunk.rb +2 -3
- data/lib/fluent/plugin/filter_parser.rb +26 -8
- data/lib/fluent/plugin/in_http.rb +18 -53
- data/lib/fluent/plugin/in_tail.rb +34 -2
- data/lib/fluent/plugin/out_http.rb +125 -13
- data/lib/fluent/plugin/owned_by_mixin.rb +0 -1
- data/lib/fluent/plugin/parser_json.rb +22 -5
- data/lib/fluent/plugin/parser_msgpack.rb +24 -3
- data/lib/fluent/plugin_helper/metrics.rb +2 -2
- data/lib/fluent/registry.rb +6 -6
- data/lib/fluent/test/output_test.rb +1 -1
- data/lib/fluent/unique_id.rb +1 -1
- data/lib/fluent/version.rb +1 -1
- data/test/log/test_console_adapter.rb +10 -3
- data/test/plugin/data/log_numeric/01.log +0 -0
- data/test/plugin/data/log_numeric/02.log +0 -0
- data/test/plugin/data/log_numeric/12.log +0 -0
- data/test/plugin/data/log_numeric/14.log +0 -0
- data/test/plugin/test_in_http.rb +23 -1
- data/test/plugin/test_in_tail.rb +141 -0
- data/test/plugin/test_out_http.rb +128 -0
- data/test/plugin/test_owned_by.rb +0 -1
- data/test/plugin/test_parser_json.rb +106 -0
- data/test/plugin/test_parser_msgpack.rb +127 -0
- data/test/plugin/test_storage.rb +0 -1
- data/test/plugin_helper/test_child_process.rb +4 -4
- metadata +101 -4
@@ -37,6 +37,8 @@ module Fluent::Plugin
|
|
37
37
|
|
38
38
|
class RetryableResponse < StandardError; end
|
39
39
|
|
40
|
+
ConnectionCache = Struct.new(:uri, :conn)
|
41
|
+
|
40
42
|
helpers :formatter
|
41
43
|
|
42
44
|
desc 'The endpoint for HTTP request, e.g. http://example.com/api'
|
@@ -60,6 +62,8 @@ module Fluent::Plugin
|
|
60
62
|
config_param :read_timeout, :integer, default: nil
|
61
63
|
desc 'The TLS timeout in seconds'
|
62
64
|
config_param :ssl_timeout, :integer, default: nil
|
65
|
+
desc 'Try to reuse connections'
|
66
|
+
config_param :reuse_connections, :bool, default: false
|
63
67
|
|
64
68
|
desc 'The CA certificate path for TLS'
|
65
69
|
config_param :tls_ca_cert_path, :string, default: nil
|
@@ -87,11 +91,29 @@ module Fluent::Plugin
|
|
87
91
|
|
88
92
|
config_section :auth, required: false, multi: false do
|
89
93
|
desc 'The method for HTTP authentication'
|
90
|
-
config_param :method, :enum, list: [:basic], default: :basic
|
94
|
+
config_param :method, :enum, list: [:basic, :aws_sigv4], default: :basic
|
91
95
|
desc 'The username for basic authentication'
|
92
96
|
config_param :username, :string, default: nil
|
93
97
|
desc 'The password for basic authentication'
|
94
98
|
config_param :password, :string, default: nil, secret: true
|
99
|
+
desc 'The AWS service to authenticate against'
|
100
|
+
config_param :aws_service, :string, default: nil
|
101
|
+
desc 'The AWS region to use when authenticating'
|
102
|
+
config_param :aws_region, :string, default: nil
|
103
|
+
desc 'The AWS role ARN to assume when authenticating'
|
104
|
+
config_param :aws_role_arn, :string, default: nil
|
105
|
+
end
|
106
|
+
|
107
|
+
def connection_cache_id_thread_key
|
108
|
+
"#{plugin_id}_connection_cache_id"
|
109
|
+
end
|
110
|
+
|
111
|
+
def connection_cache_id_for_thread
|
112
|
+
Thread.current[connection_cache_id_thread_key]
|
113
|
+
end
|
114
|
+
|
115
|
+
def connection_cache_id_for_thread=(id)
|
116
|
+
Thread.current[connection_cache_id_thread_key] = id
|
95
117
|
end
|
96
118
|
|
97
119
|
def initialize
|
@@ -100,11 +122,23 @@ module Fluent::Plugin
|
|
100
122
|
@uri = nil
|
101
123
|
@proxy_uri = nil
|
102
124
|
@formatter = nil
|
125
|
+
|
126
|
+
@connection_cache = []
|
127
|
+
@connection_cache_id_mutex = Mutex.new
|
128
|
+
@connection_cache_next_id = 0
|
129
|
+
end
|
130
|
+
|
131
|
+
def close
|
132
|
+
super
|
133
|
+
|
134
|
+
@connection_cache.each {|entry| entry.conn.finish if entry.conn&.started? }
|
103
135
|
end
|
104
136
|
|
105
137
|
def configure(conf)
|
106
138
|
super
|
107
139
|
|
140
|
+
@connection_cache = Array.new(actual_flush_thread_count, ConnectionCache.new("", nil)) if @reuse_connections
|
141
|
+
|
108
142
|
if @retryable_response_codes.nil?
|
109
143
|
log.warn('Status code 503 is going to be removed from default `retryable_response_codes` from fluentd v2. Please add it by yourself if you wish')
|
110
144
|
@retryable_response_codes = [503]
|
@@ -121,6 +155,36 @@ module Fluent::Plugin
|
|
121
155
|
end
|
122
156
|
define_singleton_method(:format, method(:format_json_array))
|
123
157
|
end
|
158
|
+
|
159
|
+
if @auth and @auth.method == :aws_sigv4
|
160
|
+
begin
|
161
|
+
require 'aws-sigv4'
|
162
|
+
require 'aws-sdk-core'
|
163
|
+
rescue LoadError
|
164
|
+
raise Fluent::ConfigError, "The aws-sdk-core and aws-sigv4 gems are required for aws_sigv4 auth. Run: gem install aws-sdk-core -v '~> 3.191'"
|
165
|
+
end
|
166
|
+
|
167
|
+
raise Fluent::ConfigError, "aws_service is required for aws_sigv4 auth" unless @auth.aws_service != nil
|
168
|
+
raise Fluent::ConfigError, "aws_region is required for aws_sigv4 auth" unless @auth.aws_region != nil
|
169
|
+
|
170
|
+
if @auth.aws_role_arn == nil
|
171
|
+
aws_credentials = Aws::CredentialProviderChain.new.resolve
|
172
|
+
else
|
173
|
+
aws_credentials = Aws::AssumeRoleCredentials.new(
|
174
|
+
client: Aws::STS::Client.new(
|
175
|
+
region: @auth.aws_region
|
176
|
+
),
|
177
|
+
role_arn: @auth.aws_role_arn,
|
178
|
+
role_session_name: "fluentd"
|
179
|
+
)
|
180
|
+
end
|
181
|
+
|
182
|
+
@aws_signer = Aws::Sigv4::Signer.new(
|
183
|
+
service: @auth.aws_service,
|
184
|
+
region: @auth.aws_region,
|
185
|
+
credentials_provider: aws_credentials
|
186
|
+
)
|
187
|
+
end
|
124
188
|
end
|
125
189
|
|
126
190
|
def multi_workers_ready?
|
@@ -215,7 +279,7 @@ module Fluent::Plugin
|
|
215
279
|
URI.parse(endpoint)
|
216
280
|
end
|
217
281
|
|
218
|
-
def set_headers(req, chunk)
|
282
|
+
def set_headers(req, uri, chunk)
|
219
283
|
if @headers
|
220
284
|
@headers.each do |k, v|
|
221
285
|
req[k] = v
|
@@ -229,6 +293,28 @@ module Fluent::Plugin
|
|
229
293
|
req['Content-Type'] = @content_type
|
230
294
|
end
|
231
295
|
|
296
|
+
def set_auth(req, uri)
|
297
|
+
return unless @auth
|
298
|
+
|
299
|
+
if @auth.method == :basic
|
300
|
+
req.basic_auth(@auth.username, @auth.password)
|
301
|
+
elsif @auth.method == :aws_sigv4
|
302
|
+
signature = @aws_signer.sign_request(
|
303
|
+
http_method: req.method,
|
304
|
+
url: uri.request_uri,
|
305
|
+
headers: {
|
306
|
+
'Content-Type' => @content_type,
|
307
|
+
'Host' => uri.host
|
308
|
+
},
|
309
|
+
body: req.body
|
310
|
+
)
|
311
|
+
req.add_field('x-amz-date', signature.headers['x-amz-date'])
|
312
|
+
req.add_field('x-amz-security-token', signature.headers['x-amz-security-token'])
|
313
|
+
req.add_field('x-amz-content-sha256', signature.headers['x-amz-content-sha256'])
|
314
|
+
req.add_field('authorization', signature.headers['authorization'])
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
232
318
|
def create_request(chunk, uri)
|
233
319
|
req = case @http_method
|
234
320
|
when :post
|
@@ -236,23 +322,49 @@ module Fluent::Plugin
|
|
236
322
|
when :put
|
237
323
|
Net::HTTP::Put.new(uri.request_uri)
|
238
324
|
end
|
239
|
-
|
240
|
-
req.basic_auth(@auth.username, @auth.password)
|
241
|
-
end
|
242
|
-
set_headers(req, chunk)
|
325
|
+
set_headers(req, uri, chunk)
|
243
326
|
req.body = @json_array ? "[#{chunk.read.chop}]" : chunk.read
|
327
|
+
|
328
|
+
# At least one authentication method requires the body and other headers, so the order of this call matters
|
329
|
+
set_auth(req, uri)
|
244
330
|
req
|
245
331
|
end
|
246
332
|
|
333
|
+
def make_request_cached(uri, req)
|
334
|
+
id = self.connection_cache_id_for_thread
|
335
|
+
if id.nil?
|
336
|
+
@connection_cache_id_mutex.synchronize {
|
337
|
+
id = @connection_cache_next_id
|
338
|
+
@connection_cache_next_id += 1
|
339
|
+
}
|
340
|
+
self.connection_cache_id_for_thread = id
|
341
|
+
end
|
342
|
+
uri_str = uri.to_s
|
343
|
+
if @connection_cache[id].uri != uri_str
|
344
|
+
@connection_cache[id].conn.finish if @connection_cache[id].conn&.started?
|
345
|
+
http = if @proxy_uri
|
346
|
+
Net::HTTP.start(uri.host, uri.port, @proxy_uri.host, @proxy_uri.port, @proxy_uri.user, @proxy_uri.password, @http_opt)
|
347
|
+
else
|
348
|
+
Net::HTTP.start(uri.host, uri.port, @http_opt)
|
349
|
+
end
|
350
|
+
@connection_cache[id] = ConnectionCache.new(uri_str, http)
|
351
|
+
end
|
352
|
+
@connection_cache[id].conn.request(req)
|
353
|
+
end
|
354
|
+
|
355
|
+
def make_request(uri, req, &block)
|
356
|
+
if @proxy_uri
|
357
|
+
Net::HTTP.start(uri.host, uri.port, @proxy_uri.host, @proxy_uri.port, @proxy_uri.user, @proxy_uri.password, @http_opt, &block)
|
358
|
+
else
|
359
|
+
Net::HTTP.start(uri.host, uri.port, @http_opt, &block)
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
247
363
|
def send_request(uri, req)
|
248
|
-
res = if @
|
249
|
-
|
250
|
-
http.request(req)
|
251
|
-
}
|
364
|
+
res = if @reuse_connections
|
365
|
+
make_request_cached(uri, req)
|
252
366
|
else
|
253
|
-
|
254
|
-
http.request(req)
|
255
|
-
}
|
367
|
+
make_request(uri, req) { |http| http.request(req) }
|
256
368
|
end
|
257
369
|
|
258
370
|
if res.is_a?(Net::HTTPSuccess)
|
@@ -70,16 +70,33 @@ module Fluent
|
|
70
70
|
end
|
71
71
|
|
72
72
|
def parse(text)
|
73
|
-
|
74
|
-
|
75
|
-
if
|
76
|
-
time, record =
|
73
|
+
parsed_json = @load_proc.call(text)
|
74
|
+
|
75
|
+
if parsed_json.is_a?(Hash)
|
76
|
+
time, record = parse_one_record(parsed_json)
|
77
|
+
yield time, record
|
78
|
+
elsif parsed_json.is_a?(Array)
|
79
|
+
parsed_json.each do |record|
|
80
|
+
unless record.is_a?(Hash)
|
81
|
+
yield nil, nil
|
82
|
+
next
|
83
|
+
end
|
84
|
+
time, parsed_record = parse_one_record(record)
|
85
|
+
yield time, parsed_record
|
86
|
+
end
|
87
|
+
else
|
88
|
+
yield nil, nil
|
77
89
|
end
|
78
|
-
|
90
|
+
|
79
91
|
rescue @error_class, EncodingError # EncodingError is for oj 3.x or later
|
80
92
|
yield nil, nil
|
81
93
|
end
|
82
94
|
|
95
|
+
def parse_one_record(record)
|
96
|
+
time = parse_time(record)
|
97
|
+
convert_values(time, record)
|
98
|
+
end
|
99
|
+
|
83
100
|
def parser_type
|
84
101
|
:text
|
85
102
|
end
|
@@ -31,9 +31,9 @@ module Fluent
|
|
31
31
|
:binary
|
32
32
|
end
|
33
33
|
|
34
|
-
def parse(data)
|
34
|
+
def parse(data, &block)
|
35
35
|
@unpacker.feed_each(data) do |obj|
|
36
|
-
|
36
|
+
parse_unpacked_data(obj, &block)
|
37
37
|
end
|
38
38
|
end
|
39
39
|
alias parse_partial_data parse
|
@@ -41,8 +41,29 @@ module Fluent
|
|
41
41
|
def parse_io(io, &block)
|
42
42
|
u = Fluent::MessagePackFactory.engine_factory.unpacker(io)
|
43
43
|
u.each do |obj|
|
44
|
-
|
44
|
+
parse_unpacked_data(obj, &block)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def parse_unpacked_data(data)
|
49
|
+
if data.is_a?(Hash)
|
50
|
+
time, record = convert_values(parse_time(data), data)
|
45
51
|
yield time, record
|
52
|
+
return
|
53
|
+
end
|
54
|
+
|
55
|
+
unless data.is_a?(Array)
|
56
|
+
yield nil, nil
|
57
|
+
return
|
58
|
+
end
|
59
|
+
|
60
|
+
data.each do |record|
|
61
|
+
unless record.is_a?(Hash)
|
62
|
+
yield nil, nil
|
63
|
+
next
|
64
|
+
end
|
65
|
+
time, converted_record = convert_values(parse_time(record), record)
|
66
|
+
yield time, converted_record
|
46
67
|
end
|
47
68
|
end
|
48
69
|
end
|
@@ -65,9 +65,9 @@ module Fluent
|
|
65
65
|
metrics.configure(config)
|
66
66
|
# For multi workers environment, cmetrics should be distinguish with static labels.
|
67
67
|
if Fluent::Engine.system_config.workers > 1
|
68
|
-
labels
|
68
|
+
labels[:worker_id] = fluentd_worker_id.to_s
|
69
69
|
end
|
70
|
-
labels
|
70
|
+
labels[:plugin] = @plugin_type_or_id
|
71
71
|
metrics.create(namespace: namespace, subsystem: subsystem, name: name, help_text: help_text, labels: labels)
|
72
72
|
|
73
73
|
@_metrics["#{@plugin_type_or_id}_#{namespace}_#{subsystem}_#{name}"] = metrics
|
data/lib/fluent/registry.rb
CHANGED
@@ -60,13 +60,13 @@ module Fluent
|
|
60
60
|
# search from additional plugin directories
|
61
61
|
if @dir_search_prefix
|
62
62
|
path = "#{@dir_search_prefix}#{type}"
|
63
|
-
files = @paths.
|
63
|
+
files = @paths.filter_map { |lp|
|
64
64
|
lpath = File.expand_path(File.join(lp, "#{path}.rb"))
|
65
65
|
File.exist?(lpath) ? lpath : nil
|
66
|
-
}
|
66
|
+
}
|
67
67
|
unless files.empty?
|
68
68
|
# prefer newer version
|
69
|
-
require files.
|
69
|
+
require files.max
|
70
70
|
return
|
71
71
|
end
|
72
72
|
end
|
@@ -74,17 +74,17 @@ module Fluent
|
|
74
74
|
path = "#{@search_prefix}#{type}"
|
75
75
|
|
76
76
|
# prefer LOAD_PATH than gems
|
77
|
-
files = $LOAD_PATH.
|
77
|
+
files = $LOAD_PATH.filter_map { |lp|
|
78
78
|
if lp == FLUENT_LIB_PATH
|
79
79
|
nil
|
80
80
|
else
|
81
81
|
lpath = File.expand_path(File.join(lp, "#{path}.rb"))
|
82
82
|
File.exist?(lpath) ? lpath : nil
|
83
83
|
end
|
84
|
-
}
|
84
|
+
}
|
85
85
|
unless files.empty?
|
86
86
|
# prefer newer version
|
87
|
-
require files.
|
87
|
+
require files.max
|
88
88
|
return
|
89
89
|
end
|
90
90
|
|
data/lib/fluent/unique_id.rb
CHANGED
data/lib/fluent/version.rb
CHANGED
@@ -72,11 +72,18 @@ class ConsoleAdapterTest < Test::Unit::TestCase
|
|
72
72
|
fatal: :fatal)
|
73
73
|
def test_options(level)
|
74
74
|
@console_logger.send(level, "subject", kwarg1: "opt1", kwarg2: "opt2")
|
75
|
+
lines = @logdev.logs[0].split("\n")
|
76
|
+
args = JSON.load(lines[1..].collect { |str| str.sub(/\s+\|/, "") }.join("\n"));
|
75
77
|
assert_equal([
|
76
|
-
|
77
|
-
"
|
78
|
+
1,
|
79
|
+
"#{@timestamp_str} [#{level}]: 0.0s: subject",
|
80
|
+
{ "kwarg1" => "opt1", "kwarg2" => "opt2" }
|
78
81
|
],
|
79
|
-
|
82
|
+
[
|
83
|
+
@logdev.logs.size,
|
84
|
+
lines[0],
|
85
|
+
args
|
86
|
+
])
|
80
87
|
end
|
81
88
|
|
82
89
|
data(debug: :debug,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/test/plugin/test_in_http.rb
CHANGED
@@ -517,6 +517,28 @@ class HttpInputTest < Test::Unit::TestCase
|
|
517
517
|
assert_equal_event_time time, d.events[1][1]
|
518
518
|
end
|
519
519
|
|
520
|
+
def test_csp_report
|
521
|
+
d = create_driver
|
522
|
+
time = event_time("2011-01-02 13:14:15 UTC")
|
523
|
+
time_i = time.to_i
|
524
|
+
events = [
|
525
|
+
["tag1", time, {"a"=>1}],
|
526
|
+
["tag2", time, {"a"=>2}],
|
527
|
+
]
|
528
|
+
res_codes = []
|
529
|
+
|
530
|
+
d.run(expect_records: 2) do
|
531
|
+
events.each do |tag, t, record|
|
532
|
+
res = post("/#{tag}?time=#{time_i.to_s}", record.to_json, {"Content-Type"=>"application/csp-report; charset=utf-8"})
|
533
|
+
res_codes << res.code
|
534
|
+
end
|
535
|
+
end
|
536
|
+
assert_equal ["200", "200"], res_codes
|
537
|
+
assert_equal events, d.events
|
538
|
+
assert_equal_event_time time, d.events[0][1]
|
539
|
+
assert_equal_event_time time, d.events[1][1]
|
540
|
+
end
|
541
|
+
|
520
542
|
def test_application_msgpack
|
521
543
|
d = create_driver
|
522
544
|
time = event_time("2011-01-02 13:14:15 UTC")
|
@@ -982,7 +1004,7 @@ class HttpInputTest < Test::Unit::TestCase
|
|
982
1004
|
assert_equal ["403", "403"], res_codes
|
983
1005
|
end
|
984
1006
|
|
985
|
-
def test_add_query_params
|
1007
|
+
def test_add_query_params
|
986
1008
|
d = create_driver(config + "add_query_params true")
|
987
1009
|
assert_equal true, d.instance.add_query_params
|
988
1010
|
|
data/test/plugin/test_in_tail.rb
CHANGED
@@ -1538,6 +1538,147 @@ class TailInputTest < Test::Unit::TestCase
|
|
1538
1538
|
assert_equal(ex_paths - [ex_paths.last], plugin.expand_paths.values.sort_by { |path_ino| path_ino.path })
|
1539
1539
|
end
|
1540
1540
|
|
1541
|
+
sub_test_case "expand_paths with glob" do |data|
|
1542
|
+
sub_test_case "extended_glob" do
|
1543
|
+
data("curly braces" => [true, "always", "test/plugin/data/log_numeric/{0,1}*.log"],
|
1544
|
+
"square brackets" => [true, "always", "test/plugin/data/log_numeric/[0-1][2-4].log"],
|
1545
|
+
"asterisk" => [true, "always", "test/plugin/data/log/*.log"],
|
1546
|
+
"one character matcher" => [true, "always", "test/plugin/data/log/tes?.log"],
|
1547
|
+
)
|
1548
|
+
def test_expand_paths_with_use_glob_p_and_almost_set_of_patterns
|
1549
|
+
result, option, path = data
|
1550
|
+
config = config_element("", "", {
|
1551
|
+
"tag" => "tail",
|
1552
|
+
"path" => path,
|
1553
|
+
"format" => "none",
|
1554
|
+
"pos_file" => "#{@tmp_dir}/tail.pos",
|
1555
|
+
"read_from_head" => true,
|
1556
|
+
"refresh_interval" => 30,
|
1557
|
+
"glob_policy" => option,
|
1558
|
+
"path_delimiter" => "|",
|
1559
|
+
"rotate_wait" => "#{EX_ROTATE_WAIT}s",
|
1560
|
+
"follow_inodes" => "#{EX_FOLLOW_INODES}",
|
1561
|
+
})
|
1562
|
+
plugin = create_driver(config, false).instance
|
1563
|
+
assert_equal(result, !!plugin.use_glob?(path))
|
1564
|
+
end
|
1565
|
+
|
1566
|
+
data("curly braces" => [true, false, "extended", "test/plugin/data/log_numeric/{0,1}*.log"],
|
1567
|
+
"square brackets" => [false, true, "extended", "test/plugin/data/log_numeric/[0-1][2-4].log"],
|
1568
|
+
"asterisk" => [false, true, "extended", "test/plugin/data/log/*.log"],
|
1569
|
+
"one character matcher" => [false, true, "extended", "test/plugin/data/log/tes?.log"],
|
1570
|
+
)
|
1571
|
+
def test_expand_paths_with_use_glob_p
|
1572
|
+
emit_exception_p, result, option, path = data
|
1573
|
+
config = config_element("", "", {
|
1574
|
+
"tag" => "tail",
|
1575
|
+
"path" => path,
|
1576
|
+
"format" => "none",
|
1577
|
+
"pos_file" => "#{@tmp_dir}/tail.pos",
|
1578
|
+
"read_from_head" => true,
|
1579
|
+
"refresh_interval" => 30,
|
1580
|
+
"glob_policy" => option,
|
1581
|
+
"rotate_wait" => "#{EX_ROTATE_WAIT}s",
|
1582
|
+
"follow_inodes" => "#{EX_FOLLOW_INODES}",
|
1583
|
+
})
|
1584
|
+
if emit_exception_p
|
1585
|
+
assert_raise(Fluent::ConfigError) do
|
1586
|
+
plugin = create_driver(config, false).instance
|
1587
|
+
end
|
1588
|
+
else
|
1589
|
+
plugin = create_driver(config, false).instance
|
1590
|
+
assert_equal(result, !!plugin.use_glob?(path))
|
1591
|
+
end
|
1592
|
+
end
|
1593
|
+
end
|
1594
|
+
|
1595
|
+
sub_test_case "only_use_backward_compatible" do
|
1596
|
+
data("square brackets" => [false, "backward_compatible", "test/plugin/data/log_numeric/[0-1][2-4].log"],
|
1597
|
+
"asterisk" => [true, "backward_compatible", "test/plugin/data/log/*.log"],
|
1598
|
+
"one character matcher" => [false, "backward_compatible", "test/plugin/data/log/tes?.log"],
|
1599
|
+
)
|
1600
|
+
def test_expand_paths_with_use_glob_p
|
1601
|
+
result, option, path = data
|
1602
|
+
config = config_element("", "", {
|
1603
|
+
"tag" => "tail",
|
1604
|
+
"path" => path,
|
1605
|
+
"format" => "none",
|
1606
|
+
"pos_file" => "#{@tmp_dir}/tail.pos",
|
1607
|
+
"read_from_head" => true,
|
1608
|
+
"refresh_interval" => 30,
|
1609
|
+
"glob_policy" => option,
|
1610
|
+
"rotate_wait" => "#{EX_ROTATE_WAIT}s",
|
1611
|
+
"follow_inodes" => "#{EX_FOLLOW_INODES}",
|
1612
|
+
})
|
1613
|
+
plugin = create_driver(config, false).instance
|
1614
|
+
assert_equal(result, !!plugin.use_glob?(path))
|
1615
|
+
end
|
1616
|
+
end
|
1617
|
+
end
|
1618
|
+
|
1619
|
+
def ex_config_with_brackets
|
1620
|
+
config_element("", "", {
|
1621
|
+
"tag" => "tail",
|
1622
|
+
"path" => "test/plugin/data/log_numeric/[0-1][2-4].log",
|
1623
|
+
"format" => "none",
|
1624
|
+
"pos_file" => "#{@tmp_dir}/tail.pos",
|
1625
|
+
"read_from_head" => true,
|
1626
|
+
"refresh_interval" => 30,
|
1627
|
+
"glob_policy" => "extended",
|
1628
|
+
"rotate_wait" => "#{EX_ROTATE_WAIT}s",
|
1629
|
+
"follow_inodes" => "#{EX_FOLLOW_INODES}",
|
1630
|
+
})
|
1631
|
+
end
|
1632
|
+
|
1633
|
+
def test_config_with_always_with_default_delimiter
|
1634
|
+
assert_raise(Fluent::ConfigError) do
|
1635
|
+
config = config_element("", "", {
|
1636
|
+
"tag" => "tail",
|
1637
|
+
"path" => "test/plugin/data/log_numeric/[0-1][2-4].log",
|
1638
|
+
"format" => "none",
|
1639
|
+
"pos_file" => "#{@tmp_dir}/tail.pos",
|
1640
|
+
"read_from_head" => true,
|
1641
|
+
"refresh_interval" => 30,
|
1642
|
+
"glob_policy" => "always",
|
1643
|
+
"rotate_wait" => "#{EX_ROTATE_WAIT}s",
|
1644
|
+
"follow_inodes" => "#{EX_FOLLOW_INODES}",
|
1645
|
+
})
|
1646
|
+
|
1647
|
+
create_driver(config, false).instance
|
1648
|
+
end
|
1649
|
+
end
|
1650
|
+
|
1651
|
+
def test_config_with_always_with_custom_delimiter
|
1652
|
+
assert_nothing_raised do
|
1653
|
+
config = config_element("", "", {
|
1654
|
+
"tag" => "tail",
|
1655
|
+
"path" => "test/plugin/data/log_numeric/[0-1][2-4].log",
|
1656
|
+
"format" => "none",
|
1657
|
+
"pos_file" => "#{@tmp_dir}/tail.pos",
|
1658
|
+
"read_from_head" => true,
|
1659
|
+
"refresh_interval" => 30,
|
1660
|
+
"glob_policy" => "always",
|
1661
|
+
"path_delimiter" => "|",
|
1662
|
+
"rotate_wait" => "#{EX_ROTATE_WAIT}s",
|
1663
|
+
"follow_inodes" => "#{EX_FOLLOW_INODES}",
|
1664
|
+
})
|
1665
|
+
|
1666
|
+
create_driver(config, false).instance
|
1667
|
+
end
|
1668
|
+
end
|
1669
|
+
|
1670
|
+
def test_expand_paths_with_brackets
|
1671
|
+
expanded_paths = [
|
1672
|
+
create_target_info('test/plugin/data/log_numeric/01.log'),
|
1673
|
+
create_target_info('test/plugin/data/log_numeric/02.log'),
|
1674
|
+
create_target_info('test/plugin/data/log_numeric/12.log'),
|
1675
|
+
create_target_info('test/plugin/data/log_numeric/14.log'),
|
1676
|
+
]
|
1677
|
+
|
1678
|
+
plugin = create_driver(ex_config_with_brackets, false).instance
|
1679
|
+
assert_equal(expanded_paths - [expanded_paths.first], plugin.expand_paths.values.sort_by { |path_ino| path_ino.path })
|
1680
|
+
end
|
1681
|
+
|
1541
1682
|
def test_expand_paths_with_duplicate_configuration
|
1542
1683
|
expanded_paths = [
|
1543
1684
|
create_target_info('test/plugin/data/log/foo/bar.log'),
|