fluentd 0.12.15 → 0.12.16
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/.gitignore +1 -0
- data/ChangeLog +18 -0
- data/fluentd.gemspec +1 -1
- data/lib/fluent/command/fluentd.rb +4 -0
- data/lib/fluent/config/configure_proxy.rb +31 -1
- data/lib/fluent/configurable.rb +4 -0
- data/lib/fluent/output.rb +1 -1
- data/lib/fluent/parser.rb +19 -2
- data/lib/fluent/plugin/filter_grep.rb +7 -16
- data/lib/fluent/plugin/in_http.rb +22 -12
- data/lib/fluent/plugin/string_util.rb +32 -0
- data/lib/fluent/rpc.rb +4 -4
- data/lib/fluent/supervisor.rb +40 -0
- data/lib/fluent/version.rb +1 -1
- data/test/config/test_configure_proxy.rb +122 -0
- data/test/plugin/test_in_http.rb +50 -0
- data/test/test_output.rb +1 -1
- data/test/test_parser.rb +90 -0
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2bc899dd92a360462c8ab40bdec4dfa955918c74
|
4
|
+
data.tar.gz: 0c93a1e695baf87d2d01c0ff10821a2733115c44
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 35585caea38a587df230faa0027cbd5820c6e43e48669d35755055f73a185509e08bf0089c0ff7b2e4c4eaacfe361406f14709161d81f7e3ebc6354c5a203fd1
|
7
|
+
data.tar.gz: 9f3e64fedf79a5609c54e7387a14d2a4c03705b7be00d4382d554a4ff357b5617dcc10689f6e4067ecd8e9e99cf6158583c88ac32761433f04fb091229db6fdc
|
data/.gitignore
CHANGED
data/ChangeLog
CHANGED
@@ -1,5 +1,23 @@
|
|
1
1
|
# v0.12
|
2
2
|
|
3
|
+
## Release 0.12.16 - 2015/09/30
|
4
|
+
|
5
|
+
### New features / Enhancement
|
6
|
+
|
7
|
+
* parser: Add null_value_pattern and null_empty_string option for ltsv, csv and tsv.
|
8
|
+
https://github.com/fluent/fluentd/pull/657
|
9
|
+
* RPC: Implement /api/config.dump and /api/config.getDump APIs to dump in memory config
|
10
|
+
https://github.com/fluent/fluentd/pull/666
|
11
|
+
* Add --show-plugin-config option
|
12
|
+
https://github.com/fluent/fluentd/pull/663
|
13
|
+
|
14
|
+
### Bug fixes
|
15
|
+
|
16
|
+
* in_http: Fix add_remote_addr and add_http_headers options not working on bulk request
|
17
|
+
https://github.com/fluent/fluentd/pull/673
|
18
|
+
* parser: RegexpParser#initialize should wrap only Hash configuration
|
19
|
+
https://github.com/fluent/fluentd/pull/647
|
20
|
+
|
3
21
|
## Release 0.12.15 - 2015/07/29
|
4
22
|
|
5
23
|
### New features / Enhancement
|
data/fluentd.gemspec
CHANGED
@@ -30,7 +30,7 @@ Gem::Specification.new do |gem|
|
|
30
30
|
gem.add_runtime_dependency("string-scrub", [">= 0.0.3"])
|
31
31
|
|
32
32
|
gem.add_development_dependency("rake", [">= 0.9.2"])
|
33
|
-
gem.add_development_dependency("flexmock")
|
33
|
+
gem.add_development_dependency("flexmock", ["~> 1.3.3"])
|
34
34
|
gem.add_development_dependency("parallel_tests", [">= 0.15.3"])
|
35
35
|
gem.add_development_dependency("simplecov", ["~> 0.6.4"])
|
36
36
|
gem.add_development_dependency("rr", [">= 1.0.0"])
|
@@ -34,6 +34,10 @@ op.on('--dry-run', "Check fluentd setup is correct or not", TrueClass) {|b|
|
|
34
34
|
opts[:dry_run] = b
|
35
35
|
}
|
36
36
|
|
37
|
+
op.on('--show-plugin-config=PLUGIN', "Show PLUGIN configuration and exit(ex: input:dummy)") {|plugin|
|
38
|
+
opts[:show_plugin_config] = plugin
|
39
|
+
}
|
40
|
+
|
37
41
|
op.on('-p', '--plugin DIR', "add plugin directory") {|s|
|
38
42
|
opts[:plugin_dirs] << s
|
39
43
|
}
|
@@ -17,7 +17,7 @@
|
|
17
17
|
module Fluent
|
18
18
|
module Config
|
19
19
|
class ConfigureProxy
|
20
|
-
attr_accessor :name, :final, :param_name, :required, :multi, :alias, :argument, :params, :defaults, :sections
|
20
|
+
attr_accessor :name, :final, :param_name, :required, :multi, :alias, :argument, :params, :defaults, :descriptions, :sections
|
21
21
|
# config_param :desc, :string, :default => '....'
|
22
22
|
# config_set_default :buffer_type, :memory
|
23
23
|
#
|
@@ -48,6 +48,7 @@ module Fluent
|
|
48
48
|
@argument = nil # nil: ignore argument
|
49
49
|
@params = {}
|
50
50
|
@defaults = {}
|
51
|
+
@descriptions = {}
|
51
52
|
@sections = {}
|
52
53
|
end
|
53
54
|
|
@@ -157,6 +158,10 @@ module Fluent
|
|
157
158
|
config_set_default(name, opts[:default])
|
158
159
|
end
|
159
160
|
|
161
|
+
if opts.has_key?(:desc)
|
162
|
+
config_set_desc(name, opts[:desc])
|
163
|
+
end
|
164
|
+
|
160
165
|
[name, block, opts]
|
161
166
|
end
|
162
167
|
|
@@ -189,6 +194,17 @@ module Fluent
|
|
189
194
|
nil
|
190
195
|
end
|
191
196
|
|
197
|
+
def config_set_desc(name, description)
|
198
|
+
name = name.to_sym
|
199
|
+
|
200
|
+
if @descriptions.has_key?(name)
|
201
|
+
raise ArgumentError, "#{self.name}: description specified twice for #{name}"
|
202
|
+
end
|
203
|
+
|
204
|
+
@descriptions[name] = description
|
205
|
+
nil
|
206
|
+
end
|
207
|
+
|
192
208
|
def config_section(name, *args, &block)
|
193
209
|
unless block_given?
|
194
210
|
raise ArgumentError, "#{self.name}: config_section requires block parameter"
|
@@ -208,6 +224,20 @@ module Fluent
|
|
208
224
|
|
209
225
|
name
|
210
226
|
end
|
227
|
+
|
228
|
+
def dump(level = 0)
|
229
|
+
dumped_config = "\n"
|
230
|
+
indent = " " * level
|
231
|
+
@params.each do |name, config|
|
232
|
+
dumped_config << "#{indent}#{name}: #{config[1][:type]}: <#{@defaults[name].inspect}>"
|
233
|
+
dumped_config << " # #{@descriptions[name]}" if @descriptions[name]
|
234
|
+
dumped_config << "\n"
|
235
|
+
end
|
236
|
+
@sections.each do |section_name, sub_proxy|
|
237
|
+
dumped_config << "#{indent}#{section_name}#{sub_proxy.dump(level + 1)}"
|
238
|
+
end
|
239
|
+
dumped_config
|
240
|
+
end
|
211
241
|
end
|
212
242
|
end
|
213
243
|
end
|
data/lib/fluent/configurable.rb
CHANGED
data/lib/fluent/output.rb
CHANGED
@@ -527,7 +527,7 @@ module Fluent
|
|
527
527
|
else
|
528
528
|
@flush_interval = [60, @time_slice_cache_interval].min
|
529
529
|
@enqueue_buffer_proc = Proc.new do
|
530
|
-
nowslice = @time_slicer.call(Engine.now
|
530
|
+
nowslice = @time_slicer.call(Engine.now - @time_slice_wait)
|
531
531
|
@buffer.keys.each {|key|
|
532
532
|
if key < nowslice
|
533
533
|
@buffer.push(key)
|
data/lib/fluent/parser.rb
CHANGED
@@ -169,7 +169,7 @@ module Fluent
|
|
169
169
|
super()
|
170
170
|
@regexp = regexp
|
171
171
|
unless conf.empty?
|
172
|
-
conf = Config::Element.new('default_regexp_conf', '', conf, [])
|
172
|
+
conf = Config::Element.new('default_regexp_conf', '', conf, []) unless conf.is_a?(Config::Element)
|
173
173
|
configure(conf)
|
174
174
|
end
|
175
175
|
|
@@ -295,6 +295,8 @@ module Fluent
|
|
295
295
|
end
|
296
296
|
config_param :time_key, :string, :default => nil
|
297
297
|
config_param :time_format, :string, :default => nil
|
298
|
+
config_param :null_value_pattern, :string, :default => nil
|
299
|
+
config_param :null_empty_string, :bool, :default => false
|
298
300
|
|
299
301
|
def configure(conf)
|
300
302
|
super
|
@@ -308,11 +310,16 @@ module Fluent
|
|
308
310
|
end
|
309
311
|
|
310
312
|
@time_parser = TimeParser.new(@time_format)
|
313
|
+
|
314
|
+
if @null_value_pattern
|
315
|
+
@null_value_pattern = Regexp.new(@null_value_pattern)
|
316
|
+
end
|
317
|
+
|
311
318
|
@mutex = Mutex.new
|
312
319
|
end
|
313
320
|
|
314
321
|
def values_map(values)
|
315
|
-
record = Hash[keys.zip(values)]
|
322
|
+
record = Hash[keys.zip(values.map { |value| convert_value_to_nil(value) })]
|
316
323
|
|
317
324
|
if @time_key
|
318
325
|
value = @keep_time_key ? record[@time_key] : record.delete(@time_key)
|
@@ -345,6 +352,16 @@ module Fluent
|
|
345
352
|
end
|
346
353
|
}
|
347
354
|
end
|
355
|
+
|
356
|
+
def convert_value_to_nil(value)
|
357
|
+
if value and @null_empty_string
|
358
|
+
value = (value == '') ? nil : value
|
359
|
+
end
|
360
|
+
if value and @null_value_pattern
|
361
|
+
value = ::Fluent::StringUtil.match_regexp(@null_value_pattern, value) ? nil : value
|
362
|
+
end
|
363
|
+
value
|
364
|
+
end
|
348
365
|
end
|
349
366
|
|
350
367
|
class TSVParser < ValuesParser
|
@@ -18,6 +18,11 @@ module Fluent
|
|
18
18
|
class GrepFilter < Filter
|
19
19
|
Fluent::Plugin.register_filter('grep', self)
|
20
20
|
|
21
|
+
def initialize
|
22
|
+
super
|
23
|
+
require 'fluent/plugin/string_util'
|
24
|
+
end
|
25
|
+
|
21
26
|
REGEXP_MAX_NUM = 20
|
22
27
|
|
23
28
|
(1..REGEXP_MAX_NUM).each {|i| config_param :"regexp#{i}", :string, :default => nil }
|
@@ -54,10 +59,10 @@ module Fluent
|
|
54
59
|
begin
|
55
60
|
catch(:break_loop) do
|
56
61
|
@regexps.each do |key, regexp|
|
57
|
-
throw :break_loop unless
|
62
|
+
throw :break_loop unless ::Fluent::StringUtil.match_regexp(regexp, record[key].to_s)
|
58
63
|
end
|
59
64
|
@excludes.each do |key, exclude|
|
60
|
-
throw :break_loop if
|
65
|
+
throw :break_loop if ::Fluent::StringUtil.match_regexp(exclude, record[key].to_s)
|
61
66
|
end
|
62
67
|
result = record
|
63
68
|
end
|
@@ -67,19 +72,5 @@ module Fluent
|
|
67
72
|
end
|
68
73
|
result
|
69
74
|
end
|
70
|
-
|
71
|
-
private
|
72
|
-
|
73
|
-
def match(regexp, string)
|
74
|
-
begin
|
75
|
-
return regexp.match(string)
|
76
|
-
rescue ArgumentError => e
|
77
|
-
raise e unless e.message.index("invalid byte sequence in".freeze).zero?
|
78
|
-
log.info "invalid byte sequence is replaced in `#{string}`"
|
79
|
-
string = string.scrub('?')
|
80
|
-
retry
|
81
|
-
end
|
82
|
-
return true
|
83
|
-
end
|
84
75
|
end
|
85
76
|
end
|
@@ -131,18 +131,18 @@ module Fluent
|
|
131
131
|
end
|
132
132
|
end
|
133
133
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
134
|
+
unless record.is_a?(Array)
|
135
|
+
if @add_http_headers
|
136
|
+
params.each_pair { |k,v|
|
137
|
+
if k.start_with?("HTTP_")
|
138
|
+
record[k] = v
|
139
|
+
end
|
140
|
+
}
|
141
|
+
end
|
142
|
+
if @add_remote_addr
|
143
|
+
record['REMOTE_ADDR'] = params['REMOTE_ADDR']
|
144
|
+
end
|
144
145
|
end
|
145
|
-
|
146
146
|
time = if param_time = params['time']
|
147
147
|
param_time = param_time.to_i
|
148
148
|
param_time.zero? ? Engine.now : param_time
|
@@ -159,11 +159,21 @@ module Fluent
|
|
159
159
|
if record.is_a?(Array)
|
160
160
|
mes = MultiEventStream.new
|
161
161
|
record.each do |single_record|
|
162
|
+
if @add_http_headers
|
163
|
+
params.each_pair { |k,v|
|
164
|
+
if k.start_with?("HTTP_")
|
165
|
+
single_record[k] = v
|
166
|
+
end
|
167
|
+
}
|
168
|
+
end
|
169
|
+
if @add_remote_addr
|
170
|
+
single_record['REMOTE_ADDR'] = params['REMOTE_ADDR']
|
171
|
+
end
|
162
172
|
single_time = single_record.delete("time") || time
|
163
173
|
mes.add(single_time, single_record)
|
164
174
|
end
|
165
175
|
router.emit_stream(tag, mes)
|
166
|
-
|
176
|
+
else
|
167
177
|
router.emit(tag, time, record)
|
168
178
|
end
|
169
179
|
rescue
|
@@ -0,0 +1,32 @@
|
|
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
|
+
module Fluent
|
18
|
+
module StringUtil
|
19
|
+
def match_regexp(regexp, string)
|
20
|
+
begin
|
21
|
+
return regexp.match(string)
|
22
|
+
rescue ArgumentError => e
|
23
|
+
raise e unless e.message.index("invalid byte sequence in".freeze).zero?
|
24
|
+
log.info "invalid byte sequence is replaced in `#{string}`"
|
25
|
+
string = string.scrub('?')
|
26
|
+
retry
|
27
|
+
end
|
28
|
+
return true
|
29
|
+
end
|
30
|
+
module_function :match_regexp
|
31
|
+
end
|
32
|
+
end
|
data/lib/fluent/rpc.rb
CHANGED
@@ -41,7 +41,7 @@ module Fluent
|
|
41
41
|
def mount_proc(path, &block)
|
42
42
|
@server.mount_proc(path) { |req, res|
|
43
43
|
begin
|
44
|
-
code, header,
|
44
|
+
code, header, response = block.call(req, res)
|
45
45
|
rescue => e
|
46
46
|
@log.warn "failed to handle RPC request", :path => path, :error => e.to_s
|
47
47
|
@log.warn_backtrace e.backtrace
|
@@ -56,11 +56,11 @@ module Fluent
|
|
56
56
|
|
57
57
|
code = 200 if code.nil?
|
58
58
|
header = {'Content-Type' => 'application/json'} if header.nil?
|
59
|
-
body = if
|
59
|
+
body = if response.nil?
|
60
60
|
'{"ok":true}'
|
61
61
|
else
|
62
|
-
body['ok'] = code == 200
|
63
|
-
body.to_json
|
62
|
+
response.body['ok'] = code == 200
|
63
|
+
response.body.to_json
|
64
64
|
end
|
65
65
|
|
66
66
|
res.status = code
|
data/lib/fluent/supervisor.rb
CHANGED
@@ -105,6 +105,7 @@ module Fluent
|
|
105
105
|
@use_v1_config = opt[:use_v1_config]
|
106
106
|
@log_path = opt[:log_path]
|
107
107
|
@dry_run = opt[:dry_run]
|
108
|
+
@show_plugin_config = opt[:show_plugin_config]
|
108
109
|
@libs = opt[:libs]
|
109
110
|
@plugin_dirs = opt[:plugin_dirs]
|
110
111
|
@chgroup = opt[:chgroup]
|
@@ -124,12 +125,15 @@ module Fluent
|
|
124
125
|
|
125
126
|
def start
|
126
127
|
@log.init
|
128
|
+
show_plugin_config if @show_plugin_config
|
127
129
|
read_config
|
128
130
|
apply_system_config
|
129
131
|
|
130
132
|
dry_run if @dry_run
|
131
133
|
start_daemonize if @daemonize
|
132
134
|
setup_rpc_server if @rpc_endpoint
|
135
|
+
setup_rpc_get_dump if @enable_get_dump
|
136
|
+
|
133
137
|
if @supervise
|
134
138
|
install_supervisor_signal_handlers
|
135
139
|
run_rpc_server if @rpc_endpoint
|
@@ -185,6 +189,17 @@ module Fluent
|
|
185
189
|
exit 1
|
186
190
|
end
|
187
191
|
|
192
|
+
def show_plugin_config
|
193
|
+
$log.info "Show config for #{@show_plugin_config}"
|
194
|
+
name, type = @show_plugin_config.split(":")
|
195
|
+
plugin = Plugin.__send__("new_#{name}", type)
|
196
|
+
$log.info plugin.class.dump
|
197
|
+
exit 0
|
198
|
+
rescue => e
|
199
|
+
$log.error "show config failed: #{e}"
|
200
|
+
exit 1
|
201
|
+
end
|
202
|
+
|
188
203
|
def start_daemonize
|
189
204
|
@wait_daemonize_pipe_r, @wait_daemonize_pipe_w = IO.pipe
|
190
205
|
|
@@ -263,6 +278,21 @@ module Fluent
|
|
263
278
|
supervisor_sighup_handler
|
264
279
|
nil
|
265
280
|
}
|
281
|
+
@rpc_server.mount_proc('/api/config.dump') { |req, res|
|
282
|
+
$log.debug "fluentd RPC got /api/config.dump request"
|
283
|
+
$log.info "dump in-memory config"
|
284
|
+
supervisor_dump_config_handler
|
285
|
+
nil
|
286
|
+
}
|
287
|
+
end
|
288
|
+
|
289
|
+
def setup_rpc_get_dump
|
290
|
+
@rpc_server.mount_proc('/api/config.getDump') { |req, res|
|
291
|
+
$log.debug "fluentd RPC got /api/config.dump request"
|
292
|
+
$log.info "get dump in-memory config via HTTP"
|
293
|
+
res.body = supervisor_get_dump_config_handler
|
294
|
+
[nil, nil, res]
|
295
|
+
}
|
266
296
|
end
|
267
297
|
|
268
298
|
def run_rpc_server
|
@@ -399,6 +429,14 @@ module Fluent
|
|
399
429
|
end
|
400
430
|
end
|
401
431
|
|
432
|
+
def supervisor_dump_config_handler
|
433
|
+
$log.info @conf.to_s
|
434
|
+
end
|
435
|
+
|
436
|
+
def supervisor_get_dump_config_handler
|
437
|
+
{conf: @conf.to_s}
|
438
|
+
end
|
439
|
+
|
402
440
|
def read_config
|
403
441
|
$log.info "reading config file", :path => @config_path
|
404
442
|
@config_fname = File.basename(@config_path)
|
@@ -423,6 +461,7 @@ module Fluent
|
|
423
461
|
config_param :suppress_config_dump, :bool, :default => nil
|
424
462
|
config_param :without_source, :bool, :default => nil
|
425
463
|
config_param :rpc_endpoint, :string, :default => nil
|
464
|
+
config_param :enable_get_dump, :bool, :default => nil
|
426
465
|
|
427
466
|
def initialize(conf)
|
428
467
|
super()
|
@@ -438,6 +477,7 @@ module Fluent
|
|
438
477
|
@suppress_repeated_stacktrace = system.suppress_repeated_stacktrace unless system.suppress_repeated_stacktrace.nil?
|
439
478
|
@without_source = system.without_source unless system.without_source.nil?
|
440
479
|
@rpc_endpoint = system.rpc_endpoint unless system.rpc_endpoint.nil?
|
480
|
+
@enable_get_dump = system.enable_get_dump unless system.enable_get_dump.nil?
|
441
481
|
}
|
442
482
|
end
|
443
483
|
end
|
data/lib/fluent/version.rb
CHANGED
@@ -94,6 +94,128 @@ module Fluent::Config
|
|
94
94
|
assert_raise(ArgumentError) { proxy.config_argument(:name, default: "name2") }
|
95
95
|
end
|
96
96
|
end
|
97
|
+
|
98
|
+
sub_test_case '#config_set_desc' do
|
99
|
+
setup do
|
100
|
+
@proxy = Fluent::Config::ConfigureProxy.new(:section)
|
101
|
+
end
|
102
|
+
|
103
|
+
test 'does not permit description specification twice w/ :desc option' do
|
104
|
+
@proxy.config_param(:name, :string, desc: "description")
|
105
|
+
assert_raise(ArgumentError) { @proxy.config_set_desc(:name, "description2") }
|
106
|
+
end
|
107
|
+
|
108
|
+
test 'does not permit description specification twice' do
|
109
|
+
@proxy.config_param(:name, :string)
|
110
|
+
@proxy.config_set_desc(:name, "description")
|
111
|
+
assert_raise(ArgumentError) { @proxy.config_set_desc(:name, "description2") }
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
sub_test_case '#dump' do
|
116
|
+
setup do
|
117
|
+
@proxy = Fluent::Config::ConfigureProxy.new(:section)
|
118
|
+
end
|
119
|
+
|
120
|
+
test 'empty proxy' do
|
121
|
+
assert_equal("\n", @proxy.dump)
|
122
|
+
end
|
123
|
+
|
124
|
+
test 'plain proxy w/o default value' do
|
125
|
+
@proxy.config_param(:name, :string)
|
126
|
+
assert_equal(<<CONFIG, @proxy.dump)
|
127
|
+
|
128
|
+
name: string: <nil>
|
129
|
+
CONFIG
|
130
|
+
end
|
131
|
+
|
132
|
+
test 'plain proxy w/ default value' do
|
133
|
+
@proxy.config_param(:name, :string, default: "name1")
|
134
|
+
assert_equal(<<CONFIG, @proxy.dump)
|
135
|
+
|
136
|
+
name: string: <"name1">
|
137
|
+
CONFIG
|
138
|
+
end
|
139
|
+
|
140
|
+
test 'plain proxy w/ default value using config_set_default' do
|
141
|
+
@proxy.config_param(:name, :string)
|
142
|
+
@proxy.config_set_default(:name, "name1")
|
143
|
+
assert_equal(<<CONFIG, @proxy.dump)
|
144
|
+
|
145
|
+
name: string: <"name1">
|
146
|
+
CONFIG
|
147
|
+
end
|
148
|
+
|
149
|
+
test 'single sub proxy' do
|
150
|
+
@proxy.config_section(:sub) do
|
151
|
+
config_param(:name, :string, default: "name1")
|
152
|
+
end
|
153
|
+
assert_equal(<<CONFIG, @proxy.dump)
|
154
|
+
|
155
|
+
sub
|
156
|
+
name: string: <"name1">
|
157
|
+
CONFIG
|
158
|
+
end
|
159
|
+
|
160
|
+
test 'nested sub proxy' do
|
161
|
+
@proxy.config_section(:sub) do
|
162
|
+
config_param(:name1, :string, default: "name1")
|
163
|
+
config_param(:name2, :string, default: "name2")
|
164
|
+
config_section(:sub2) do
|
165
|
+
config_param(:name3, :string, default: "name3")
|
166
|
+
config_param(:name4, :string, default: "name4")
|
167
|
+
end
|
168
|
+
end
|
169
|
+
assert_equal(<<CONFIG, @proxy.dump)
|
170
|
+
|
171
|
+
sub
|
172
|
+
name1: string: <"name1">
|
173
|
+
name2: string: <"name2">
|
174
|
+
sub2
|
175
|
+
name3: string: <"name3">
|
176
|
+
name4: string: <"name4">
|
177
|
+
CONFIG
|
178
|
+
end
|
179
|
+
|
180
|
+
sub_test_case 'w/ description' do
|
181
|
+
test 'single proxy' do
|
182
|
+
@proxy.config_param(:name, :string, desc: "description for name")
|
183
|
+
assert_equal(<<CONFIG, @proxy.dump)
|
184
|
+
|
185
|
+
name: string: <nil> # description for name
|
186
|
+
CONFIG
|
187
|
+
end
|
188
|
+
|
189
|
+
test 'single proxy using config_set_desc' do
|
190
|
+
@proxy.config_param(:name, :string)
|
191
|
+
@proxy.config_set_desc(:name, "description for name")
|
192
|
+
assert_equal(<<CONFIG, @proxy.dump)
|
193
|
+
|
194
|
+
name: string: <nil> # description for name
|
195
|
+
CONFIG
|
196
|
+
end
|
197
|
+
|
198
|
+
test 'sub proxy' do
|
199
|
+
@proxy.config_section(:sub) do
|
200
|
+
config_param(:name1, :string, default: "name1", desc: "desc1")
|
201
|
+
config_param(:name2, :string, default: "name2", desc: "desc2")
|
202
|
+
config_section(:sub2) do
|
203
|
+
config_param(:name3, :string, default: "name3")
|
204
|
+
config_param(:name4, :string, default: "name4", desc: "desc4")
|
205
|
+
end
|
206
|
+
end
|
207
|
+
assert_equal(<<CONFIG, @proxy.dump)
|
208
|
+
|
209
|
+
sub
|
210
|
+
name1: string: <"name1"> # desc1
|
211
|
+
name2: string: <"name2"> # desc2
|
212
|
+
sub2
|
213
|
+
name3: string: <"name3">
|
214
|
+
name4: string: <"name4"> # desc4
|
215
|
+
CONFIG
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
97
219
|
end
|
98
220
|
end
|
99
221
|
end
|
data/test/plugin/test_in_http.rb
CHANGED
@@ -85,6 +85,56 @@ class HttpInputTest < Test::Unit::TestCase
|
|
85
85
|
|
86
86
|
end
|
87
87
|
|
88
|
+
def test_json_with_add_remote_addr
|
89
|
+
d = create_driver(CONFIG + "add_remote_addr true")
|
90
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
91
|
+
|
92
|
+
d.expect_emit "tag1", time, {"REMOTE_ADDR"=>"127.0.0.1", "a"=>1}
|
93
|
+
d.expect_emit "tag2", time, {"REMOTE_ADDR"=>"127.0.0.1", "a"=>2}
|
94
|
+
|
95
|
+
d.run do
|
96
|
+
d.expected_emits.each {|tag,time,record|
|
97
|
+
res = post("/#{tag}", {"json"=>record.to_json, "time"=>time.to_s})
|
98
|
+
assert_equal "200", res.code
|
99
|
+
}
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_multi_json_with_add_remote_addr
|
105
|
+
d = create_driver(CONFIG + "add_remote_addr true")
|
106
|
+
|
107
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
108
|
+
events = [{"a"=>1},{"a"=>2}]
|
109
|
+
tag = "tag1"
|
110
|
+
|
111
|
+
d.expect_emit "tag1", time, {"REMOTE_ADDR"=>"127.0.0.1", "a"=>1}
|
112
|
+
d.expect_emit "tag1", time, {"REMOTE_ADDR"=>"127.0.0.1", "a"=>2}
|
113
|
+
|
114
|
+
d.run do
|
115
|
+
res = post("/#{tag}", {"json"=>events.to_json, "time"=>time.to_s})
|
116
|
+
assert_equal "200", res.code
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_multi_json_with_add_http_headers
|
122
|
+
d = create_driver(CONFIG + "add_http_headers true")
|
123
|
+
|
124
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
125
|
+
events = [{"a"=>1},{"a"=>2}]
|
126
|
+
tag = "tag1"
|
127
|
+
|
128
|
+
d.run do
|
129
|
+
res = post("/#{tag}", {"json"=>events.to_json, "time"=>time.to_s})
|
130
|
+
assert_equal "200", res.code
|
131
|
+
end
|
132
|
+
|
133
|
+
d.emit_streams.each { |tag, es|
|
134
|
+
assert include_http_header?(es.first[1])
|
135
|
+
}
|
136
|
+
end
|
137
|
+
|
88
138
|
def test_json_with_add_http_headers
|
89
139
|
d = create_driver(CONFIG + "add_http_headers true")
|
90
140
|
|
data/test/test_output.rb
CHANGED
@@ -213,7 +213,7 @@ module FluentOutputTest
|
|
213
213
|
FileUtils.mkdir_p(TMP_DIR)
|
214
214
|
end
|
215
215
|
|
216
|
-
TMP_DIR = File.expand_path(File.dirname(__FILE__) + "
|
216
|
+
TMP_DIR = File.expand_path(File.dirname(__FILE__) + "/tmp/time_sliced_output")
|
217
217
|
|
218
218
|
CONFIG = %[]
|
219
219
|
|
data/test/test_parser.rb
CHANGED
@@ -529,6 +529,38 @@ module ParserTest
|
|
529
529
|
assert_equal text, record['time']
|
530
530
|
end
|
531
531
|
end
|
532
|
+
|
533
|
+
data('array param' => '["a","b","c","d","e","f"]', 'string param' => 'a,b,c,d,e,f')
|
534
|
+
def test_parse_with_null_value_pattern
|
535
|
+
parser = TextParser::TSVParser.new
|
536
|
+
parser.configure(
|
537
|
+
'keys'=>param,
|
538
|
+
'time_key'=>'time',
|
539
|
+
'null_value_pattern'=>'^(-|null|NULL)$'
|
540
|
+
)
|
541
|
+
parser.parse("-\tnull\tNULL\t\t--\tnuLL") do |time, record|
|
542
|
+
assert_nil record['a']
|
543
|
+
assert_nil record['b']
|
544
|
+
assert_nil record['c']
|
545
|
+
assert_equal record['d'], ''
|
546
|
+
assert_equal record['e'], '--'
|
547
|
+
assert_equal record['f'], 'nuLL'
|
548
|
+
end
|
549
|
+
end
|
550
|
+
|
551
|
+
data('array param' => '["a","b"]', 'string param' => 'a,b')
|
552
|
+
def test_parse_with_null_empty_string
|
553
|
+
parser = TextParser::TSVParser.new
|
554
|
+
parser.configure(
|
555
|
+
'keys'=>param,
|
556
|
+
'time_key'=>'time',
|
557
|
+
'null_empty_string'=>true
|
558
|
+
)
|
559
|
+
parser.parse("\t ") do |time, record|
|
560
|
+
assert_nil record['a']
|
561
|
+
assert_equal record['b'], ' '
|
562
|
+
end
|
563
|
+
end
|
532
564
|
end
|
533
565
|
|
534
566
|
class CSVParserTest < ::Test::Unit::TestCase
|
@@ -586,6 +618,38 @@ module ParserTest
|
|
586
618
|
assert_equal text, record['time']
|
587
619
|
end
|
588
620
|
end
|
621
|
+
|
622
|
+
data('array param' => '["a","b","c","d","e","f"]', 'string param' => 'a,b,c,d,e,f')
|
623
|
+
def test_parse_with_null_value_pattern
|
624
|
+
parser = TextParser::CSVParser.new
|
625
|
+
parser.configure(
|
626
|
+
'keys'=>param,
|
627
|
+
'time_key'=>'time',
|
628
|
+
'null_value_pattern'=>'^(-|null|NULL)$'
|
629
|
+
)
|
630
|
+
parser.parse("-,null,NULL,,--,nuLL") do |time, record|
|
631
|
+
assert_nil record['a']
|
632
|
+
assert_nil record['b']
|
633
|
+
assert_nil record['c']
|
634
|
+
assert_equal record['d'], ''
|
635
|
+
assert_equal record['e'], '--'
|
636
|
+
assert_equal record['f'], 'nuLL'
|
637
|
+
end
|
638
|
+
end
|
639
|
+
|
640
|
+
data('array param' => '["a","b"]', 'string param' => 'a,b')
|
641
|
+
def test_parse_with_null_empty_string
|
642
|
+
parser = TextParser::CSVParser.new
|
643
|
+
parser.configure(
|
644
|
+
'keys'=>param,
|
645
|
+
'time_key'=>'time',
|
646
|
+
'null_empty_string'=>true
|
647
|
+
)
|
648
|
+
parser.parse(", ") do |time, record|
|
649
|
+
assert_nil record['a']
|
650
|
+
assert_equal record['b'], ' '
|
651
|
+
end
|
652
|
+
end
|
589
653
|
end
|
590
654
|
|
591
655
|
class LabeledTSVParserTest < ::Test::Unit::TestCase
|
@@ -684,6 +748,32 @@ module ParserTest
|
|
684
748
|
assert_equal text, record['time']
|
685
749
|
end
|
686
750
|
end
|
751
|
+
|
752
|
+
def test_parse_with_null_value_pattern
|
753
|
+
parser = TextParser::LabeledTSVParser.new
|
754
|
+
parser.configure(
|
755
|
+
'null_value_pattern'=>'^(-|null|NULL)$'
|
756
|
+
)
|
757
|
+
parser.parse("a:-\tb:null\tc:NULL\td:\te:--\tf:nuLL") do |time, record|
|
758
|
+
assert_nil record['a']
|
759
|
+
assert_nil record['b']
|
760
|
+
assert_nil record['c']
|
761
|
+
assert_equal record['d'], ''
|
762
|
+
assert_equal record['e'], '--'
|
763
|
+
assert_equal record['f'], 'nuLL'
|
764
|
+
end
|
765
|
+
end
|
766
|
+
|
767
|
+
def test_parse_with_null_empty_string
|
768
|
+
parser = TextParser::LabeledTSVParser.new
|
769
|
+
parser.configure(
|
770
|
+
'null_empty_string'=>true
|
771
|
+
)
|
772
|
+
parser.parse("a:\tb: ") do |time, record|
|
773
|
+
assert_nil record['a']
|
774
|
+
assert_equal record['b'], ' '
|
775
|
+
end
|
776
|
+
end
|
687
777
|
end
|
688
778
|
|
689
779
|
class NoneParserTest < ::Test::Unit::TestCase
|
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: 0.12.
|
4
|
+
version: 0.12.16
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sadayuki Furuhashi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-09-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: msgpack
|
@@ -172,16 +172,16 @@ dependencies:
|
|
172
172
|
name: flexmock
|
173
173
|
requirement: !ruby/object:Gem::Requirement
|
174
174
|
requirements:
|
175
|
-
- - "
|
175
|
+
- - "~>"
|
176
176
|
- !ruby/object:Gem::Version
|
177
|
-
version:
|
177
|
+
version: 1.3.3
|
178
178
|
type: :development
|
179
179
|
prerelease: false
|
180
180
|
version_requirements: !ruby/object:Gem::Requirement
|
181
181
|
requirements:
|
182
|
-
- - "
|
182
|
+
- - "~>"
|
183
183
|
- !ruby/object:Gem::Version
|
184
|
-
version:
|
184
|
+
version: 1.3.3
|
185
185
|
- !ruby/object:Gem::Dependency
|
186
186
|
name: parallel_tests
|
187
187
|
requirement: !ruby/object:Gem::Requirement
|
@@ -370,6 +370,7 @@ files:
|
|
370
370
|
- lib/fluent/plugin/out_stdout.rb
|
371
371
|
- lib/fluent/plugin/out_stream.rb
|
372
372
|
- lib/fluent/plugin/socket_util.rb
|
373
|
+
- lib/fluent/plugin/string_util.rb
|
373
374
|
- lib/fluent/process.rb
|
374
375
|
- lib/fluent/registry.rb
|
375
376
|
- lib/fluent/root_agent.rb
|