Skip to content

Commit 58e3730

Browse files
author
Matthias Rampke
committed
Import example app from juliusv/prometheus_workshop
1 parent 43b9726 commit 58e3730

File tree

3 files changed

+166
-0
lines changed

3 files changed

+166
-0
lines changed

example_golang/client.go

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"flag"
6+
"math"
7+
"net/http"
8+
"time"
9+
)
10+
11+
var oscillationPeriod = flag.Duration("oscillation-period", 5*time.Minute, "The duration of the rate oscillation period.")
12+
13+
func startClient(servAddr string) {
14+
15+
oscillationFactor := func() float64 {
16+
return 2 + math.Sin(math.Sin(2*math.Pi*float64(time.Since(start))/float64(*oscillationPeriod)))
17+
}
18+
19+
ignoreRequest := func(resp *http.Response, err error) {
20+
if err != nil {
21+
return
22+
}
23+
resp.Body.Close()
24+
}
25+
26+
// GET /api/foo.
27+
go func() {
28+
for {
29+
ignoreRequest(http.Get("http://" + servAddr + "/api/foo"))
30+
time.Sleep(time.Duration(10*oscillationFactor()) * time.Millisecond)
31+
}
32+
}()
33+
// POST /api/foo.
34+
go func() {
35+
for {
36+
ignoreRequest(http.Post("http://"+servAddr+"/api/foo", "text/plain", &bytes.Buffer{}))
37+
time.Sleep(time.Duration(150*oscillationFactor()) * time.Millisecond)
38+
}
39+
}()
40+
// GET /api/bar.
41+
go func() {
42+
for {
43+
ignoreRequest(http.Get("http://" + servAddr + "/api/bar"))
44+
time.Sleep(time.Duration(20*oscillationFactor()) * time.Millisecond)
45+
}
46+
}()
47+
// POST /api/bar.
48+
go func() {
49+
for {
50+
ignoreRequest(http.Post("http://"+servAddr+"/api/bar", "text/plain", &bytes.Buffer{}))
51+
time.Sleep(time.Duration(100*oscillationFactor()) * time.Millisecond)
52+
}
53+
}()
54+
// GET /api/nonexistent.
55+
go func() {
56+
for {
57+
ignoreRequest(http.Get("http://" + servAddr + "/api/nonexistent"))
58+
time.Sleep(time.Duration(500*oscillationFactor()) * time.Millisecond)
59+
}
60+
}()
61+
}

example_golang/main.go

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"net/http"
6+
"os"
7+
"time"
8+
9+
"github.com/justinas/alice"
10+
"github.com/streadway/handy/report"
11+
)
12+
13+
var (
14+
addr = flag.String("listen-address", ":8080", "The address to listen on for HTTP requests.")
15+
16+
start = time.Now()
17+
)
18+
19+
func main() {
20+
flag.Parse()
21+
22+
http.HandleFunc("/api/", handleAPI)
23+
24+
// Log every received HTTP request to stdout.
25+
go http.ListenAndServe(*addr, alice.New(
26+
report.JSONMiddleware(os.Stdout),
27+
).Then(http.DefaultServeMux))
28+
29+
startClient(*addr)
30+
31+
select {}
32+
}

example_golang/server.go

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package main
2+
3+
import (
4+
"math/rand"
5+
"net/http"
6+
_ "net/http/pprof"
7+
"time"
8+
)
9+
10+
type responseOpts struct {
11+
baseLatency time.Duration
12+
errorRatio float64
13+
14+
// Whenever 10*outageDuration has passed, an outage will be simulated
15+
// that lasts for outageDuration. During the outage, errorRatio is
16+
// increased by a factor of 10, and baseLatency by a factor of 3. At
17+
// start-up time, an outage is simulated, too (so that you can see the
18+
// effects right ahead and don't have to wait for 10*outageDuration).
19+
outageDuration time.Duration
20+
}
21+
22+
var opts = map[string]map[string]responseOpts{
23+
"/api/foo": map[string]responseOpts{
24+
"GET": responseOpts{
25+
baseLatency: 10 * time.Millisecond,
26+
errorRatio: 0.005,
27+
outageDuration: 23 * time.Second,
28+
},
29+
"POST": responseOpts{
30+
baseLatency: 20 * time.Millisecond,
31+
errorRatio: 0.02,
32+
outageDuration: time.Minute,
33+
},
34+
},
35+
"/api/bar": map[string]responseOpts{
36+
"GET": responseOpts{
37+
baseLatency: 15 * time.Millisecond,
38+
errorRatio: 0.0025,
39+
outageDuration: 13 * time.Second,
40+
},
41+
"POST": responseOpts{
42+
baseLatency: 50 * time.Millisecond,
43+
errorRatio: 0.01,
44+
outageDuration: 47 * time.Second,
45+
},
46+
},
47+
}
48+
49+
func handleAPI(w http.ResponseWriter, r *http.Request) {
50+
pathOpts, ok := opts[r.URL.Path]
51+
if !ok {
52+
http.Error(w, "Not Found", http.StatusNotFound)
53+
return
54+
}
55+
methodOpts, ok := pathOpts[r.Method]
56+
if !ok {
57+
http.Error(w, "Method not Allowed", http.StatusMethodNotAllowed)
58+
return
59+
}
60+
61+
latencyFactor := time.Duration(1)
62+
errorFactor := 1.
63+
if time.Since(start)%(10*methodOpts.outageDuration) < methodOpts.outageDuration {
64+
latencyFactor *= 3
65+
errorFactor *= 10
66+
}
67+
time.Sleep(
68+
(methodOpts.baseLatency + time.Duration(rand.NormFloat64()*float64(methodOpts.baseLatency)/10)) * latencyFactor,
69+
)
70+
if rand.Float64() <= methodOpts.errorRatio*errorFactor {
71+
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
72+
}
73+
}

0 commit comments

Comments
 (0)