-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add tcp/udp check connection input plugin
- Loading branch information
1 parent
85594cc
commit 160a2d0
Showing
4 changed files
with
483 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
# Example Input Plugin | ||
|
||
The input plugin test UDP/TCP connections response time. | ||
It can also check response text. | ||
|
||
### Configuration: | ||
|
||
``` | ||
# List of UDP/TCP connections you want to check | ||
[[inputs.net_response]] | ||
protocol = "tcp" | ||
# Server address (default IP localhost) | ||
address = "github.com:80" | ||
# Set timeout (default 1.0) | ||
timeout = 1.0 | ||
# Set read timeout (default 1.0) | ||
read_timeout = 1.0 | ||
# String sent to the server | ||
send = "ssh" | ||
# Expected string in answer | ||
expect = "ssh" | ||
[[inputs.net_response]] | ||
protocol = "tcp" | ||
address = ":80" | ||
[[inputs.net_response]] | ||
protocol = "udp" | ||
# Server address (default IP localhost) | ||
address = "github.com:80" | ||
# Set timeout (default 1.0) | ||
timeout = 1.0 | ||
# Set read timeout (default 1.0) | ||
read_timeout = 1.0 | ||
# String sent to the server | ||
send = "ssh" | ||
# Expected string in answer | ||
expect = "ssh" | ||
[[inputs.net_response]] | ||
protocol = "udp" | ||
address = "localhost:161" | ||
timeout = 2.0 | ||
``` | ||
|
||
### Measurements & Fields: | ||
|
||
- net_response | ||
- response_time (float, seconds) | ||
- string_found (bool) # Only if "expected: option is set | ||
|
||
### Tags: | ||
|
||
- All measurements have the following tags: | ||
- host | ||
- port | ||
- protocol | ||
|
||
### Example Output: | ||
|
||
``` | ||
$ ./telegraf -config telegraf.conf -input-filter net_response -test | ||
net_response,host=127.0.0.1,port=22,protocol=tcp response_time=0.18070360500000002,string_found=true 1454785464182527094 | ||
net_response,host=127.0.0.1,port=2222,protocol=tcp response_time=1.090124776,string_found=false 1454784433658942325 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,218 @@ | ||
package net_response | ||
|
||
import ( | ||
"bufio" | ||
"errors" | ||
"net" | ||
"net/textproto" | ||
"regexp" | ||
"time" | ||
|
||
"github.com/influxdata/telegraf" | ||
"github.com/influxdata/telegraf/plugins/inputs" | ||
) | ||
|
||
// NetResponses struct | ||
type NetResponse struct { | ||
Address string | ||
Timeout float64 | ||
ReadTimeout float64 | ||
Send string | ||
Expect string | ||
Protocol string | ||
} | ||
|
||
func (_ *NetResponse) Description() string { | ||
return "Ping given url(s) and return statistics" | ||
} | ||
|
||
var sampleConfig = ` | ||
[[inputs.net_response]] | ||
protocol = "tcp" | ||
# Server address (default IP localhost) | ||
address = "github.com:80" | ||
# Set timeout (default 1.0) | ||
timeout = 1.0 | ||
# Set read timeout (default 1.0) | ||
read_timeout = 1.0 | ||
# String sent to the server | ||
send = "ssh" | ||
# Expected string in answer | ||
expect = "ssh" | ||
[[inputs.net_response]] | ||
protocol = "tcp" | ||
address = ":80" | ||
[[inputs.net_response]] | ||
protocol = "udp" | ||
# Server address (default IP localhost) | ||
address = "github.com:80" | ||
# Set timeout (default 1.0) | ||
timeout = 1.0 | ||
# Set read timeout (default 1.0) | ||
read_timeout = 1.0 | ||
# String sent to the server | ||
send = "ssh" | ||
# Expected string in answer | ||
expect = "ssh" | ||
[[inputs.net_response]] | ||
protocol = "udp" | ||
address = "localhost:161" | ||
timeout = 2.0 | ||
` | ||
|
||
func (_ *NetResponse) SampleConfig() string { | ||
return sampleConfig | ||
} | ||
|
||
func (t *NetResponse) TcpGather() (map[string]interface{}, error) { | ||
// Prepare fields | ||
fields := make(map[string]interface{}) | ||
// Start Timer | ||
start := time.Now() | ||
// Resolving | ||
tcpAddr, err := net.ResolveTCPAddr("tcp", t.Address) | ||
// Connecting | ||
conn, err := net.DialTCP("tcp", nil, tcpAddr) | ||
// Stop timer | ||
responseTime := time.Since(start).Seconds() | ||
// Handle error | ||
if err != nil { | ||
return nil, err | ||
} | ||
defer conn.Close() | ||
// Send string if needed | ||
if t.Send != "" { | ||
msg := []byte(t.Send) | ||
conn.Write(msg) | ||
conn.CloseWrite() | ||
// Stop timer | ||
responseTime = time.Since(start).Seconds() | ||
} | ||
// Read string if needed | ||
if t.Expect != "" { | ||
// Set read timeout | ||
conn.SetReadDeadline(time.Now().Add(time.Duration(t.ReadTimeout) * time.Second)) | ||
// Prepare reader | ||
reader := bufio.NewReader(conn) | ||
tp := textproto.NewReader(reader) | ||
// Read | ||
data, err := tp.ReadLine() | ||
// Stop timer | ||
responseTime = time.Since(start).Seconds() | ||
// Handle error | ||
if err != nil { | ||
fields["string_found"] = false | ||
} else { | ||
// Looking for string in answer | ||
RegEx := regexp.MustCompile(`.*` + t.Expect + `.*`) | ||
find := RegEx.FindString(string(data)) | ||
if find != "" { | ||
fields["string_found"] = true | ||
} else { | ||
fields["string_found"] = false | ||
} | ||
} | ||
|
||
} | ||
fields["response_time"] = responseTime | ||
return fields, nil | ||
} | ||
|
||
func (u *NetResponse) UdpGather() (map[string]interface{}, error) { | ||
// Prepare fields | ||
fields := make(map[string]interface{}) | ||
// Start Timer | ||
start := time.Now() | ||
// Resolving | ||
udpAddr, err := net.ResolveUDPAddr("udp", u.Address) | ||
LocalAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0") | ||
// Connecting | ||
conn, err := net.DialUDP("udp", LocalAddr, udpAddr) | ||
defer conn.Close() | ||
// Handle error | ||
if err != nil { | ||
return nil, err | ||
} | ||
// Send string | ||
msg := []byte(u.Send) | ||
conn.Write(msg) | ||
// Read string | ||
// Set read timeout | ||
conn.SetReadDeadline(time.Now().Add(time.Duration(u.ReadTimeout) * time.Second)) | ||
// Read | ||
buf := make([]byte, 1024) | ||
_, _, err = conn.ReadFromUDP(buf) | ||
// Stop timer | ||
responseTime := time.Since(start).Seconds() | ||
// Handle error | ||
if err != nil { | ||
return nil, err | ||
} else { | ||
// Looking for string in answer | ||
RegEx := regexp.MustCompile(`.*` + u.Expect + `.*`) | ||
find := RegEx.FindString(string(buf)) | ||
if find != "" { | ||
fields["string_found"] = true | ||
} else { | ||
fields["string_found"] = false | ||
} | ||
} | ||
fields["response_time"] = responseTime | ||
return fields, nil | ||
} | ||
|
||
func (c *NetResponse) Gather(acc telegraf.Accumulator) error { | ||
// Set default values | ||
if c.Timeout == 0 { | ||
c.Timeout = 1.0 | ||
} | ||
if c.ReadTimeout == 0 { | ||
c.ReadTimeout = 1.0 | ||
} | ||
// Check send and expected string | ||
if c.Protocol == "udp" && c.Send == "" { | ||
return errors.New("Send string cannot be empty") | ||
} | ||
if c.Protocol == "udp" && c.Expect == "" { | ||
return errors.New("Expected string cannot be empty") | ||
} | ||
// Prepare host and port | ||
host, port, err := net.SplitHostPort(c.Address) | ||
if err != nil { | ||
return err | ||
} | ||
if host == "" { | ||
c.Address = "localhost:" + port | ||
} | ||
if port == "" { | ||
return errors.New("Bad port") | ||
} | ||
// Prepare data | ||
tags := map[string]string{"host": host, "port": port} | ||
var fields map[string]interface{} | ||
// Gather data | ||
if c.Protocol == "tcp" { | ||
fields, err = c.TcpGather() | ||
tags["protocol"] = "tcp" | ||
} else if c.Protocol == "udp" { | ||
fields, err = c.UdpGather() | ||
tags["protocol"] = "udp" | ||
} else { | ||
return errors.New("Bad protocol") | ||
} | ||
if err != nil { | ||
return err | ||
} | ||
// Add metrics | ||
acc.AddFields("net_response", fields, tags) | ||
return nil | ||
} | ||
|
||
func init() { | ||
inputs.Add("net_response", func() telegraf.Input { | ||
return &NetResponse{} | ||
}) | ||
} |
Oops, something went wrong.