fluentd 1.11.5-x86-mingw32 → 1.12.0-x86-mingw32
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/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
- data/.github/ISSUE_TEMPLATE/config.yml +5 -0
- data/.github/workflows/stale-actions.yml +22 -0
- data/.travis.yml +22 -2
- data/CHANGELOG.md +38 -0
- data/README.md +1 -1
- data/appveyor.yml +3 -0
- data/bin/fluent-cap-ctl +7 -0
- data/bin/fluent-ctl +7 -0
- data/fluentd.gemspec +1 -0
- data/lib/fluent/capability.rb +87 -0
- data/lib/fluent/command/cap_ctl.rb +174 -0
- data/lib/fluent/command/ctl.rb +177 -0
- data/lib/fluent/command/plugin_config_formatter.rb +2 -1
- data/lib/fluent/env.rb +4 -0
- data/lib/fluent/plugin.rb +5 -0
- data/lib/fluent/plugin/buffer.rb +2 -21
- data/lib/fluent/plugin/formatter.rb +2 -2
- data/lib/fluent/plugin/formatter_csv.rb +1 -1
- data/lib/fluent/plugin/formatter_hash.rb +1 -1
- data/lib/fluent/plugin/formatter_ltsv.rb +3 -3
- data/lib/fluent/plugin/formatter_out_file.rb +3 -3
- data/lib/fluent/plugin/formatter_single_value.rb +2 -2
- data/lib/fluent/plugin/formatter_tsv.rb +2 -2
- data/lib/fluent/plugin/in_http.rb +23 -2
- data/lib/fluent/plugin/in_tail.rb +109 -41
- data/lib/fluent/plugin/in_tail/position_file.rb +39 -14
- data/lib/fluent/plugin/in_tcp.rb +1 -0
- data/lib/fluent/plugin/output.rb +7 -1
- data/lib/fluent/plugin_helper/http_server/compat/server.rb +1 -1
- data/lib/fluent/plugin_helper/inject.rb +4 -2
- data/lib/fluent/plugin_helper/retry_state.rb +4 -0
- data/lib/fluent/supervisor.rb +140 -42
- data/lib/fluent/time.rb +1 -0
- data/lib/fluent/version.rb +1 -1
- data/lib/fluent/winsvc.rb +22 -4
- data/test/command/test_cap_ctl.rb +100 -0
- data/test/command/test_ctl.rb +57 -0
- data/test/command/test_plugin_config_formatter.rb +57 -2
- data/test/plugin/in_tail/test_position_file.rb +45 -25
- data/test/plugin/test_in_http.rb +25 -0
- data/test/plugin/test_in_tail.rb +430 -30
- data/test/plugin/test_parser_syslog.rb +2 -2
- data/test/plugin_helper/test_inject.rb +29 -0
- data/test/test_capability.rb +74 -0
- data/test/test_supervisor.rb +102 -10
- metadata +31 -2
@@ -22,34 +22,40 @@ module Fluent::Plugin
|
|
22
22
|
UNWATCHED_POSITION = 0xffffffffffffffff
|
23
23
|
POSITION_FILE_ENTRY_REGEX = /^([^\t]+)\t([0-9a-fA-F]+)\t([0-9a-fA-F]+)/.freeze
|
24
24
|
|
25
|
-
def self.load(file, logger:)
|
26
|
-
pf = new(file, logger: logger)
|
25
|
+
def self.load(file, follow_inodes, existing_paths, logger:)
|
26
|
+
pf = new(file, follow_inodes, existing_paths, logger: logger)
|
27
27
|
pf.load
|
28
28
|
pf
|
29
29
|
end
|
30
30
|
|
31
|
-
def initialize(file, logger: nil)
|
31
|
+
def initialize(file, follow_inodes, existing_paths, logger: nil)
|
32
32
|
@file = file
|
33
33
|
@logger = logger
|
34
34
|
@file_mutex = Mutex.new
|
35
35
|
@map = {}
|
36
|
+
@follow_inodes = follow_inodes
|
37
|
+
@existing_paths = existing_paths
|
36
38
|
end
|
37
39
|
|
38
|
-
def [](
|
39
|
-
if m = @map[path]
|
40
|
+
def [](target_info)
|
41
|
+
if m = @map[@follow_inodes ? target_info.ino : target_info.path]
|
40
42
|
return m
|
41
43
|
end
|
42
44
|
|
43
45
|
@file_mutex.synchronize {
|
44
46
|
@file.seek(0, IO::SEEK_END)
|
45
|
-
seek = @file.pos + path.bytesize + 1
|
46
|
-
@file.write "#{path}\t0000000000000000\t0000000000000000\n"
|
47
|
-
|
47
|
+
seek = @file.pos + target_info.path.bytesize + 1
|
48
|
+
@file.write "#{target_info.path}\t0000000000000000\t0000000000000000\n"
|
49
|
+
if @follow_inodes
|
50
|
+
@map[target_info.ino] = FilePositionEntry.new(@file, @file_mutex, seek, 0, 0)
|
51
|
+
else
|
52
|
+
@map[target_info.path] = FilePositionEntry.new(@file, @file_mutex, seek, 0, 0)
|
53
|
+
end
|
48
54
|
}
|
49
55
|
end
|
50
56
|
|
51
|
-
def unwatch(
|
52
|
-
if (entry = @map.delete(path))
|
57
|
+
def unwatch(target_info)
|
58
|
+
if (entry = @map.delete(@follow_inodes ? target_info.ino : target_info.path))
|
53
59
|
entry.update_pos(UNWATCHED_POSITION)
|
54
60
|
end
|
55
61
|
end
|
@@ -69,7 +75,11 @@ module Fluent::Plugin
|
|
69
75
|
pos = m[2].to_i(16)
|
70
76
|
ino = m[3].to_i(16)
|
71
77
|
seek = @file.pos - line.bytesize + path.bytesize + 1
|
72
|
-
|
78
|
+
if @follow_inodes
|
79
|
+
map[ino] = FilePositionEntry.new(@file, @file_mutex, seek, pos, ino)
|
80
|
+
else
|
81
|
+
map[path] = FilePositionEntry.new(@file, @file_mutex, seek, pos, ino)
|
82
|
+
end
|
73
83
|
end
|
74
84
|
end
|
75
85
|
|
@@ -94,8 +104,9 @@ module Fluent::Plugin
|
|
94
104
|
@file.truncate(0)
|
95
105
|
@file.write(entries.values.map(&:to_entry_fmt).join)
|
96
106
|
|
97
|
-
|
98
|
-
|
107
|
+
# entry contains path/ino key and value.
|
108
|
+
entries.each do |key, val|
|
109
|
+
if (m = @map[key])
|
99
110
|
m.seek = val.seek
|
100
111
|
end
|
101
112
|
end
|
@@ -139,13 +150,25 @@ module Fluent::Plugin
|
|
139
150
|
@logger.warn("#{path} already exists. use latest one: deleted #{entries[path]}") if @logger
|
140
151
|
end
|
141
152
|
|
142
|
-
|
153
|
+
if @follow_inodes
|
154
|
+
entries[ino] = Entry.new(path, pos, ino, file_pos + path.size + 1)
|
155
|
+
else
|
156
|
+
entries[path] = Entry.new(path, pos, ino, file_pos + path.size + 1)
|
157
|
+
end
|
143
158
|
file_pos += line.size
|
144
159
|
end
|
145
160
|
end
|
146
161
|
|
162
|
+
entries = remove_deleted_files_entries(entries, @existing_paths) if @follow_inodes
|
147
163
|
entries
|
148
164
|
end
|
165
|
+
|
166
|
+
def remove_deleted_files_entries(existent_entries, existing_paths)
|
167
|
+
filtered_entries = existent_entries.select {|file_entry|
|
168
|
+
existing_paths.key?(file_entry)
|
169
|
+
}
|
170
|
+
filtered_entries
|
171
|
+
end
|
149
172
|
end
|
150
173
|
|
151
174
|
Entry = Struct.new(:path, :pos, :ino, :seek) do
|
@@ -224,5 +247,7 @@ module Fluent::Plugin
|
|
224
247
|
@inode
|
225
248
|
end
|
226
249
|
end
|
250
|
+
|
251
|
+
TargetInfo = Struct.new(:path, :ino)
|
227
252
|
end
|
228
253
|
end
|
data/lib/fluent/plugin/in_tcp.rb
CHANGED
@@ -98,6 +98,7 @@ module Fluent::Plugin
|
|
98
98
|
def start
|
99
99
|
super
|
100
100
|
|
101
|
+
log.info "listening tcp socket", bind: @bind, port: @port
|
101
102
|
del_size = @delimiter.length
|
102
103
|
if @_extract_enabled && @_extract_tag_key
|
103
104
|
server_create(:in_tcp_server_single_emit, @port, bind: @bind, resolve_name: !!@source_hostname_key) do |data, conn|
|
data/lib/fluent/plugin/output.rb
CHANGED
@@ -1252,7 +1252,13 @@ module Fluent
|
|
1252
1252
|
log.debug "buffer queue cleared"
|
1253
1253
|
@retry = nil
|
1254
1254
|
else
|
1255
|
-
@retry.
|
1255
|
+
# Ensure that the current time is greater than or equal to @retry.next_time to avoid the situation when
|
1256
|
+
# @retry.step is called almost as many times as the number of flush threads in a short time.
|
1257
|
+
if Time.now >= @retry.next_time
|
1258
|
+
@retry.step
|
1259
|
+
else
|
1260
|
+
@retry.recalc_next_time # to prevent all flush threads from retrying at the same time
|
1261
|
+
end
|
1256
1262
|
if error
|
1257
1263
|
if using_secondary
|
1258
1264
|
msg = "failed to flush the buffer with secondary output."
|
@@ -81,7 +81,7 @@ module Fluent
|
|
81
81
|
|
82
82
|
def build_handler
|
83
83
|
@methods.group_by(&:first).each do |(path, rest)|
|
84
|
-
klass = Fluent::PluginHelper::HttpServer::Compat::WebrickHandler.build(Hash[rest.map { |e| [e[1], e[2]] }])
|
84
|
+
klass = Fluent::PluginHelper::HttpServer::Compat::WebrickHandler.build(**Hash[rest.map { |e| [e[1], e[2]] }])
|
85
85
|
@server.mount(path, klass)
|
86
86
|
end
|
87
87
|
end
|
@@ -76,7 +76,7 @@ module Fluent
|
|
76
76
|
config_param :time_key, :string, default: nil
|
77
77
|
|
78
78
|
# To avoid defining :time_type twice
|
79
|
-
config_param :time_type, :enum, list: [:float, :unixtime, :unixtime_millis, :string], default: :float
|
79
|
+
config_param :time_type, :enum, list: [:float, :unixtime, :unixtime_millis, :unixtime_micros, :unixtime_nanos, :string], default: :float
|
80
80
|
|
81
81
|
Fluent::TimeMixin::TIME_PARAMETERS.each do |name, type, opts|
|
82
82
|
config_param(name, type, **opts)
|
@@ -132,7 +132,9 @@ module Fluent
|
|
132
132
|
if @_inject_time_key
|
133
133
|
@_inject_time_formatter = case @inject_config.time_type
|
134
134
|
when :float then ->(time){ time.to_r.truncate(+6).to_f } # microsecond floating point value
|
135
|
-
when :unixtime_millis then ->(time) { time.
|
135
|
+
when :unixtime_millis then ->(time) { time.respond_to?(:nsec) ? time.to_i * 1_000 + time.nsec / 1_000_000 : (time * 1_000).floor }
|
136
|
+
when :unixtime_micros then ->(time) { time.respond_to?(:nsec) ? time.to_i * 1_000_000 + time.nsec / 1_000 : (time * 1_000_000).floor }
|
137
|
+
when :unixtime_nanos then ->(time) { time.respond_to?(:nsec) ? time.to_i * 1_000_000_000 + time.nsec : (time * 1_000_000_000).floor }
|
136
138
|
when :unixtime then ->(time){ time.to_i }
|
137
139
|
else
|
138
140
|
localtime = @inject_config.localtime && !@inject_config.utc
|
data/lib/fluent/supervisor.rb
CHANGED
@@ -53,11 +53,11 @@ module Fluent
|
|
53
53
|
@enable_get_dump = config[:enable_get_dump]
|
54
54
|
run_rpc_server
|
55
55
|
end
|
56
|
-
install_supervisor_signal_handlers
|
57
56
|
|
58
|
-
if
|
59
|
-
@signame = config[:signame]
|
57
|
+
if Fluent.windows?
|
60
58
|
install_windows_event_handler
|
59
|
+
else
|
60
|
+
install_supervisor_signal_handlers
|
61
61
|
end
|
62
62
|
|
63
63
|
if counter = config[:counter_server]
|
@@ -70,6 +70,7 @@ module Fluent
|
|
70
70
|
end
|
71
71
|
|
72
72
|
def after_run
|
73
|
+
stop_windows_event_thread if Fluent.windows?
|
73
74
|
stop_rpc_server if @rpc_endpoint
|
74
75
|
stop_counter_server if @counter
|
75
76
|
Fluent::Supervisor.cleanup_resources
|
@@ -92,7 +93,8 @@ module Fluent
|
|
92
93
|
@rpc_server.mount_proc('/api/processes.flushBuffersAndKillWorkers') { |req, res|
|
93
94
|
$log.debug "fluentd RPC got /api/processes.flushBuffersAndKillWorkers request"
|
94
95
|
if Fluent.windows?
|
95
|
-
|
96
|
+
supervisor_sigusr1_handler
|
97
|
+
stop(true)
|
96
98
|
else
|
97
99
|
Process.kill :USR1, $$
|
98
100
|
Process.kill :TERM, $$
|
@@ -101,7 +103,9 @@ module Fluent
|
|
101
103
|
}
|
102
104
|
@rpc_server.mount_proc('/api/plugins.flushBuffers') { |req, res|
|
103
105
|
$log.debug "fluentd RPC got /api/plugins.flushBuffers request"
|
104
|
-
|
106
|
+
if Fluent.windows?
|
107
|
+
supervisor_sigusr1_handler
|
108
|
+
else
|
105
109
|
Process.kill :USR1, $$
|
106
110
|
end
|
107
111
|
nil
|
@@ -125,7 +129,9 @@ module Fluent
|
|
125
129
|
|
126
130
|
@rpc_server.mount_proc('/api/config.gracefulReload') { |req, res|
|
127
131
|
$log.debug "fluentd RPC got /api/config.gracefulReload request"
|
128
|
-
|
132
|
+
if Fluent.windows?
|
133
|
+
supervisor_sigusr2_handler
|
134
|
+
else
|
129
135
|
Process.kill :USR2, $$
|
130
136
|
end
|
131
137
|
|
@@ -159,37 +165,101 @@ module Fluent
|
|
159
165
|
end
|
160
166
|
|
161
167
|
def install_supervisor_signal_handlers
|
168
|
+
return if Fluent.windows?
|
169
|
+
|
162
170
|
trap :HUP do
|
163
171
|
$log.debug "fluentd supervisor process get SIGHUP"
|
164
172
|
supervisor_sighup_handler
|
165
|
-
end
|
173
|
+
end
|
166
174
|
|
167
175
|
trap :USR1 do
|
168
176
|
$log.debug "fluentd supervisor process get SIGUSR1"
|
169
177
|
supervisor_sigusr1_handler
|
170
|
-
end
|
178
|
+
end
|
171
179
|
|
172
180
|
trap :USR2 do
|
173
181
|
$log.debug 'fluentd supervisor process got SIGUSR2'
|
174
182
|
supervisor_sigusr2_handler
|
175
|
-
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
if Fluent.windows?
|
187
|
+
# Override some methods of ServerEngine::MultiSpawnWorker
|
188
|
+
# Since Fluentd's Supervisor doesn't use ServerEngine's HUP, USR1 and USR2
|
189
|
+
# handlers (see install_supervisor_signal_handlers), they should be
|
190
|
+
# disabled also on Windows, just send commands to workers instead.
|
191
|
+
def restart(graceful)
|
192
|
+
@monitors.each do |m|
|
193
|
+
m.send_command(graceful ? "GRACEFUL_RESTART\n" : "IMMEDIATE_RESTART\n")
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def reload
|
198
|
+
@monitors.each do |m|
|
199
|
+
m.send_command("RELOAD\n")
|
200
|
+
end
|
201
|
+
end
|
176
202
|
end
|
177
203
|
|
178
204
|
def install_windows_event_handler
|
205
|
+
return unless Fluent.windows?
|
206
|
+
|
207
|
+
@pid_signame = "fluentd_#{$$}"
|
208
|
+
@signame = config[:signame]
|
209
|
+
|
179
210
|
Thread.new do
|
180
|
-
|
211
|
+
ipc = Win32::Ipc.new(nil)
|
212
|
+
events = [
|
213
|
+
Win32::Event.new("#{@pid_signame}_STOP_EVENT_THREAD"),
|
214
|
+
Win32::Event.new("#{@pid_signame}"),
|
215
|
+
Win32::Event.new("#{@pid_signame}_HUP"),
|
216
|
+
Win32::Event.new("#{@pid_signame}_USR1"),
|
217
|
+
Win32::Event.new("#{@pid_signame}_USR2"),
|
218
|
+
]
|
219
|
+
if @signame
|
220
|
+
signame_events = [
|
221
|
+
Win32::Event.new("#{@signame}"),
|
222
|
+
Win32::Event.new("#{@signame}_HUP"),
|
223
|
+
Win32::Event.new("#{@signame}_USR1"),
|
224
|
+
Win32::Event.new("#{@signame}_USR2"),
|
225
|
+
]
|
226
|
+
events.concat(signame_events)
|
227
|
+
end
|
181
228
|
begin
|
182
|
-
|
183
|
-
|
184
|
-
|
229
|
+
loop do
|
230
|
+
idx = ipc.wait_any(events, Windows::Synchronize::INFINITE)
|
231
|
+
if idx > 0 && idx <= events.length
|
232
|
+
$log.debug("Got Win32 event \"#{events[idx - 1].name}\"")
|
233
|
+
else
|
234
|
+
$log.warn("Unexpected reutrn value of Win32::Ipc#wait_any: #{idx}")
|
235
|
+
end
|
236
|
+
case idx
|
237
|
+
when 2, 6
|
238
|
+
stop(true)
|
239
|
+
when 3, 7
|
240
|
+
supervisor_sighup_handler
|
241
|
+
when 4, 8
|
242
|
+
supervisor_sigusr1_handler
|
243
|
+
when 5, 9
|
244
|
+
supervisor_sigusr2_handler
|
245
|
+
when 1
|
246
|
+
break
|
247
|
+
end
|
185
248
|
end
|
186
|
-
stop(true)
|
187
249
|
ensure
|
188
|
-
|
250
|
+
events.each { |event| event.close }
|
189
251
|
end
|
190
252
|
end
|
191
253
|
end
|
192
254
|
|
255
|
+
def stop_windows_event_thread
|
256
|
+
if Fluent.windows?
|
257
|
+
ev = Win32::Event.open("#{@pid_signame}_STOP_EVENT_THREAD")
|
258
|
+
ev.set
|
259
|
+
ev.close
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
193
263
|
def supervisor_sighup_handler
|
194
264
|
kill_worker
|
195
265
|
end
|
@@ -264,9 +334,25 @@ module Fluent
|
|
264
334
|
def send_signal_to_workers(signal)
|
265
335
|
return unless config[:worker_pid]
|
266
336
|
|
267
|
-
|
268
|
-
|
269
|
-
|
337
|
+
if Fluent.windows?
|
338
|
+
send_command_to_workers(signal)
|
339
|
+
else
|
340
|
+
config[:worker_pid].each_value do |pid|
|
341
|
+
# don't rescue Errno::ESRCH here (invalid status)
|
342
|
+
Process.kill(signal, pid)
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
def send_command_to_workers(signal)
|
348
|
+
# Use SeverEngine's CommandSender on Windows
|
349
|
+
case signal
|
350
|
+
when :HUP
|
351
|
+
restart(false)
|
352
|
+
when :USR1
|
353
|
+
restart(true)
|
354
|
+
when :USR2
|
355
|
+
reload
|
270
356
|
end
|
271
357
|
end
|
272
358
|
end
|
@@ -745,33 +831,45 @@ module Fluent
|
|
745
831
|
end
|
746
832
|
end
|
747
833
|
|
748
|
-
|
749
|
-
|
750
|
-
|
834
|
+
if Fluent.windows?
|
835
|
+
install_main_process_command_handlers
|
836
|
+
else
|
837
|
+
trap :USR1 do
|
838
|
+
flush_buffer
|
839
|
+
end
|
751
840
|
|
752
|
-
|
753
|
-
|
754
|
-
|
841
|
+
trap :USR2 do
|
842
|
+
reload_config
|
843
|
+
end
|
844
|
+
end
|
845
|
+
end
|
755
846
|
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
847
|
+
def install_main_process_command_handlers
|
848
|
+
command_pipe = $stdin.dup
|
849
|
+
$stdin.reopen(File::NULL, "rb")
|
850
|
+
command_pipe.binmode
|
851
|
+
command_pipe.sync = true
|
761
852
|
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
853
|
+
Thread.new do
|
854
|
+
loop do
|
855
|
+
cmd = command_pipe.gets
|
856
|
+
break unless cmd
|
857
|
+
|
858
|
+
case cmd.chomp!
|
859
|
+
when "GRACEFUL_STOP", "IMMEDIATE_STOP"
|
860
|
+
$log.debug "fluentd main process get #{cmd} command"
|
861
|
+
@finished = true
|
862
|
+
$log.debug "getting start to shutdown main process"
|
863
|
+
Fluent::Engine.stop
|
864
|
+
break
|
865
|
+
when "GRACEFUL_RESTART"
|
866
|
+
$log.debug "fluentd main process get #{cmd} command"
|
867
|
+
flush_buffer
|
868
|
+
when "RELOAD"
|
869
|
+
$log.debug "fluentd main process get #{cmd} command"
|
870
|
+
reload_config
|
871
|
+
else
|
872
|
+
$log.warn "fluentd main process get unknown command [#{cmd}]"
|
775
873
|
end
|
776
874
|
end
|
777
875
|
end
|
data/lib/fluent/time.rb
CHANGED