Skip to content

Commit

Permalink
Add jaeger tracing and properly set grpc interceptors
Browse files Browse the repository at this point in the history
Signed-off-by: Alexandre Beslic <abeslic@abronan.com>
  • Loading branch information
abronan committed Apr 9, 2018
1 parent d702f20 commit a1372c6
Show file tree
Hide file tree
Showing 139 changed files with 22,509 additions and 18 deletions.
44 changes: 43 additions & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,48 +54,48 @@ GLOBAL OPTIONS:
- Create a new Todo:

```bash
$ curl -X POST -H "Content-Type: application/json" -d '{"title":"Test","description":"Test"}' "http://localhost:8080/v1/todo"
curl -X POST -H "Content-Type: application/json" -d '{"title":"Test","description":"Test"}' "http://localhost:8080/v1/todo"
{"id":"34d63bd4-56b3-4795-80d4-86e5db6fa0b5"}
```

- Get an existing Todo:

```bash
$ curl -X GET "http://localhost:8080/v1/todo/34d63bd4-56b3-4795-80d4-86e5db6fa0b5"
curl -X GET "http://localhost:8080/v1/todo/34d63bd4-56b3-4795-80d4-86e5db6fa0b5"
{"item":{"id":"34d63bd4-56b3-4795-80d4-86e5db6fa0b5","title":"Test","description":"Test","created_at":"2018-03-30T20:13:25.291887Z"}}
```

- List Todos (example with limit and non completed items in query parameters):

```bash
$ curl -X GET "http://localhost:8080/v1/todo?limit=10&not_completed=true"
curl -X GET "http://localhost:8080/v1/todo?limit=10&not_completed=true"
```

- Update a Todo:

```bash
$ curl -X PUT -H "Content-Type: application/json" -d '{"id": "34d63bd4-56b3-4795-80d4-86e5db6fa0b5", "title":"TestBis", "description":"TestBis", "completed": true}' "http://localhost:8080/v1/todo"
curl -X PUT -H "Content-Type: application/json" -d '{"id": "34d63bd4-56b3-4795-80d4-86e5db6fa0b5", "title":"TestBis", "description":"TestBis", "completed": true}' "http://localhost:8080/v1/todo"
{}
```

- Delete a Todo:

```bash
$ curl -X DELETE "http://localhost:8080/v1/todo/34d63bd4-56b3-4795-80d4-86e5db6fa0b5"
curl -X DELETE "http://localhost:8080/v1/todo/34d63bd4-56b3-4795-80d4-86e5db6fa0b5"
{}
```

- Bulk Insert Todos:

```bash
$ curl -X POST -H "Content-Type: application/json" -d '{"items": [{"title":"Todo_1","description":"Todo_1"},{"title":"Todo_2","description":"Todo_2"}]}' "http://localhost:8080/v1/todo/bulk"
curl -X POST -H "Content-Type: application/json" -d '{"items": [{"title":"Todo_1","description":"Todo_1"},{"title":"Todo_2","description":"Todo_2"}]}' "http://localhost:8080/v1/todo/bulk"
{"ids":["e8924469-8847-4840-ae16-21be734173f4","0db11e34-4707-4a5d-92fe-f4952213d940"]}
```

- Bulk Update Todos:

```bash
$ curl -X PUT -H "Content-Type: application/json" -d '{"items": [{"id":"e94a6d0b-953b-4dad-aecb-318f183db4c7","title":"Todo_1","description":"Todo_1","completed":true},{"id":"d53daa2c-e6af-45ba-b192-3e1dc443b165","title":"Todo_2","description":"Todo_2","completed":true}]}' "http://localhost:8080/v1/todo/bulk"
curl -X PUT -H "Content-Type: application/json" -d '{"items": [{"id":"e94a6d0b-953b-4dad-aecb-318f183db4c7","title":"Todo_1","description":"Todo_1","completed":true},{"id":"d53daa2c-e6af-45ba-b192-3e1dc443b165","title":"Todo_2","description":"Todo_2","completed":true}]}' "http://localhost:8080/v1/todo/bulk"
{}
```

Expand All @@ -109,7 +109,7 @@ $ curl -X PUT -H "Content-Type: application/json" -d '{"items": [{"id":"e94a6d0b

## Author

**Alexandre Beslic**
Alexandre Beslic

- [abronan.com](https://abronan.com)
- [@abronan](https://twitter.com/abronan)
Expand Down
37 changes: 32 additions & 5 deletions flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,24 @@ import (
)

var commonFlags = []cli.Flag{
// Server
cli.StringFlag{
Name: "bind-http",
Usage: "bind address for HTTP",
EnvVar: "BIND_HTTP",
Value: "localhost:8080",
Value: ":8080",
},
cli.StringFlag{
Name: "bind-grpc",
Usage: "bind address for gRPC",
EnvVar: "BIND_GRPC",
Value: "localhost:2338",
Value: ":2338",
},
cli.StringFlag{
Name: "bind-prometheus-http",
Usage: "bind prometheus address for HTTP",
EnvVar: "BIND_PROMETHEUS_HTTP",
Value: ":8081",
},

// PostgresQL
cli.StringFlag{
Name: "db-name",
Usage: "database name",
Expand Down Expand Up @@ -49,4 +52,28 @@ var commonFlags = []cli.Flag{
EnvVar: "DB_PORT",
Value: 5432,
},
cli.StringFlag{
Name: "jaeger-host",
Usage: "Jaeger hostname",
EnvVar: "JAEGER_HOST",
Value: "127.0.0.1",
},
cli.IntFlag{
Name: "jaeger-port",
Usage: "Jaeger port",
EnvVar: "JAEGER_PORT",
Value: 5775,
},
cli.Float64Flag{
Name: "jaeger-sampler",
Usage: "Jaeger sampler",
EnvVar: "JAEGER_SAMPLER",
Value: 0.05,
},
cli.StringFlag{
Name: "jaeger-tags",
Usage: "Jaeger tags",
EnvVar: "JAEGER_TAGS",
Value: "directory",
},
}
75 changes: 71 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package main

import (
"context"
"fmt"
"io"
"net"
"net/http"
"os"
Expand All @@ -18,12 +20,22 @@ import (
"github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
"github.com/grpc-ecosystem/go-grpc-prometheus"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
opentracing "github.com/opentracing/opentracing-go"
"github.com/uber/jaeger-client-go/config"
"github.com/uber/jaeger-client-go/rpcmetrics"
"github.com/uber/jaeger-lib/metrics"
prometheus_metrics "github.com/uber/jaeger-lib/metrics/prometheus"

log "github.com/sirupsen/logrus"
"github.com/urfave/cli"
"google.golang.org/grpc"
)

var (
metricsFactory metrics.Factory
tracer opentracing.Tracer
)

func main() {
app := cli.NewApp()
app.Name = path.Base(os.Args[0])
Expand All @@ -43,27 +55,46 @@ func start(c *cli.Context) {
log.Fatalf("failed to listen: %v", c.String("bind-grpc"))
}

// Logrus
logrusEntry := log.NewEntry(log.New())
grpc_logrus.ReplaceGrpcLogger(logrusEntry)
log.SetLevel(log.InfoLevel)

// Prometheus monitoring
metricsFactory = prometheus_metrics.New()

// Jaeger tracing
tracer, closer, err := newTracing(
"todo",
c.String("jaeger-host")+":"+c.String("jaeger-port"),
metricsFactory.Namespace("todo", nil),
logrusEntry,
c.Float64("jaeger-sampler"),
)
if err != nil {
panic(err.Error())
}
defer closer.Close()

// Set GRPC Interceptors
server := grpc.NewServer(
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
grpc_ctxtags.StreamServerInterceptor(),
grpc_opentracing.StreamServerInterceptor(),
grpc_ctxtags.StreamServerInterceptor(grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.CodeGenRequestFieldExtractor)),
grpc_opentracing.StreamServerInterceptor(grpc_opentracing.WithTracer(tracer)),
grpc_prometheus.StreamServerInterceptor,
grpc_logrus.StreamServerInterceptor(logrusEntry),
grpc_recovery.StreamServerInterceptor(),
)),
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
grpc_ctxtags.UnaryServerInterceptor(),
grpc_opentracing.UnaryServerInterceptor(),
grpc_ctxtags.UnaryServerInterceptor(grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.CodeGenRequestFieldExtractor)),
grpc_opentracing.UnaryServerInterceptor(grpc_opentracing.WithTracer(tracer)),
grpc_prometheus.UnaryServerInterceptor,
grpc_logrus.UnaryServerInterceptor(logrusEntry),
grpc_recovery.UnaryServerInterceptor(),
)),
)

// Connect to PostgresQL
db := pg.Connect(&pg.Options{
User: c.String("db-user"),
Password: c.String("db-password"),
Expand All @@ -77,6 +108,7 @@ func start(c *cli.Context) {
// Create Table from Todo struct generated by gRPC
db.CreateTable(&api.Todo{}, nil)

// Register Todo service, prometheus and HTTP service handler
api.RegisterTodoServiceServer(server, &todo.Service{DB: db})
grpc_prometheus.Register(server)
mux := runtime.NewServeMux()
Expand All @@ -94,3 +126,38 @@ func start(c *cli.Context) {
}
http.ListenAndServe(c.String("bind-http"), mux)
}

func newTracing(service, jaegerHost string, metrics metrics.Factory, logger *log.Entry, sampler float64) (tracer opentracing.Tracer, closer io.Closer, err error) {
cfg := config.Configuration{
Sampler: &config.SamplerConfig{
Type: "const",
Param: sampler,
},
Reporter: &config.ReporterConfig{
LogSpans: false,
BufferFlushInterval: 1 * time.Second,
LocalAgentHostPort: jaegerHost,
},
}
tracer, closer, err = cfg.New(
service,
config.Logger(jaegerLoggerAdapter{logger}),
config.Observer(rpcmetrics.NewObserver(metricsFactory, rpcmetrics.DefaultNameNormalizer)),
)
if err != nil {
logger.Fatalf("cannot initialize Jaeger Tracer %s", err)
}
return
}

type jaegerLoggerAdapter struct {
logger *log.Entry
}

func (l jaegerLoggerAdapter) Error(msg string) {
l.logger.Error(msg)
}

func (l jaegerLoggerAdapter) Infof(msg string, args ...interface{}) {
l.logger.Info(fmt.Sprintf(msg, args...))
}
Loading

0 comments on commit a1372c6

Please sign in to comment.