fluentd 1.6.3 → 1.7.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/.drone.yml +35 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +2 -0
- data/CHANGELOG.md +58 -0
- data/README.md +5 -1
- data/fluentd.gemspec +1 -1
- data/lib/fluent/clock.rb +4 -0
- data/lib/fluent/compat/output.rb +3 -3
- data/lib/fluent/compat/socket_util.rb +1 -1
- data/lib/fluent/config/element.rb +3 -3
- data/lib/fluent/config/literal_parser.rb +1 -1
- data/lib/fluent/config/section.rb +4 -1
- data/lib/fluent/error.rb +4 -0
- data/lib/fluent/event.rb +28 -24
- data/lib/fluent/event_router.rb +2 -1
- data/lib/fluent/log.rb +1 -1
- data/lib/fluent/msgpack_factory.rb +8 -0
- data/lib/fluent/plugin/bare_output.rb +4 -4
- data/lib/fluent/plugin/buf_file_single.rb +211 -0
- data/lib/fluent/plugin/buffer.rb +62 -63
- data/lib/fluent/plugin/buffer/chunk.rb +21 -3
- data/lib/fluent/plugin/buffer/file_chunk.rb +37 -12
- data/lib/fluent/plugin/buffer/file_single_chunk.rb +314 -0
- data/lib/fluent/plugin/buffer/memory_chunk.rb +2 -1
- data/lib/fluent/plugin/compressable.rb +10 -6
- data/lib/fluent/plugin/filter_grep.rb +2 -2
- data/lib/fluent/plugin/formatter_csv.rb +10 -6
- data/lib/fluent/plugin/in_syslog.rb +10 -3
- data/lib/fluent/plugin/in_tail.rb +7 -2
- data/lib/fluent/plugin/in_tcp.rb +34 -7
- data/lib/fluent/plugin/multi_output.rb +4 -4
- data/lib/fluent/plugin/out_exec_filter.rb +1 -0
- data/lib/fluent/plugin/out_file.rb +13 -3
- data/lib/fluent/plugin/out_forward.rb +126 -588
- data/lib/fluent/plugin/out_forward/ack_handler.rb +161 -0
- data/lib/fluent/plugin/out_forward/connection_manager.rb +113 -0
- data/lib/fluent/plugin/out_forward/error.rb +28 -0
- data/lib/fluent/plugin/out_forward/failure_detector.rb +84 -0
- data/lib/fluent/plugin/out_forward/handshake_protocol.rb +121 -0
- data/lib/fluent/plugin/out_forward/load_balancer.rb +111 -0
- data/lib/fluent/plugin/out_forward/socket_cache.rb +138 -0
- data/lib/fluent/plugin/out_http.rb +231 -0
- data/lib/fluent/plugin/output.rb +29 -35
- data/lib/fluent/plugin/parser.rb +77 -0
- data/lib/fluent/plugin/parser_csv.rb +75 -0
- data/lib/fluent/plugin_helper/server.rb +1 -1
- data/lib/fluent/plugin_helper/thread.rb +1 -0
- data/lib/fluent/root_agent.rb +1 -1
- data/lib/fluent/time.rb +4 -2
- data/lib/fluent/timezone.rb +21 -7
- data/lib/fluent/version.rb +1 -1
- data/test/command/test_fluentd.rb +1 -1
- data/test/command/test_plugin_generator.rb +18 -2
- data/test/config/test_configurable.rb +78 -40
- data/test/counter/test_store.rb +1 -1
- data/test/helper.rb +1 -0
- data/test/helpers/process_extenstion.rb +33 -0
- data/test/plugin/out_forward/test_ack_handler.rb +101 -0
- data/test/plugin/out_forward/test_connection_manager.rb +145 -0
- data/test/plugin/out_forward/test_handshake_protocol.rb +103 -0
- data/test/plugin/out_forward/test_load_balancer.rb +60 -0
- data/test/plugin/out_forward/test_socket_cache.rb +139 -0
- data/test/plugin/test_buf_file.rb +118 -2
- data/test/plugin/test_buf_file_single.rb +734 -0
- data/test/plugin/test_buffer.rb +4 -48
- data/test/plugin/test_buffer_file_chunk.rb +19 -1
- data/test/plugin/test_buffer_file_single_chunk.rb +620 -0
- data/test/plugin/test_formatter_csv.rb +16 -0
- data/test/plugin/test_in_syslog.rb +56 -6
- data/test/plugin/test_in_tail.rb +1 -1
- data/test/plugin/test_in_tcp.rb +25 -0
- data/test/plugin/test_out_forward.rb +75 -201
- data/test/plugin/test_out_http.rb +352 -0
- data/test/plugin/test_output_as_buffered.rb +27 -24
- data/test/plugin/test_parser.rb +40 -0
- data/test/plugin/test_parser_csv.rb +83 -0
- data/test/plugin_helper/test_record_accessor.rb +1 -1
- data/test/test_time_formatter.rb +140 -121
- metadata +33 -4
@@ -40,7 +40,7 @@ module Fluent
|
|
40
40
|
|
41
41
|
def initialize
|
42
42
|
super
|
43
|
-
@
|
43
|
+
@counter_mutex = Mutex.new
|
44
44
|
# TODO: well organized counters
|
45
45
|
@num_errors = 0
|
46
46
|
@emit_count = 0
|
@@ -48,12 +48,12 @@ module Fluent
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def emit_sync(tag, es)
|
51
|
-
@
|
51
|
+
@counter_mutex.synchronize{ @emit_count += 1 }
|
52
52
|
begin
|
53
53
|
process(tag, es)
|
54
|
-
@
|
54
|
+
@counter_mutex.synchronize{ @emit_records += es.size }
|
55
55
|
rescue
|
56
|
-
@
|
56
|
+
@counter_mutex.synchronize{ @num_errors += 1 }
|
57
57
|
raise
|
58
58
|
end
|
59
59
|
end
|
@@ -0,0 +1,211 @@
|
|
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
|
+
require 'fileutils'
|
18
|
+
|
19
|
+
require 'fluent/plugin/buffer'
|
20
|
+
require 'fluent/plugin/buffer/file_single_chunk'
|
21
|
+
require 'fluent/system_config'
|
22
|
+
|
23
|
+
module Fluent
|
24
|
+
module Plugin
|
25
|
+
class FileSingleBuffer < Fluent::Plugin::Buffer
|
26
|
+
Plugin.register_buffer('file_single', self)
|
27
|
+
|
28
|
+
include SystemConfig::Mixin
|
29
|
+
|
30
|
+
DEFAULT_CHUNK_LIMIT_SIZE = 256 * 1024 * 1024 # 256MB
|
31
|
+
DEFAULT_TOTAL_LIMIT_SIZE = 64 * 1024 * 1024 * 1024 # 64GB
|
32
|
+
|
33
|
+
PATH_SUFFIX = ".#{Fluent::Plugin::Buffer::FileSingleChunk::PATH_EXT}"
|
34
|
+
DIR_PERMISSION = 0755
|
35
|
+
|
36
|
+
desc 'The path where buffer chunks are stored.'
|
37
|
+
config_param :path, :string, default: nil
|
38
|
+
desc 'Calculate the number of record in chunk during resume'
|
39
|
+
config_param :calc_num_records, :bool, default: true
|
40
|
+
desc 'The format of chunk. This is used to calculate the number of record'
|
41
|
+
config_param :chunk_format, :enum, list: [:msgpack, :text, :auto], default: :auto
|
42
|
+
|
43
|
+
config_set_default :chunk_limit_size, DEFAULT_CHUNK_LIMIT_SIZE
|
44
|
+
config_set_default :total_limit_size, DEFAULT_TOTAL_LIMIT_SIZE
|
45
|
+
|
46
|
+
desc 'The permission of chunk file. If no specified, <system> setting or 0644 is used'
|
47
|
+
config_param :file_permission, :string, default: nil
|
48
|
+
desc 'The permission of chunk directory. If no specified, <system> setting or 0755 is used'
|
49
|
+
config_param :dir_permission, :string, default: nil
|
50
|
+
|
51
|
+
@@buffer_paths = {}
|
52
|
+
|
53
|
+
def initialize
|
54
|
+
super
|
55
|
+
|
56
|
+
@multi_workers_available = false
|
57
|
+
@additional_resume_path = nil
|
58
|
+
end
|
59
|
+
|
60
|
+
def configure(conf)
|
61
|
+
super
|
62
|
+
|
63
|
+
if @chunk_format == :auto
|
64
|
+
@chunk_format = owner.formatted_to_msgpack_binary? ? :msgpack : :text
|
65
|
+
end
|
66
|
+
|
67
|
+
@key_in_path = nil
|
68
|
+
if owner.chunk_keys.empty?
|
69
|
+
log.debug "use event tag for buffer key"
|
70
|
+
else
|
71
|
+
if owner.chunk_key_tag
|
72
|
+
raise Fluent::ConfigError, "chunk keys must be tag or one field"
|
73
|
+
elsif owner.chunk_keys.size > 1
|
74
|
+
raise Fluent::ConfigError, "2 or more chunk keys is not allowed"
|
75
|
+
else
|
76
|
+
@key_in_path = owner.chunk_keys.first.to_sym
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
multi_workers_configured = owner.system_config.workers > 1
|
81
|
+
using_plugin_root_dir = false
|
82
|
+
unless @path
|
83
|
+
if root_dir = owner.plugin_root_dir
|
84
|
+
@path = File.join(root_dir, 'buffer')
|
85
|
+
using_plugin_root_dir = true # plugin_root_dir path contains worker id
|
86
|
+
else
|
87
|
+
raise Fluent::ConfigError, "buffer path is not configured. specify 'path' in <buffer>"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
type_of_owner = Plugin.lookup_type_from_class(@_owner.class)
|
92
|
+
if @@buffer_paths.has_key?(@path) && !called_in_test?
|
93
|
+
type_using_this_path = @@buffer_paths[@path]
|
94
|
+
raise Fluent::ConfigError, "Other '#{type_using_this_path}' plugin already uses same buffer path: type = #{type_of_owner}, buffer path = #{@path}"
|
95
|
+
end
|
96
|
+
|
97
|
+
@@buffer_paths[@path] = type_of_owner
|
98
|
+
|
99
|
+
specified_directory_exists = File.exist?(@path) && File.directory?(@path)
|
100
|
+
unexisting_path_for_directory = !File.exist?(@path) && !@path.include?('.*')
|
101
|
+
|
102
|
+
if specified_directory_exists || unexisting_path_for_directory # directory
|
103
|
+
if using_plugin_root_dir || !multi_workers_configured
|
104
|
+
@path = File.join(@path, "fsb.*#{PATH_SUFFIX}")
|
105
|
+
else
|
106
|
+
@path = File.join(@path, "worker#{fluentd_worker_id}", "fsb.*#{PATH_SUFFIX}")
|
107
|
+
if fluentd_worker_id == 0
|
108
|
+
# worker 0 always checks unflushed buffer chunks to be resumed (might be created while non-multi-worker configuration)
|
109
|
+
@additional_resume_path = File.join(File.expand_path("../../", @path), "fsb.*#{PATH_SUFFIX}")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
@multi_workers_available = true
|
113
|
+
else # specified path is file path
|
114
|
+
if File.basename(@path).include?('.*.')
|
115
|
+
new_path = File.join(File.dirname(@path), "fsb.*#{PATH_SUFFIX}")
|
116
|
+
log.warn "file_single doesn't allow user specified 'prefix.*.suffix' style path. Use '#{new_path}' for file instead: #{@path}"
|
117
|
+
@path = new_path
|
118
|
+
elsif File.basename(@path).end_with?('.*')
|
119
|
+
@path = @path + PATH_SUFFIX
|
120
|
+
else
|
121
|
+
# existing file will be ignored
|
122
|
+
@path = @path + ".*#{PATH_SUFFIX}"
|
123
|
+
end
|
124
|
+
@multi_workers_available = false
|
125
|
+
end
|
126
|
+
|
127
|
+
@dir_permission = if @dir_permission
|
128
|
+
@dir_permission.to_i(8)
|
129
|
+
else
|
130
|
+
system_config.dir_permission || DIR_PERMISSION
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# This method is called only when multi worker is configured
|
135
|
+
def multi_workers_ready?
|
136
|
+
unless @multi_workers_available
|
137
|
+
log.error "file_single buffer with multi workers should be configured to use directory 'path', or system root_dir and plugin id"
|
138
|
+
end
|
139
|
+
@multi_workers_available
|
140
|
+
end
|
141
|
+
|
142
|
+
def start
|
143
|
+
FileUtils.mkdir_p(File.dirname(@path), mode: @dir_permission)
|
144
|
+
|
145
|
+
super
|
146
|
+
end
|
147
|
+
|
148
|
+
def persistent?
|
149
|
+
true
|
150
|
+
end
|
151
|
+
|
152
|
+
def resume
|
153
|
+
stage = {}
|
154
|
+
queue = []
|
155
|
+
|
156
|
+
patterns = [@path]
|
157
|
+
patterns.unshift @additional_resume_path if @additional_resume_path
|
158
|
+
Dir.glob(patterns) do |path|
|
159
|
+
next unless File.file?(path)
|
160
|
+
|
161
|
+
log.debug { "restoring buffer file: path = #{path}" }
|
162
|
+
|
163
|
+
m = new_metadata() # this metadata will be updated in FileSingleChunk.new
|
164
|
+
mode = Fluent::Plugin::Buffer::FileSingleChunk.assume_chunk_state(path)
|
165
|
+
if mode == :unknown
|
166
|
+
log.debug "unknown state chunk found", path: path
|
167
|
+
next
|
168
|
+
end
|
169
|
+
|
170
|
+
begin
|
171
|
+
chunk = Fluent::Plugin::Buffer::FileSingleChunk.new(m, path, mode, @key_in_path)
|
172
|
+
chunk.restore_size(@chunk_format) if @calc_num_records
|
173
|
+
rescue Fluent::Plugin::Buffer::FileSingleChunk::FileChunkError => e
|
174
|
+
handle_broken_files(path, mode, e)
|
175
|
+
next
|
176
|
+
end
|
177
|
+
|
178
|
+
case chunk.state
|
179
|
+
when :staged
|
180
|
+
stage[chunk.metadata] = chunk
|
181
|
+
when :queued
|
182
|
+
queue << chunk
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
queue.sort_by!(&:modified_at)
|
187
|
+
|
188
|
+
return stage, queue
|
189
|
+
end
|
190
|
+
|
191
|
+
def generate_chunk(metadata)
|
192
|
+
# FileChunk generates real path with unique_id
|
193
|
+
if @file_permission
|
194
|
+
chunk = Fluent::Plugin::Buffer::FileSingleChunk.new(metadata, @path, :create, @key_in_path, perm: @file_permission, compress: @compress)
|
195
|
+
else
|
196
|
+
chunk = Fluent::Plugin::Buffer::FileSingleChunk.new(metadata, @path, :create, @key_in_path, compress: @compress)
|
197
|
+
end
|
198
|
+
|
199
|
+
log.debug "Created new chunk", chunk_id: dump_unique_id_hex(chunk.unique_id), metadata: metadata
|
200
|
+
|
201
|
+
chunk
|
202
|
+
end
|
203
|
+
|
204
|
+
def handle_broken_files(path, mode, e)
|
205
|
+
log.error "found broken chunk file during resume. Delete corresponding files:", path: path, mode: mode, err_msg: e.message
|
206
|
+
# After support 'backup_dir' feature, these files are moved to backup_dir instead of unlink.
|
207
|
+
File.unlink(path) rescue nil
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
data/lib/fluent/plugin/buffer.rb
CHANGED
@@ -133,6 +133,15 @@ module Fluent
|
|
133
133
|
cmp_variables(variables, variables2)
|
134
134
|
end
|
135
135
|
end
|
136
|
+
|
137
|
+
# This is an optimization code. Current Struct's implementation is comparing all data.
|
138
|
+
# https://github.com/ruby/ruby/blob/0623e2b7cc621b1733a760b72af246b06c30cf96/struct.c#L1200-L1203
|
139
|
+
# Actually this overhead is very small but this class is generated *per chunk* (and used in hash object).
|
140
|
+
# This means that this class is one of the most called object in Fluentd.
|
141
|
+
# See https://github.com/fluent/fluentd/pull/2560
|
142
|
+
def hash
|
143
|
+
timekey.object_id
|
144
|
+
end
|
136
145
|
end
|
137
146
|
|
138
147
|
# for tests
|
@@ -155,7 +164,7 @@ module Fluent
|
|
155
164
|
|
156
165
|
@stage_size = @queue_size = 0
|
157
166
|
@timekeys = Hash.new(0)
|
158
|
-
@
|
167
|
+
@mutex = Mutex.new
|
159
168
|
end
|
160
169
|
|
161
170
|
def persistent?
|
@@ -175,16 +184,18 @@ module Fluent
|
|
175
184
|
|
176
185
|
@stage, @queue = resume
|
177
186
|
@stage.each_pair do |metadata, chunk|
|
178
|
-
@metadata_list << metadata unless @metadata_list.include?(metadata)
|
179
187
|
@stage_size += chunk.bytesize
|
180
|
-
|
188
|
+
if chunk.metadata && chunk.metadata.timekey
|
189
|
+
add_timekey(metadata.timekey)
|
190
|
+
end
|
181
191
|
end
|
182
192
|
@queue.each do |chunk|
|
183
|
-
@metadata_list << chunk.metadata unless @metadata_list.include?(chunk.metadata)
|
184
193
|
@queued_num[chunk.metadata] ||= 0
|
185
194
|
@queued_num[chunk.metadata] += 1
|
186
195
|
@queue_size += chunk.bytesize
|
187
|
-
|
196
|
+
if chunk.metadata && chunk.metadata.timekey
|
197
|
+
add_timekey(chunk.metadata.timekey)
|
198
|
+
end
|
188
199
|
end
|
189
200
|
log.debug "buffer started", instance: self.object_id, stage_size: @stage_size, queue_size: @queue_size
|
190
201
|
end
|
@@ -207,7 +218,7 @@ module Fluent
|
|
207
218
|
|
208
219
|
def terminate
|
209
220
|
super
|
210
|
-
@dequeued = @stage = @queue = @queued_num =
|
221
|
+
@dequeued = @stage = @queue = @queued_num = nil
|
211
222
|
@stage_size = @queue_size = 0
|
212
223
|
@timekeys.clear
|
213
224
|
end
|
@@ -230,61 +241,17 @@ module Fluent
|
|
230
241
|
raise NotImplementedError, "Implement this method in child class"
|
231
242
|
end
|
232
243
|
|
233
|
-
def metadata_list
|
234
|
-
synchronize do
|
235
|
-
@metadata_list.dup
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
|
-
# it's too dangerous, and use it so carefully to remove metadata for tests
|
240
|
-
def metadata_list_clear!
|
241
|
-
synchronize do
|
242
|
-
@metadata_list.clear
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
244
|
def new_metadata(timekey: nil, tag: nil, variables: nil)
|
247
245
|
Metadata.new(timekey, tag, variables)
|
248
246
|
end
|
249
247
|
|
250
|
-
def add_metadata(metadata)
|
251
|
-
log.on_trace { log.trace "adding metadata", instance: self.object_id, metadata: metadata }
|
252
|
-
|
253
|
-
synchronize do
|
254
|
-
if i = @metadata_list.index(metadata)
|
255
|
-
@metadata_list[i]
|
256
|
-
else
|
257
|
-
@metadata_list << metadata
|
258
|
-
add_timekey(metadata)
|
259
|
-
metadata
|
260
|
-
end
|
261
|
-
end
|
262
|
-
end
|
263
|
-
|
264
248
|
def metadata(timekey: nil, tag: nil, variables: nil)
|
265
|
-
meta =
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
def add_timekey(metadata)
|
270
|
-
if t = metadata.timekey
|
271
|
-
@timekeys[t] += 1
|
249
|
+
meta = Metadata.new(timekey, tag, variables)
|
250
|
+
if (t = meta.timekey)
|
251
|
+
add_timekey(t)
|
272
252
|
end
|
273
|
-
|
253
|
+
meta
|
274
254
|
end
|
275
|
-
private :add_timekey
|
276
|
-
|
277
|
-
def del_timekey(metadata)
|
278
|
-
if t = metadata.timekey
|
279
|
-
if @timekeys[t] <= 1
|
280
|
-
@timekeys.delete(t)
|
281
|
-
else
|
282
|
-
@timekeys[t] -= 1
|
283
|
-
end
|
284
|
-
end
|
285
|
-
nil
|
286
|
-
end
|
287
|
-
private :del_timekey
|
288
255
|
|
289
256
|
def timekeys
|
290
257
|
@timekeys.keys
|
@@ -408,13 +375,12 @@ module Fluent
|
|
408
375
|
synchronize { @queue.reduce(0){|r, chunk| r + chunk.size } }
|
409
376
|
end
|
410
377
|
|
411
|
-
def queued?(metadata=nil)
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
!@queue.empty?
|
378
|
+
def queued?(metadata = nil, optimistic: false)
|
379
|
+
if optimistic
|
380
|
+
optimistic_queued?(metadata)
|
381
|
+
else
|
382
|
+
synchronize do
|
383
|
+
optimistic_queued?(metadata)
|
418
384
|
end
|
419
385
|
end
|
420
386
|
end
|
@@ -514,6 +480,7 @@ module Fluent
|
|
514
480
|
end
|
515
481
|
|
516
482
|
def purge_chunk(chunk_id)
|
483
|
+
metadata = nil
|
517
484
|
synchronize do
|
518
485
|
chunk = @dequeued.delete(chunk_id)
|
519
486
|
return nil unless chunk # purged by other threads
|
@@ -532,13 +499,16 @@ module Fluent
|
|
532
499
|
|
533
500
|
@dequeued_num[chunk.metadata] -= 1
|
534
501
|
if metadata && !@stage[metadata] && (!@queued_num[metadata] || @queued_num[metadata] < 1) && @dequeued_num[metadata].zero?
|
535
|
-
@metadata_list.delete(metadata)
|
536
502
|
@queued_num.delete(metadata)
|
537
503
|
@dequeued_num.delete(metadata)
|
538
|
-
del_timekey(metadata)
|
539
504
|
end
|
540
505
|
log.trace "chunk purged", instance: self.object_id, chunk_id: dump_unique_id_hex(chunk_id), metadata: metadata
|
541
506
|
end
|
507
|
+
|
508
|
+
if metadata && metadata.timekey
|
509
|
+
del_timekey(metadata.timekey)
|
510
|
+
end
|
511
|
+
|
542
512
|
nil
|
543
513
|
end
|
544
514
|
|
@@ -774,6 +744,35 @@ module Fluent
|
|
774
744
|
|
775
745
|
{ 'buffer' => stats }
|
776
746
|
end
|
747
|
+
|
748
|
+
private
|
749
|
+
|
750
|
+
def optimistic_queued?(metadata = nil)
|
751
|
+
if metadata
|
752
|
+
n = @queued_num[metadata]
|
753
|
+
n && n.nonzero?
|
754
|
+
else
|
755
|
+
!@queue.empty?
|
756
|
+
end
|
757
|
+
end
|
758
|
+
|
759
|
+
def add_timekey(t)
|
760
|
+
@mutex.synchronize do
|
761
|
+
@timekeys[t] += 1
|
762
|
+
end
|
763
|
+
nil
|
764
|
+
end
|
765
|
+
|
766
|
+
def del_timekey(t)
|
767
|
+
@mutex.synchronize do
|
768
|
+
if @timekeys[t] <= 1
|
769
|
+
@timekeys.delete(t)
|
770
|
+
else
|
771
|
+
@timekeys[t] -= 1
|
772
|
+
end
|
773
|
+
end
|
774
|
+
nil
|
775
|
+
end
|
777
776
|
end
|
778
777
|
end
|
779
778
|
end
|
@@ -57,13 +57,31 @@ module Fluent
|
|
57
57
|
@state = :unstaged
|
58
58
|
|
59
59
|
@size = 0
|
60
|
-
@created_at =
|
61
|
-
@modified_at =
|
60
|
+
@created_at = Fluent::Clock.real_now
|
61
|
+
@modified_at = Fluent::Clock.real_now
|
62
62
|
|
63
63
|
extend Decompressable if compress == :gzip
|
64
64
|
end
|
65
65
|
|
66
|
-
attr_reader :unique_id, :metadata, :
|
66
|
+
attr_reader :unique_id, :metadata, :state
|
67
|
+
|
68
|
+
def raw_create_at
|
69
|
+
@created_at
|
70
|
+
end
|
71
|
+
|
72
|
+
def raw_modified_at
|
73
|
+
@modified_at
|
74
|
+
end
|
75
|
+
|
76
|
+
# for compatibility
|
77
|
+
def created_at
|
78
|
+
@created_at_object ||= Time.at(@created_at)
|
79
|
+
end
|
80
|
+
|
81
|
+
# for compatibility
|
82
|
+
def modified_at
|
83
|
+
@modified_at_object ||= Time.at(@modified_at)
|
84
|
+
end
|
67
85
|
|
68
86
|
# data is array of formatted record string
|
69
87
|
def append(data, **kwargs)
|