Skip to content

Commit a7b7596

Browse files
committed
New write_behavior setting.
This setting introduces a new behavior to allow each event to overwrite the entire file. The default behavior (append) is unchanged. Fixes #24
1 parent 77657eb commit a7b7596

File tree

3 files changed

+64
-1
lines changed

3 files changed

+64
-1
lines changed

lib/logstash/outputs/file.rb

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# encoding: utf-8
22
require "logstash/namespace"
33
require "logstash/outputs/base"
4+
require "flores/random"
45
require "logstash/errors"
56
require "zlib"
67

@@ -66,6 +67,16 @@ class LogStash::Outputs::File < LogStash::Outputs::Base
6667
# Example: `"file_mode" => 0640`
6768
config :file_mode, :validate => :number, :default => -1
6869

70+
71+
# How should the file be written?
72+
#
73+
# If `append`, the file will be opened for appending and each new event will
74+
# be written at the end of the file.
75+
#
76+
# If `overwrite`, the file will be truncated before writing and only the most
77+
# recent event will appear in the file.
78+
config :write_behavior, :validate => [ "overwrite", "append" ], :default => "append"
79+
6980
default :codec, "json_lines"
7081

7182
public
@@ -130,7 +141,14 @@ def multi_receive_encoded(events_and_encoded)
130141
@io_mutex.synchronize do
131142
encoded_by_path.each do |path,chunks|
132143
fd = open(path)
133-
chunks.each {|chunk| fd.write(chunk) }
144+
if @write_behavior == "overwrite"
145+
fd.truncate(0)
146+
fd.seek(0, IO::SEEK_SET)
147+
fd.write(chunks.last)
148+
else
149+
# append to the file
150+
chunks.each {|chunk| fd.write(chunk) }
151+
end
134152
fd.flush
135153
end
136154

logstash-output-file.gemspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@ Gem::Specification.new do |s|
2525
s.add_runtime_dependency 'logstash-codec-line'
2626

2727
s.add_development_dependency 'logstash-devutils'
28+
s.add_development_dependency 'flores'
2829
s.add_development_dependency 'logstash-input-generator'
2930
end

spec/outputs/file_spec.rb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
require "logstash/devutils/rspec/spec_helper"
33
require "logstash/outputs/file"
44
require "logstash/codecs/line"
5+
require "logstash/codecs/json_lines"
56
require "logstash/event"
67
require "logstash/json"
78
require "stud/temporary"
@@ -111,6 +112,49 @@
111112

112113
describe "receiving events" do
113114

115+
context "when write_behavior => 'overwrite'" do
116+
let(:tmp) { Stud::Temporary.pathname }
117+
let(:config) {
118+
{
119+
"write_behavior" => "overwrite",
120+
"path" => tmp,
121+
"codec" => LogStash::Codecs::JSONLines.new
122+
}
123+
}
124+
let(:output) { LogStash::Outputs::File.new(config) }
125+
126+
let(:count) { Flores::Random.integer(1..10) }
127+
let(:events) do
128+
Flores::Random.iterations(1..10).collect do |i|
129+
LogStash::Event.new("value" => i)
130+
end
131+
end
132+
133+
before do
134+
output.register
135+
end
136+
137+
after do
138+
File.unlink(tmp) if File.exist?(tmp)
139+
end
140+
141+
it "should write only the last event of a batch" do
142+
output.multi_receive(events)
143+
result = LogStash::Json.load(File.read(tmp))
144+
expect(result["value"]).to be == events.last.get("value")
145+
end
146+
147+
context "the file" do
148+
it "should only contain the last event received" do
149+
events.each do |event|
150+
output.multi_receive([event])
151+
result = LogStash::Json.load(File.read(tmp))
152+
expect(result["value"]).to be == event.get("value")
153+
end
154+
end
155+
end
156+
end
157+
114158
context "when the output file is deleted" do
115159

116160
let(:temp_file) { Tempfile.new('logstash-spec-output-file_deleted') }

0 commit comments

Comments
 (0)