fluentd 1.11.3 → 1.12.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/.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 +66 -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 +2 -1
- 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 +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 +5 -3
- 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 +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/out_http.rb +20 -2
- data/lib/fluent/plugin/output.rb +14 -6
- 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 +140 -43
- 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_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_plugin_config_formatter.rb +57 -2
- data/test/plugin/in_tail/test_position_file.rb +45 -25
- 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_http.rb +25 -0
- data/test/plugin/test_in_tail.rb +430 -30
- data/test/plugin/test_out_file.rb +23 -18
- data/test/plugin/test_output.rb +12 -0
- data/test/plugin/test_parser_syslog.rb +2 -2
- data/test/plugin_helper/test_compat_parameters.rb +7 -2
- data/test/plugin_helper/test_inject.rb +42 -0
- data/test/test_capability.rb +74 -0
- data/test/test_formatter.rb +34 -10
- data/test/test_output.rb +6 -1
- data/test/test_supervisor.rb +119 -1
- metadata +33 -4
data/lib/fluent/plugin/output.rb
CHANGED
@@ -769,17 +769,19 @@ module Fluent
|
|
769
769
|
end
|
770
770
|
end
|
771
771
|
|
772
|
-
|
773
|
-
log.warn "chunk key placeholder '#{$1}' not replaced. template:#{str}"
|
774
|
-
end
|
775
|
-
|
776
|
-
rvalue.sub(CHUNK_ID_PLACEHOLDER_PATTERN) {
|
772
|
+
rvalue = rvalue.sub(CHUNK_ID_PLACEHOLDER_PATTERN) {
|
777
773
|
if chunk_passed
|
778
774
|
dump_unique_id_hex(chunk.unique_id)
|
779
775
|
else
|
780
776
|
log.warn "${chunk_id} is not allowed in this plugin. Pass Chunk instead of metadata in extract_placeholders's 2nd argument"
|
781
777
|
end
|
782
778
|
}
|
779
|
+
|
780
|
+
if rvalue =~ CHUNK_KEY_PLACEHOLDER_PATTERN
|
781
|
+
log.warn "chunk key placeholder '#{$1}' not replaced. template:#{str}"
|
782
|
+
end
|
783
|
+
|
784
|
+
rvalue
|
783
785
|
end
|
784
786
|
end
|
785
787
|
|
@@ -1250,7 +1252,13 @@ module Fluent
|
|
1250
1252
|
log.debug "buffer queue cleared"
|
1251
1253
|
@retry = nil
|
1252
1254
|
else
|
1253
|
-
@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
|
1254
1262
|
if error
|
1255
1263
|
if using_secondary
|
1256
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, :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
@@ -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,38 +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
|
-
kill_worker
|
187
|
-
stop(true)
|
188
249
|
ensure
|
189
|
-
|
250
|
+
events.each { |event| event.close }
|
190
251
|
end
|
191
252
|
end
|
192
253
|
end
|
193
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
|
+
|
194
263
|
def supervisor_sighup_handler
|
195
264
|
kill_worker
|
196
265
|
end
|
@@ -265,9 +334,25 @@ module Fluent
|
|
265
334
|
def send_signal_to_workers(signal)
|
266
335
|
return unless config[:worker_pid]
|
267
336
|
|
268
|
-
|
269
|
-
|
270
|
-
|
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
|
271
356
|
end
|
272
357
|
end
|
273
358
|
end
|
@@ -746,33 +831,45 @@ module Fluent
|
|
746
831
|
end
|
747
832
|
end
|
748
833
|
|
749
|
-
|
750
|
-
|
751
|
-
|
834
|
+
if Fluent.windows?
|
835
|
+
install_main_process_command_handlers
|
836
|
+
else
|
837
|
+
trap :USR1 do
|
838
|
+
flush_buffer
|
839
|
+
end
|
752
840
|
|
753
|
-
|
754
|
-
|
755
|
-
|
841
|
+
trap :USR2 do
|
842
|
+
reload_config
|
843
|
+
end
|
844
|
+
end
|
845
|
+
end
|
756
846
|
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
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
|
762
852
|
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
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}]"
|
776
873
|
end
|
777
874
|
end
|
778
875
|
end
|
data/lib/fluent/time.rb
CHANGED
data/lib/fluent/version.rb
CHANGED
data/lib/fluent/winsvc.rb
CHANGED
@@ -61,7 +61,6 @@ begin
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def service_main
|
64
|
-
|
65
64
|
@pid = service_main_start(@service_name)
|
66
65
|
while running?
|
67
66
|
sleep 10
|
@@ -69,13 +68,32 @@ begin
|
|
69
68
|
end
|
70
69
|
|
71
70
|
def service_stop
|
72
|
-
|
73
|
-
ev.set
|
74
|
-
ev.close
|
71
|
+
set_event(@service_name)
|
75
72
|
if @pid > 0
|
76
73
|
Process.waitpid(@pid)
|
77
74
|
end
|
78
75
|
end
|
76
|
+
|
77
|
+
def service_paramchange
|
78
|
+
set_event("#{@service_name}_USR2")
|
79
|
+
end
|
80
|
+
|
81
|
+
def service_user_defined_control(code)
|
82
|
+
case code
|
83
|
+
when 128
|
84
|
+
set_event("#{@service_name}_HUP")
|
85
|
+
when 129
|
86
|
+
set_event("#{@service_name}_USR1")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def set_event(event_name)
|
93
|
+
ev = Win32::Event.open(event_name)
|
94
|
+
ev.set
|
95
|
+
ev.close
|
96
|
+
end
|
79
97
|
end
|
80
98
|
|
81
99
|
FluentdService.new(opts[:service_name]).mainloop
|
@@ -82,6 +82,14 @@ class TestBaseCommand < ::Test::Unit::TestCase
|
|
82
82
|
end
|
83
83
|
|
84
84
|
class TestHead < TestBaseCommand
|
85
|
+
setup do
|
86
|
+
@default_newline = if Fluent.windows?
|
87
|
+
"\r\n"
|
88
|
+
else
|
89
|
+
"\n"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
85
93
|
sub_test_case 'initialize' do
|
86
94
|
data(
|
87
95
|
'file is not passed' => %w(),
|
@@ -138,7 +146,7 @@ class TestHead < TestBaseCommand
|
|
138
146
|
create_message_packed_file(@file_name, [event_time(@t).to_i] * 6, [@record] * 6)
|
139
147
|
head = BinlogReaderCommand::Head.new(argv)
|
140
148
|
out = capture_stdout { head.call }
|
141
|
-
assert_equal "2011-01-02T13:14:15+00:00\t#{TMP_DIR}/#{@file_name}\t#{Yajl.dump(@record)}
|
149
|
+
assert_equal "2011-01-02T13:14:15+00:00\t#{TMP_DIR}/#{@file_name}\t#{Yajl.dump(@record)}#{@default_newline}" * 5, out
|
142
150
|
end
|
143
151
|
end
|
144
152
|
|
@@ -149,7 +157,7 @@ class TestHead < TestBaseCommand
|
|
149
157
|
create_message_packed_file(@file_name, [event_time(@t).to_i] * 6, [@record] * 6)
|
150
158
|
head = BinlogReaderCommand::Head.new(argv)
|
151
159
|
out = capture_stdout { head.call }
|
152
|
-
assert_equal "2011-01-02T13:14:15+00:00\t#{TMP_DIR}/#{@file_name}\t#{Yajl.dump(@record)}
|
160
|
+
assert_equal "2011-01-02T13:14:15+00:00\t#{TMP_DIR}/#{@file_name}\t#{Yajl.dump(@record)}#{@default_newline}", out
|
153
161
|
end
|
154
162
|
end
|
155
163
|
|
@@ -169,7 +177,7 @@ class TestHead < TestBaseCommand
|
|
169
177
|
create_message_packed_file(@file_name, [event_time(@t).to_i], [@record])
|
170
178
|
head = BinlogReaderCommand::Head.new(argv)
|
171
179
|
out = capture_stdout { head.call }
|
172
|
-
assert_equal "#{Yajl.dump(@record)}
|
180
|
+
assert_equal "#{Yajl.dump(@record)}#{@default_newline}", out
|
173
181
|
end
|
174
182
|
end
|
175
183
|
|
@@ -198,6 +206,14 @@ class TestHead < TestBaseCommand
|
|
198
206
|
end
|
199
207
|
|
200
208
|
class TestCat < TestBaseCommand
|
209
|
+
setup do
|
210
|
+
@default_newline = if Fluent.windows?
|
211
|
+
"\r\n"
|
212
|
+
else
|
213
|
+
"\n"
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
201
217
|
sub_test_case 'initialize' do
|
202
218
|
data(
|
203
219
|
'file is not passed' => [],
|
@@ -254,7 +270,7 @@ class TestCat < TestBaseCommand
|
|
254
270
|
create_message_packed_file(@file_name, [event_time(@t).to_i] * 6, [@record] * 6)
|
255
271
|
head = BinlogReaderCommand::Cat.new(argv)
|
256
272
|
out = capture_stdout { head.call }
|
257
|
-
assert_equal "2011-01-02T13:14:15+00:00\t#{TMP_DIR}/#{@file_name}\t#{Yajl.dump(@record)}
|
273
|
+
assert_equal "2011-01-02T13:14:15+00:00\t#{TMP_DIR}/#{@file_name}\t#{Yajl.dump(@record)}#{@default_newline}" * 6, out
|
258
274
|
end
|
259
275
|
end
|
260
276
|
|
@@ -265,7 +281,7 @@ class TestCat < TestBaseCommand
|
|
265
281
|
create_message_packed_file(@file_name, [event_time(@t).to_i] * 6, [@record] * 6)
|
266
282
|
head = BinlogReaderCommand::Cat.new(argv)
|
267
283
|
out = capture_stdout { head.call }
|
268
|
-
assert_equal "2011-01-02T13:14:15+00:00\t#{TMP_DIR}/#{@file_name}\t#{Yajl.dump(@record)}
|
284
|
+
assert_equal "2011-01-02T13:14:15+00:00\t#{TMP_DIR}/#{@file_name}\t#{Yajl.dump(@record)}#{@default_newline}", out
|
269
285
|
end
|
270
286
|
end
|
271
287
|
|
@@ -276,7 +292,7 @@ class TestCat < TestBaseCommand
|
|
276
292
|
create_message_packed_file(@file_name, [event_time(@t).to_i], [@record])
|
277
293
|
head = BinlogReaderCommand::Cat.new(argv)
|
278
294
|
out = capture_stdout { head.call }
|
279
|
-
assert_equal "#{Yajl.dump(@record)}
|
295
|
+
assert_equal "#{Yajl.dump(@record)}#{@default_newline}", out
|
280
296
|
end
|
281
297
|
end
|
282
298
|
|