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

Add tag(s) DNS lookup time out. #67

Merged
merged 9 commits into from
Jan 26, 2023
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
Gemfile.lock
.bundle
vendor
.idea
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 3.2.0
- Support adding tag(s) on DNS lookup times out, defaults to `["_dnstimeout"]` [#67](https://github.com/logstash-plugins/logstash-filter-dns/pull/67)
- As timeouts can be received through tags now, DNS lookup timeouts are logged in debug logs only. [#67](https://github.com/logstash-plugins/logstash-filter-dns/pull/67)

## 3.1.5
- Fixed an issue where a non-string value existing in the resolve/reverse field could cause the plugin to crash [#65](https://github.com/logstash-plugins/logstash-filter-dns/pull/65)

Expand Down
8 changes: 8 additions & 0 deletions docs/index.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ This plugin supports the following configuration options plus the <<plugins-{typ
| <<plugins-{type}s-{plugin}-nameserver>> |<<hash,hash>>|No
| <<plugins-{type}s-{plugin}-resolve>> |<<array,array>>|No
| <<plugins-{type}s-{plugin}-reverse>> |<<array,array>>|No
| <<plugins-{type}s-{plugin}-tag_on_timeout>> |<<array,array>>|No
| <<plugins-{type}s-{plugin}-timeout>> |<<number,number>>|No
|=======================================================================

Expand Down Expand Up @@ -173,6 +174,13 @@ Reverse resolve one or more fields.

`resolv` calls will be wrapped in a timeout instance

[id="plugins-{type}s-{plugin}-tag_on_timeout"]
===== `tag_on_timeout`

* Value type is <<array,array>>
* Defaults to `["_dnstimeout"]`.

Add tag(s) on DNS lookup time out.


[id="plugins-{type}s-{plugin}-common-options"]
Expand Down
11 changes: 8 additions & 3 deletions lib/logstash/filters/dns.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ class LogStash::Filters::DNS < LogStash::Filters::Base
# Use custom hosts file(s). For example: `["/var/db/my_custom_hosts"]`
config :hostsfile, :validate => :array

# Tag(s) to apply if a DNS lookup times out. Defaults to `["_dnstimeout"]`.
config :tag_on_timeout, :validate => :string, :list => true, :default => ["_dnstimeout"]

attr_reader :hit_cache
attr_reader :failed_cache

Expand Down Expand Up @@ -219,8 +222,9 @@ def resolve(event)
end
rescue Resolv::ResolvTimeout
@failed_cache[raw] = true if @failed_cache
@logger.warn("DNS: timeout on resolving the hostname.",
@logger.debug("DNS: timeout on resolving the hostname.",

Choose a reason for hiding this comment

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

Ok I think it is fair to say that changing the log level is not a breaking change, and we need to re-evalute in the future how we handle logging for event processing, so I'm fine leaving this as debug.

:field => field, :value => raw)
@tag_on_timeout.each { |tag| event.tag(tag) }
return
rescue SocketError => e
@logger.error("DNS: Encountered SocketError.",
Expand Down Expand Up @@ -305,8 +309,9 @@ def reverse(event)
end
rescue Resolv::ResolvTimeout
@failed_cache[raw] = true if @failed_cache
@logger.warn("DNS: timeout on resolving address.",
@logger.debug("DNS: timeout on resolving address.",
:field => field, :value => raw)
@tag_on_timeout.each { |tag| event.tag(tag) }
return
rescue SocketError => e
@logger.error("DNS: Encountered SocketError.",
Expand Down Expand Up @@ -345,7 +350,7 @@ def retriable_request(&block)
tries = 0
begin
block.call
rescue Resolv::ResolvTimeout, SocketError
rescue Resolv::ResolvTimeout, SocketError
if tries < @max_retries
tries = tries + 1
retry
Expand Down
2 changes: 1 addition & 1 deletion logstash-filter-dns.gemspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Gem::Specification.new do |s|

s.name = 'logstash-filter-dns'
s.version = '3.1.5'
s.version = '3.2.0'
s.licenses = ['Apache License (2.0)']
s.summary = "Performs a standard or reverse DNS lookup"
s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"
Expand Down
112 changes: 112 additions & 0 deletions spec/filters/dns_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@


describe LogStash::Filters::DNS do

describe "with stubbed Resolv" do
before(:each) do
# We use `Resolv#each_address` and `Resolv#each_name`, which have
Expand Down Expand Up @@ -621,4 +622,115 @@
end
end
end

describe "dns forward timeout" do

let(:subject) { LogStash::Filters::DNS.new(config) }

before(:each) do
allow(subject).to receive(:getaddress).and_raise(Resolv::ResolvTimeout)
subject.register
subject.filter(event)
end

context "when using the default tag" do
let(:config) { { "resolve" => ["message"] } }
let(:event) { LogStash::Event.new("message" => "carrera.databits.net") }

it "should add the default DNS timeout tag" do
expect(event.get("tags")).to eq(["_dnstimeout"])
end
end

context "when using a custom tag" do
let(:config) { { "resolve" => ["message"], "tag_on_timeout" => ["dns_custom_timeout"] } }
let(:event) { LogStash::Event.new("message" => "carrera.databits.net") }

it "should add the custom DNS timeout tag" do
expect(event.get("tags")).to eq(["dns_custom_timeout"])
end
end

context "when using no tags" do
let(:config) { { "resolve" => ["message"], "tag_on_timeout" => [] } }
let(:event) { LogStash::Event.new("message" => "carrera.databits.net") }

it "should not add any failure tags" do
expect(event.get("tags")).to eq(nil)
end
end

context "when logging" do

context "with debug" do
let(:config) { { "resolve" => ["message"] } }
let(:event) { LogStash::Event.new("message" => "127.0.0.1") }

before do
allow(subject.logger).to receive(:debug).with(any_args)
end

it "logs on timeout exception" do
subject.filter(event)
expect(subject.logger).to have_received(:debug).with("DNS: timeout on resolving the hostname.", :field => "message", :value => "127.0.0.1")
end
end
end
end

describe "dns reverse timeout" do

let(:subject) { LogStash::Filters::DNS.new(config) }

before(:each) do
allow(subject).to receive(:getname).and_raise(Resolv::ResolvTimeout)
subject.register
subject.filter(event)
end

context "when using the default tag" do
let(:config) { { "reverse" => ["message"] } }
let(:event) { LogStash::Event.new("message" => "127.0.0.1") }

it "should add the default DNS timeout tag" do
expect(event.get("tags")).to eq(["_dnstimeout"])
end
end

context "when using a custom tag" do
let(:config) { { "reverse" => ["message"], "tag_on_timeout" => ["dns_custom_timeout"] } }
let(:event) { LogStash::Event.new("message" => "127.0.0.1") }

it "should add the custom DNS timeout tag" do
expect(event.get("tags")).to eq(["dns_custom_timeout"])
end
end

context "when using no tags" do
let(:config) { { "reverse" => ["message"], "tag_on_timeout" => [] } }
let(:event) { LogStash::Event.new("message" => "127.0.0.1") }

it "should not add any failure tags" do
expect(event.get("tags")).to eq(nil)
end
end

context "when logging" do

context "with debug" do
let(:config) { { "reverse" => ["message"] } }
let(:event) { LogStash::Event.new("message" => "127.0.0.1") }

before do
allow(subject.logger).to receive(:debug).with(any_args)
end

it "logs timeout exception" do
subject.filter(event)
expect(subject.logger).to have_received(:debug).with("DNS: timeout on resolving address.", :field => "message", :value => "127.0.0.1")
end
end
end
end

end