fluentd 0.12.0.pre.1 → 0.12.0.pre.2
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 -1
- data/.travis.yml +1 -0
- data/ChangeLog +21 -0
- data/README.md +10 -2
- data/Rakefile +4 -13
- data/example/v1_literal_example.conf +36 -0
- data/fluentd.gemspec +4 -1
- data/lib/fluent/buffer.rb +73 -46
- data/lib/fluent/command/fluentd.rb +7 -2
- data/lib/fluent/config/basic_parser.rb +5 -0
- data/lib/fluent/config/element.rb +2 -5
- data/lib/fluent/config/literal_parser.rb +26 -7
- data/lib/fluent/config/section.rb +2 -0
- data/lib/fluent/config/v1_parser.rb +9 -2
- data/lib/fluent/formatter.rb +2 -1
- data/lib/fluent/mixin.rb +22 -7
- data/lib/fluent/output.rb +17 -8
- data/lib/fluent/parser.rb +14 -3
- data/lib/fluent/plugin/buf_file.rb +30 -15
- data/lib/fluent/plugin/filter_grep.rb +69 -0
- data/lib/fluent/plugin/filter_record_transformer.rb +183 -0
- data/lib/fluent/plugin/in_exec.rb +6 -0
- data/lib/fluent/plugin/in_forward.rb +34 -4
- data/lib/fluent/plugin/in_http.rb +1 -1
- data/lib/fluent/plugin/out_exec.rb +1 -1
- data/lib/fluent/plugin/out_exec_filter.rb +8 -1
- data/lib/fluent/plugin/out_forward.rb +82 -4
- data/lib/fluent/supervisor.rb +1 -1
- data/lib/fluent/timezone.rb +131 -0
- data/lib/fluent/version.rb +1 -1
- data/test/config/assertions.rb +42 -0
- data/test/config/test_config_parser.rb +385 -0
- data/test/config/test_configurable.rb +530 -0
- data/test/config/test_configure_proxy.rb +99 -0
- data/test/config/test_dsl.rb +237 -0
- data/test/config/test_literal_parser.rb +293 -0
- data/test/config/test_section.rb +112 -0
- data/test/config/test_system_config.rb +49 -0
- data/test/helper.rb +25 -0
- data/test/plugin/test_buf_file.rb +604 -0
- data/test/plugin/test_buf_memory.rb +204 -0
- data/test/plugin/test_filter_grep.rb +124 -0
- data/test/plugin/test_filter_record_transformer.rb +251 -0
- data/test/plugin/test_in_exec.rb +1 -0
- data/test/plugin/test_in_forward.rb +205 -2
- data/test/plugin/test_in_gc_stat.rb +1 -0
- data/test/plugin/test_in_http.rb +58 -2
- data/test/plugin/test_in_object_space.rb +1 -0
- data/test/plugin/test_in_status.rb +1 -0
- data/test/plugin/test_in_stream.rb +1 -1
- data/test/plugin/test_in_syslog.rb +1 -1
- data/test/plugin/test_in_tail.rb +1 -0
- data/test/plugin/test_in_tcp.rb +1 -1
- data/test/plugin/test_in_udp.rb +1 -1
- data/test/plugin/test_out_copy.rb +1 -0
- data/test/plugin/test_out_exec.rb +1 -0
- data/test/plugin/test_out_exec_filter.rb +1 -0
- data/test/plugin/test_out_file.rb +36 -0
- data/test/plugin/test_out_forward.rb +279 -8
- data/test/plugin/test_out_roundrobin.rb +1 -0
- data/test/plugin/test_out_stdout.rb +1 -0
- data/test/plugin/test_out_stream.rb +1 -1
- data/test/test_buffer.rb +530 -0
- data/test/test_config.rb +1 -1
- data/test/test_configdsl.rb +1 -1
- data/test/test_formatter.rb +223 -0
- data/test/test_match.rb +1 -2
- data/test/test_mixin.rb +74 -2
- data/test/test_parser.rb +7 -1
- metadata +88 -35
- data/lib/fluent/plugin/buf_zfile.rb +0 -75
- data/spec/config/config_parser_spec.rb +0 -314
- data/spec/config/configurable_spec.rb +0 -524
- data/spec/config/configure_proxy_spec.rb +0 -96
- data/spec/config/dsl_spec.rb +0 -239
- data/spec/config/helper.rb +0 -49
- data/spec/config/literal_parser_spec.rb +0 -222
- data/spec/config/section_spec.rb +0 -97
- data/spec/config/system_config_spec.rb +0 -49
- data/spec/spec_helper.rb +0 -60
@@ -45,6 +45,7 @@ module Fluent
|
|
45
45
|
"name:#{@name}, arg:#{@arg}, " + attrs + ", " + @elements.inspect
|
46
46
|
end
|
47
47
|
|
48
|
+
# This method assumes _o_ is an Element object. Should return false for nil or other object
|
48
49
|
def ==(o)
|
49
50
|
self.name == o.name && self.arg == o.arg &&
|
50
51
|
self.keys.size == o.keys.size &&
|
@@ -102,11 +103,7 @@ module Fluent
|
|
102
103
|
out << "#{indent}<#{@name} #{@arg}>\n"
|
103
104
|
end
|
104
105
|
each_pair { |k, v|
|
105
|
-
|
106
|
-
out << "#{nindent}#{k} #{Element.unescape_parameter(v)}\n"
|
107
|
-
else
|
108
|
-
out << "#{nindent}#{k} #{v}\n"
|
109
|
-
end
|
106
|
+
out << "#{nindent}#{k} #{v}\n"
|
110
107
|
}
|
111
108
|
@elements.each { |e|
|
112
109
|
out << e.to_s(nest + 1)
|
@@ -51,7 +51,7 @@ module Fluent
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def parse_literal(string_boundary_charset = LINE_END)
|
54
|
-
|
54
|
+
spacing_without_comment
|
55
55
|
|
56
56
|
value = if skip(/\[/)
|
57
57
|
scan_json(true)
|
@@ -65,13 +65,15 @@ module Fluent
|
|
65
65
|
|
66
66
|
def scan_string(string_boundary_charset = LINE_END)
|
67
67
|
if skip(/\"/)
|
68
|
-
return
|
68
|
+
return scan_double_quoted_string
|
69
|
+
elsif skip(/\'/)
|
70
|
+
return scan_single_quoted_string
|
69
71
|
else
|
70
72
|
return scan_nonquoted_string(string_boundary_charset)
|
71
73
|
end
|
72
74
|
end
|
73
75
|
|
74
|
-
def
|
76
|
+
def scan_double_quoted_string
|
75
77
|
string = []
|
76
78
|
while true
|
77
79
|
if skip(/\"/)
|
@@ -84,7 +86,24 @@ module Fluent
|
|
84
86
|
elsif s = scan(/./)
|
85
87
|
string << s
|
86
88
|
else
|
87
|
-
parse_error! "unexpected end of file in a quoted string"
|
89
|
+
parse_error! "unexpected end of file in a double quoted string"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def scan_single_quoted_string
|
95
|
+
string = []
|
96
|
+
while true
|
97
|
+
if skip(/\'/)
|
98
|
+
return string.join
|
99
|
+
elsif s = scan(/\\'/)
|
100
|
+
string << "'"
|
101
|
+
elsif s = scan(/\\\\/)
|
102
|
+
string << "\\"
|
103
|
+
elsif s = scan(/./)
|
104
|
+
string << s
|
105
|
+
else
|
106
|
+
parse_error! "unexpected end of file in a signle quoted string"
|
88
107
|
end
|
89
108
|
end
|
90
109
|
end
|
@@ -94,8 +113,8 @@ module Fluent
|
|
94
113
|
|
95
114
|
string = []
|
96
115
|
while true
|
97
|
-
if s = scan(
|
98
|
-
string <<
|
116
|
+
if s = scan(/\#/)
|
117
|
+
string << '#'
|
99
118
|
elsif s = scan(charset)
|
100
119
|
string << s
|
101
120
|
else
|
@@ -214,7 +233,7 @@ module Fluent
|
|
214
233
|
end
|
215
234
|
|
216
235
|
unless result
|
217
|
-
parse_error! "got incomplete #{is_array ? 'array' : 'hash'} configuration"
|
236
|
+
parse_error! "got incomplete JSON #{is_array ? 'array' : 'hash'} configuration"
|
218
237
|
end
|
219
238
|
|
220
239
|
JSON.dump(result)
|
@@ -50,6 +50,8 @@ module Fluent
|
|
50
50
|
return root
|
51
51
|
end
|
52
52
|
|
53
|
+
ELEM_SYMBOLS = ['match', 'source', 'filter', 'system']
|
54
|
+
|
53
55
|
def parse_element(root_element, elem_name, attrs = {}, elems = [])
|
54
56
|
while true
|
55
57
|
spacing
|
@@ -100,7 +102,7 @@ module Fluent
|
|
100
102
|
|
101
103
|
else
|
102
104
|
k = scan_string(SPACING)
|
103
|
-
|
105
|
+
spacing_without_comment
|
104
106
|
if prev_match.include?("\n") # support 'tag_mapped' like "without value" configuration
|
105
107
|
attrs[k] = ""
|
106
108
|
else
|
@@ -114,7 +116,12 @@ module Fluent
|
|
114
116
|
attrs[k] = v
|
115
117
|
else
|
116
118
|
if k.start_with?('@')
|
117
|
-
|
119
|
+
if root_element || ELEM_SYMBOLS.include?(elem_name)
|
120
|
+
parse_error! "'@' is the system reserved prefix. Don't use '@' prefix parameter in the configuration: #{k}"
|
121
|
+
else
|
122
|
+
# TODO: This is for backward compatibility. It will throw an error in the future.
|
123
|
+
$log.warn "'@' is the system reserved prefix. It works in the nested configuration for now but it will be rejected: #{k}"
|
124
|
+
end
|
118
125
|
end
|
119
126
|
|
120
127
|
v = parse_literal
|
data/lib/fluent/formatter.rb
CHANGED
@@ -27,6 +27,7 @@ module Fluent
|
|
27
27
|
config_param :include_tag_key, :bool, :default => false
|
28
28
|
config_param :tag_key, :string, :default => 'tag'
|
29
29
|
config_param :localtime, :bool, :default => true
|
30
|
+
config_param :timezone, :string, :default => nil
|
30
31
|
}
|
31
32
|
end
|
32
33
|
|
@@ -36,7 +37,7 @@ module Fluent
|
|
36
37
|
if conf['utc']
|
37
38
|
@localtime = false
|
38
39
|
end
|
39
|
-
@timef = TimeFormatter.new(@time_format, @localtime)
|
40
|
+
@timef = TimeFormatter.new(@time_format, @localtime, @timezone)
|
40
41
|
end
|
41
42
|
|
42
43
|
def filter_record(tag, time, record)
|
data/lib/fluent/mixin.rb
CHANGED
@@ -16,12 +16,21 @@
|
|
16
16
|
|
17
17
|
module Fluent
|
18
18
|
class TimeFormatter
|
19
|
-
|
19
|
+
require 'fluent/timezone'
|
20
|
+
|
21
|
+
def initialize(format, localtime, timezone = nil)
|
20
22
|
@tc1 = 0
|
21
23
|
@tc1_str = nil
|
22
24
|
@tc2 = 0
|
23
25
|
@tc2_str = nil
|
24
26
|
|
27
|
+
if formatter = Fluent::Timezone.formatter(timezone, format)
|
28
|
+
define_singleton_method(:format_nocache) {|time|
|
29
|
+
formatter.call(time)
|
30
|
+
}
|
31
|
+
return
|
32
|
+
end
|
33
|
+
|
25
34
|
if format
|
26
35
|
if localtime
|
27
36
|
define_singleton_method(:format_nocache) {|time|
|
@@ -112,15 +121,16 @@ module Fluent
|
|
112
121
|
end
|
113
122
|
|
114
123
|
module SetTimeKeyMixin
|
124
|
+
require 'fluent/timezone'
|
115
125
|
include RecordFilterMixin
|
116
126
|
|
117
|
-
attr_accessor :include_time_key, :time_key, :localtime
|
127
|
+
attr_accessor :include_time_key, :time_key, :localtime, :timezone
|
118
128
|
|
119
129
|
def configure(conf)
|
120
|
-
super
|
121
|
-
|
122
130
|
@include_time_key = false
|
123
131
|
|
132
|
+
super
|
133
|
+
|
124
134
|
if s = conf['include_time_key']
|
125
135
|
include_time_key = Config.bool_value(s)
|
126
136
|
raise ConfigError, "Invalid boolean expression '#{s}' for include_time_key parameter" if include_time_key.nil?
|
@@ -138,7 +148,12 @@ module Fluent
|
|
138
148
|
@localtime = false
|
139
149
|
end
|
140
150
|
|
141
|
-
|
151
|
+
if conf['timezone']
|
152
|
+
@timezone = conf['timezone']
|
153
|
+
Fluent::Timezone.validate!(@timezone)
|
154
|
+
end
|
155
|
+
|
156
|
+
@timef = TimeFormatter.new(@time_format, @localtime, @timezone)
|
142
157
|
end
|
143
158
|
end
|
144
159
|
|
@@ -155,10 +170,10 @@ module Fluent
|
|
155
170
|
attr_accessor :include_tag_key, :tag_key
|
156
171
|
|
157
172
|
def configure(conf)
|
158
|
-
super
|
159
|
-
|
160
173
|
@include_tag_key = false
|
161
174
|
|
175
|
+
super
|
176
|
+
|
162
177
|
if s = conf['include_tag_key']
|
163
178
|
include_tag_key = Config.bool_value(s)
|
164
179
|
raise ConfigError, "Invalid boolean expression '#{s}' for include_tag_key parameter" if include_tag_key.nil?
|
data/lib/fluent/output.rb
CHANGED
@@ -322,7 +322,7 @@ module Fluent
|
|
322
322
|
@num_errors = 0
|
323
323
|
# Note: don't notify to other threads to prevent
|
324
324
|
# burst to recovered server
|
325
|
-
$log.warn "retry succeeded.", :
|
325
|
+
$log.warn "retry succeeded.", :plugin_id=>plugin_id
|
326
326
|
end
|
327
327
|
|
328
328
|
if has_next
|
@@ -347,20 +347,20 @@ module Fluent
|
|
347
347
|
end
|
348
348
|
|
349
349
|
if @disable_retry_limit || error_count < @retry_limit
|
350
|
-
$log.warn "temporarily failed to flush the buffer.", :next_retry=>Time.at(@next_retry_time), :error_class=>e.class.to_s, :error=>e.to_s, :
|
350
|
+
$log.warn "temporarily failed to flush the buffer.", :next_retry=>Time.at(@next_retry_time), :error_class=>e.class.to_s, :error=>e.to_s, :plugin_id=>plugin_id
|
351
351
|
$log.warn_backtrace e.backtrace
|
352
352
|
|
353
353
|
elsif @secondary
|
354
354
|
if error_count == @retry_limit
|
355
|
-
$log.warn "failed to flush the buffer.", :error_class=>e.class.to_s, :error=>e.to_s, :
|
355
|
+
$log.warn "failed to flush the buffer.", :error_class=>e.class.to_s, :error=>e.to_s, :plugin_id=>plugin_id
|
356
356
|
$log.warn "retry count exceededs limit. falling back to secondary output."
|
357
357
|
$log.warn_backtrace e.backtrace
|
358
358
|
retry # retry immediately
|
359
359
|
elsif error_count <= @retry_limit + @secondary_limit
|
360
|
-
$log.warn "failed to flush the buffer, next retry will be with secondary output.", :next_retry=>Time.at(@next_retry_time), :error_class=>e.class.to_s, :error=>e.to_s, :
|
360
|
+
$log.warn "failed to flush the buffer, next retry will be with secondary output.", :next_retry=>Time.at(@next_retry_time), :error_class=>e.class.to_s, :error=>e.to_s, :plugin_id=>plugin_id
|
361
361
|
$log.warn_backtrace e.backtrace
|
362
362
|
else
|
363
|
-
$log.warn "failed to flush the buffer.", :error_class=>e.class, :error=>e.to_s, :
|
363
|
+
$log.warn "failed to flush the buffer.", :error_class=>e.class, :error=>e.to_s, :plugin_id=>plugin_id
|
364
364
|
$log.warn "secondary retry count exceededs limit."
|
365
365
|
$log.warn_backtrace e.backtrace
|
366
366
|
write_abort
|
@@ -368,7 +368,7 @@ module Fluent
|
|
368
368
|
end
|
369
369
|
|
370
370
|
else
|
371
|
-
$log.warn "failed to flush the buffer.", :error_class=>e.class.to_s, :error=>e.to_s, :
|
371
|
+
$log.warn "failed to flush the buffer.", :error_class=>e.class.to_s, :error=>e.to_s, :plugin_id=>plugin_id
|
372
372
|
$log.warn "retry count exceededs limit."
|
373
373
|
$log.warn_backtrace e.backtrace
|
374
374
|
write_abort
|
@@ -459,6 +459,8 @@ module Fluent
|
|
459
459
|
|
460
460
|
|
461
461
|
class TimeSlicedOutput < BufferedOutput
|
462
|
+
require 'fluent/timezone'
|
463
|
+
|
462
464
|
def initialize
|
463
465
|
super
|
464
466
|
@localtime = true
|
@@ -467,6 +469,7 @@ module Fluent
|
|
467
469
|
|
468
470
|
config_param :time_slice_format, :string, :default => '%Y%m%d'
|
469
471
|
config_param :time_slice_wait, :time, :default => 10*60
|
472
|
+
config_param :timezone, :string, :default => nil
|
470
473
|
config_set_default :buffer_type, 'file' # overwrite default buffer_type
|
471
474
|
config_set_default :buffer_chunk_limit, 256*1024*1024 # overwrite default buffer_chunk_limit
|
472
475
|
config_set_default :flush_interval, nil
|
@@ -476,14 +479,20 @@ module Fluent
|
|
476
479
|
def configure(conf)
|
477
480
|
super
|
478
481
|
|
479
|
-
# TODO timezone
|
480
482
|
if conf['utc']
|
481
483
|
@localtime = false
|
482
484
|
elsif conf['localtime']
|
483
485
|
@localtime = true
|
484
486
|
end
|
485
487
|
|
486
|
-
if
|
488
|
+
if conf['timezone']
|
489
|
+
@timezone = conf['timezone']
|
490
|
+
Fluent::Timezone.validate!(@timezone)
|
491
|
+
end
|
492
|
+
|
493
|
+
if @timezone
|
494
|
+
@time_slicer = Timezone.formatter(@timezone, @time_slice_format)
|
495
|
+
elsif @localtime
|
487
496
|
@time_slicer = Proc.new {|time|
|
488
497
|
Time.at(time).strftime(@time_slice_format)
|
489
498
|
}
|
data/lib/fluent/parser.rb
CHANGED
@@ -18,6 +18,9 @@ module Fluent
|
|
18
18
|
require 'fluent/registry'
|
19
19
|
|
20
20
|
class TextParser
|
21
|
+
class ParserError < StandardError
|
22
|
+
end
|
23
|
+
|
21
24
|
class TimeParser
|
22
25
|
def initialize(time_format)
|
23
26
|
@cache1_key = nil
|
@@ -34,7 +37,7 @@ module Fluent
|
|
34
37
|
|
35
38
|
def parse(value)
|
36
39
|
unless value.is_a?(String)
|
37
|
-
raise
|
40
|
+
raise ParserError, "value must be string: #{value}"
|
38
41
|
end
|
39
42
|
|
40
43
|
if @cache1_key == value
|
@@ -42,7 +45,11 @@ module Fluent
|
|
42
45
|
elsif @cache2_key == value
|
43
46
|
return @cache2_time
|
44
47
|
else
|
45
|
-
|
48
|
+
begin
|
49
|
+
time = @parser.call(value).to_i
|
50
|
+
rescue => e
|
51
|
+
raise ParserError, "invalid time format: value = #{value}, error_class = #{e.class.name}, error = #{e.message}"
|
52
|
+
end
|
46
53
|
@cache1_key = @cache2_key
|
47
54
|
@cache1_time = @cache2_time
|
48
55
|
@cache2_key = value
|
@@ -224,7 +231,11 @@ module Fluent
|
|
224
231
|
if @time_format
|
225
232
|
time = @mutex.synchronize { @time_parser.parse(value) }
|
226
233
|
else
|
227
|
-
|
234
|
+
begin
|
235
|
+
time = value.to_i
|
236
|
+
rescue => e
|
237
|
+
raise ParserError, "invalid time value: value = #{value}, error_class = #{e.class.name}, error = #{e.message}"
|
238
|
+
end
|
228
239
|
end
|
229
240
|
else
|
230
241
|
if @estimate_current_event
|
@@ -26,7 +26,7 @@ module Fluent
|
|
26
26
|
FileUtils.ln_sf(@path, symlink_path) if symlink_path
|
27
27
|
end
|
28
28
|
|
29
|
-
attr_reader :unique_id
|
29
|
+
attr_reader :unique_id, :path
|
30
30
|
|
31
31
|
def <<(data)
|
32
32
|
@file.write(data)
|
@@ -64,8 +64,6 @@ module Fluent
|
|
64
64
|
yield @file
|
65
65
|
end
|
66
66
|
|
67
|
-
attr_reader :path
|
68
|
-
|
69
67
|
def mv(path)
|
70
68
|
File.rename(@path, path)
|
71
69
|
@path = path
|
@@ -80,10 +78,15 @@ module Fluent
|
|
80
78
|
def initialize
|
81
79
|
require 'uri'
|
82
80
|
super
|
81
|
+
|
82
|
+
@uri_parser = URI::Parser.new
|
83
83
|
end
|
84
84
|
|
85
85
|
config_param :buffer_path, :string
|
86
86
|
|
87
|
+
# 'symlink_path' is currently only for out_file.
|
88
|
+
# That is the reason why this is not config_param, but attr_accessor.
|
89
|
+
# See: https://github.com/fluent/fluentd/pull/181
|
87
90
|
attr_accessor :symlink_path
|
88
91
|
|
89
92
|
def configure(conf)
|
@@ -96,10 +99,10 @@ module Fluent
|
|
96
99
|
end
|
97
100
|
|
98
101
|
if pos = @buffer_path.index('*')
|
99
|
-
@buffer_path_prefix = @buffer_path[0,pos]
|
100
|
-
@buffer_path_suffix = @buffer_path[pos+1..-1]
|
102
|
+
@buffer_path_prefix = @buffer_path[0, pos]
|
103
|
+
@buffer_path_suffix = @buffer_path[(pos + 1)..-1]
|
101
104
|
else
|
102
|
-
@buffer_path_prefix = @buffer_path+"."
|
105
|
+
@buffer_path_prefix = @buffer_path + "."
|
103
106
|
@buffer_path_suffix = ".log"
|
104
107
|
end
|
105
108
|
|
@@ -111,11 +114,13 @@ module Fluent
|
|
111
114
|
end
|
112
115
|
|
113
116
|
def start
|
114
|
-
FileUtils.mkdir_p File.dirname(@buffer_path_prefix+"path")
|
117
|
+
FileUtils.mkdir_p File.dirname(@buffer_path_prefix + "path")
|
115
118
|
super
|
116
119
|
end
|
117
120
|
|
118
|
-
|
121
|
+
# Dots are separator for many cases:
|
122
|
+
# we should have to escape dots in keys...
|
123
|
+
PATH_MATCH = /^([-_.%0-9a-zA-Z]*)\.(b|q)([0-9a-fA-F]{1,32})$/
|
119
124
|
|
120
125
|
def new_chunk(key)
|
121
126
|
encoded_key = encode_key(key)
|
@@ -129,8 +134,8 @@ module Fluent
|
|
129
134
|
queues = []
|
130
135
|
|
131
136
|
Dir.glob("#{@buffer_path_prefix}*#{@buffer_path_suffix}") {|path|
|
132
|
-
|
133
|
-
if m = PATH_MATCH.match(
|
137
|
+
identifier_part = chunk_identifier_in_path(path)
|
138
|
+
if m = PATH_MATCH.match(identifier_part)
|
134
139
|
key = decode_key(m[1])
|
135
140
|
bq = m[2]
|
136
141
|
tsuffix = m[3]
|
@@ -163,11 +168,18 @@ module Fluent
|
|
163
168
|
return queue, map
|
164
169
|
end
|
165
170
|
|
171
|
+
def chunk_identifier_in_path(path)
|
172
|
+
pos_after_prefix = @buffer_path_prefix.length
|
173
|
+
pos_before_suffix = @buffer_path_suffix.length + 1 # from tail of path
|
174
|
+
|
175
|
+
path.slice(pos_after_prefix..-pos_before_suffix)
|
176
|
+
end
|
177
|
+
|
166
178
|
def enqueue(chunk)
|
167
179
|
path = chunk.path
|
168
|
-
|
180
|
+
identifier_part = chunk_identifier_in_path(path)
|
169
181
|
|
170
|
-
m = PATH_MATCH.match(
|
182
|
+
m = PATH_MATCH.match(identifier_part)
|
171
183
|
encoded_key = m ? m[1] : ""
|
172
184
|
tsuffix = m[3]
|
173
185
|
npath = "#{@buffer_path_prefix}#{encoded_key}.q#{tsuffix}#{@buffer_path_suffix}"
|
@@ -189,23 +201,26 @@ module Fluent
|
|
189
201
|
|
190
202
|
protected
|
191
203
|
|
204
|
+
# Dots are separator for many cases:
|
205
|
+
# we should have to escape dots in keys...
|
192
206
|
def encode_key(key)
|
193
|
-
|
207
|
+
@uri_parser.escape(key, /[^-_.a-zA-Z0-9]/n) # //n switch means explicit 'ASCII-8BIT' pattern
|
194
208
|
end
|
195
209
|
|
196
210
|
def decode_key(encoded_key)
|
197
|
-
|
211
|
+
@uri_parser.unescape(encoded_key)
|
198
212
|
end
|
199
213
|
|
200
214
|
def make_path(encoded_key, bq)
|
201
215
|
now = Time.now.utc
|
202
|
-
timestamp = ((now.to_i*1000*1000+now.usec) << 12 | rand(0xfff))
|
216
|
+
timestamp = ((now.to_i * 1000 * 1000 + now.usec) << 12 | rand(0xfff))
|
203
217
|
tsuffix = timestamp.to_s(16)
|
204
218
|
path = "#{@buffer_path_prefix}#{encoded_key}.#{bq}#{tsuffix}#{@buffer_path_suffix}"
|
205
219
|
return path, tsuffix
|
206
220
|
end
|
207
221
|
|
208
222
|
def tsuffix_to_unique_id(tsuffix)
|
223
|
+
# why *2 ? frsyuki said that I forgot why completely.
|
209
224
|
tsuffix.scan(/../).map {|x| x.to_i(16) }.pack('C*') * 2
|
210
225
|
end
|
211
226
|
end
|