From f7fff2cf1c94c2a3e12899502fea62d001762089 Mon Sep 17 00:00:00 2001 From: Phil Winder Date: Tue, 21 Mar 2017 15:49:30 +0000 Subject: [PATCH] Refactor to use middleware code from weaveworks/common --- .travis.yml | 2 +- docker/payment/Dockerfile | 2 +- middleware/instrument.go | 94 ----------------- middleware/middleware.go | 33 ------ scripts/build.sh | 1 - test/unit.py | 2 +- vendor/manifest | 214 +++++++++++++++++++++++++++++++++++++- wiring.go | 18 +++- 8 files changed, 229 insertions(+), 137 deletions(-) delete mode 100644 middleware/instrument.go delete mode 100644 middleware/middleware.go diff --git a/.travis.yml b/.travis.yml index c022d1b..1387cc3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ sudo: required services: - docker go: -- 1.6 +- 1.7 before_install: - go get -u github.com/mattn/goveralls - go get -u github.com/FiloSottile/gvt diff --git a/docker/payment/Dockerfile b/docker/payment/Dockerfile index 020befa..4a05cbd 100644 --- a/docker/payment/Dockerfile +++ b/docker/payment/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.6 +FROM golang:1.7 RUN mkdir /app COPY . /go/src/github.com/microservices-demo/payment/ diff --git a/middleware/instrument.go b/middleware/instrument.go deleted file mode 100644 index 3ec1b92..0000000 --- a/middleware/instrument.go +++ /dev/null @@ -1,94 +0,0 @@ -package middleware - -import ( - "net/http" - "regexp" - "strconv" - "strings" - "time" - - "github.com/felixge/httpsnoop" - "github.com/gorilla/mux" - "github.com/prometheus/client_golang/prometheus" -) - -var ( - HTTPLatency = prometheus.NewHistogramVec(prometheus.HistogramOpts{ - Name: "request_duration_seconds", - Help: "Time (in seconds) spent serving HTTP requests.", - Buckets: prometheus.DefBuckets, - }, []string{"service", "method", "route", "status_code"}) -) - -func init() { - prometheus.MustRegister(HTTPLatency) -} - -// RouteMatcher matches routes -type RouteMatcher interface { - Match(*http.Request, *mux.RouteMatch) bool -} - -// Instrument is a Middleware which records timings for every HTTP request -type Instrument struct { - RouteMatcher RouteMatcher - Duration *prometheus.HistogramVec - Service string -} - -// Wrap implements middleware.Interface -func (i Instrument) Wrap(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - begin := time.Now() - interceptor := httpsnoop.CaptureMetrics(next, w, r) - route := i.getRouteName(r) - var ( - status = strconv.Itoa(interceptor.Code) - took = time.Since(begin) - ) - i.Duration.WithLabelValues(i.Service, r.Method, route, status).Observe(took.Seconds()) - }) -} - -// Return a name identifier for ths request. There are three options: -// 1. The request matches a gorilla mux route, with a name. Use that. -// 2. The request matches an unamed gorilla mux router. Munge the path -// template such that templates like '/api/{org}/foo' come out as -// 'api_org_foo'. -// 3. The request doesn't match a mux route. Munge the Path in the same -// manner as (2). -// We do all this as we do not wish to emit high cardinality labels to -// prometheus. -func (i Instrument) getRouteName(r *http.Request) string { - var routeMatch mux.RouteMatch - if i.RouteMatcher != nil && i.RouteMatcher.Match(r, &routeMatch) { - if name := routeMatch.Route.GetName(); name != "" { - return name - } - if tmpl, err := routeMatch.Route.GetPathTemplate(); err == nil { - return MakeLabelValue(tmpl) - } - } - return MakeLabelValue(r.URL.Path) -} - -var invalidChars = regexp.MustCompile(`[^a-zA-Z0-9]+`) - -// MakeLabelValue converts a Gorilla mux path to a string suitable for use in -// a Prometheus label value. -func MakeLabelValue(path string) string { - // Convert non-alnums to underscores. - result := invalidChars.ReplaceAllString(path, "_") - - // Trim leading and trailing underscores. - result = strings.Trim(result, "_") - - // Make it all lowercase - result = strings.ToLower(result) - - // Special case. - if result == "" { - result = "root" - } - return result -} diff --git a/middleware/middleware.go b/middleware/middleware.go deleted file mode 100644 index ad8925a..0000000 --- a/middleware/middleware.go +++ /dev/null @@ -1,33 +0,0 @@ -package middleware - -import ( - "net/http" -) - -// Interface is the shared contract for all middlesware, and allows middlesware -// to wrap handlers. -type Interface interface { - Wrap(http.Handler) http.Handler -} - -// Func is to Interface as http.HandlerFunc is to http.Handler -type Func func(http.Handler) http.Handler - -// Wrap implements Interface -func (m Func) Wrap(next http.Handler) http.Handler { - return m(next) -} - -// Identity is an Interface which doesn't do anything. -var Identity Interface = Func(func(h http.Handler) http.Handler { return h }) - -// Merge produces a middleware that applies multiple middlesware in turn; -// ie Merge(f,g,h).Wrap(handler) == f.Wrap(g.Wrap(h.Wrap(handler))) -func Merge(middlesware ...Interface) Interface { - return Func(func(next http.Handler) http.Handler { - for i := len(middlesware) - 1; i >= 0; i-- { - next = middlesware[i].Wrap(next) - } - return next - }) -} diff --git a/scripts/build.sh b/scripts/build.sh index 6b9dca9..beae1a3 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -23,7 +23,6 @@ CODE_DIR=$(cd $SCRIPT_DIR/..; pwd) echo $CODE_DIR cp -r $CODE_DIR/cmd/ $CODE_DIR/docker/payment/cmd/ -cp -r $CODE_DIR/middleware/ $CODE_DIR/docker/payment/middleware/ cp $CODE_DIR/*.go $CODE_DIR/docker/payment/ mkdir $CODE_DIR/docker/payment/vendor && cp $CODE_DIR/vendor/manifest $CODE_DIR/docker/payment/vendor/ diff --git a/test/unit.py b/test/unit.py index 95a3f9d..8f6aecb 100755 --- a/test/unit.py +++ b/test/unit.py @@ -13,7 +13,7 @@ def test_go(self): '-v', code_dir + ':/go/src/github.com/microservices-demo/payment', '-w', '/go/src/github.com/microservices-demo/payment', '-e', 'GOPATH=/go/', - 'golang:1.6', + 'golang:1.7', 'go', 'test', '-v', '-covermode=count', '-coverprofile=coverage.out' ] diff --git a/vendor/manifest b/vendor/manifest index b657da1..4f00c54 100644 --- a/vendor/manifest +++ b/vendor/manifest @@ -1,6 +1,24 @@ { "version": 0, "dependencies": [ + { + "importpath": "cloud.google.com/go/compute/metadata", + "repository": "https://code.googlesource.com/gocloud", + "vcs": "git", + "revision": "daf945bb8684eb8df711af0c3e3a07930a2a01b0", + "branch": "master", + "path": "/compute/metadata", + "notests": true + }, + { + "importpath": "cloud.google.com/go/internal", + "repository": "https://code.googlesource.com/gocloud", + "vcs": "git", + "revision": "daf945bb8684eb8df711af0c3e3a07930a2a01b0", + "branch": "master", + "path": "internal", + "notests": true + }, { "importpath": "github.com/Shopify/sarama", "repository": "https://github.com/Shopify/sarama", @@ -9,6 +27,14 @@ "branch": "master", "notests": true }, + { + "importpath": "github.com/Sirupsen/logrus", + "repository": "https://github.com/Sirupsen/logrus", + "vcs": "git", + "revision": "10f801ebc38b33738c9d17d50860f484a0988ff5", + "branch": "master", + "notests": true + }, { "importpath": "github.com/VividCortex/gohistogram", "repository": "https://github.com/VividCortex/gohistogram", @@ -208,6 +234,23 @@ "path": "types", "notests": true }, + { + "importpath": "github.com/golang/glog", + "repository": "https://github.com/golang/glog", + "vcs": "git", + "revision": "23def4e6c14b4da8ac2ed8007337bc5eb5007998", + "branch": "master", + "notests": true + }, + { + "importpath": "github.com/golang/mock/gomock", + "repository": "https://github.com/golang/mock", + "vcs": "git", + "revision": "bd3c8e81be01eef76d4b503f5e687d2d1354d2d9", + "branch": "master", + "path": "/gomock", + "notests": true + }, { "importpath": "github.com/golang/protobuf/proto", "repository": "https://github.com/golang/protobuf", @@ -217,6 +260,15 @@ "path": "/proto", "notests": true }, + { + "importpath": "github.com/golang/protobuf/protoc-gen-go/descriptor", + "repository": "https://github.com/golang/protobuf", + "vcs": "git", + "revision": "c9c7427a2a70d2eb3bafa0ab2dc163e45f143317", + "branch": "master", + "path": "/protoc-gen-go/descriptor", + "notests": true + }, { "importpath": "github.com/golang/protobuf/ptypes/any", "repository": "https://github.com/golang/protobuf", @@ -234,6 +286,14 @@ "branch": "master", "notests": true }, + { + "importpath": "github.com/googleapis/gax-go", + "repository": "https://github.com/googleapis/gax-go", + "vcs": "git", + "revision": "9af46dd5a1713e8b5cd71106287eba3cefdde50b", + "branch": "master", + "notests": true + }, { "importpath": "github.com/gorilla/context", "repository": "https://github.com/gorilla/context", @@ -487,6 +547,60 @@ "notests": true, "allfiles": true }, + { + "importpath": "github.com/weaveworks/common/errors", + "repository": "https://github.com/weaveworks/common", + "vcs": "git", + "revision": "f94043b3da140c7a735b1f2f286d72d19014b200", + "branch": "master", + "path": "errors", + "notests": true + }, + { + "importpath": "github.com/weaveworks/common/middleware", + "repository": "https://github.com/weaveworks/common", + "vcs": "git", + "revision": "f94043b3da140c7a735b1f2f286d72d19014b200", + "branch": "master", + "path": "/middleware", + "notests": true + }, + { + "importpath": "github.com/weaveworks/common/user", + "repository": "https://github.com/weaveworks/common", + "vcs": "git", + "revision": "f94043b3da140c7a735b1f2f286d72d19014b200", + "branch": "master", + "path": "user", + "notests": true + }, + { + "importpath": "go4.org/syncutil/singleflight", + "repository": "https://github.com/camlistore/go4", + "vcs": "git", + "revision": "169ea6cabe2a4888dba958edaecc9e9751adc711", + "branch": "master", + "path": "/syncutil/singleflight", + "notests": true + }, + { + "importpath": "golang.org/x/crypto/acme", + "repository": "https://go.googlesource.com/crypto", + "vcs": "git", + "revision": "459e26527287adbc2adcc5d0d49abff9a5f315a7", + "branch": "master", + "path": "acme", + "notests": true + }, + { + "importpath": "golang.org/x/crypto/ssh/terminal", + "repository": "https://go.googlesource.com/crypto", + "vcs": "git", + "revision": "459e26527287adbc2adcc5d0d49abff9a5f315a7", + "branch": "master", + "path": "ssh/terminal", + "notests": true + }, { "importpath": "golang.org/x/net/context", "repository": "https://go.googlesource.com/net", @@ -496,6 +610,24 @@ "path": "/context", "notests": true }, + { + "importpath": "golang.org/x/net/http2", + "repository": "https://go.googlesource.com/net", + "vcs": "git", + "revision": "a6577fac2d73be281a500b310739095313165611", + "branch": "master", + "path": "/http2", + "notests": true + }, + { + "importpath": "golang.org/x/net/idna", + "repository": "https://go.googlesource.com/net", + "vcs": "git", + "revision": "a6577fac2d73be281a500b310739095313165611", + "branch": "master", + "path": "idna", + "notests": true + }, { "importpath": "golang.org/x/net/internal/timeseries", "repository": "https://go.googlesource.com/net", @@ -505,6 +637,15 @@ "path": "internal/timeseries", "notests": true }, + { + "importpath": "golang.org/x/net/lex/httplex", + "repository": "https://go.googlesource.com/net", + "vcs": "git", + "revision": "a6577fac2d73be281a500b310739095313165611", + "branch": "master", + "path": "lex/httplex", + "notests": true + }, { "importpath": "golang.org/x/net/trace", "repository": "https://go.googlesource.com/net", @@ -515,12 +656,79 @@ "notests": true }, { - "importpath": "google.golang.org/grpc/metadata", + "importpath": "golang.org/x/oauth2", + "repository": "https://go.googlesource.com/oauth2", + "vcs": "git", + "revision": "7fdf09982454086d5570c7db3e11f360194830ca", + "branch": "master", + "notests": true + }, + { + "importpath": "golang.org/x/sys/unix", + "repository": "https://go.googlesource.com/sys", + "vcs": "git", + "revision": "99f16d856c9836c42d24e7ab64ea72916925fa97", + "branch": "master", + "path": "/unix", + "notests": true + }, + { + "importpath": "google.golang.org/api/compute/v1", + "repository": "https://code.googlesource.com/google-api-go-client", + "vcs": "git", + "revision": "16ab375f94503bfa0d19db78e96bffbe1a34354f", + "branch": "master", + "path": "/compute/v1", + "notests": true + }, + { + "importpath": "google.golang.org/api/gensupport", + "repository": "https://code.googlesource.com/google-api-go-client", + "vcs": "git", + "revision": "16ab375f94503bfa0d19db78e96bffbe1a34354f", + "branch": "master", + "path": "gensupport", + "notests": true + }, + { + "importpath": "google.golang.org/api/googleapi", + "repository": "https://code.googlesource.com/google-api-go-client", + "vcs": "git", + "revision": "16ab375f94503bfa0d19db78e96bffbe1a34354f", + "branch": "master", + "path": "googleapi", + "notests": true + }, + { + "importpath": "google.golang.org/appengine", + "repository": "https://github.com/golang/appengine", + "vcs": "git", + "revision": "b79c28f0197795b4050bfcd7c4c2209136c594b1", + "branch": "master", + "notests": true + }, + { + "importpath": "google.golang.org/grpc", "repository": "https://github.com/grpc/grpc-go", "vcs": "git", - "revision": "c8105071640ef29fce843ed96983e864bb18eb0e", + "revision": "cdee119ee21e61eef7093a41ba148fa83585e143", + "branch": "master", + "notests": true + }, + { + "importpath": "gopkg.in/airbrake/gobrake.v2", + "repository": "https://gopkg.in/airbrake/gobrake.v2", + "vcs": "git", + "revision": "668876711219e8b0206e2994bf0a59d889c775aa", + "branch": "master", + "notests": true + }, + { + "importpath": "gopkg.in/gemnasium/logrus-airbrake-hook.v2", + "repository": "https://gopkg.in/gemnasium/logrus-airbrake-hook.v2", + "vcs": "git", + "revision": "bfee1239d796830ca346767650cce5ba90d58c57", "branch": "master", - "path": "/metadata", "notests": true } ] diff --git a/wiring.go b/wiring.go index d8bd3aa..4f4852d 100644 --- a/wiring.go +++ b/wiring.go @@ -7,10 +7,23 @@ import ( "github.com/go-kit/kit/log" "golang.org/x/net/context" - "github.com/microservices-demo/payment/middleware" stdopentracing "github.com/opentracing/opentracing-go" + "github.com/prometheus/client_golang/prometheus" + "github.com/weaveworks/common/middleware" ) +var ( + HTTPLatency = prometheus.NewHistogramVec(prometheus.HistogramOpts{ + Name: "request_duration_seconds", + Help: "Time (in seconds) spent serving HTTP requests.", + Buckets: prometheus.DefBuckets, + }, []string{"method", "route", "status_code", "isWS"}) +) + +func init() { + prometheus.MustRegister(HTTPLatency) +} + func WireUp(ctx context.Context, declineAmount float32, tracer stdopentracing.Tracer, serviceName string) (http.Handler, log.Logger) { // Log domain. var logger log.Logger @@ -34,9 +47,8 @@ func WireUp(ctx context.Context, declineAmount float32, tracer stdopentracing.Tr httpMiddleware := []middleware.Interface{ middleware.Instrument{ - Duration: middleware.HTTPLatency, + Duration: HTTPLatency, RouteMatcher: router, - Service: serviceName, }, }