Advertisement
Guest User

Untitled

a guest
Jan 8th, 2018
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 5.55 KB | None | 0 0
  1. root@example-app-5b8868d69d-64zjm:/go/src/app# cat client.go
  2. package main
  3.  
  4. import (
  5.     "bytes"
  6.     "flag"
  7.     "math"
  8.     "net/http"
  9.     "time"
  10. )
  11.  
  12. var oscillationPeriod = flag.Duration("oscillation-period", 5*time.Minute, "The duration of the rate oscillation period.")
  13.  
  14. func startClient(servAddr string) {
  15.  
  16.     oscillationFactor := func() float64 {
  17.         return 2 + math.Sin(math.Sin(2*math.Pi*float64(time.Since(start))/float64(*oscillationPeriod)))
  18.     }
  19.  
  20.     ignoreRequest := func(resp *http.Response, err error) {
  21.         if err != nil {
  22.             return
  23.         }
  24.         resp.Body.Close()
  25.     }
  26.  
  27.     // GET /api/foo.
  28.     go func() {
  29.         for {
  30.             ignoreRequest(http.Get("http://" + servAddr + "/api/foo"))
  31.             time.Sleep(time.Duration(10*oscillationFactor()) * time.Millisecond)
  32.         }
  33.     }()
  34.     // POST /api/foo.
  35.     go func() {
  36.         for {
  37.             ignoreRequest(http.Post("http://"+servAddr+"/api/foo", "text/plain", &bytes.Buffer{}))
  38.             time.Sleep(time.Duration(150*oscillationFactor()) * time.Millisecond)
  39.         }
  40.     }()
  41.     // GET /api/bar.
  42.     go func() {
  43.         for {
  44.             ignoreRequest(http.Get("http://" + servAddr + "/api/bar"))
  45.             time.Sleep(time.Duration(20*oscillationFactor()) * time.Millisecond)
  46.         }
  47.     }()
  48.     // POST /api/bar.
  49.     go func() {
  50.         for {
  51.             ignoreRequest(http.Post("http://"+servAddr+"/api/bar", "text/plain", &bytes.Buffer{}))
  52.             time.Sleep(time.Duration(100*oscillationFactor()) * time.Millisecond)
  53.         }
  54.     }()
  55.     // GET /api/nonexistent.
  56.     go func() {
  57.         for {
  58.             ignoreRequest(http.Get("http://" + servAddr + "/api/nonexistent"))
  59.             time.Sleep(time.Duration(500*oscillationFactor()) * time.Millisecond)
  60.         }
  61.     }()
  62. }
  63.  
  64. root@example-app-5b8868d69d-64zjm:/go/src/app# cat server.go
  65. package main
  66.  
  67. import (
  68.     "fmt"
  69.     "math/rand"
  70.     "net/http"
  71.     _ "net/http/pprof"
  72.     "time"
  73.  
  74.     "github.com/prometheus/client_golang/prometheus"
  75. )
  76.  
  77. var (
  78.     namespace = "codelab"
  79.     subsystem = "api"
  80.  
  81.     requestHistogram = prometheus.NewHistogramVec(
  82.         prometheus.HistogramOpts{
  83.             Namespace: namespace,
  84.             Subsystem: subsystem,
  85.             Name:      "request_duration_seconds",
  86.             Help:      "A histogram of the API HTTP request durations in seconds.",
  87.             Buckets:   prometheus.ExponentialBuckets(0.0001, 1.5, 25),
  88.         },
  89.         []string{"method", "path", "status"},
  90.     )
  91.     requestsInProgress = prometheus.NewGauge(
  92.         prometheus.GaugeOpts{
  93.             Namespace: namespace,
  94.             Subsystem: subsystem,
  95.             Name:      "http_requests_in_progress",
  96.             Help:      "The current number of API HTTP requests in progress.",
  97.         })
  98. )
  99.  
  100. func init() {
  101.     prometheus.MustRegister(requestHistogram)
  102.     prometheus.MustRegister(requestsInProgress)
  103. }
  104.  
  105. type responseOpts struct {
  106.     baseLatency time.Duration
  107.     errorRatio  float64
  108.  
  109.     // Whenever 10*outageDuration has passed, an outage will be simulated
  110.     // that lasts for outageDuration. During the outage, errorRatio is
  111.     // increased by a factor of 10, and baseLatency by a factor of 3.  At
  112.     // start-up time, an outage is simulated, too (so that you can see the
  113.     // effects right ahead and don't have to wait for 10*outageDuration).
  114.     outageDuration time.Duration
  115. }
  116.  
  117. var opts = map[string]map[string]responseOpts{
  118.     "/api/foo": map[string]responseOpts{
  119.         "GET": responseOpts{
  120.             baseLatency:    10 * time.Millisecond,
  121.             errorRatio:     0.005,
  122.             outageDuration: 23 * time.Second,
  123.         },
  124.         "POST": responseOpts{
  125.             baseLatency:    20 * time.Millisecond,
  126.             errorRatio:     0.02,
  127.             outageDuration: time.Minute,
  128.         },
  129.     },
  130.     "/api/bar": map[string]responseOpts{
  131.         "GET": responseOpts{
  132.             baseLatency:    15 * time.Millisecond,
  133.             errorRatio:     0.0025,
  134.             outageDuration: 13 * time.Second,
  135.         },
  136.         "POST": responseOpts{
  137.             baseLatency:    50 * time.Millisecond,
  138.             errorRatio:     0.01,
  139.             outageDuration: 47 * time.Second,
  140.         },
  141.     },
  142. }
  143.  
  144. func handleAPI(w http.ResponseWriter, r *http.Request) {
  145.     begun := time.Now()
  146.     requestsInProgress.Inc()
  147.     status := http.StatusOK
  148.  
  149.     defer func() {
  150.         requestsInProgress.Dec()
  151.         requestHistogram.With(prometheus.Labels{
  152.             "method": r.Method,
  153.             "path":   r.URL.Path,
  154.             "status": fmt.Sprint(status),
  155.         }).Observe(time.Since(begun).Seconds())
  156.     }()
  157.  
  158.     pathOpts, ok := opts[r.URL.Path]
  159.     if !ok {
  160.         status = http.StatusNotFound
  161.         http.Error(w, fmt.Sprintf("Path %q not found.", r.URL.Path), status)
  162.         return
  163.     }
  164.     methodOpts, ok := pathOpts[r.Method]
  165.     if !ok {
  166.         status = http.StatusMethodNotAllowed
  167.         http.Error(w, fmt.Sprintf("Method %q not allowed.", r.Method), status)
  168.         return
  169.     }
  170.  
  171.     latencyFactor := time.Duration(1)
  172.     errorFactor := 1.
  173.     if time.Since(start)%(10*methodOpts.outageDuration) < methodOpts.outageDuration {
  174.         latencyFactor *= 3
  175.         errorFactor *= 10
  176.     }
  177.     time.Sleep(
  178.         (methodOpts.baseLatency + time.Duration(rand.NormFloat64()*float64(methodOpts.baseLatency)/10)) * latencyFactor,
  179.     )
  180.     if rand.Float64() <= methodOpts.errorRatio*errorFactor {
  181.         status = http.StatusInternalServerError
  182.         http.Error(w, "Fake error to test monitoring.", status)
  183.     }
  184. }
  185.  
  186. root@example-app-5b8868d69d-64zjm:/go/src/app# cat main.go
  187. package main
  188.  
  189. import (
  190.     "flag"
  191.     "net/http"
  192.     "os"
  193.     "time"
  194.  
  195.     "github.com/justinas/alice"
  196.     "github.com/prometheus/client_golang/prometheus"
  197.     "github.com/streadway/handy/report"
  198. )
  199.  
  200. var (
  201.     addr = flag.String("listen-address", ":8080", "The address to listen on for HTTP requests.")
  202.  
  203.     start = time.Now()
  204. )
  205.  
  206. func main() {
  207.     flag.Parse()
  208.  
  209.     http.HandleFunc("/api/", prometheus.InstrumentHandlerFunc("api", handleAPI))
  210.     http.Handle("/metrics", prometheus.Handler())
  211.  
  212.     // Log every received HTTP request to stdout.
  213.     go http.ListenAndServe(*addr, alice.New(
  214.         report.JSONMiddleware(os.Stdout),
  215.     ).Then(http.DefaultServeMux))
  216.  
  217.     startClient(*addr)
  218.  
  219.     select {}
  220. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement