Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Copies the beat.hostname field into host #28

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# 2.0.0
- Add support for stream identity, the ID will be generated from beat.id+resource_id or beat.name + beat.source if not present #22 #13
The identity allow the multiline codec to correctly merge string from multiples files.
- Copy the `beat.hostname` field into the `host` field for better compatibility with the other Logstash plugins #28
# 0.9.6
- Fix an issue with rogue events created by buffered codecs #19
# 0.9.5
Expand Down
13 changes: 13 additions & 0 deletions lib/logstash/inputs/beats.rb
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,13 @@ def stop

public
def create_event(map, identity_stream)

# Filebeats uses the `message` key and LSF `line`
target_field = target_field_for_codec ? map.delete(target_field_for_codec) : nil

if target_field.nil?
event = LogStash::Event.new(map)
copy_beat_hostname(event)
decorate(event)
return event
else
Expand All @@ -141,13 +143,24 @@ def create_event(map, identity_stream)
ts = coerce_ts(map.delete("@timestamp"))
decoded["@timestamp"] = ts unless ts.nil?
map.each { |k, v| decoded[k] = v }
copy_beat_hostname(decoded)
decorate(decoded)
return decoded
end
end
return nil
end

# Copies the beat.hostname field into the host field unless
# the host field is already defined
private
def copy_beat_hostname(event)
host = event["beat"] ? event["beat"]["hostname"] : nil
if host && event["host"].nil?
event["host"] = host
end
end

private
def coerce_ts(ts)
return nil if ts.nil?
Expand Down
1 change: 1 addition & 0 deletions logstash-input-beats.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ Gem::Specification.new do |s|
s.add_development_dependency "pry"
s.add_development_dependency "rspec-wait"
s.add_development_dependency "logstash-devutils", "~> 0.0.18"
s.add_development_dependency "logstash-codec-json"
end

48 changes: 48 additions & 0 deletions spec/inputs/beats_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require "stud/temporary"
require "logstash/inputs/beats"
require "logstash/codecs/plain"
require "logstash/codecs/json"
require "logstash/codecs/multiline"
require "logstash/event"
require "lumberjack/beats/client"
Expand Down Expand Up @@ -117,6 +118,53 @@
expect(event).to be_nil
end
end

context "with a beat.hostname field" do
let(:event_map) { {"message" => "hello", "beat" => {"hostname" => "linux01"} } }

it "copies it to the host field" do
event = beats.create_event(event_map, identity_stream)
expect(event["host"]).to eq("linux01")
end
end

context "with a beat.hostname field but without the message" do
let(:event_map) { {"beat" => {"hostname" => "linux01"} } }

it "copies it to the host field" do
event = beats.create_event(event_map, identity_stream)
expect(event["host"]).to eq("linux01")
end
end

context "without a beat.hostname field" do
let(:event_map) { {"message" => "hello", "beat" => {"name" => "linux01"} } }

it "should not add a host field" do
event = beats.create_event(event_map, identity_stream)
expect(event["beat"]["name"]).to eq("linux01")
expect(event["host"]).to be_nil
end
end

context "with a beat.hostname and host fields" do
let(:event_map) { {"message" => "hello", "host" => "linux02", "beat" => {"hostname" => "linux01"} } }

it "should not overwrite host" do
event = beats.create_event(event_map, identity_stream)
expect(event["host"]).to eq("linux02")
end
end

context "with a host field in the message" do
let(:codec) { LogStash::Codecs::JSON.new }
let(:event_map) { {"message" => '{"host": "linux02"}', "beat" => {"hostname" => "linux01"} } }

it "should take the host from the JSON message" do
event = beats.create_event(event_map, identity_stream)
expect(event["host"]).to eq("linux02")
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is only small problem with the tests. We use the message field to check if we should apply a codec or not to the event and theses tests will only trigger the else part of this conditionals. https://github.com/logstash-plugins/logstash-input-beats/pull/28/files#diff-28d8b79a78399c1304c58e81cd3672f2R140

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, good point, I added a test that doesn't have the message field.

end
end
end

Expand Down