Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,29 @@ Create a "targets" file that looks like:
<host>:<port>
<host>:<port>
```
then just `go build smoketcp.go` and `./smoketcp <statsd_host>:<statsd_port>` and boom.

Every second it tests every entry (in parallel), and reports errors and time-to-connection to statsd.
then just:
```
go build smoketcp.go
```

and:
```
./smoketcp --statsdHost <statsdHost> --statsdPort <statsdPort> --bucket <bucket_prefix>
```

The flags are available with --help:
```
./smoketcp --help
Usage of ./smoketcp:
-bucket="smoketcp": Graphite bucket prefix
-debug=false: if true, turn on debugging output
-interval=10: How often to run the tests
-statsdHost="localhost": Statsd Hostname
-statsdPort="8125": Statsd port
-targetFile="targets": File containing the list of targets, ex: server1:80
```

Every ten seconds (configurable with --interval) it tests every entry (in parallel), and reports errors and time-to-connection to statsd.
Statsd then aggregates across the flushInterval (in our case 60s) and stores in graphite per target the errors rate,
and the mean, lower, upper, upper_90 etc values.
60 changes: 36 additions & 24 deletions smoketcp.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"flag"
"fmt"
"github.com/cactus/go-statsd-client/statsd"
"io/ioutil"
Expand All @@ -16,55 +17,66 @@ func dieIfError(err error) {
os.Exit(1)
}
}
func doEvery(d time.Duration, f func(*statsd.Client), s *statsd.Client) {
f(s)

func doEvery(d time.Duration, f func(*statsd.Client, string, bool), s *statsd.Client, targetFile string, debug bool) {
f(s, targetFile, debug)
for _ = range time.Tick(d) {
f(s)
f(s, targetFile, debug)
}
}

func process_targets(s *statsd.Client) {
content, err := ioutil.ReadFile("targets")
func processTargets(s *statsd.Client, targetFile string, debug bool) {
content, err := ioutil.ReadFile(targetFile)
if err != nil {
fmt.Println("couldn't open targets file")
if debug {
fmt.Println("couldn't open targets file:", targetFile)
}
return
}
targets := strings.Split(string(content), "\n")
for _, target := range targets {
if len(target) < 1 {
continue
}
go test(target, s)
go test(target, s, debug)
}
}
func test(target string, s *statsd.Client) {

func test(target string, s *statsd.Client, debug bool) {
tuple := strings.Split(target, ":")
host := tuple[0]
port := tuple[1]
subhost := strings.Replace(host, ".", "_", -1)

pre := time.Now()
conn, err := net.Dial("tcp", target)
if err != nil {
fmt.Println("connect error", target)
s.Inc(fmt.Sprintf("error.%s.dial_failed", target), 1, 1)
if debug {
fmt.Println("connect error:", subhost, port)
}
s.Inc(fmt.Sprintf("%s.%s.dial_failed", subhost, port), 1, 1)
return
}
conn.Close()
duration := time.Since(pre)
tuple := strings.Split(target, ":")
host := strings.Replace(tuple[0], ".", "_", -1)
port := tuple[1]
ms := int64(duration / time.Millisecond)
fmt.Printf("%s.%s.duration %d\n", host, port, ms)
s.Timing(fmt.Sprintf("dial.%s.%s", host, port), ms, 1)
conn.Close()
if debug {
fmt.Printf("%s.%s.duration %d\n", subhost, port, ms)
}
s.Timing(fmt.Sprintf("%s.%s", subhost, port), ms, 1)
}

func main() {
if len(os.Args) == 1 {
fmt.Println("Usage: smoketcp <statsd_host>:<statsd_port>")
os.Exit(1)
}
var statsdHost = flag.String("statsdHost", "localhost", "Statsd Hostname")
var statsdPort = flag.String("statsdPort", "8125", "Statsd port")
var bucket = flag.String("bucket", "smoketcp", "Graphite bucket prefix")
var targetFile = flag.String("targetFile", "targets", "File containing the list of targets, ex: server1:80")
var debug = flag.Bool("debug", false, "if true, turn on debugging output")
var interval = flag.Int("interval", 10, "How often to run the tests")
flag.Parse()

hostname, err := os.Hostname()
dieIfError(err)
s, err := statsd.Dial(os.Args[1], fmt.Sprintf("smoketcp.%s", hostname))
s, err := statsd.Dial(fmt.Sprintf("%s:%s", *statsdHost, *statsdPort), fmt.Sprintf("%s", *bucket))
dieIfError(err)
defer s.Close()
doEvery(time.Second, process_targets, s)
doEvery(time.Duration(*interval)*time.Second, processTargets, s, *targetFile, *debug)
}