forked from tsenart/eagle
/
eagle.go
102 lines (83 loc) · 2.45 KB
/
eagle.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package main
import (
"flag"
"log"
"net/http"
_ "net/http/pprof"
"os"
"strconv"
"time"
"github.com/prometheus/client_golang/prometheus"
)
const (
// defaultRate defines how many requests per second are sent to each
// endpoint.
defaultRate uint64 = 100
// defaultInterval defines how long an ephemeral test should get executed.
// Note that one-off load tests aren't supported at the moment.
defaultInterval = 1 * time.Second
// defaultTimeout defines how long we wait for a request to return.
defaultTimeout = 1 * time.Second
)
var (
HeaderEndpoint = "X-eagle-endpoint"
HeaderTarget = "X-eagle-target"
HeaderTest = "X-eagle-test"
// For Prometheus:
namespace = "eagle"
labelNames = []string{"target", "code", "endpoint"}
)
func main() {
var (
listen = flag.String("listen", ":7800", "Server listen address.")
name = flag.String("test.name", "unknown", "Name of the test to run.")
path = flag.String("test.path", "/", "Path to hit on the targets")
rate = flag.Uint64("test.rate", defaultRate, "Number of requests to send during test duration.")
timeout = flag.Duration("test.timeout", defaultTimeout, "Time until a request is discarded")
ts = targets{}
)
flag.Var(&ts, "test.target", `Target to hit by the test with the following format: -test.target="NAME:address/url"`)
flag.Parse()
if *listen == "" || len(ts) == 0 {
flag.Usage()
os.Exit(1)
}
var (
test = newTest(*name, *path, *rate, defaultInterval, *timeout, ts)
registry = newRegistry(prometheus.Labels{"test": test.name})
resultc = make(chan result)
)
test.run(resultc)
go registry.collect(resultc)
http.Handle("/metrics", prometheus.Handler())
log.Printf("Starting server on %s", *listen)
log.Fatal(http.ListenAndServe(*listen, nil))
}
type registry struct {
latencies *prometheus.SummaryVec
}
func newRegistry(constLabels prometheus.Labels) *registry {
var (
latencies = prometheus.NewSummaryVec(
prometheus.SummaryOpts{
Namespace: namespace,
Name: "request_durations_nanoseconds",
Help: "The total duration of HTTP requests (nanoseconds).",
ConstLabels: constLabels,
},
labelNames,
)
)
prometheus.MustRegister(latencies)
return ®istry{latencies}
}
func (r *registry) collect(resultc chan result) {
for {
rr := <-resultc
for _, t := range rr.results {
r.latencies.
WithLabelValues(rr.target, strconv.Itoa(int(t.Code)), rr.endpoint).
Observe(float64(t.Latency.Nanoseconds()))
}
}
}