An open API service indexing awesome lists of open source software.

https://github.com/objenious/kitty

A microservice framework extending go-kit
https://github.com/objenious/kitty

Last synced: 5 months ago
JSON representation

A microservice framework extending go-kit

Awesome Lists containing this project

README

          

# kitty
[![Travis-CI](https://travis-ci.org/objenious/kitty.svg?branch=master)](https://travis-ci.org/objenious/kitty) [![GoDoc](https://godoc.org/github.com/objenious/kitty?status.svg)](http://godoc.org/github.com/objenious/kitty)
[![GoReportCard](https://goreportcard.com/badge/github.com/objenious/kitty)](https://goreportcard.com/report/github.com/objenious/kitty)
[![Coverage Status](https://coveralls.io/repos/github/objenious/kitty/badge.svg?branch=master)](https://coveralls.io/github/objenious/kitty?branch=master)

`go get github.com/objenious/kitty`

Kitty is a slightly opinionated framework based on go-kit.
It's goal is to ease development of microservices deployed on Kubernetes (or any similar orchestration platform).

Kitty has an opinion on:
* transports: HTTP only (additional transports can be added as long as they implement kitty.Transport, a Google Pub/Sub transport is available as a separate package),
* errors: an error may be Retryable (e.g. 5XX status codes) or not (e.g. 4XX status codes),
* status codes: unless specified, request decoding errors will generate 400 HTTP status codes.

Kitty has no opinion on:
* logging: no logs are generated by default, you can plug your logger and it will get additional context,
* packages: kitty only imports go-kit and the standard library,
* routers: you can use any router (a Gorilla Mux implementation is available in a sub-package, other routers can easily be plugged),
* encoding: use whatever encoding you want (JSON, messagepack, protobuf, ...),
* monitoring, metrics and tracing: use Istio, a sidecar process or a middleware.

Kitty includes 2 sub-packages:
* backoff: Retryable-aware exponential backoff (only Retryable errors trigger retries),
* circuitbreaker: Retryable-aware circuit breaker (only Retryable errors trigger the circuit breaker).

## Example

Server-side
```
t := kitty.NewHTTPTransport(kitty.Config{HTTPPort: 8081}).
Router(gorilla.Router()).
Endpoint("POST", "/foo", Foo, kitty.Decoder(decodeFooRequest)).
Endpoint("GET", "/bar", Bar)

kitty.NewServer(t).Run(ctx)

// Foo is a go-kit Endpoint
func Foo(ctx context.Context, request interface{}) (interface{}, error) {
fr := request.(fooRequest)
return fooResponse{Message: fmt.Sprintf("Good morning %s !", fr.Name)}, nil
}

// decodeFooRequest
func decodeFooRequest(ctx context.Context, r *http.Request) (interface{}, error) {
var request fooRequest
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
return nil, err
}
return request, nil
}
```

Client-side (with circuit breaker & exponential backoff)
```
u, err := url.Parse("http://example.com/foo")
e := kitty.NewClient(
"POST",
u,
kithttp.EncodeJSONRequest,
decodeFooResponse
).Endpoint()
cb := gobreaker.NewCircuitBreaker(gobreaker.Settings{Name: "foo"})
e = kittycircuitbreaker.NewCircuitBreaker(cb)(e)
bo := backoff.NewExponentialBackOff()
e = kittybackoff.NewBackoff(bo)(e)
```

## How-to

### Log requests

```
kitty.NewServer(t).
// Log as JSON
Logger(log.NewJSONLogger(log.NewSyncWriter(os.Stdout))).
// Add path and method to all log lines
LogContext("http-path", "http-method").
// Log request only if an error occurred
Middlewares(kitty.LogEndpoint(kitty.LogErrors))
```

### Integrate with Istio

TBD

### Integrate liveness/readiness checks

Using github.com/heptiolabs/healthcheck:
```
health := healthcheck.NewHandler()
health.AddLivenessCheck("goroutine-threshold", healthcheck.GoroutineCountCheck(100))
health.AddReadinessCheck("database", healthcheck.DatabasePingCheck(db, 1*time.Second))

t := kitty.NewTransport(kitty.Config{}).Liveness(health.LiveEndpoint).Readiness(health.ReadyEndpoint)
```

### Use Google Pub/Sub as a transport

https://github.com/objenious/kitty-gcp adds a Google Pub/Sub transport to kitty:
```
import "github.com/objenious/kitty-gcp/pubsub"

tr := pubsub.NewTransport(ctx, "project-id").
Endpoint(subscriptionName, endpoint, Decoder(decodeFunc))
err := kitty.NewServer(tr).Run(ctx)
```

## Requirements

Go > 1.11

## Contribution guidelines

Contributions are welcome, as long as :
* unit tests & comments are included,
* no external package is added to the top-level package (implementations can be added as sub-packages).

## Thanks

kitty is heavily inspired by gizmo/kit (https://godoc.org/github.com/NYTimes/gizmo/server/kit),
with a different approach to server setup and without the gRPC clutter.

## License

MIT - See LICENSE file