Skip to content
This repository has been archived by the owner on Dec 5, 2023. It is now read-only.

Commit

Permalink
Merge pull request #30 from microservices-demo/enhancement/opentracing
Browse files Browse the repository at this point in the history
Enhancement/opentracing
  • Loading branch information
jasonrichardsmith committed Dec 23, 2016
2 parents 1d394b6 + 6bc65ab commit fae2a75
Show file tree
Hide file tree
Showing 7 changed files with 257 additions and 33 deletions.
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,24 @@ curl http://localhost:8080/register
```bash
make dockertravisbuild
```

## Test Zipkin

To test with Zipkin

```
make
docker-compose -f docker-compose-zipkin.yml build
docker-compose -f docker-compose-zipkin.yml up
```
It takes about 10 seconds to seed data

you should see it at:
[http://localhost:9411/](http://localhost:9411)

be sure to hit the "Find Traces" button. You may need to reload the page.

when done you can run:
```
docker-compose -f docker-compose-zipkin.yml down
```
74 changes: 63 additions & 11 deletions api/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ package api

import (
"github.com/go-kit/kit/endpoint"
"github.com/go-kit/kit/tracing/opentracing"
"github.com/microservices-demo/user/db"
"github.com/microservices-demo/user/users"
stdopentracing "github.com/opentracing/opentracing-go"
"golang.org/x/net/context"
)

Expand All @@ -27,24 +29,28 @@ type Endpoints struct {

// MakeEndpoints returns an Endpoints structure, where each endpoint is
// backed by the given service.
func MakeEndpoints(s Service) Endpoints {
func MakeEndpoints(s Service, tracer stdopentracing.Tracer) Endpoints {
return Endpoints{
LoginEndpoint: MakeLoginEndpoint(s),
RegisterEndpoint: MakeRegisterEndpoint(s),
HealthEndpoint: MakeHealthEndpoint(s),
UserGetEndpoint: MakeUserGetEndpoint(s),
UserPostEndpoint: MakeUserPostEndpoint(s),
AddressGetEndpoint: MakeAddressGetEndpoint(s),
AddressPostEndpoint: MakeAddressPostEndpoint(s),
CardGetEndpoint: MakeCardGetEndpoint(s),
DeleteEndpoint: MakeDeleteEndpoint(s),
CardPostEndpoint: MakeCardPostEndpoint(s),
LoginEndpoint: opentracing.TraceServer(tracer, "GET /login")(MakeLoginEndpoint(s)),
RegisterEndpoint: opentracing.TraceServer(tracer, "POST /register")(MakeRegisterEndpoint(s)),
HealthEndpoint: opentracing.TraceServer(tracer, "GET /health")(MakeHealthEndpoint(s)),
UserGetEndpoint: opentracing.TraceServer(tracer, "GET /customers")(MakeUserGetEndpoint(s)),
UserPostEndpoint: opentracing.TraceServer(tracer, "POST /customers")(MakeUserPostEndpoint(s)),
AddressGetEndpoint: opentracing.TraceServer(tracer, "GET /addresses")(MakeAddressGetEndpoint(s)),
AddressPostEndpoint: opentracing.TraceServer(tracer, "POST /addresses")(MakeAddressPostEndpoint(s)),
CardGetEndpoint: opentracing.TraceServer(tracer, "GET /cards")(MakeCardGetEndpoint(s)),
DeleteEndpoint: opentracing.TraceServer(tracer, "DELETE /")(MakeDeleteEndpoint(s)),
CardPostEndpoint: opentracing.TraceServer(tracer, "POST /cards")(MakeCardPostEndpoint(s)),
}
}

// MakeLoginEndpoint returns an endpoint via the given service.
func MakeLoginEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
var span stdopentracing.Span
span, ctx = stdopentracing.StartSpanFromContext(ctx, "login user")
span.SetTag("service", "user")
defer span.Finish()
req := request.(loginRequest)
u, err := s.Login(req.Username, req.Password)
return userResponse{User: u}, err
Expand All @@ -54,6 +60,10 @@ func MakeLoginEndpoint(s Service) endpoint.Endpoint {
// MakeRegisterEndpoint returns an endpoint via the given service.
func MakeRegisterEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
var span stdopentracing.Span
span, ctx = stdopentracing.StartSpanFromContext(ctx, "register user")
span.SetTag("service", "user")
defer span.Finish()
req := request.(registerRequest)
id, err := s.Register(req.Username, req.Password, req.Email, req.FirstName, req.LastName)
return postResponse{ID: id}, err
Expand All @@ -63,8 +73,16 @@ func MakeRegisterEndpoint(s Service) endpoint.Endpoint {
// MakeUserGetEndpoint returns an endpoint via the given service.
func MakeUserGetEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
var span stdopentracing.Span
span, ctx = stdopentracing.StartSpanFromContext(ctx, "get users")
span.SetTag("service", "user")
defer span.Finish()

req := request.(GetRequest)

userspan := stdopentracing.StartSpan("users from db", stdopentracing.ChildOf(span.Context()))
usrs, err := s.GetUsers(req.ID)
userspan.Finish()
if req.ID == "" {
return EmbedStruct{usersResponse{Users: usrs}}, err
}
Expand All @@ -78,7 +96,9 @@ func MakeUserGetEndpoint(s Service) endpoint.Endpoint {
return users.User{}, err
}
user := usrs[0]
attrspan := stdopentracing.StartSpan("attributes from db", stdopentracing.ChildOf(span.Context()))
db.GetUserAttributes(&user)
attrspan.Finish()
if req.Attr == "addresses" {
return EmbedStruct{addressesResponse{Addresses: user.Addresses}}, err
}
Expand All @@ -92,6 +112,10 @@ func MakeUserGetEndpoint(s Service) endpoint.Endpoint {
// MakeUserPostEndpoint returns an endpoint via the given service.
func MakeUserPostEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
var span stdopentracing.Span
span, ctx = stdopentracing.StartSpanFromContext(ctx, "post user")
span.SetTag("service", "user")
defer span.Finish()
req := request.(users.User)
id, err := s.PostUser(req)
return postResponse{ID: id}, err
Expand All @@ -101,8 +125,14 @@ func MakeUserPostEndpoint(s Service) endpoint.Endpoint {
// MakeAddressGetEndpoint returns an endpoint via the given service.
func MakeAddressGetEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
var span stdopentracing.Span
span, ctx = stdopentracing.StartSpanFromContext(ctx, "get users")
span.SetTag("service", "user")
defer span.Finish()
req := request.(GetRequest)
addrspan := stdopentracing.StartSpan("addresses from db", stdopentracing.ChildOf(span.Context()))
adds, err := s.GetAddresses(req.ID)
addrspan.Finish()
if req.ID == "" {
return EmbedStruct{addressesResponse{Addresses: adds}}, err
}
Expand All @@ -116,6 +146,10 @@ func MakeAddressGetEndpoint(s Service) endpoint.Endpoint {
// MakeAddressPostEndpoint returns an endpoint via the given service.
func MakeAddressPostEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
var span stdopentracing.Span
span, ctx = stdopentracing.StartSpanFromContext(ctx, "post address")
span.SetTag("service", "user")
defer span.Finish()
req := request.(addressPostRequest)
id, err := s.PostAddress(req.Address, req.UserID)
return postResponse{ID: id}, err
Expand All @@ -125,8 +159,14 @@ func MakeAddressPostEndpoint(s Service) endpoint.Endpoint {
// MakeUserGetEndpoint returns an endpoint via the given service.
func MakeCardGetEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
var span stdopentracing.Span
span, ctx = stdopentracing.StartSpanFromContext(ctx, "get cards")
span.SetTag("service", "user")
defer span.Finish()
req := request.(GetRequest)
cardspan := stdopentracing.StartSpan("addresses from db", stdopentracing.ChildOf(span.Context()))
cards, err := s.GetCards(req.ID)
cardspan.Finish()
if req.ID == "" {
return EmbedStruct{cardsResponse{Cards: cards}}, err
}
Expand All @@ -140,6 +180,10 @@ func MakeCardGetEndpoint(s Service) endpoint.Endpoint {
// MakeCardPostEndpoint returns an endpoint via the given service.
func MakeCardPostEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
var span stdopentracing.Span
span, ctx = stdopentracing.StartSpanFromContext(ctx, "post card")
span.SetTag("service", "user")
defer span.Finish()
req := request.(cardPostRequest)
id, err := s.PostCard(req.Card, req.UserID)
return postResponse{ID: id}, err
Expand All @@ -149,6 +193,10 @@ func MakeCardPostEndpoint(s Service) endpoint.Endpoint {
// MakeLoginEndpoint returns an endpoint via the given service.
func MakeDeleteEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
var span stdopentracing.Span
span, ctx = stdopentracing.StartSpanFromContext(ctx, "delete entity")
span.SetTag("service", "user")
defer span.Finish()
req := request.(deleteRequest)
err = s.Delete(req.Entity, req.ID)
if err == nil {
Expand All @@ -161,6 +209,10 @@ func MakeDeleteEndpoint(s Service) endpoint.Endpoint {
// MakeHealthEndpoint returns current health of the given service.
func MakeHealthEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
var span stdopentracing.Span
span, ctx = stdopentracing.StartSpanFromContext(ctx, "health check")
span.SetTag("service", "user")
defer span.Finish()
health := s.Health()
return healthResponse{Health: health}, nil
}
Expand Down
24 changes: 13 additions & 11 deletions api/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import (
"strings"

"github.com/go-kit/kit/log"
"github.com/go-kit/kit/tracing/opentracing"
httptransport "github.com/go-kit/kit/transport/http"
"github.com/gorilla/mux"
"github.com/microservices-demo/user/users"
stdopentracing "github.com/opentracing/opentracing-go"
"github.com/prometheus/client_golang/prometheus/promhttp"
"golang.org/x/net/context"
)
Expand All @@ -22,7 +24,7 @@ var (
)

// MakeHTTPHandler mounts the endpoints into a REST-y HTTP handler.
func MakeHTTPHandler(ctx context.Context, e Endpoints, logger log.Logger) http.Handler {
func MakeHTTPHandler(ctx context.Context, e Endpoints, logger log.Logger, tracer stdopentracing.Tracer) http.Handler {
r := mux.NewRouter().StrictSlash(false)
options := []httptransport.ServerOption{
httptransport.ServerErrorLogger(logger),
Expand All @@ -38,70 +40,70 @@ func MakeHTTPHandler(ctx context.Context, e Endpoints, logger log.Logger) http.H
e.LoginEndpoint,
decodeLoginRequest,
encodeResponse,
options...,
append(options, httptransport.ServerBefore(opentracing.FromHTTPRequest(tracer, "GET /login", logger)))...,
))
r.Methods("POST").Path("/register").Handler(httptransport.NewServer(
ctx,
e.RegisterEndpoint,
decodeRegisterRequest,
encodeResponse,
options...,
append(options, httptransport.ServerBefore(opentracing.FromHTTPRequest(tracer, "POST /register", logger)))...,
))
r.Methods("GET").PathPrefix("/customers").Handler(httptransport.NewServer(
ctx,
e.UserGetEndpoint,
decodeGetRequest,
encodeResponse,
options...,
append(options, httptransport.ServerBefore(opentracing.FromHTTPRequest(tracer, "GET /customers", logger)))...,
))
r.Methods("GET").PathPrefix("/cards").Handler(httptransport.NewServer(
ctx,
e.CardGetEndpoint,
decodeGetRequest,
encodeResponse,
options...,
append(options, httptransport.ServerBefore(opentracing.FromHTTPRequest(tracer, "GET /cards", logger)))...,
))
r.Methods("GET").PathPrefix("/addresses").Handler(httptransport.NewServer(
ctx,
e.AddressGetEndpoint,
decodeGetRequest,
encodeResponse,
options...,
append(options, httptransport.ServerBefore(opentracing.FromHTTPRequest(tracer, "GET /addresses", logger)))...,
))
r.Methods("POST").Path("/customers").Handler(httptransport.NewServer(
ctx,
e.UserPostEndpoint,
decodeUserRequest,
encodeResponse,
options...,
append(options, httptransport.ServerBefore(opentracing.FromHTTPRequest(tracer, "POST /customers", logger)))...,
))
r.Methods("POST").Path("/addresses").Handler(httptransport.NewServer(
ctx,
e.AddressPostEndpoint,
decodeAddressRequest,
encodeResponse,
options...,
append(options, httptransport.ServerBefore(opentracing.FromHTTPRequest(tracer, "POST /addresses", logger)))...,
))
r.Methods("POST").Path("/cards").Handler(httptransport.NewServer(
ctx,
e.CardPostEndpoint,
decodeCardRequest,
encodeResponse,
options...,
append(options, httptransport.ServerBefore(opentracing.FromHTTPRequest(tracer, "POST /cards", logger)))...,
))
r.Methods("DELETE").PathPrefix("/").Handler(httptransport.NewServer(
ctx,
e.DeleteEndpoint,
decodeDeleteRequest,
encodeResponse,
options...,
append(options, httptransport.ServerBefore(opentracing.FromHTTPRequest(tracer, "DELETE /", logger)))...,
))
r.Methods("GET").PathPrefix("/health").Handler(httptransport.NewServer(
ctx,
e.HealthEndpoint,
decodeHealthRequest,
encodeHealthResponse,
options...,
append(options, httptransport.ServerBefore(opentracing.FromHTTPRequest(tracer, "GET /health", logger)))...,
))
r.Handle("/metrics", promhttp.Handler())
return r
Expand Down
57 changes: 57 additions & 0 deletions docker-compose-zipkin.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
version: '2'

services:
user:
build:
context: .
image: weaveworksdemos/user
hostname: user
restart: always
read_only: true
environment:
- MONGO_HOST=user-db:27017
- ZIPKIN=http://zipkin:9411/api/v1/spans
- reschedule=on-node-failure
ports:
- "8084:8084"
user-db:
build:
context: ./docker/user-db/
image: weaveworksdemos/user-db
hostname: user-db
restart: always
cap_drop:
- all
cap_add:
- CHOWN
- SETGID
- SETUID
read_only: true
tmpfs:
- /tmp:rw,noexec,nosuid
environment:
- reschedule=on-node-failure
ports:
- "27017:27017"
zipkin:
image: openzipkin/zipkin
hostname: zipkin
restart: always
cap_drop:
- all
cap_add:
- CHOWN
- SETGID
- SETUID
read_only: true
tmpfs:
- /tmp:rw,noexec,nosuid
environment:
- reschedule=on-node-failure
ports:
- "9411:9411"
zipkinseed:
image: alpine
command: /bin/sh -c 'sleep 10 ; wget http://user:8084/health ; wget http://user:8084/customers ; wget http://user:8084/customers/57a98d98e4b00679b4a830af ; wget http://user:8084/cards'


0 comments on commit fae2a75

Please sign in to comment.