From 6073cd79f63124a390b6f2d4879f4cc421538af7 Mon Sep 17 00:00:00 2001 From: Alex <alexellis2@gmail.com> Date: Thu, 22 Dec 2016 21:27:07 +0000 Subject: [PATCH] Add metrics --- README.md | 2 + gateway/Dockerfile | 12 ++++-- gateway/metrics/metrics.go | 13 +++++++ gateway/server.go | 75 +++++++++++++++++++++++++++++--------- 4 files changed, 81 insertions(+), 21 deletions(-) create mode 100644 gateway/metrics/metrics.go diff --git a/README.md b/README.md index 02a72061..077a4e01 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # faas Functions as a service +Minimum requirements: Docker 1.13 + gateway ======= diff --git a/gateway/Dockerfile b/gateway/Dockerfile index 8476e7e3..ee309dfa 100644 --- a/gateway/Dockerfile +++ b/gateway/Dockerfile @@ -4,12 +4,16 @@ RUN go get -d github.com/docker/docker/api/types \ && go get -d github.com/docker/docker/api/types/filters \ && go get -d github.com/docker/docker/api/types/swarm \ && go get -d github.com/docker/docker/client +RUN go get github.com/gorilla/mux \ + && go get github.com/prometheus/client_golang/prometheus -WORKDIR /go/src/app/ -RUN go get github.com/gorilla/mux +WORKDIR /go/src/github.com/alexellis/faas/gateway + +COPY metrics metrics COPY server.go . + +RUN find /go/src/github.com/alexellis/faas/gateway/ RUN go build EXPOSE 8080 -CMD ["./app"] - +CMD ["./gateway"] diff --git a/gateway/metrics/metrics.go b/gateway/metrics/metrics.go new file mode 100644 index 00000000..bb3be41d --- /dev/null +++ b/gateway/metrics/metrics.go @@ -0,0 +1,13 @@ +package metrics + +import ( + "net/http" + + "github.com/prometheus/client_golang/prometheus" +) + +// Handler returns the global http.Handler that provides the prometheus +// metrics format on GET requests +func Handler() http.Handler { + return prometheus.Handler() +} diff --git a/gateway/server.go b/gateway/server.go index e21c33bb..20bb29e1 100644 --- a/gateway/server.go +++ b/gateway/server.go @@ -5,17 +5,26 @@ import ( "context" "log" "net/http" + "time" "io/ioutil" "strconv" + "github.com/alexellis/faas/gateway/metrics" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/client" "github.com/gorilla/mux" + "github.com/prometheus/client_golang/prometheus" ) +type MetricOptions struct { + GatewayRequestsTotal prometheus.Counter + GatewayServerlessServedTotal prometheus.Counter + GatewayFunctions prometheus.Histogram +} + func lookupSwarmService(serviceName string) (bool, error) { var c *client.Client var err error @@ -30,34 +39,66 @@ func lookupSwarmService(serviceName string) (bool, error) { return len(services) > 0, err } -func proxy(w http.ResponseWriter, r *http.Request) { - if r.Method == "POST" { - log.Println(r.Header) - header := r.Header["X-Function"] - log.Println(header) +func makeProxy(metrics MetricOptions) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + metrics.GatewayRequestsTotal.Inc() - exists, err := lookupSwarmService(header[0]) - if err != nil { - log.Fatalln(err) - } + start := time.Now() - if exists == true { - // client := http.Client{Timeout: time.Second * 2} - requestBody, _ := ioutil.ReadAll(r.Body) - buf := bytes.NewBuffer(requestBody) + if r.Method == "POST" { + log.Println(r.Header) + header := r.Header["X-Function"] + log.Println(header) - response, err := http.Post("http://"+header[0]+":"+strconv.Itoa(8080)+"/", "text/plain", buf) + exists, err := lookupSwarmService(header[0]) if err != nil { log.Fatalln(err) } - responseBody, _ := ioutil.ReadAll(response.Body) - w.Write(responseBody) + + if exists == true { + requestBody, _ := ioutil.ReadAll(r.Body) + buf := bytes.NewBuffer(requestBody) + + response, err := http.Post("http://"+header[0]+":"+strconv.Itoa(8080)+"/", "text/plain", buf) + if err != nil { + log.Fatalln(err) + } + responseBody, _ := ioutil.ReadAll(response.Body) + w.Write(responseBody) + metrics.GatewayServerlessServedTotal.Inc() + + metrics.GatewayFunctions.Observe(time.Since(start).Seconds()) + } } } } func main() { + GatewayRequestsTotal := prometheus.NewCounter(prometheus.CounterOpts{ + Name: "gateway_requests_total", + Help: "Total amount of HTTP requests to the gateway", + }) + GatewayServerlessServedTotal := prometheus.NewCounter(prometheus.CounterOpts{ + Name: "gateway_serverless_invocation_total", + Help: "Total amount of serverless function invocations", + }) + GatewayFunctions := prometheus.NewHistogram(prometheus.HistogramOpts{ + Name: "gateway_functions", + Help: "Gateway functions", + }) + + prometheus.Register(GatewayRequestsTotal) + prometheus.Register(GatewayServerlessServedTotal) + prometheus.Register(GatewayFunctions) + r := mux.NewRouter() - r.HandleFunc("/", proxy) + r.HandleFunc("/", makeProxy(MetricOptions{ + GatewayRequestsTotal: GatewayRequestsTotal, + GatewayServerlessServedTotal: GatewayServerlessServedTotal, + GatewayFunctions: GatewayFunctions, + })) + + metricsHandler := metrics.Handler() + r.Handle("/metrics", metricsHandler) log.Fatal(http.ListenAndServe(":8080", r)) } -- GitLab