fluentd 1.0.2 → 1.1.0
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 +7 -1
- data/CHANGELOG.md +26 -0
- data/bin/fluent-ca-generate +6 -0
- data/fluentd.gemspec +1 -1
- data/lib/fluent/command/ca_generate.rb +179 -0
- data/lib/fluent/config/literal_parser.rb +6 -0
- data/lib/fluent/log.rb +29 -19
- data/lib/fluent/plugin/buffer.rb +17 -9
- data/lib/fluent/plugin/filter_record_transformer.rb +7 -2
- data/lib/fluent/plugin/formatter_stdout.rb +3 -2
- data/lib/fluent/plugin/out_stdout.rb +0 -1
- data/lib/fluent/plugin/output.rb +3 -2
- data/lib/fluent/plugin/parser_ltsv.rb +9 -0
- data/lib/fluent/plugin_helper/record_accessor.rb +34 -3
- data/lib/fluent/plugin_helper/server.rb +3 -0
- data/lib/fluent/time.rb +10 -7
- data/lib/fluent/timezone.rb +12 -2
- data/lib/fluent/version.rb +1 -1
- data/test/command/test_ca_generate.rb +70 -0
- data/test/command/test_fluentd.rb +2 -2
- data/test/config/test_literal_parser.rb +8 -0
- data/test/plugin/test_filter_record_transformer.rb +10 -1
- data/test/plugin/test_parser_labeled_tsv.rb +17 -0
- data/test/plugin_helper/test_record_accessor.rb +67 -0
- metadata +17 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f7457e2a191772c11ca520188030ea3ef06c211d
|
4
|
+
data.tar.gz: 2ae8a9864a31245d3fca6756cb4f39c82aed53fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ad103cd892630b1c15452a4749ddba854b2ca73e87bbe252bdf75a7a85964589801e21d002bf6140b23d107dbed207e856a0eaee275ea04c895ebb5df31d361
|
7
|
+
data.tar.gz: 44cfc8efcc83ac52e55fb35afcc93486dbb44ed9ee84ac20fa8da335a011812f04eb256bdb55d741facc8bdbb5e87728d75c11f118fe370f7690b553b082223a
|
data/.travis.yml
CHANGED
@@ -31,8 +31,14 @@ matrix:
|
|
31
31
|
osx_image: xcode8.3 # OSX 10.12
|
32
32
|
- rvm: ruby-head
|
33
33
|
os: osx
|
34
|
-
osx_image:
|
34
|
+
osx_image: xcode8.3 # OSX 10.12
|
35
35
|
allow_failures:
|
36
|
+
- rvm: 2.1.10
|
37
|
+
os: osx
|
38
|
+
osx_image: xcode8.3
|
39
|
+
- rvm: 2.4.1
|
40
|
+
os: osx
|
41
|
+
osx_image: xcode8.3
|
36
42
|
- rvm: ruby-head
|
37
43
|
|
38
44
|
branches:
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,31 @@
|
|
1
1
|
# v1.0
|
2
2
|
|
3
|
+
## Release v1.1.0 - 2018/01/17
|
4
|
+
|
5
|
+
### New features / Enhancements
|
6
|
+
|
7
|
+
* config: Add hostname and worker_id short-cut
|
8
|
+
https://github.com/fluent/fluentd/pull/1814
|
9
|
+
* parser_ltsv: Add delimiter_pattern parameter
|
10
|
+
https://github.com/fluent/fluentd/pull/1802
|
11
|
+
* record_accessor helper: Support nested field deletion
|
12
|
+
https://github.com/fluent/fluentd/pull/1800
|
13
|
+
* record_accessor helper: Expose internal instance `@keys` variable
|
14
|
+
https://github.com/fluent/fluentd/pull/1808
|
15
|
+
* log: Improve Log#on_xxx API performance
|
16
|
+
https://github.com/fluent/fluentd/pull/1809
|
17
|
+
* time: Improve time formatting performance
|
18
|
+
https://github.com/fluent/fluentd/pull/1796
|
19
|
+
* command: Port certificates generating command from secure-forward
|
20
|
+
https://github.com/fluent/fluentd/pull/1818
|
21
|
+
|
22
|
+
### Bug fixes
|
23
|
+
|
24
|
+
* server helper: Fix TCP + TLS degradation
|
25
|
+
https://github.com/fluent/fluentd/pull/1805
|
26
|
+
* time: Fix the method for TimeFormatter#call
|
27
|
+
https://github.com/fluent/fluentd/pull/1813
|
28
|
+
|
3
29
|
## Release v1.0.2 - 2017/12/17
|
4
30
|
|
5
31
|
### New features / Enhancements
|
data/fluentd.gemspec
CHANGED
@@ -27,7 +27,7 @@ Gem::Specification.new do |gem|
|
|
27
27
|
gem.add_runtime_dependency("sigdump", ["~> 0.2.2"])
|
28
28
|
gem.add_runtime_dependency("tzinfo", ["~> 1.0"])
|
29
29
|
gem.add_runtime_dependency("tzinfo-data", ["~> 1.0"])
|
30
|
-
gem.add_runtime_dependency("strptime", ["
|
30
|
+
gem.add_runtime_dependency("strptime", [">= 0.2.2", "< 1.0.0"])
|
31
31
|
gem.add_runtime_dependency("dig_rb", ["~> 1.0.0"])
|
32
32
|
|
33
33
|
# build gem for a certain platform. see also Rakefile
|
@@ -0,0 +1,179 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'optparse'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module Fluent
|
6
|
+
class CaGenerate
|
7
|
+
DEFAULT_OPTIONS = {
|
8
|
+
private_key_length: 2048,
|
9
|
+
cert_country: 'US',
|
10
|
+
cert_state: 'CA',
|
11
|
+
cert_locality: 'Mountain View',
|
12
|
+
cert_common_name: 'Fluentd Forward CA',
|
13
|
+
}
|
14
|
+
HELP_TEXT = <<HELP
|
15
|
+
Usage: fluent-ca-genrate DIR_PATH PRIVATE_KEY_PASSPHRASE [--country COUNTRY] [--state STATE] [--locality LOCALITY] [--common-name COMMON_NAME]
|
16
|
+
HELP
|
17
|
+
|
18
|
+
def initialize(argv = ARGV)
|
19
|
+
@argv = argv
|
20
|
+
@options = {}
|
21
|
+
@opt_parser = OptionParser.new
|
22
|
+
configure_option_parser
|
23
|
+
@options.merge!(DEFAULT_OPTIONS)
|
24
|
+
parse_options!
|
25
|
+
end
|
26
|
+
|
27
|
+
def usage(msg = nil)
|
28
|
+
puts HELP_TEXT
|
29
|
+
puts "Error: #{msg}" if msg
|
30
|
+
exit 1
|
31
|
+
end
|
32
|
+
|
33
|
+
def call
|
34
|
+
ca_dir, passphrase, = @argv[0..1]
|
35
|
+
|
36
|
+
unless ca_dir && passphrase
|
37
|
+
puts "#{HELP_TEXT}"
|
38
|
+
puts ''
|
39
|
+
exit 1
|
40
|
+
end
|
41
|
+
|
42
|
+
FileUtils.mkdir_p(ca_dir)
|
43
|
+
|
44
|
+
cert, key = Fluent::CaGenerate.generate_ca_pair(@options)
|
45
|
+
|
46
|
+
key_data = key.export(OpenSSL::Cipher.new('aes256'), passphrase)
|
47
|
+
File.open(File.join(ca_dir, 'ca_key.pem'), 'w') do |file|
|
48
|
+
file.write key_data
|
49
|
+
end
|
50
|
+
File.open(File.join(ca_dir, 'ca_cert.pem'), 'w') do |file|
|
51
|
+
file.write cert.to_pem
|
52
|
+
end
|
53
|
+
|
54
|
+
puts "successfully generated: ca_key.pem, ca_cert.pem"
|
55
|
+
puts "copy and use ca_cert.pem to client(out_forward)"
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.certificates_from_file(path)
|
59
|
+
data = File.read(path)
|
60
|
+
pattern = Regexp.compile('-+BEGIN CERTIFICATE-+\n(?:[^-]*\n)+-+END CERTIFICATE-+\n', Regexp::MULTILINE)
|
61
|
+
list = []
|
62
|
+
data.scan(pattern){|match| list << OpenSSL::X509::Certificate.new(match)}
|
63
|
+
list
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.generate_ca_pair(opts={})
|
67
|
+
key = OpenSSL::PKey::RSA.generate(opts[:private_key_length])
|
68
|
+
|
69
|
+
issuer = subject = OpenSSL::X509::Name.new
|
70
|
+
subject.add_entry('C', opts[:cert_country])
|
71
|
+
subject.add_entry('ST', opts[:cert_state])
|
72
|
+
subject.add_entry('L', opts[:cert_locality])
|
73
|
+
subject.add_entry('CN', opts[:cert_common_name])
|
74
|
+
|
75
|
+
digest = OpenSSL::Digest::SHA256.new
|
76
|
+
|
77
|
+
cert = OpenSSL::X509::Certificate.new
|
78
|
+
cert.not_before = Time.at(0)
|
79
|
+
cert.not_after = Time.now + 5 * 365 * 86400 # 5 years after
|
80
|
+
cert.public_key = key
|
81
|
+
cert.serial = 1
|
82
|
+
cert.issuer = issuer
|
83
|
+
cert.subject = subject
|
84
|
+
cert.add_extension OpenSSL::X509::Extension.new('basicConstraints', OpenSSL::ASN1.Sequence([OpenSSL::ASN1::Boolean(true)]))
|
85
|
+
cert.sign(key, digest)
|
86
|
+
|
87
|
+
return cert, key
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.generate_server_pair(opts={})
|
91
|
+
key = OpenSSL::PKey::RSA.generate(opts[:private_key_length])
|
92
|
+
|
93
|
+
ca_key = OpenSSL::PKey::RSA.new(File.read(opts[:ca_key_path]), opts[:ca_key_passphrase])
|
94
|
+
ca_cert = OpenSSL::X509::Certificate.new(File.read(opts[:ca_cert_path]))
|
95
|
+
issuer = ca_cert.issuer
|
96
|
+
|
97
|
+
subject = OpenSSL::X509::Name.new
|
98
|
+
subject.add_entry('C', opts[:country])
|
99
|
+
subject.add_entry('ST', opts[:state])
|
100
|
+
subject.add_entry('L', opts[:locality])
|
101
|
+
subject.add_entry('CN', opts[:common_name])
|
102
|
+
|
103
|
+
digest = OpenSSL::Digest::SHA256.new
|
104
|
+
|
105
|
+
cert = OpenSSL::X509::Certificate.new
|
106
|
+
cert.not_before = Time.at(0)
|
107
|
+
cert.not_after = Time.now + 5 * 365 * 86400 # 5 years after
|
108
|
+
cert.public_key = key
|
109
|
+
cert.serial = 2
|
110
|
+
cert.issuer = issuer
|
111
|
+
cert.subject = subject
|
112
|
+
|
113
|
+
cert.add_extension OpenSSL::X509::Extension.new('basicConstraints', OpenSSL::ASN1.Sequence([OpenSSL::ASN1::Boolean(false)]))
|
114
|
+
cert.add_extension OpenSSL::X509::Extension.new('nsCertType', 'server')
|
115
|
+
|
116
|
+
cert.sign ca_key, digest
|
117
|
+
|
118
|
+
return cert, key
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.generate_self_signed_server_pair(opts={})
|
122
|
+
key = OpenSSL::PKey::RSA.generate(opts[:private_key_length])
|
123
|
+
|
124
|
+
issuer = subject = OpenSSL::X509::Name.new
|
125
|
+
subject.add_entry('C', opts[:country])
|
126
|
+
subject.add_entry('ST', opts[:state])
|
127
|
+
subject.add_entry('L', opts[:locality])
|
128
|
+
subject.add_entry('CN', opts[:common_name])
|
129
|
+
|
130
|
+
digest = OpenSSL::Digest::SHA256.new
|
131
|
+
|
132
|
+
cert = OpenSSL::X509::Certificate.new
|
133
|
+
cert.not_before = Time.at(0)
|
134
|
+
cert.not_after = Time.now + 5 * 365 * 86400 # 5 years after
|
135
|
+
cert.public_key = key
|
136
|
+
cert.serial = 1
|
137
|
+
cert.issuer = issuer
|
138
|
+
cert.subject = subject
|
139
|
+
cert.sign(key, digest)
|
140
|
+
|
141
|
+
return cert, key
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def configure_option_parser
|
147
|
+
@opt_parser.banner = HELP_TEXT
|
148
|
+
|
149
|
+
@opt_parser.on('--key-length [KEY_LENGTH]',
|
150
|
+
"configure key length. (default: #{DEFAULT_OPTIONS[:private_key_length]})") do |v|
|
151
|
+
@options[:private_key_length] = v.to_i
|
152
|
+
end
|
153
|
+
|
154
|
+
@opt_parser.on('--country [COUNTRY]',
|
155
|
+
"configure country. (default: #{DEFAULT_OPTIONS[:cert_country]})") do |v|
|
156
|
+
@options[:cert_country] = v.upcase
|
157
|
+
end
|
158
|
+
|
159
|
+
@opt_parser.on('--state [STATE]',
|
160
|
+
"configure state. (default: #{DEFAULT_OPTIONS[:cert_state]})") do |v|
|
161
|
+
@options[:cert_state] = v
|
162
|
+
end
|
163
|
+
|
164
|
+
@opt_parser.on('--locality [LOCALITY]',
|
165
|
+
"configure locality. (default: #{DEFAULT_OPTIONS[:cert_locality]})") do |v|
|
166
|
+
@options[:cert_locality] = v
|
167
|
+
end
|
168
|
+
|
169
|
+
@opt_parser.on('--common-name [COMMON_NAME]',
|
170
|
+
"configure common name (default: #{DEFAULT_OPTIONS[:cert_common_name]})") do |v|
|
171
|
+
@options[:cert_common_name] = v
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def parse_options!
|
176
|
+
@opt_parser.parse!(@argv)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
@@ -18,6 +18,7 @@ require 'stringio'
|
|
18
18
|
|
19
19
|
require 'json'
|
20
20
|
require 'yajl'
|
21
|
+
require 'socket'
|
21
22
|
require 'irb/ruby-lex' # RubyLex
|
22
23
|
|
23
24
|
require 'fluent/config/basic_parser'
|
@@ -162,6 +163,11 @@ module Fluent
|
|
162
163
|
if @eval_context.nil?
|
163
164
|
parse_error! "embedded code is not allowed in this file"
|
164
165
|
end
|
166
|
+
# Add hostname and worker_id to code for preventing unused warnings
|
167
|
+
code = <<EOM + code
|
168
|
+
hostname = Socket.gethostname
|
169
|
+
worker_id = ENV['SERVERENGINE_WORKER_ID'] || ''
|
170
|
+
EOM
|
165
171
|
@eval_context.instance_eval(code)
|
166
172
|
end
|
167
173
|
|
data/lib/fluent/log.rb
CHANGED
@@ -163,10 +163,12 @@ module Fluent
|
|
163
163
|
def format=(fmt)
|
164
164
|
return if @format == fmt
|
165
165
|
|
166
|
+
@time_format = '%Y-%m-%d %H:%M:%S %z'
|
167
|
+
@time_formatter = Strftime.new(@time_format) rescue nil
|
168
|
+
|
166
169
|
case fmt
|
167
170
|
when :text
|
168
171
|
@format = :text
|
169
|
-
@time_format = '%Y-%m-%d %H:%M:%S %z'
|
170
172
|
@formatter = Proc.new { |type, time, level, msg|
|
171
173
|
r = caller_line(type, time, @depth_offset, level)
|
172
174
|
r << msg
|
@@ -174,10 +176,9 @@ module Fluent
|
|
174
176
|
}
|
175
177
|
when :json
|
176
178
|
@format = :json
|
177
|
-
@time_format = '%Y-%m-%d %H:%M:%S %z'
|
178
179
|
@formatter = Proc.new { |type, time, level, msg|
|
179
180
|
r = {
|
180
|
-
'time' => time
|
181
|
+
'time' => format_time(time),
|
181
182
|
'level' => LEVEL_TEXT[level],
|
182
183
|
'message' => msg
|
183
184
|
}
|
@@ -191,6 +192,11 @@ module Fluent
|
|
191
192
|
nil
|
192
193
|
end
|
193
194
|
|
195
|
+
def time_format=(time_fmt)
|
196
|
+
@time_format = time_fmt
|
197
|
+
@time_formatter = Strftime.new(@time_format) rescue nil
|
198
|
+
end
|
199
|
+
|
194
200
|
def reopen!
|
195
201
|
# do nothing in @logger.reopen! because it's already reopened in Supervisor.load_config
|
196
202
|
@logger.reopen! if @logger
|
@@ -261,9 +267,9 @@ module Fluent
|
|
261
267
|
end
|
262
268
|
end
|
263
269
|
|
264
|
-
def on_trace
|
270
|
+
def on_trace
|
265
271
|
return if @level > LEVEL_TRACE
|
266
|
-
|
272
|
+
yield
|
267
273
|
end
|
268
274
|
|
269
275
|
def trace(*args, &block)
|
@@ -282,9 +288,9 @@ module Fluent
|
|
282
288
|
dump_stacktrace(type, backtrace, LEVEL_TRACE)
|
283
289
|
end
|
284
290
|
|
285
|
-
def on_debug
|
291
|
+
def on_debug
|
286
292
|
return if @level > LEVEL_DEBUG
|
287
|
-
|
293
|
+
yield
|
288
294
|
end
|
289
295
|
|
290
296
|
def debug(*args, &block)
|
@@ -302,9 +308,9 @@ module Fluent
|
|
302
308
|
dump_stacktrace(type, backtrace, LEVEL_DEBUG)
|
303
309
|
end
|
304
310
|
|
305
|
-
def on_info
|
311
|
+
def on_info
|
306
312
|
return if @level > LEVEL_INFO
|
307
|
-
|
313
|
+
yield
|
308
314
|
end
|
309
315
|
|
310
316
|
def info(*args, &block)
|
@@ -322,9 +328,9 @@ module Fluent
|
|
322
328
|
dump_stacktrace(type, backtrace, LEVEL_INFO)
|
323
329
|
end
|
324
330
|
|
325
|
-
def on_warn
|
331
|
+
def on_warn
|
326
332
|
return if @level > LEVEL_WARN
|
327
|
-
|
333
|
+
yield
|
328
334
|
end
|
329
335
|
|
330
336
|
def warn(*args, &block)
|
@@ -342,9 +348,9 @@ module Fluent
|
|
342
348
|
dump_stacktrace(type, backtrace, LEVEL_WARN)
|
343
349
|
end
|
344
350
|
|
345
|
-
def on_error
|
351
|
+
def on_error
|
346
352
|
return if @level > LEVEL_ERROR
|
347
|
-
|
353
|
+
yield
|
348
354
|
end
|
349
355
|
|
350
356
|
def error(*args, &block)
|
@@ -362,9 +368,9 @@ module Fluent
|
|
362
368
|
dump_stacktrace(type, backtrace, LEVEL_ERROR)
|
363
369
|
end
|
364
370
|
|
365
|
-
def on_fatal
|
371
|
+
def on_fatal
|
366
372
|
return if @level > LEVEL_FATAL
|
367
|
-
|
373
|
+
yield
|
368
374
|
end
|
369
375
|
|
370
376
|
def fatal(*args, &block)
|
@@ -423,7 +429,7 @@ module Fluent
|
|
423
429
|
end
|
424
430
|
else
|
425
431
|
r = {
|
426
|
-
'time' => time
|
432
|
+
'time' => format_time(time),
|
427
433
|
'level' => LEVEL_TEXT[level],
|
428
434
|
}
|
429
435
|
if wid = get_worker_id(type)
|
@@ -491,7 +497,7 @@ module Fluent
|
|
491
497
|
else
|
492
498
|
"".freeze
|
493
499
|
end
|
494
|
-
log_msg = "#{time
|
500
|
+
log_msg = "#{format_time(time)} [#{LEVEL_TEXT[level]}]: #{worker_id_part}"
|
495
501
|
if @debug_mode
|
496
502
|
line = caller(depth+1)[0]
|
497
503
|
if match = /^(.+?):(\d+)(?::in `(.*)')?/.match(line)
|
@@ -503,6 +509,10 @@ module Fluent
|
|
503
509
|
end
|
504
510
|
return log_msg
|
505
511
|
end
|
512
|
+
|
513
|
+
def format_time(time)
|
514
|
+
@time_formatter ? @time_formatter.exec(time) : time.strftime(@time_format)
|
515
|
+
end
|
506
516
|
end
|
507
517
|
|
508
518
|
|
@@ -545,8 +555,8 @@ module Fluent
|
|
545
555
|
extend Forwardable
|
546
556
|
def_delegators '@logger', :get_worker_id, :enable_color?, :enable_debug, :enable_event,
|
547
557
|
:disable_events, :log_event_enabled, :log_event_enamed=, :time_format, :time_format=,
|
548
|
-
:event, :caller_line, :puts, :write, :<<, :flush,
|
549
|
-
:optional_header, :optional_header=, :optional_attrs, :optional_attrs=
|
558
|
+
:time_formatter, :time_formatter=, :event, :caller_line, :puts, :write, :<<, :flush,
|
559
|
+
:reset, :out, :out=, :optional_header, :optional_header=, :optional_attrs, :optional_attrs=
|
550
560
|
end
|
551
561
|
|
552
562
|
|
data/lib/fluent/plugin/buffer.rb
CHANGED
@@ -240,7 +240,8 @@ module Fluent
|
|
240
240
|
end
|
241
241
|
|
242
242
|
def add_metadata(metadata)
|
243
|
-
log.trace "adding metadata", instance: self.object_id, metadata: metadata
|
243
|
+
log.on_trace { log.trace "adding metadata", instance: self.object_id, metadata: metadata }
|
244
|
+
|
244
245
|
synchronize do
|
245
246
|
if i = @metadata_list.index(metadata)
|
246
247
|
@metadata_list[i]
|
@@ -263,7 +264,7 @@ module Fluent
|
|
263
264
|
return if metadata_and_data.size < 1
|
264
265
|
raise BufferOverflowError, "buffer space has too many data" unless storable?
|
265
266
|
|
266
|
-
log.trace "writing events into buffer", instance: self.object_id, metadata_size: metadata_and_data.size
|
267
|
+
log.on_trace { log.trace "writing events into buffer", instance: self.object_id, metadata_size: metadata_and_data.size }
|
267
268
|
|
268
269
|
staged_bytesize = 0
|
269
270
|
operated_chunks = []
|
@@ -382,7 +383,8 @@ module Fluent
|
|
382
383
|
end
|
383
384
|
|
384
385
|
def enqueue_chunk(metadata)
|
385
|
-
log.trace "enqueueing chunk", instance: self.object_id, metadata: metadata
|
386
|
+
log.on_trace { log.trace "enqueueing chunk", instance: self.object_id, metadata: metadata }
|
387
|
+
|
386
388
|
chunk = synchronize do
|
387
389
|
@stage.delete(metadata)
|
388
390
|
end
|
@@ -406,7 +408,8 @@ module Fluent
|
|
406
408
|
end
|
407
409
|
|
408
410
|
def enqueue_unstaged_chunk(chunk)
|
409
|
-
log.trace "enqueueing unstaged chunk", instance: self.object_id, metadata: chunk.metadata
|
411
|
+
log.on_trace { log.trace "enqueueing unstaged chunk", instance: self.object_id, metadata: chunk.metadata }
|
412
|
+
|
410
413
|
synchronize do
|
411
414
|
chunk.synchronize do
|
412
415
|
metadata = chunk.metadata
|
@@ -419,7 +422,8 @@ module Fluent
|
|
419
422
|
end
|
420
423
|
|
421
424
|
def enqueue_all
|
422
|
-
log.trace "enqueueing all chunks in buffer", instance: self.object_id
|
425
|
+
log.on_trace { log.trace "enqueueing all chunks in buffer", instance: self.object_id }
|
426
|
+
|
423
427
|
if block_given?
|
424
428
|
synchronize{ @stage.keys }.each do |metadata|
|
425
429
|
# NOTE: The following line might cause data race depending on Ruby implementations except CRuby
|
@@ -438,7 +442,8 @@ module Fluent
|
|
438
442
|
|
439
443
|
def dequeue_chunk
|
440
444
|
return nil if @queue.empty?
|
441
|
-
log.trace "dequeueing a chunk", instance: self.object_id
|
445
|
+
log.on_trace { log.trace "dequeueing a chunk", instance: self.object_id }
|
446
|
+
|
442
447
|
synchronize do
|
443
448
|
chunk = @queue.shift
|
444
449
|
|
@@ -453,7 +458,8 @@ module Fluent
|
|
453
458
|
end
|
454
459
|
|
455
460
|
def takeback_chunk(chunk_id)
|
456
|
-
log.trace "taking back a chunk", instance: self.object_id, chunk_id: dump_unique_id_hex(chunk_id)
|
461
|
+
log.on_trace { log.trace "taking back a chunk", instance: self.object_id, chunk_id: dump_unique_id_hex(chunk_id) }
|
462
|
+
|
457
463
|
synchronize do
|
458
464
|
chunk = @dequeued.delete(chunk_id)
|
459
465
|
return false unless chunk # already purged by other thread
|
@@ -470,7 +476,8 @@ module Fluent
|
|
470
476
|
return nil unless chunk # purged by other threads
|
471
477
|
|
472
478
|
metadata = chunk.metadata
|
473
|
-
log.trace "purging a chunk", instance: self.object_id, chunk_id: dump_unique_id_hex(chunk_id), metadata: metadata
|
479
|
+
log.on_trace { log.trace "purging a chunk", instance: self.object_id, chunk_id: dump_unique_id_hex(chunk_id), metadata: metadata }
|
480
|
+
|
474
481
|
begin
|
475
482
|
bytesize = chunk.bytesize
|
476
483
|
chunk.purge
|
@@ -489,7 +496,8 @@ module Fluent
|
|
489
496
|
end
|
490
497
|
|
491
498
|
def clear_queue!
|
492
|
-
log.trace "clearing queue", instance: self.object_id
|
499
|
+
log.on_trace { log.trace "clearing queue", instance: self.object_id }
|
500
|
+
|
493
501
|
synchronize do
|
494
502
|
until @queue.empty?
|
495
503
|
begin
|
@@ -27,6 +27,8 @@ module Fluent::Plugin
|
|
27
27
|
class RecordTransformerFilter < Fluent::Plugin::Filter
|
28
28
|
Fluent::Plugin.register_filter('record_transformer', self)
|
29
29
|
|
30
|
+
helpers :record_accessor
|
31
|
+
|
30
32
|
desc 'A comma-delimited list of keys to delete.'
|
31
33
|
config_param :remove_keys, :array, default: nil
|
32
34
|
desc 'A comma-delimited list of keys to keep.'
|
@@ -56,6 +58,10 @@ module Fluent::Plugin
|
|
56
58
|
raise Fluent::ConfigError, "`renew_record` must be true to use `keep_keys`" unless @renew_record
|
57
59
|
end
|
58
60
|
|
61
|
+
@key_deleters = if @remove_keys
|
62
|
+
@remove_keys.map { |k| record_accessor_create(k) }
|
63
|
+
end
|
64
|
+
|
59
65
|
placeholder_expander_params = {
|
60
66
|
log: log,
|
61
67
|
auto_typecast: @auto_typecast,
|
@@ -96,8 +102,7 @@ module Fluent::Plugin
|
|
96
102
|
if @renew_time_key && new_record.has_key?(@renew_time_key)
|
97
103
|
time = Fluent::EventTime.from_time(Time.at(new_record[@renew_time_key].to_f))
|
98
104
|
end
|
99
|
-
@
|
100
|
-
|
105
|
+
@key_deleters.each { |deleter| deleter.delete(new_record) } if @key_deleters
|
101
106
|
new_es.add(time, new_record)
|
102
107
|
rescue => e
|
103
108
|
router.emit_error_event(tag, time, record, e)
|
@@ -21,13 +21,14 @@ module Fluent
|
|
21
21
|
class StdoutFormatter < Formatter
|
22
22
|
Plugin.register_formatter('stdout', self)
|
23
23
|
|
24
|
-
TIME_FORMAT = '%Y-%m-%d %H:%M:%S.%
|
24
|
+
TIME_FORMAT = '%Y-%m-%d %H:%M:%S.%N %z'
|
25
25
|
|
26
26
|
config_param :output_type, :string, default: 'json'
|
27
27
|
|
28
28
|
def configure(conf)
|
29
29
|
super
|
30
30
|
|
31
|
+
@time_formatter = Strftime.new(TIME_FORMAT)
|
31
32
|
@sub_formatter = Plugin.new_formatter(@output_type, parent: self.owner)
|
32
33
|
@sub_formatter.configure(conf)
|
33
34
|
end
|
@@ -38,7 +39,7 @@ module Fluent
|
|
38
39
|
end
|
39
40
|
|
40
41
|
def format(tag, time, record)
|
41
|
-
"#{Time.at(time).localtime
|
42
|
+
"#{@time_formatter.exec(Time.at(time).localtime)} #{tag}: #{@sub_formatter.format(tag, time, record).chomp}\n"
|
42
43
|
end
|
43
44
|
|
44
45
|
def stop
|
data/lib/fluent/plugin/output.rb
CHANGED
@@ -971,7 +971,8 @@ module Fluent
|
|
971
971
|
end
|
972
972
|
|
973
973
|
def commit_write(chunk_id, delayed: @delayed_commit, secondary: false)
|
974
|
-
log.trace "committing write operation to a chunk", chunk: dump_unique_id_hex(chunk_id), delayed: delayed
|
974
|
+
log.on_trace { log.trace "committing write operation to a chunk", chunk: dump_unique_id_hex(chunk_id), delayed: delayed }
|
975
|
+
|
975
976
|
if delayed
|
976
977
|
@dequeued_chunks_mutex.synchronize do
|
977
978
|
@dequeued_chunks.delete_if{ |info| info.chunk_id == chunk_id }
|
@@ -1057,7 +1058,7 @@ module Fluent
|
|
1057
1058
|
chunk = @buffer.dequeue_chunk
|
1058
1059
|
return unless chunk
|
1059
1060
|
|
1060
|
-
log.trace "trying flush for a chunk", chunk: dump_unique_id_hex(chunk.unique_id)
|
1061
|
+
log.on_trace { log.trace "trying flush for a chunk", chunk: dump_unique_id_hex(chunk.unique_id) }
|
1061
1062
|
|
1062
1063
|
output = self
|
1063
1064
|
using_secondary = false
|
@@ -23,11 +23,20 @@ module Fluent
|
|
23
23
|
|
24
24
|
desc 'The delimiter character (or string) of TSV values'
|
25
25
|
config_param :delimiter, :string, default: "\t"
|
26
|
+
desc 'The delimiter pattern of TSV values'
|
27
|
+
config_param :delimiter_pattern, default: nil do |value|
|
28
|
+
Regexp.compile(value[1..-2]) if value
|
29
|
+
end
|
26
30
|
desc 'The delimiter character between field name and value'
|
27
31
|
config_param :label_delimiter, :string, default: ":"
|
28
32
|
|
29
33
|
config_set_default :time_key, 'time'
|
30
34
|
|
35
|
+
def configure(conf)
|
36
|
+
super
|
37
|
+
@delimiter = @delimiter_pattern || @delimiter
|
38
|
+
end
|
39
|
+
|
31
40
|
def parse(text)
|
32
41
|
r = {}
|
33
42
|
text.split(@delimiter).each do |pair|
|
@@ -32,13 +32,25 @@ module Fluent
|
|
32
32
|
end
|
33
33
|
|
34
34
|
class Accessor
|
35
|
+
attr_reader :keys
|
36
|
+
|
35
37
|
def initialize(param)
|
36
38
|
@keys = Accessor.parse_parameter(param)
|
37
39
|
|
38
|
-
|
39
|
-
|
40
|
+
if @keys.is_a?(Array)
|
41
|
+
@last_key = @keys.last
|
42
|
+
@dig_keys = @keys[0..-2]
|
43
|
+
mcall = method(:call_dig)
|
44
|
+
mdelete = method(:delete_nest)
|
45
|
+
else
|
46
|
+
# Call [] for single key to reduce dig overhead
|
47
|
+
mcall = method(:call_index)
|
48
|
+
mdelete = method(:delete_top)
|
49
|
+
end
|
50
|
+
|
40
51
|
singleton_class.module_eval do
|
41
|
-
define_method(:call,
|
52
|
+
define_method(:call, mcall)
|
53
|
+
define_method(:delete, mdelete)
|
42
54
|
end
|
43
55
|
end
|
44
56
|
|
@@ -55,6 +67,25 @@ module Fluent
|
|
55
67
|
r[@keys]
|
56
68
|
end
|
57
69
|
|
70
|
+
def delete(r)
|
71
|
+
end
|
72
|
+
|
73
|
+
def delete_nest(r)
|
74
|
+
if target = r.dig(*@dig_keys)
|
75
|
+
if target.is_a?(Array)
|
76
|
+
target.delete_at(@last_key)
|
77
|
+
else
|
78
|
+
target.delete(@last_key)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
rescue
|
82
|
+
nil
|
83
|
+
end
|
84
|
+
|
85
|
+
def delete_top(r)
|
86
|
+
r.delete(@keys)
|
87
|
+
end
|
88
|
+
|
58
89
|
def self.parse_parameter(param)
|
59
90
|
if param.start_with?('$.')
|
60
91
|
parse_dot_notation(param)
|
@@ -446,9 +446,12 @@ module Fluent
|
|
446
446
|
class TLSCallbackSocket < CallbackSocket
|
447
447
|
ENABLED_EVENTS = [:data, :write_complete, :close]
|
448
448
|
|
449
|
+
attr_accessor :buffer
|
450
|
+
|
449
451
|
def initialize(sock)
|
450
452
|
super("tls", sock, ENABLED_EVENTS)
|
451
453
|
@peeraddr = (@sock.to_io.peeraddr rescue PEERADDR_FAILED)
|
454
|
+
@buffer = ''
|
452
455
|
end
|
453
456
|
|
454
457
|
def write(data)
|
data/lib/fluent/time.rb
CHANGED
@@ -319,21 +319,24 @@ module Fluent
|
|
319
319
|
@tc2 = 0
|
320
320
|
@tc2_str = nil
|
321
321
|
|
322
|
+
strftime = format && (Strftime.new(format) rescue nil)
|
322
323
|
if format && format =~ /(^|[^%])(%%)*%L|(^|[^%])(%%)*%\d*N/
|
323
324
|
define_singleton_method(:format, method(:format_with_subsec))
|
324
325
|
define_singleton_method(:call, method(:format_with_subsec))
|
325
326
|
else
|
326
327
|
define_singleton_method(:format, method(:format_without_subsec))
|
327
|
-
define_singleton_method(:call, method(:
|
328
|
+
define_singleton_method(:call, method(:format_without_subsec))
|
328
329
|
end
|
329
330
|
|
330
|
-
formatter = Fluent::Timezone.formatter(timezone, format)
|
331
|
+
formatter = Fluent::Timezone.formatter(timezone, strftime ? strftime : format)
|
331
332
|
@format_nocache = case
|
332
|
-
when formatter
|
333
|
-
when
|
334
|
-
when format
|
335
|
-
when
|
336
|
-
|
333
|
+
when formatter then formatter
|
334
|
+
when strftime && localtime then ->(time){ strftime.exec(Time.at(time)) }
|
335
|
+
when format && localtime then ->(time){ Time.at(time).strftime(format) }
|
336
|
+
when strftime then ->(time){ strftime.exec(Time.at(time).utc) }
|
337
|
+
when format then ->(time){ Time.at(time).utc.strftime(format) }
|
338
|
+
when localtime then ->(time){ Time.at(time).iso8601 }
|
339
|
+
else ->(time){ Time.at(time).utc.iso8601 }
|
337
340
|
end
|
338
341
|
end
|
339
342
|
|
data/lib/fluent/timezone.rb
CHANGED
@@ -97,10 +97,15 @@ module Fluent
|
|
97
97
|
if NUMERIC_PATTERN === timezone
|
98
98
|
offset = Time.zone_offset(timezone)
|
99
99
|
|
100
|
-
|
100
|
+
case
|
101
|
+
when format.is_a?(String)
|
101
102
|
return Proc.new {|time|
|
102
103
|
Time.at(time).localtime(offset).strftime(format)
|
103
104
|
}
|
105
|
+
when format.is_a?(Strftime)
|
106
|
+
return Proc.new {|time|
|
107
|
+
format.exec(Time.at(time).localtime(offset))
|
108
|
+
}
|
104
109
|
else
|
105
110
|
return Proc.new {|time|
|
106
111
|
Time.at(time).localtime(offset).iso8601
|
@@ -116,10 +121,15 @@ module Fluent
|
|
116
121
|
return nil
|
117
122
|
end
|
118
123
|
|
119
|
-
|
124
|
+
case
|
125
|
+
when format.is_a?(String)
|
120
126
|
return Proc.new {|time|
|
121
127
|
Time.at(time).localtime(tz.period_for_utc(time).utc_total_offset).strftime(format)
|
122
128
|
}
|
129
|
+
when format.is_a?(Strftime)
|
130
|
+
return Proc.new {|time|
|
131
|
+
format.exec(Time.at(time).localtime(tz.period_for_utc(time).utc_total_offset))
|
132
|
+
}
|
123
133
|
else
|
124
134
|
return Proc.new {|time|
|
125
135
|
Time.at(time).localtime(tz.period_for_utc(time).utc_total_offset).iso8601
|
data/lib/fluent/version.rb
CHANGED
@@ -0,0 +1,70 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
|
3
|
+
require 'yajl'
|
4
|
+
require 'flexmock/test_unit'
|
5
|
+
require 'tmpdir'
|
6
|
+
|
7
|
+
require 'fluent/command/ca_generate'
|
8
|
+
require 'fluent/event'
|
9
|
+
|
10
|
+
class TestFluentCaGenerate < ::Test::Unit::TestCase
|
11
|
+
def test_generate_ca_pair
|
12
|
+
cert, key = Fluent::CaGenerate.generate_ca_pair(Fluent::CaGenerate::DEFAULT_OPTIONS)
|
13
|
+
assert_equal(OpenSSL::X509::Certificate, cert.class)
|
14
|
+
assert_true(key.private?)
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_ca_generate
|
18
|
+
dumped_output = capture_stdout do
|
19
|
+
Dir.mktmpdir do |dir|
|
20
|
+
Fluent::CaGenerate.new([dir, "fluentd"]).call
|
21
|
+
assert_true(File.exist?(File.join(dir, "ca_key.pem")))
|
22
|
+
assert_true(File.exist?(File.join(dir, "ca_cert.pem")))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
expected = <<TEXT
|
26
|
+
successfully generated: ca_key.pem, ca_cert.pem
|
27
|
+
copy and use ca_cert.pem to client(out_forward)
|
28
|
+
TEXT
|
29
|
+
assert_equal(expected, dumped_output)
|
30
|
+
end
|
31
|
+
|
32
|
+
sub_test_case "configure options" do
|
33
|
+
test "should respond multiple options" do
|
34
|
+
dumped_output = capture_stdout do
|
35
|
+
Dir.mktmpdir do |dir|
|
36
|
+
Fluent::CaGenerate.new([dir, "fluentd",
|
37
|
+
"--country", "JP", "--key-length", "4096",
|
38
|
+
"--state", "Tokyo", "--locality", "Chiyoda-ku",
|
39
|
+
"--common-name", "Forward CA"]).call
|
40
|
+
assert_true(File.exist?(File.join(dir, "ca_key.pem")))
|
41
|
+
assert_true(File.exist?(File.join(dir, "ca_cert.pem")))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
expected = <<TEXT
|
45
|
+
successfully generated: ca_key.pem, ca_cert.pem
|
46
|
+
copy and use ca_cert.pem to client(out_forward)
|
47
|
+
TEXT
|
48
|
+
assert_equal(expected, dumped_output)
|
49
|
+
end
|
50
|
+
|
51
|
+
test "invalid options" do
|
52
|
+
Dir.mktmpdir do |dir|
|
53
|
+
assert_raise(OptionParser::InvalidOption) do
|
54
|
+
Fluent::CaGenerate.new([dir, "fluentd",
|
55
|
+
"--invalid"]).call
|
56
|
+
end
|
57
|
+
assert_false(File.exist?(File.join(dir, "ca_key.pem")))
|
58
|
+
assert_false(File.exist?(File.join(dir, "ca_cert.pem")))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
test "empty options" do
|
63
|
+
assert_raise(SystemExit) do
|
64
|
+
capture_stdout do
|
65
|
+
Fluent::CaGenerate.new([]).call
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -494,14 +494,14 @@ CONF
|
|
494
494
|
end
|
495
495
|
|
496
496
|
test 'success to start the number of workers specified in configuration' do
|
497
|
-
conf = <<CONF
|
497
|
+
conf = <<'CONF'
|
498
498
|
<system>
|
499
499
|
workers 2
|
500
500
|
root_dir #{@root_path}
|
501
501
|
</system>
|
502
502
|
<source>
|
503
503
|
@type dummy
|
504
|
-
@id dummy
|
504
|
+
@id "dummy#{worker_id}" # check worker_id works or not with actual command
|
505
505
|
@label @dummydata
|
506
506
|
tag dummy
|
507
507
|
dummy {"message": "yay!"}
|
@@ -232,6 +232,14 @@ module Fluent::Config
|
|
232
232
|
test("\"\#{\n=begin\n}\"") { assert_parse_error("\"\#{\n=begin\n}\"") } # error in embedded ruby code
|
233
233
|
test('"#{v1}foo#{v2}"') { assert_text_parsed_as("#{v1}foo#{v2}", '"#{v1}foo#{v2}"') }
|
234
234
|
test('"#{1+1}foo#{2+2}bar"') { assert_text_parsed_as("#{1+1}foo#{2+2}bar", '"#{1+1}foo#{2+2}bar"') }
|
235
|
+
test('"foo#{hostname}"') { assert_text_parsed_as("foo#{Socket.gethostname}", '"foo#{hostname}"') }
|
236
|
+
test('"foo#{worker_id}"') {
|
237
|
+
ENV.delete('SERVERENGINE_WORKER_ID')
|
238
|
+
assert_text_parsed_as("foo", '"foo#{worker_id}"')
|
239
|
+
ENV['SERVERENGINE_WORKER_ID'] = '1'
|
240
|
+
assert_text_parsed_as("foo1", '"foo#{worker_id}"')
|
241
|
+
ENV.delete('SERVERENGINE_WORKER_ID')
|
242
|
+
}
|
235
243
|
end
|
236
244
|
|
237
245
|
sub_test_case 'array parsing' do
|
@@ -44,7 +44,7 @@ class RecordTransformerFilterTest < Test::Unit::TestCase
|
|
44
44
|
d = create_driver(config)
|
45
45
|
d.run {
|
46
46
|
msgs.each { |msg|
|
47
|
-
d.feed(@tag, @time, {'foo' => 'bar', 'message' => msg})
|
47
|
+
d.feed(@tag, @time, {'foo' => 'bar', 'message' => msg, 'nest' => {'k1' => 'v1', 'k2' => 'v2'}})
|
48
48
|
}
|
49
49
|
}
|
50
50
|
d.filtered
|
@@ -68,6 +68,7 @@ class RecordTransformerFilterTest < Test::Unit::TestCase
|
|
68
68
|
assert_equal(@tag, r['tag'])
|
69
69
|
assert_equal(Time.at(@time).localtime.to_s, r['time'])
|
70
70
|
assert_equal("#{@hostname} #{@tag_parts[-1]} #{msgs[i]}", r['message'])
|
71
|
+
assert_equal({'k1' => 'v1', 'k2' => 'v2'}, r['nest'])
|
71
72
|
end
|
72
73
|
end
|
73
74
|
|
@@ -83,6 +84,14 @@ class RecordTransformerFilterTest < Test::Unit::TestCase
|
|
83
84
|
end
|
84
85
|
end
|
85
86
|
|
87
|
+
test 'remove_keys with nested key' do
|
88
|
+
config = CONFIG + %[remove_keys $.nest.k1]
|
89
|
+
filtered = filter(config)
|
90
|
+
filtered.each_with_index do |(_t, r), i|
|
91
|
+
assert_not_include(r['nest'], 'k1')
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
86
95
|
test 'renew_record' do
|
87
96
|
config = CONFIG + %[renew_record true]
|
88
97
|
msgs = ['1', '2']
|
@@ -125,4 +125,21 @@ class LabeledTSVParserTest < ::Test::Unit::TestCase
|
|
125
125
|
assert_equal record['b'], ' '
|
126
126
|
end
|
127
127
|
end
|
128
|
+
|
129
|
+
data("single space" => ["k1=v1 k2=v2", { "k1" => "v1", "k2" => "v2" }],
|
130
|
+
"multiple space" => ["k1=v1 k2=v2", { "k1" => "v1", "k2" => "v2" }],
|
131
|
+
"reverse" => ["k2=v2 k1=v1", { "k1" => "v1", "k2" => "v2" }],
|
132
|
+
"tab" => ["k2=v2\tk1=v1", { "k1" => "v1", "k2" => "v2" }],
|
133
|
+
"tab and space" => ["k2=v2\t k1=v1", { "k1" => "v1", "k2" => "v2" }])
|
134
|
+
def test_parse_with_delimiter_pattern(data)
|
135
|
+
text, expected = data
|
136
|
+
parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin::LabeledTSVParser)
|
137
|
+
parser.configure(
|
138
|
+
'delimiter_pattern' => '/\s+/',
|
139
|
+
'label_delimiter' => '='
|
140
|
+
)
|
141
|
+
parser.instance.parse(text) do |_time, record|
|
142
|
+
assert_equal(expected, record)
|
143
|
+
end
|
144
|
+
end
|
128
145
|
end
|
@@ -62,6 +62,40 @@ class RecordAccessorHelperTest < Test::Unit::TestCase
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
+
sub_test_case 'attr_reader :keys' do
|
66
|
+
setup do
|
67
|
+
@d = Dummy.new
|
68
|
+
end
|
69
|
+
|
70
|
+
data('normal' => 'key1',
|
71
|
+
'space' => 'ke y2',
|
72
|
+
'dot key' => 'this.is.key3')
|
73
|
+
test 'access single key' do |param|
|
74
|
+
accessor = @d.record_accessor_create(param)
|
75
|
+
assert_equal param, accessor.keys
|
76
|
+
end
|
77
|
+
|
78
|
+
test "nested bracket keys with dot" do
|
79
|
+
accessor = @d.record_accessor_create("$['key1']['this.is.key3']")
|
80
|
+
assert_equal ['key1','this.is.key3'], accessor.keys
|
81
|
+
end
|
82
|
+
|
83
|
+
data('dot' => '$.key1.key2[0]',
|
84
|
+
'bracket' => "$['key1']['key2'][0]",
|
85
|
+
'bracket w/ double quotes' => '$["key1"]["key2"][0]')
|
86
|
+
test "nested keys ['key1', 'key2', 0]" do |param|
|
87
|
+
accessor = @d.record_accessor_create(param)
|
88
|
+
assert_equal ['key1', 'key2', 0], accessor.keys
|
89
|
+
end
|
90
|
+
|
91
|
+
data('bracket' => "$['key1'][0]['ke y2']",
|
92
|
+
'bracket w/ double quotes' => '$["key1"][0]["ke y2"]')
|
93
|
+
test "nested keys ['key1', 0, 'ke y2']" do |param|
|
94
|
+
accessor = @d.record_accessor_create(param)
|
95
|
+
assert_equal ['key1', 0, 'ke y2'], accessor.keys
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
65
99
|
sub_test_case Fluent::PluginHelper::RecordAccessor::Accessor do
|
66
100
|
setup do
|
67
101
|
@d = Dummy.new
|
@@ -114,4 +148,37 @@ class RecordAccessorHelperTest < Test::Unit::TestCase
|
|
114
148
|
end
|
115
149
|
end
|
116
150
|
end
|
151
|
+
|
152
|
+
sub_test_case 'Fluent::PluginHelper::RecordAccessor::Accessor#delete' do
|
153
|
+
setup do
|
154
|
+
@d = Dummy.new
|
155
|
+
end
|
156
|
+
|
157
|
+
data('normal' => 'key1',
|
158
|
+
'space' => 'ke y2',
|
159
|
+
'dot key' => 'this.is.key3')
|
160
|
+
test 'delete top key' do |param|
|
161
|
+
r = {'key1' => 'v1', 'ke y2' => 'v2', 'this.is.key3' => 'v3'}
|
162
|
+
accessor = @d.record_accessor_create(param)
|
163
|
+
accessor.delete(r)
|
164
|
+
assert_not_include(r, param)
|
165
|
+
end
|
166
|
+
|
167
|
+
data('bracket' => "$['key1'][0]['ke y2']",
|
168
|
+
'bracket w/ double quotes' => '$["key1"][0]["ke y2"]')
|
169
|
+
test "delete nested keys ['key1', 0, 'ke y2']" do |param|
|
170
|
+
r = {'key1' => [{'ke y2' => "value"}]}
|
171
|
+
accessor = @d.record_accessor_create(param)
|
172
|
+
accessor.delete(r)
|
173
|
+
assert_not_include(r['key1'][0], 'ke y2')
|
174
|
+
end
|
175
|
+
|
176
|
+
test "don't raise an error when unexpected record is coming" do
|
177
|
+
r = {'key1' => [{'key3' => "value"}]}
|
178
|
+
accessor = @d.record_accessor_create("$['key1']['key2']['key3']")
|
179
|
+
assert_nothing_raised do
|
180
|
+
assert_nil accessor.delete(r)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
117
184
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluentd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sadayuki Furuhashi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-01-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: msgpack
|
@@ -150,16 +150,22 @@ dependencies:
|
|
150
150
|
name: strptime
|
151
151
|
requirement: !ruby/object:Gem::Requirement
|
152
152
|
requirements:
|
153
|
-
- - "
|
153
|
+
- - ">="
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
version: 0.2.2
|
156
|
+
- - "<"
|
154
157
|
- !ruby/object:Gem::Version
|
155
|
-
version:
|
158
|
+
version: 1.0.0
|
156
159
|
type: :runtime
|
157
160
|
prerelease: false
|
158
161
|
version_requirements: !ruby/object:Gem::Requirement
|
159
162
|
requirements:
|
160
|
-
- - "
|
163
|
+
- - ">="
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: 0.2.2
|
166
|
+
- - "<"
|
161
167
|
- !ruby/object:Gem::Version
|
162
|
-
version:
|
168
|
+
version: 1.0.0
|
163
169
|
- !ruby/object:Gem::Dependency
|
164
170
|
name: dig_rb
|
165
171
|
requirement: !ruby/object:Gem::Requirement
|
@@ -306,6 +312,7 @@ email:
|
|
306
312
|
- frsyuki@gmail.com
|
307
313
|
executables:
|
308
314
|
- fluent-binlog-reader
|
315
|
+
- fluent-ca-generate
|
309
316
|
- fluent-cat
|
310
317
|
- fluent-debug
|
311
318
|
- fluent-gem
|
@@ -332,6 +339,7 @@ files:
|
|
332
339
|
- Vagrantfile
|
333
340
|
- appveyor.yml
|
334
341
|
- bin/fluent-binlog-reader
|
342
|
+
- bin/fluent-ca-generate
|
335
343
|
- bin/fluent-cat
|
336
344
|
- bin/fluent-debug
|
337
345
|
- bin/fluent-gem
|
@@ -379,6 +387,7 @@ files:
|
|
379
387
|
- lib/fluent/clock.rb
|
380
388
|
- lib/fluent/command/binlog_reader.rb
|
381
389
|
- lib/fluent/command/bundler_injection.rb
|
390
|
+
- lib/fluent/command/ca_generate.rb
|
382
391
|
- lib/fluent/command/cat.rb
|
383
392
|
- lib/fluent/command/debug.rb
|
384
393
|
- lib/fluent/command/fluentd.rb
|
@@ -580,6 +589,7 @@ files:
|
|
580
589
|
- templates/plugin_config_formatter/param.md.erb
|
581
590
|
- templates/plugin_config_formatter/section.md.erb
|
582
591
|
- test/command/test_binlog_reader.rb
|
592
|
+
- test/command/test_ca_generate.rb
|
583
593
|
- test/command/test_fluentd.rb
|
584
594
|
- test/command/test_plugin_config_formatter.rb
|
585
595
|
- test/command/test_plugin_generator.rb
|
@@ -748,6 +758,7 @@ specification_version: 4
|
|
748
758
|
summary: Fluentd event collector
|
749
759
|
test_files:
|
750
760
|
- test/command/test_binlog_reader.rb
|
761
|
+
- test/command/test_ca_generate.rb
|
751
762
|
- test/command/test_fluentd.rb
|
752
763
|
- test/command/test_plugin_config_formatter.rb
|
753
764
|
- test/command/test_plugin_generator.rb
|