fluentd 0.12.20 → 0.12.21
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/ChangeLog +23 -0
- data/Rakefile +2 -2
- data/bin/fluent-debug +0 -1
- data/lib/fluent/agent.rb +12 -9
- data/lib/fluent/buffer.rb +9 -3
- data/lib/fluent/command/bundler_injection.rb +2 -0
- data/lib/fluent/command/cat.rb +1 -1
- data/lib/fluent/command/debug.rb +3 -2
- data/lib/fluent/command/fluentd.rb +3 -1
- data/lib/fluent/config.rb +4 -5
- data/lib/fluent/config/basic_parser.rb +3 -4
- data/lib/fluent/config/configure_proxy.rb +2 -0
- data/lib/fluent/config/dsl.rb +3 -0
- data/lib/fluent/config/element.rb +3 -2
- data/lib/fluent/config/literal_parser.rb +8 -5
- data/lib/fluent/config/parser.rb +5 -3
- data/lib/fluent/config/section.rb +3 -3
- data/lib/fluent/config/types.rb +44 -50
- data/lib/fluent/config/v1_parser.rb +8 -6
- data/lib/fluent/configurable.rb +8 -6
- data/lib/fluent/engine.rb +23 -11
- data/lib/fluent/event.rb +2 -0
- data/lib/fluent/event_router.rb +4 -2
- data/lib/fluent/filter.rb +6 -0
- data/lib/fluent/formatter.rb +27 -25
- data/lib/fluent/input.rb +5 -0
- data/lib/fluent/label.rb +2 -2
- data/lib/fluent/log.rb +5 -2
- data/lib/fluent/mixin.rb +4 -2
- data/lib/fluent/output.rb +45 -31
- data/lib/fluent/parser.rb +35 -25
- data/lib/fluent/plugin.rb +4 -0
- data/lib/fluent/plugin/buf_file.rb +9 -2
- data/lib/fluent/plugin/buf_memory.rb +7 -1
- data/lib/fluent/plugin/exec_util.rb +7 -2
- data/lib/fluent/plugin/filter_grep.rb +6 -3
- data/lib/fluent/plugin/filter_record_transformer.rb +52 -51
- data/lib/fluent/plugin/filter_stdout.rb +4 -1
- data/lib/fluent/plugin/in_debug_agent.rb +7 -5
- data/lib/fluent/plugin/in_dummy.rb +8 -3
- data/lib/fluent/plugin/in_exec.rb +16 -10
- data/lib/fluent/plugin/in_forward.rb +18 -11
- data/lib/fluent/plugin/in_gc_stat.rb +6 -2
- data/lib/fluent/plugin/in_http.rb +23 -14
- data/lib/fluent/plugin/in_monitor_agent.rb +24 -17
- data/lib/fluent/plugin/in_object_space.rb +9 -4
- data/lib/fluent/plugin/in_stream.rb +15 -6
- data/lib/fluent/plugin/in_syslog.rb +18 -12
- data/lib/fluent/plugin/in_tail.rb +61 -40
- data/lib/fluent/plugin/in_tcp.rb +3 -1
- data/lib/fluent/plugin/in_udp.rb +1 -1
- data/lib/fluent/plugin/out_copy.rb +5 -1
- data/lib/fluent/plugin/out_exec.rb +9 -6
- data/lib/fluent/plugin/out_exec_filter.rb +32 -25
- data/lib/fluent/plugin/out_file.rb +11 -5
- data/lib/fluent/plugin/out_forward.rb +30 -24
- data/lib/fluent/plugin/out_null.rb +2 -0
- data/lib/fluent/plugin/out_relabel.rb +2 -0
- data/lib/fluent/plugin/out_roundrobin.rb +3 -0
- data/lib/fluent/plugin/out_stdout.rb +3 -1
- data/lib/fluent/plugin/out_stream.rb +8 -8
- data/lib/fluent/plugin/socket_util.rb +12 -10
- data/lib/fluent/process.rb +14 -8
- data/lib/fluent/registry.rb +2 -2
- data/lib/fluent/root_agent.rb +16 -12
- data/lib/fluent/rpc.rb +7 -7
- data/lib/fluent/supervisor.rb +35 -69
- data/lib/fluent/system_config.rb +98 -0
- data/lib/fluent/test.rb +1 -1
- data/lib/fluent/test/base.rb +6 -1
- data/lib/fluent/test/filter_test.rb +4 -0
- data/lib/fluent/test/formatter_test.rb +3 -2
- data/lib/fluent/test/input_test.rb +6 -0
- data/lib/fluent/test/output_test.rb +4 -0
- data/lib/fluent/test/parser_test.rb +3 -2
- data/lib/fluent/timezone.rb +2 -0
- data/lib/fluent/version.rb +1 -1
- data/test/config/test_configurable.rb +11 -11
- data/test/config/test_configure_proxy.rb +1 -1
- data/test/config/test_system_config.rb +5 -5
- data/test/config/test_types.rb +70 -0
- data/test/plugin/test_filter_record_transformer.rb +72 -55
- data/test/plugin/test_in_forward.rb +4 -0
- data/test/plugin/test_in_tail.rb +73 -2
- data/test/test_config.rb +2 -2
- data/test/test_event_router.rb +1 -0
- data/test/test_output.rb +27 -3
- data/test/test_plugin_classes.rb +3 -0
- data/test/test_process.rb +1 -0
- data/test/test_root_agent.rb +5 -3
- metadata +3 -2
data/lib/fluent/parser.rb
CHANGED
@@ -14,9 +14,19 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
16
|
|
17
|
-
|
18
|
-
|
17
|
+
require 'time'
|
18
|
+
require 'json'
|
19
|
+
|
20
|
+
require 'yajl'
|
19
21
|
|
22
|
+
require 'fluent/config/error'
|
23
|
+
require 'fluent/config/element'
|
24
|
+
require 'fluent/configurable'
|
25
|
+
require 'fluent/engine'
|
26
|
+
require 'fluent/registry'
|
27
|
+
require 'fluent/time'
|
28
|
+
|
29
|
+
module Fluent
|
20
30
|
class ParserError < StandardError
|
21
31
|
end
|
22
32
|
|
@@ -27,7 +37,7 @@ module Fluent
|
|
27
37
|
# 'configure()' may raise errors for unexpected configurations
|
28
38
|
attr_accessor :estimate_current_event
|
29
39
|
|
30
|
-
config_param :keep_time_key, :bool, :
|
40
|
+
config_param :keep_time_key, :bool, default: false
|
31
41
|
|
32
42
|
def initialize
|
33
43
|
super
|
@@ -113,9 +123,9 @@ module Fluent
|
|
113
123
|
|
114
124
|
def self.included(klass)
|
115
125
|
klass.instance_eval {
|
116
|
-
config_param :types, :string, :
|
117
|
-
config_param :types_delimiter, :string, :
|
118
|
-
config_param :types_label_delimiter, :string, :
|
126
|
+
config_param :types, :string, default: nil
|
127
|
+
config_param :types_delimiter, :string, default: ','
|
128
|
+
config_param :types_label_delimiter, :string, default: ':'
|
119
129
|
}
|
120
130
|
end
|
121
131
|
|
@@ -162,8 +172,8 @@ module Fluent
|
|
162
172
|
class RegexpParser < Parser
|
163
173
|
include TypeConverter
|
164
174
|
|
165
|
-
config_param :time_key, :string, :
|
166
|
-
config_param :time_format, :string, :
|
175
|
+
config_param :time_key, :string, default: 'time'
|
176
|
+
config_param :time_format, :string, default: nil
|
167
177
|
|
168
178
|
def initialize(regexp, conf={})
|
169
179
|
super()
|
@@ -235,9 +245,9 @@ module Fluent
|
|
235
245
|
end
|
236
246
|
|
237
247
|
class JSONParser < Parser
|
238
|
-
config_param :time_key, :string, :
|
239
|
-
config_param :time_format, :string, :
|
240
|
-
config_param :json_parser, :string, :
|
248
|
+
config_param :time_key, :string, default: 'time'
|
249
|
+
config_param :time_format, :string, default: nil
|
250
|
+
config_param :json_parser, :string, default: 'oj'
|
241
251
|
|
242
252
|
def configure(conf)
|
243
253
|
super
|
@@ -250,7 +260,7 @@ module Fluent
|
|
250
260
|
begin
|
251
261
|
raise LoadError unless @json_parser == 'oj'
|
252
262
|
require 'oj'
|
253
|
-
Oj.default_options = {:
|
263
|
+
Oj.default_options = {bigdecimal_load: :float}
|
254
264
|
@load_proc = Oj.method(:load)
|
255
265
|
@error_class = Oj::ParseError
|
256
266
|
rescue LoadError
|
@@ -298,17 +308,17 @@ module Fluent
|
|
298
308
|
class ValuesParser < Parser
|
299
309
|
include TypeConverter
|
300
310
|
|
301
|
-
config_param :keys, :
|
311
|
+
config_param :keys, default: [] do |val|
|
302
312
|
if val.start_with?('[') # This check is enough because keys parameter is simple. No '[' started column name.
|
303
313
|
JSON.load(val)
|
304
314
|
else
|
305
315
|
val.split(",")
|
306
316
|
end
|
307
317
|
end
|
308
|
-
config_param :time_key, :string, :
|
309
|
-
config_param :time_format, :string, :
|
310
|
-
config_param :null_value_pattern, :string, :
|
311
|
-
config_param :null_empty_string, :bool, :
|
318
|
+
config_param :time_key, :string, default: nil
|
319
|
+
config_param :time_format, :string, default: nil
|
320
|
+
config_param :null_value_pattern, :string, default: nil
|
321
|
+
config_param :null_empty_string, :bool, default: false
|
312
322
|
|
313
323
|
def configure(conf)
|
314
324
|
super
|
@@ -377,7 +387,7 @@ module Fluent
|
|
377
387
|
end
|
378
388
|
|
379
389
|
class TSVParser < ValuesParser
|
380
|
-
config_param :delimiter, :string, :
|
390
|
+
config_param :delimiter, :string, default: "\t"
|
381
391
|
|
382
392
|
def configure(conf)
|
383
393
|
super
|
@@ -394,9 +404,9 @@ module Fluent
|
|
394
404
|
end
|
395
405
|
|
396
406
|
class LabeledTSVParser < ValuesParser
|
397
|
-
config_param :delimiter, :string, :
|
398
|
-
config_param :label_delimiter, :string, :
|
399
|
-
config_param :time_key, :string, :
|
407
|
+
config_param :delimiter, :string, default: "\t"
|
408
|
+
config_param :label_delimiter, :string, default: ":"
|
409
|
+
config_param :time_key, :string, default: "time"
|
400
410
|
|
401
411
|
def configure(conf)
|
402
412
|
conf['keys'] = conf['time_key'] || 'time'
|
@@ -437,7 +447,7 @@ module Fluent
|
|
437
447
|
end
|
438
448
|
|
439
449
|
class NoneParser < Parser
|
440
|
-
config_param :message_key, :string, :
|
450
|
+
config_param :message_key, :string, default: 'message'
|
441
451
|
|
442
452
|
def parse(text)
|
443
453
|
record = {}
|
@@ -526,8 +536,8 @@ module Fluent
|
|
526
536
|
# From in_syslog default pattern
|
527
537
|
REGEXP_WITH_PRI = /^\<(?<pri>[0-9]+)\>(?<time>[^ ]* {1,2}[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?(?:[^\:]*\:)? *(?<message>.*)$/
|
528
538
|
|
529
|
-
config_param :time_format, :string, :
|
530
|
-
config_param :with_priority, :bool, :
|
539
|
+
config_param :time_format, :string, default: "%b %d %H:%M:%S"
|
540
|
+
config_param :with_priority, :bool, default: false
|
531
541
|
|
532
542
|
def initialize
|
533
543
|
super
|
@@ -586,7 +596,7 @@ module Fluent
|
|
586
596
|
end
|
587
597
|
|
588
598
|
class MultilineParser < Parser
|
589
|
-
config_param :format_firstline, :string, :
|
599
|
+
config_param :format_firstline, :string, default: nil
|
590
600
|
|
591
601
|
FORMAT_MAX_NUM = 20
|
592
602
|
|
data/lib/fluent/plugin.rb
CHANGED
@@ -14,6 +14,8 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
16
|
|
17
|
+
require 'fluent/config/error'
|
18
|
+
|
17
19
|
module Fluent
|
18
20
|
class PluginClass
|
19
21
|
# This class is refactored using Fluent::Registry at v0.14
|
@@ -66,10 +68,12 @@ module Fluent
|
|
66
68
|
end
|
67
69
|
|
68
70
|
def new_parser(type)
|
71
|
+
require 'fluent/parser'
|
69
72
|
TextParser.lookup(type)
|
70
73
|
end
|
71
74
|
|
72
75
|
def new_formatter(type)
|
76
|
+
require 'fluent/formatter'
|
73
77
|
TextFormatter.lookup(type)
|
74
78
|
end
|
75
79
|
|
@@ -14,6 +14,13 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
16
|
|
17
|
+
require 'fileutils'
|
18
|
+
require 'uri'
|
19
|
+
|
20
|
+
require 'fluent/env'
|
21
|
+
require 'fluent/plugin'
|
22
|
+
require 'fluent/buffer'
|
23
|
+
|
17
24
|
module Fluent
|
18
25
|
class FileBufferChunk < BufferChunk
|
19
26
|
def initialize(key, path, unique_id, mode="a+", symlink_path = nil)
|
@@ -85,7 +92,7 @@ module Fluent
|
|
85
92
|
desc 'The path where buffer chunks are stored.'
|
86
93
|
config_param :buffer_path, :string
|
87
94
|
desc 'If true, queued chunks are flushed at shutdown process.'
|
88
|
-
config_param :flush_at_shutdown, :bool, :
|
95
|
+
config_param :flush_at_shutdown, :bool, default: false
|
89
96
|
|
90
97
|
# 'symlink_path' is currently only for out_file.
|
91
98
|
# That is the reason why this is not config_param, but attr_accessor.
|
@@ -112,7 +119,7 @@ module Fluent
|
|
112
119
|
end
|
113
120
|
|
114
121
|
def start
|
115
|
-
FileUtils.mkdir_p File.dirname(@buffer_path_prefix + "path"), :
|
122
|
+
FileUtils.mkdir_p File.dirname(@buffer_path_prefix + "path"), mode: DEFAULT_DIR_PERMISSION
|
116
123
|
super
|
117
124
|
end
|
118
125
|
|
@@ -14,6 +14,12 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
16
|
|
17
|
+
require 'stringio'
|
18
|
+
|
19
|
+
require 'fluent/engine'
|
20
|
+
require 'fluent/plugin'
|
21
|
+
require 'fluent/buffer'
|
22
|
+
|
17
23
|
module Fluent
|
18
24
|
class MemoryBufferChunk < BufferChunk
|
19
25
|
def initialize(key, data='')
|
@@ -71,7 +77,7 @@ module Fluent
|
|
71
77
|
end
|
72
78
|
|
73
79
|
desc 'If true, queued chunks are flushed at shutdown process. Otherwise queued chunks are discarded'
|
74
|
-
config_param :flush_at_shutdown, :bool, :
|
80
|
+
config_param :flush_at_shutdown, :bool, default: true
|
75
81
|
# Overwrite default BasicBuffer#buffer_queue_limit
|
76
82
|
# to limit total memory usage upto 512MB.
|
77
83
|
config_set_default :buffer_queue_limit, 64
|
@@ -14,10 +14,15 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
16
|
|
17
|
+
require 'msgpack'
|
18
|
+
require 'yajl'
|
19
|
+
|
20
|
+
require 'fluent/engine'
|
21
|
+
require 'fluent/plugin'
|
22
|
+
require 'fluent/parser'
|
23
|
+
|
17
24
|
module Fluent
|
18
25
|
module ExecUtil
|
19
|
-
require 'fluent/parser'
|
20
|
-
|
21
26
|
SUPPORTED_FORMAT = {
|
22
27
|
'tsv' => :tsv,
|
23
28
|
'json' => :json,
|
@@ -14,6 +14,9 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
16
|
|
17
|
+
require 'fluent/filter'
|
18
|
+
require 'fluent/config/error'
|
19
|
+
|
17
20
|
module Fluent
|
18
21
|
class GrepFilter < Filter
|
19
22
|
Fluent::Plugin.register_filter('grep', self)
|
@@ -25,8 +28,8 @@ module Fluent
|
|
25
28
|
|
26
29
|
REGEXP_MAX_NUM = 20
|
27
30
|
|
28
|
-
(1..REGEXP_MAX_NUM).each {|i| config_param :"regexp#{i}", :string, :
|
29
|
-
(1..REGEXP_MAX_NUM).each {|i| config_param :"exclude#{i}", :string, :
|
31
|
+
(1..REGEXP_MAX_NUM).each {|i| config_param :"regexp#{i}", :string, default: nil }
|
32
|
+
(1..REGEXP_MAX_NUM).each {|i| config_param :"exclude#{i}", :string, default: nil }
|
30
33
|
|
31
34
|
# for test
|
32
35
|
attr_reader :regexps
|
@@ -67,7 +70,7 @@ module Fluent
|
|
67
70
|
result = record
|
68
71
|
end
|
69
72
|
rescue => e
|
70
|
-
log.warn "failed to grep events", :
|
73
|
+
log.warn "failed to grep events", error_class: e.class, error: e.message
|
71
74
|
log.warn_backtrace
|
72
75
|
end
|
73
76
|
result
|
@@ -14,29 +14,31 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
16
|
|
17
|
+
require 'socket'
|
18
|
+
require 'json'
|
17
19
|
require 'ostruct'
|
18
20
|
|
21
|
+
require 'fluent/filter'
|
22
|
+
require 'fluent/config/error'
|
23
|
+
require 'fluent/event'
|
24
|
+
require 'fluent/time'
|
25
|
+
|
19
26
|
module Fluent
|
20
27
|
class RecordTransformerFilter < Filter
|
21
28
|
Fluent::Plugin.register_filter('record_transformer', self)
|
22
29
|
|
23
|
-
def initialize
|
24
|
-
require 'socket'
|
25
|
-
super
|
26
|
-
end
|
27
|
-
|
28
30
|
desc 'A comma-delimited list of keys to delete.'
|
29
|
-
config_param :remove_keys, :string, :
|
31
|
+
config_param :remove_keys, :string, default: nil
|
30
32
|
desc 'A comma-delimited list of keys to keep.'
|
31
|
-
config_param :keep_keys, :string, :
|
33
|
+
config_param :keep_keys, :string, default: nil
|
32
34
|
desc 'Create new Hash to transform incoming data'
|
33
|
-
config_param :renew_record, :bool, :
|
35
|
+
config_param :renew_record, :bool, default: false
|
34
36
|
desc 'Specify field name of the record to overwrite the time of events. Its value must be unix time.'
|
35
|
-
config_param :renew_time_key, :string, :
|
37
|
+
config_param :renew_time_key, :string, default: nil
|
36
38
|
desc 'When set to true, the full Ruby syntax is enabled in the ${...} expression.'
|
37
|
-
config_param :enable_ruby, :bool, :
|
39
|
+
config_param :enable_ruby, :bool, default: false
|
38
40
|
desc 'Use original value type.'
|
39
|
-
config_param :auto_typecast, :bool, :
|
41
|
+
config_param :auto_typecast, :bool, default: false # false for lower version compatibility
|
40
42
|
|
41
43
|
def configure(conf)
|
42
44
|
super
|
@@ -60,8 +62,8 @@ module Fluent
|
|
60
62
|
end
|
61
63
|
|
62
64
|
placeholder_expander_params = {
|
63
|
-
:
|
64
|
-
:
|
65
|
+
log: log,
|
66
|
+
auto_typecast: @auto_typecast,
|
65
67
|
}
|
66
68
|
@placeholder_expander =
|
67
69
|
if @enable_ruby
|
@@ -105,7 +107,7 @@ module Fluent
|
|
105
107
|
end
|
106
108
|
new_es
|
107
109
|
rescue => e
|
108
|
-
log.warn "failed to reform records", :
|
110
|
+
log.warn "failed to reform records", error_class: e.class, error: e.message
|
109
111
|
log.warn_backtrace
|
110
112
|
log.debug "map:#{@map} record:#{last_record} placeholder_values:#{placeholder_values}"
|
111
113
|
end
|
@@ -119,33 +121,34 @@ module Fluent
|
|
119
121
|
value_str
|
120
122
|
end
|
121
123
|
rescue => e
|
122
|
-
log.warn "failed to parse #{value_str} as json. Assuming #{value_str} is a string", :
|
124
|
+
log.warn "failed to parse #{value_str} as json. Assuming #{value_str} is a string", error_class: e.class, error: e.message
|
123
125
|
value_str # emit as string
|
124
126
|
end
|
125
127
|
|
126
128
|
def reform(record, placeholder_values)
|
127
|
-
@placeholder_expander.prepare_placeholders(placeholder_values)
|
129
|
+
placeholders = @placeholder_expander.prepare_placeholders(placeholder_values)
|
128
130
|
|
129
131
|
new_record = @renew_record ? {} : record.dup
|
130
132
|
@keep_keys.each {|k| new_record[k] = record[k]} if @keep_keys and @renew_record
|
131
|
-
new_record.merge!(expand_placeholders(@map))
|
133
|
+
new_record.merge!(expand_placeholders(@map, placeholders))
|
132
134
|
@remove_keys.each {|k| new_record.delete(k) } if @remove_keys
|
133
135
|
|
134
136
|
new_record
|
135
137
|
end
|
136
138
|
|
137
|
-
def expand_placeholders(value)
|
139
|
+
def expand_placeholders(value, placeholders)
|
138
140
|
if value.is_a?(String)
|
139
|
-
new_value = @placeholder_expander.expand(value)
|
141
|
+
new_value = @placeholder_expander.expand(value, placeholders)
|
140
142
|
elsif value.is_a?(Hash)
|
141
143
|
new_value = {}
|
142
144
|
value.each_pair do |k, v|
|
143
|
-
|
145
|
+
new_key = @placeholder_expander.expand(k, placeholders, true)
|
146
|
+
new_value[new_key] = expand_placeholders(v, placeholders)
|
144
147
|
end
|
145
148
|
elsif value.is_a?(Array)
|
146
149
|
new_value = []
|
147
150
|
value.each_with_index do |v, i|
|
148
|
-
new_value[i] = expand_placeholders(v)
|
151
|
+
new_value[i] = expand_placeholders(v, placeholders)
|
149
152
|
end
|
150
153
|
else
|
151
154
|
new_value = value
|
@@ -172,6 +175,7 @@ module Fluent
|
|
172
175
|
rev_tag_suffix.reverse!
|
173
176
|
end
|
174
177
|
|
178
|
+
# THIS CLASS MUST BE THREAD-SAFE
|
175
179
|
class PlaceholderExpander
|
176
180
|
attr_reader :placeholders, :log
|
177
181
|
|
@@ -208,36 +212,37 @@ module Fluent
|
|
208
212
|
end
|
209
213
|
end
|
210
214
|
|
211
|
-
|
215
|
+
placeholders
|
212
216
|
end
|
213
217
|
|
214
218
|
# Expand string with placeholders
|
215
219
|
#
|
216
220
|
# @param [String] str
|
217
221
|
# @param [Boolean] force_stringify the value must be string, used for hash key
|
218
|
-
def expand(str, force_stringify = false)
|
222
|
+
def expand(str, placeholders, force_stringify = false)
|
219
223
|
if @auto_typecast and !force_stringify
|
220
224
|
single_placeholder_matched = str.match(/\A(\${[^}]+}|__[A-Z_]+__)\z/)
|
221
225
|
if single_placeholder_matched
|
222
|
-
log_if_unknown_placeholder($1)
|
223
|
-
return
|
226
|
+
log_if_unknown_placeholder($1, placeholders)
|
227
|
+
return placeholders[single_placeholder_matched[1]]
|
224
228
|
end
|
225
229
|
end
|
226
230
|
str.gsub(/(\${[^}]+}|__[A-Z_]+__)/) {
|
227
|
-
log_if_unknown_placeholder($1)
|
228
|
-
|
231
|
+
log_if_unknown_placeholder($1, placeholders)
|
232
|
+
placeholders[$1]
|
229
233
|
}
|
230
234
|
end
|
231
235
|
|
232
236
|
private
|
233
237
|
|
234
|
-
def log_if_unknown_placeholder(placeholder)
|
235
|
-
unless
|
238
|
+
def log_if_unknown_placeholder(placeholder, placeholders)
|
239
|
+
unless placeholders.include?(placeholder)
|
236
240
|
log.warn "unknown placeholder `#{placeholder}` found"
|
237
241
|
end
|
238
242
|
end
|
239
243
|
end
|
240
244
|
|
245
|
+
# THIS CLASS MUST BE THREAD-SAFE
|
241
246
|
class RubyPlaceholderExpander
|
242
247
|
attr_reader :log
|
243
248
|
|
@@ -259,12 +264,13 @@ module Fluent
|
|
259
264
|
new_value = nil
|
260
265
|
if value.is_a?(String)
|
261
266
|
if @auto_typecast and !force_stringify
|
262
|
-
|
263
|
-
|
267
|
+
num_placeholders = value.scan('${').size
|
268
|
+
if num_placeholders == 1 and value.start_with?('${') && value.end_with?('}')
|
269
|
+
new_value = value[2..-2] # ${..} => ..
|
264
270
|
end
|
265
271
|
end
|
266
272
|
unless new_value
|
267
|
-
new_value = %Q
|
273
|
+
new_value = "%Q[#{value.gsub('${', '#{')}]" # xx${..}xx => %Q[xx#{..}xx]
|
268
274
|
end
|
269
275
|
elsif value.is_a?(Hash)
|
270
276
|
new_value = {}
|
@@ -283,31 +289,25 @@ module Fluent
|
|
283
289
|
end
|
284
290
|
|
285
291
|
def prepare_placeholders(placeholder_values)
|
286
|
-
|
287
|
-
@time = placeholder_values['time']
|
288
|
-
@record = placeholder_values['record']
|
289
|
-
@tag_parts = placeholder_values['tag_parts']
|
290
|
-
@tag_prefix = placeholder_values['tag_prefix']
|
291
|
-
@tag_suffix = placeholder_values['tag_suffix']
|
292
|
-
@hostname = placeholder_values['hostname']
|
292
|
+
placeholder_values
|
293
293
|
end
|
294
294
|
|
295
295
|
# Expand string with placeholders
|
296
296
|
#
|
297
297
|
# @param [String] str
|
298
|
-
def expand(str, force_stringify = false)
|
298
|
+
def expand(str, placeholders, force_stringify = false)
|
299
299
|
@cleanroom_expander.expand(
|
300
300
|
str,
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
301
|
+
placeholders['tag'],
|
302
|
+
placeholders['time'],
|
303
|
+
placeholders['record'],
|
304
|
+
placeholders['tag_parts'],
|
305
|
+
placeholders['tag_prefix'],
|
306
|
+
placeholders['tag_suffix'],
|
307
|
+
placeholders['hostname'],
|
308
308
|
)
|
309
309
|
rescue => e
|
310
|
-
log.warn "failed to expand `#{str}`", :
|
310
|
+
log.warn "failed to expand `#{str}`", error_class: e.class, error: e.message
|
311
311
|
log.warn_backtrace
|
312
312
|
nil
|
313
313
|
end
|
@@ -315,15 +315,16 @@ module Fluent
|
|
315
315
|
class CleanroomExpander
|
316
316
|
def expand(__str_to_eval__, tag, time, record, tag_parts, tag_prefix, tag_suffix, hostname)
|
317
317
|
tags = tag_parts # for old version compatibility
|
318
|
-
|
318
|
+
Thread.current[:record_transformer_record] = record # for old version compatibility
|
319
319
|
instance_eval(__str_to_eval__)
|
320
320
|
end
|
321
321
|
|
322
322
|
# for old version compatibility
|
323
323
|
def method_missing(name)
|
324
324
|
key = name.to_s
|
325
|
-
|
326
|
-
|
325
|
+
record = Thread.current[:record_transformer_record]
|
326
|
+
if record.has_key?(key)
|
327
|
+
record[key]
|
327
328
|
else
|
328
329
|
raise NameError, "undefined local variable or method `#{key}'"
|
329
330
|
end
|