fluentd 1.11.3-x86-mingw32 → 1.12.2-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/.deepsource.toml +13 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
- data/.github/ISSUE_TEMPLATE/config.yml +5 -0
- data/.github/workflows/linux-test.yaml +36 -0
- data/.github/workflows/macos-test.yaml +30 -0
- data/.github/workflows/stale-actions.yml +22 -0
- data/.github/workflows/windows-test.yaml +30 -0
- data/CHANGELOG.md +138 -0
- data/MAINTAINERS.md +5 -2
- data/README.md +2 -2
- data/bin/fluent-cap-ctl +7 -0
- data/bin/fluent-ctl +7 -0
- data/fluentd.gemspec +4 -3
- data/lib/fluent/capability.rb +87 -0
- data/lib/fluent/command/bundler_injection.rb +1 -1
- data/lib/fluent/command/ca_generate.rb +6 -3
- data/lib/fluent/command/cap_ctl.rb +174 -0
- data/lib/fluent/command/cat.rb +0 -1
- data/lib/fluent/command/ctl.rb +177 -0
- data/lib/fluent/command/fluentd.rb +4 -0
- data/lib/fluent/command/plugin_config_formatter.rb +18 -2
- data/lib/fluent/compat/parser.rb +2 -2
- data/lib/fluent/config/section.rb +2 -2
- data/lib/fluent/config/types.rb +2 -2
- data/lib/fluent/env.rb +4 -0
- data/lib/fluent/event.rb +3 -13
- data/lib/fluent/load.rb +0 -1
- data/lib/fluent/plugin.rb +5 -0
- data/lib/fluent/plugin/buffer.rb +2 -21
- data/lib/fluent/plugin/formatter.rb +24 -0
- data/lib/fluent/plugin/formatter_csv.rb +1 -1
- data/lib/fluent/plugin/formatter_hash.rb +3 -1
- data/lib/fluent/plugin/formatter_json.rb +3 -1
- data/lib/fluent/plugin/formatter_ltsv.rb +7 -5
- data/lib/fluent/plugin/formatter_out_file.rb +6 -4
- data/lib/fluent/plugin/formatter_single_value.rb +4 -2
- data/lib/fluent/plugin/formatter_tsv.rb +4 -2
- data/lib/fluent/plugin/in_http.rb +24 -3
- data/lib/fluent/plugin/in_monitor_agent.rb +1 -1
- data/lib/fluent/plugin/in_tail.rb +128 -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/out_copy.rb +18 -5
- data/lib/fluent/plugin/out_exec_filter.rb +3 -3
- data/lib/fluent/plugin/out_forward.rb +61 -28
- data/lib/fluent/plugin/out_http.rb +29 -4
- data/lib/fluent/plugin/output.rb +14 -6
- data/lib/fluent/plugin/storage_local.rb +3 -3
- data/lib/fluent/plugin_helper/http_server/compat/server.rb +1 -1
- data/lib/fluent/plugin_helper/inject.rb +4 -1
- data/lib/fluent/plugin_helper/retry_state.rb +4 -0
- data/lib/fluent/supervisor.rb +153 -48
- data/lib/fluent/system_config.rb +2 -1
- data/lib/fluent/time.rb +58 -1
- data/lib/fluent/version.rb +1 -1
- data/lib/fluent/winsvc.rb +22 -4
- data/templates/plugin_config_formatter/param.md-table.erb +10 -0
- data/test/command/test_binlog_reader.rb +22 -6
- data/test/command/test_cap_ctl.rb +100 -0
- data/test/command/test_ctl.rb +57 -0
- data/test/command/test_fluentd.rb +38 -0
- data/test/command/test_plugin_config_formatter.rb +124 -2
- data/test/config/test_configurable.rb +1 -1
- data/test/plugin/in_tail/test_position_file.rb +46 -26
- data/test/plugin/out_forward/test_connection_manager.rb +6 -0
- data/test/plugin/test_filter_stdout.rb +6 -1
- data/test/plugin/test_formatter_hash.rb +6 -3
- data/test/plugin/test_formatter_json.rb +14 -4
- data/test/plugin/test_formatter_ltsv.rb +13 -5
- data/test/plugin/test_formatter_out_file.rb +35 -14
- data/test/plugin/test_formatter_single_value.rb +12 -6
- data/test/plugin/test_formatter_tsv.rb +12 -4
- data/test/plugin/test_in_exec.rb +1 -1
- data/test/plugin/test_in_http.rb +25 -0
- data/test/plugin/test_in_tail.rb +470 -32
- data/test/plugin/test_out_copy.rb +87 -0
- data/test/plugin/test_out_file.rb +23 -18
- data/test/plugin/test_out_forward.rb +74 -0
- data/test/plugin/test_out_http.rb +20 -1
- data/test/plugin/test_output.rb +12 -0
- data/test/plugin/test_parser_syslog.rb +2 -2
- data/test/plugin/test_sd_file.rb +1 -1
- data/test/plugin_helper/test_child_process.rb +5 -2
- data/test/plugin_helper/test_compat_parameters.rb +7 -2
- data/test/plugin_helper/test_http_server_helper.rb +3 -1
- data/test/plugin_helper/test_inject.rb +42 -0
- data/test/plugin_helper/test_server.rb +18 -5
- data/test/test_capability.rb +74 -0
- data/test/test_event.rb +16 -0
- data/test/test_formatter.rb +64 -10
- data/test/test_output.rb +6 -1
- data/test/test_supervisor.rb +150 -1
- data/test/test_time_parser.rb +109 -0
- metadata +61 -29
- data/.travis.yml +0 -57
- data/appveyor.yml +0 -28
@@ -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, :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,6 +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.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 }
|
135
138
|
when :unixtime then ->(time){ time.to_i }
|
136
139
|
else
|
137
140
|
localtime = @inject_config.localtime && !@inject_config.utc
|
data/lib/fluent/supervisor.rb
CHANGED
@@ -45,6 +45,7 @@ module Fluent
|
|
45
45
|
module ServerModule
|
46
46
|
def before_run
|
47
47
|
@fluentd_conf = config[:fluentd_conf]
|
48
|
+
@rpc_endpoint = nil
|
48
49
|
@rpc_server = nil
|
49
50
|
@counter = nil
|
50
51
|
|
@@ -53,23 +54,28 @@ module Fluent
|
|
53
54
|
@enable_get_dump = config[:enable_get_dump]
|
54
55
|
run_rpc_server
|
55
56
|
end
|
56
|
-
install_supervisor_signal_handlers
|
57
57
|
|
58
|
-
if
|
59
|
-
@signame = config[:signame]
|
58
|
+
if Fluent.windows?
|
60
59
|
install_windows_event_handler
|
60
|
+
else
|
61
|
+
install_supervisor_signal_handlers
|
61
62
|
end
|
62
63
|
|
63
64
|
if counter = config[:counter_server]
|
64
65
|
run_counter_server(counter)
|
65
66
|
end
|
66
67
|
|
67
|
-
|
68
|
-
|
69
|
-
|
68
|
+
if config[:disable_shared_socket]
|
69
|
+
$log.info "shared socket for multiple workers is disabled"
|
70
|
+
else
|
71
|
+
socket_manager_path = ServerEngine::SocketManager::Server.generate_path
|
72
|
+
ServerEngine::SocketManager::Server.open(socket_manager_path)
|
73
|
+
ENV['SERVERENGINE_SOCKETMANAGER_PATH'] = socket_manager_path.to_s
|
74
|
+
end
|
70
75
|
end
|
71
76
|
|
72
77
|
def after_run
|
78
|
+
stop_windows_event_thread if Fluent.windows?
|
73
79
|
stop_rpc_server if @rpc_endpoint
|
74
80
|
stop_counter_server if @counter
|
75
81
|
Fluent::Supervisor.cleanup_resources
|
@@ -92,7 +98,8 @@ module Fluent
|
|
92
98
|
@rpc_server.mount_proc('/api/processes.flushBuffersAndKillWorkers') { |req, res|
|
93
99
|
$log.debug "fluentd RPC got /api/processes.flushBuffersAndKillWorkers request"
|
94
100
|
if Fluent.windows?
|
95
|
-
|
101
|
+
supervisor_sigusr1_handler
|
102
|
+
stop(true)
|
96
103
|
else
|
97
104
|
Process.kill :USR1, $$
|
98
105
|
Process.kill :TERM, $$
|
@@ -101,7 +108,9 @@ module Fluent
|
|
101
108
|
}
|
102
109
|
@rpc_server.mount_proc('/api/plugins.flushBuffers') { |req, res|
|
103
110
|
$log.debug "fluentd RPC got /api/plugins.flushBuffers request"
|
104
|
-
|
111
|
+
if Fluent.windows?
|
112
|
+
supervisor_sigusr1_handler
|
113
|
+
else
|
105
114
|
Process.kill :USR1, $$
|
106
115
|
end
|
107
116
|
nil
|
@@ -125,7 +134,9 @@ module Fluent
|
|
125
134
|
|
126
135
|
@rpc_server.mount_proc('/api/config.gracefulReload') { |req, res|
|
127
136
|
$log.debug "fluentd RPC got /api/config.gracefulReload request"
|
128
|
-
|
137
|
+
if Fluent.windows?
|
138
|
+
supervisor_sigusr2_handler
|
139
|
+
else
|
129
140
|
Process.kill :USR2, $$
|
130
141
|
end
|
131
142
|
|
@@ -159,38 +170,101 @@ module Fluent
|
|
159
170
|
end
|
160
171
|
|
161
172
|
def install_supervisor_signal_handlers
|
173
|
+
return if Fluent.windows?
|
174
|
+
|
162
175
|
trap :HUP do
|
163
176
|
$log.debug "fluentd supervisor process get SIGHUP"
|
164
177
|
supervisor_sighup_handler
|
165
|
-
end
|
178
|
+
end
|
166
179
|
|
167
180
|
trap :USR1 do
|
168
181
|
$log.debug "fluentd supervisor process get SIGUSR1"
|
169
182
|
supervisor_sigusr1_handler
|
170
|
-
end
|
183
|
+
end
|
171
184
|
|
172
185
|
trap :USR2 do
|
173
186
|
$log.debug 'fluentd supervisor process got SIGUSR2'
|
174
187
|
supervisor_sigusr2_handler
|
175
|
-
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
if Fluent.windows?
|
192
|
+
# Override some methods of ServerEngine::MultiSpawnWorker
|
193
|
+
# Since Fluentd's Supervisor doesn't use ServerEngine's HUP, USR1 and USR2
|
194
|
+
# handlers (see install_supervisor_signal_handlers), they should be
|
195
|
+
# disabled also on Windows, just send commands to workers instead.
|
196
|
+
def restart(graceful)
|
197
|
+
@monitors.each do |m|
|
198
|
+
m.send_command(graceful ? "GRACEFUL_RESTART\n" : "IMMEDIATE_RESTART\n")
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def reload
|
203
|
+
@monitors.each do |m|
|
204
|
+
m.send_command("RELOAD\n")
|
205
|
+
end
|
206
|
+
end
|
176
207
|
end
|
177
208
|
|
178
209
|
def install_windows_event_handler
|
210
|
+
return unless Fluent.windows?
|
211
|
+
|
212
|
+
@pid_signame = "fluentd_#{$$}"
|
213
|
+
@signame = config[:signame]
|
214
|
+
|
179
215
|
Thread.new do
|
180
|
-
|
216
|
+
ipc = Win32::Ipc.new(nil)
|
217
|
+
events = [
|
218
|
+
Win32::Event.new("#{@pid_signame}_STOP_EVENT_THREAD"),
|
219
|
+
Win32::Event.new("#{@pid_signame}"),
|
220
|
+
Win32::Event.new("#{@pid_signame}_HUP"),
|
221
|
+
Win32::Event.new("#{@pid_signame}_USR1"),
|
222
|
+
Win32::Event.new("#{@pid_signame}_USR2"),
|
223
|
+
]
|
224
|
+
if @signame
|
225
|
+
signame_events = [
|
226
|
+
Win32::Event.new("#{@signame}"),
|
227
|
+
Win32::Event.new("#{@signame}_HUP"),
|
228
|
+
Win32::Event.new("#{@signame}_USR1"),
|
229
|
+
Win32::Event.new("#{@signame}_USR2"),
|
230
|
+
]
|
231
|
+
events.concat(signame_events)
|
232
|
+
end
|
181
233
|
begin
|
182
|
-
|
183
|
-
|
184
|
-
|
234
|
+
loop do
|
235
|
+
idx = ipc.wait_any(events, Windows::Synchronize::INFINITE)
|
236
|
+
if idx > 0 && idx <= events.length
|
237
|
+
$log.debug("Got Win32 event \"#{events[idx - 1].name}\"")
|
238
|
+
else
|
239
|
+
$log.warn("Unexpected reutrn value of Win32::Ipc#wait_any: #{idx}")
|
240
|
+
end
|
241
|
+
case idx
|
242
|
+
when 2, 6
|
243
|
+
stop(true)
|
244
|
+
when 3, 7
|
245
|
+
supervisor_sighup_handler
|
246
|
+
when 4, 8
|
247
|
+
supervisor_sigusr1_handler
|
248
|
+
when 5, 9
|
249
|
+
supervisor_sigusr2_handler
|
250
|
+
when 1
|
251
|
+
break
|
252
|
+
end
|
185
253
|
end
|
186
|
-
kill_worker
|
187
|
-
stop(true)
|
188
254
|
ensure
|
189
|
-
|
255
|
+
events.each { |event| event.close }
|
190
256
|
end
|
191
257
|
end
|
192
258
|
end
|
193
259
|
|
260
|
+
def stop_windows_event_thread
|
261
|
+
if Fluent.windows?
|
262
|
+
ev = Win32::Event.open("#{@pid_signame}_STOP_EVENT_THREAD")
|
263
|
+
ev.set
|
264
|
+
ev.close
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
194
268
|
def supervisor_sighup_handler
|
195
269
|
kill_worker
|
196
270
|
end
|
@@ -265,9 +339,25 @@ module Fluent
|
|
265
339
|
def send_signal_to_workers(signal)
|
266
340
|
return unless config[:worker_pid]
|
267
341
|
|
268
|
-
|
269
|
-
|
270
|
-
|
342
|
+
if Fluent.windows?
|
343
|
+
send_command_to_workers(signal)
|
344
|
+
else
|
345
|
+
config[:worker_pid].each_value do |pid|
|
346
|
+
# don't rescue Errno::ESRCH here (invalid status)
|
347
|
+
Process.kill(signal, pid)
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
def send_command_to_workers(signal)
|
353
|
+
# Use SeverEngine's CommandSender on Windows
|
354
|
+
case signal
|
355
|
+
when :HUP
|
356
|
+
restart(false)
|
357
|
+
when :USR1
|
358
|
+
restart(true)
|
359
|
+
when :USR2
|
360
|
+
reload
|
271
361
|
end
|
272
362
|
end
|
273
363
|
end
|
@@ -295,7 +385,7 @@ module Fluent
|
|
295
385
|
config_mtime = File.mtime(path)
|
296
386
|
|
297
387
|
# reuse previous config if last load time is within 5 seconds and mtime of the config file is not changed
|
298
|
-
if Time.now - Time.at(pre_loadtime) < 5
|
388
|
+
if (Time.now - Time.at(pre_loadtime) < 5) && (config_mtime == pre_config_mtime)
|
299
389
|
return params['pre_conf']
|
300
390
|
end
|
301
391
|
|
@@ -367,6 +457,7 @@ module Fluent
|
|
367
457
|
config_path: path,
|
368
458
|
main_cmd: params['main_cmd'],
|
369
459
|
signame: params['signame'],
|
460
|
+
disable_shared_socket: params['disable_shared_socket']
|
370
461
|
}
|
371
462
|
if daemonize
|
372
463
|
se_config[:pid_path] = pid_path
|
@@ -482,7 +573,8 @@ module Fluent
|
|
482
573
|
supervise: true,
|
483
574
|
standalone_worker: false,
|
484
575
|
signame: nil,
|
485
|
-
conf_encoding: 'utf-8'
|
576
|
+
conf_encoding: 'utf-8',
|
577
|
+
disable_shared_socket: nil
|
486
578
|
}
|
487
579
|
end
|
488
580
|
|
@@ -710,6 +802,7 @@ module Fluent
|
|
710
802
|
'counter_server' => @system_config.counter_server,
|
711
803
|
'log_format' => @system_config.log.format,
|
712
804
|
'log_time_format' => @system_config.log.time_format,
|
805
|
+
'disable_shared_socket' => @system_config.disable_shared_socket
|
713
806
|
}
|
714
807
|
|
715
808
|
se = ServerEngine.create(ServerModule, WorkerModule){
|
@@ -746,33 +839,45 @@ module Fluent
|
|
746
839
|
end
|
747
840
|
end
|
748
841
|
|
749
|
-
|
750
|
-
|
751
|
-
|
842
|
+
if Fluent.windows?
|
843
|
+
install_main_process_command_handlers
|
844
|
+
else
|
845
|
+
trap :USR1 do
|
846
|
+
flush_buffer
|
847
|
+
end
|
752
848
|
|
753
|
-
|
754
|
-
|
755
|
-
|
849
|
+
trap :USR2 do
|
850
|
+
reload_config
|
851
|
+
end
|
852
|
+
end
|
853
|
+
end
|
756
854
|
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
855
|
+
def install_main_process_command_handlers
|
856
|
+
command_pipe = $stdin.dup
|
857
|
+
$stdin.reopen(File::NULL, "rb")
|
858
|
+
command_pipe.binmode
|
859
|
+
command_pipe.sync = true
|
762
860
|
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
861
|
+
Thread.new do
|
862
|
+
loop do
|
863
|
+
cmd = command_pipe.gets
|
864
|
+
break unless cmd
|
865
|
+
|
866
|
+
case cmd.chomp!
|
867
|
+
when "GRACEFUL_STOP", "IMMEDIATE_STOP"
|
868
|
+
$log.debug "fluentd main process get #{cmd} command"
|
869
|
+
@finished = true
|
870
|
+
$log.debug "getting start to shutdown main process"
|
871
|
+
Fluent::Engine.stop
|
872
|
+
break
|
873
|
+
when "GRACEFUL_RESTART"
|
874
|
+
$log.debug "fluentd main process get #{cmd} command"
|
875
|
+
flush_buffer
|
876
|
+
when "RELOAD"
|
877
|
+
$log.debug "fluentd main process get #{cmd} command"
|
878
|
+
reload_config
|
879
|
+
else
|
880
|
+
$log.warn "fluentd main process get unknown command [#{cmd}]"
|
776
881
|
end
|
777
882
|
end
|
778
883
|
end
|
data/lib/fluent/system_config.rb
CHANGED
@@ -27,7 +27,7 @@ module Fluent
|
|
27
27
|
:log_event_verbose, :ignore_repeated_log_interval, :ignore_same_log_interval,
|
28
28
|
:without_source, :rpc_endpoint, :enable_get_dump, :process_name,
|
29
29
|
:file_permission, :dir_permission, :counter_server, :counter_client,
|
30
|
-
:strict_config_value, :enable_msgpack_time_support
|
30
|
+
:strict_config_value, :enable_msgpack_time_support, :disable_shared_socket
|
31
31
|
]
|
32
32
|
|
33
33
|
config_param :workers, :integer, default: 1
|
@@ -45,6 +45,7 @@ module Fluent
|
|
45
45
|
config_param :process_name, :string, default: nil
|
46
46
|
config_param :strict_config_value, :bool, default: nil
|
47
47
|
config_param :enable_msgpack_time_support, :bool, default: nil
|
48
|
+
config_param :disable_shared_socket, :bool, default: nil
|
48
49
|
config_param :file_permission, default: nil do |v|
|
49
50
|
v.to_i(8)
|
50
51
|
end
|
data/lib/fluent/time.rb
CHANGED
@@ -50,6 +50,7 @@ module Fluent
|
|
50
50
|
def to_int
|
51
51
|
@sec
|
52
52
|
end
|
53
|
+
alias :to_i :to_int
|
53
54
|
|
54
55
|
def to_f
|
55
56
|
@sec + @nsec / 1_000_000_000.0
|
@@ -131,13 +132,14 @@ module Fluent
|
|
131
132
|
end
|
132
133
|
|
133
134
|
module TimeMixin
|
134
|
-
TIME_TYPES = ['string', 'unixtime', 'float']
|
135
|
+
TIME_TYPES = ['string', 'unixtime', 'float', 'mixed']
|
135
136
|
|
136
137
|
TIME_PARAMETERS = [
|
137
138
|
[:time_format, :string, {default: nil}],
|
138
139
|
[:localtime, :bool, {default: true}], # UTC if :localtime is false and :timezone is nil
|
139
140
|
[:utc, :bool, {default: false}], # to turn :localtime false
|
140
141
|
[:timezone, :string, {default: nil}],
|
142
|
+
[:time_format_fallbacks, :array, {default: []}], # try time_format, then try fallbacks
|
141
143
|
]
|
142
144
|
TIME_FULL_PARAMETERS = [
|
143
145
|
# To avoid to define :time_type twice (in plugin_helper/inject)
|
@@ -169,6 +171,12 @@ module Fluent
|
|
169
171
|
raise Fluent::ConfigError, "both of utc and localtime are specified, use only one of them"
|
170
172
|
end
|
171
173
|
|
174
|
+
if conf.has_key?('time_type') and @time_type == :mixed
|
175
|
+
if @time_format.nil? and @time_format_fallbacks.empty?
|
176
|
+
raise Fluent::ConfigError, "time_type is :mixed but time_format and time_format_fallbacks is empty."
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
172
180
|
Fluent::Timezone.validate!(@timezone) if @timezone
|
173
181
|
end
|
174
182
|
end
|
@@ -179,6 +187,7 @@ module Fluent
|
|
179
187
|
end
|
180
188
|
|
181
189
|
def time_parser_create(type: @time_type, format: @time_format, timezone: @timezone, force_localtime: false)
|
190
|
+
return MixedTimeParser.new(type, format, @localtime, timezone, @utc, force_localtime, @time_format_fallbacks) if type == :mixed
|
182
191
|
return NumericTimeParser.new(type) if type != :string
|
183
192
|
return TimeParser.new(format, true, nil) if force_localtime
|
184
193
|
|
@@ -451,4 +460,52 @@ module Fluent
|
|
451
460
|
end
|
452
461
|
end
|
453
462
|
end
|
463
|
+
|
464
|
+
# MixedTimeParser is available when time_type is set to :mixed
|
465
|
+
#
|
466
|
+
# Use Case 1: primary format is specified explicitly in time_format
|
467
|
+
# time_type mixed
|
468
|
+
# time_format %iso8601
|
469
|
+
# time_format_fallbacks unixtime
|
470
|
+
# Use Case 2: time_format is omitted
|
471
|
+
# time_type mixed
|
472
|
+
# time_format_fallbacks %iso8601, unixtime
|
473
|
+
#
|
474
|
+
class MixedTimeParser < TimeParser # to include TimeParseError
|
475
|
+
def initialize(type, format = nil, localtime = nil, timezone = nil, utc = nil, force_localtime = nil, fallbacks = [])
|
476
|
+
@parsers = []
|
477
|
+
fallbacks.unshift(format).each do |fallback|
|
478
|
+
next unless fallback
|
479
|
+
case fallback
|
480
|
+
when 'unixtime', 'float'
|
481
|
+
@parsers << NumericTimeParser.new(fallback, localtime, timezone)
|
482
|
+
else
|
483
|
+
if force_localtime
|
484
|
+
@parsers << TimeParser.new(fallback, true, nil)
|
485
|
+
else
|
486
|
+
localtime = localtime && (timezone.nil? && !utc)
|
487
|
+
@parsers << TimeParser.new(fallback, localtime, timezone)
|
488
|
+
end
|
489
|
+
end
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
def parse(value)
|
494
|
+
@parsers.each do |parser|
|
495
|
+
begin
|
496
|
+
Float(value) if parser.class == Fluent::NumericTimeParser
|
497
|
+
rescue
|
498
|
+
next
|
499
|
+
end
|
500
|
+
begin
|
501
|
+
return parser.parse(value)
|
502
|
+
rescue
|
503
|
+
# skip TimeParseError
|
504
|
+
end
|
505
|
+
end
|
506
|
+
fallback_class = @parsers.collect do |parser| parser.class end.join(",")
|
507
|
+
raise TimeParseError, "invalid time format: value = #{value}, even though fallbacks: #{fallback_class}"
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
454
511
|
end
|