diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b79b64dc..1a55c029c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Features - [#727](https://github.com/influxdata/telegraf/pull/727): riak input, thanks @jcoene! +- [#694](https://github.com/influxdata/telegraf/pull/694): DNS Query input, thanks @mjasion! ### Bugfixes diff --git a/Makefile b/Makefile index 84b3a1fe0..ef316bd03 100644 --- a/Makefile +++ b/Makefile @@ -105,4 +105,4 @@ test-short: vet vet: go vet ./... -.PHONY: test +.PHONY: test test-short vet build default diff --git a/README.md b/README.md index 34a3df7ed..001974ba3 100644 --- a/README.md +++ b/README.md @@ -157,8 +157,7 @@ Currently implemented sources: * bcache * couchdb * disque -* dns - * query time +* dns query time * docker * dovecot * elasticsearch diff --git a/plugins/inputs/all/all.go b/plugins/inputs/all/all.go index e6cf6b377..5af18fcff 100644 --- a/plugins/inputs/all/all.go +++ b/plugins/inputs/all/all.go @@ -6,7 +6,7 @@ import ( _ "github.com/influxdata/telegraf/plugins/inputs/bcache" _ "github.com/influxdata/telegraf/plugins/inputs/couchdb" _ "github.com/influxdata/telegraf/plugins/inputs/disque" - _ "github.com/influxdata/telegraf/plugins/inputs/dns" + _ "github.com/influxdata/telegraf/plugins/inputs/dns_query" _ "github.com/influxdata/telegraf/plugins/inputs/docker" _ "github.com/influxdata/telegraf/plugins/inputs/dovecot" _ "github.com/influxdata/telegraf/plugins/inputs/elasticsearch" diff --git a/plugins/inputs/dns/README.md b/plugins/inputs/dns_query/README.md similarity index 55% rename from plugins/inputs/dns/README.md rename to plugins/inputs/dns_query/README.md index 564743d9c..34b285c37 100644 --- a/plugins/inputs/dns/README.md +++ b/plugins/inputs/dns_query/README.md @@ -7,45 +7,45 @@ The DNS plugin gathers dns query times in miliseconds - like [Dig](https://en.wi ``` # Sample Config: [[inputs.dns_query]] - ### Domains or subdomains to query - domains = ["mjasion.pl"] # required - - ### servers to query + ## servers to query servers = ["8.8.8.8"] # required - ### Query record type. Posible values: A, CNAME, MX, TXT, NS. Default is "A" - recordType = "A" # optional + ## Domains or subdomains to query. "." (root) is default + domains = ["."] # optional - ### Dns server port. 53 is default + ## Query record type. Posible values: A, AAAA, ANY, CNAME, MX, NS, PTR, SOA, SPF, SRV, TXT. Default is "NS" + record_type = "A" # optional + + ## Dns server port. 53 is default port = 53 # optional - ### Query timeout in seconds. Default is 2 seconds + ## Query timeout in seconds. Default is 2 seconds timeout = 2 # optional ``` For querying more than one record type make: - + ``` [[inputs.dns_query]] domains = ["mjasion.pl"] servers = ["8.8.8.8", "8.8.4.4"] - recordType = "A" + record_type = "A" [[inputs.dns_query]] domains = ["mjasion.pl"] servers = ["8.8.8.8", "8.8.4.4"] - recordType = "MX" + record_type = "MX" ``` ### Tags: -- server +- server - domain -- recordType +- record_type ### Example output: ``` ./telegraf -config telegraf.conf -test -input-filter dns_query -test -> dns,domain=mjasion.pl,record_type=A,server=8.8.8.8 query_time_ms=36.327025 1455548824989943491 +> dns_query,domain=mjasion.pl,record_type=A,server=8.8.8.8 query_time_ms=67.189842 1456082743585760680 ``` diff --git a/plugins/inputs/dns/dns_query.go b/plugins/inputs/dns_query/dns_query.go similarity index 70% rename from plugins/inputs/dns/dns_query.go rename to plugins/inputs/dns_query/dns_query.go index 5ca58d880..397482a98 100644 --- a/plugins/inputs/dns/dns_query.go +++ b/plugins/inputs/dns_query/dns_query.go @@ -1,4 +1,4 @@ -package dns +package dns_query import ( "errors" @@ -11,7 +11,7 @@ import ( "time" ) -type Dns struct { +type DnsQuery struct { // Domains or subdomains to query Domains []string @@ -29,30 +29,30 @@ type Dns struct { } var sampleConfig = ` - ### Domains or subdomains to query - domains = ["mjasion.pl"] # required - - ### servers to query + ## servers to query servers = ["8.8.8.8"] # required - ### Query record type. Posible values: A, AAAA, CNAME, MX, TXT, NS, ANY. Default is "A" + ## Domains or subdomains to query. "."(root) is default + domains = ["."] # optional + + ## Query record type. Posible values: A, AAAA, CNAME, MX, NS, PTR, TXT, SOA, SPF, SRV. Default is "NS" record_type = "A" # optional - ### Dns server port. 53 is default + ## Dns server port. 53 is default port = 53 # optional - ### Query timeout in seconds. Default is 2 seconds + ## Query timeout in seconds. Default is 2 seconds timeout = 2 # optional ` -func (d *Dns) SampleConfig() string { +func (d *DnsQuery) SampleConfig() string { return sampleConfig } -func (d *Dns) Description() string { +func (d *DnsQuery) Description() string { return "Query given DNS server and gives statistics" } -func (d *Dns) Gather(acc telegraf.Accumulator) error { +func (d *DnsQuery) Gather(acc telegraf.Accumulator) error { d.setDefaultValues() for _, domain := range d.Domains { for _, server := range d.Servers { @@ -67,26 +67,33 @@ func (d *Dns) Gather(acc telegraf.Accumulator) error { } fields := map[string]interface{}{"query_time_ms": dnsQueryTime} - acc.AddFields("dns", fields, tags) + acc.AddFields("dns_query", fields, tags) } } return nil } -func (d *Dns) setDefaultValues() { +func (d *DnsQuery) setDefaultValues() { if len(d.RecordType) == 0 { - d.RecordType = "A" + d.RecordType = "NS" } + + if len(d.Domains) == 0 { + d.Domains = []string{"."} + d.RecordType = "NS" + } + if d.Port == 0 { d.Port = 53 } + if d.Timeout == 0 { d.Timeout = 2 } } -func (d *Dns) getDnsQueryTime(domain string, server string) (float64, error) { +func (d *DnsQuery) getDnsQueryTime(domain string, server string) (float64, error) { dnsQueryTime := float64(0) c := new(dns.Client) @@ -111,7 +118,7 @@ func (d *Dns) getDnsQueryTime(domain string, server string) (float64, error) { return dnsQueryTime, nil } -func (d *Dns) parseRecordType() (uint16, error) { +func (d *DnsQuery) parseRecordType() (uint16, error) { var recordType uint16 var error error @@ -128,6 +135,14 @@ func (d *Dns) parseRecordType() (uint16, error) { recordType = dns.TypeMX case "NS": recordType = dns.TypeNS + case "PTR": + recordType = dns.TypePTR + case "SOA": + recordType = dns.TypeSOA + case "SPF": + recordType = dns.TypeSPF + case "SRV": + recordType = dns.TypeSRV case "TXT": recordType = dns.TypeTXT default: @@ -139,6 +154,6 @@ func (d *Dns) parseRecordType() (uint16, error) { func init() { inputs.Add("dns_query", func() telegraf.Input { - return &Dns{} + return &DnsQuery{} }) } diff --git a/plugins/inputs/dns/dns_query_test.go b/plugins/inputs/dns_query/dns_query_test.go similarity index 52% rename from plugins/inputs/dns/dns_query_test.go rename to plugins/inputs/dns_query/dns_query_test.go index 44a62d708..ff923dae3 100644 --- a/plugins/inputs/dns/dns_query_test.go +++ b/plugins/inputs/dns_query/dns_query_test.go @@ -1,4 +1,4 @@ -package dns +package dns_query import ( "github.com/influxdata/telegraf/testutil" @@ -12,21 +12,21 @@ var servers = []string{"8.8.8.8"} var domains = []string{"mjasion.pl"} func TestGathering(t *testing.T) { - var dnsConfig = Dns{ + var dnsConfig = DnsQuery{ Servers: servers, Domains: domains, } var acc testutil.Accumulator dnsConfig.Gather(&acc) - metric, _ := acc.Get("dns") + metric, _ := acc.Get("dns_query") queryTime, _ := metric.Fields["query_time_ms"].(float64) assert.NotEqual(t, 0, queryTime) } func TestGatheringMxRecord(t *testing.T) { - var dnsConfig = Dns{ + var dnsConfig = DnsQuery{ Servers: servers, Domains: domains, } @@ -34,14 +34,36 @@ func TestGatheringMxRecord(t *testing.T) { dnsConfig.RecordType = "MX" dnsConfig.Gather(&acc) - metric, _ := acc.Get("dns") + metric, _ := acc.Get("dns_query") queryTime, _ := metric.Fields["query_time_ms"].(float64) assert.NotEqual(t, 0, queryTime) } +func TestGatheringRootDomain(t *testing.T) { + var dnsConfig = DnsQuery{ + Servers: servers, + Domains: []string{"."}, + RecordType: "MX", + } + var acc testutil.Accumulator + tags := map[string]string{ + "server": "8.8.8.8", + "domain": ".", + "record_type": "MX", + } + fields := map[string]interface{}{} + + dnsConfig.Gather(&acc) + metric, _ := acc.Get("dns_query") + queryTime, _ := metric.Fields["query_time_ms"].(float64) + + fields["query_time_ms"] = queryTime + acc.AssertContainsTaggedFields(t, "dns_query", fields, tags) +} + func TestMetricContainsServerAndDomainAndRecordTypeTags(t *testing.T) { - var dnsConfig = Dns{ + var dnsConfig = DnsQuery{ Servers: servers, Domains: domains, } @@ -49,20 +71,20 @@ func TestMetricContainsServerAndDomainAndRecordTypeTags(t *testing.T) { tags := map[string]string{ "server": "8.8.8.8", "domain": "mjasion.pl", - "record_type": "A", + "record_type": "NS", } fields := map[string]interface{}{} dnsConfig.Gather(&acc) - metric, _ := acc.Get("dns") + metric, _ := acc.Get("dns_query") queryTime, _ := metric.Fields["query_time_ms"].(float64) fields["query_time_ms"] = queryTime - acc.AssertContainsTaggedFields(t, "dns", fields, tags) + acc.AssertContainsTaggedFields(t, "dns_query", fields, tags) } func TestGatheringTimeout(t *testing.T) { - var dnsConfig = Dns{ + var dnsConfig = DnsQuery{ Servers: servers, Domains: domains, } @@ -87,49 +109,76 @@ func TestGatheringTimeout(t *testing.T) { } func TestSettingDefaultValues(t *testing.T) { - dnsConfig := Dns{} + dnsConfig := DnsQuery{} dnsConfig.setDefaultValues() - assert.Equal(t, "A", dnsConfig.RecordType, "Default record type not equal 'A'") + assert.Equal(t, []string{"."}, dnsConfig.Domains, "Default domain not equal \".\"") + assert.Equal(t, "NS", dnsConfig.RecordType, "Default record type not equal 'NS'") assert.Equal(t, 53, dnsConfig.Port, "Default port number not equal 53") assert.Equal(t, 2, dnsConfig.Timeout, "Default timeout not equal 2") + + dnsConfig = DnsQuery{Domains: []string{"."}} + + dnsConfig.setDefaultValues() + + assert.Equal(t, "NS", dnsConfig.RecordType, "Default record type not equal 'NS'") } func TestRecordTypeParser(t *testing.T) { - var dnsConfig = Dns{} + var dnsConfig = DnsQuery{} var recordType uint16 - var err error dnsConfig.RecordType = "A" - recordType, err = dnsConfig.parseRecordType() + recordType, _ = dnsConfig.parseRecordType() assert.Equal(t, dns.TypeA, recordType) dnsConfig.RecordType = "AAAA" - recordType, err = dnsConfig.parseRecordType() + recordType, _ = dnsConfig.parseRecordType() assert.Equal(t, dns.TypeAAAA, recordType) dnsConfig.RecordType = "ANY" - recordType, err = dnsConfig.parseRecordType() + recordType, _ = dnsConfig.parseRecordType() assert.Equal(t, dns.TypeANY, recordType) dnsConfig.RecordType = "CNAME" - recordType, err = dnsConfig.parseRecordType() + recordType, _ = dnsConfig.parseRecordType() assert.Equal(t, dns.TypeCNAME, recordType) dnsConfig.RecordType = "MX" - recordType, err = dnsConfig.parseRecordType() + recordType, _ = dnsConfig.parseRecordType() assert.Equal(t, dns.TypeMX, recordType) dnsConfig.RecordType = "NS" - recordType, err = dnsConfig.parseRecordType() + recordType, _ = dnsConfig.parseRecordType() assert.Equal(t, dns.TypeNS, recordType) + dnsConfig.RecordType = "PTR" + recordType, _ = dnsConfig.parseRecordType() + assert.Equal(t, dns.TypePTR, recordType) + + dnsConfig.RecordType = "SOA" + recordType, _ = dnsConfig.parseRecordType() + assert.Equal(t, dns.TypeSOA, recordType) + + dnsConfig.RecordType = "SPF" + recordType, _ = dnsConfig.parseRecordType() + assert.Equal(t, dns.TypeSPF, recordType) + + dnsConfig.RecordType = "SRV" + recordType, _ = dnsConfig.parseRecordType() + assert.Equal(t, dns.TypeSRV, recordType) + dnsConfig.RecordType = "TXT" - recordType, err = dnsConfig.parseRecordType() + recordType, _ = dnsConfig.parseRecordType() assert.Equal(t, dns.TypeTXT, recordType) +} + +func TestRecordTypeParserError(t *testing.T) { + var dnsConfig = DnsQuery{} + var err error dnsConfig.RecordType = "nil" - recordType, err = dnsConfig.parseRecordType() + _, err = dnsConfig.parseRecordType() assert.Error(t, err) }