pax_global_header 0000666 0000000 0000000 00000000064 13622563124 0014516 g ustar 00root root 0000000 0000000 52 comment=cc938d52e0cdf4c811ab203f428fcd06f9d9a148
golang-github-go-kit-kit-0.10.0/ 0000775 0000000 0000000 00000000000 13622563124 0016300 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/.build.yml 0000664 0000000 0000000 00000001171 13622563124 0020200 0 ustar 00root root 0000000 0000000 image: debian/stable
packages:
- wget
sources:
- https://github.com/go-kit/kit
tasks:
- go_toolchain: |
go_version="$(wget -q -O- https://golang.org/VERSION?m=text)"
wget -q https://dl.google.com/go/$go_version.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf $go_version.linux-amd64.tar.gz
sudo ln -s /usr/local/go/bin/go /usr/bin/go
go env
- dependencies: |
mkdir -p $(go env GOPATH)/src/github.com/go-kit
mv kit $(go env GOPATH)/src/github.com/go-kit
go get -t github.com/go-kit/kit/...
- test: |
go test -race -v github.com/go-kit/kit/...
golang-github-go-kit-kit-0.10.0/.github/ 0000775 0000000 0000000 00000000000 13622563124 0017640 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/.github/FUNDING.yml 0000664 0000000 0000000 00000000106 13622563124 0021452 0 ustar 00root root 0000000 0000000 # These are supported funding model platforms
github: [peterbourgon]
golang-github-go-kit-kit-0.10.0/.gitignore 0000664 0000000 0000000 00000001244 13622563124 0020271 0 ustar 00root root 0000000 0000000 examples/addsvc/addsvc
examples/addsvc/client/client
examples/apigateway/apigateway
examples/profilesvc/profilesvc
examples/stringsvc1/stringsvc1
examples/stringsvc2/stringsvc2
examples/stringsvc3/stringsvc3
*.coverprofile
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
_old*
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
# https://github.com/github/gitignore/blob/master/Global/Vim.gitignore
# swap
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
# session
Session.vim
# temporary
.netrwhist
*~
# auto-generated tag files
tags
golang-github-go-kit-kit-0.10.0/.travis.yml 0000664 0000000 0000000 00000000364 13622563124 0020414 0 ustar 00root root 0000000 0000000 language: go
env:
- COVERALLS_TOKEN=MYSkSqcsWXd6DmP6TnSeiDhtvuL4u6ndp
before_install:
- go get github.com/mattn/goveralls
- go get github.com/modocache/gover
script:
- go test -race -v ./...
- ./coveralls.bash
go:
- 1.x
- tip
golang-github-go-kit-kit-0.10.0/CONTRIBUTING.md 0000664 0000000 0000000 00000001507 13622563124 0020534 0 ustar 00root root 0000000 0000000 # Contributing
First, thank you for contributing! We love and encourage pull requests from everyone.
Before submitting major changes, here are a few guidelines to follow:
1. Check the [open issues][issues] and [pull requests][prs] for existing discussions.
1. Open an [issue][issues] first, to discuss a new feature or enhancement.
1. Write tests, and make sure the test suite passes locally and on CI.
1. Open a pull request, and reference the relevant issue(s).
1. After receiving feedback, [squash your commits][squash] and add a [great commit message][message].
1. Have fun!
[issues]: https://github.com/go-kit/kit/issues
[prs]: https://github.com/go-kit/kit/pulls
[squash]: http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html
[message]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
golang-github-go-kit-kit-0.10.0/LICENSE 0000664 0000000 0000000 00000002071 13622563124 0017305 0 ustar 00root root 0000000 0000000 The MIT License (MIT)
Copyright (c) 2015 Peter Bourgon
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
golang-github-go-kit-kit-0.10.0/README.md 0000664 0000000 0000000 00000014532 13622563124 0017564 0 ustar 00root root 0000000 0000000 # Go kit
[](https://circleci.com/gh/go-kit/kit) [](https://travis-ci.org/go-kit/kit) [](https://builds.sr.ht/~peterbourgon/kit?) [](https://godoc.org/github.com/go-kit/kit) [](https://coveralls.io/github/go-kit/kit?branch=master) [](https://goreportcard.com/report/go-kit/kit) [](https://sourcegraph.com/github.com/go-kit/kit?badge)
**Go kit** is a **programming toolkit** for building microservices
(or elegant monoliths) in Go. We solve common problems in distributed
systems and application architecture so you can focus on delivering
business value.
- Website: [gokit.io](https://gokit.io)
- Mailing list: [go-kit](https://groups.google.com/forum/#!forum/go-kit)
- Slack: [gophers.slack.com](https://gophers.slack.com) **#go-kit** ([invite](https://gophersinvite.herokuapp.com/))
## Sponsors
- [OrderMyGear](https://www.ordermygear.com)
Click on Sponsor, above, for more information on sponsorship.
## Motivation
Go has emerged as the language of the server, but it remains underrepresented
in so-called "modern enterprise" companies like Facebook, Twitter, Netflix, and
SoundCloud. Many of these organizations have turned to JVM-based stacks for
their business logic, owing in large part to libraries and ecosystems that
directly support their microservice architectures.
To reach its next level of success, Go needs more than simple primitives and
idioms. It needs a comprehensive toolkit, for coherent distributed programming
in the large. Go kit is a set of packages and best practices, which provide a
comprehensive, robust, and trustable way of building microservices for
organizations of any size.
For more details, see
[the website](https://gokit.io),
[the motivating blog post](http://peter.bourgon.org/go-kit/) and
[the video of the talk](https://www.youtube.com/watch?v=iFR_7AKkJFU).
See also the
[Go kit talk at GopherCon 2015](https://www.youtube.com/watch?v=1AjaZi4QuGo).
## Goals
- Operate in a heterogeneous SOA — expect to interact with mostly non-Go-kit services
- RPC as the primary messaging pattern
- Pluggable serialization and transport — not just JSON over HTTP
- Operate within existing infrastructures — no mandates for specific tools or technologies
## Non-goals
- Supporting messaging patterns other than RPC (for now) — e.g. MPI, pub/sub, CQRS, etc.
- Re-implementing functionality that can be provided by adapting existing software
- Having opinions on operational concerns: deployment, configuration, process supervision, orchestration, etc.
## Contributing
Please see [CONTRIBUTING.md](/CONTRIBUTING.md).
Thank you, [contributors](https://github.com/go-kit/kit/graphs/contributors)!
## Dependency management
Go kit is [modules](https://github.com/golang/go/wiki/Modules) aware, and we
encourage users to use the standard modules tooling. But Go kit is at major
version 0, so it should be compatible with non-modules environments.
## Related projects
Projects with a ★ have had particular influence on Go kit's design (or vice-versa).
### Service frameworks
- [gizmo](https://github.com/nytimes/gizmo), a microservice toolkit from The New York Times ★
- [go-micro](https://github.com/myodc/go-micro), a microservices client/server library ★
- [gotalk](https://github.com/rsms/gotalk), async peer communication protocol & library
- [Kite](https://github.com/koding/kite), a micro-service framework
- [gocircuit](https://github.com/gocircuit/circuit), dynamic cloud orchestration
### Individual components
- [afex/hystrix-go](https://github.com/afex/hystrix-go), client-side latency and fault tolerance library
- [armon/go-metrics](https://github.com/armon/go-metrics), library for exporting performance and runtime metrics to external metrics systems
- [codahale/lunk](https://github.com/codahale/lunk), structured logging in the style of Google's Dapper or Twitter's Zipkin
- [eapache/go-resiliency](https://github.com/eapache/go-resiliency), resiliency patterns
- [sasbury/logging](https://github.com/sasbury/logging), a tagged style of logging
- [grpc/grpc-go](https://github.com/grpc/grpc-go), HTTP/2 based RPC
- [inconshreveable/log15](https://github.com/inconshreveable/log15), simple, powerful logging for Go ★
- [mailgun/vulcand](https://github.com/vulcand/vulcand), programmatic load balancer backed by etcd
- [mattheath/phosphor](https://github.com/mondough/phosphor), distributed system tracing
- [pivotal-golang/lager](https://github.com/pivotal-golang/lager), an opinionated logging library
- [rubyist/circuitbreaker](https://github.com/rubyist/circuitbreaker), circuit breaker library
- [sirupsen/logrus](https://github.com/sirupsen/logrus), structured, pluggable logging for Go ★
- [sourcegraph/appdash](https://github.com/sourcegraph/appdash), application tracing system based on Google's Dapper
- [spacemonkeygo/monitor](https://github.com/spacemonkeygo/monitor), data collection, monitoring, instrumentation, and Zipkin client library
- [streadway/handy](https://github.com/streadway/handy), net/http handler filters
- [vitess/rpcplus](https://godoc.org/github.com/youtube/vitess/go/rpcplus), package rpc + context.Context
- [gdamore/mangos](https://github.com/gdamore/mangos), nanomsg implementation in pure Go
### Web frameworks
- [Gorilla](http://www.gorillatoolkit.org)
- [Gin](https://gin-gonic.com/)
- [Negroni](https://github.com/codegangsta/negroni)
- [Goji](https://github.com/zenazn/goji)
- [Martini](https://github.com/go-martini/martini)
- [Beego](http://beego.me/)
- [Revel](https://revel.github.io/) (considered [harmful](https://github.com/go-kit/kit/issues/350))
- [GoBuffalo](https://gobuffalo.io/)
## Additional reading
- [Architecting for the Cloud](https://slideshare.net/stonse/architecting-for-the-cloud-using-netflixoss-codemash-workshop-29852233) — Netflix
- [Dapper, a Large-Scale Distributed Systems Tracing Infrastructure](http://research.google.com/pubs/pub36356.html) — Google
- [Your Server as a Function](http://monkey.org/~marius/funsrv.pdf) (PDF) — Twitter
golang-github-go-kit-kit-0.10.0/auth/ 0000775 0000000 0000000 00000000000 13622563124 0017241 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/auth/basic/ 0000775 0000000 0000000 00000000000 13622563124 0020322 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/auth/basic/README.md 0000664 0000000 0000000 00000001562 13622563124 0021605 0 ustar 00root root 0000000 0000000 This package provides a Basic Authentication middleware.
It'll try to compare credentials from Authentication request header to a username/password pair in middleware constructor.
More details about this type of authentication can be found in [Mozilla article](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication).
## Usage
```go
import httptransport "github.com/go-kit/kit/transport/http"
httptransport.NewServer(
AuthMiddleware(cfg.auth.user, cfg.auth.password, "Example Realm")(makeUppercaseEndpoint()),
decodeMappingsRequest,
httptransport.EncodeJSONResponse,
httptransport.ServerBefore(httptransport.PopulateRequestContext),
)
```
For AuthMiddleware to be able to pick up the Authentication header from an HTTP request we need to pass it through the context with something like ```httptransport.ServerBefore(httptransport.PopulateRequestContext)```. golang-github-go-kit-kit-0.10.0/auth/basic/middleware.go 0000664 0000000 0000000 00000004767 13622563124 0023004 0 ustar 00root root 0000000 0000000 package basic
import (
"bytes"
"context"
"crypto/sha256"
"crypto/subtle"
"encoding/base64"
"fmt"
"net/http"
"strings"
"github.com/go-kit/kit/endpoint"
httptransport "github.com/go-kit/kit/transport/http"
)
// AuthError represents an authorization error.
type AuthError struct {
Realm string
}
// StatusCode is an implementation of the StatusCoder interface in go-kit/http.
func (AuthError) StatusCode() int {
return http.StatusUnauthorized
}
// Error is an implementation of the Error interface.
func (AuthError) Error() string {
return http.StatusText(http.StatusUnauthorized)
}
// Headers is an implementation of the Headerer interface in go-kit/http.
func (e AuthError) Headers() http.Header {
return http.Header{
"Content-Type": []string{"text/plain; charset=utf-8"},
"X-Content-Type-Options": []string{"nosniff"},
"WWW-Authenticate": []string{fmt.Sprintf(`Basic realm=%q`, e.Realm)},
}
}
// parseBasicAuth parses an HTTP Basic Authentication string.
// "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" returns ([]byte("Aladdin"), []byte("open sesame"), true).
func parseBasicAuth(auth string) (username, password []byte, ok bool) {
const prefix = "Basic "
if !strings.HasPrefix(auth, prefix) {
return
}
c, err := base64.StdEncoding.DecodeString(auth[len(prefix):])
if err != nil {
return
}
s := bytes.IndexByte(c, ':')
if s < 0 {
return
}
return c[:s], c[s+1:], true
}
// Returns a hash of a given slice.
func toHashSlice(s []byte) []byte {
hash := sha256.Sum256(s)
return hash[:]
}
// AuthMiddleware returns a Basic Authentication middleware for a particular user and password.
func AuthMiddleware(requiredUser, requiredPassword, realm string) endpoint.Middleware {
requiredUserBytes := toHashSlice([]byte(requiredUser))
requiredPasswordBytes := toHashSlice([]byte(requiredPassword))
return func(next endpoint.Endpoint) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
auth, ok := ctx.Value(httptransport.ContextKeyRequestAuthorization).(string)
if !ok {
return nil, AuthError{realm}
}
givenUser, givenPassword, ok := parseBasicAuth(auth)
if !ok {
return nil, AuthError{realm}
}
givenUserBytes := toHashSlice(givenUser)
givenPasswordBytes := toHashSlice(givenPassword)
if subtle.ConstantTimeCompare(givenUserBytes, requiredUserBytes) == 0 ||
subtle.ConstantTimeCompare(givenPasswordBytes, requiredPasswordBytes) == 0 {
return nil, AuthError{realm}
}
return next(ctx, request)
}
}
}
golang-github-go-kit-kit-0.10.0/auth/basic/middleware_test.go 0000664 0000000 0000000 00000003276 13622563124 0024035 0 ustar 00root root 0000000 0000000 package basic
import (
"context"
"encoding/base64"
"fmt"
"testing"
httptransport "github.com/go-kit/kit/transport/http"
)
func TestWithBasicAuth(t *testing.T) {
requiredUser := "test-user"
requiredPassword := "test-pass"
realm := "test realm"
type want struct {
result interface{}
err error
}
tests := []struct {
name string
authHeader interface{}
want want
}{
{"Isn't valid with nil header", nil, want{nil, AuthError{realm}}},
{"Isn't valid with non-string header", 42, want{nil, AuthError{realm}}},
{"Isn't valid without authHeader", "", want{nil, AuthError{realm}}},
{"Isn't valid for wrong user", makeAuthString("wrong-user", requiredPassword), want{nil, AuthError{realm}}},
{"Isn't valid for wrong password", makeAuthString(requiredUser, "wrong-password"), want{nil, AuthError{realm}}},
{"Is valid for correct creds", makeAuthString(requiredUser, requiredPassword), want{true, nil}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.WithValue(context.TODO(), httptransport.ContextKeyRequestAuthorization, tt.authHeader)
result, err := AuthMiddleware(requiredUser, requiredPassword, realm)(passedValidation)(ctx, nil)
if result != tt.want.result || err != tt.want.err {
t.Errorf("WithBasicAuth() = result: %v, err: %v, want result: %v, want error: %v", result, err, tt.want.result, tt.want.err)
}
})
}
}
func makeAuthString(user string, password string) string {
data := []byte(fmt.Sprintf("%s:%s", user, password))
return fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString(data))
}
func passedValidation(ctx context.Context, request interface{}) (response interface{}, err error) {
return true, nil
}
golang-github-go-kit-kit-0.10.0/auth/casbin/ 0000775 0000000 0000000 00000000000 13622563124 0020500 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/auth/casbin/middleware.go 0000664 0000000 0000000 00000004412 13622563124 0023145 0 ustar 00root root 0000000 0000000 package casbin
import (
"context"
"errors"
stdcasbin "github.com/casbin/casbin/v2"
"github.com/go-kit/kit/endpoint"
)
type contextKey string
const (
// CasbinModelContextKey holds the key to store the access control model
// in context, it can be a path to configuration file or a casbin/model
// Model.
CasbinModelContextKey contextKey = "CasbinModel"
// CasbinPolicyContextKey holds the key to store the access control policy
// in context, it can be a path to policy file or an implementation of
// casbin/persist Adapter interface.
CasbinPolicyContextKey contextKey = "CasbinPolicy"
// CasbinEnforcerContextKey holds the key to retrieve the active casbin
// Enforcer.
CasbinEnforcerContextKey contextKey = "CasbinEnforcer"
)
var (
// ErrModelContextMissing denotes a casbin model was not passed into
// the parsing of middleware's context.
ErrModelContextMissing = errors.New("CasbinModel is required in context")
// ErrPolicyContextMissing denotes a casbin policy was not passed into
// the parsing of middleware's context.
ErrPolicyContextMissing = errors.New("CasbinPolicy is required in context")
// ErrUnauthorized denotes the subject is not authorized to do the action
// intended on the given object, based on the context model and policy.
ErrUnauthorized = errors.New("Unauthorized Access")
)
// NewEnforcer checks whether the subject is authorized to do the specified
// action on the given object. If a valid access control model and policy
// is given, then the generated casbin Enforcer is stored in the context
// with CasbinEnforcer as the key.
func NewEnforcer(
subject string, object interface{}, action string,
) endpoint.Middleware {
return func(next endpoint.Endpoint) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
casbinModel := ctx.Value(CasbinModelContextKey)
casbinPolicy := ctx.Value(CasbinPolicyContextKey)
enforcer, err := stdcasbin.NewEnforcer(casbinModel, casbinPolicy)
if err != nil {
return nil, err
}
ctx = context.WithValue(ctx, CasbinEnforcerContextKey, enforcer)
ok, err := enforcer.Enforce(subject, object, action)
if err != nil {
return nil, err
}
if !ok {
return nil, ErrUnauthorized
}
return next(ctx, request)
}
}
}
golang-github-go-kit-kit-0.10.0/auth/casbin/middleware_test.go 0000664 0000000 0000000 00000003416 13622563124 0024207 0 ustar 00root root 0000000 0000000 package casbin
import (
"context"
"testing"
stdcasbin "github.com/casbin/casbin/v2"
"github.com/casbin/casbin/v2/model"
fileadapter "github.com/casbin/casbin/v2/persist/file-adapter"
)
func TestStructBaseContext(t *testing.T) {
e := func(ctx context.Context, i interface{}) (interface{}, error) { return ctx, nil }
m := model.NewModel()
m.AddDef("r", "r", "sub, obj, act")
m.AddDef("p", "p", "sub, obj, act")
m.AddDef("e", "e", "some(where (p.eft == allow))")
m.AddDef("m", "m", "r.sub == p.sub && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act)")
a := fileadapter.NewAdapter("testdata/keymatch_policy.csv")
ctx := context.WithValue(context.Background(), CasbinModelContextKey, m)
ctx = context.WithValue(ctx, CasbinPolicyContextKey, a)
// positive case
middleware := NewEnforcer("alice", "/alice_data/resource1", "GET")(e)
ctx1, err := middleware(ctx, struct{}{})
if err != nil {
t.Fatalf("Enforcer returned error: %s", err)
}
_, ok := ctx1.(context.Context).Value(CasbinEnforcerContextKey).(*stdcasbin.Enforcer)
if !ok {
t.Fatalf("context should contains the active enforcer")
}
// negative case
middleware = NewEnforcer("alice", "/alice_data/resource2", "POST")(e)
_, err = middleware(ctx, struct{}{})
if err == nil {
t.Fatalf("Enforcer should return error")
}
}
func TestFileBaseContext(t *testing.T) {
e := func(ctx context.Context, i interface{}) (interface{}, error) { return ctx, nil }
ctx := context.WithValue(context.Background(), CasbinModelContextKey, "testdata/basic_model.conf")
ctx = context.WithValue(ctx, CasbinPolicyContextKey, "testdata/basic_policy.csv")
// positive case
middleware := NewEnforcer("alice", "data1", "read")(e)
_, err := middleware(ctx, struct{}{})
if err != nil {
t.Fatalf("Enforcer returned error: %s", err)
}
}
golang-github-go-kit-kit-0.10.0/auth/casbin/testdata/ 0000775 0000000 0000000 00000000000 13622563124 0022311 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/auth/casbin/testdata/basic_model.conf 0000664 0000000 0000000 00000000302 13622563124 0025414 0 ustar 00root root 0000000 0000000 [request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act golang-github-go-kit-kit-0.10.0/auth/casbin/testdata/basic_policy.csv 0000664 0000000 0000000 00000000052 13622563124 0025463 0 ustar 00root root 0000000 0000000 p, alice, data1, read
p, bob, data2, write golang-github-go-kit-kit-0.10.0/auth/casbin/testdata/keymatch_policy.csv 0000664 0000000 0000000 00000000245 13622563124 0026213 0 ustar 00root root 0000000 0000000 p, alice, /alice_data/*, GET
p, alice, /alice_data/resource1, POST
p, bob, /alice_data/resource2, GET
p, bob, /bob_data/*, POST
p, cathy, /cathy_data, (GET)|(POST) golang-github-go-kit-kit-0.10.0/auth/jwt/ 0000775 0000000 0000000 00000000000 13622563124 0020045 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/auth/jwt/README.md 0000664 0000000 0000000 00000006237 13622563124 0021334 0 ustar 00root root 0000000 0000000 # package auth/jwt
`package auth/jwt` provides a set of interfaces for service authorization
through [JSON Web Tokens](https://jwt.io/).
## Usage
NewParser takes a key function and an expected signing method and returns an
`endpoint.Middleware`. The middleware will parse a token passed into the
context via the `jwt.JWTTokenContextKey`. If the token is valid, any claims
will be added to the context via the `jwt.JWTClaimsContextKey`.
```go
import (
stdjwt "github.com/dgrijalva/jwt-go"
"github.com/go-kit/kit/auth/jwt"
"github.com/go-kit/kit/endpoint"
)
func main() {
var exampleEndpoint endpoint.Endpoint
{
kf := func(token *stdjwt.Token) (interface{}, error) { return []byte("SigningString"), nil }
exampleEndpoint = MakeExampleEndpoint(service)
exampleEndpoint = jwt.NewParser(kf, stdjwt.SigningMethodHS256, jwt.StandardClaimsFactory)(exampleEndpoint)
}
}
```
NewSigner takes a JWT key ID header, the signing key, signing method, and a
claims object. It returns an `endpoint.Middleware`. The middleware will build
the token string and add it to the context via the `jwt.JWTTokenContextKey`.
```go
import (
stdjwt "github.com/dgrijalva/jwt-go"
"github.com/go-kit/kit/auth/jwt"
"github.com/go-kit/kit/endpoint"
)
func main() {
var exampleEndpoint endpoint.Endpoint
{
exampleEndpoint = grpctransport.NewClient(...).Endpoint()
exampleEndpoint = jwt.NewSigner(
"kid-header",
[]byte("SigningString"),
stdjwt.SigningMethodHS256,
jwt.Claims{},
)(exampleEndpoint)
}
}
```
In order for the parser and the signer to work, the authorization headers need
to be passed between the request and the context. `HTTPToContext()`,
`ContextToHTTP()`, `GRPCToContext()`, and `ContextToGRPC()` are given as
helpers to do this. These functions implement the correlating transport's
RequestFunc interface and can be passed as ClientBefore or ServerBefore
options.
Example of use in a client:
```go
import (
stdjwt "github.com/dgrijalva/jwt-go"
grpctransport "github.com/go-kit/kit/transport/grpc"
"github.com/go-kit/kit/auth/jwt"
"github.com/go-kit/kit/endpoint"
)
func main() {
options := []httptransport.ClientOption{}
var exampleEndpoint endpoint.Endpoint
{
exampleEndpoint = grpctransport.NewClient(..., grpctransport.ClientBefore(jwt.ContextToGRPC())).Endpoint()
exampleEndpoint = jwt.NewSigner(
"kid-header",
[]byte("SigningString"),
stdjwt.SigningMethodHS256,
jwt.Claims{},
)(exampleEndpoint)
}
}
```
Example of use in a server:
```go
import (
"context"
"github.com/go-kit/kit/auth/jwt"
"github.com/go-kit/kit/log"
grpctransport "github.com/go-kit/kit/transport/grpc"
)
func MakeGRPCServer(ctx context.Context, endpoints Endpoints, logger log.Logger) pb.ExampleServer {
options := []grpctransport.ServerOption{grpctransport.ServerErrorLogger(logger)}
return &grpcServer{
createUser: grpctransport.NewServer(
ctx,
endpoints.CreateUserEndpoint,
DecodeGRPCCreateUserRequest,
EncodeGRPCCreateUserResponse,
append(options, grpctransport.ServerBefore(jwt.GRPCToContext()))...,
),
getUser: grpctransport.NewServer(
ctx,
endpoints.GetUserEndpoint,
DecodeGRPCGetUserRequest,
EncodeGRPCGetUserResponse,
options...,
),
}
}
```
golang-github-go-kit-kit-0.10.0/auth/jwt/middleware.go 0000664 0000000 0000000 00000011366 13622563124 0022520 0 ustar 00root root 0000000 0000000 package jwt
import (
"context"
"errors"
jwt "github.com/dgrijalva/jwt-go"
"github.com/go-kit/kit/endpoint"
)
type contextKey string
const (
// JWTTokenContextKey holds the key used to store a JWT Token in the
// context.
JWTTokenContextKey contextKey = "JWTToken"
// JWTClaimsContextKey holds the key used to store the JWT Claims in the
// context.
JWTClaimsContextKey contextKey = "JWTClaims"
)
var (
// ErrTokenContextMissing denotes a token was not passed into the parsing
// middleware's context.
ErrTokenContextMissing = errors.New("token up for parsing was not passed through the context")
// ErrTokenInvalid denotes a token was not able to be validated.
ErrTokenInvalid = errors.New("JWT Token was invalid")
// ErrTokenExpired denotes a token's expire header (exp) has since passed.
ErrTokenExpired = errors.New("JWT Token is expired")
// ErrTokenMalformed denotes a token was not formatted as a JWT token.
ErrTokenMalformed = errors.New("JWT Token is malformed")
// ErrTokenNotActive denotes a token's not before header (nbf) is in the
// future.
ErrTokenNotActive = errors.New("token is not valid yet")
// ErrUnexpectedSigningMethod denotes a token was signed with an unexpected
// signing method.
ErrUnexpectedSigningMethod = errors.New("unexpected signing method")
)
// NewSigner creates a new JWT token generating middleware, specifying key ID,
// signing string, signing method and the claims you would like it to contain.
// Tokens are signed with a Key ID header (kid) which is useful for determining
// the key to use for parsing. Particularly useful for clients.
func NewSigner(kid string, key []byte, method jwt.SigningMethod, claims jwt.Claims) endpoint.Middleware {
return func(next endpoint.Endpoint) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
token := jwt.NewWithClaims(method, claims)
token.Header["kid"] = kid
// Sign and get the complete encoded token as a string using the secret
tokenString, err := token.SignedString(key)
if err != nil {
return nil, err
}
ctx = context.WithValue(ctx, JWTTokenContextKey, tokenString)
return next(ctx, request)
}
}
}
// ClaimsFactory is a factory for jwt.Claims.
// Useful in NewParser middleware.
type ClaimsFactory func() jwt.Claims
// MapClaimsFactory is a ClaimsFactory that returns
// an empty jwt.MapClaims.
func MapClaimsFactory() jwt.Claims {
return jwt.MapClaims{}
}
// StandardClaimsFactory is a ClaimsFactory that returns
// an empty jwt.StandardClaims.
func StandardClaimsFactory() jwt.Claims {
return &jwt.StandardClaims{}
}
// NewParser creates a new JWT token parsing middleware, specifying a
// jwt.Keyfunc interface, the signing method and the claims type to be used. NewParser
// adds the resulting claims to endpoint context or returns error on invalid token.
// Particularly useful for servers.
func NewParser(keyFunc jwt.Keyfunc, method jwt.SigningMethod, newClaims ClaimsFactory) endpoint.Middleware {
return func(next endpoint.Endpoint) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
// tokenString is stored in the context from the transport handlers.
tokenString, ok := ctx.Value(JWTTokenContextKey).(string)
if !ok {
return nil, ErrTokenContextMissing
}
// Parse takes the token string and a function for looking up the
// key. The latter is especially useful if you use multiple keys
// for your application. The standard is to use 'kid' in the head
// of the token to identify which key to use, but the parsed token
// (head and claims) is provided to the callback, providing
// flexibility.
token, err := jwt.ParseWithClaims(tokenString, newClaims(), func(token *jwt.Token) (interface{}, error) {
// Don't forget to validate the alg is what you expect:
if token.Method != method {
return nil, ErrUnexpectedSigningMethod
}
return keyFunc(token)
})
if err != nil {
if e, ok := err.(*jwt.ValidationError); ok {
switch {
case e.Errors&jwt.ValidationErrorMalformed != 0:
// Token is malformed
return nil, ErrTokenMalformed
case e.Errors&jwt.ValidationErrorExpired != 0:
// Token is expired
return nil, ErrTokenExpired
case e.Errors&jwt.ValidationErrorNotValidYet != 0:
// Token is not active yet
return nil, ErrTokenNotActive
case e.Inner != nil:
// report e.Inner
return nil, e.Inner
}
// We have a ValidationError but have no specific Go kit error for it.
// Fall through to return original error.
}
return nil, err
}
if !token.Valid {
return nil, ErrTokenInvalid
}
ctx = context.WithValue(ctx, JWTClaimsContextKey, token.Claims)
return next(ctx, request)
}
}
}
golang-github-go-kit-kit-0.10.0/auth/jwt/middleware_test.go 0000664 0000000 0000000 00000017167 13622563124 0023564 0 ustar 00root root 0000000 0000000 package jwt
import (
"context"
"sync"
"testing"
"time"
"crypto/subtle"
jwt "github.com/dgrijalva/jwt-go"
"github.com/go-kit/kit/endpoint"
)
type customClaims struct {
MyProperty string `json:"my_property"`
jwt.StandardClaims
}
func (c customClaims) VerifyMyProperty(p string) bool {
return subtle.ConstantTimeCompare([]byte(c.MyProperty), []byte(p)) != 0
}
var (
kid = "kid"
key = []byte("test_signing_key")
myProperty = "some value"
method = jwt.SigningMethodHS256
invalidMethod = jwt.SigningMethodRS256
mapClaims = jwt.MapClaims{"user": "go-kit"}
standardClaims = jwt.StandardClaims{Audience: "go-kit"}
myCustomClaims = customClaims{MyProperty: myProperty, StandardClaims: standardClaims}
// Signed tokens generated at https://jwt.io/
signedKey = "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtpZCIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiZ28ta2l0In0.14M2VmYyApdSlV_LZ88ajjwuaLeIFplB8JpyNy0A19E"
standardSignedKey = "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtpZCIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJnby1raXQifQ.L5ypIJjCOOv3jJ8G5SelaHvR04UJuxmcBN5QW3m_aoY"
customSignedKey = "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtpZCIsInR5cCI6IkpXVCJ9.eyJteV9wcm9wZXJ0eSI6InNvbWUgdmFsdWUiLCJhdWQiOiJnby1raXQifQ.s8F-IDrV4WPJUsqr7qfDi-3GRlcKR0SRnkTeUT_U-i0"
invalidKey = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.e30.vKVCKto-Wn6rgz3vBdaZaCBGfCBDTXOENSo_X2Gq7qA"
malformedKey = "malformed.jwt.token"
)
func signingValidator(t *testing.T, signer endpoint.Endpoint, expectedKey string) {
ctx, err := signer(context.Background(), struct{}{})
if err != nil {
t.Fatalf("Signer returned error: %s", err)
}
token, ok := ctx.(context.Context).Value(JWTTokenContextKey).(string)
if !ok {
t.Fatal("Token did not exist in context")
}
if token != expectedKey {
t.Fatalf("JWT tokens did not match: expecting %s got %s", expectedKey, token)
}
}
func TestNewSigner(t *testing.T) {
e := func(ctx context.Context, i interface{}) (interface{}, error) { return ctx, nil }
signer := NewSigner(kid, key, method, mapClaims)(e)
signingValidator(t, signer, signedKey)
signer = NewSigner(kid, key, method, standardClaims)(e)
signingValidator(t, signer, standardSignedKey)
signer = NewSigner(kid, key, method, myCustomClaims)(e)
signingValidator(t, signer, customSignedKey)
}
func TestJWTParser(t *testing.T) {
e := func(ctx context.Context, i interface{}) (interface{}, error) { return ctx, nil }
keys := func(token *jwt.Token) (interface{}, error) {
return key, nil
}
parser := NewParser(keys, method, MapClaimsFactory)(e)
// No Token is passed into the parser
_, err := parser(context.Background(), struct{}{})
if err == nil {
t.Error("Parser should have returned an error")
}
if err != ErrTokenContextMissing {
t.Errorf("unexpected error returned, expected: %s got: %s", ErrTokenContextMissing, err)
}
// Invalid Token is passed into the parser
ctx := context.WithValue(context.Background(), JWTTokenContextKey, invalidKey)
_, err = parser(ctx, struct{}{})
if err == nil {
t.Error("Parser should have returned an error")
}
// Invalid Method is used in the parser
badParser := NewParser(keys, invalidMethod, MapClaimsFactory)(e)
ctx = context.WithValue(context.Background(), JWTTokenContextKey, signedKey)
_, err = badParser(ctx, struct{}{})
if err == nil {
t.Error("Parser should have returned an error")
}
if err != ErrUnexpectedSigningMethod {
t.Errorf("unexpected error returned, expected: %s got: %s", ErrUnexpectedSigningMethod, err)
}
// Invalid key is used in the parser
invalidKeys := func(token *jwt.Token) (interface{}, error) {
return []byte("bad"), nil
}
badParser = NewParser(invalidKeys, method, MapClaimsFactory)(e)
ctx = context.WithValue(context.Background(), JWTTokenContextKey, signedKey)
_, err = badParser(ctx, struct{}{})
if err == nil {
t.Error("Parser should have returned an error")
}
// Correct token is passed into the parser
ctx = context.WithValue(context.Background(), JWTTokenContextKey, signedKey)
ctx1, err := parser(ctx, struct{}{})
if err != nil {
t.Fatalf("Parser returned error: %s", err)
}
cl, ok := ctx1.(context.Context).Value(JWTClaimsContextKey).(jwt.MapClaims)
if !ok {
t.Fatal("Claims were not passed into context correctly")
}
if cl["user"] != mapClaims["user"] {
t.Fatalf("JWT Claims.user did not match: expecting %s got %s", mapClaims["user"], cl["user"])
}
// Test for malformed token error response
parser = NewParser(keys, method, StandardClaimsFactory)(e)
ctx = context.WithValue(context.Background(), JWTTokenContextKey, malformedKey)
ctx1, err = parser(ctx, struct{}{})
if want, have := ErrTokenMalformed, err; want != have {
t.Fatalf("Expected %+v, got %+v", want, have)
}
// Test for expired token error response
parser = NewParser(keys, method, StandardClaimsFactory)(e)
expired := jwt.NewWithClaims(method, jwt.StandardClaims{ExpiresAt: time.Now().Unix() - 100})
token, err := expired.SignedString(key)
if err != nil {
t.Fatalf("Unable to Sign Token: %+v", err)
}
ctx = context.WithValue(context.Background(), JWTTokenContextKey, token)
ctx1, err = parser(ctx, struct{}{})
if want, have := ErrTokenExpired, err; want != have {
t.Fatalf("Expected %+v, got %+v", want, have)
}
// Test for not activated token error response
parser = NewParser(keys, method, StandardClaimsFactory)(e)
notactive := jwt.NewWithClaims(method, jwt.StandardClaims{NotBefore: time.Now().Unix() + 100})
token, err = notactive.SignedString(key)
if err != nil {
t.Fatalf("Unable to Sign Token: %+v", err)
}
ctx = context.WithValue(context.Background(), JWTTokenContextKey, token)
ctx1, err = parser(ctx, struct{}{})
if want, have := ErrTokenNotActive, err; want != have {
t.Fatalf("Expected %+v, got %+v", want, have)
}
// test valid standard claims token
parser = NewParser(keys, method, StandardClaimsFactory)(e)
ctx = context.WithValue(context.Background(), JWTTokenContextKey, standardSignedKey)
ctx1, err = parser(ctx, struct{}{})
if err != nil {
t.Fatalf("Parser returned error: %s", err)
}
stdCl, ok := ctx1.(context.Context).Value(JWTClaimsContextKey).(*jwt.StandardClaims)
if !ok {
t.Fatal("Claims were not passed into context correctly")
}
if !stdCl.VerifyAudience("go-kit", true) {
t.Fatalf("JWT jwt.StandardClaims.Audience did not match: expecting %s got %s", standardClaims.Audience, stdCl.Audience)
}
// test valid customized claims token
parser = NewParser(keys, method, func() jwt.Claims { return &customClaims{} })(e)
ctx = context.WithValue(context.Background(), JWTTokenContextKey, customSignedKey)
ctx1, err = parser(ctx, struct{}{})
if err != nil {
t.Fatalf("Parser returned error: %s", err)
}
custCl, ok := ctx1.(context.Context).Value(JWTClaimsContextKey).(*customClaims)
if !ok {
t.Fatal("Claims were not passed into context correctly")
}
if !custCl.VerifyAudience("go-kit", true) {
t.Fatalf("JWT customClaims.Audience did not match: expecting %s got %s", standardClaims.Audience, custCl.Audience)
}
if !custCl.VerifyMyProperty(myProperty) {
t.Fatalf("JWT customClaims.MyProperty did not match: expecting %s got %s", myProperty, custCl.MyProperty)
}
}
func TestIssue562(t *testing.T) {
var (
kf = func(token *jwt.Token) (interface{}, error) { return []byte("secret"), nil }
e = NewParser(kf, jwt.SigningMethodHS256, MapClaimsFactory)(endpoint.Nop)
key = JWTTokenContextKey
val = "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtpZCIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiZ28ta2l0In0.14M2VmYyApdSlV_LZ88ajjwuaLeIFplB8JpyNy0A19E"
ctx = context.WithValue(context.Background(), key, val)
)
wg := sync.WaitGroup{}
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
e(ctx, struct{}{}) // fatal error: concurrent map read and map write
}()
}
wg.Wait()
}
golang-github-go-kit-kit-0.10.0/auth/jwt/transport.go 0000664 0000000 0000000 00000004313 13622563124 0022431 0 ustar 00root root 0000000 0000000 package jwt
import (
"context"
"fmt"
stdhttp "net/http"
"strings"
"google.golang.org/grpc/metadata"
"github.com/go-kit/kit/transport/grpc"
"github.com/go-kit/kit/transport/http"
)
const (
bearer string = "bearer"
bearerFormat string = "Bearer %s"
)
// HTTPToContext moves a JWT from request header to context. Particularly
// useful for servers.
func HTTPToContext() http.RequestFunc {
return func(ctx context.Context, r *stdhttp.Request) context.Context {
token, ok := extractTokenFromAuthHeader(r.Header.Get("Authorization"))
if !ok {
return ctx
}
return context.WithValue(ctx, JWTTokenContextKey, token)
}
}
// ContextToHTTP moves a JWT from context to request header. Particularly
// useful for clients.
func ContextToHTTP() http.RequestFunc {
return func(ctx context.Context, r *stdhttp.Request) context.Context {
token, ok := ctx.Value(JWTTokenContextKey).(string)
if ok {
r.Header.Add("Authorization", generateAuthHeaderFromToken(token))
}
return ctx
}
}
// GRPCToContext moves a JWT from grpc metadata to context. Particularly
// userful for servers.
func GRPCToContext() grpc.ServerRequestFunc {
return func(ctx context.Context, md metadata.MD) context.Context {
// capital "Key" is illegal in HTTP/2.
authHeader, ok := md["authorization"]
if !ok {
return ctx
}
token, ok := extractTokenFromAuthHeader(authHeader[0])
if ok {
ctx = context.WithValue(ctx, JWTTokenContextKey, token)
}
return ctx
}
}
// ContextToGRPC moves a JWT from context to grpc metadata. Particularly
// useful for clients.
func ContextToGRPC() grpc.ClientRequestFunc {
return func(ctx context.Context, md *metadata.MD) context.Context {
token, ok := ctx.Value(JWTTokenContextKey).(string)
if ok {
// capital "Key" is illegal in HTTP/2.
(*md)["authorization"] = []string{generateAuthHeaderFromToken(token)}
}
return ctx
}
}
func extractTokenFromAuthHeader(val string) (token string, ok bool) {
authHeaderParts := strings.Split(val, " ")
if len(authHeaderParts) != 2 || !strings.EqualFold(authHeaderParts[0], bearer) {
return "", false
}
return authHeaderParts[1], true
}
func generateAuthHeaderFromToken(token string) string {
return fmt.Sprintf(bearerFormat, token)
}
golang-github-go-kit-kit-0.10.0/auth/jwt/transport_test.go 0000664 0000000 0000000 00000006464 13622563124 0023501 0 ustar 00root root 0000000 0000000 package jwt
import (
"context"
"fmt"
"net/http"
"testing"
"google.golang.org/grpc/metadata"
)
func TestHTTPToContext(t *testing.T) {
reqFunc := HTTPToContext()
// When the header doesn't exist
ctx := reqFunc(context.Background(), &http.Request{})
if ctx.Value(JWTTokenContextKey) != nil {
t.Error("Context shouldn't contain the encoded JWT")
}
// Authorization header value has invalid format
header := http.Header{}
header.Set("Authorization", "no expected auth header format value")
ctx = reqFunc(context.Background(), &http.Request{Header: header})
if ctx.Value(JWTTokenContextKey) != nil {
t.Error("Context shouldn't contain the encoded JWT")
}
// Authorization header is correct
header.Set("Authorization", generateAuthHeaderFromToken(signedKey))
ctx = reqFunc(context.Background(), &http.Request{Header: header})
token := ctx.Value(JWTTokenContextKey).(string)
if token != signedKey {
t.Errorf("Context doesn't contain the expected encoded token value; expected: %s, got: %s", signedKey, token)
}
}
func TestContextToHTTP(t *testing.T) {
reqFunc := ContextToHTTP()
// No JWT Token is passed in the context
ctx := context.Background()
r := http.Request{}
reqFunc(ctx, &r)
token := r.Header.Get("Authorization")
if token != "" {
t.Error("authorization key should not exist in metadata")
}
// Correct JWT Token is passed in the context
ctx = context.WithValue(context.Background(), JWTTokenContextKey, signedKey)
r = http.Request{Header: http.Header{}}
reqFunc(ctx, &r)
token = r.Header.Get("Authorization")
expected := generateAuthHeaderFromToken(signedKey)
if token != expected {
t.Errorf("Authorization header does not contain the expected JWT token; expected %s, got %s", expected, token)
}
}
func TestGRPCToContext(t *testing.T) {
md := metadata.MD{}
reqFunc := GRPCToContext()
// No Authorization header is passed
ctx := reqFunc(context.Background(), md)
token := ctx.Value(JWTTokenContextKey)
if token != nil {
t.Error("Context should not contain a JWT Token")
}
// Invalid Authorization header is passed
md["authorization"] = []string{fmt.Sprintf("%s", signedKey)}
ctx = reqFunc(context.Background(), md)
token = ctx.Value(JWTTokenContextKey)
if token != nil {
t.Error("Context should not contain a JWT Token")
}
// Authorization header is correct
md["authorization"] = []string{fmt.Sprintf("Bearer %s", signedKey)}
ctx = reqFunc(context.Background(), md)
token, ok := ctx.Value(JWTTokenContextKey).(string)
if !ok {
t.Fatal("JWT Token not passed to context correctly")
}
if token != signedKey {
t.Errorf("JWT tokens did not match: expecting %s got %s", signedKey, token)
}
}
func TestContextToGRPC(t *testing.T) {
reqFunc := ContextToGRPC()
// No JWT Token is passed in the context
ctx := context.Background()
md := metadata.MD{}
reqFunc(ctx, &md)
_, ok := md["authorization"]
if ok {
t.Error("authorization key should not exist in metadata")
}
// Correct JWT Token is passed in the context
ctx = context.WithValue(context.Background(), JWTTokenContextKey, signedKey)
md = metadata.MD{}
reqFunc(ctx, &md)
token, ok := md["authorization"]
if !ok {
t.Fatal("JWT Token not passed to metadata correctly")
}
if token[0] != generateAuthHeaderFromToken(signedKey) {
t.Errorf("JWT tokens did not match: expecting %s got %s", signedKey, token[0])
}
}
golang-github-go-kit-kit-0.10.0/circle.yml 0000664 0000000 0000000 00000001475 13622563124 0020273 0 ustar 00root root 0000000 0000000 version: 2
jobs:
build:
machine: true
working_directory: /home/circleci/.go_workspace/src/github.com/go-kit/kit
environment:
ETCD_ADDR: http://localhost:2379
CONSUL_ADDR: localhost:8500
ZK_ADDR: localhost:2181
EUREKA_ADDR: http://localhost:8761/eureka
steps:
- checkout
- run: wget -q -O- https://golang.org/VERSION?m=text > go_version.txt
- run: wget -q https://storage.googleapis.com/golang/$(cat go_version.txt).linux-amd64.tar.gz
- run: sudo rm -rf /usr/local/go
- run: sudo tar -C /usr/local -xzf $(cat go_version.txt).linux-amd64.tar.gz
- run: docker-compose -f docker-compose-integration.yml up -d --force-recreate
- run: go get -t github.com/go-kit/kit/...
- run: go test -v -race -tags integration github.com/go-kit/kit/...
golang-github-go-kit-kit-0.10.0/circuitbreaker/ 0000775 0000000 0000000 00000000000 13622563124 0021276 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/circuitbreaker/doc.go 0000664 0000000 0000000 00000000722 13622563124 0022373 0 ustar 00root root 0000000 0000000 // Package circuitbreaker implements the circuit breaker pattern.
//
// Circuit breakers prevent thundering herds, and improve resiliency against
// intermittent errors. Every client-side endpoint should be wrapped in a
// circuit breaker.
//
// We provide several implementations in this package, but if you're looking
// for guidance, Gobreaker is probably the best place to start. It has a
// simple and intuitive API, and is well-tested.
package circuitbreaker
golang-github-go-kit-kit-0.10.0/circuitbreaker/gobreaker.go 0000664 0000000 0000000 00000001275 13622563124 0023573 0 ustar 00root root 0000000 0000000 package circuitbreaker
import (
"context"
"github.com/sony/gobreaker"
"github.com/go-kit/kit/endpoint"
)
// Gobreaker returns an endpoint.Middleware that implements the circuit
// breaker pattern using the sony/gobreaker package. Only errors returned by
// the wrapped endpoint count against the circuit breaker's error count.
//
// See http://godoc.org/github.com/sony/gobreaker for more information.
func Gobreaker(cb *gobreaker.CircuitBreaker) endpoint.Middleware {
return func(next endpoint.Endpoint) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
return cb.Execute(func() (interface{}, error) { return next(ctx, request) })
}
}
}
golang-github-go-kit-kit-0.10.0/circuitbreaker/gobreaker_test.go 0000664 0000000 0000000 00000001033 13622563124 0024622 0 ustar 00root root 0000000 0000000 package circuitbreaker_test
import (
"testing"
"github.com/sony/gobreaker"
"github.com/go-kit/kit/circuitbreaker"
)
func TestGobreaker(t *testing.T) {
var (
breaker = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{}))
primeWith = 100
shouldPass = func(n int) bool { return n <= 5 } // https://github.com/sony/gobreaker/blob/bfa846d/gobreaker.go#L76
circuitOpenError = "circuit breaker is open"
)
testFailingEndpoint(t, breaker, primeWith, shouldPass, 0, circuitOpenError)
}
golang-github-go-kit-kit-0.10.0/circuitbreaker/handy_breaker.go 0000664 0000000 0000000 00000001660 13622563124 0024426 0 ustar 00root root 0000000 0000000 package circuitbreaker
import (
"context"
"time"
"github.com/streadway/handy/breaker"
"github.com/go-kit/kit/endpoint"
)
// HandyBreaker returns an endpoint.Middleware that implements the circuit
// breaker pattern using the streadway/handy/breaker package. Only errors
// returned by the wrapped endpoint count against the circuit breaker's error
// count.
//
// See http://godoc.org/github.com/streadway/handy/breaker for more
// information.
func HandyBreaker(cb breaker.Breaker) endpoint.Middleware {
return func(next endpoint.Endpoint) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
if !cb.Allow() {
return nil, breaker.ErrCircuitOpen
}
defer func(begin time.Time) {
if err == nil {
cb.Success(time.Since(begin))
} else {
cb.Failure(time.Since(begin))
}
}(time.Now())
response, err = next(ctx, request)
return
}
}
}
golang-github-go-kit-kit-0.10.0/circuitbreaker/handy_breaker_test.go 0000664 0000000 0000000 00000001136 13622563124 0025463 0 ustar 00root root 0000000 0000000 package circuitbreaker_test
import (
"testing"
handybreaker "github.com/streadway/handy/breaker"
"github.com/go-kit/kit/circuitbreaker"
)
func TestHandyBreaker(t *testing.T) {
var (
failureRatio = 0.05
breaker = circuitbreaker.HandyBreaker(handybreaker.NewBreaker(failureRatio))
primeWith = handybreaker.DefaultMinObservations * 10
shouldPass = func(n int) bool { return (float64(n) / float64(primeWith+n)) <= failureRatio }
openCircuitError = handybreaker.ErrCircuitOpen.Error()
)
testFailingEndpoint(t, breaker, primeWith, shouldPass, 0, openCircuitError)
}
golang-github-go-kit-kit-0.10.0/circuitbreaker/hystrix.go 0000664 0000000 0000000 00000001476 13622563124 0023347 0 ustar 00root root 0000000 0000000 package circuitbreaker
import (
"context"
"github.com/afex/hystrix-go/hystrix"
"github.com/go-kit/kit/endpoint"
)
// Hystrix returns an endpoint.Middleware that implements the circuit
// breaker pattern using the afex/hystrix-go package.
//
// When using this circuit breaker, please configure your commands separately.
//
// See https://godoc.org/github.com/afex/hystrix-go/hystrix for more
// information.
func Hystrix(commandName string) endpoint.Middleware {
return func(next endpoint.Endpoint) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
var resp interface{}
if err := hystrix.Do(commandName, func() (err error) {
resp, err = next(ctx, request)
return err
}, nil); err != nil {
return nil, err
}
return resp, nil
}
}
}
golang-github-go-kit-kit-0.10.0/circuitbreaker/hystrix_test.go 0000664 0000000 0000000 00000002167 13622563124 0024404 0 ustar 00root root 0000000 0000000 package circuitbreaker_test
import (
"io/ioutil"
stdlog "log"
"testing"
"time"
"github.com/afex/hystrix-go/hystrix"
"github.com/go-kit/kit/circuitbreaker"
)
func TestHystrix(t *testing.T) {
stdlog.SetOutput(ioutil.Discard)
const (
commandName = "my-endpoint"
errorPercent = 5
maxConcurrent = 1000
)
hystrix.ConfigureCommand(commandName, hystrix.CommandConfig{
ErrorPercentThreshold: errorPercent,
MaxConcurrentRequests: maxConcurrent,
})
var (
breaker = circuitbreaker.Hystrix(commandName)
primeWith = hystrix.DefaultVolumeThreshold * 2
shouldPass = func(n int) bool { return (float64(n) / float64(primeWith+n)) <= (float64(errorPercent-1) / 100.0) }
openCircuitError = hystrix.ErrCircuitOpen.Error()
)
// hystrix-go uses buffered channels to receive reports on request success/failure,
// and so is basically impossible to test deterministically. We have to make sure
// the report buffer is emptied, by injecting a sleep between each invocation.
requestDelay := 5 * time.Millisecond
testFailingEndpoint(t, breaker, primeWith, shouldPass, requestDelay, openCircuitError)
}
golang-github-go-kit-kit-0.10.0/circuitbreaker/util_test.go 0000664 0000000 0000000 00000003373 13622563124 0023647 0 ustar 00root root 0000000 0000000 package circuitbreaker_test
import (
"context"
"errors"
"fmt"
"path/filepath"
"runtime"
"testing"
"time"
"github.com/go-kit/kit/endpoint"
)
func testFailingEndpoint(
t *testing.T,
breaker endpoint.Middleware,
primeWith int,
shouldPass func(int) bool,
requestDelay time.Duration,
openCircuitError string,
) {
_, file, line, _ := runtime.Caller(1)
caller := fmt.Sprintf("%s:%d", filepath.Base(file), line)
// Create a mock endpoint and wrap it with the breaker.
m := mock{}
var e endpoint.Endpoint
e = m.endpoint
e = breaker(e)
// Prime the endpoint with successful requests.
for i := 0; i < primeWith; i++ {
if _, err := e(context.Background(), struct{}{}); err != nil {
t.Fatalf("%s: during priming, got error: %v", caller, err)
}
time.Sleep(requestDelay)
}
// Switch the endpoint to start throwing errors.
m.err = errors.New("tragedy+disaster")
m.through = 0
// The first several should be allowed through and yield our error.
for i := 0; shouldPass(i); i++ {
if _, err := e(context.Background(), struct{}{}); err != m.err {
t.Fatalf("%s: want %v, have %v", caller, m.err, err)
}
time.Sleep(requestDelay)
}
through := m.through
// But the rest should be blocked by an open circuit.
for i := 0; i < 10; i++ {
if _, err := e(context.Background(), struct{}{}); err.Error() != openCircuitError {
t.Fatalf("%s: want %q, have %q", caller, openCircuitError, err.Error())
}
time.Sleep(requestDelay)
}
// Make sure none of those got through.
if want, have := through, m.through; want != have {
t.Errorf("%s: want %d, have %d", caller, want, have)
}
}
type mock struct {
through int
err error
}
func (m *mock) endpoint(context.Context, interface{}) (interface{}, error) {
m.through++
return struct{}{}, m.err
}
golang-github-go-kit-kit-0.10.0/cmd/ 0000775 0000000 0000000 00000000000 13622563124 0017043 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/ 0000775 0000000 0000000 00000000000 13622563124 0020324 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/.ignore 0000664 0000000 0000000 00000000016 13622563124 0021605 0 ustar 00root root 0000000 0000000 testdata/*/*/
golang-github-go-kit-kit-0.10.0/cmd/kitgen/README.md 0000664 0000000 0000000 00000003261 13622563124 0021605 0 ustar 00root root 0000000 0000000 # kitgen
kitgen is an experimental code generation utility that helps with some of the
boilerplate code required to implement the "onion" pattern `go-kit` utilizes.
## Usage
Before using this tool please explore the [testdata]() directory for examples
of the inputs it requires and the outputs that will be produced. _You may not
need this tool._ If you are new to and just learning `go-kit` or if your use
case involves introducing `go-kit` to an existing codebase you are better
suited by slowly building out the "onion" by hand.
Before starting you need to *install* `kitgen` utility — see instructions below.
1. **Define** your service. Create a `.go` file with the definition of your
Service interface and any of the custom types it refers to:
```go
// service.go
package profilesvc // don't forget to name your package
type Service interface {
PostProfile(ctx context.Context, p Profile) error
// ...
}
type Profile struct {
ID string `json:"id"`
Name string `json:"name,omitempty"`
// ...
}
```
2. **Generate** your code. Run the following command:
```sh
kitgen ./service.go
# kitgen has a couple of flags that you may find useful
# keep all code in the root directory
kitgen -repo-layout flat ./service.go
# put generated code elsewhere
kitgen -target-dir ~/Projects/gohome/src/home.com/kitchenservice/brewcoffee
```
## Installation
1. **Fetch** the `inlinefiles` utility. Go generate will use it to create your
code:
```
go get github.com/nyarly/inlinefiles
```
2. **Install** the binary for easy access to `kitgen`. Run the following commands:
```sh
cd $GOPATH/src/github.com/go-kit/kit/cmd/kitgen
go install
# Check installation by running:
kitgen -h
```
golang-github-go-kit-kit-0.10.0/cmd/kitgen/arg.go 0000664 0000000 0000000 00000001160 13622563124 0021422 0 ustar 00root root 0000000 0000000 package main
import "go/ast"
type arg struct {
name, asField *ast.Ident
typ ast.Expr
}
func (a arg) chooseName(scope *ast.Scope) *ast.Ident {
if a.name == nil || scope.Lookup(a.name.Name) != nil {
return inventName(a.typ, scope)
}
return a.name
}
func (a arg) field(scope *ast.Scope) *ast.Field {
return &ast.Field{
Names: []*ast.Ident{a.chooseName(scope)},
Type: a.typ,
}
}
func (a arg) result() *ast.Field {
return &ast.Field{
Names: nil,
Type: a.typ,
}
}
func (a arg) exported() *ast.Field {
return &ast.Field{
Names: []*ast.Ident{id(export(a.asField.Name))},
Type: a.typ,
}
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/ast_helpers.go 0000664 0000000 0000000 00000010150 13622563124 0023161 0 ustar 00root root 0000000 0000000 package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"path/filepath"
"strings"
"unicode"
)
func export(s string) string {
return strings.Title(s)
}
func unexport(s string) string {
first := true
return strings.Map(func(r rune) rune {
if first {
first = false
return unicode.ToLower(r)
}
return r
}, s)
}
func inventName(t ast.Expr, scope *ast.Scope) *ast.Ident {
n := baseName(t)
for try := 0; ; try++ {
nstr := pickName(n, try)
obj := ast.NewObj(ast.Var, nstr)
if alt := scope.Insert(obj); alt == nil {
return ast.NewIdent(nstr)
}
}
}
func baseName(t ast.Expr) string {
switch tt := t.(type) {
default:
panic(fmt.Sprintf("don't know how to choose a base name for %T (%[1]v)", tt))
case *ast.ArrayType:
return "slice"
case *ast.Ident:
return tt.Name
case *ast.SelectorExpr:
return tt.Sel.Name
}
}
func pickName(base string, idx int) string {
if idx == 0 {
switch base {
default:
return strings.Split(base, "")[0]
case "Context":
return "ctx"
case "error":
return "err"
}
}
return fmt.Sprintf("%s%d", base, idx)
}
func scopeWith(names ...string) *ast.Scope {
scope := ast.NewScope(nil)
for _, name := range names {
scope.Insert(ast.NewObj(ast.Var, name))
}
return scope
}
type visitFn func(ast.Node, func(ast.Node))
func (fn visitFn) Visit(node ast.Node, r func(ast.Node)) Visitor {
fn(node, r)
return fn
}
func replaceIdent(src ast.Node, named string, with ast.Node) ast.Node {
r := visitFn(func(node ast.Node, replaceWith func(ast.Node)) {
switch id := node.(type) {
case *ast.Ident:
if id.Name == named {
replaceWith(with)
}
}
})
return WalkReplace(r, src)
}
func replaceLit(src ast.Node, from, to string) ast.Node {
r := visitFn(func(node ast.Node, replaceWith func(ast.Node)) {
switch lit := node.(type) {
case *ast.BasicLit:
if lit.Value == from {
replaceWith(&ast.BasicLit{Value: to})
}
}
})
return WalkReplace(r, src)
}
func fullAST() *ast.File {
full, err := ASTTemplates.Open("full.go")
if err != nil {
panic(err)
}
f, err := parser.ParseFile(token.NewFileSet(), "templates/full.go", full, parser.DeclarationErrors)
if err != nil {
panic(err)
}
return f
}
func fetchImports() []*ast.ImportSpec {
return fullAST().Imports
}
func fetchFuncDecl(name string) *ast.FuncDecl {
f := fullAST()
for _, decl := range f.Decls {
if f, ok := decl.(*ast.FuncDecl); ok && f.Name.Name == name {
return f
}
}
panic(fmt.Errorf("no function called %q in 'templates/full.go'", name))
}
func id(name string) *ast.Ident {
return ast.NewIdent(name)
}
func sel(ids ...*ast.Ident) ast.Expr {
switch len(ids) {
default:
return &ast.SelectorExpr{
X: sel(ids[:len(ids)-1]...),
Sel: ids[len(ids)-1],
}
case 1:
return ids[0]
case 0:
panic("zero ids to sel()")
}
}
func typeField(t ast.Expr) *ast.Field {
return &ast.Field{Type: t}
}
func field(n *ast.Ident, t ast.Expr) *ast.Field {
return &ast.Field{
Names: []*ast.Ident{n},
Type: t,
}
}
func fieldList(list ...*ast.Field) *ast.FieldList {
return &ast.FieldList{List: list}
}
func mappedFieldList(fn func(arg) *ast.Field, args ...arg) *ast.FieldList {
fl := &ast.FieldList{List: []*ast.Field{}}
for _, a := range args {
fl.List = append(fl.List, fn(a))
}
return fl
}
func blockStmt(stmts ...ast.Stmt) *ast.BlockStmt {
return &ast.BlockStmt{
List: stmts,
}
}
func structDecl(name *ast.Ident, fields *ast.FieldList) ast.Decl {
return typeDecl(&ast.TypeSpec{
Name: name,
Type: &ast.StructType{
Fields: fields,
},
})
}
func typeDecl(ts *ast.TypeSpec) ast.Decl {
return &ast.GenDecl{
Tok: token.TYPE,
Specs: []ast.Spec{ts},
}
}
func pasteStmts(body *ast.BlockStmt, idx int, stmts []ast.Stmt) {
list := body.List
prefix := list[:idx]
suffix := make([]ast.Stmt, len(list)-idx-1)
copy(suffix, list[idx+1:])
body.List = append(append(prefix, stmts...), suffix...)
}
func importFor(is *ast.ImportSpec) *ast.GenDecl {
return &ast.GenDecl{Tok: token.IMPORT, Specs: []ast.Spec{is}}
}
func importSpec(path string) *ast.ImportSpec {
return &ast.ImportSpec{Path: &ast.BasicLit{Kind: token.STRING, Value: `"` + filepath.ToSlash(path) + `"`}}
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/ast_templates.go 0000664 0000000 0000000 00000003516 13622563124 0023525 0 ustar 00root root 0000000 0000000 // This file was automatically generated based on the contents of *.tmpl
// If you need to update this file, change the contents of those files
// (or add new ones) and run 'go generate'
package main
import "golang.org/x/tools/godoc/vfs/mapfs"
var ASTTemplates = mapfs.New(map[string]string{
`full.go`: "package foo\n\nimport (\n \"context\"\n \"encoding/json\"\n \"errors\"\n \"net/http\"\n\n \"github.com/go-kit/kit/endpoint\"\n httptransport \"github.com/go-kit/kit/transport/http\"\n)\n\ntype ExampleService struct {\n}\n\ntype ExampleRequest struct {\n I int\n S string\n}\ntype ExampleResponse struct {\n S string\n Err error\n}\n\ntype Endpoints struct {\n ExampleEndpoint endpoint.Endpoint\n}\n\nfunc (f ExampleService) ExampleEndpoint(ctx context.Context, i int, s string) (string, error) {\n panic(errors.New(\"not implemented\"))\n}\n\nfunc makeExampleEndpoint(f ExampleService) endpoint.Endpoint {\n return func(ctx context.Context, request interface{}) (interface{}, error) {\n req := request.(ExampleRequest)\n s, err := f.ExampleEndpoint(ctx, req.I, req.S)\n return ExampleResponse{S: s, Err: err}, nil\n }\n}\n\nfunc inlineHandlerBuilder(m *http.ServeMux, endpoints Endpoints) {\n m.Handle(\"/bar\", httptransport.NewServer(endpoints.ExampleEndpoint, DecodeExampleRequest, EncodeExampleResponse))\n}\n\nfunc NewHTTPHandler(endpoints Endpoints) http.Handler {\n m := http.NewServeMux()\n inlineHandlerBuilder(m, endpoints)\n return m\n}\n\nfunc DecodeExampleRequest(_ context.Context, r *http.Request) (interface{}, error) {\n var req ExampleRequest\n err := json.NewDecoder(r.Body).Decode(&req)\n return req, err\n}\n\nfunc EncodeExampleResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {\n w.Header().Set(\"Content-Type\", \"application/json; charset=utf-8\")\n return json.NewEncoder(w).Encode(response)\n}\n",
})
golang-github-go-kit-kit-0.10.0/cmd/kitgen/deflayout.go 0000664 0000000 0000000 00000003063 13622563124 0022651 0 ustar 00root root 0000000 0000000 package main
import "path/filepath"
type deflayout struct {
targetDir string
}
func (l deflayout) packagePath(sub string) string {
return filepath.Join(l.targetDir, sub)
}
func (l deflayout) transformAST(ctx *sourceContext) (files, error) {
out := make(outputTree)
endpoints := out.addFile("endpoints/endpoints.go", "endpoints")
http := out.addFile("http/http.go", "http")
service := out.addFile("service/service.go", "service")
addImports(endpoints, ctx)
addImports(http, ctx)
addImports(service, ctx)
for _, typ := range ctx.types {
addType(service, typ)
}
for _, iface := range ctx.interfaces { //only one...
addStubStruct(service, iface)
for _, meth := range iface.methods {
addMethod(service, iface, meth)
addRequestStruct(endpoints, meth)
addResponseStruct(endpoints, meth)
addEndpointMaker(endpoints, iface, meth)
}
addEndpointsStruct(endpoints, iface)
addHTTPHandler(http, iface)
for _, meth := range iface.methods {
addDecoder(http, meth)
addEncoder(http, meth)
}
for name := range out {
out[name] = selectify(out[name], "service", iface.stubName().Name, l.packagePath("service"))
for _, meth := range iface.methods {
out[name] = selectify(out[name], "endpoints", meth.requestStructName().Name, l.packagePath("endpoints"))
}
}
}
for name := range out {
out[name] = selectify(out[name], "endpoints", "Endpoints", l.packagePath("endpoints"))
for _, typ := range ctx.types {
out[name] = selectify(out[name], "service", typ.Name.Name, l.packagePath("service"))
}
}
return formatNodes(out)
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/flatlayout.go 0000664 0000000 0000000 00000001346 13622563124 0023043 0 ustar 00root root 0000000 0000000 package main
import "go/ast"
type flat struct{}
func (f flat) transformAST(ctx *sourceContext) (files, error) {
root := &ast.File{
Name: ctx.pkg,
Decls: []ast.Decl{},
}
addImports(root, ctx)
for _, typ := range ctx.types {
addType(root, typ)
}
for _, iface := range ctx.interfaces { //only one...
addStubStruct(root, iface)
for _, meth := range iface.methods {
addMethod(root, iface, meth)
addRequestStruct(root, meth)
addResponseStruct(root, meth)
addEndpointMaker(root, iface, meth)
}
addEndpointsStruct(root, iface)
addHTTPHandler(root, iface)
for _, meth := range iface.methods {
addDecoder(root, meth)
addEncoder(root, meth)
}
}
return formatNodes(outputTree{"gokit.go": root})
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/interface.go 0000664 0000000 0000000 00000003635 13622563124 0022622 0 ustar 00root root 0000000 0000000 package main
import "go/ast"
// because "interface" is a keyword...
type iface struct {
name, stubname, rcvrName *ast.Ident
methods []method
}
func (i iface) stubName() *ast.Ident {
return i.stubname
}
func (i iface) stubStructDecl() ast.Decl {
return structDecl(i.stubName(), &ast.FieldList{})
}
func (i iface) endpointsStruct() ast.Decl {
fl := &ast.FieldList{}
for _, m := range i.methods {
fl.List = append(fl.List, &ast.Field{Names: []*ast.Ident{m.name}, Type: sel(id("endpoint"), id("Endpoint"))})
}
return structDecl(id("Endpoints"), fl)
}
func (i iface) httpHandler() ast.Decl {
handlerFn := fetchFuncDecl("NewHTTPHandler")
// does this "inlining" process merit a helper akin to replaceIdent?
handleCalls := []ast.Stmt{}
for _, m := range i.methods {
handleCall := fetchFuncDecl("inlineHandlerBuilder").Body.List[0].(*ast.ExprStmt).X.(*ast.CallExpr)
handleCall = replaceLit(handleCall, `"/bar"`, `"`+m.pathName()+`"`).(*ast.CallExpr)
handleCall = replaceIdent(handleCall, "ExampleEndpoint", m.name).(*ast.CallExpr)
handleCall = replaceIdent(handleCall, "DecodeExampleRequest", m.decodeFuncName()).(*ast.CallExpr)
handleCall = replaceIdent(handleCall, "EncodeExampleResponse", m.encodeFuncName()).(*ast.CallExpr)
handleCalls = append(handleCalls, &ast.ExprStmt{X: handleCall})
}
pasteStmts(handlerFn.Body, 1, handleCalls)
return handlerFn
}
func (i iface) receiver() *ast.Field {
return field(i.receiverName(), i.stubName())
}
func (i iface) receiverName() *ast.Ident {
if i.rcvrName != nil {
return i.rcvrName
}
scope := ast.NewScope(nil)
for _, meth := range i.methods {
for _, arg := range meth.params {
if arg.name != nil {
scope.Insert(ast.NewObj(ast.Var, arg.name.Name))
}
}
for _, arg := range meth.results {
if arg.name != nil {
scope.Insert(ast.NewObj(ast.Var, arg.name.Name))
}
}
}
return id(unexport(inventName(i.name, scope).Name))
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/main.go 0000664 0000000 0000000 00000006431 13622563124 0021603 0 ustar 00root root 0000000 0000000 package main
import (
"flag"
"fmt"
"go/ast"
"go/parser"
"go/token"
"io"
"log"
"os"
"path"
"github.com/pkg/errors"
)
// go get github.com/nyarly/inlinefiles
//go:generate inlinefiles --package=main --vfs=ASTTemplates ./templates ast_templates.go
func usage() string {
return fmt.Sprintf("Usage: %s (try -h)", os.Args[0])
}
var (
help = flag.Bool("h", false, "print this help")
layoutkind = flag.String("repo-layout", "default", "default, flat...")
outdirrel = flag.String("target-dir", ".", "base directory to emit into")
//contextOmittable = flag.Bool("allow-no-context", false, "allow service methods to omit context parameter")
)
func helpText() {
fmt.Println("USAGE")
fmt.Println(" kitgen [flags] path/to/service.go")
fmt.Println("")
fmt.Println("FLAGS")
flag.PrintDefaults()
}
func main() {
flag.Parse()
if *help {
helpText()
os.Exit(0)
}
outdir := *outdirrel
if !path.IsAbs(*outdirrel) {
wd, err := os.Getwd()
if err != nil {
log.Fatalf("error getting current working directory: %v", err)
}
outdir = path.Join(wd, *outdirrel)
}
var layout layout
switch *layoutkind {
default:
log.Fatalf("Unrecognized layout kind: %q - try 'default' or 'flat'", *layoutkind)
case "default":
gopath := getGopath()
importBase, err := importPath(outdir, gopath)
if err != nil {
log.Fatal(err)
}
layout = deflayout{targetDir: importBase}
case "flat":
layout = flat{}
}
if len(os.Args) < 2 {
log.Fatal(usage())
}
filename := flag.Arg(0)
file, err := os.Open(filename)
if err != nil {
log.Fatalf("error while opening %q: %v", filename, err)
}
tree, err := process(filename, file, layout)
if err != nil {
log.Fatal(err)
}
err = splat(outdir, tree)
if err != nil {
log.Fatal(err)
}
}
func process(filename string, source io.Reader, layout layout) (files, error) {
f, err := parseFile(filename, source)
if err != nil {
return nil, errors.Wrapf(err, "parsing input %q", filename)
}
context, err := extractContext(f)
if err != nil {
return nil, errors.Wrapf(err, "examining input file %q", filename)
}
tree, err := layout.transformAST(context)
if err != nil {
return nil, errors.Wrapf(err, "generating AST")
}
return tree, nil
}
/*
buf, err := formatNode(dest)
if err != nil {
return nil, errors.Wrapf(err, "formatting")
}
return buf, nil
}
*/
func parseFile(fname string, source io.Reader) (ast.Node, error) {
f, err := parser.ParseFile(token.NewFileSet(), fname, source, parser.DeclarationErrors)
if err != nil {
return nil, err
}
return f, nil
}
func extractContext(f ast.Node) (*sourceContext, error) {
context := &sourceContext{}
visitor := &parseVisitor{src: context}
ast.Walk(visitor, f)
return context, context.validate()
}
func splat(dir string, tree files) error {
for fn, buf := range tree {
if err := splatFile(path.Join(dir, fn), buf); err != nil {
return err
}
}
return nil
}
func splatFile(target string, buf io.Reader) error {
err := os.MkdirAll(path.Dir(target), os.ModePerm)
if err != nil {
return errors.Wrapf(err, "Couldn't create directory for %q", target)
}
f, err := os.Create(target)
if err != nil {
return errors.Wrapf(err, "Couldn't create file %q", target)
}
defer f.Close()
_, err = io.Copy(f, buf)
return errors.Wrapf(err, "Error writing data to file %q", target)
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/main_test.go 0000664 0000000 0000000 00000005077 13622563124 0022647 0 ustar 00root root 0000000 0000000 package main
import (
"bufio"
"bytes"
"flag"
"fmt"
"io/ioutil"
"os/exec"
"path/filepath"
"testing"
"github.com/aryann/difflib"
)
var update = flag.Bool("update", false, "update golden files")
func TestProcess(t *testing.T) {
cases, err := filepath.Glob("testdata/*")
if err != nil {
t.Fatal(err)
}
laidout := func(t *testing.T, inpath, dir, kind string, layout layout, in []byte) {
t.Run(kind, func(t *testing.T) {
targetDir := filepath.Join(dir, kind)
tree, err := process(inpath, bytes.NewBuffer(in), layout)
if err != nil {
t.Fatal(inpath, fmt.Sprintf("%+#v", err))
}
if *update {
err := splat(targetDir, tree)
if err != nil {
t.Fatal(kind, err)
}
// otherwise we need to do some tomfoolery with resetting buffers
// I'm willing to just run the tests again - besides, we shouldn't be
// regerating the golden files that often
t.Error("Updated outputs - DID NOT COMPARE! (run tests again without -update)")
return
}
for filename, buf := range tree {
actual, err := ioutil.ReadAll(buf)
if err != nil {
t.Fatal(kind, filename, err)
}
outpath := filepath.Join(targetDir, filename)
expected, err := ioutil.ReadFile(outpath)
if err != nil {
t.Fatal(outpath, err)
}
if !bytes.Equal(expected, actual) {
results := difflib.Diff(splitLines(expected), splitLines(actual))
for _, result := range results {
if result.Delta == difflib.Common {
continue
}
t.Error(result)
}
}
}
if !t.Failed() {
build := exec.Command("go", "build", "./...")
build.Dir = targetDir
out, err := build.CombinedOutput()
if err != nil {
t.Fatalf("Cannot build output: %v\n%s", err, string(out))
}
}
})
}
testcase := func(dir string) {
name := filepath.Base(dir)
t.Run(name, func(t *testing.T) {
inpath := filepath.Join(dir, "in.go")
in, err := ioutil.ReadFile(inpath)
if err != nil {
t.Fatal(inpath, err)
}
laidout(t, inpath, dir, "flat", flat{}, in)
laidout(t, inpath, dir, "default", deflayout{
targetDir: filepath.Join("github.com/go-kit/kit/cmd/kitgen", dir, "default"),
}, in)
})
}
for _, dir := range cases {
testcase(dir)
}
}
func TestTemplatesBuild(t *testing.T) {
build := exec.Command("go", "build", "./...")
build.Dir = "templates"
out, err := build.CombinedOutput()
if err != nil {
t.Fatal(err, "\n", string(out))
}
}
func splitLines(txt []byte) []string {
s := bufio.NewScanner(bytes.NewReader(txt))
var ss []string
for s.Scan() {
ss = append(ss, s.Text())
}
return ss
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/method.go 0000664 0000000 0000000 00000012513 13622563124 0022135 0 ustar 00root root 0000000 0000000 package main
import (
"go/ast"
"go/token"
"strings"
)
type method struct {
name *ast.Ident
params []arg
results []arg
structsResolved bool
}
func (m method) definition(ifc iface) ast.Decl {
notImpl := fetchFuncDecl("ExampleEndpoint")
notImpl.Name = m.name
notImpl.Recv = fieldList(ifc.receiver())
scope := scopeWith(notImpl.Recv.List[0].Names[0].Name)
notImpl.Type.Params = m.funcParams(scope)
notImpl.Type.Results = m.funcResults()
return notImpl
}
func (m method) endpointMaker(ifc iface) ast.Decl {
endpointFn := fetchFuncDecl("makeExampleEndpoint")
scope := scopeWith("ctx", "req", ifc.receiverName().Name)
anonFunc := endpointFn.Body.List[0].(*ast.ReturnStmt).Results[0].(*ast.FuncLit)
if !m.hasContext() {
// strip context param from endpoint function
anonFunc.Type.Params.List = anonFunc.Type.Params.List[1:]
}
anonFunc = replaceIdent(anonFunc, "ExampleRequest", m.requestStructName()).(*ast.FuncLit)
callMethod := m.called(ifc, scope, "ctx", "req")
anonFunc.Body.List[1] = callMethod
anonFunc.Body.List[2].(*ast.ReturnStmt).Results[0] = m.wrapResult(callMethod.Lhs)
endpointFn.Body.List[0].(*ast.ReturnStmt).Results[0] = anonFunc
endpointFn.Name = m.endpointMakerName()
endpointFn.Type.Params = fieldList(ifc.receiver())
endpointFn.Type.Results = fieldList(typeField(sel(id("endpoint"), id("Endpoint"))))
return endpointFn
}
func (m method) pathName() string {
return "/" + strings.ToLower(m.name.Name)
}
func (m method) encodeFuncName() *ast.Ident {
return id("Encode" + m.name.Name + "Response")
}
func (m method) decodeFuncName() *ast.Ident {
return id("Decode" + m.name.Name + "Request")
}
func (m method) resultNames(scope *ast.Scope) []*ast.Ident {
ids := []*ast.Ident{}
for _, rz := range m.results {
ids = append(ids, rz.chooseName(scope))
}
return ids
}
func (m method) called(ifc iface, scope *ast.Scope, ctxName, spreadStruct string) *ast.AssignStmt {
m.resolveStructNames()
resNamesExpr := []ast.Expr{}
for _, r := range m.resultNames(scope) {
resNamesExpr = append(resNamesExpr, ast.Expr(r))
}
arglist := []ast.Expr{}
if m.hasContext() {
arglist = append(arglist, id(ctxName))
}
ssid := id(spreadStruct)
for _, f := range m.requestStructFields().List {
arglist = append(arglist, sel(ssid, f.Names[0]))
}
return &ast.AssignStmt{
Lhs: resNamesExpr,
Tok: token.DEFINE,
Rhs: []ast.Expr{
&ast.CallExpr{
Fun: sel(ifc.receiverName(), m.name),
Args: arglist,
},
},
}
}
func (m method) wrapResult(results []ast.Expr) ast.Expr {
kvs := []ast.Expr{}
m.resolveStructNames()
for i, a := range m.results {
kvs = append(kvs, &ast.KeyValueExpr{
Key: ast.NewIdent(export(a.asField.Name)),
Value: results[i],
})
}
return &ast.CompositeLit{
Type: m.responseStructName(),
Elts: kvs,
}
}
func (m method) resolveStructNames() {
if m.structsResolved {
return
}
m.structsResolved = true
scope := ast.NewScope(nil)
for i, p := range m.params {
p.asField = p.chooseName(scope)
m.params[i] = p
}
scope = ast.NewScope(nil)
for i, r := range m.results {
r.asField = r.chooseName(scope)
m.results[i] = r
}
}
func (m method) decoderFunc() ast.Decl {
fn := fetchFuncDecl("DecodeExampleRequest")
fn.Name = m.decodeFuncName()
fn = replaceIdent(fn, "ExampleRequest", m.requestStructName()).(*ast.FuncDecl)
return fn
}
func (m method) encoderFunc() ast.Decl {
fn := fetchFuncDecl("EncodeExampleResponse")
fn.Name = m.encodeFuncName()
return fn
}
func (m method) endpointMakerName() *ast.Ident {
return id("Make" + m.name.Name + "Endpoint")
}
func (m method) requestStruct() ast.Decl {
m.resolveStructNames()
return structDecl(m.requestStructName(), m.requestStructFields())
}
func (m method) responseStruct() ast.Decl {
m.resolveStructNames()
return structDecl(m.responseStructName(), m.responseStructFields())
}
func (m method) hasContext() bool {
if len(m.params) < 1 {
return false
}
carg := m.params[0].typ
// ugh. this is maybe okay for the one-off, but a general case for matching
// types would be helpful
if sel, is := carg.(*ast.SelectorExpr); is && sel.Sel.Name == "Context" {
if id, is := sel.X.(*ast.Ident); is && id.Name == "context" {
return true
}
}
return false
}
func (m method) nonContextParams() []arg {
if m.hasContext() {
return m.params[1:]
}
return m.params
}
func (m method) funcParams(scope *ast.Scope) *ast.FieldList {
parms := &ast.FieldList{}
if m.hasContext() {
parms.List = []*ast.Field{{
Names: []*ast.Ident{ast.NewIdent("ctx")},
Type: sel(id("context"), id("Context")),
}}
scope.Insert(ast.NewObj(ast.Var, "ctx"))
}
parms.List = append(parms.List, mappedFieldList(func(a arg) *ast.Field {
return a.field(scope)
}, m.nonContextParams()...).List...)
return parms
}
func (m method) funcResults() *ast.FieldList {
return mappedFieldList(func(a arg) *ast.Field {
return a.result()
}, m.results...)
}
func (m method) requestStructName() *ast.Ident {
return id(export(m.name.Name) + "Request")
}
func (m method) requestStructFields() *ast.FieldList {
return mappedFieldList(func(a arg) *ast.Field {
return a.exported()
}, m.nonContextParams()...)
}
func (m method) responseStructName() *ast.Ident {
return id(export(m.name.Name) + "Response")
}
func (m method) responseStructFields() *ast.FieldList {
return mappedFieldList(func(a arg) *ast.Field {
return a.exported()
}, m.results...)
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/parsevisitor.go 0000664 0000000 0000000 00000006412 13622563124 0023410 0 ustar 00root root 0000000 0000000 package main
import (
"go/ast"
)
type (
parseVisitor struct {
src *sourceContext
}
typeSpecVisitor struct {
src *sourceContext
node *ast.TypeSpec
iface *iface
name *ast.Ident
}
interfaceTypeVisitor struct {
node *ast.TypeSpec
ts *typeSpecVisitor
methods []method
}
methodVisitor struct {
depth int
node *ast.TypeSpec
list *[]method
name *ast.Ident
params, results *[]arg
isMethod bool
}
argListVisitor struct {
list *[]arg
}
argVisitor struct {
node *ast.TypeSpec
parts []ast.Expr
list *[]arg
}
)
func (v *parseVisitor) Visit(n ast.Node) ast.Visitor {
switch rn := n.(type) {
default:
return v
case *ast.File:
v.src.pkg = rn.Name
return v
case *ast.ImportSpec:
v.src.imports = append(v.src.imports, rn)
return nil
case *ast.TypeSpec:
switch rn.Type.(type) {
default:
v.src.types = append(v.src.types, rn)
case *ast.InterfaceType:
// can't output interfaces
// because they'd conflict with our implementations
}
return &typeSpecVisitor{src: v.src, node: rn}
}
}
/*
package foo
type FooService interface {
Bar(ctx context.Context, i int, s string) (string, error)
}
*/
func (v *typeSpecVisitor) Visit(n ast.Node) ast.Visitor {
switch rn := n.(type) {
default:
return v
case *ast.Ident:
if v.name == nil {
v.name = rn
}
return v
case *ast.InterfaceType:
return &interfaceTypeVisitor{ts: v, methods: []method{}}
case nil:
if v.iface != nil {
v.iface.name = v.name
sn := *v.name
v.iface.stubname = &sn
v.iface.stubname.Name = v.name.String()
v.src.interfaces = append(v.src.interfaces, *v.iface)
}
return nil
}
}
func (v *interfaceTypeVisitor) Visit(n ast.Node) ast.Visitor {
switch n.(type) {
default:
return v
case *ast.Field:
return &methodVisitor{list: &v.methods}
case nil:
v.ts.iface = &iface{methods: v.methods}
return nil
}
}
func (v *methodVisitor) Visit(n ast.Node) ast.Visitor {
switch rn := n.(type) {
default:
v.depth++
return v
case *ast.Ident:
if rn.IsExported() {
v.name = rn
}
v.depth++
return v
case *ast.FuncType:
v.depth++
v.isMethod = true
return v
case *ast.FieldList:
if v.params == nil {
v.params = &[]arg{}
return &argListVisitor{list: v.params}
}
if v.results == nil {
v.results = &[]arg{}
}
return &argListVisitor{list: v.results}
case nil:
v.depth--
if v.depth == 0 && v.isMethod && v.name != nil {
*v.list = append(*v.list, method{name: v.name, params: *v.params, results: *v.results})
}
return nil
}
}
func (v *argListVisitor) Visit(n ast.Node) ast.Visitor {
switch n.(type) {
default:
return nil
case *ast.Field:
return &argVisitor{list: v.list}
}
}
func (v *argVisitor) Visit(n ast.Node) ast.Visitor {
switch t := n.(type) {
case *ast.CommentGroup, *ast.BasicLit:
return nil
case *ast.Ident: //Expr -> everything, but clarity
if t.Name != "_" {
v.parts = append(v.parts, t)
}
case ast.Expr:
v.parts = append(v.parts, t)
case nil:
names := v.parts[:len(v.parts)-1]
tp := v.parts[len(v.parts)-1]
if len(names) == 0 {
*v.list = append(*v.list, arg{typ: tp})
return nil
}
for _, n := range names {
*v.list = append(*v.list, arg{
name: n.(*ast.Ident),
typ: tp,
})
}
}
return nil
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/path_test.go 0000664 0000000 0000000 00000003210 13622563124 0022642 0 ustar 00root root 0000000 0000000 package main
import (
"fmt"
"runtime"
"strings"
"testing"
)
func TestImportPath(t *testing.T) {
testcase := func(gopath, targetpath, expected string) {
t.Run(fmt.Sprintf("%q + %q", gopath, targetpath), func(t *testing.T) {
actual, err := importPath(targetpath, gopath)
if err != nil {
t.Fatalf("Expected no error, got %q", err)
}
if actual != expected {
t.Errorf("Expected %q, got %q", expected, actual)
}
})
}
if runtime.GOOS == "windows" {
testcase("c:\\gopath\\", "c:\\gopath\\src\\somewhere", "somewhere")
testcase("c:\\gopath", "c:\\gopath\\src\\somewhere", "somewhere")
testcase("c:\\gopath;\\other", "c:\\gopath\\src\\somewhere", "somewhere")
testcase("c:\\other;c:\\gopath\\", "c:\\gopath\\src\\somewhere", "somewhere")
} else {
testcase("/gopath/", "/gopath/src/somewhere", "somewhere")
testcase("/gopath", "/gopath/src/somewhere", "somewhere")
testcase("/gopath:/other", "/gopath/src/somewhere", "somewhere")
testcase("/other:/gopath/", "/gopath/src/somewhere", "somewhere")
}
}
func TestImportPathSadpath(t *testing.T) {
testcase := func(gopath, targetpath, expected string) {
t.Run(fmt.Sprintf("%q + %q", gopath, targetpath), func(t *testing.T) {
actual, err := importPath(targetpath, gopath)
if actual != "" {
t.Errorf("Expected empty path, got %q", actual)
}
if strings.Index(err.Error(), expected) == -1 {
t.Errorf("Expected %q to include %q", err, expected)
}
})
}
if runtime.GOOS == "windows" {
testcase("", "c:\\gopath\\src\\somewhere", "is not in")
} else {
testcase("", "/gopath/src/somewhere", "is not in")
}
testcase("", "./somewhere", "not an absolute")
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/replacewalk.go 0000664 0000000 0000000 00000036227 13622563124 0023157 0 ustar 00root root 0000000 0000000 package main
import (
"fmt"
"go/ast"
)
// A Visitor's Visit method is invoked for each node encountered by walkToReplace.
// If the result visitor w is not nil, walkToReplace visits each of the children
// of node with the visitor w, followed by a call of w.Visit(nil).
type Visitor interface {
Visit(node ast.Node, replace func(ast.Node)) (w Visitor)
}
// Helper functions for common node lists. They may be empty.
func walkIdentList(v Visitor, list []*ast.Ident) {
for i, x := range list {
walkToReplace(v, x, func(r ast.Node) {
list[i] = r.(*ast.Ident)
})
}
}
func walkExprList(v Visitor, list []ast.Expr) {
for i, x := range list {
walkToReplace(v, x, func(r ast.Node) {
list[i] = r.(ast.Expr)
})
}
}
func walkStmtList(v Visitor, list []ast.Stmt) {
for i, x := range list {
walkToReplace(v, x, func(r ast.Node) {
list[i] = r.(ast.Stmt)
})
}
}
func walkDeclList(v Visitor, list []ast.Decl) {
for i, x := range list {
walkToReplace(v, x, func(r ast.Node) {
list[i] = r.(ast.Decl)
})
}
}
// WalkToReplace traverses an AST in depth-first order: It starts by calling
// v.Visit(node); node must not be nil. If the visitor w returned by
// v.Visit(node) is not nil, walkToReplace is invoked recursively with visitor
// w for each of the non-nil children of node, followed by a call of
// w.Visit(nil).
func WalkReplace(v Visitor, node ast.Node) (replacement ast.Node) {
walkToReplace(v, node, func(r ast.Node) {
replacement = r
})
return
}
func walkToReplace(v Visitor, node ast.Node, replace func(ast.Node)) {
if v == nil {
return
}
var replacement ast.Node
repl := func(r ast.Node) {
replacement = r
replace(r)
}
v = v.Visit(node, repl)
if replacement != nil {
return
}
// walk children
// (the order of the cases matches the order
// of the corresponding node types in ast.go)
switch n := node.(type) {
// These are all leaves, so there's no sub-walk to do.
// We just need to replace them on their parent with a copy.
case *ast.Comment:
cpy := *n
replace(&cpy)
case *ast.BadExpr:
cpy := *n
replace(&cpy)
case *ast.Ident:
cpy := *n
replace(&cpy)
case *ast.BasicLit:
cpy := *n
replace(&cpy)
case *ast.BadDecl:
cpy := *n
replace(&cpy)
case *ast.EmptyStmt:
cpy := *n
replace(&cpy)
case *ast.BadStmt:
cpy := *n
replace(&cpy)
case *ast.CommentGroup:
cpy := *n
if n.List != nil {
cpy.List = make([]*ast.Comment, len(n.List))
copy(cpy.List, n.List)
}
for i, c := range cpy.List {
walkToReplace(v, c, func(r ast.Node) {
cpy.List[i] = r.(*ast.Comment)
})
}
replace(&cpy)
case *ast.Field:
cpy := *n
if n.Names != nil {
cpy.Names = make([]*ast.Ident, len(n.Names))
copy(cpy.Names, n.Names)
}
if cpy.Doc != nil {
walkToReplace(v, cpy.Doc, func(r ast.Node) {
cpy.Doc = r.(*ast.CommentGroup)
})
}
walkIdentList(v, cpy.Names)
walkToReplace(v, cpy.Type, func(r ast.Node) {
cpy.Type = r.(ast.Expr)
})
if cpy.Tag != nil {
walkToReplace(v, cpy.Tag, func(r ast.Node) {
cpy.Tag = r.(*ast.BasicLit)
})
}
if cpy.Comment != nil {
walkToReplace(v, cpy.Comment, func(r ast.Node) {
cpy.Comment = r.(*ast.CommentGroup)
})
}
replace(&cpy)
case *ast.FieldList:
cpy := *n
if n.List != nil {
cpy.List = make([]*ast.Field, len(n.List))
copy(cpy.List, n.List)
}
for i, f := range cpy.List {
walkToReplace(v, f, func(r ast.Node) {
cpy.List[i] = r.(*ast.Field)
})
}
replace(&cpy)
case *ast.Ellipsis:
cpy := *n
if cpy.Elt != nil {
walkToReplace(v, cpy.Elt, func(r ast.Node) {
cpy.Elt = r.(ast.Expr)
})
}
replace(&cpy)
case *ast.FuncLit:
cpy := *n
walkToReplace(v, cpy.Type, func(r ast.Node) {
cpy.Type = r.(*ast.FuncType)
})
walkToReplace(v, cpy.Body, func(r ast.Node) {
cpy.Body = r.(*ast.BlockStmt)
})
replace(&cpy)
case *ast.CompositeLit:
cpy := *n
if n.Elts != nil {
cpy.Elts = make([]ast.Expr, len(n.Elts))
copy(cpy.Elts, n.Elts)
}
if cpy.Type != nil {
walkToReplace(v, cpy.Type, func(r ast.Node) {
cpy.Type = r.(ast.Expr)
})
}
walkExprList(v, cpy.Elts)
replace(&cpy)
case *ast.ParenExpr:
cpy := *n
walkToReplace(v, cpy.X, func(r ast.Node) {
cpy.X = r.(ast.Expr)
})
replace(&cpy)
case *ast.SelectorExpr:
cpy := *n
walkToReplace(v, cpy.X, func(r ast.Node) {
cpy.X = r.(ast.Expr)
})
walkToReplace(v, cpy.Sel, func(r ast.Node) {
cpy.Sel = r.(*ast.Ident)
})
replace(&cpy)
case *ast.IndexExpr:
cpy := *n
walkToReplace(v, cpy.X, func(r ast.Node) {
cpy.X = r.(ast.Expr)
})
walkToReplace(v, cpy.Index, func(r ast.Node) {
cpy.Index = r.(ast.Expr)
})
replace(&cpy)
case *ast.SliceExpr:
cpy := *n
walkToReplace(v, cpy.X, func(r ast.Node) {
cpy.X = r.(ast.Expr)
})
if cpy.Low != nil {
walkToReplace(v, cpy.Low, func(r ast.Node) {
cpy.Low = r.(ast.Expr)
})
}
if cpy.High != nil {
walkToReplace(v, cpy.High, func(r ast.Node) {
cpy.High = r.(ast.Expr)
})
}
if cpy.Max != nil {
walkToReplace(v, cpy.Max, func(r ast.Node) {
cpy.Max = r.(ast.Expr)
})
}
replace(&cpy)
case *ast.TypeAssertExpr:
cpy := *n
walkToReplace(v, cpy.X, func(r ast.Node) {
cpy.X = r.(ast.Expr)
})
if cpy.Type != nil {
walkToReplace(v, cpy.Type, func(r ast.Node) {
cpy.Type = r.(ast.Expr)
})
}
replace(&cpy)
case *ast.CallExpr:
cpy := *n
if n.Args != nil {
cpy.Args = make([]ast.Expr, len(n.Args))
copy(cpy.Args, n.Args)
}
walkToReplace(v, cpy.Fun, func(r ast.Node) {
cpy.Fun = r.(ast.Expr)
})
walkExprList(v, cpy.Args)
replace(&cpy)
case *ast.StarExpr:
cpy := *n
walkToReplace(v, cpy.X, func(r ast.Node) {
cpy.X = r.(ast.Expr)
})
replace(&cpy)
case *ast.UnaryExpr:
cpy := *n
walkToReplace(v, cpy.X, func(r ast.Node) {
cpy.X = r.(ast.Expr)
})
replace(&cpy)
case *ast.BinaryExpr:
cpy := *n
walkToReplace(v, cpy.X, func(r ast.Node) {
cpy.X = r.(ast.Expr)
})
walkToReplace(v, cpy.Y, func(r ast.Node) {
cpy.Y = r.(ast.Expr)
})
replace(&cpy)
case *ast.KeyValueExpr:
cpy := *n
walkToReplace(v, cpy.Key, func(r ast.Node) {
cpy.Key = r.(ast.Expr)
})
walkToReplace(v, cpy.Value, func(r ast.Node) {
cpy.Value = r.(ast.Expr)
})
replace(&cpy)
// Types
case *ast.ArrayType:
cpy := *n
if cpy.Len != nil {
walkToReplace(v, cpy.Len, func(r ast.Node) {
cpy.Len = r.(ast.Expr)
})
}
walkToReplace(v, cpy.Elt, func(r ast.Node) {
cpy.Elt = r.(ast.Expr)
})
replace(&cpy)
case *ast.StructType:
cpy := *n
walkToReplace(v, cpy.Fields, func(r ast.Node) {
cpy.Fields = r.(*ast.FieldList)
})
replace(&cpy)
case *ast.FuncType:
cpy := *n
if cpy.Params != nil {
walkToReplace(v, cpy.Params, func(r ast.Node) {
cpy.Params = r.(*ast.FieldList)
})
}
if cpy.Results != nil {
walkToReplace(v, cpy.Results, func(r ast.Node) {
cpy.Results = r.(*ast.FieldList)
})
}
replace(&cpy)
case *ast.InterfaceType:
cpy := *n
walkToReplace(v, cpy.Methods, func(r ast.Node) {
cpy.Methods = r.(*ast.FieldList)
})
replace(&cpy)
case *ast.MapType:
cpy := *n
walkToReplace(v, cpy.Key, func(r ast.Node) {
cpy.Key = r.(ast.Expr)
})
walkToReplace(v, cpy.Value, func(r ast.Node) {
cpy.Value = r.(ast.Expr)
})
replace(&cpy)
case *ast.ChanType:
cpy := *n
walkToReplace(v, cpy.Value, func(r ast.Node) {
cpy.Value = r.(ast.Expr)
})
replace(&cpy)
case *ast.DeclStmt:
cpy := *n
walkToReplace(v, cpy.Decl, func(r ast.Node) {
cpy.Decl = r.(ast.Decl)
})
replace(&cpy)
case *ast.LabeledStmt:
cpy := *n
walkToReplace(v, cpy.Label, func(r ast.Node) {
cpy.Label = r.(*ast.Ident)
})
walkToReplace(v, cpy.Stmt, func(r ast.Node) {
cpy.Stmt = r.(ast.Stmt)
})
replace(&cpy)
case *ast.ExprStmt:
cpy := *n
walkToReplace(v, cpy.X, func(r ast.Node) {
cpy.X = r.(ast.Expr)
})
replace(&cpy)
case *ast.SendStmt:
cpy := *n
walkToReplace(v, cpy.Chan, func(r ast.Node) {
cpy.Chan = r.(ast.Expr)
})
walkToReplace(v, cpy.Value, func(r ast.Node) {
cpy.Value = r.(ast.Expr)
})
replace(&cpy)
case *ast.IncDecStmt:
cpy := *n
walkToReplace(v, cpy.X, func(r ast.Node) {
cpy.X = r.(ast.Expr)
})
replace(&cpy)
case *ast.AssignStmt:
cpy := *n
if n.Lhs != nil {
cpy.Lhs = make([]ast.Expr, len(n.Lhs))
copy(cpy.Lhs, n.Lhs)
}
if n.Rhs != nil {
cpy.Rhs = make([]ast.Expr, len(n.Rhs))
copy(cpy.Rhs, n.Rhs)
}
walkExprList(v, cpy.Lhs)
walkExprList(v, cpy.Rhs)
replace(&cpy)
case *ast.GoStmt:
cpy := *n
walkToReplace(v, cpy.Call, func(r ast.Node) {
cpy.Call = r.(*ast.CallExpr)
})
replace(&cpy)
case *ast.DeferStmt:
cpy := *n
walkToReplace(v, cpy.Call, func(r ast.Node) {
cpy.Call = r.(*ast.CallExpr)
})
replace(&cpy)
case *ast.ReturnStmt:
cpy := *n
if n.Results != nil {
cpy.Results = make([]ast.Expr, len(n.Results))
copy(cpy.Results, n.Results)
}
walkExprList(v, cpy.Results)
replace(&cpy)
case *ast.BranchStmt:
cpy := *n
if cpy.Label != nil {
walkToReplace(v, cpy.Label, func(r ast.Node) {
cpy.Label = r.(*ast.Ident)
})
}
replace(&cpy)
case *ast.BlockStmt:
cpy := *n
if n.List != nil {
cpy.List = make([]ast.Stmt, len(n.List))
copy(cpy.List, n.List)
}
walkStmtList(v, cpy.List)
replace(&cpy)
case *ast.IfStmt:
cpy := *n
if cpy.Init != nil {
walkToReplace(v, cpy.Init, func(r ast.Node) {
cpy.Init = r.(ast.Stmt)
})
}
walkToReplace(v, cpy.Cond, func(r ast.Node) {
cpy.Cond = r.(ast.Expr)
})
walkToReplace(v, cpy.Body, func(r ast.Node) {
cpy.Body = r.(*ast.BlockStmt)
})
if cpy.Else != nil {
walkToReplace(v, cpy.Else, func(r ast.Node) {
cpy.Else = r.(ast.Stmt)
})
}
replace(&cpy)
case *ast.CaseClause:
cpy := *n
if n.List != nil {
cpy.List = make([]ast.Expr, len(n.List))
copy(cpy.List, n.List)
}
if n.Body != nil {
cpy.Body = make([]ast.Stmt, len(n.Body))
copy(cpy.Body, n.Body)
}
walkExprList(v, cpy.List)
walkStmtList(v, cpy.Body)
replace(&cpy)
case *ast.SwitchStmt:
cpy := *n
if cpy.Init != nil {
walkToReplace(v, cpy.Init, func(r ast.Node) {
cpy.Init = r.(ast.Stmt)
})
}
if cpy.Tag != nil {
walkToReplace(v, cpy.Tag, func(r ast.Node) {
cpy.Tag = r.(ast.Expr)
})
}
walkToReplace(v, cpy.Body, func(r ast.Node) {
cpy.Body = r.(*ast.BlockStmt)
})
replace(&cpy)
case *ast.TypeSwitchStmt:
cpy := *n
if cpy.Init != nil {
walkToReplace(v, cpy.Init, func(r ast.Node) {
cpy.Init = r.(ast.Stmt)
})
}
walkToReplace(v, cpy.Assign, func(r ast.Node) {
cpy.Assign = r.(ast.Stmt)
})
walkToReplace(v, cpy.Body, func(r ast.Node) {
cpy.Body = r.(*ast.BlockStmt)
})
replace(&cpy)
case *ast.CommClause:
cpy := *n
if n.Body != nil {
cpy.Body = make([]ast.Stmt, len(n.Body))
copy(cpy.Body, n.Body)
}
if cpy.Comm != nil {
walkToReplace(v, cpy.Comm, func(r ast.Node) {
cpy.Comm = r.(ast.Stmt)
})
}
walkStmtList(v, cpy.Body)
replace(&cpy)
case *ast.SelectStmt:
cpy := *n
walkToReplace(v, cpy.Body, func(r ast.Node) {
cpy.Body = r.(*ast.BlockStmt)
})
replace(&cpy)
case *ast.ForStmt:
cpy := *n
if cpy.Init != nil {
walkToReplace(v, cpy.Init, func(r ast.Node) {
cpy.Init = r.(ast.Stmt)
})
}
if cpy.Cond != nil {
walkToReplace(v, cpy.Cond, func(r ast.Node) {
cpy.Cond = r.(ast.Expr)
})
}
if cpy.Post != nil {
walkToReplace(v, cpy.Post, func(r ast.Node) {
cpy.Post = r.(ast.Stmt)
})
}
walkToReplace(v, cpy.Body, func(r ast.Node) {
cpy.Body = r.(*ast.BlockStmt)
})
replace(&cpy)
case *ast.RangeStmt:
cpy := *n
if cpy.Key != nil {
walkToReplace(v, cpy.Key, func(r ast.Node) {
cpy.Key = r.(ast.Expr)
})
}
if cpy.Value != nil {
walkToReplace(v, cpy.Value, func(r ast.Node) {
cpy.Value = r.(ast.Expr)
})
}
walkToReplace(v, cpy.X, func(r ast.Node) {
cpy.X = r.(ast.Expr)
})
walkToReplace(v, cpy.Body, func(r ast.Node) {
cpy.Body = r.(*ast.BlockStmt)
})
// Declarations
replace(&cpy)
case *ast.ImportSpec:
cpy := *n
if cpy.Doc != nil {
walkToReplace(v, cpy.Doc, func(r ast.Node) {
cpy.Doc = r.(*ast.CommentGroup)
})
}
if cpy.Name != nil {
walkToReplace(v, cpy.Name, func(r ast.Node) {
cpy.Name = r.(*ast.Ident)
})
}
walkToReplace(v, cpy.Path, func(r ast.Node) {
cpy.Path = r.(*ast.BasicLit)
})
if cpy.Comment != nil {
walkToReplace(v, cpy.Comment, func(r ast.Node) {
cpy.Comment = r.(*ast.CommentGroup)
})
}
replace(&cpy)
case *ast.ValueSpec:
cpy := *n
if n.Names != nil {
cpy.Names = make([]*ast.Ident, len(n.Names))
copy(cpy.Names, n.Names)
}
if n.Values != nil {
cpy.Values = make([]ast.Expr, len(n.Values))
copy(cpy.Values, n.Values)
}
if cpy.Doc != nil {
walkToReplace(v, cpy.Doc, func(r ast.Node) {
cpy.Doc = r.(*ast.CommentGroup)
})
}
walkIdentList(v, cpy.Names)
if cpy.Type != nil {
walkToReplace(v, cpy.Type, func(r ast.Node) {
cpy.Type = r.(ast.Expr)
})
}
walkExprList(v, cpy.Values)
if cpy.Comment != nil {
walkToReplace(v, cpy.Comment, func(r ast.Node) {
cpy.Comment = r.(*ast.CommentGroup)
})
}
replace(&cpy)
case *ast.TypeSpec:
cpy := *n
if cpy.Doc != nil {
walkToReplace(v, cpy.Doc, func(r ast.Node) {
cpy.Doc = r.(*ast.CommentGroup)
})
}
walkToReplace(v, cpy.Name, func(r ast.Node) {
cpy.Name = r.(*ast.Ident)
})
walkToReplace(v, cpy.Type, func(r ast.Node) {
cpy.Type = r.(ast.Expr)
})
if cpy.Comment != nil {
walkToReplace(v, cpy.Comment, func(r ast.Node) {
cpy.Comment = r.(*ast.CommentGroup)
})
}
replace(&cpy)
case *ast.GenDecl:
cpy := *n
if n.Specs != nil {
cpy.Specs = make([]ast.Spec, len(n.Specs))
copy(cpy.Specs, n.Specs)
}
if cpy.Doc != nil {
walkToReplace(v, cpy.Doc, func(r ast.Node) {
cpy.Doc = r.(*ast.CommentGroup)
})
}
for i, s := range cpy.Specs {
walkToReplace(v, s, func(r ast.Node) {
cpy.Specs[i] = r.(ast.Spec)
})
}
replace(&cpy)
case *ast.FuncDecl:
cpy := *n
if cpy.Doc != nil {
walkToReplace(v, cpy.Doc, func(r ast.Node) {
cpy.Doc = r.(*ast.CommentGroup)
})
}
if cpy.Recv != nil {
walkToReplace(v, cpy.Recv, func(r ast.Node) {
cpy.Recv = r.(*ast.FieldList)
})
}
walkToReplace(v, cpy.Name, func(r ast.Node) {
cpy.Name = r.(*ast.Ident)
})
walkToReplace(v, cpy.Type, func(r ast.Node) {
cpy.Type = r.(*ast.FuncType)
})
if cpy.Body != nil {
walkToReplace(v, cpy.Body, func(r ast.Node) {
cpy.Body = r.(*ast.BlockStmt)
})
}
// Files and packages
replace(&cpy)
case *ast.File:
cpy := *n
if cpy.Doc != nil {
walkToReplace(v, cpy.Doc, func(r ast.Node) {
cpy.Doc = r.(*ast.CommentGroup)
})
}
walkToReplace(v, cpy.Name, func(r ast.Node) {
cpy.Name = r.(*ast.Ident)
})
walkDeclList(v, cpy.Decls)
// don't walk cpy.Comments - they have been
// visited already through the individual
// nodes
replace(&cpy)
case *ast.Package:
cpy := *n
cpy.Files = map[string]*ast.File{}
for i, f := range n.Files {
cpy.Files[i] = f
walkToReplace(v, f, func(r ast.Node) {
cpy.Files[i] = r.(*ast.File)
})
}
replace(&cpy)
default:
panic(fmt.Sprintf("walkToReplace: unexpected node type %T", n))
}
if v != nil {
v.Visit(nil, func(ast.Node) { panic("can't replace the go-up nil") })
}
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/sourcecontext.go 0000664 0000000 0000000 00000002045 13622563124 0023561 0 ustar 00root root 0000000 0000000 package main
import (
"fmt"
"go/ast"
"go/token"
)
type sourceContext struct {
pkg *ast.Ident
imports []*ast.ImportSpec
interfaces []iface
types []*ast.TypeSpec
}
func (sc *sourceContext) validate() error {
if len(sc.interfaces) != 1 {
return fmt.Errorf("found %d interfaces, expecting exactly 1", len(sc.interfaces))
}
for _, i := range sc.interfaces {
for _, m := range i.methods {
if len(m.results) < 1 {
return fmt.Errorf("method %q of interface %q has no result types", m.name, i.name)
}
}
}
return nil
}
func (sc *sourceContext) importDecls() (decls []ast.Decl) {
have := map[string]struct{}{}
notHave := func(is *ast.ImportSpec) bool {
if _, has := have[is.Path.Value]; has {
return false
}
have[is.Path.Value] = struct{}{}
return true
}
for _, is := range sc.imports {
if notHave(is) {
decls = append(decls, importFor(is))
}
}
for _, is := range fetchImports() {
if notHave(is) {
decls = append(decls, &ast.GenDecl{Tok: token.IMPORT, Specs: []ast.Spec{is}})
}
}
return
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/templates/ 0000775 0000000 0000000 00000000000 13622563124 0022322 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/templates/full.go 0000664 0000000 0000000 00000002704 13622563124 0023616 0 ustar 00root root 0000000 0000000 package foo
import (
"context"
"encoding/json"
"errors"
"net/http"
"github.com/go-kit/kit/endpoint"
httptransport "github.com/go-kit/kit/transport/http"
)
type ExampleService struct {
}
type ExampleRequest struct {
I int
S string
}
type ExampleResponse struct {
S string
Err error
}
type Endpoints struct {
ExampleEndpoint endpoint.Endpoint
}
func (f ExampleService) ExampleEndpoint(ctx context.Context, i int, s string) (string, error) {
panic(errors.New("not implemented"))
}
func makeExampleEndpoint(f ExampleService) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(ExampleRequest)
s, err := f.ExampleEndpoint(ctx, req.I, req.S)
return ExampleResponse{S: s, Err: err}, nil
}
}
func inlineHandlerBuilder(m *http.ServeMux, endpoints Endpoints) {
m.Handle("/bar", httptransport.NewServer(endpoints.ExampleEndpoint, DecodeExampleRequest, EncodeExampleResponse))
}
func NewHTTPHandler(endpoints Endpoints) http.Handler {
m := http.NewServeMux()
inlineHandlerBuilder(m, endpoints)
return m
}
func DecodeExampleRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req ExampleRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodeExampleResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/ 0000775 0000000 0000000 00000000000 13622563124 0022135 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/anonfields/ 0000775 0000000 0000000 00000000000 13622563124 0024257 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/anonfields/default/ 0000775 0000000 0000000 00000000000 13622563124 0025703 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/anonfields/default/endpoints/ 0000775 0000000 0000000 00000000000 13622563124 0027706 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/anonfields/default/endpoints/endpoints.go 0000664 0000000 0000000 00000001040 13622563124 0032233 0 ustar 00root root 0000000 0000000 package endpoints
import (
"context"
"github.com/go-kit/kit/cmd/kitgen/testdata/anonfields/default/service"
"github.com/go-kit/kit/endpoint"
)
type FooRequest struct {
I int
S string
}
type FooResponse struct {
I int
Err error
}
func MakeFooEndpoint(s service.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(FooRequest)
i, err := s.Foo(ctx, req.I, req.S)
return FooResponse{I: i, Err: err}, nil
}
}
type Endpoints struct {
Foo endpoint.Endpoint
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/anonfields/default/http/ 0000775 0000000 0000000 00000000000 13622563124 0026662 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/anonfields/default/http/http.go 0000664 0000000 0000000 00000001410 13622563124 0030164 0 ustar 00root root 0000000 0000000 package http
import (
"context"
"encoding/json"
"net/http"
"github.com/go-kit/kit/cmd/kitgen/testdata/anonfields/default/endpoints"
httptransport "github.com/go-kit/kit/transport/http"
)
func NewHTTPHandler(endpoints endpoints.Endpoints) http.Handler {
m := http.NewServeMux()
m.Handle("/foo", httptransport.NewServer(endpoints.Foo, DecodeFooRequest, EncodeFooResponse))
return m
}
func DecodeFooRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req endpoints.FooRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodeFooResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/anonfields/default/service/ 0000775 0000000 0000000 00000000000 13622563124 0027343 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/anonfields/default/service/service.go 0000664 0000000 0000000 00000000303 13622563124 0031326 0 ustar 00root root 0000000 0000000 package service
import (
"context"
"errors"
)
type Service struct {
}
func (s Service) Foo(ctx context.Context, i int, string1 string) (int, error) {
panic(errors.New("not implemented"))
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/anonfields/flat/ 0000775 0000000 0000000 00000000000 13622563124 0025205 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/anonfields/flat/gokit.go 0000664 0000000 0000000 00000002354 13622563124 0026655 0 ustar 00root root 0000000 0000000 package foo
import (
"context"
"encoding/json"
"errors"
"net/http"
"github.com/go-kit/kit/endpoint"
httptransport "github.com/go-kit/kit/transport/http"
)
type Service struct {
}
func (s Service) Foo(ctx context.Context, i int, string1 string) (int, error) {
panic(errors.New("not implemented"))
}
type FooRequest struct {
I int
S string
}
type FooResponse struct {
I int
Err error
}
func MakeFooEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(FooRequest)
i, err := s.Foo(ctx, req.I, req.S)
return FooResponse{I: i, Err: err}, nil
}
}
type Endpoints struct {
Foo endpoint.Endpoint
}
func NewHTTPHandler(endpoints Endpoints) http.Handler {
m := http.NewServeMux()
m.Handle("/foo", httptransport.NewServer(endpoints.Foo, DecodeFooRequest, EncodeFooResponse))
return m
}
func DecodeFooRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req FooRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodeFooResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/anonfields/in.go 0000664 0000000 0000000 00000000236 13622563124 0025215 0 ustar 00root root 0000000 0000000 package foo
// from https://github.com/go-kit/kit/pull/589#issuecomment-319937530
type Service interface {
Foo(context.Context, int, string) (int, error)
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/foo/ 0000775 0000000 0000000 00000000000 13622563124 0022720 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/foo/default/ 0000775 0000000 0000000 00000000000 13622563124 0024344 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/foo/default/endpoints/ 0000775 0000000 0000000 00000000000 13622563124 0026347 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/foo/default/endpoints/endpoints.go 0000664 0000000 0000000 00000001037 13622563124 0030702 0 ustar 00root root 0000000 0000000 package endpoints
import (
"context"
"github.com/go-kit/kit/cmd/kitgen/testdata/foo/default/service"
"github.com/go-kit/kit/endpoint"
)
type BarRequest struct {
I int
S string
}
type BarResponse struct {
S string
Err error
}
func MakeBarEndpoint(f service.FooService) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(BarRequest)
s, err := f.Bar(ctx, req.I, req.S)
return BarResponse{S: s, Err: err}, nil
}
}
type Endpoints struct {
Bar endpoint.Endpoint
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/foo/default/http/ 0000775 0000000 0000000 00000000000 13622563124 0025323 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/foo/default/http/http.go 0000664 0000000 0000000 00000001401 13622563124 0026625 0 ustar 00root root 0000000 0000000 package http
import (
"context"
"encoding/json"
"net/http"
"github.com/go-kit/kit/cmd/kitgen/testdata/foo/default/endpoints"
httptransport "github.com/go-kit/kit/transport/http"
)
func NewHTTPHandler(endpoints endpoints.Endpoints) http.Handler {
m := http.NewServeMux()
m.Handle("/bar", httptransport.NewServer(endpoints.Bar, DecodeBarRequest, EncodeBarResponse))
return m
}
func DecodeBarRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req endpoints.BarRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodeBarResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/foo/default/service/ 0000775 0000000 0000000 00000000000 13622563124 0026004 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/foo/default/service/service.go 0000664 0000000 0000000 00000000306 13622563124 0027772 0 ustar 00root root 0000000 0000000 package service
import (
"context"
"errors"
)
type FooService struct {
}
func (f FooService) Bar(ctx context.Context, i int, s string) (string, error) {
panic(errors.New("not implemented"))
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/foo/flat/ 0000775 0000000 0000000 00000000000 13622563124 0023646 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/foo/flat/gokit.go 0000664 0000000 0000000 00000002365 13622563124 0025320 0 ustar 00root root 0000000 0000000 package foo
import (
"context"
"encoding/json"
"errors"
"net/http"
"github.com/go-kit/kit/endpoint"
httptransport "github.com/go-kit/kit/transport/http"
)
type FooService struct {
}
func (f FooService) Bar(ctx context.Context, i int, s string) (string, error) {
panic(errors.New("not implemented"))
}
type BarRequest struct {
I int
S string
}
type BarResponse struct {
S string
Err error
}
func MakeBarEndpoint(f FooService) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(BarRequest)
s, err := f.Bar(ctx, req.I, req.S)
return BarResponse{S: s, Err: err}, nil
}
}
type Endpoints struct {
Bar endpoint.Endpoint
}
func NewHTTPHandler(endpoints Endpoints) http.Handler {
m := http.NewServeMux()
m.Handle("/bar", httptransport.NewServer(endpoints.Bar, DecodeBarRequest, EncodeBarResponse))
return m
}
func DecodeBarRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req BarRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodeBarResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/foo/in.go 0000664 0000000 0000000 00000000146 13622563124 0023656 0 ustar 00root root 0000000 0000000 package foo
type FooService interface {
Bar(ctx context.Context, i int, s string) (string, error)
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/profilesvc/ 0000775 0000000 0000000 00000000000 13622563124 0024311 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/profilesvc/default/ 0000775 0000000 0000000 00000000000 13622563124 0025735 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/profilesvc/default/endpoints/ 0000775 0000000 0000000 00000000000 13622563124 0027740 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/profilesvc/default/endpoints/endpoints.go 0000664 0000000 0000000 00000007765 13622563124 0032311 0 ustar 00root root 0000000 0000000 package endpoints
import (
"context"
"github.com/go-kit/kit/cmd/kitgen/testdata/profilesvc/default/service"
"github.com/go-kit/kit/endpoint"
)
type PostProfileRequest struct {
P service.Profile
}
type PostProfileResponse struct {
Err error
}
func MakePostProfileEndpoint(s service.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(PostProfileRequest)
err := s.PostProfile(ctx, req.P)
return PostProfileResponse{Err: err}, nil
}
}
type GetProfileRequest struct {
Id string
}
type GetProfileResponse struct {
P service.Profile
Err error
}
func MakeGetProfileEndpoint(s service.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(GetProfileRequest)
P, err := s.GetProfile(ctx, req.Id)
return GetProfileResponse{P: P, Err: err}, nil
}
}
type PutProfileRequest struct {
Id string
P service.Profile
}
type PutProfileResponse struct {
Err error
}
func MakePutProfileEndpoint(s service.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(PutProfileRequest)
err := s.PutProfile(ctx, req.Id, req.P)
return PutProfileResponse{Err: err}, nil
}
}
type PatchProfileRequest struct {
Id string
P service.Profile
}
type PatchProfileResponse struct {
Err error
}
func MakePatchProfileEndpoint(s service.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(PatchProfileRequest)
err := s.PatchProfile(ctx, req.Id, req.P)
return PatchProfileResponse{Err: err}, nil
}
}
type DeleteProfileRequest struct {
Id string
}
type DeleteProfileResponse struct {
Err error
}
func MakeDeleteProfileEndpoint(s service.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(DeleteProfileRequest)
err := s.DeleteProfile(ctx, req.Id)
return DeleteProfileResponse{Err: err}, nil
}
}
type GetAddressesRequest struct {
ProfileID string
}
type GetAddressesResponse struct {
S []service.Address
Err error
}
func MakeGetAddressesEndpoint(s service.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(GetAddressesRequest)
slice1, err := s.GetAddresses(ctx, req.ProfileID)
return GetAddressesResponse{S: slice1, Err: err}, nil
}
}
type GetAddressRequest struct {
ProfileID string
AddressID string
}
type GetAddressResponse struct {
A service.Address
Err error
}
func MakeGetAddressEndpoint(s service.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(GetAddressRequest)
A, err := s.GetAddress(ctx, req.ProfileID, req.AddressID)
return GetAddressResponse{A: A, Err: err}, nil
}
}
type PostAddressRequest struct {
ProfileID string
A service.Address
}
type PostAddressResponse struct {
Err error
}
func MakePostAddressEndpoint(s service.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(PostAddressRequest)
err := s.PostAddress(ctx, req.ProfileID, req.A)
return PostAddressResponse{Err: err}, nil
}
}
type DeleteAddressRequest struct {
ProfileID string
AddressID string
}
type DeleteAddressResponse struct {
Err error
}
func MakeDeleteAddressEndpoint(s service.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(DeleteAddressRequest)
err := s.DeleteAddress(ctx, req.ProfileID, req.AddressID)
return DeleteAddressResponse{Err: err}, nil
}
}
type Endpoints struct {
PostProfile endpoint.Endpoint
GetProfile endpoint.Endpoint
PutProfile endpoint.Endpoint
PatchProfile endpoint.Endpoint
DeleteProfile endpoint.Endpoint
GetAddresses endpoint.Endpoint
GetAddress endpoint.Endpoint
PostAddress endpoint.Endpoint
DeleteAddress endpoint.Endpoint
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/profilesvc/default/http/ 0000775 0000000 0000000 00000000000 13622563124 0026714 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/profilesvc/default/http/http.go 0000664 0000000 0000000 00000012005 13622563124 0030220 0 ustar 00root root 0000000 0000000 package http
import (
"context"
"encoding/json"
"net/http"
"github.com/go-kit/kit/cmd/kitgen/testdata/profilesvc/default/endpoints"
httptransport "github.com/go-kit/kit/transport/http"
)
func NewHTTPHandler(endpoints endpoints.Endpoints) http.Handler {
m := http.NewServeMux()
m.Handle("/postprofile", httptransport.NewServer(endpoints.PostProfile, DecodePostProfileRequest, EncodePostProfileResponse))
m.Handle("/getprofile", httptransport.NewServer(endpoints.GetProfile, DecodeGetProfileRequest, EncodeGetProfileResponse))
m.Handle("/putprofile", httptransport.NewServer(endpoints.PutProfile, DecodePutProfileRequest, EncodePutProfileResponse))
m.Handle("/patchprofile", httptransport.NewServer(endpoints.PatchProfile, DecodePatchProfileRequest, EncodePatchProfileResponse))
m.Handle("/deleteprofile", httptransport.NewServer(endpoints.DeleteProfile, DecodeDeleteProfileRequest, EncodeDeleteProfileResponse))
m.Handle("/getaddresses", httptransport.NewServer(endpoints.GetAddresses, DecodeGetAddressesRequest, EncodeGetAddressesResponse))
m.Handle("/getaddress", httptransport.NewServer(endpoints.GetAddress, DecodeGetAddressRequest, EncodeGetAddressResponse))
m.Handle("/postaddress", httptransport.NewServer(endpoints.PostAddress, DecodePostAddressRequest, EncodePostAddressResponse))
m.Handle("/deleteaddress", httptransport.NewServer(endpoints.DeleteAddress, DecodeDeleteAddressRequest, EncodeDeleteAddressResponse))
return m
}
func DecodePostProfileRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req endpoints.PostProfileRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodePostProfileResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
func DecodeGetProfileRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req endpoints.GetProfileRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodeGetProfileResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
func DecodePutProfileRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req endpoints.PutProfileRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodePutProfileResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
func DecodePatchProfileRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req endpoints.PatchProfileRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodePatchProfileResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
func DecodeDeleteProfileRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req endpoints.DeleteProfileRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodeDeleteProfileResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
func DecodeGetAddressesRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req endpoints.GetAddressesRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodeGetAddressesResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
func DecodeGetAddressRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req endpoints.GetAddressRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodeGetAddressResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
func DecodePostAddressRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req endpoints.PostAddressRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodePostAddressResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
func DecodeDeleteAddressRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req endpoints.DeleteAddressRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodeDeleteAddressResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/profilesvc/default/service/ 0000775 0000000 0000000 00000000000 13622563124 0027375 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/profilesvc/default/service/service.go 0000664 0000000 0000000 00000002641 13622563124 0031367 0 ustar 00root root 0000000 0000000 package service
import (
"context"
"errors"
)
type Profile struct {
ID string `json:"id"`
Name string `json:"name,omitempty"`
Addresses []Address `json:"addresses,omitempty"`
}
type Address struct {
ID string `json:"id"`
Location string `json:"location,omitempty"`
}
type Service struct {
}
func (s Service) PostProfile(ctx context.Context, p Profile) error {
panic(errors.New("not implemented"))
}
func (s Service) GetProfile(ctx context.Context, id string) (Profile, error) {
panic(errors.New("not implemented"))
}
func (s Service) PutProfile(ctx context.Context, id string, p Profile) error {
panic(errors.New("not implemented"))
}
func (s Service) PatchProfile(ctx context.Context, id string, p Profile) error {
panic(errors.New("not implemented"))
}
func (s Service) DeleteProfile(ctx context.Context, id string) error {
panic(errors.New("not implemented"))
}
func (s Service) GetAddresses(ctx context.Context, profileID string) ([]Address, error) {
panic(errors.New("not implemented"))
}
func (s Service) GetAddress(ctx context.Context, profileID string, addressID string) (Address, error) {
panic(errors.New("not implemented"))
}
func (s Service) PostAddress(ctx context.Context, profileID string, a Address) error {
panic(errors.New("not implemented"))
}
func (s Service) DeleteAddress(ctx context.Context, profileID string, addressID string) error {
panic(errors.New("not implemented"))
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/profilesvc/flat/ 0000775 0000000 0000000 00000000000 13622563124 0025237 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/profilesvc/flat/gokit.go 0000664 0000000 0000000 00000023733 13622563124 0026713 0 ustar 00root root 0000000 0000000 package profilesvc
import (
"context"
"encoding/json"
"errors"
"net/http"
"github.com/go-kit/kit/endpoint"
httptransport "github.com/go-kit/kit/transport/http"
)
type Profile struct {
ID string `json:"id"`
Name string `json:"name,omitempty"`
Addresses []Address `json:"addresses,omitempty"`
}
type Address struct {
ID string `json:"id"`
Location string `json:"location,omitempty"`
}
type Service struct {
}
func (s Service) PostProfile(ctx context.Context, p Profile) error {
panic(errors.New("not implemented"))
}
type PostProfileRequest struct {
P Profile
}
type PostProfileResponse struct {
Err error
}
func MakePostProfileEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(PostProfileRequest)
err := s.PostProfile(ctx, req.P)
return PostProfileResponse{Err: err}, nil
}
}
func (s Service) GetProfile(ctx context.Context, id string) (Profile, error) {
panic(errors.New("not implemented"))
}
type GetProfileRequest struct {
Id string
}
type GetProfileResponse struct {
P Profile
Err error
}
func MakeGetProfileEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(GetProfileRequest)
P, err := s.GetProfile(ctx, req.Id)
return GetProfileResponse{P: P, Err: err}, nil
}
}
func (s Service) PutProfile(ctx context.Context, id string, p Profile) error {
panic(errors.New("not implemented"))
}
type PutProfileRequest struct {
Id string
P Profile
}
type PutProfileResponse struct {
Err error
}
func MakePutProfileEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(PutProfileRequest)
err := s.PutProfile(ctx, req.Id, req.P)
return PutProfileResponse{Err: err}, nil
}
}
func (s Service) PatchProfile(ctx context.Context, id string, p Profile) error {
panic(errors.New("not implemented"))
}
type PatchProfileRequest struct {
Id string
P Profile
}
type PatchProfileResponse struct {
Err error
}
func MakePatchProfileEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(PatchProfileRequest)
err := s.PatchProfile(ctx, req.Id, req.P)
return PatchProfileResponse{Err: err}, nil
}
}
func (s Service) DeleteProfile(ctx context.Context, id string) error {
panic(errors.New("not implemented"))
}
type DeleteProfileRequest struct {
Id string
}
type DeleteProfileResponse struct {
Err error
}
func MakeDeleteProfileEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(DeleteProfileRequest)
err := s.DeleteProfile(ctx, req.Id)
return DeleteProfileResponse{Err: err}, nil
}
}
func (s Service) GetAddresses(ctx context.Context, profileID string) ([]Address, error) {
panic(errors.New("not implemented"))
}
type GetAddressesRequest struct {
ProfileID string
}
type GetAddressesResponse struct {
S []Address
Err error
}
func MakeGetAddressesEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(GetAddressesRequest)
slice1, err := s.GetAddresses(ctx, req.ProfileID)
return GetAddressesResponse{S: slice1, Err: err}, nil
}
}
func (s Service) GetAddress(ctx context.Context, profileID string, addressID string) (Address, error) {
panic(errors.New("not implemented"))
}
type GetAddressRequest struct {
ProfileID string
AddressID string
}
type GetAddressResponse struct {
A Address
Err error
}
func MakeGetAddressEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(GetAddressRequest)
A, err := s.GetAddress(ctx, req.ProfileID, req.AddressID)
return GetAddressResponse{A: A, Err: err}, nil
}
}
func (s Service) PostAddress(ctx context.Context, profileID string, a Address) error {
panic(errors.New("not implemented"))
}
type PostAddressRequest struct {
ProfileID string
A Address
}
type PostAddressResponse struct {
Err error
}
func MakePostAddressEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(PostAddressRequest)
err := s.PostAddress(ctx, req.ProfileID, req.A)
return PostAddressResponse{Err: err}, nil
}
}
func (s Service) DeleteAddress(ctx context.Context, profileID string, addressID string) error {
panic(errors.New("not implemented"))
}
type DeleteAddressRequest struct {
ProfileID string
AddressID string
}
type DeleteAddressResponse struct {
Err error
}
func MakeDeleteAddressEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(DeleteAddressRequest)
err := s.DeleteAddress(ctx, req.ProfileID, req.AddressID)
return DeleteAddressResponse{Err: err}, nil
}
}
type Endpoints struct {
PostProfile endpoint.Endpoint
GetProfile endpoint.Endpoint
PutProfile endpoint.Endpoint
PatchProfile endpoint.Endpoint
DeleteProfile endpoint.Endpoint
GetAddresses endpoint.Endpoint
GetAddress endpoint.Endpoint
PostAddress endpoint.Endpoint
DeleteAddress endpoint.Endpoint
}
func NewHTTPHandler(endpoints Endpoints) http.Handler {
m := http.NewServeMux()
m.Handle("/postprofile", httptransport.NewServer(endpoints.PostProfile, DecodePostProfileRequest, EncodePostProfileResponse))
m.Handle("/getprofile", httptransport.NewServer(endpoints.GetProfile, DecodeGetProfileRequest, EncodeGetProfileResponse))
m.Handle("/putprofile", httptransport.NewServer(endpoints.PutProfile, DecodePutProfileRequest, EncodePutProfileResponse))
m.Handle("/patchprofile", httptransport.NewServer(endpoints.PatchProfile, DecodePatchProfileRequest, EncodePatchProfileResponse))
m.Handle("/deleteprofile", httptransport.NewServer(endpoints.DeleteProfile, DecodeDeleteProfileRequest, EncodeDeleteProfileResponse))
m.Handle("/getaddresses", httptransport.NewServer(endpoints.GetAddresses, DecodeGetAddressesRequest, EncodeGetAddressesResponse))
m.Handle("/getaddress", httptransport.NewServer(endpoints.GetAddress, DecodeGetAddressRequest, EncodeGetAddressResponse))
m.Handle("/postaddress", httptransport.NewServer(endpoints.PostAddress, DecodePostAddressRequest, EncodePostAddressResponse))
m.Handle("/deleteaddress", httptransport.NewServer(endpoints.DeleteAddress, DecodeDeleteAddressRequest, EncodeDeleteAddressResponse))
return m
}
func DecodePostProfileRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req PostProfileRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodePostProfileResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
func DecodeGetProfileRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req GetProfileRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodeGetProfileResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
func DecodePutProfileRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req PutProfileRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodePutProfileResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
func DecodePatchProfileRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req PatchProfileRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodePatchProfileResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
func DecodeDeleteProfileRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req DeleteProfileRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodeDeleteProfileResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
func DecodeGetAddressesRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req GetAddressesRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodeGetAddressesResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
func DecodeGetAddressRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req GetAddressRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodeGetAddressResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
func DecodePostAddressRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req PostAddressRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodePostAddressResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
func DecodeDeleteAddressRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req DeleteAddressRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodeDeleteAddressResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/profilesvc/in.go 0000664 0000000 0000000 00000001575 13622563124 0025256 0 ustar 00root root 0000000 0000000 package profilesvc
type Service interface {
PostProfile(ctx context.Context, p Profile) error
GetProfile(ctx context.Context, id string) (Profile, error)
PutProfile(ctx context.Context, id string, p Profile) error
PatchProfile(ctx context.Context, id string, p Profile) error
DeleteProfile(ctx context.Context, id string) error
GetAddresses(ctx context.Context, profileID string) ([]Address, error)
GetAddress(ctx context.Context, profileID string, addressID string) (Address, error)
PostAddress(ctx context.Context, profileID string, a Address) error
DeleteAddress(ctx context.Context, profileID string, addressID string) error
}
type Profile struct {
ID string `json:"id"`
Name string `json:"name,omitempty"`
Addresses []Address `json:"addresses,omitempty"`
}
type Address struct {
ID string `json:"id"`
Location string `json:"location,omitempty"`
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/stringservice/ 0000775 0000000 0000000 00000000000 13622563124 0025024 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/stringservice/default/ 0000775 0000000 0000000 00000000000 13622563124 0026450 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/stringservice/default/endpoints/ 0000775 0000000 0000000 00000000000 13622563124 0030453 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/stringservice/default/endpoints/endpoints.go 0000664 0000000 0000000 00000001660 13622563124 0033010 0 ustar 00root root 0000000 0000000 package endpoints
import (
"context"
"github.com/go-kit/kit/cmd/kitgen/testdata/stringservice/default/service"
"github.com/go-kit/kit/endpoint"
)
type ConcatRequest struct {
A string
B string
}
type ConcatResponse struct {
S string
Err error
}
func MakeConcatEndpoint(s service.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(ConcatRequest)
string1, err := s.Concat(ctx, req.A, req.B)
return ConcatResponse{S: string1, Err: err}, nil
}
}
type CountRequest struct {
S string
}
type CountResponse struct {
Count int
}
func MakeCountEndpoint(s service.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(CountRequest)
count := s.Count(ctx, req.S)
return CountResponse{Count: count}, nil
}
}
type Endpoints struct {
Concat endpoint.Endpoint
Count endpoint.Endpoint
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/stringservice/default/http/ 0000775 0000000 0000000 00000000000 13622563124 0027427 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/stringservice/default/http/http.go 0000664 0000000 0000000 00000002414 13622563124 0030736 0 ustar 00root root 0000000 0000000 package http
import (
"context"
"encoding/json"
"net/http"
"github.com/go-kit/kit/cmd/kitgen/testdata/stringservice/default/endpoints"
httptransport "github.com/go-kit/kit/transport/http"
)
func NewHTTPHandler(endpoints endpoints.Endpoints) http.Handler {
m := http.NewServeMux()
m.Handle("/concat", httptransport.NewServer(endpoints.Concat, DecodeConcatRequest, EncodeConcatResponse))
m.Handle("/count", httptransport.NewServer(endpoints.Count, DecodeCountRequest, EncodeCountResponse))
return m
}
func DecodeConcatRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req endpoints.ConcatRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodeConcatResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
func DecodeCountRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req endpoints.CountRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodeCountResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/stringservice/default/service/ 0000775 0000000 0000000 00000000000 13622563124 0030110 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/stringservice/default/service/service.go 0000664 0000000 0000000 00000000460 13622563124 0032077 0 ustar 00root root 0000000 0000000 package service
import (
"context"
"errors"
)
type Service struct {
}
func (s Service) Concat(ctx context.Context, a string, b string) (string, error) {
panic(errors.New("not implemented"))
}
func (s Service) Count(ctx context.Context, string1 string) int {
panic(errors.New("not implemented"))
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/stringservice/flat/ 0000775 0000000 0000000 00000000000 13622563124 0025752 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/stringservice/flat/gokit.go 0000664 0000000 0000000 00000004325 13622563124 0027422 0 ustar 00root root 0000000 0000000 package foo
import (
"context"
"encoding/json"
"errors"
"net/http"
"github.com/go-kit/kit/endpoint"
httptransport "github.com/go-kit/kit/transport/http"
)
type Service struct {
}
func (s Service) Concat(ctx context.Context, a string, b string) (string, error) {
panic(errors.New("not implemented"))
}
type ConcatRequest struct {
A string
B string
}
type ConcatResponse struct {
S string
Err error
}
func MakeConcatEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(ConcatRequest)
string1, err := s.Concat(ctx, req.A, req.B)
return ConcatResponse{S: string1, Err: err}, nil
}
}
func (s Service) Count(ctx context.Context, string1 string) int {
panic(errors.New("not implemented"))
}
type CountRequest struct {
S string
}
type CountResponse struct {
Count int
}
func MakeCountEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(CountRequest)
count := s.Count(ctx, req.S)
return CountResponse{Count: count}, nil
}
}
type Endpoints struct {
Concat endpoint.Endpoint
Count endpoint.Endpoint
}
func NewHTTPHandler(endpoints Endpoints) http.Handler {
m := http.NewServeMux()
m.Handle("/concat", httptransport.NewServer(endpoints.Concat, DecodeConcatRequest, EncodeConcatResponse))
m.Handle("/count", httptransport.NewServer(endpoints.Count, DecodeCountRequest, EncodeCountResponse))
return m
}
func DecodeConcatRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req ConcatRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodeConcatResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
func DecodeCountRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req CountRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodeCountResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/stringservice/in.go 0000664 0000000 0000000 00000000224 13622563124 0025757 0 ustar 00root root 0000000 0000000 package foo
type Service interface {
Concat(ctx context.Context, a, b string) (string, error)
Count(ctx context.Context, s string) (count int)
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/underscores/ 0000775 0000000 0000000 00000000000 13622563124 0024471 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/underscores/default/ 0000775 0000000 0000000 00000000000 13622563124 0026115 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/underscores/default/endpoints/ 0000775 0000000 0000000 00000000000 13622563124 0030120 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/underscores/default/endpoints/endpoints.go 0000664 0000000 0000000 00000001020 13622563124 0032443 0 ustar 00root root 0000000 0000000 package endpoints
import (
"context"
"github.com/go-kit/kit/cmd/kitgen/testdata/underscores/default/service"
"github.com/go-kit/kit/endpoint"
)
type FooRequest struct {
I int
}
type FooResponse struct {
I int
Err error
}
func MakeFooEndpoint(s service.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(FooRequest)
i, err := s.Foo(ctx, req.I)
return FooResponse{I: i, Err: err}, nil
}
}
type Endpoints struct {
Foo endpoint.Endpoint
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/underscores/default/http/ 0000775 0000000 0000000 00000000000 13622563124 0027074 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/underscores/default/http/http.go 0000664 0000000 0000000 00000001411 13622563124 0030377 0 ustar 00root root 0000000 0000000 package http
import (
"context"
"encoding/json"
"net/http"
"github.com/go-kit/kit/cmd/kitgen/testdata/underscores/default/endpoints"
httptransport "github.com/go-kit/kit/transport/http"
)
func NewHTTPHandler(endpoints endpoints.Endpoints) http.Handler {
m := http.NewServeMux()
m.Handle("/foo", httptransport.NewServer(endpoints.Foo, DecodeFooRequest, EncodeFooResponse))
return m
}
func DecodeFooRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req endpoints.FooRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodeFooResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/underscores/default/service/ 0000775 0000000 0000000 00000000000 13622563124 0027555 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/underscores/default/service/service.go 0000664 0000000 0000000 00000000263 13622563124 0031545 0 ustar 00root root 0000000 0000000 package service
import (
"context"
"errors"
)
type Service struct {
}
func (s Service) Foo(ctx context.Context, i int) (int, error) {
panic(errors.New("not implemented"))
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/underscores/flat/ 0000775 0000000 0000000 00000000000 13622563124 0025417 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/underscores/flat/gokit.go 0000664 0000000 0000000 00000002323 13622563124 0027063 0 ustar 00root root 0000000 0000000 package underscores
import (
"context"
"encoding/json"
"errors"
"net/http"
"github.com/go-kit/kit/endpoint"
httptransport "github.com/go-kit/kit/transport/http"
)
type Service struct {
}
func (s Service) Foo(ctx context.Context, i int) (int, error) {
panic(errors.New("not implemented"))
}
type FooRequest struct {
I int
}
type FooResponse struct {
I int
Err error
}
func MakeFooEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(FooRequest)
i, err := s.Foo(ctx, req.I)
return FooResponse{I: i, Err: err}, nil
}
}
type Endpoints struct {
Foo endpoint.Endpoint
}
func NewHTTPHandler(endpoints Endpoints) http.Handler {
m := http.NewServeMux()
m.Handle("/foo", httptransport.NewServer(endpoints.Foo, DecodeFooRequest, EncodeFooResponse))
return m
}
func DecodeFooRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req FooRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
func EncodeFooResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/testdata/underscores/in.go 0000664 0000000 0000000 00000000156 13622563124 0025430 0 ustar 00root root 0000000 0000000 package underscores
import "context"
type Service interface {
Foo(_ context.Context, _ int) (int, error)
}
golang-github-go-kit-kit-0.10.0/cmd/kitgen/transform.go 0000664 0000000 0000000 00000011725 13622563124 0022674 0 ustar 00root root 0000000 0000000 package main
import (
"bytes"
"fmt"
"go/ast"
"go/format"
"go/token"
"io"
"os"
"path/filepath"
"sort"
"strings"
"github.com/davecgh/go-spew/spew"
"github.com/pkg/errors"
"golang.org/x/tools/imports"
)
type (
files map[string]io.Reader
layout interface {
transformAST(ctx *sourceContext) (files, error)
}
outputTree map[string]*ast.File
)
func (ot outputTree) addFile(path, pkgname string) *ast.File {
file := &ast.File{
Name: id(pkgname),
Decls: []ast.Decl{},
}
ot[path] = file
return file
}
func getGopath() string {
gopath, set := os.LookupEnv("GOPATH")
if !set {
return filepath.Join(os.Getenv("HOME"), "go")
}
return gopath
}
func importPath(targetDir, gopath string) (string, error) {
if !filepath.IsAbs(targetDir) {
return "", fmt.Errorf("%q is not an absolute path", targetDir)
}
for _, dir := range filepath.SplitList(gopath) {
abspath, err := filepath.Abs(dir)
if err != nil {
continue
}
srcPath := filepath.Join(abspath, "src")
res, err := filepath.Rel(srcPath, targetDir)
if err != nil {
continue
}
if strings.Index(res, "..") == -1 {
return res, nil
}
}
return "", fmt.Errorf("%q is not in GOPATH (%s)", targetDir, gopath)
}
func selectify(file *ast.File, pkgName, identName, importPath string) *ast.File {
if file.Name.Name == pkgName {
return file
}
selector := sel(id(pkgName), id(identName))
var did bool
if file, did = selectifyIdent(identName, file, selector); did {
addImport(file, importPath)
}
return file
}
type selIdentFn func(ast.Node, func(ast.Node)) Visitor
func (f selIdentFn) Visit(node ast.Node, r func(ast.Node)) Visitor {
return f(node, r)
}
func selectifyIdent(identName string, file *ast.File, selector ast.Expr) (*ast.File, bool) {
var replaced bool
var r selIdentFn
r = selIdentFn(func(node ast.Node, replaceWith func(ast.Node)) Visitor {
switch id := node.(type) {
case *ast.SelectorExpr:
return nil
case *ast.Ident:
if id.Name == identName {
replaced = true
replaceWith(selector)
}
}
return r
})
return WalkReplace(r, file).(*ast.File), replaced
}
func formatNode(fname string, node ast.Node) (*bytes.Buffer, error) {
if file, is := node.(*ast.File); is {
sort.Stable(sortableDecls(file.Decls))
}
outfset := token.NewFileSet()
buf := &bytes.Buffer{}
err := format.Node(buf, outfset, node)
if err != nil {
return nil, err
}
imps, err := imports.Process(fname, buf.Bytes(), nil)
if err != nil {
return nil, err
}
return bytes.NewBuffer(imps), nil
}
type sortableDecls []ast.Decl
func (sd sortableDecls) Len() int {
return len(sd)
}
func (sd sortableDecls) Less(i int, j int) bool {
switch left := sd[i].(type) {
case *ast.GenDecl:
switch right := sd[j].(type) {
default:
return left.Tok == token.IMPORT
case *ast.GenDecl:
return left.Tok == token.IMPORT && right.Tok != token.IMPORT
}
}
return false
}
func (sd sortableDecls) Swap(i int, j int) {
sd[i], sd[j] = sd[j], sd[i]
}
func formatNodes(nodes outputTree) (files, error) {
res := files{}
var err error
for fn, node := range nodes {
res[fn], err = formatNode(fn, node)
if err != nil {
return nil, errors.Wrapf(err, "formatNodes")
}
}
return res, nil
}
// XXX debug
func spewDecls(f *ast.File) {
for _, d := range f.Decls {
switch dcl := d.(type) {
default:
spew.Dump(dcl)
case *ast.GenDecl:
spew.Dump(dcl.Tok)
case *ast.FuncDecl:
spew.Dump(dcl.Name.Name)
}
}
}
func addImports(root *ast.File, ctx *sourceContext) {
root.Decls = append(root.Decls, ctx.importDecls()...)
}
func addImport(root *ast.File, path string) {
for _, d := range root.Decls {
if imp, is := d.(*ast.GenDecl); is && imp.Tok == token.IMPORT {
for _, s := range imp.Specs {
if s.(*ast.ImportSpec).Path.Value == `"`+filepath.ToSlash(path)+`"` {
return // already have one
// xxx aliased imports?
}
}
}
}
root.Decls = append(root.Decls, importFor(importSpec(path)))
}
func addStubStruct(root *ast.File, iface iface) {
root.Decls = append(root.Decls, iface.stubStructDecl())
}
func addType(root *ast.File, typ *ast.TypeSpec) {
root.Decls = append(root.Decls, typeDecl(typ))
}
func addMethod(root *ast.File, iface iface, meth method) {
def := meth.definition(iface)
root.Decls = append(root.Decls, def)
}
func addRequestStruct(root *ast.File, meth method) {
root.Decls = append(root.Decls, meth.requestStruct())
}
func addResponseStruct(root *ast.File, meth method) {
root.Decls = append(root.Decls, meth.responseStruct())
}
func addEndpointMaker(root *ast.File, ifc iface, meth method) {
root.Decls = append(root.Decls, meth.endpointMaker(ifc))
}
func addEndpointsStruct(root *ast.File, ifc iface) {
root.Decls = append(root.Decls, ifc.endpointsStruct())
}
func addHTTPHandler(root *ast.File, ifc iface) {
root.Decls = append(root.Decls, ifc.httpHandler())
}
func addDecoder(root *ast.File, meth method) {
root.Decls = append(root.Decls, meth.decoderFunc())
}
func addEncoder(root *ast.File, meth method) {
root.Decls = append(root.Decls, meth.encoderFunc())
}
golang-github-go-kit-kit-0.10.0/coveralls.bash 0000775 0000000 0000000 00000001105 13622563124 0021131 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash
if ! type -P gover
then
echo gover missing: go get github.com/modocache/gover
exit 1
fi
if ! type -P goveralls
then
echo goveralls missing: go get github.com/mattn/goveralls
exit 1
fi
if [[ "$COVERALLS_TOKEN" == "" ]]
then
echo COVERALLS_TOKEN not set
exit 1
fi
go list ./... | grep -v '/examples/' | cut -d'/' -f 4- | while read d
do
cd $d
go test -covermode count -coverprofile coverage.coverprofile
cd -
done
gover
goveralls -coverprofile gover.coverprofile -service travis-ci -repotoken $COVERALLS_TOKEN
find . -name '*.coverprofile' -delete
golang-github-go-kit-kit-0.10.0/docker-compose-integration.yml 0000664 0000000 0000000 00000001051 13622563124 0024253 0 ustar 00root root 0000000 0000000 version: '2'
services:
etcd:
image: quay.io/coreos/etcd
ports:
- "2379:2379"
command: /usr/local/bin/etcd -advertise-client-urls http://0.0.0.0:2379,http://0.0.0.0:4001 -listen-client-urls "http://0.0.0.0:2379,http://0.0.0.0:4001"
consul:
image: progrium/consul
ports:
- "8500:8500"
command: -server -bootstrap
zk:
image: zookeeper
ports:
- "2181:2181"
eureka:
image: springcloud/eureka
environment:
eureka.server.responseCacheUpdateIntervalMs: 1000
ports:
- "8761:8761"
golang-github-go-kit-kit-0.10.0/endpoint/ 0000775 0000000 0000000 00000000000 13622563124 0020120 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/endpoint/doc.go 0000664 0000000 0000000 00000000323 13622563124 0021212 0 ustar 00root root 0000000 0000000 // Package endpoint defines an abstraction for RPCs.
//
// Endpoints are a fundamental building block for many Go kit components.
// Endpoints are implemented by servers, and called by clients.
package endpoint
golang-github-go-kit-kit-0.10.0/endpoint/endpoint.go 0000664 0000000 0000000 00000002656 13622563124 0022300 0 ustar 00root root 0000000 0000000 package endpoint
import (
"context"
)
// Endpoint is the fundamental building block of servers and clients.
// It represents a single RPC method.
type Endpoint func(ctx context.Context, request interface{}) (response interface{}, err error)
// Nop is an endpoint that does nothing and returns a nil error.
// Useful for tests.
func Nop(context.Context, interface{}) (interface{}, error) { return struct{}{}, nil }
// Middleware is a chainable behavior modifier for endpoints.
type Middleware func(Endpoint) Endpoint
// Chain is a helper function for composing middlewares. Requests will
// traverse them in the order they're declared. That is, the first middleware
// is treated as the outermost middleware.
func Chain(outer Middleware, others ...Middleware) Middleware {
return func(next Endpoint) Endpoint {
for i := len(others) - 1; i >= 0; i-- { // reverse
next = others[i](next)
}
return outer(next)
}
}
// Failer may be implemented by Go kit response types that contain business
// logic error details. If Failed returns a non-nil error, the Go kit transport
// layer may interpret this as a business logic error, and may encode it
// differently than a regular, successful response.
//
// It's not necessary for your response types to implement Failer, but it may
// help for more sophisticated use cases. The addsvc example shows how Failer
// should be used by a complete application.
type Failer interface {
Failed() error
}
golang-github-go-kit-kit-0.10.0/endpoint/endpoint_example_test.go 0000664 0000000 0000000 00000001517 13622563124 0025045 0 ustar 00root root 0000000 0000000 package endpoint_test
import (
"context"
"fmt"
"github.com/go-kit/kit/endpoint"
)
func ExampleChain() {
e := endpoint.Chain(
annotate("first"),
annotate("second"),
annotate("third"),
)(myEndpoint)
if _, err := e(ctx, req); err != nil {
panic(err)
}
// Output:
// first pre
// second pre
// third pre
// my endpoint!
// third post
// second post
// first post
}
var (
ctx = context.Background()
req = struct{}{}
)
func annotate(s string) endpoint.Middleware {
return func(next endpoint.Endpoint) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
fmt.Println(s, "pre")
defer fmt.Println(s, "post")
return next(ctx, request)
}
}
}
func myEndpoint(context.Context, interface{}) (interface{}, error) {
fmt.Println("my endpoint!")
return struct{}{}, nil
}
golang-github-go-kit-kit-0.10.0/examples/ 0000775 0000000 0000000 00000000000 13622563124 0020116 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/README.md 0000664 0000000 0000000 00000000237 13622563124 0021377 0 ustar 00root root 0000000 0000000 # Examples
For more information about these examples,
including a walkthrough of the stringsvc example,
see [gokit.io/examples](https://gokit.io/examples).
golang-github-go-kit-kit-0.10.0/examples/addsvc/ 0000775 0000000 0000000 00000000000 13622563124 0021362 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/addsvc/README.md 0000664 0000000 0000000 00000001764 13622563124 0022651 0 ustar 00root root 0000000 0000000 # addsvc
addsvc is an example microservice which takes full advantage of most of Go
kit's features, including both service- and transport-level middlewares,
speaking multiple transports simultaneously, distributed tracing, and rich
error definitions. The server binary is available in cmd/addsvc. The client
binary is available in cmd/addcli.
Finally, the addtransport package provides both server and clients for each
supported transport. The client structs bake-in certain middlewares, in order to
demonstrate the _client library pattern_. But beware: client libraries are
generally a bad idea, because they easily lead to the
[distributed monolith antipattern](https://www.microservices.com/talks/dont-build-a-distributed-monolith/).
If you don't _know_ you need to use one in your organization, it's probably best
avoided: prefer moving that logic to consumers, and relying on
[contract testing](https://docs.pact.io/best_practices/contract_tests_not_functional_tests.html)
to detect incompatibilities.
golang-github-go-kit-kit-0.10.0/examples/addsvc/cmd/ 0000775 0000000 0000000 00000000000 13622563124 0022125 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/addsvc/cmd/addcli/ 0000775 0000000 0000000 00000000000 13622563124 0023345 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/addsvc/cmd/addcli/addcli.go 0000664 0000000 0000000 00000016250 13622563124 0025120 0 ustar 00root root 0000000 0000000 package main
import (
"context"
"flag"
"fmt"
"os"
"strconv"
"text/tabwriter"
"time"
"google.golang.org/grpc"
"github.com/apache/thrift/lib/go/thrift"
lightstep "github.com/lightstep/lightstep-tracer-go"
stdopentracing "github.com/opentracing/opentracing-go"
zipkinot "github.com/openzipkin-contrib/zipkin-go-opentracing"
zipkin "github.com/openzipkin/zipkin-go"
zipkinhttp "github.com/openzipkin/zipkin-go/reporter/http"
"sourcegraph.com/sourcegraph/appdash"
appdashot "sourcegraph.com/sourcegraph/appdash/opentracing"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/examples/addsvc/pkg/addservice"
"github.com/go-kit/kit/examples/addsvc/pkg/addtransport"
addthrift "github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc"
)
func main() {
// The addcli presumes no service discovery system, and expects users to
// provide the direct address of an addsvc. This presumption is reflected in
// the addcli binary and the client packages: the -transport.addr flags
// and various client constructors both expect host:port strings. For an
// example service with a client built on top of a service discovery system,
// see profilesvc.
fs := flag.NewFlagSet("addcli", flag.ExitOnError)
var (
httpAddr = fs.String("http-addr", "", "HTTP address of addsvc")
grpcAddr = fs.String("grpc-addr", "", "gRPC address of addsvc")
thriftAddr = fs.String("thrift-addr", "", "Thrift address of addsvc")
jsonRPCAddr = fs.String("jsonrpc-addr", "", "JSON RPC address of addsvc")
thriftProtocol = fs.String("thrift-protocol", "binary", "binary, compact, json, simplejson")
thriftBuffer = fs.Int("thrift-buffer", 0, "0 for unbuffered")
thriftFramed = fs.Bool("thrift-framed", false, "true to enable framing")
zipkinURL = fs.String("zipkin-url", "", "Enable Zipkin tracing via HTTP reporter URL e.g. http://localhost:9411/api/v2/spans")
zipkinBridge = fs.Bool("zipkin-ot-bridge", false, "Use Zipkin OpenTracing bridge instead of native implementation")
lightstepToken = fs.String("lightstep-token", "", "Enable LightStep tracing via a LightStep access token")
appdashAddr = fs.String("appdash-addr", "", "Enable Appdash tracing via an Appdash server host:port")
method = fs.String("method", "sum", "sum, concat")
)
fs.Usage = usageFor(fs, os.Args[0]+" [flags] ")
fs.Parse(os.Args[1:])
if len(fs.Args()) != 2 {
fs.Usage()
os.Exit(1)
}
// This is a demonstration of the native Zipkin tracing client. If using
// Zipkin this is the more idiomatic client over OpenTracing.
var zipkinTracer *zipkin.Tracer
{
if *zipkinURL != "" {
var (
err error
hostPort = "" // if host:port is unknown we can keep this empty
serviceName = "addsvc-cli"
reporter = zipkinhttp.NewReporter(*zipkinURL)
)
defer reporter.Close()
zEP, _ := zipkin.NewEndpoint(serviceName, hostPort)
zipkinTracer, err = zipkin.NewTracer(reporter, zipkin.WithLocalEndpoint(zEP))
if err != nil {
fmt.Fprintf(os.Stderr, "unable to create zipkin tracer: %s\n", err.Error())
os.Exit(1)
}
}
}
// This is a demonstration client, which supports multiple tracers.
// Your clients will probably just use one tracer.
var otTracer stdopentracing.Tracer
{
if *zipkinBridge && zipkinTracer != nil {
otTracer = zipkinot.Wrap(zipkinTracer)
zipkinTracer = nil // do not instrument with both native and ot bridge
} else if *lightstepToken != "" {
otTracer = lightstep.NewTracer(lightstep.Options{
AccessToken: *lightstepToken,
})
defer lightstep.FlushLightStepTracer(otTracer)
} else if *appdashAddr != "" {
otTracer = appdashot.NewTracer(appdash.NewRemoteCollector(*appdashAddr))
} else {
otTracer = stdopentracing.GlobalTracer() // no-op
}
}
// This is a demonstration client, which supports multiple transports.
// Your clients will probably just define and stick with 1 transport.
var (
svc addservice.Service
err error
)
if *httpAddr != "" {
svc, err = addtransport.NewHTTPClient(*httpAddr, otTracer, zipkinTracer, log.NewNopLogger())
} else if *grpcAddr != "" {
conn, err := grpc.Dial(*grpcAddr, grpc.WithInsecure(), grpc.WithTimeout(time.Second))
if err != nil {
fmt.Fprintf(os.Stderr, "error: %v", err)
os.Exit(1)
}
defer conn.Close()
svc = addtransport.NewGRPCClient(conn, otTracer, zipkinTracer, log.NewNopLogger())
} else if *jsonRPCAddr != "" {
svc, err = addtransport.NewJSONRPCClient(*jsonRPCAddr, otTracer, log.NewNopLogger())
} else if *thriftAddr != "" {
// It's necessary to do all of this construction in the func main,
// because (among other reasons) we need to control the lifecycle of the
// Thrift transport, i.e. close it eventually.
var protocolFactory thrift.TProtocolFactory
switch *thriftProtocol {
case "compact":
protocolFactory = thrift.NewTCompactProtocolFactory()
case "simplejson":
protocolFactory = thrift.NewTSimpleJSONProtocolFactory()
case "json":
protocolFactory = thrift.NewTJSONProtocolFactory()
case "binary", "":
protocolFactory = thrift.NewTBinaryProtocolFactoryDefault()
default:
fmt.Fprintf(os.Stderr, "error: invalid protocol %q\n", *thriftProtocol)
os.Exit(1)
}
var transportFactory thrift.TTransportFactory
if *thriftBuffer > 0 {
transportFactory = thrift.NewTBufferedTransportFactory(*thriftBuffer)
} else {
transportFactory = thrift.NewTTransportFactory()
}
if *thriftFramed {
transportFactory = thrift.NewTFramedTransportFactory(transportFactory)
}
transportSocket, err := thrift.NewTSocket(*thriftAddr)
if err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
transport, err := transportFactory.GetTransport(transportSocket)
if err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
if err := transport.Open(); err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
defer transport.Close()
client := addthrift.NewAddServiceClientFactory(transport, protocolFactory)
svc = addtransport.NewThriftClient(client)
} else {
fmt.Fprintf(os.Stderr, "error: no remote address specified\n")
os.Exit(1)
}
if err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
switch *method {
case "sum":
a, _ := strconv.ParseInt(fs.Args()[0], 10, 64)
b, _ := strconv.ParseInt(fs.Args()[1], 10, 64)
v, err := svc.Sum(context.Background(), int(a), int(b))
if err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
fmt.Fprintf(os.Stdout, "%d + %d = %d\n", a, b, v)
case "concat":
a := fs.Args()[0]
b := fs.Args()[1]
v, err := svc.Concat(context.Background(), a, b)
if err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
fmt.Fprintf(os.Stdout, "%q + %q = %q\n", a, b, v)
default:
fmt.Fprintf(os.Stderr, "error: invalid method %q\n", *method)
os.Exit(1)
}
}
func usageFor(fs *flag.FlagSet, short string) func() {
return func() {
fmt.Fprintf(os.Stderr, "USAGE\n")
fmt.Fprintf(os.Stderr, " %s\n", short)
fmt.Fprintf(os.Stderr, "\n")
fmt.Fprintf(os.Stderr, "FLAGS\n")
w := tabwriter.NewWriter(os.Stderr, 0, 2, 2, ' ', 0)
fs.VisitAll(func(f *flag.Flag) {
fmt.Fprintf(w, "\t-%s %s\t%s\n", f.Name, f.DefValue, f.Usage)
})
w.Flush()
fmt.Fprintf(os.Stderr, "\n")
}
}
golang-github-go-kit-kit-0.10.0/examples/addsvc/cmd/addsvc/ 0000775 0000000 0000000 00000000000 13622563124 0023371 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/addsvc/cmd/addsvc/addsvc.go 0000664 0000000 0000000 00000025756 13622563124 0025203 0 ustar 00root root 0000000 0000000 package main
import (
"flag"
"fmt"
"net"
"net/http"
"os"
"os/signal"
"syscall"
"text/tabwriter"
"github.com/apache/thrift/lib/go/thrift"
lightstep "github.com/lightstep/lightstep-tracer-go"
"github.com/oklog/oklog/pkg/group"
stdopentracing "github.com/opentracing/opentracing-go"
zipkinot "github.com/openzipkin-contrib/zipkin-go-opentracing"
zipkin "github.com/openzipkin/zipkin-go"
zipkinhttp "github.com/openzipkin/zipkin-go/reporter/http"
stdprometheus "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"google.golang.org/grpc"
"sourcegraph.com/sourcegraph/appdash"
appdashot "sourcegraph.com/sourcegraph/appdash/opentracing"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/metrics"
"github.com/go-kit/kit/metrics/prometheus"
kitgrpc "github.com/go-kit/kit/transport/grpc"
addpb "github.com/go-kit/kit/examples/addsvc/pb"
"github.com/go-kit/kit/examples/addsvc/pkg/addendpoint"
"github.com/go-kit/kit/examples/addsvc/pkg/addservice"
"github.com/go-kit/kit/examples/addsvc/pkg/addtransport"
addthrift "github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc"
)
func main() {
// Define our flags. Your service probably won't need to bind listeners for
// *all* supported transports, or support both Zipkin and LightStep, and so
// on, but we do it here for demonstration purposes.
fs := flag.NewFlagSet("addsvc", flag.ExitOnError)
var (
debugAddr = fs.String("debug.addr", ":8080", "Debug and metrics listen address")
httpAddr = fs.String("http-addr", ":8081", "HTTP listen address")
grpcAddr = fs.String("grpc-addr", ":8082", "gRPC listen address")
thriftAddr = fs.String("thrift-addr", ":8083", "Thrift listen address")
jsonRPCAddr = fs.String("jsonrpc-addr", ":8084", "JSON RPC listen address")
thriftProtocol = fs.String("thrift-protocol", "binary", "binary, compact, json, simplejson")
thriftBuffer = fs.Int("thrift-buffer", 0, "0 for unbuffered")
thriftFramed = fs.Bool("thrift-framed", false, "true to enable framing")
zipkinURL = fs.String("zipkin-url", "", "Enable Zipkin tracing via HTTP reporter URL e.g. http://localhost:9411/api/v2/spans")
zipkinBridge = fs.Bool("zipkin-ot-bridge", false, "Use Zipkin OpenTracing bridge instead of native implementation")
lightstepToken = fs.String("lightstep-token", "", "Enable LightStep tracing via a LightStep access token")
appdashAddr = fs.String("appdash-addr", "", "Enable Appdash tracing via an Appdash server host:port")
)
fs.Usage = usageFor(fs, os.Args[0]+" [flags]")
fs.Parse(os.Args[1:])
// Create a single logger, which we'll use and give to other components.
var logger log.Logger
{
logger = log.NewLogfmtLogger(os.Stderr)
logger = log.With(logger, "ts", log.DefaultTimestampUTC)
logger = log.With(logger, "caller", log.DefaultCaller)
}
var zipkinTracer *zipkin.Tracer
{
if *zipkinURL != "" {
var (
err error
hostPort = "localhost:80"
serviceName = "addsvc"
reporter = zipkinhttp.NewReporter(*zipkinURL)
)
defer reporter.Close()
zEP, _ := zipkin.NewEndpoint(serviceName, hostPort)
zipkinTracer, err = zipkin.NewTracer(reporter, zipkin.WithLocalEndpoint(zEP))
if err != nil {
logger.Log("err", err)
os.Exit(1)
}
if !(*zipkinBridge) {
logger.Log("tracer", "Zipkin", "type", "Native", "URL", *zipkinURL)
}
}
}
// Determine which OpenTracing tracer to use. We'll pass the tracer to all the
// components that use it, as a dependency.
var tracer stdopentracing.Tracer
{
if *zipkinBridge && zipkinTracer != nil {
logger.Log("tracer", "Zipkin", "type", "OpenTracing", "URL", *zipkinURL)
tracer = zipkinot.Wrap(zipkinTracer)
zipkinTracer = nil // do not instrument with both native tracer and opentracing bridge
} else if *lightstepToken != "" {
logger.Log("tracer", "LightStep") // probably don't want to print out the token :)
tracer = lightstep.NewTracer(lightstep.Options{
AccessToken: *lightstepToken,
})
defer lightstep.FlushLightStepTracer(tracer)
} else if *appdashAddr != "" {
logger.Log("tracer", "Appdash", "addr", *appdashAddr)
tracer = appdashot.NewTracer(appdash.NewRemoteCollector(*appdashAddr))
} else {
tracer = stdopentracing.GlobalTracer() // no-op
}
}
// Create the (sparse) metrics we'll use in the service. They, too, are
// dependencies that we pass to components that use them.
var ints, chars metrics.Counter
{
// Business-level metrics.
ints = prometheus.NewCounterFrom(stdprometheus.CounterOpts{
Namespace: "example",
Subsystem: "addsvc",
Name: "integers_summed",
Help: "Total count of integers summed via the Sum method.",
}, []string{})
chars = prometheus.NewCounterFrom(stdprometheus.CounterOpts{
Namespace: "example",
Subsystem: "addsvc",
Name: "characters_concatenated",
Help: "Total count of characters concatenated via the Concat method.",
}, []string{})
}
var duration metrics.Histogram
{
// Endpoint-level metrics.
duration = prometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
Namespace: "example",
Subsystem: "addsvc",
Name: "request_duration_seconds",
Help: "Request duration in seconds.",
}, []string{"method", "success"})
}
http.DefaultServeMux.Handle("/metrics", promhttp.Handler())
// Build the layers of the service "onion" from the inside out. First, the
// business logic service; then, the set of endpoints that wrap the service;
// and finally, a series of concrete transport adapters. The adapters, like
// the HTTP handler or the gRPC server, are the bridge between Go kit and
// the interfaces that the transports expect. Note that we're not binding
// them to ports or anything yet; we'll do that next.
var (
service = addservice.New(logger, ints, chars)
endpoints = addendpoint.New(service, logger, duration, tracer, zipkinTracer)
httpHandler = addtransport.NewHTTPHandler(endpoints, tracer, zipkinTracer, logger)
grpcServer = addtransport.NewGRPCServer(endpoints, tracer, zipkinTracer, logger)
thriftServer = addtransport.NewThriftServer(endpoints)
jsonrpcHandler = addtransport.NewJSONRPCHandler(endpoints, logger)
)
// Now we're to the part of the func main where we want to start actually
// running things, like servers bound to listeners to receive connections.
//
// The method is the same for each component: add a new actor to the group
// struct, which is a combination of 2 anonymous functions: the first
// function actually runs the component, and the second function should
// interrupt the first function and cause it to return. It's in these
// functions that we actually bind the Go kit server/handler structs to the
// concrete transports and run them.
//
// Putting each component into its own block is mostly for aesthetics: it
// clearly demarcates the scope in which each listener/socket may be used.
var g group.Group
{
// The debug listener mounts the http.DefaultServeMux, and serves up
// stuff like the Prometheus metrics route, the Go debug and profiling
// routes, and so on.
debugListener, err := net.Listen("tcp", *debugAddr)
if err != nil {
logger.Log("transport", "debug/HTTP", "during", "Listen", "err", err)
os.Exit(1)
}
g.Add(func() error {
logger.Log("transport", "debug/HTTP", "addr", *debugAddr)
return http.Serve(debugListener, http.DefaultServeMux)
}, func(error) {
debugListener.Close()
})
}
{
// The HTTP listener mounts the Go kit HTTP handler we created.
httpListener, err := net.Listen("tcp", *httpAddr)
if err != nil {
logger.Log("transport", "HTTP", "during", "Listen", "err", err)
os.Exit(1)
}
g.Add(func() error {
logger.Log("transport", "HTTP", "addr", *httpAddr)
return http.Serve(httpListener, httpHandler)
}, func(error) {
httpListener.Close()
})
}
{
// The gRPC listener mounts the Go kit gRPC server we created.
grpcListener, err := net.Listen("tcp", *grpcAddr)
if err != nil {
logger.Log("transport", "gRPC", "during", "Listen", "err", err)
os.Exit(1)
}
g.Add(func() error {
logger.Log("transport", "gRPC", "addr", *grpcAddr)
// we add the Go Kit gRPC Interceptor to our gRPC service as it is used by
// the here demonstrated zipkin tracing middleware.
baseServer := grpc.NewServer(grpc.UnaryInterceptor(kitgrpc.Interceptor))
addpb.RegisterAddServer(baseServer, grpcServer)
return baseServer.Serve(grpcListener)
}, func(error) {
grpcListener.Close()
})
}
{
// The Thrift socket mounts the Go kit Thrift server we created earlier.
// There's a lot of boilerplate involved here, related to configuring
// the protocol and transport; blame Thrift.
thriftSocket, err := thrift.NewTServerSocket(*thriftAddr)
if err != nil {
logger.Log("transport", "Thrift", "during", "Listen", "err", err)
os.Exit(1)
}
g.Add(func() error {
logger.Log("transport", "Thrift", "addr", *thriftAddr)
var protocolFactory thrift.TProtocolFactory
switch *thriftProtocol {
case "binary":
protocolFactory = thrift.NewTBinaryProtocolFactoryDefault()
case "compact":
protocolFactory = thrift.NewTCompactProtocolFactory()
case "json":
protocolFactory = thrift.NewTJSONProtocolFactory()
case "simplejson":
protocolFactory = thrift.NewTSimpleJSONProtocolFactory()
default:
return fmt.Errorf("invalid Thrift protocol %q", *thriftProtocol)
}
var transportFactory thrift.TTransportFactory
if *thriftBuffer > 0 {
transportFactory = thrift.NewTBufferedTransportFactory(*thriftBuffer)
} else {
transportFactory = thrift.NewTTransportFactory()
}
if *thriftFramed {
transportFactory = thrift.NewTFramedTransportFactory(transportFactory)
}
return thrift.NewTSimpleServer4(
addthrift.NewAddServiceProcessor(thriftServer),
thriftSocket,
transportFactory,
protocolFactory,
).Serve()
}, func(error) {
thriftSocket.Close()
})
}
{
httpListener, err := net.Listen("tcp", *jsonRPCAddr)
if err != nil {
logger.Log("transport", "JSONRPC over HTTP", "during", "Listen", "err", err)
os.Exit(1)
}
g.Add(func() error {
logger.Log("transport", "JSONRPC over HTTP", "addr", *jsonRPCAddr)
return http.Serve(httpListener, jsonrpcHandler)
}, func(error) {
httpListener.Close()
})
}
{
// This function just sits and waits for ctrl-C.
cancelInterrupt := make(chan struct{})
g.Add(func() error {
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
select {
case sig := <-c:
return fmt.Errorf("received signal %s", sig)
case <-cancelInterrupt:
return nil
}
}, func(error) {
close(cancelInterrupt)
})
}
logger.Log("exit", g.Run())
}
func usageFor(fs *flag.FlagSet, short string) func() {
return func() {
fmt.Fprintf(os.Stderr, "USAGE\n")
fmt.Fprintf(os.Stderr, " %s\n", short)
fmt.Fprintf(os.Stderr, "\n")
fmt.Fprintf(os.Stderr, "FLAGS\n")
w := tabwriter.NewWriter(os.Stderr, 0, 2, 2, ' ', 0)
fs.VisitAll(func(f *flag.Flag) {
fmt.Fprintf(w, "\t-%s %s\t%s\n", f.Name, f.DefValue, f.Usage)
})
w.Flush()
fmt.Fprintf(os.Stderr, "\n")
}
}
golang-github-go-kit-kit-0.10.0/examples/addsvc/cmd/addsvc/pact_test.go 0000664 0000000 0000000 00000002352 13622563124 0025710 0 ustar 00root root 0000000 0000000 package main
import (
"fmt"
"net/http"
"os"
"strings"
"testing"
"github.com/pact-foundation/pact-go/dsl"
)
func TestPactStringsvcUppercase(t *testing.T) {
if os.Getenv("WRITE_PACTS") == "" {
t.Skip("skipping Pact contracts; set WRITE_PACTS environment variable to enable")
}
pact := dsl.Pact{
Consumer: "addsvc",
Provider: "stringsvc",
}
defer pact.Teardown()
pact.AddInteraction().
UponReceiving("stringsvc uppercase").
WithRequest(dsl.Request{
Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/json; charset=utf-8")},
Method: "POST",
Path: dsl.String("/uppercase"),
Body: `{"s":"foo"}`,
}).
WillRespondWith(dsl.Response{
Status: 200,
Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/json; charset=utf-8")},
Body: `{"v":"FOO"}`,
})
if err := pact.Verify(func() error {
u := fmt.Sprintf("http://localhost:%d/uppercase", pact.Server.Port)
req, err := http.NewRequest("POST", u, strings.NewReader(`{"s":"foo"}`))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
if _, err = http.DefaultClient.Do(req); err != nil {
return err
}
return nil
}); err != nil {
t.Fatal(err)
}
pact.WritePact()
}
golang-github-go-kit-kit-0.10.0/examples/addsvc/cmd/addsvc/wiring_test.go 0000664 0000000 0000000 00000002612 13622563124 0026257 0 ustar 00root root 0000000 0000000 package main
import (
"io/ioutil"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/opentracing/opentracing-go"
zipkin "github.com/openzipkin/zipkin-go"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/metrics/discard"
"github.com/go-kit/kit/examples/addsvc/pkg/addendpoint"
"github.com/go-kit/kit/examples/addsvc/pkg/addservice"
"github.com/go-kit/kit/examples/addsvc/pkg/addtransport"
)
func TestHTTP(t *testing.T) {
zkt, _ := zipkin.NewTracer(nil, zipkin.WithNoopTracer(true))
svc := addservice.New(log.NewNopLogger(), discard.NewCounter(), discard.NewCounter())
eps := addendpoint.New(svc, log.NewNopLogger(), discard.NewHistogram(), opentracing.GlobalTracer(), zkt)
mux := addtransport.NewHTTPHandler(eps, opentracing.GlobalTracer(), zkt, log.NewNopLogger())
srv := httptest.NewServer(mux)
defer srv.Close()
for _, testcase := range []struct {
method, url, body, want string
}{
{"GET", srv.URL + "/concat", `{"a":"1","b":"2"}`, `{"v":"12"}`},
{"GET", srv.URL + "/sum", `{"a":1,"b":2}`, `{"v":3}`},
} {
req, _ := http.NewRequest(testcase.method, testcase.url, strings.NewReader(testcase.body))
resp, _ := http.DefaultClient.Do(req)
body, _ := ioutil.ReadAll(resp.Body)
if want, have := testcase.want, strings.TrimSpace(string(body)); want != have {
t.Errorf("%s %s %s: want %q, have %q", testcase.method, testcase.url, testcase.body, want, have)
}
}
}
golang-github-go-kit-kit-0.10.0/examples/addsvc/pb/ 0000775 0000000 0000000 00000000000 13622563124 0021763 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/addsvc/pb/addsvc.pb.go 0000664 0000000 0000000 00000025576 13622563124 0024175 0 ustar 00root root 0000000 0000000 // Code generated by protoc-gen-go. DO NOT EDIT.
// source: addsvc.proto
package pb
import (
context "context"
fmt "fmt"
proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
// The sum request contains two parameters.
type SumRequest struct {
A int64 `protobuf:"varint,1,opt,name=a,proto3" json:"a,omitempty"`
B int64 `protobuf:"varint,2,opt,name=b,proto3" json:"b,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *SumRequest) Reset() { *m = SumRequest{} }
func (m *SumRequest) String() string { return proto.CompactTextString(m) }
func (*SumRequest) ProtoMessage() {}
func (*SumRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_174367f558d60c26, []int{0}
}
func (m *SumRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SumRequest.Unmarshal(m, b)
}
func (m *SumRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_SumRequest.Marshal(b, m, deterministic)
}
func (m *SumRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_SumRequest.Merge(m, src)
}
func (m *SumRequest) XXX_Size() int {
return xxx_messageInfo_SumRequest.Size(m)
}
func (m *SumRequest) XXX_DiscardUnknown() {
xxx_messageInfo_SumRequest.DiscardUnknown(m)
}
var xxx_messageInfo_SumRequest proto.InternalMessageInfo
func (m *SumRequest) GetA() int64 {
if m != nil {
return m.A
}
return 0
}
func (m *SumRequest) GetB() int64 {
if m != nil {
return m.B
}
return 0
}
// The sum response contains the result of the calculation.
type SumReply struct {
V int64 `protobuf:"varint,1,opt,name=v,proto3" json:"v,omitempty"`
Err string `protobuf:"bytes,2,opt,name=err,proto3" json:"err,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *SumReply) Reset() { *m = SumReply{} }
func (m *SumReply) String() string { return proto.CompactTextString(m) }
func (*SumReply) ProtoMessage() {}
func (*SumReply) Descriptor() ([]byte, []int) {
return fileDescriptor_174367f558d60c26, []int{1}
}
func (m *SumReply) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SumReply.Unmarshal(m, b)
}
func (m *SumReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_SumReply.Marshal(b, m, deterministic)
}
func (m *SumReply) XXX_Merge(src proto.Message) {
xxx_messageInfo_SumReply.Merge(m, src)
}
func (m *SumReply) XXX_Size() int {
return xxx_messageInfo_SumReply.Size(m)
}
func (m *SumReply) XXX_DiscardUnknown() {
xxx_messageInfo_SumReply.DiscardUnknown(m)
}
var xxx_messageInfo_SumReply proto.InternalMessageInfo
func (m *SumReply) GetV() int64 {
if m != nil {
return m.V
}
return 0
}
func (m *SumReply) GetErr() string {
if m != nil {
return m.Err
}
return ""
}
// The Concat request contains two parameters.
type ConcatRequest struct {
A string `protobuf:"bytes,1,opt,name=a,proto3" json:"a,omitempty"`
B string `protobuf:"bytes,2,opt,name=b,proto3" json:"b,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ConcatRequest) Reset() { *m = ConcatRequest{} }
func (m *ConcatRequest) String() string { return proto.CompactTextString(m) }
func (*ConcatRequest) ProtoMessage() {}
func (*ConcatRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_174367f558d60c26, []int{2}
}
func (m *ConcatRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ConcatRequest.Unmarshal(m, b)
}
func (m *ConcatRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ConcatRequest.Marshal(b, m, deterministic)
}
func (m *ConcatRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_ConcatRequest.Merge(m, src)
}
func (m *ConcatRequest) XXX_Size() int {
return xxx_messageInfo_ConcatRequest.Size(m)
}
func (m *ConcatRequest) XXX_DiscardUnknown() {
xxx_messageInfo_ConcatRequest.DiscardUnknown(m)
}
var xxx_messageInfo_ConcatRequest proto.InternalMessageInfo
func (m *ConcatRequest) GetA() string {
if m != nil {
return m.A
}
return ""
}
func (m *ConcatRequest) GetB() string {
if m != nil {
return m.B
}
return ""
}
// The Concat response contains the result of the concatenation.
type ConcatReply struct {
V string `protobuf:"bytes,1,opt,name=v,proto3" json:"v,omitempty"`
Err string `protobuf:"bytes,2,opt,name=err,proto3" json:"err,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ConcatReply) Reset() { *m = ConcatReply{} }
func (m *ConcatReply) String() string { return proto.CompactTextString(m) }
func (*ConcatReply) ProtoMessage() {}
func (*ConcatReply) Descriptor() ([]byte, []int) {
return fileDescriptor_174367f558d60c26, []int{3}
}
func (m *ConcatReply) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ConcatReply.Unmarshal(m, b)
}
func (m *ConcatReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ConcatReply.Marshal(b, m, deterministic)
}
func (m *ConcatReply) XXX_Merge(src proto.Message) {
xxx_messageInfo_ConcatReply.Merge(m, src)
}
func (m *ConcatReply) XXX_Size() int {
return xxx_messageInfo_ConcatReply.Size(m)
}
func (m *ConcatReply) XXX_DiscardUnknown() {
xxx_messageInfo_ConcatReply.DiscardUnknown(m)
}
var xxx_messageInfo_ConcatReply proto.InternalMessageInfo
func (m *ConcatReply) GetV() string {
if m != nil {
return m.V
}
return ""
}
func (m *ConcatReply) GetErr() string {
if m != nil {
return m.Err
}
return ""
}
func init() {
proto.RegisterType((*SumRequest)(nil), "pb.SumRequest")
proto.RegisterType((*SumReply)(nil), "pb.SumReply")
proto.RegisterType((*ConcatRequest)(nil), "pb.ConcatRequest")
proto.RegisterType((*ConcatReply)(nil), "pb.ConcatReply")
}
func init() { proto.RegisterFile("addsvc.proto", fileDescriptor_174367f558d60c26) }
var fileDescriptor_174367f558d60c26 = []byte{
// 189 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x49, 0x4c, 0x49, 0x29,
0x2e, 0x4b, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2a, 0x48, 0x52, 0xd2, 0xe0, 0xe2,
0x0a, 0x2e, 0xcd, 0x0d, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x11, 0xe2, 0xe1, 0x62, 0x4c, 0x94,
0x60, 0x54, 0x60, 0xd4, 0x60, 0x0e, 0x62, 0x4c, 0x04, 0xf1, 0x92, 0x24, 0x98, 0x20, 0xbc, 0x24,
0x25, 0x2d, 0x2e, 0x0e, 0xb0, 0xca, 0x82, 0x9c, 0x4a, 0x90, 0x4c, 0x19, 0x4c, 0x5d, 0x99, 0x90,
0x00, 0x17, 0x73, 0x6a, 0x51, 0x11, 0x58, 0x25, 0x67, 0x10, 0x88, 0xa9, 0xa4, 0xcd, 0xc5, 0xeb,
0x9c, 0x9f, 0x97, 0x9c, 0x58, 0x82, 0x61, 0x30, 0x27, 0x8a, 0xc1, 0x9c, 0x20, 0x83, 0x75, 0xb9,
0xb8, 0x61, 0x8a, 0x51, 0xcc, 0xe6, 0xc4, 0x6a, 0xb6, 0x51, 0x0c, 0x17, 0xb3, 0x63, 0x4a, 0x8a,
0x90, 0x2a, 0x17, 0x73, 0x70, 0x69, 0xae, 0x10, 0x9f, 0x5e, 0x41, 0x92, 0x1e, 0xc2, 0x07, 0x52,
0x3c, 0x70, 0x7e, 0x41, 0x4e, 0xa5, 0x12, 0x83, 0x90, 0x1e, 0x17, 0x1b, 0xc4, 0x70, 0x21, 0x41,
0x90, 0x0c, 0x8a, 0xab, 0xa4, 0xf8, 0x91, 0x85, 0xc0, 0xea, 0x93, 0xd8, 0xc0, 0x41, 0x63, 0x0c,
0x08, 0x00, 0x00, 0xff, 0xff, 0xdc, 0x37, 0x81, 0x99, 0x2a, 0x01, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// AddClient is the client API for Add service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type AddClient interface {
// Sums two integers.
Sum(ctx context.Context, in *SumRequest, opts ...grpc.CallOption) (*SumReply, error)
// Concatenates two strings
Concat(ctx context.Context, in *ConcatRequest, opts ...grpc.CallOption) (*ConcatReply, error)
}
type addClient struct {
cc *grpc.ClientConn
}
func NewAddClient(cc *grpc.ClientConn) AddClient {
return &addClient{cc}
}
func (c *addClient) Sum(ctx context.Context, in *SumRequest, opts ...grpc.CallOption) (*SumReply, error) {
out := new(SumReply)
err := c.cc.Invoke(ctx, "/pb.Add/Sum", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *addClient) Concat(ctx context.Context, in *ConcatRequest, opts ...grpc.CallOption) (*ConcatReply, error) {
out := new(ConcatReply)
err := c.cc.Invoke(ctx, "/pb.Add/Concat", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// AddServer is the server API for Add service.
type AddServer interface {
// Sums two integers.
Sum(context.Context, *SumRequest) (*SumReply, error)
// Concatenates two strings
Concat(context.Context, *ConcatRequest) (*ConcatReply, error)
}
func RegisterAddServer(s *grpc.Server, srv AddServer) {
s.RegisterService(&_Add_serviceDesc, srv)
}
func _Add_Sum_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SumRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AddServer).Sum(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/pb.Add/Sum",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AddServer).Sum(ctx, req.(*SumRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Add_Concat_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ConcatRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AddServer).Concat(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/pb.Add/Concat",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AddServer).Concat(ctx, req.(*ConcatRequest))
}
return interceptor(ctx, in, info, handler)
}
var _Add_serviceDesc = grpc.ServiceDesc{
ServiceName: "pb.Add",
HandlerType: (*AddServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Sum",
Handler: _Add_Sum_Handler,
},
{
MethodName: "Concat",
Handler: _Add_Concat_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "addsvc.proto",
}
golang-github-go-kit-kit-0.10.0/examples/addsvc/pb/addsvc.proto 0000664 0000000 0000000 00000001245 13622563124 0024316 0 ustar 00root root 0000000 0000000 syntax = "proto3";
package pb;
// The Add service definition.
service Add {
// Sums two integers.
rpc Sum (SumRequest) returns (SumReply) {}
// Concatenates two strings
rpc Concat (ConcatRequest) returns (ConcatReply) {}
}
// The sum request contains two parameters.
message SumRequest {
int64 a = 1;
int64 b = 2;
}
// The sum response contains the result of the calculation.
message SumReply {
int64 v = 1;
string err = 2;
}
// The Concat request contains two parameters.
message ConcatRequest {
string a = 1;
string b = 2;
}
// The Concat response contains the result of the concatenation.
message ConcatReply {
string v = 1;
string err = 2;
}
golang-github-go-kit-kit-0.10.0/examples/addsvc/pb/compile.sh 0000775 0000000 0000000 00000000620 13622563124 0023750 0 ustar 00root root 0000000 0000000 #!/usr/bin/env sh
# Install proto3 from source
# brew install autoconf automake libtool
# git clone https://github.com/google/protobuf
# ./autogen.sh ; ./configure ; make ; make install
#
# Update protoc Go bindings via
# go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
#
# See also
# https://github.com/grpc/grpc-go/tree/master/examples
protoc addsvc.proto --go_out=plugins=grpc:.
golang-github-go-kit-kit-0.10.0/examples/addsvc/pkg/ 0000775 0000000 0000000 00000000000 13622563124 0022143 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/addsvc/pkg/addendpoint/ 0000775 0000000 0000000 00000000000 13622563124 0024434 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/addsvc/pkg/addendpoint/middleware.go 0000664 0000000 0000000 00000002441 13622563124 0027101 0 ustar 00root root 0000000 0000000 package addendpoint
import (
"context"
"fmt"
"time"
"github.com/go-kit/kit/endpoint"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/metrics"
)
// InstrumentingMiddleware returns an endpoint middleware that records
// the duration of each invocation to the passed histogram. The middleware adds
// a single field: "success", which is "true" if no error is returned, and
// "false" otherwise.
func InstrumentingMiddleware(duration metrics.Histogram) endpoint.Middleware {
return func(next endpoint.Endpoint) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
defer func(begin time.Time) {
duration.With("success", fmt.Sprint(err == nil)).Observe(time.Since(begin).Seconds())
}(time.Now())
return next(ctx, request)
}
}
}
// LoggingMiddleware returns an endpoint middleware that logs the
// duration of each invocation, and the resulting error, if any.
func LoggingMiddleware(logger log.Logger) endpoint.Middleware {
return func(next endpoint.Endpoint) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
defer func(begin time.Time) {
logger.Log("transport_error", err, "took", time.Since(begin))
}(time.Now())
return next(ctx, request)
}
}
}
golang-github-go-kit-kit-0.10.0/examples/addsvc/pkg/addendpoint/set.go 0000664 0000000 0000000 00000011711 13622563124 0025557 0 ustar 00root root 0000000 0000000 package addendpoint
import (
"context"
"time"
"golang.org/x/time/rate"
stdopentracing "github.com/opentracing/opentracing-go"
stdzipkin "github.com/openzipkin/zipkin-go"
"github.com/sony/gobreaker"
"github.com/go-kit/kit/circuitbreaker"
"github.com/go-kit/kit/endpoint"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/metrics"
"github.com/go-kit/kit/ratelimit"
"github.com/go-kit/kit/tracing/opentracing"
"github.com/go-kit/kit/tracing/zipkin"
"github.com/go-kit/kit/examples/addsvc/pkg/addservice"
)
// Set collects all of the endpoints that compose an add service. It's meant to
// be used as a helper struct, to collect all of the endpoints into a single
// parameter.
type Set struct {
SumEndpoint endpoint.Endpoint
ConcatEndpoint endpoint.Endpoint
}
// New returns a Set that wraps the provided server, and wires in all of the
// expected endpoint middlewares via the various parameters.
func New(svc addservice.Service, logger log.Logger, duration metrics.Histogram, otTracer stdopentracing.Tracer, zipkinTracer *stdzipkin.Tracer) Set {
var sumEndpoint endpoint.Endpoint
{
sumEndpoint = MakeSumEndpoint(svc)
// Sum is limited to 1 request per second with burst of 1 request.
// Note, rate is defined as a time interval between requests.
sumEndpoint = ratelimit.NewErroringLimiter(rate.NewLimiter(rate.Every(time.Second), 1))(sumEndpoint)
sumEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{}))(sumEndpoint)
sumEndpoint = opentracing.TraceServer(otTracer, "Sum")(sumEndpoint)
if zipkinTracer != nil {
sumEndpoint = zipkin.TraceEndpoint(zipkinTracer, "Sum")(sumEndpoint)
}
sumEndpoint = LoggingMiddleware(log.With(logger, "method", "Sum"))(sumEndpoint)
sumEndpoint = InstrumentingMiddleware(duration.With("method", "Sum"))(sumEndpoint)
}
var concatEndpoint endpoint.Endpoint
{
concatEndpoint = MakeConcatEndpoint(svc)
// Concat is limited to 1 request per second with burst of 100 requests.
// Note, rate is defined as a number of requests per second.
concatEndpoint = ratelimit.NewErroringLimiter(rate.NewLimiter(rate.Limit(1), 100))(concatEndpoint)
concatEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{}))(concatEndpoint)
concatEndpoint = opentracing.TraceServer(otTracer, "Concat")(concatEndpoint)
if zipkinTracer != nil {
concatEndpoint = zipkin.TraceEndpoint(zipkinTracer, "Concat")(concatEndpoint)
}
concatEndpoint = LoggingMiddleware(log.With(logger, "method", "Concat"))(concatEndpoint)
concatEndpoint = InstrumentingMiddleware(duration.With("method", "Concat"))(concatEndpoint)
}
return Set{
SumEndpoint: sumEndpoint,
ConcatEndpoint: concatEndpoint,
}
}
// Sum implements the service interface, so Set may be used as a service.
// This is primarily useful in the context of a client library.
func (s Set) Sum(ctx context.Context, a, b int) (int, error) {
resp, err := s.SumEndpoint(ctx, SumRequest{A: a, B: b})
if err != nil {
return 0, err
}
response := resp.(SumResponse)
return response.V, response.Err
}
// Concat implements the service interface, so Set may be used as a
// service. This is primarily useful in the context of a client library.
func (s Set) Concat(ctx context.Context, a, b string) (string, error) {
resp, err := s.ConcatEndpoint(ctx, ConcatRequest{A: a, B: b})
if err != nil {
return "", err
}
response := resp.(ConcatResponse)
return response.V, response.Err
}
// MakeSumEndpoint constructs a Sum endpoint wrapping the service.
func MakeSumEndpoint(s addservice.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
req := request.(SumRequest)
v, err := s.Sum(ctx, req.A, req.B)
return SumResponse{V: v, Err: err}, nil
}
}
// MakeConcatEndpoint constructs a Concat endpoint wrapping the service.
func MakeConcatEndpoint(s addservice.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
req := request.(ConcatRequest)
v, err := s.Concat(ctx, req.A, req.B)
return ConcatResponse{V: v, Err: err}, nil
}
}
// compile time assertions for our response types implementing endpoint.Failer.
var (
_ endpoint.Failer = SumResponse{}
_ endpoint.Failer = ConcatResponse{}
)
// SumRequest collects the request parameters for the Sum method.
type SumRequest struct {
A, B int
}
// SumResponse collects the response values for the Sum method.
type SumResponse struct {
V int `json:"v"`
Err error `json:"-"` // should be intercepted by Failed/errorEncoder
}
// Failed implements endpoint.Failer.
func (r SumResponse) Failed() error { return r.Err }
// ConcatRequest collects the request parameters for the Concat method.
type ConcatRequest struct {
A, B string
}
// ConcatResponse collects the response values for the Concat method.
type ConcatResponse struct {
V string `json:"v"`
Err error `json:"-"`
}
// Failed implements endpoint.Failer.
func (r ConcatResponse) Failed() error { return r.Err }
golang-github-go-kit-kit-0.10.0/examples/addsvc/pkg/addservice/ 0000775 0000000 0000000 00000000000 13622563124 0024254 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/addsvc/pkg/addservice/middleware.go 0000664 0000000 0000000 00000003336 13622563124 0026725 0 ustar 00root root 0000000 0000000 package addservice
import (
"context"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/metrics"
)
// Middleware describes a service (as opposed to endpoint) middleware.
type Middleware func(Service) Service
// LoggingMiddleware takes a logger as a dependency
// and returns a service Middleware.
func LoggingMiddleware(logger log.Logger) Middleware {
return func(next Service) Service {
return loggingMiddleware{logger, next}
}
}
type loggingMiddleware struct {
logger log.Logger
next Service
}
func (mw loggingMiddleware) Sum(ctx context.Context, a, b int) (v int, err error) {
defer func() {
mw.logger.Log("method", "Sum", "a", a, "b", b, "v", v, "err", err)
}()
return mw.next.Sum(ctx, a, b)
}
func (mw loggingMiddleware) Concat(ctx context.Context, a, b string) (v string, err error) {
defer func() {
mw.logger.Log("method", "Concat", "a", a, "b", b, "v", v, "err", err)
}()
return mw.next.Concat(ctx, a, b)
}
// InstrumentingMiddleware returns a service middleware that instruments
// the number of integers summed and characters concatenated over the lifetime of
// the service.
func InstrumentingMiddleware(ints, chars metrics.Counter) Middleware {
return func(next Service) Service {
return instrumentingMiddleware{
ints: ints,
chars: chars,
next: next,
}
}
}
type instrumentingMiddleware struct {
ints metrics.Counter
chars metrics.Counter
next Service
}
func (mw instrumentingMiddleware) Sum(ctx context.Context, a, b int) (int, error) {
v, err := mw.next.Sum(ctx, a, b)
mw.ints.Add(float64(v))
return v, err
}
func (mw instrumentingMiddleware) Concat(ctx context.Context, a, b string) (string, error) {
v, err := mw.next.Concat(ctx, a, b)
mw.chars.Add(float64(len(v)))
return v, err
}
golang-github-go-kit-kit-0.10.0/examples/addsvc/pkg/addservice/service.go 0000664 0000000 0000000 00000003470 13622563124 0026247 0 ustar 00root root 0000000 0000000 package addservice
import (
"context"
"errors"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/metrics"
)
// Service describes a service that adds things together.
type Service interface {
Sum(ctx context.Context, a, b int) (int, error)
Concat(ctx context.Context, a, b string) (string, error)
}
// New returns a basic Service with all of the expected middlewares wired in.
func New(logger log.Logger, ints, chars metrics.Counter) Service {
var svc Service
{
svc = NewBasicService()
svc = LoggingMiddleware(logger)(svc)
svc = InstrumentingMiddleware(ints, chars)(svc)
}
return svc
}
var (
// ErrTwoZeroes is an arbitrary business rule for the Add method.
ErrTwoZeroes = errors.New("can't sum two zeroes")
// ErrIntOverflow protects the Add method. We've decided that this error
// indicates a misbehaving service and should count against e.g. circuit
// breakers. So, we return it directly in endpoints, to illustrate the
// difference. In a real service, this probably wouldn't be the case.
ErrIntOverflow = errors.New("integer overflow")
// ErrMaxSizeExceeded protects the Concat method.
ErrMaxSizeExceeded = errors.New("result exceeds maximum size")
)
// NewBasicService returns a naïve, stateless implementation of Service.
func NewBasicService() Service {
return basicService{}
}
type basicService struct{}
const (
intMax = 1<<31 - 1
intMin = -(intMax + 1)
maxLen = 10
)
func (s basicService) Sum(_ context.Context, a, b int) (int, error) {
if a == 0 && b == 0 {
return 0, ErrTwoZeroes
}
if (b > 0 && a > (intMax-b)) || (b < 0 && a < (intMin-b)) {
return 0, ErrIntOverflow
}
return a + b, nil
}
// Concat implements Service.
func (s basicService) Concat(_ context.Context, a, b string) (string, error) {
if len(a)+len(b) > maxLen {
return "", ErrMaxSizeExceeded
}
return a + b, nil
}
golang-github-go-kit-kit-0.10.0/examples/addsvc/pkg/addtransport/ 0000775 0000000 0000000 00000000000 13622563124 0024650 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/addsvc/pkg/addtransport/grpc.go 0000664 0000000 0000000 00000021754 13622563124 0026143 0 ustar 00root root 0000000 0000000 package addtransport
import (
"context"
"errors"
"time"
"google.golang.org/grpc"
stdopentracing "github.com/opentracing/opentracing-go"
stdzipkin "github.com/openzipkin/zipkin-go"
"github.com/sony/gobreaker"
"golang.org/x/time/rate"
"github.com/go-kit/kit/circuitbreaker"
"github.com/go-kit/kit/endpoint"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/ratelimit"
"github.com/go-kit/kit/tracing/opentracing"
"github.com/go-kit/kit/tracing/zipkin"
"github.com/go-kit/kit/transport"
grpctransport "github.com/go-kit/kit/transport/grpc"
"github.com/go-kit/kit/examples/addsvc/pb"
"github.com/go-kit/kit/examples/addsvc/pkg/addendpoint"
"github.com/go-kit/kit/examples/addsvc/pkg/addservice"
)
type grpcServer struct {
sum grpctransport.Handler
concat grpctransport.Handler
}
// NewGRPCServer makes a set of endpoints available as a gRPC AddServer.
func NewGRPCServer(endpoints addendpoint.Set, otTracer stdopentracing.Tracer, zipkinTracer *stdzipkin.Tracer, logger log.Logger) pb.AddServer {
options := []grpctransport.ServerOption{
grpctransport.ServerErrorHandler(transport.NewLogErrorHandler(logger)),
}
if zipkinTracer != nil {
// Zipkin GRPC Server Trace can either be instantiated per gRPC method with a
// provided operation name or a global tracing service can be instantiated
// without an operation name and fed to each Go kit gRPC server as a
// ServerOption.
// In the latter case, the operation name will be the endpoint's grpc method
// path if used in combination with the Go kit gRPC Interceptor.
//
// In this example, we demonstrate a global Zipkin tracing service with
// Go kit gRPC Interceptor.
options = append(options, zipkin.GRPCServerTrace(zipkinTracer))
}
return &grpcServer{
sum: grpctransport.NewServer(
endpoints.SumEndpoint,
decodeGRPCSumRequest,
encodeGRPCSumResponse,
append(options, grpctransport.ServerBefore(opentracing.GRPCToContext(otTracer, "Sum", logger)))...,
),
concat: grpctransport.NewServer(
endpoints.ConcatEndpoint,
decodeGRPCConcatRequest,
encodeGRPCConcatResponse,
append(options, grpctransport.ServerBefore(opentracing.GRPCToContext(otTracer, "Concat", logger)))...,
),
}
}
func (s *grpcServer) Sum(ctx context.Context, req *pb.SumRequest) (*pb.SumReply, error) {
_, rep, err := s.sum.ServeGRPC(ctx, req)
if err != nil {
return nil, err
}
return rep.(*pb.SumReply), nil
}
func (s *grpcServer) Concat(ctx context.Context, req *pb.ConcatRequest) (*pb.ConcatReply, error) {
_, rep, err := s.concat.ServeGRPC(ctx, req)
if err != nil {
return nil, err
}
return rep.(*pb.ConcatReply), nil
}
// NewGRPCClient returns an AddService backed by a gRPC server at the other end
// of the conn. The caller is responsible for constructing the conn, and
// eventually closing the underlying transport. We bake-in certain middlewares,
// implementing the client library pattern.
func NewGRPCClient(conn *grpc.ClientConn, otTracer stdopentracing.Tracer, zipkinTracer *stdzipkin.Tracer, logger log.Logger) addservice.Service {
// We construct a single ratelimiter middleware, to limit the total outgoing
// QPS from this client to all methods on the remote instance. We also
// construct per-endpoint circuitbreaker middlewares to demonstrate how
// that's done, although they could easily be combined into a single breaker
// for the entire remote instance, too.
limiter := ratelimit.NewErroringLimiter(rate.NewLimiter(rate.Every(time.Second), 100))
// global client middlewares
var options []grpctransport.ClientOption
if zipkinTracer != nil {
// Zipkin GRPC Client Trace can either be instantiated per gRPC method with a
// provided operation name or a global tracing client can be instantiated
// without an operation name and fed to each Go kit client as ClientOption.
// In the latter case, the operation name will be the endpoint's grpc method
// path.
//
// In this example, we demonstrace a global tracing client.
options = append(options, zipkin.GRPCClientTrace(zipkinTracer))
}
// Each individual endpoint is an grpc/transport.Client (which implements
// endpoint.Endpoint) that gets wrapped with various middlewares. If you
// made your own client library, you'd do this work there, so your server
// could rely on a consistent set of client behavior.
var sumEndpoint endpoint.Endpoint
{
sumEndpoint = grpctransport.NewClient(
conn,
"pb.Add",
"Sum",
encodeGRPCSumRequest,
decodeGRPCSumResponse,
pb.SumReply{},
append(options, grpctransport.ClientBefore(opentracing.ContextToGRPC(otTracer, logger)))...,
).Endpoint()
sumEndpoint = opentracing.TraceClient(otTracer, "Sum")(sumEndpoint)
sumEndpoint = limiter(sumEndpoint)
sumEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{
Name: "Sum",
Timeout: 30 * time.Second,
}))(sumEndpoint)
}
// The Concat endpoint is the same thing, with slightly different
// middlewares to demonstrate how to specialize per-endpoint.
var concatEndpoint endpoint.Endpoint
{
concatEndpoint = grpctransport.NewClient(
conn,
"pb.Add",
"Concat",
encodeGRPCConcatRequest,
decodeGRPCConcatResponse,
pb.ConcatReply{},
append(options, grpctransport.ClientBefore(opentracing.ContextToGRPC(otTracer, logger)))...,
).Endpoint()
concatEndpoint = opentracing.TraceClient(otTracer, "Concat")(concatEndpoint)
concatEndpoint = limiter(concatEndpoint)
concatEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{
Name: "Concat",
Timeout: 10 * time.Second,
}))(concatEndpoint)
}
// Returning the endpoint.Set as a service.Service relies on the
// endpoint.Set implementing the Service methods. That's just a simple bit
// of glue code.
return addendpoint.Set{
SumEndpoint: sumEndpoint,
ConcatEndpoint: concatEndpoint,
}
}
// decodeGRPCSumRequest is a transport/grpc.DecodeRequestFunc that converts a
// gRPC sum request to a user-domain sum request. Primarily useful in a server.
func decodeGRPCSumRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
req := grpcReq.(*pb.SumRequest)
return addendpoint.SumRequest{A: int(req.A), B: int(req.B)}, nil
}
// decodeGRPCConcatRequest is a transport/grpc.DecodeRequestFunc that converts a
// gRPC concat request to a user-domain concat request. Primarily useful in a
// server.
func decodeGRPCConcatRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
req := grpcReq.(*pb.ConcatRequest)
return addendpoint.ConcatRequest{A: req.A, B: req.B}, nil
}
// decodeGRPCSumResponse is a transport/grpc.DecodeResponseFunc that converts a
// gRPC sum reply to a user-domain sum response. Primarily useful in a client.
func decodeGRPCSumResponse(_ context.Context, grpcReply interface{}) (interface{}, error) {
reply := grpcReply.(*pb.SumReply)
return addendpoint.SumResponse{V: int(reply.V), Err: str2err(reply.Err)}, nil
}
// decodeGRPCConcatResponse is a transport/grpc.DecodeResponseFunc that converts
// a gRPC concat reply to a user-domain concat response. Primarily useful in a
// client.
func decodeGRPCConcatResponse(_ context.Context, grpcReply interface{}) (interface{}, error) {
reply := grpcReply.(*pb.ConcatReply)
return addendpoint.ConcatResponse{V: reply.V, Err: str2err(reply.Err)}, nil
}
// encodeGRPCSumResponse is a transport/grpc.EncodeResponseFunc that converts a
// user-domain sum response to a gRPC sum reply. Primarily useful in a server.
func encodeGRPCSumResponse(_ context.Context, response interface{}) (interface{}, error) {
resp := response.(addendpoint.SumResponse)
return &pb.SumReply{V: int64(resp.V), Err: err2str(resp.Err)}, nil
}
// encodeGRPCConcatResponse is a transport/grpc.EncodeResponseFunc that converts
// a user-domain concat response to a gRPC concat reply. Primarily useful in a
// server.
func encodeGRPCConcatResponse(_ context.Context, response interface{}) (interface{}, error) {
resp := response.(addendpoint.ConcatResponse)
return &pb.ConcatReply{V: resp.V, Err: err2str(resp.Err)}, nil
}
// encodeGRPCSumRequest is a transport/grpc.EncodeRequestFunc that converts a
// user-domain sum request to a gRPC sum request. Primarily useful in a client.
func encodeGRPCSumRequest(_ context.Context, request interface{}) (interface{}, error) {
req := request.(addendpoint.SumRequest)
return &pb.SumRequest{A: int64(req.A), B: int64(req.B)}, nil
}
// encodeGRPCConcatRequest is a transport/grpc.EncodeRequestFunc that converts a
// user-domain concat request to a gRPC concat request. Primarily useful in a
// client.
func encodeGRPCConcatRequest(_ context.Context, request interface{}) (interface{}, error) {
req := request.(addendpoint.ConcatRequest)
return &pb.ConcatRequest{A: req.A, B: req.B}, nil
}
// These annoying helper functions are required to translate Go error types to
// and from strings, which is the type we use in our IDLs to represent errors.
// There is special casing to treat empty strings as nil errors.
func str2err(s string) error {
if s == "" {
return nil
}
return errors.New(s)
}
func err2str(err error) string {
if err == nil {
return ""
}
return err.Error()
}
golang-github-go-kit-kit-0.10.0/examples/addsvc/pkg/addtransport/http.go 0000664 0000000 0000000 00000021670 13622563124 0026164 0 ustar 00root root 0000000 0000000 package addtransport
import (
"bytes"
"context"
"encoding/json"
"errors"
"io/ioutil"
"net/http"
"net/url"
"strings"
"time"
"golang.org/x/time/rate"
stdopentracing "github.com/opentracing/opentracing-go"
stdzipkin "github.com/openzipkin/zipkin-go"
"github.com/sony/gobreaker"
"github.com/go-kit/kit/circuitbreaker"
"github.com/go-kit/kit/endpoint"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/ratelimit"
"github.com/go-kit/kit/tracing/opentracing"
"github.com/go-kit/kit/tracing/zipkin"
"github.com/go-kit/kit/transport"
httptransport "github.com/go-kit/kit/transport/http"
"github.com/go-kit/kit/examples/addsvc/pkg/addendpoint"
"github.com/go-kit/kit/examples/addsvc/pkg/addservice"
)
// NewHTTPHandler returns an HTTP handler that makes a set of endpoints
// available on predefined paths.
func NewHTTPHandler(endpoints addendpoint.Set, otTracer stdopentracing.Tracer, zipkinTracer *stdzipkin.Tracer, logger log.Logger) http.Handler {
options := []httptransport.ServerOption{
httptransport.ServerErrorEncoder(errorEncoder),
httptransport.ServerErrorHandler(transport.NewLogErrorHandler(logger)),
}
if zipkinTracer != nil {
// Zipkin HTTP Server Trace can either be instantiated per endpoint with a
// provided operation name or a global tracing service can be instantiated
// without an operation name and fed to each Go kit endpoint as ServerOption.
// In the latter case, the operation name will be the endpoint's http method.
// We demonstrate a global tracing service here.
options = append(options, zipkin.HTTPServerTrace(zipkinTracer))
}
m := http.NewServeMux()
m.Handle("/sum", httptransport.NewServer(
endpoints.SumEndpoint,
decodeHTTPSumRequest,
encodeHTTPGenericResponse,
append(options, httptransport.ServerBefore(opentracing.HTTPToContext(otTracer, "Sum", logger)))...,
))
m.Handle("/concat", httptransport.NewServer(
endpoints.ConcatEndpoint,
decodeHTTPConcatRequest,
encodeHTTPGenericResponse,
append(options, httptransport.ServerBefore(opentracing.HTTPToContext(otTracer, "Concat", logger)))...,
))
return m
}
// NewHTTPClient returns an AddService backed by an HTTP server living at the
// remote instance. We expect instance to come from a service discovery system,
// so likely of the form "host:port". We bake-in certain middlewares,
// implementing the client library pattern.
func NewHTTPClient(instance string, otTracer stdopentracing.Tracer, zipkinTracer *stdzipkin.Tracer, logger log.Logger) (addservice.Service, error) {
// Quickly sanitize the instance string.
if !strings.HasPrefix(instance, "http") {
instance = "http://" + instance
}
u, err := url.Parse(instance)
if err != nil {
return nil, err
}
// We construct a single ratelimiter middleware, to limit the total outgoing
// QPS from this client to all methods on the remote instance. We also
// construct per-endpoint circuitbreaker middlewares to demonstrate how
// that's done, although they could easily be combined into a single breaker
// for the entire remote instance, too.
limiter := ratelimit.NewErroringLimiter(rate.NewLimiter(rate.Every(time.Second), 100))
// global client middlewares
var options []httptransport.ClientOption
if zipkinTracer != nil {
// Zipkin HTTP Client Trace can either be instantiated per endpoint with a
// provided operation name or a global tracing client can be instantiated
// without an operation name and fed to each Go kit endpoint as ClientOption.
// In the latter case, the operation name will be the endpoint's http method.
options = append(options, zipkin.HTTPClientTrace(zipkinTracer))
}
// Each individual endpoint is an http/transport.Client (which implements
// endpoint.Endpoint) that gets wrapped with various middlewares. If you
// made your own client library, you'd do this work there, so your server
// could rely on a consistent set of client behavior.
var sumEndpoint endpoint.Endpoint
{
sumEndpoint = httptransport.NewClient(
"POST",
copyURL(u, "/sum"),
encodeHTTPGenericRequest,
decodeHTTPSumResponse,
append(options, httptransport.ClientBefore(opentracing.ContextToHTTP(otTracer, logger)))...,
).Endpoint()
sumEndpoint = opentracing.TraceClient(otTracer, "Sum")(sumEndpoint)
if zipkinTracer != nil {
sumEndpoint = zipkin.TraceEndpoint(zipkinTracer, "Sum")(sumEndpoint)
}
sumEndpoint = limiter(sumEndpoint)
sumEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{
Name: "Sum",
Timeout: 30 * time.Second,
}))(sumEndpoint)
}
// The Concat endpoint is the same thing, with slightly different
// middlewares to demonstrate how to specialize per-endpoint.
var concatEndpoint endpoint.Endpoint
{
concatEndpoint = httptransport.NewClient(
"POST",
copyURL(u, "/concat"),
encodeHTTPGenericRequest,
decodeHTTPConcatResponse,
append(options, httptransport.ClientBefore(opentracing.ContextToHTTP(otTracer, logger)))...,
).Endpoint()
concatEndpoint = opentracing.TraceClient(otTracer, "Concat")(concatEndpoint)
if zipkinTracer != nil {
concatEndpoint = zipkin.TraceEndpoint(zipkinTracer, "Concat")(concatEndpoint)
}
concatEndpoint = limiter(concatEndpoint)
concatEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{
Name: "Concat",
Timeout: 10 * time.Second,
}))(concatEndpoint)
}
// Returning the endpoint.Set as a service.Service relies on the
// endpoint.Set implementing the Service methods. That's just a simple bit
// of glue code.
return addendpoint.Set{
SumEndpoint: sumEndpoint,
ConcatEndpoint: concatEndpoint,
}, nil
}
func copyURL(base *url.URL, path string) *url.URL {
next := *base
next.Path = path
return &next
}
func errorEncoder(_ context.Context, err error, w http.ResponseWriter) {
w.WriteHeader(err2code(err))
json.NewEncoder(w).Encode(errorWrapper{Error: err.Error()})
}
func err2code(err error) int {
switch err {
case addservice.ErrTwoZeroes, addservice.ErrMaxSizeExceeded, addservice.ErrIntOverflow:
return http.StatusBadRequest
}
return http.StatusInternalServerError
}
func errorDecoder(r *http.Response) error {
var w errorWrapper
if err := json.NewDecoder(r.Body).Decode(&w); err != nil {
return err
}
return errors.New(w.Error)
}
type errorWrapper struct {
Error string `json:"error"`
}
// decodeHTTPSumRequest is a transport/http.DecodeRequestFunc that decodes a
// JSON-encoded sum request from the HTTP request body. Primarily useful in a
// server.
func decodeHTTPSumRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req addendpoint.SumRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
// decodeHTTPConcatRequest is a transport/http.DecodeRequestFunc that decodes a
// JSON-encoded concat request from the HTTP request body. Primarily useful in a
// server.
func decodeHTTPConcatRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req addendpoint.ConcatRequest
err := json.NewDecoder(r.Body).Decode(&req)
return req, err
}
// decodeHTTPSumResponse is a transport/http.DecodeResponseFunc that decodes a
// JSON-encoded sum response from the HTTP response body. If the response has a
// non-200 status code, we will interpret that as an error and attempt to decode
// the specific error message from the response body. Primarily useful in a
// client.
func decodeHTTPSumResponse(_ context.Context, r *http.Response) (interface{}, error) {
if r.StatusCode != http.StatusOK {
return nil, errors.New(r.Status)
}
var resp addendpoint.SumResponse
err := json.NewDecoder(r.Body).Decode(&resp)
return resp, err
}
// decodeHTTPConcatResponse is a transport/http.DecodeResponseFunc that decodes
// a JSON-encoded concat response from the HTTP response body. If the response
// has a non-200 status code, we will interpret that as an error and attempt to
// decode the specific error message from the response body. Primarily useful in
// a client.
func decodeHTTPConcatResponse(_ context.Context, r *http.Response) (interface{}, error) {
if r.StatusCode != http.StatusOK {
return nil, errors.New(r.Status)
}
var resp addendpoint.ConcatResponse
err := json.NewDecoder(r.Body).Decode(&resp)
return resp, err
}
// encodeHTTPGenericRequest is a transport/http.EncodeRequestFunc that
// JSON-encodes any request to the request body. Primarily useful in a client.
func encodeHTTPGenericRequest(_ context.Context, r *http.Request, request interface{}) error {
var buf bytes.Buffer
if err := json.NewEncoder(&buf).Encode(request); err != nil {
return err
}
r.Body = ioutil.NopCloser(&buf)
return nil
}
// encodeHTTPGenericResponse is a transport/http.EncodeResponseFunc that encodes
// the response as JSON to the response writer. Primarily useful in a server.
func encodeHTTPGenericResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error {
if f, ok := response.(endpoint.Failer); ok && f.Failed() != nil {
errorEncoder(ctx, f.Failed(), w)
return nil
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
golang-github-go-kit-kit-0.10.0/examples/addsvc/pkg/addtransport/jsonrpc.go 0000664 0000000 0000000 00000014542 13622563124 0026663 0 ustar 00root root 0000000 0000000 package addtransport
import (
"context"
"encoding/json"
"fmt"
"net/url"
"strings"
"time"
"golang.org/x/time/rate"
"github.com/go-kit/kit/circuitbreaker"
"github.com/go-kit/kit/endpoint"
"github.com/go-kit/kit/examples/addsvc/pkg/addendpoint"
"github.com/go-kit/kit/examples/addsvc/pkg/addservice"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/ratelimit"
"github.com/go-kit/kit/tracing/opentracing"
"github.com/go-kit/kit/transport/http/jsonrpc"
stdopentracing "github.com/opentracing/opentracing-go"
"github.com/sony/gobreaker"
)
// NewJSONRPCHandler returns a JSON RPC Server/Handler that can be passed to http.Handle()
func NewJSONRPCHandler(endpoints addendpoint.Set, logger log.Logger) *jsonrpc.Server {
handler := jsonrpc.NewServer(
makeEndpointCodecMap(endpoints),
jsonrpc.ServerErrorLogger(logger),
)
return handler
}
// NewJSONRPCClient returns an addservice backed by a JSON RPC over HTTP server
// living at the remote instance. We expect instance to come from a service
// discovery system, so likely of the form "host:port". We bake-in certain
// middlewares, implementing the client library pattern.
func NewJSONRPCClient(instance string, tracer stdopentracing.Tracer, logger log.Logger) (addservice.Service, error) {
// Quickly sanitize the instance string.
if !strings.HasPrefix(instance, "http") {
instance = "http://" + instance
}
u, err := url.Parse(instance)
if err != nil {
return nil, err
}
// We construct a single ratelimiter middleware, to limit the total outgoing
// QPS from this client to all methods on the remote instance. We also
// construct per-endpoint circuitbreaker middlewares to demonstrate how
// that's done, although they could easily be combined into a single breaker
// for the entire remote instance, too.
limiter := ratelimit.NewErroringLimiter(rate.NewLimiter(rate.Every(time.Second), 100))
var sumEndpoint endpoint.Endpoint
{
sumEndpoint = jsonrpc.NewClient(
u,
"sum",
jsonrpc.ClientRequestEncoder(encodeSumRequest),
jsonrpc.ClientResponseDecoder(decodeSumResponse),
).Endpoint()
sumEndpoint = opentracing.TraceClient(tracer, "Sum")(sumEndpoint)
sumEndpoint = limiter(sumEndpoint)
sumEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{
Name: "Sum",
Timeout: 30 * time.Second,
}))(sumEndpoint)
}
var concatEndpoint endpoint.Endpoint
{
concatEndpoint = jsonrpc.NewClient(
u,
"concat",
jsonrpc.ClientRequestEncoder(encodeConcatRequest),
jsonrpc.ClientResponseDecoder(decodeConcatResponse),
).Endpoint()
concatEndpoint = opentracing.TraceClient(tracer, "Concat")(concatEndpoint)
concatEndpoint = limiter(concatEndpoint)
concatEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{
Name: "Concat",
Timeout: 30 * time.Second,
}))(concatEndpoint)
}
// Returning the endpoint.Set as a service.Service relies on the
// endpoint.Set implementing the Service methods. That's just a simple bit
// of glue code.
return addendpoint.Set{
SumEndpoint: sumEndpoint,
ConcatEndpoint: concatEndpoint,
}, nil
}
// makeEndpointCodecMap returns a codec map configured for the addsvc.
func makeEndpointCodecMap(endpoints addendpoint.Set) jsonrpc.EndpointCodecMap {
return jsonrpc.EndpointCodecMap{
"sum": jsonrpc.EndpointCodec{
Endpoint: endpoints.SumEndpoint,
Decode: decodeSumRequest,
Encode: encodeSumResponse,
},
"concat": jsonrpc.EndpointCodec{
Endpoint: endpoints.ConcatEndpoint,
Decode: decodeConcatRequest,
Encode: encodeConcatResponse,
},
}
}
func decodeSumRequest(_ context.Context, msg json.RawMessage) (interface{}, error) {
var req addendpoint.SumRequest
err := json.Unmarshal(msg, &req)
if err != nil {
return nil, &jsonrpc.Error{
Code: -32000,
Message: fmt.Sprintf("couldn't unmarshal body to sum request: %s", err),
}
}
return req, nil
}
func encodeSumResponse(_ context.Context, obj interface{}) (json.RawMessage, error) {
res, ok := obj.(addendpoint.SumResponse)
if !ok {
return nil, &jsonrpc.Error{
Code: -32000,
Message: fmt.Sprintf("Asserting result to *SumResponse failed. Got %T, %+v", obj, obj),
}
}
b, err := json.Marshal(res)
if err != nil {
return nil, fmt.Errorf("couldn't marshal response: %s", err)
}
return b, nil
}
func decodeSumResponse(_ context.Context, res jsonrpc.Response) (interface{}, error) {
if res.Error != nil {
return nil, *res.Error
}
var sumres addendpoint.SumResponse
err := json.Unmarshal(res.Result, &sumres)
if err != nil {
return nil, fmt.Errorf("couldn't unmarshal body to SumResponse: %s", err)
}
return sumres, nil
}
func encodeSumRequest(_ context.Context, obj interface{}) (json.RawMessage, error) {
req, ok := obj.(addendpoint.SumRequest)
if !ok {
return nil, fmt.Errorf("couldn't assert request as SumRequest, got %T", obj)
}
b, err := json.Marshal(req)
if err != nil {
return nil, fmt.Errorf("couldn't marshal request: %s", err)
}
return b, nil
}
func decodeConcatRequest(_ context.Context, msg json.RawMessage) (interface{}, error) {
var req addendpoint.ConcatRequest
err := json.Unmarshal(msg, &req)
if err != nil {
return nil, &jsonrpc.Error{
Code: -32000,
Message: fmt.Sprintf("couldn't unmarshal body to concat request: %s", err),
}
}
return req, nil
}
func encodeConcatResponse(_ context.Context, obj interface{}) (json.RawMessage, error) {
res, ok := obj.(addendpoint.ConcatResponse)
if !ok {
return nil, &jsonrpc.Error{
Code: -32000,
Message: fmt.Sprintf("Asserting result to *ConcatResponse failed. Got %T, %+v", obj, obj),
}
}
b, err := json.Marshal(res)
if err != nil {
return nil, fmt.Errorf("couldn't marshal response: %s", err)
}
return b, nil
}
func decodeConcatResponse(_ context.Context, res jsonrpc.Response) (interface{}, error) {
if res.Error != nil {
return nil, *res.Error
}
var concatres addendpoint.ConcatResponse
err := json.Unmarshal(res.Result, &concatres)
if err != nil {
return nil, fmt.Errorf("couldn't unmarshal body to ConcatResponse: %s", err)
}
return concatres, nil
}
func encodeConcatRequest(_ context.Context, obj interface{}) (json.RawMessage, error) {
req, ok := obj.(addendpoint.ConcatRequest)
if !ok {
return nil, fmt.Errorf("couldn't assert request as ConcatRequest, got %T", obj)
}
b, err := json.Marshal(req)
if err != nil {
return nil, fmt.Errorf("couldn't marshal request: %s", err)
}
return b, nil
}
golang-github-go-kit-kit-0.10.0/examples/addsvc/pkg/addtransport/thrift.go 0000664 0000000 0000000 00000010664 13622563124 0026506 0 ustar 00root root 0000000 0000000 package addtransport
import (
"context"
"time"
"golang.org/x/time/rate"
"github.com/sony/gobreaker"
"github.com/go-kit/kit/circuitbreaker"
"github.com/go-kit/kit/endpoint"
"github.com/go-kit/kit/ratelimit"
"github.com/go-kit/kit/examples/addsvc/pkg/addendpoint"
"github.com/go-kit/kit/examples/addsvc/pkg/addservice"
addthrift "github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc"
)
type thriftServer struct {
ctx context.Context
endpoints addendpoint.Set
}
// NewThriftServer makes a set of endpoints available as a Thrift service.
func NewThriftServer(endpoints addendpoint.Set) addthrift.AddService {
return &thriftServer{
endpoints: endpoints,
}
}
func (s *thriftServer) Sum(ctx context.Context, a int64, b int64) (*addthrift.SumReply, error) {
request := addendpoint.SumRequest{A: int(a), B: int(b)}
response, err := s.endpoints.SumEndpoint(ctx, request)
if err != nil {
return nil, err
}
resp := response.(addendpoint.SumResponse)
return &addthrift.SumReply{Value: int64(resp.V), Err: err2str(resp.Err)}, nil
}
func (s *thriftServer) Concat(ctx context.Context, a string, b string) (*addthrift.ConcatReply, error) {
request := addendpoint.ConcatRequest{A: a, B: b}
response, err := s.endpoints.ConcatEndpoint(ctx, request)
if err != nil {
return nil, err
}
resp := response.(addendpoint.ConcatResponse)
return &addthrift.ConcatReply{Value: resp.V, Err: err2str(resp.Err)}, nil
}
// NewThriftClient returns an AddService backed by a Thrift server described by
// the provided client. The caller is responsible for constructing the client,
// and eventually closing the underlying transport. We bake-in certain middlewares,
// implementing the client library pattern.
func NewThriftClient(client *addthrift.AddServiceClient) addservice.Service {
// We construct a single ratelimiter middleware, to limit the total outgoing
// QPS from this client to all methods on the remote instance. We also
// construct per-endpoint circuitbreaker middlewares to demonstrate how
// that's done, although they could easily be combined into a single breaker
// for the entire remote instance, too.
limiter := ratelimit.NewErroringLimiter(rate.NewLimiter(rate.Every(time.Second), 100))
// Each individual endpoint is an http/transport.Client (which implements
// endpoint.Endpoint) that gets wrapped with various middlewares. If you
// could rely on a consistent set of client behavior.
var sumEndpoint endpoint.Endpoint
{
sumEndpoint = MakeThriftSumEndpoint(client)
sumEndpoint = limiter(sumEndpoint)
sumEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{
Name: "Sum",
Timeout: 30 * time.Second,
}))(sumEndpoint)
}
// The Concat endpoint is the same thing, with slightly different
// middlewares to demonstrate how to specialize per-endpoint.
var concatEndpoint endpoint.Endpoint
{
concatEndpoint = MakeThriftConcatEndpoint(client)
concatEndpoint = limiter(concatEndpoint)
concatEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{
Name: "Concat",
Timeout: 10 * time.Second,
}))(concatEndpoint)
}
// Returning the endpoint.Set as a service.Service relies on the
// endpoint.Set implementing the Service methods. That's just a simple bit
// of glue code.
return addendpoint.Set{
SumEndpoint: sumEndpoint,
ConcatEndpoint: concatEndpoint,
}
}
// MakeThriftSumEndpoint returns an endpoint that invokes the passed Thrift client.
// Useful only in clients, and only until a proper transport/thrift.Client exists.
func MakeThriftSumEndpoint(client *addthrift.AddServiceClient) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(addendpoint.SumRequest)
reply, err := client.Sum(ctx, int64(req.A), int64(req.B))
if err == addservice.ErrIntOverflow {
return nil, err // special case; see comment on ErrIntOverflow
}
return addendpoint.SumResponse{V: int(reply.Value), Err: err}, nil
}
}
// MakeThriftConcatEndpoint returns an endpoint that invokes the passed Thrift
// client. Useful only in clients, and only until a proper
// transport/thrift.Client exists.
func MakeThriftConcatEndpoint(client *addthrift.AddServiceClient) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(addendpoint.ConcatRequest)
reply, err := client.Concat(ctx, req.A, req.B)
return addendpoint.ConcatResponse{V: reply.Value, Err: err}, nil
}
}
golang-github-go-kit-kit-0.10.0/examples/addsvc/thrift/ 0000775 0000000 0000000 00000000000 13622563124 0022662 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/addsvc/thrift/addsvc.thrift 0000664 0000000 0000000 00000000321 13622563124 0025344 0 ustar 00root root 0000000 0000000 struct SumReply {
1: i64 value
2: string err
}
struct ConcatReply {
1: string value
2: string err
}
service AddService {
SumReply Sum(1: i64 a, 2: i64 b)
ConcatReply Concat(1: string a, 2: string b)
}
golang-github-go-kit-kit-0.10.0/examples/addsvc/thrift/compile.sh 0000775 0000000 0000000 00000001720 13622563124 0024651 0 ustar 00root root 0000000 0000000 #!/usr/bin/env sh
# See also https://thrift.apache.org/tutorial/go.
#
# An old version can be obtained via `brew install thrift`.
# For the latest, here's the annoying dance:
#
# brew install automake bison pkg-config openssl
# ln -s /usr/local/opt/openssl/include/openssl /usr/local/include # if it isn't already
# git clone git@github.com:apache/thrift
# ./bootstrap.sh
# bash
# export PATH=/usr/local/Cellar/bison/*/bin:$PATH
# ./configure ./configure --without-qt4 --without-qt5 --without-c_glib --without-csharp --without-java --without-erlang --without-nodejs --without-lua --without-python --without-perl --without-php --without-php_extension --without-dart --without-ruby --without-haskell --without-rs --without-cl --without-haxe --without-dotnetcore --without-d
# make
# sudo make install
thrift -r --gen "go:package_prefix=github.com/go-kit/kit/examples/addsvc/thrift/gen-go/,thrift_import=github.com/apache/thrift/lib/go/thrift" addsvc.thrift
golang-github-go-kit-kit-0.10.0/examples/addsvc/thrift/gen-go/ 0000775 0000000 0000000 00000000000 13622563124 0024036 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/addsvc/thrift/gen-go/addsvc/ 0000775 0000000 0000000 00000000000 13622563124 0025302 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/addsvc/thrift/gen-go/addsvc/GoUnusedProtection__.go 0000664 0000000 0000000 00000000244 13622563124 0031727 0 ustar 00root root 0000000 0000000 // Autogenerated by Thrift Compiler (1.0.0-dev)
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
package addsvc
var GoUnusedProtection__ int;
golang-github-go-kit-kit-0.10.0/examples/addsvc/thrift/gen-go/addsvc/add_service-remote/ 0000775 0000000 0000000 00000000000 13622563124 0031043 5 ustar 00root root 0000000 0000000 add_service-remote.go 0000775 0000000 0000000 00000011234 13622563124 0035060 0 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/addsvc/thrift/gen-go/addsvc/add_service-remote // Autogenerated by Thrift Compiler (1.0.0-dev)
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
package main
import (
"context"
"flag"
"fmt"
"github.com/apache/thrift/lib/go/thrift"
"github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc"
"math"
"net"
"net/url"
"os"
"strconv"
"strings"
)
func Usage() {
fmt.Fprintln(os.Stderr, "Usage of ", os.Args[0], " [-h host:port] [-u url] [-f[ramed]] function [arg1 [arg2...]]:")
flag.PrintDefaults()
fmt.Fprintln(os.Stderr, "\nFunctions:")
fmt.Fprintln(os.Stderr, " SumReply Sum(i64 a, i64 b)")
fmt.Fprintln(os.Stderr, " ConcatReply Concat(string a, string b)")
fmt.Fprintln(os.Stderr)
os.Exit(0)
}
type httpHeaders map[string]string
func (h httpHeaders) String() string {
var m map[string]string = h
return fmt.Sprintf("%s", m)
}
func (h httpHeaders) Set(value string) error {
parts := strings.Split(value, ": ")
if len(parts) != 2 {
return fmt.Errorf("header should be of format 'Key: Value'")
}
h[parts[0]] = parts[1]
return nil
}
func main() {
flag.Usage = Usage
var host string
var port int
var protocol string
var urlString string
var framed bool
var useHttp bool
headers := make(httpHeaders)
var parsedUrl *url.URL
var trans thrift.TTransport
_ = strconv.Atoi
_ = math.Abs
flag.Usage = Usage
flag.StringVar(&host, "h", "localhost", "Specify host and port")
flag.IntVar(&port, "p", 9090, "Specify port")
flag.StringVar(&protocol, "P", "binary", "Specify the protocol (binary, compact, simplejson, json)")
flag.StringVar(&urlString, "u", "", "Specify the url")
flag.BoolVar(&framed, "framed", false, "Use framed transport")
flag.BoolVar(&useHttp, "http", false, "Use http")
flag.Var(headers, "H", "Headers to set on the http(s) request (e.g. -H \"Key: Value\")")
flag.Parse()
if len(urlString) > 0 {
var err error
parsedUrl, err = url.Parse(urlString)
if err != nil {
fmt.Fprintln(os.Stderr, "Error parsing URL: ", err)
flag.Usage()
}
host = parsedUrl.Host
useHttp = parsedUrl.Scheme == "" || parsedUrl.Scheme == "http" || parsedUrl.Scheme == "https"
} else if useHttp {
_, err := url.Parse(fmt.Sprint("http://", host, ":", port))
if err != nil {
fmt.Fprintln(os.Stderr, "Error parsing URL: ", err)
flag.Usage()
}
}
cmd := flag.Arg(0)
var err error
if useHttp {
trans, err = thrift.NewTHttpClient(parsedUrl.String())
if len(headers) > 0 {
httptrans := trans.(*thrift.THttpClient)
for key, value := range headers {
httptrans.SetHeader(key, value)
}
}
} else {
portStr := fmt.Sprint(port)
if strings.Contains(host, ":") {
host, portStr, err = net.SplitHostPort(host)
if err != nil {
fmt.Fprintln(os.Stderr, "error with host:", err)
os.Exit(1)
}
}
trans, err = thrift.NewTSocket(net.JoinHostPort(host, portStr))
if err != nil {
fmt.Fprintln(os.Stderr, "error resolving address:", err)
os.Exit(1)
}
if framed {
trans = thrift.NewTFramedTransport(trans)
}
}
if err != nil {
fmt.Fprintln(os.Stderr, "Error creating transport", err)
os.Exit(1)
}
defer trans.Close()
var protocolFactory thrift.TProtocolFactory
switch protocol {
case "compact":
protocolFactory = thrift.NewTCompactProtocolFactory()
break
case "simplejson":
protocolFactory = thrift.NewTSimpleJSONProtocolFactory()
break
case "json":
protocolFactory = thrift.NewTJSONProtocolFactory()
break
case "binary", "":
protocolFactory = thrift.NewTBinaryProtocolFactoryDefault()
break
default:
fmt.Fprintln(os.Stderr, "Invalid protocol specified: ", protocol)
Usage()
os.Exit(1)
}
iprot := protocolFactory.GetProtocol(trans)
oprot := protocolFactory.GetProtocol(trans)
client := addsvc.NewAddServiceClient(thrift.NewTStandardClient(iprot, oprot))
if err := trans.Open(); err != nil {
fmt.Fprintln(os.Stderr, "Error opening socket to ", host, ":", port, " ", err)
os.Exit(1)
}
switch cmd {
case "Sum":
if flag.NArg()-1 != 2 {
fmt.Fprintln(os.Stderr, "Sum requires 2 args")
flag.Usage()
}
argvalue0, err6 := (strconv.ParseInt(flag.Arg(1), 10, 64))
if err6 != nil {
Usage()
return
}
value0 := argvalue0
argvalue1, err7 := (strconv.ParseInt(flag.Arg(2), 10, 64))
if err7 != nil {
Usage()
return
}
value1 := argvalue1
fmt.Print(client.Sum(context.Background(), value0, value1))
fmt.Print("\n")
break
case "Concat":
if flag.NArg()-1 != 2 {
fmt.Fprintln(os.Stderr, "Concat requires 2 args")
flag.Usage()
}
argvalue0 := flag.Arg(1)
value0 := argvalue0
argvalue1 := flag.Arg(2)
value1 := argvalue1
fmt.Print(client.Concat(context.Background(), value0, value1))
fmt.Print("\n")
break
case "":
Usage()
break
default:
fmt.Fprintln(os.Stderr, "Invalid function ", cmd)
}
}
golang-github-go-kit-kit-0.10.0/examples/addsvc/thrift/gen-go/addsvc/addsvc-consts.go 0000664 0000000 0000000 00000000654 13622563124 0030411 0 ustar 00root root 0000000 0000000 // Autogenerated by Thrift Compiler (1.0.0-dev)
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
package addsvc
import (
"bytes"
"context"
"reflect"
"fmt"
"github.com/apache/thrift/lib/go/thrift"
)
// (needed to ensure safety because of naive import list construction.)
var _ = thrift.ZERO
var _ = fmt.Printf
var _ = context.Background
var _ = reflect.DeepEqual
var _ = bytes.Equal
func init() {
}
golang-github-go-kit-kit-0.10.0/examples/addsvc/thrift/gen-go/addsvc/addsvc.go 0000664 0000000 0000000 00000066512 13622563124 0027107 0 ustar 00root root 0000000 0000000 // Autogenerated by Thrift Compiler (1.0.0-dev)
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
package addsvc
import (
"bytes"
"context"
"reflect"
"fmt"
"github.com/apache/thrift/lib/go/thrift"
)
// (needed to ensure safety because of naive import list construction.)
var _ = thrift.ZERO
var _ = fmt.Printf
var _ = context.Background
var _ = reflect.DeepEqual
var _ = bytes.Equal
// Attributes:
// - Value
// - Err
type SumReply struct {
Value int64 `thrift:"value,1" db:"value" json:"value"`
Err string `thrift:"err,2" db:"err" json:"err"`
}
func NewSumReply() *SumReply {
return &SumReply{}
}
func (p *SumReply) GetValue() int64 {
return p.Value
}
func (p *SumReply) GetErr() string {
return p.Err
}
func (p *SumReply) Read(iprot thrift.TProtocol) error {
if _, err := iprot.ReadStructBegin(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
}
for {
_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
if err != nil {
return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
}
if fieldTypeId == thrift.STOP { break; }
switch fieldId {
case 1:
if fieldTypeId == thrift.I64 {
if err := p.ReadField1(iprot); err != nil {
return err
}
} else {
if err := iprot.Skip(fieldTypeId); err != nil {
return err
}
}
case 2:
if fieldTypeId == thrift.STRING {
if err := p.ReadField2(iprot); err != nil {
return err
}
} else {
if err := iprot.Skip(fieldTypeId); err != nil {
return err
}
}
default:
if err := iprot.Skip(fieldTypeId); err != nil {
return err
}
}
if err := iprot.ReadFieldEnd(); err != nil {
return err
}
}
if err := iprot.ReadStructEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
return nil
}
func (p *SumReply) ReadField1(iprot thrift.TProtocol) error {
if v, err := iprot.ReadI64(); err != nil {
return thrift.PrependError("error reading field 1: ", err)
} else {
p.Value = v
}
return nil
}
func (p *SumReply) ReadField2(iprot thrift.TProtocol) error {
if v, err := iprot.ReadString(); err != nil {
return thrift.PrependError("error reading field 2: ", err)
} else {
p.Err = v
}
return nil
}
func (p *SumReply) Write(oprot thrift.TProtocol) error {
if err := oprot.WriteStructBegin("SumReply"); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) }
if p != nil {
if err := p.writeField1(oprot); err != nil { return err }
if err := p.writeField2(oprot); err != nil { return err }
}
if err := oprot.WriteFieldStop(); err != nil {
return thrift.PrependError("write field stop error: ", err) }
if err := oprot.WriteStructEnd(); err != nil {
return thrift.PrependError("write struct stop error: ", err) }
return nil
}
func (p *SumReply) writeField1(oprot thrift.TProtocol) (err error) {
if err := oprot.WriteFieldBegin("value", thrift.I64, 1); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:value: ", p), err) }
if err := oprot.WriteI64(int64(p.Value)); err != nil {
return thrift.PrependError(fmt.Sprintf("%T.value (1) field write error: ", p), err) }
if err := oprot.WriteFieldEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field end error 1:value: ", p), err) }
return err
}
func (p *SumReply) writeField2(oprot thrift.TProtocol) (err error) {
if err := oprot.WriteFieldBegin("err", thrift.STRING, 2); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:err: ", p), err) }
if err := oprot.WriteString(string(p.Err)); err != nil {
return thrift.PrependError(fmt.Sprintf("%T.err (2) field write error: ", p), err) }
if err := oprot.WriteFieldEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field end error 2:err: ", p), err) }
return err
}
func (p *SumReply) String() string {
if p == nil {
return ""
}
return fmt.Sprintf("SumReply(%+v)", *p)
}
// Attributes:
// - Value
// - Err
type ConcatReply struct {
Value string `thrift:"value,1" db:"value" json:"value"`
Err string `thrift:"err,2" db:"err" json:"err"`
}
func NewConcatReply() *ConcatReply {
return &ConcatReply{}
}
func (p *ConcatReply) GetValue() string {
return p.Value
}
func (p *ConcatReply) GetErr() string {
return p.Err
}
func (p *ConcatReply) Read(iprot thrift.TProtocol) error {
if _, err := iprot.ReadStructBegin(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
}
for {
_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
if err != nil {
return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
}
if fieldTypeId == thrift.STOP { break; }
switch fieldId {
case 1:
if fieldTypeId == thrift.STRING {
if err := p.ReadField1(iprot); err != nil {
return err
}
} else {
if err := iprot.Skip(fieldTypeId); err != nil {
return err
}
}
case 2:
if fieldTypeId == thrift.STRING {
if err := p.ReadField2(iprot); err != nil {
return err
}
} else {
if err := iprot.Skip(fieldTypeId); err != nil {
return err
}
}
default:
if err := iprot.Skip(fieldTypeId); err != nil {
return err
}
}
if err := iprot.ReadFieldEnd(); err != nil {
return err
}
}
if err := iprot.ReadStructEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
return nil
}
func (p *ConcatReply) ReadField1(iprot thrift.TProtocol) error {
if v, err := iprot.ReadString(); err != nil {
return thrift.PrependError("error reading field 1: ", err)
} else {
p.Value = v
}
return nil
}
func (p *ConcatReply) ReadField2(iprot thrift.TProtocol) error {
if v, err := iprot.ReadString(); err != nil {
return thrift.PrependError("error reading field 2: ", err)
} else {
p.Err = v
}
return nil
}
func (p *ConcatReply) Write(oprot thrift.TProtocol) error {
if err := oprot.WriteStructBegin("ConcatReply"); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) }
if p != nil {
if err := p.writeField1(oprot); err != nil { return err }
if err := p.writeField2(oprot); err != nil { return err }
}
if err := oprot.WriteFieldStop(); err != nil {
return thrift.PrependError("write field stop error: ", err) }
if err := oprot.WriteStructEnd(); err != nil {
return thrift.PrependError("write struct stop error: ", err) }
return nil
}
func (p *ConcatReply) writeField1(oprot thrift.TProtocol) (err error) {
if err := oprot.WriteFieldBegin("value", thrift.STRING, 1); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:value: ", p), err) }
if err := oprot.WriteString(string(p.Value)); err != nil {
return thrift.PrependError(fmt.Sprintf("%T.value (1) field write error: ", p), err) }
if err := oprot.WriteFieldEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field end error 1:value: ", p), err) }
return err
}
func (p *ConcatReply) writeField2(oprot thrift.TProtocol) (err error) {
if err := oprot.WriteFieldBegin("err", thrift.STRING, 2); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:err: ", p), err) }
if err := oprot.WriteString(string(p.Err)); err != nil {
return thrift.PrependError(fmt.Sprintf("%T.err (2) field write error: ", p), err) }
if err := oprot.WriteFieldEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field end error 2:err: ", p), err) }
return err
}
func (p *ConcatReply) String() string {
if p == nil {
return ""
}
return fmt.Sprintf("ConcatReply(%+v)", *p)
}
type AddService interface {
// Parameters:
// - A
// - B
Sum(ctx context.Context, a int64, b int64) (r *SumReply, err error)
// Parameters:
// - A
// - B
Concat(ctx context.Context, a string, b string) (r *ConcatReply, err error)
}
type AddServiceClient struct {
c thrift.TClient
}
func NewAddServiceClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *AddServiceClient {
return &AddServiceClient{
c: thrift.NewTStandardClient(f.GetProtocol(t), f.GetProtocol(t)),
}
}
func NewAddServiceClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *AddServiceClient {
return &AddServiceClient{
c: thrift.NewTStandardClient(iprot, oprot),
}
}
func NewAddServiceClient(c thrift.TClient) *AddServiceClient {
return &AddServiceClient{
c: c,
}
}
func (p *AddServiceClient) Client_() thrift.TClient {
return p.c
}
// Parameters:
// - A
// - B
func (p *AddServiceClient) Sum(ctx context.Context, a int64, b int64) (r *SumReply, err error) {
var _args0 AddServiceSumArgs
_args0.A = a
_args0.B = b
var _result1 AddServiceSumResult
if err = p.Client_().Call(ctx, "Sum", &_args0, &_result1); err != nil {
return
}
return _result1.GetSuccess(), nil
}
// Parameters:
// - A
// - B
func (p *AddServiceClient) Concat(ctx context.Context, a string, b string) (r *ConcatReply, err error) {
var _args2 AddServiceConcatArgs
_args2.A = a
_args2.B = b
var _result3 AddServiceConcatResult
if err = p.Client_().Call(ctx, "Concat", &_args2, &_result3); err != nil {
return
}
return _result3.GetSuccess(), nil
}
type AddServiceProcessor struct {
processorMap map[string]thrift.TProcessorFunction
handler AddService
}
func (p *AddServiceProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) {
p.processorMap[key] = processor
}
func (p *AddServiceProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) {
processor, ok = p.processorMap[key]
return processor, ok
}
func (p *AddServiceProcessor) ProcessorMap() map[string]thrift.TProcessorFunction {
return p.processorMap
}
func NewAddServiceProcessor(handler AddService) *AddServiceProcessor {
self4 := &AddServiceProcessor{handler:handler, processorMap:make(map[string]thrift.TProcessorFunction)}
self4.processorMap["Sum"] = &addServiceProcessorSum{handler:handler}
self4.processorMap["Concat"] = &addServiceProcessorConcat{handler:handler}
return self4
}
func (p *AddServiceProcessor) Process(ctx context.Context, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
name, _, seqId, err := iprot.ReadMessageBegin()
if err != nil { return false, err }
if processor, ok := p.GetProcessorFunction(name); ok {
return processor.Process(ctx, seqId, iprot, oprot)
}
iprot.Skip(thrift.STRUCT)
iprot.ReadMessageEnd()
x5 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function " + name)
oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId)
x5.Write(oprot)
oprot.WriteMessageEnd()
oprot.Flush(ctx)
return false, x5
}
type addServiceProcessorSum struct {
handler AddService
}
func (p *addServiceProcessorSum) Process(ctx context.Context, seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
args := AddServiceSumArgs{}
if err = args.Read(iprot); err != nil {
iprot.ReadMessageEnd()
x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error())
oprot.WriteMessageBegin("Sum", thrift.EXCEPTION, seqId)
x.Write(oprot)
oprot.WriteMessageEnd()
oprot.Flush(ctx)
return false, err
}
iprot.ReadMessageEnd()
result := AddServiceSumResult{}
var retval *SumReply
var err2 error
if retval, err2 = p.handler.Sum(ctx, args.A, args.B); err2 != nil {
x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing Sum: " + err2.Error())
oprot.WriteMessageBegin("Sum", thrift.EXCEPTION, seqId)
x.Write(oprot)
oprot.WriteMessageEnd()
oprot.Flush(ctx)
return true, err2
} else {
result.Success = retval
}
if err2 = oprot.WriteMessageBegin("Sum", thrift.REPLY, seqId); err2 != nil {
err = err2
}
if err2 = result.Write(oprot); err == nil && err2 != nil {
err = err2
}
if err2 = oprot.WriteMessageEnd(); err == nil && err2 != nil {
err = err2
}
if err2 = oprot.Flush(ctx); err == nil && err2 != nil {
err = err2
}
if err != nil {
return
}
return true, err
}
type addServiceProcessorConcat struct {
handler AddService
}
func (p *addServiceProcessorConcat) Process(ctx context.Context, seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
args := AddServiceConcatArgs{}
if err = args.Read(iprot); err != nil {
iprot.ReadMessageEnd()
x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error())
oprot.WriteMessageBegin("Concat", thrift.EXCEPTION, seqId)
x.Write(oprot)
oprot.WriteMessageEnd()
oprot.Flush(ctx)
return false, err
}
iprot.ReadMessageEnd()
result := AddServiceConcatResult{}
var retval *ConcatReply
var err2 error
if retval, err2 = p.handler.Concat(ctx, args.A, args.B); err2 != nil {
x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing Concat: " + err2.Error())
oprot.WriteMessageBegin("Concat", thrift.EXCEPTION, seqId)
x.Write(oprot)
oprot.WriteMessageEnd()
oprot.Flush(ctx)
return true, err2
} else {
result.Success = retval
}
if err2 = oprot.WriteMessageBegin("Concat", thrift.REPLY, seqId); err2 != nil {
err = err2
}
if err2 = result.Write(oprot); err == nil && err2 != nil {
err = err2
}
if err2 = oprot.WriteMessageEnd(); err == nil && err2 != nil {
err = err2
}
if err2 = oprot.Flush(ctx); err == nil && err2 != nil {
err = err2
}
if err != nil {
return
}
return true, err
}
// HELPER FUNCTIONS AND STRUCTURES
// Attributes:
// - A
// - B
type AddServiceSumArgs struct {
A int64 `thrift:"a,1" db:"a" json:"a"`
B int64 `thrift:"b,2" db:"b" json:"b"`
}
func NewAddServiceSumArgs() *AddServiceSumArgs {
return &AddServiceSumArgs{}
}
func (p *AddServiceSumArgs) GetA() int64 {
return p.A
}
func (p *AddServiceSumArgs) GetB() int64 {
return p.B
}
func (p *AddServiceSumArgs) Read(iprot thrift.TProtocol) error {
if _, err := iprot.ReadStructBegin(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
}
for {
_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
if err != nil {
return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
}
if fieldTypeId == thrift.STOP { break; }
switch fieldId {
case 1:
if fieldTypeId == thrift.I64 {
if err := p.ReadField1(iprot); err != nil {
return err
}
} else {
if err := iprot.Skip(fieldTypeId); err != nil {
return err
}
}
case 2:
if fieldTypeId == thrift.I64 {
if err := p.ReadField2(iprot); err != nil {
return err
}
} else {
if err := iprot.Skip(fieldTypeId); err != nil {
return err
}
}
default:
if err := iprot.Skip(fieldTypeId); err != nil {
return err
}
}
if err := iprot.ReadFieldEnd(); err != nil {
return err
}
}
if err := iprot.ReadStructEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
return nil
}
func (p *AddServiceSumArgs) ReadField1(iprot thrift.TProtocol) error {
if v, err := iprot.ReadI64(); err != nil {
return thrift.PrependError("error reading field 1: ", err)
} else {
p.A = v
}
return nil
}
func (p *AddServiceSumArgs) ReadField2(iprot thrift.TProtocol) error {
if v, err := iprot.ReadI64(); err != nil {
return thrift.PrependError("error reading field 2: ", err)
} else {
p.B = v
}
return nil
}
func (p *AddServiceSumArgs) Write(oprot thrift.TProtocol) error {
if err := oprot.WriteStructBegin("Sum_args"); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) }
if p != nil {
if err := p.writeField1(oprot); err != nil { return err }
if err := p.writeField2(oprot); err != nil { return err }
}
if err := oprot.WriteFieldStop(); err != nil {
return thrift.PrependError("write field stop error: ", err) }
if err := oprot.WriteStructEnd(); err != nil {
return thrift.PrependError("write struct stop error: ", err) }
return nil
}
func (p *AddServiceSumArgs) writeField1(oprot thrift.TProtocol) (err error) {
if err := oprot.WriteFieldBegin("a", thrift.I64, 1); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:a: ", p), err) }
if err := oprot.WriteI64(int64(p.A)); err != nil {
return thrift.PrependError(fmt.Sprintf("%T.a (1) field write error: ", p), err) }
if err := oprot.WriteFieldEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field end error 1:a: ", p), err) }
return err
}
func (p *AddServiceSumArgs) writeField2(oprot thrift.TProtocol) (err error) {
if err := oprot.WriteFieldBegin("b", thrift.I64, 2); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:b: ", p), err) }
if err := oprot.WriteI64(int64(p.B)); err != nil {
return thrift.PrependError(fmt.Sprintf("%T.b (2) field write error: ", p), err) }
if err := oprot.WriteFieldEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field end error 2:b: ", p), err) }
return err
}
func (p *AddServiceSumArgs) String() string {
if p == nil {
return ""
}
return fmt.Sprintf("AddServiceSumArgs(%+v)", *p)
}
// Attributes:
// - Success
type AddServiceSumResult struct {
Success *SumReply `thrift:"success,0" db:"success" json:"success,omitempty"`
}
func NewAddServiceSumResult() *AddServiceSumResult {
return &AddServiceSumResult{}
}
var AddServiceSumResult_Success_DEFAULT *SumReply
func (p *AddServiceSumResult) GetSuccess() *SumReply {
if !p.IsSetSuccess() {
return AddServiceSumResult_Success_DEFAULT
}
return p.Success
}
func (p *AddServiceSumResult) IsSetSuccess() bool {
return p.Success != nil
}
func (p *AddServiceSumResult) Read(iprot thrift.TProtocol) error {
if _, err := iprot.ReadStructBegin(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
}
for {
_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
if err != nil {
return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
}
if fieldTypeId == thrift.STOP { break; }
switch fieldId {
case 0:
if fieldTypeId == thrift.STRUCT {
if err := p.ReadField0(iprot); err != nil {
return err
}
} else {
if err := iprot.Skip(fieldTypeId); err != nil {
return err
}
}
default:
if err := iprot.Skip(fieldTypeId); err != nil {
return err
}
}
if err := iprot.ReadFieldEnd(); err != nil {
return err
}
}
if err := iprot.ReadStructEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
return nil
}
func (p *AddServiceSumResult) ReadField0(iprot thrift.TProtocol) error {
p.Success = &SumReply{}
if err := p.Success.Read(iprot); err != nil {
return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Success), err)
}
return nil
}
func (p *AddServiceSumResult) Write(oprot thrift.TProtocol) error {
if err := oprot.WriteStructBegin("Sum_result"); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) }
if p != nil {
if err := p.writeField0(oprot); err != nil { return err }
}
if err := oprot.WriteFieldStop(); err != nil {
return thrift.PrependError("write field stop error: ", err) }
if err := oprot.WriteStructEnd(); err != nil {
return thrift.PrependError("write struct stop error: ", err) }
return nil
}
func (p *AddServiceSumResult) writeField0(oprot thrift.TProtocol) (err error) {
if p.IsSetSuccess() {
if err := oprot.WriteFieldBegin("success", thrift.STRUCT, 0); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field begin error 0:success: ", p), err) }
if err := p.Success.Write(oprot); err != nil {
return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Success), err)
}
if err := oprot.WriteFieldEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field end error 0:success: ", p), err) }
}
return err
}
func (p *AddServiceSumResult) String() string {
if p == nil {
return ""
}
return fmt.Sprintf("AddServiceSumResult(%+v)", *p)
}
// Attributes:
// - A
// - B
type AddServiceConcatArgs struct {
A string `thrift:"a,1" db:"a" json:"a"`
B string `thrift:"b,2" db:"b" json:"b"`
}
func NewAddServiceConcatArgs() *AddServiceConcatArgs {
return &AddServiceConcatArgs{}
}
func (p *AddServiceConcatArgs) GetA() string {
return p.A
}
func (p *AddServiceConcatArgs) GetB() string {
return p.B
}
func (p *AddServiceConcatArgs) Read(iprot thrift.TProtocol) error {
if _, err := iprot.ReadStructBegin(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
}
for {
_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
if err != nil {
return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
}
if fieldTypeId == thrift.STOP { break; }
switch fieldId {
case 1:
if fieldTypeId == thrift.STRING {
if err := p.ReadField1(iprot); err != nil {
return err
}
} else {
if err := iprot.Skip(fieldTypeId); err != nil {
return err
}
}
case 2:
if fieldTypeId == thrift.STRING {
if err := p.ReadField2(iprot); err != nil {
return err
}
} else {
if err := iprot.Skip(fieldTypeId); err != nil {
return err
}
}
default:
if err := iprot.Skip(fieldTypeId); err != nil {
return err
}
}
if err := iprot.ReadFieldEnd(); err != nil {
return err
}
}
if err := iprot.ReadStructEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
return nil
}
func (p *AddServiceConcatArgs) ReadField1(iprot thrift.TProtocol) error {
if v, err := iprot.ReadString(); err != nil {
return thrift.PrependError("error reading field 1: ", err)
} else {
p.A = v
}
return nil
}
func (p *AddServiceConcatArgs) ReadField2(iprot thrift.TProtocol) error {
if v, err := iprot.ReadString(); err != nil {
return thrift.PrependError("error reading field 2: ", err)
} else {
p.B = v
}
return nil
}
func (p *AddServiceConcatArgs) Write(oprot thrift.TProtocol) error {
if err := oprot.WriteStructBegin("Concat_args"); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) }
if p != nil {
if err := p.writeField1(oprot); err != nil { return err }
if err := p.writeField2(oprot); err != nil { return err }
}
if err := oprot.WriteFieldStop(); err != nil {
return thrift.PrependError("write field stop error: ", err) }
if err := oprot.WriteStructEnd(); err != nil {
return thrift.PrependError("write struct stop error: ", err) }
return nil
}
func (p *AddServiceConcatArgs) writeField1(oprot thrift.TProtocol) (err error) {
if err := oprot.WriteFieldBegin("a", thrift.STRING, 1); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:a: ", p), err) }
if err := oprot.WriteString(string(p.A)); err != nil {
return thrift.PrependError(fmt.Sprintf("%T.a (1) field write error: ", p), err) }
if err := oprot.WriteFieldEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field end error 1:a: ", p), err) }
return err
}
func (p *AddServiceConcatArgs) writeField2(oprot thrift.TProtocol) (err error) {
if err := oprot.WriteFieldBegin("b", thrift.STRING, 2); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:b: ", p), err) }
if err := oprot.WriteString(string(p.B)); err != nil {
return thrift.PrependError(fmt.Sprintf("%T.b (2) field write error: ", p), err) }
if err := oprot.WriteFieldEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field end error 2:b: ", p), err) }
return err
}
func (p *AddServiceConcatArgs) String() string {
if p == nil {
return ""
}
return fmt.Sprintf("AddServiceConcatArgs(%+v)", *p)
}
// Attributes:
// - Success
type AddServiceConcatResult struct {
Success *ConcatReply `thrift:"success,0" db:"success" json:"success,omitempty"`
}
func NewAddServiceConcatResult() *AddServiceConcatResult {
return &AddServiceConcatResult{}
}
var AddServiceConcatResult_Success_DEFAULT *ConcatReply
func (p *AddServiceConcatResult) GetSuccess() *ConcatReply {
if !p.IsSetSuccess() {
return AddServiceConcatResult_Success_DEFAULT
}
return p.Success
}
func (p *AddServiceConcatResult) IsSetSuccess() bool {
return p.Success != nil
}
func (p *AddServiceConcatResult) Read(iprot thrift.TProtocol) error {
if _, err := iprot.ReadStructBegin(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
}
for {
_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
if err != nil {
return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
}
if fieldTypeId == thrift.STOP { break; }
switch fieldId {
case 0:
if fieldTypeId == thrift.STRUCT {
if err := p.ReadField0(iprot); err != nil {
return err
}
} else {
if err := iprot.Skip(fieldTypeId); err != nil {
return err
}
}
default:
if err := iprot.Skip(fieldTypeId); err != nil {
return err
}
}
if err := iprot.ReadFieldEnd(); err != nil {
return err
}
}
if err := iprot.ReadStructEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
return nil
}
func (p *AddServiceConcatResult) ReadField0(iprot thrift.TProtocol) error {
p.Success = &ConcatReply{}
if err := p.Success.Read(iprot); err != nil {
return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Success), err)
}
return nil
}
func (p *AddServiceConcatResult) Write(oprot thrift.TProtocol) error {
if err := oprot.WriteStructBegin("Concat_result"); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) }
if p != nil {
if err := p.writeField0(oprot); err != nil { return err }
}
if err := oprot.WriteFieldStop(); err != nil {
return thrift.PrependError("write field stop error: ", err) }
if err := oprot.WriteStructEnd(); err != nil {
return thrift.PrependError("write struct stop error: ", err) }
return nil
}
func (p *AddServiceConcatResult) writeField0(oprot thrift.TProtocol) (err error) {
if p.IsSetSuccess() {
if err := oprot.WriteFieldBegin("success", thrift.STRUCT, 0); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field begin error 0:success: ", p), err) }
if err := p.Success.Write(oprot); err != nil {
return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Success), err)
}
if err := oprot.WriteFieldEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field end error 0:success: ", p), err) }
}
return err
}
func (p *AddServiceConcatResult) String() string {
if p == nil {
return ""
}
return fmt.Sprintf("AddServiceConcatResult(%+v)", *p)
}
golang-github-go-kit-kit-0.10.0/examples/apigateway/ 0000775 0000000 0000000 00000000000 13622563124 0022251 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/apigateway/main.go 0000664 0000000 0000000 00000022114 13622563124 0023524 0 ustar 00root root 0000000 0000000 package main
import (
"bytes"
"context"
"encoding/json"
"flag"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"os"
"os/signal"
"strings"
"syscall"
"time"
consulsd "github.com/go-kit/kit/sd/consul"
"github.com/gorilla/mux"
"github.com/hashicorp/consul/api"
stdopentracing "github.com/opentracing/opentracing-go"
stdzipkin "github.com/openzipkin/zipkin-go"
"google.golang.org/grpc"
"github.com/go-kit/kit/endpoint"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/sd"
"github.com/go-kit/kit/sd/lb"
httptransport "github.com/go-kit/kit/transport/http"
"github.com/go-kit/kit/examples/addsvc/pkg/addendpoint"
"github.com/go-kit/kit/examples/addsvc/pkg/addservice"
"github.com/go-kit/kit/examples/addsvc/pkg/addtransport"
)
func main() {
var (
httpAddr = flag.String("http.addr", ":8000", "Address for HTTP (JSON) server")
consulAddr = flag.String("consul.addr", "", "Consul agent address")
retryMax = flag.Int("retry.max", 3, "per-request retries to different instances")
retryTimeout = flag.Duration("retry.timeout", 500*time.Millisecond, "per-request timeout, including retries")
)
flag.Parse()
// Logging domain.
var logger log.Logger
{
logger = log.NewLogfmtLogger(os.Stderr)
logger = log.With(logger, "ts", log.DefaultTimestampUTC)
logger = log.With(logger, "caller", log.DefaultCaller)
}
// Service discovery domain. In this example we use Consul.
var client consulsd.Client
{
consulConfig := api.DefaultConfig()
if len(*consulAddr) > 0 {
consulConfig.Address = *consulAddr
}
consulClient, err := api.NewClient(consulConfig)
if err != nil {
logger.Log("err", err)
os.Exit(1)
}
client = consulsd.NewClient(consulClient)
}
// Transport domain.
tracer := stdopentracing.GlobalTracer() // no-op
zipkinTracer, _ := stdzipkin.NewTracer(nil, stdzipkin.WithNoopTracer(true))
ctx := context.Background()
r := mux.NewRouter()
// Now we begin installing the routes. Each route corresponds to a single
// method: sum, concat, uppercase, and count.
// addsvc routes.
{
// Each method gets constructed with a factory. Factories take an
// instance string, and return a specific endpoint. In the factory we
// dial the instance string we get from Consul, and then leverage an
// addsvc client package to construct a complete service. We can then
// leverage the addsvc.Make{Sum,Concat}Endpoint constructors to convert
// the complete service to specific endpoint.
var (
tags = []string{}
passingOnly = true
endpoints = addendpoint.Set{}
instancer = consulsd.NewInstancer(client, logger, "addsvc", tags, passingOnly)
)
{
factory := addsvcFactory(addendpoint.MakeSumEndpoint, tracer, zipkinTracer, logger)
endpointer := sd.NewEndpointer(instancer, factory, logger)
balancer := lb.NewRoundRobin(endpointer)
retry := lb.Retry(*retryMax, *retryTimeout, balancer)
endpoints.SumEndpoint = retry
}
{
factory := addsvcFactory(addendpoint.MakeConcatEndpoint, tracer, zipkinTracer, logger)
endpointer := sd.NewEndpointer(instancer, factory, logger)
balancer := lb.NewRoundRobin(endpointer)
retry := lb.Retry(*retryMax, *retryTimeout, balancer)
endpoints.ConcatEndpoint = retry
}
// Here we leverage the fact that addsvc comes with a constructor for an
// HTTP handler, and just install it under a particular path prefix in
// our router.
r.PathPrefix("/addsvc").Handler(http.StripPrefix("/addsvc", addtransport.NewHTTPHandler(endpoints, tracer, zipkinTracer, logger)))
}
// stringsvc routes.
{
// addsvc had lots of nice importable Go packages we could leverage.
// With stringsvc we are not so fortunate, it just has some endpoints
// that we assume will exist. So we have to write that logic here. This
// is by design, so you can see two totally different methods of
// proxying to a remote service.
var (
tags = []string{}
passingOnly = true
uppercase endpoint.Endpoint
count endpoint.Endpoint
instancer = consulsd.NewInstancer(client, logger, "stringsvc", tags, passingOnly)
)
{
factory := stringsvcFactory(ctx, "GET", "/uppercase")
endpointer := sd.NewEndpointer(instancer, factory, logger)
balancer := lb.NewRoundRobin(endpointer)
retry := lb.Retry(*retryMax, *retryTimeout, balancer)
uppercase = retry
}
{
factory := stringsvcFactory(ctx, "GET", "/count")
endpointer := sd.NewEndpointer(instancer, factory, logger)
balancer := lb.NewRoundRobin(endpointer)
retry := lb.Retry(*retryMax, *retryTimeout, balancer)
count = retry
}
// We can use the transport/http.Server to act as our handler, all we
// have to do provide it with the encode and decode functions for our
// stringsvc methods.
r.Handle("/stringsvc/uppercase", httptransport.NewServer(uppercase, decodeUppercaseRequest, encodeJSONResponse))
r.Handle("/stringsvc/count", httptransport.NewServer(count, decodeCountRequest, encodeJSONResponse))
}
// Interrupt handler.
errc := make(chan error)
go func() {
c := make(chan os.Signal)
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
errc <- fmt.Errorf("%s", <-c)
}()
// HTTP transport.
go func() {
logger.Log("transport", "HTTP", "addr", *httpAddr)
errc <- http.ListenAndServe(*httpAddr, r)
}()
// Run!
logger.Log("exit", <-errc)
}
func addsvcFactory(makeEndpoint func(addservice.Service) endpoint.Endpoint, tracer stdopentracing.Tracer, zipkinTracer *stdzipkin.Tracer, logger log.Logger) sd.Factory {
return func(instance string) (endpoint.Endpoint, io.Closer, error) {
// We could just as easily use the HTTP or Thrift client package to make
// the connection to addsvc. We've chosen gRPC arbitrarily. Note that
// the transport is an implementation detail: it doesn't leak out of
// this function. Nice!
conn, err := grpc.Dial(instance, grpc.WithInsecure())
if err != nil {
return nil, nil, err
}
service := addtransport.NewGRPCClient(conn, tracer, zipkinTracer, logger)
endpoint := makeEndpoint(service)
// Notice that the addsvc gRPC client converts the connection to a
// complete addsvc, and we just throw away everything except the method
// we're interested in. A smarter factory would mux multiple methods
// over the same connection. But that would require more work to manage
// the returned io.Closer, e.g. reference counting. Since this is for
// the purposes of demonstration, we'll just keep it simple.
return endpoint, conn, nil
}
}
func stringsvcFactory(ctx context.Context, method, path string) sd.Factory {
return func(instance string) (endpoint.Endpoint, io.Closer, error) {
if !strings.HasPrefix(instance, "http") {
instance = "http://" + instance
}
tgt, err := url.Parse(instance)
if err != nil {
return nil, nil, err
}
tgt.Path = path
// Since stringsvc doesn't have any kind of package we can import, or
// any formal spec, we are forced to just assert where the endpoints
// live, and write our own code to encode and decode requests and
// responses. Ideally, if you write the service, you will want to
// provide stronger guarantees to your clients.
var (
enc httptransport.EncodeRequestFunc
dec httptransport.DecodeResponseFunc
)
switch path {
case "/uppercase":
enc, dec = encodeJSONRequest, decodeUppercaseResponse
case "/count":
enc, dec = encodeJSONRequest, decodeCountResponse
default:
return nil, nil, fmt.Errorf("unknown stringsvc path %q", path)
}
return httptransport.NewClient(method, tgt, enc, dec).Endpoint(), nil, nil
}
}
func encodeJSONRequest(_ context.Context, req *http.Request, request interface{}) error {
// Both uppercase and count requests are encoded in the same way:
// simple JSON serialization to the request body.
var buf bytes.Buffer
if err := json.NewEncoder(&buf).Encode(request); err != nil {
return err
}
req.Body = ioutil.NopCloser(&buf)
return nil
}
func encodeJSONResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
// I've just copied these functions from stringsvc3/transport.go, inlining the
// struct definitions.
func decodeUppercaseResponse(ctx context.Context, resp *http.Response) (interface{}, error) {
var response struct {
V string `json:"v"`
Err string `json:"err,omitempty"`
}
if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
return nil, err
}
return response, nil
}
func decodeCountResponse(ctx context.Context, resp *http.Response) (interface{}, error) {
var response struct {
V int `json:"v"`
}
if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
return nil, err
}
return response, nil
}
func decodeUppercaseRequest(ctx context.Context, req *http.Request) (interface{}, error) {
var request struct {
S string `json:"s"`
}
if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
return nil, err
}
return request, nil
}
func decodeCountRequest(ctx context.Context, req *http.Request) (interface{}, error) {
var request struct {
S string `json:"s"`
}
if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
return nil, err
}
return request, nil
}
golang-github-go-kit-kit-0.10.0/examples/profilesvc/ 0000775 0000000 0000000 00000000000 13622563124 0022272 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/profilesvc/README.md 0000664 0000000 0000000 00000001242 13622563124 0023550 0 ustar 00root root 0000000 0000000 # profilesvc
This example demonstrates how to use Go kit to implement a REST-y HTTP service.
It leverages the excellent [gorilla mux package](https://github.com/gorilla/mux) for routing.
Run the example with the optional port address for the service:
```bash
$ go run ./cmd/profilesvc/main.go -http.addr :8080
ts=2018-05-01T16:13:12.849086255Z caller=main.go:47 transport=HTTP addr=:8080
```
Create a Profile:
```bash
$ curl -d '{"id":"1234","Name":"Go Kit"}' -H "Content-Type: application/json" -X POST http://localhost:8080/profiles/
{}
```
Get the profile you just created
```bash
$ curl localhost:8080/profiles/1234
{"profile":{"id":"1234","name":"Go Kit"}}
```
golang-github-go-kit-kit-0.10.0/examples/profilesvc/client/ 0000775 0000000 0000000 00000000000 13622563124 0023550 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/profilesvc/client/client.go 0000664 0000000 0000000 00000007713 13622563124 0025365 0 ustar 00root root 0000000 0000000 // Package client provides a profilesvc client based on a predefined Consul
// service name and relevant tags. Users must only provide the address of a
// Consul server.
package client
import (
"io"
"time"
consulapi "github.com/hashicorp/consul/api"
"github.com/go-kit/kit/endpoint"
"github.com/go-kit/kit/examples/profilesvc"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/sd"
"github.com/go-kit/kit/sd/consul"
"github.com/go-kit/kit/sd/lb"
)
// New returns a service that's load-balanced over instances of profilesvc found
// in the provided Consul server. The mechanism of looking up profilesvc
// instances in Consul is hard-coded into the client.
func New(consulAddr string, logger log.Logger) (profilesvc.Service, error) {
apiclient, err := consulapi.NewClient(&consulapi.Config{
Address: consulAddr,
})
if err != nil {
return nil, err
}
// As the implementer of profilesvc, we declare and enforce these
// parameters for all of the profilesvc consumers.
var (
consulService = "profilesvc"
consulTags = []string{"prod"}
passingOnly = true
retryMax = 3
retryTimeout = 500 * time.Millisecond
)
var (
sdclient = consul.NewClient(apiclient)
instancer = consul.NewInstancer(sdclient, logger, consulService, consulTags, passingOnly)
endpoints profilesvc.Endpoints
)
{
factory := factoryFor(profilesvc.MakePostProfileEndpoint)
endpointer := sd.NewEndpointer(instancer, factory, logger)
balancer := lb.NewRoundRobin(endpointer)
retry := lb.Retry(retryMax, retryTimeout, balancer)
endpoints.PostProfileEndpoint = retry
}
{
factory := factoryFor(profilesvc.MakeGetProfileEndpoint)
endpointer := sd.NewEndpointer(instancer, factory, logger)
balancer := lb.NewRoundRobin(endpointer)
retry := lb.Retry(retryMax, retryTimeout, balancer)
endpoints.GetProfileEndpoint = retry
}
{
factory := factoryFor(profilesvc.MakePutProfileEndpoint)
endpointer := sd.NewEndpointer(instancer, factory, logger)
balancer := lb.NewRoundRobin(endpointer)
retry := lb.Retry(retryMax, retryTimeout, balancer)
endpoints.PutProfileEndpoint = retry
}
{
factory := factoryFor(profilesvc.MakePatchProfileEndpoint)
endpointer := sd.NewEndpointer(instancer, factory, logger)
balancer := lb.NewRoundRobin(endpointer)
retry := lb.Retry(retryMax, retryTimeout, balancer)
endpoints.PatchProfileEndpoint = retry
}
{
factory := factoryFor(profilesvc.MakeDeleteProfileEndpoint)
endpointer := sd.NewEndpointer(instancer, factory, logger)
balancer := lb.NewRoundRobin(endpointer)
retry := lb.Retry(retryMax, retryTimeout, balancer)
endpoints.DeleteProfileEndpoint = retry
}
{
factory := factoryFor(profilesvc.MakeGetAddressesEndpoint)
endpointer := sd.NewEndpointer(instancer, factory, logger)
balancer := lb.NewRoundRobin(endpointer)
retry := lb.Retry(retryMax, retryTimeout, balancer)
endpoints.GetAddressesEndpoint = retry
}
{
factory := factoryFor(profilesvc.MakeGetAddressEndpoint)
endpointer := sd.NewEndpointer(instancer, factory, logger)
balancer := lb.NewRoundRobin(endpointer)
retry := lb.Retry(retryMax, retryTimeout, balancer)
endpoints.GetAddressEndpoint = retry
}
{
factory := factoryFor(profilesvc.MakePostAddressEndpoint)
endpointer := sd.NewEndpointer(instancer, factory, logger)
balancer := lb.NewRoundRobin(endpointer)
retry := lb.Retry(retryMax, retryTimeout, balancer)
endpoints.PostAddressEndpoint = retry
}
{
factory := factoryFor(profilesvc.MakeDeleteAddressEndpoint)
endpointer := sd.NewEndpointer(instancer, factory, logger)
balancer := lb.NewRoundRobin(endpointer)
retry := lb.Retry(retryMax, retryTimeout, balancer)
endpoints.DeleteAddressEndpoint = retry
}
return endpoints, nil
}
func factoryFor(makeEndpoint func(profilesvc.Service) endpoint.Endpoint) sd.Factory {
return func(instance string) (endpoint.Endpoint, io.Closer, error) {
service, err := profilesvc.MakeClientEndpoints(instance)
if err != nil {
return nil, nil, err
}
return makeEndpoint(service), nil, nil
}
}
golang-github-go-kit-kit-0.10.0/examples/profilesvc/cmd/ 0000775 0000000 0000000 00000000000 13622563124 0023035 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/profilesvc/cmd/profilesvc/ 0000775 0000000 0000000 00000000000 13622563124 0025211 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/profilesvc/cmd/profilesvc/main.go 0000664 0000000 0000000 00000001716 13622563124 0026471 0 ustar 00root root 0000000 0000000 package main
import (
"flag"
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"github.com/go-kit/kit/examples/profilesvc"
"github.com/go-kit/kit/log"
)
func main() {
var (
httpAddr = flag.String("http.addr", ":8080", "HTTP listen address")
)
flag.Parse()
var logger log.Logger
{
logger = log.NewLogfmtLogger(os.Stderr)
logger = log.With(logger, "ts", log.DefaultTimestampUTC)
logger = log.With(logger, "caller", log.DefaultCaller)
}
var s profilesvc.Service
{
s = profilesvc.NewInmemService()
s = profilesvc.LoggingMiddleware(logger)(s)
}
var h http.Handler
{
h = profilesvc.MakeHTTPHandler(s, log.With(logger, "component", "HTTP"))
}
errs := make(chan error)
go func() {
c := make(chan os.Signal)
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
errs <- fmt.Errorf("%s", <-c)
}()
go func() {
logger.Log("transport", "HTTP", "addr", *httpAddr)
errs <- http.ListenAndServe(*httpAddr, h)
}()
logger.Log("exit", <-errs)
}
golang-github-go-kit-kit-0.10.0/examples/profilesvc/endpoints.go 0000664 0000000 0000000 00000032360 13622563124 0024630 0 ustar 00root root 0000000 0000000 package profilesvc
import (
"context"
"net/url"
"strings"
"github.com/go-kit/kit/endpoint"
httptransport "github.com/go-kit/kit/transport/http"
)
// Endpoints collects all of the endpoints that compose a profile service. It's
// meant to be used as a helper struct, to collect all of the endpoints into a
// single parameter.
//
// In a server, it's useful for functions that need to operate on a per-endpoint
// basis. For example, you might pass an Endpoints to a function that produces
// an http.Handler, with each method (endpoint) wired up to a specific path. (It
// is probably a mistake in design to invoke the Service methods on the
// Endpoints struct in a server.)
//
// In a client, it's useful to collect individually constructed endpoints into a
// single type that implements the Service interface. For example, you might
// construct individual endpoints using transport/http.NewClient, combine them
// into an Endpoints, and return it to the caller as a Service.
type Endpoints struct {
PostProfileEndpoint endpoint.Endpoint
GetProfileEndpoint endpoint.Endpoint
PutProfileEndpoint endpoint.Endpoint
PatchProfileEndpoint endpoint.Endpoint
DeleteProfileEndpoint endpoint.Endpoint
GetAddressesEndpoint endpoint.Endpoint
GetAddressEndpoint endpoint.Endpoint
PostAddressEndpoint endpoint.Endpoint
DeleteAddressEndpoint endpoint.Endpoint
}
// MakeServerEndpoints returns an Endpoints struct where each endpoint invokes
// the corresponding method on the provided service. Useful in a profilesvc
// server.
func MakeServerEndpoints(s Service) Endpoints {
return Endpoints{
PostProfileEndpoint: MakePostProfileEndpoint(s),
GetProfileEndpoint: MakeGetProfileEndpoint(s),
PutProfileEndpoint: MakePutProfileEndpoint(s),
PatchProfileEndpoint: MakePatchProfileEndpoint(s),
DeleteProfileEndpoint: MakeDeleteProfileEndpoint(s),
GetAddressesEndpoint: MakeGetAddressesEndpoint(s),
GetAddressEndpoint: MakeGetAddressEndpoint(s),
PostAddressEndpoint: MakePostAddressEndpoint(s),
DeleteAddressEndpoint: MakeDeleteAddressEndpoint(s),
}
}
// MakeClientEndpoints returns an Endpoints struct where each endpoint invokes
// the corresponding method on the remote instance, via a transport/http.Client.
// Useful in a profilesvc client.
func MakeClientEndpoints(instance string) (Endpoints, error) {
if !strings.HasPrefix(instance, "http") {
instance = "http://" + instance
}
tgt, err := url.Parse(instance)
if err != nil {
return Endpoints{}, err
}
tgt.Path = ""
options := []httptransport.ClientOption{}
// Note that the request encoders need to modify the request URL, changing
// the path. That's fine: we simply need to provide specific encoders for
// each endpoint.
return Endpoints{
PostProfileEndpoint: httptransport.NewClient("POST", tgt, encodePostProfileRequest, decodePostProfileResponse, options...).Endpoint(),
GetProfileEndpoint: httptransport.NewClient("GET", tgt, encodeGetProfileRequest, decodeGetProfileResponse, options...).Endpoint(),
PutProfileEndpoint: httptransport.NewClient("PUT", tgt, encodePutProfileRequest, decodePutProfileResponse, options...).Endpoint(),
PatchProfileEndpoint: httptransport.NewClient("PATCH", tgt, encodePatchProfileRequest, decodePatchProfileResponse, options...).Endpoint(),
DeleteProfileEndpoint: httptransport.NewClient("DELETE", tgt, encodeDeleteProfileRequest, decodeDeleteProfileResponse, options...).Endpoint(),
GetAddressesEndpoint: httptransport.NewClient("GET", tgt, encodeGetAddressesRequest, decodeGetAddressesResponse, options...).Endpoint(),
GetAddressEndpoint: httptransport.NewClient("GET", tgt, encodeGetAddressRequest, decodeGetAddressResponse, options...).Endpoint(),
PostAddressEndpoint: httptransport.NewClient("POST", tgt, encodePostAddressRequest, decodePostAddressResponse, options...).Endpoint(),
DeleteAddressEndpoint: httptransport.NewClient("DELETE", tgt, encodeDeleteAddressRequest, decodeDeleteAddressResponse, options...).Endpoint(),
}, nil
}
// PostProfile implements Service. Primarily useful in a client.
func (e Endpoints) PostProfile(ctx context.Context, p Profile) error {
request := postProfileRequest{Profile: p}
response, err := e.PostProfileEndpoint(ctx, request)
if err != nil {
return err
}
resp := response.(postProfileResponse)
return resp.Err
}
// GetProfile implements Service. Primarily useful in a client.
func (e Endpoints) GetProfile(ctx context.Context, id string) (Profile, error) {
request := getProfileRequest{ID: id}
response, err := e.GetProfileEndpoint(ctx, request)
if err != nil {
return Profile{}, err
}
resp := response.(getProfileResponse)
return resp.Profile, resp.Err
}
// PutProfile implements Service. Primarily useful in a client.
func (e Endpoints) PutProfile(ctx context.Context, id string, p Profile) error {
request := putProfileRequest{ID: id, Profile: p}
response, err := e.PutProfileEndpoint(ctx, request)
if err != nil {
return err
}
resp := response.(putProfileResponse)
return resp.Err
}
// PatchProfile implements Service. Primarily useful in a client.
func (e Endpoints) PatchProfile(ctx context.Context, id string, p Profile) error {
request := patchProfileRequest{ID: id, Profile: p}
response, err := e.PatchProfileEndpoint(ctx, request)
if err != nil {
return err
}
resp := response.(patchProfileResponse)
return resp.Err
}
// DeleteProfile implements Service. Primarily useful in a client.
func (e Endpoints) DeleteProfile(ctx context.Context, id string) error {
request := deleteProfileRequest{ID: id}
response, err := e.DeleteProfileEndpoint(ctx, request)
if err != nil {
return err
}
resp := response.(deleteProfileResponse)
return resp.Err
}
// GetAddresses implements Service. Primarily useful in a client.
func (e Endpoints) GetAddresses(ctx context.Context, profileID string) ([]Address, error) {
request := getAddressesRequest{ProfileID: profileID}
response, err := e.GetAddressesEndpoint(ctx, request)
if err != nil {
return nil, err
}
resp := response.(getAddressesResponse)
return resp.Addresses, resp.Err
}
// GetAddress implements Service. Primarily useful in a client.
func (e Endpoints) GetAddress(ctx context.Context, profileID string, addressID string) (Address, error) {
request := getAddressRequest{ProfileID: profileID, AddressID: addressID}
response, err := e.GetAddressEndpoint(ctx, request)
if err != nil {
return Address{}, err
}
resp := response.(getAddressResponse)
return resp.Address, resp.Err
}
// PostAddress implements Service. Primarily useful in a client.
func (e Endpoints) PostAddress(ctx context.Context, profileID string, a Address) error {
request := postAddressRequest{ProfileID: profileID, Address: a}
response, err := e.PostAddressEndpoint(ctx, request)
if err != nil {
return err
}
resp := response.(postAddressResponse)
return resp.Err
}
// DeleteAddress implements Service. Primarily useful in a client.
func (e Endpoints) DeleteAddress(ctx context.Context, profileID string, addressID string) error {
request := deleteAddressRequest{ProfileID: profileID, AddressID: addressID}
response, err := e.DeleteAddressEndpoint(ctx, request)
if err != nil {
return err
}
resp := response.(deleteAddressResponse)
return resp.Err
}
// MakePostProfileEndpoint returns an endpoint via the passed service.
// Primarily useful in a server.
func MakePostProfileEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
req := request.(postProfileRequest)
e := s.PostProfile(ctx, req.Profile)
return postProfileResponse{Err: e}, nil
}
}
// MakeGetProfileEndpoint returns an endpoint via the passed service.
// Primarily useful in a server.
func MakeGetProfileEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
req := request.(getProfileRequest)
p, e := s.GetProfile(ctx, req.ID)
return getProfileResponse{Profile: p, Err: e}, nil
}
}
// MakePutProfileEndpoint returns an endpoint via the passed service.
// Primarily useful in a server.
func MakePutProfileEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
req := request.(putProfileRequest)
e := s.PutProfile(ctx, req.ID, req.Profile)
return putProfileResponse{Err: e}, nil
}
}
// MakePatchProfileEndpoint returns an endpoint via the passed service.
// Primarily useful in a server.
func MakePatchProfileEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
req := request.(patchProfileRequest)
e := s.PatchProfile(ctx, req.ID, req.Profile)
return patchProfileResponse{Err: e}, nil
}
}
// MakeDeleteProfileEndpoint returns an endpoint via the passed service.
// Primarily useful in a server.
func MakeDeleteProfileEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
req := request.(deleteProfileRequest)
e := s.DeleteProfile(ctx, req.ID)
return deleteProfileResponse{Err: e}, nil
}
}
// MakeGetAddressesEndpoint returns an endpoint via the passed service.
// Primarily useful in a server.
func MakeGetAddressesEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
req := request.(getAddressesRequest)
a, e := s.GetAddresses(ctx, req.ProfileID)
return getAddressesResponse{Addresses: a, Err: e}, nil
}
}
// MakeGetAddressEndpoint returns an endpoint via the passed service.
// Primarily useful in a server.
func MakeGetAddressEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
req := request.(getAddressRequest)
a, e := s.GetAddress(ctx, req.ProfileID, req.AddressID)
return getAddressResponse{Address: a, Err: e}, nil
}
}
// MakePostAddressEndpoint returns an endpoint via the passed service.
// Primarily useful in a server.
func MakePostAddressEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
req := request.(postAddressRequest)
e := s.PostAddress(ctx, req.ProfileID, req.Address)
return postAddressResponse{Err: e}, nil
}
}
// MakeDeleteAddressEndpoint returns an endpoint via the passed service.
// Primarily useful in a server.
func MakeDeleteAddressEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
req := request.(deleteAddressRequest)
e := s.DeleteAddress(ctx, req.ProfileID, req.AddressID)
return deleteAddressResponse{Err: e}, nil
}
}
// We have two options to return errors from the business logic.
//
// We could return the error via the endpoint itself. That makes certain things
// a little bit easier, like providing non-200 HTTP responses to the client. But
// Go kit assumes that endpoint errors are (or may be treated as)
// transport-domain errors. For example, an endpoint error will count against a
// circuit breaker error count.
//
// Therefore, it's often better to return service (business logic) errors in the
// response object. This means we have to do a bit more work in the HTTP
// response encoder to detect e.g. a not-found error and provide a proper HTTP
// status code. That work is done with the errorer interface, in transport.go.
// Response types that may contain business-logic errors implement that
// interface.
type postProfileRequest struct {
Profile Profile
}
type postProfileResponse struct {
Err error `json:"err,omitempty"`
}
func (r postProfileResponse) error() error { return r.Err }
type getProfileRequest struct {
ID string
}
type getProfileResponse struct {
Profile Profile `json:"profile,omitempty"`
Err error `json:"err,omitempty"`
}
func (r getProfileResponse) error() error { return r.Err }
type putProfileRequest struct {
ID string
Profile Profile
}
type putProfileResponse struct {
Err error `json:"err,omitempty"`
}
func (r putProfileResponse) error() error { return nil }
type patchProfileRequest struct {
ID string
Profile Profile
}
type patchProfileResponse struct {
Err error `json:"err,omitempty"`
}
func (r patchProfileResponse) error() error { return r.Err }
type deleteProfileRequest struct {
ID string
}
type deleteProfileResponse struct {
Err error `json:"err,omitempty"`
}
func (r deleteProfileResponse) error() error { return r.Err }
type getAddressesRequest struct {
ProfileID string
}
type getAddressesResponse struct {
Addresses []Address `json:"addresses,omitempty"`
Err error `json:"err,omitempty"`
}
func (r getAddressesResponse) error() error { return r.Err }
type getAddressRequest struct {
ProfileID string
AddressID string
}
type getAddressResponse struct {
Address Address `json:"address,omitempty"`
Err error `json:"err,omitempty"`
}
func (r getAddressResponse) error() error { return r.Err }
type postAddressRequest struct {
ProfileID string
Address Address
}
type postAddressResponse struct {
Err error `json:"err,omitempty"`
}
func (r postAddressResponse) error() error { return r.Err }
type deleteAddressRequest struct {
ProfileID string
AddressID string
}
type deleteAddressResponse struct {
Err error `json:"err,omitempty"`
}
func (r deleteAddressResponse) error() error { return r.Err }
golang-github-go-kit-kit-0.10.0/examples/profilesvc/middlewares.go 0000664 0000000 0000000 00000006032 13622563124 0025122 0 ustar 00root root 0000000 0000000 package profilesvc
import (
"context"
"time"
"github.com/go-kit/kit/log"
)
// Middleware describes a service (as opposed to endpoint) middleware.
type Middleware func(Service) Service
func LoggingMiddleware(logger log.Logger) Middleware {
return func(next Service) Service {
return &loggingMiddleware{
next: next,
logger: logger,
}
}
}
type loggingMiddleware struct {
next Service
logger log.Logger
}
func (mw loggingMiddleware) PostProfile(ctx context.Context, p Profile) (err error) {
defer func(begin time.Time) {
mw.logger.Log("method", "PostProfile", "id", p.ID, "took", time.Since(begin), "err", err)
}(time.Now())
return mw.next.PostProfile(ctx, p)
}
func (mw loggingMiddleware) GetProfile(ctx context.Context, id string) (p Profile, err error) {
defer func(begin time.Time) {
mw.logger.Log("method", "GetProfile", "id", id, "took", time.Since(begin), "err", err)
}(time.Now())
return mw.next.GetProfile(ctx, id)
}
func (mw loggingMiddleware) PutProfile(ctx context.Context, id string, p Profile) (err error) {
defer func(begin time.Time) {
mw.logger.Log("method", "PutProfile", "id", id, "took", time.Since(begin), "err", err)
}(time.Now())
return mw.next.PutProfile(ctx, id, p)
}
func (mw loggingMiddleware) PatchProfile(ctx context.Context, id string, p Profile) (err error) {
defer func(begin time.Time) {
mw.logger.Log("method", "PatchProfile", "id", id, "took", time.Since(begin), "err", err)
}(time.Now())
return mw.next.PatchProfile(ctx, id, p)
}
func (mw loggingMiddleware) DeleteProfile(ctx context.Context, id string) (err error) {
defer func(begin time.Time) {
mw.logger.Log("method", "DeleteProfile", "id", id, "took", time.Since(begin), "err", err)
}(time.Now())
return mw.next.DeleteProfile(ctx, id)
}
func (mw loggingMiddleware) GetAddresses(ctx context.Context, profileID string) (addresses []Address, err error) {
defer func(begin time.Time) {
mw.logger.Log("method", "GetAddresses", "profileID", profileID, "took", time.Since(begin), "err", err)
}(time.Now())
return mw.next.GetAddresses(ctx, profileID)
}
func (mw loggingMiddleware) GetAddress(ctx context.Context, profileID string, addressID string) (a Address, err error) {
defer func(begin time.Time) {
mw.logger.Log("method", "GetAddress", "profileID", profileID, "addressID", addressID, "took", time.Since(begin), "err", err)
}(time.Now())
return mw.next.GetAddress(ctx, profileID, addressID)
}
func (mw loggingMiddleware) PostAddress(ctx context.Context, profileID string, a Address) (err error) {
defer func(begin time.Time) {
mw.logger.Log("method", "PostAddress", "profileID", profileID, "took", time.Since(begin), "err", err)
}(time.Now())
return mw.next.PostAddress(ctx, profileID, a)
}
func (mw loggingMiddleware) DeleteAddress(ctx context.Context, profileID string, addressID string) (err error) {
defer func(begin time.Time) {
mw.logger.Log("method", "DeleteAddress", "profileID", profileID, "addressID", addressID, "took", time.Since(begin), "err", err)
}(time.Now())
return mw.next.DeleteAddress(ctx, profileID, addressID)
}
golang-github-go-kit-kit-0.10.0/examples/profilesvc/service.go 0000664 0000000 0000000 00000010744 13622563124 0024267 0 ustar 00root root 0000000 0000000 package profilesvc
import (
"context"
"errors"
"sync"
)
// Service is a simple CRUD interface for user profiles.
type Service interface {
PostProfile(ctx context.Context, p Profile) error
GetProfile(ctx context.Context, id string) (Profile, error)
PutProfile(ctx context.Context, id string, p Profile) error
PatchProfile(ctx context.Context, id string, p Profile) error
DeleteProfile(ctx context.Context, id string) error
GetAddresses(ctx context.Context, profileID string) ([]Address, error)
GetAddress(ctx context.Context, profileID string, addressID string) (Address, error)
PostAddress(ctx context.Context, profileID string, a Address) error
DeleteAddress(ctx context.Context, profileID string, addressID string) error
}
// Profile represents a single user profile.
// ID should be globally unique.
type Profile struct {
ID string `json:"id"`
Name string `json:"name,omitempty"`
Addresses []Address `json:"addresses,omitempty"`
}
// Address is a field of a user profile.
// ID should be unique within the profile (at a minimum).
type Address struct {
ID string `json:"id"`
Location string `json:"location,omitempty"`
}
var (
ErrInconsistentIDs = errors.New("inconsistent IDs")
ErrAlreadyExists = errors.New("already exists")
ErrNotFound = errors.New("not found")
)
type inmemService struct {
mtx sync.RWMutex
m map[string]Profile
}
func NewInmemService() Service {
return &inmemService{
m: map[string]Profile{},
}
}
func (s *inmemService) PostProfile(ctx context.Context, p Profile) error {
s.mtx.Lock()
defer s.mtx.Unlock()
if _, ok := s.m[p.ID]; ok {
return ErrAlreadyExists // POST = create, don't overwrite
}
s.m[p.ID] = p
return nil
}
func (s *inmemService) GetProfile(ctx context.Context, id string) (Profile, error) {
s.mtx.RLock()
defer s.mtx.RUnlock()
p, ok := s.m[id]
if !ok {
return Profile{}, ErrNotFound
}
return p, nil
}
func (s *inmemService) PutProfile(ctx context.Context, id string, p Profile) error {
if id != p.ID {
return ErrInconsistentIDs
}
s.mtx.Lock()
defer s.mtx.Unlock()
s.m[id] = p // PUT = create or update
return nil
}
func (s *inmemService) PatchProfile(ctx context.Context, id string, p Profile) error {
if p.ID != "" && id != p.ID {
return ErrInconsistentIDs
}
s.mtx.Lock()
defer s.mtx.Unlock()
existing, ok := s.m[id]
if !ok {
return ErrNotFound // PATCH = update existing, don't create
}
// We assume that it's not possible to PATCH the ID, and that it's not
// possible to PATCH any field to its zero value. That is, the zero value
// means not specified. The way around this is to use e.g. Name *string in
// the Profile definition. But since this is just a demonstrative example,
// I'm leaving that out.
if p.Name != "" {
existing.Name = p.Name
}
if len(p.Addresses) > 0 {
existing.Addresses = p.Addresses
}
s.m[id] = existing
return nil
}
func (s *inmemService) DeleteProfile(ctx context.Context, id string) error {
s.mtx.Lock()
defer s.mtx.Unlock()
if _, ok := s.m[id]; !ok {
return ErrNotFound
}
delete(s.m, id)
return nil
}
func (s *inmemService) GetAddresses(ctx context.Context, profileID string) ([]Address, error) {
s.mtx.RLock()
defer s.mtx.RUnlock()
p, ok := s.m[profileID]
if !ok {
return []Address{}, ErrNotFound
}
return p.Addresses, nil
}
func (s *inmemService) GetAddress(ctx context.Context, profileID string, addressID string) (Address, error) {
s.mtx.RLock()
defer s.mtx.RUnlock()
p, ok := s.m[profileID]
if !ok {
return Address{}, ErrNotFound
}
for _, address := range p.Addresses {
if address.ID == addressID {
return address, nil
}
}
return Address{}, ErrNotFound
}
func (s *inmemService) PostAddress(ctx context.Context, profileID string, a Address) error {
s.mtx.Lock()
defer s.mtx.Unlock()
p, ok := s.m[profileID]
if !ok {
return ErrNotFound
}
for _, address := range p.Addresses {
if address.ID == a.ID {
return ErrAlreadyExists
}
}
p.Addresses = append(p.Addresses, a)
s.m[profileID] = p
return nil
}
func (s *inmemService) DeleteAddress(ctx context.Context, profileID string, addressID string) error {
s.mtx.Lock()
defer s.mtx.Unlock()
p, ok := s.m[profileID]
if !ok {
return ErrNotFound
}
newAddresses := make([]Address, 0, len(p.Addresses))
for _, address := range p.Addresses {
if address.ID == addressID {
continue // delete
}
newAddresses = append(newAddresses, address)
}
if len(newAddresses) == len(p.Addresses) {
return ErrNotFound
}
p.Addresses = newAddresses
s.m[profileID] = p
return nil
}
golang-github-go-kit-kit-0.10.0/examples/profilesvc/transport.go 0000664 0000000 0000000 00000030624 13622563124 0024662 0 ustar 00root root 0000000 0000000 package profilesvc
// The profilesvc is just over HTTP, so we just have a single transport.go.
import (
"bytes"
"context"
"encoding/json"
"errors"
"io/ioutil"
"net/http"
"net/url"
"github.com/gorilla/mux"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/transport"
httptransport "github.com/go-kit/kit/transport/http"
)
var (
// ErrBadRouting is returned when an expected path variable is missing.
// It always indicates programmer error.
ErrBadRouting = errors.New("inconsistent mapping between route and handler (programmer error)")
)
// MakeHTTPHandler mounts all of the service endpoints into an http.Handler.
// Useful in a profilesvc server.
func MakeHTTPHandler(s Service, logger log.Logger) http.Handler {
r := mux.NewRouter()
e := MakeServerEndpoints(s)
options := []httptransport.ServerOption{
httptransport.ServerErrorHandler(transport.NewLogErrorHandler(logger)),
httptransport.ServerErrorEncoder(encodeError),
}
// POST /profiles/ adds another profile
// GET /profiles/:id retrieves the given profile by id
// PUT /profiles/:id post updated profile information about the profile
// PATCH /profiles/:id partial updated profile information
// DELETE /profiles/:id remove the given profile
// GET /profiles/:id/addresses/ retrieve addresses associated with the profile
// GET /profiles/:id/addresses/:addressID retrieve a particular profile address
// POST /profiles/:id/addresses/ add a new address
// DELETE /profiles/:id/addresses/:addressID remove an address
r.Methods("POST").Path("/profiles/").Handler(httptransport.NewServer(
e.PostProfileEndpoint,
decodePostProfileRequest,
encodeResponse,
options...,
))
r.Methods("GET").Path("/profiles/{id}").Handler(httptransport.NewServer(
e.GetProfileEndpoint,
decodeGetProfileRequest,
encodeResponse,
options...,
))
r.Methods("PUT").Path("/profiles/{id}").Handler(httptransport.NewServer(
e.PutProfileEndpoint,
decodePutProfileRequest,
encodeResponse,
options...,
))
r.Methods("PATCH").Path("/profiles/{id}").Handler(httptransport.NewServer(
e.PatchProfileEndpoint,
decodePatchProfileRequest,
encodeResponse,
options...,
))
r.Methods("DELETE").Path("/profiles/{id}").Handler(httptransport.NewServer(
e.DeleteProfileEndpoint,
decodeDeleteProfileRequest,
encodeResponse,
options...,
))
r.Methods("GET").Path("/profiles/{id}/addresses/").Handler(httptransport.NewServer(
e.GetAddressesEndpoint,
decodeGetAddressesRequest,
encodeResponse,
options...,
))
r.Methods("GET").Path("/profiles/{id}/addresses/{addressID}").Handler(httptransport.NewServer(
e.GetAddressEndpoint,
decodeGetAddressRequest,
encodeResponse,
options...,
))
r.Methods("POST").Path("/profiles/{id}/addresses/").Handler(httptransport.NewServer(
e.PostAddressEndpoint,
decodePostAddressRequest,
encodeResponse,
options...,
))
r.Methods("DELETE").Path("/profiles/{id}/addresses/{addressID}").Handler(httptransport.NewServer(
e.DeleteAddressEndpoint,
decodeDeleteAddressRequest,
encodeResponse,
options...,
))
return r
}
func decodePostProfileRequest(_ context.Context, r *http.Request) (request interface{}, err error) {
var req postProfileRequest
if e := json.NewDecoder(r.Body).Decode(&req.Profile); e != nil {
return nil, e
}
return req, nil
}
func decodeGetProfileRequest(_ context.Context, r *http.Request) (request interface{}, err error) {
vars := mux.Vars(r)
id, ok := vars["id"]
if !ok {
return nil, ErrBadRouting
}
return getProfileRequest{ID: id}, nil
}
func decodePutProfileRequest(_ context.Context, r *http.Request) (request interface{}, err error) {
vars := mux.Vars(r)
id, ok := vars["id"]
if !ok {
return nil, ErrBadRouting
}
var profile Profile
if err := json.NewDecoder(r.Body).Decode(&profile); err != nil {
return nil, err
}
return putProfileRequest{
ID: id,
Profile: profile,
}, nil
}
func decodePatchProfileRequest(_ context.Context, r *http.Request) (request interface{}, err error) {
vars := mux.Vars(r)
id, ok := vars["id"]
if !ok {
return nil, ErrBadRouting
}
var profile Profile
if err := json.NewDecoder(r.Body).Decode(&profile); err != nil {
return nil, err
}
return patchProfileRequest{
ID: id,
Profile: profile,
}, nil
}
func decodeDeleteProfileRequest(_ context.Context, r *http.Request) (request interface{}, err error) {
vars := mux.Vars(r)
id, ok := vars["id"]
if !ok {
return nil, ErrBadRouting
}
return deleteProfileRequest{ID: id}, nil
}
func decodeGetAddressesRequest(_ context.Context, r *http.Request) (request interface{}, err error) {
vars := mux.Vars(r)
id, ok := vars["id"]
if !ok {
return nil, ErrBadRouting
}
return getAddressesRequest{ProfileID: id}, nil
}
func decodeGetAddressRequest(_ context.Context, r *http.Request) (request interface{}, err error) {
vars := mux.Vars(r)
id, ok := vars["id"]
if !ok {
return nil, ErrBadRouting
}
addressID, ok := vars["addressID"]
if !ok {
return nil, ErrBadRouting
}
return getAddressRequest{
ProfileID: id,
AddressID: addressID,
}, nil
}
func decodePostAddressRequest(_ context.Context, r *http.Request) (request interface{}, err error) {
vars := mux.Vars(r)
id, ok := vars["id"]
if !ok {
return nil, ErrBadRouting
}
var address Address
if err := json.NewDecoder(r.Body).Decode(&address); err != nil {
return nil, err
}
return postAddressRequest{
ProfileID: id,
Address: address,
}, nil
}
func decodeDeleteAddressRequest(_ context.Context, r *http.Request) (request interface{}, err error) {
vars := mux.Vars(r)
id, ok := vars["id"]
if !ok {
return nil, ErrBadRouting
}
addressID, ok := vars["addressID"]
if !ok {
return nil, ErrBadRouting
}
return deleteAddressRequest{
ProfileID: id,
AddressID: addressID,
}, nil
}
func encodePostProfileRequest(ctx context.Context, req *http.Request, request interface{}) error {
// r.Methods("POST").Path("/profiles/")
req.URL.Path = "/profiles/"
return encodeRequest(ctx, req, request)
}
func encodeGetProfileRequest(ctx context.Context, req *http.Request, request interface{}) error {
// r.Methods("GET").Path("/profiles/{id}")
r := request.(getProfileRequest)
profileID := url.QueryEscape(r.ID)
req.URL.Path = "/profiles/" + profileID
return encodeRequest(ctx, req, request)
}
func encodePutProfileRequest(ctx context.Context, req *http.Request, request interface{}) error {
// r.Methods("PUT").Path("/profiles/{id}")
r := request.(putProfileRequest)
profileID := url.QueryEscape(r.ID)
req.URL.Path = "/profiles/" + profileID
return encodeRequest(ctx, req, request)
}
func encodePatchProfileRequest(ctx context.Context, req *http.Request, request interface{}) error {
// r.Methods("PATCH").Path("/profiles/{id}")
r := request.(patchProfileRequest)
profileID := url.QueryEscape(r.ID)
req.URL.Path = "/profiles/" + profileID
return encodeRequest(ctx, req, request)
}
func encodeDeleteProfileRequest(ctx context.Context, req *http.Request, request interface{}) error {
// r.Methods("DELETE").Path("/profiles/{id}")
r := request.(deleteProfileRequest)
profileID := url.QueryEscape(r.ID)
req.URL.Path = "/profiles/" + profileID
return encodeRequest(ctx, req, request)
}
func encodeGetAddressesRequest(ctx context.Context, req *http.Request, request interface{}) error {
// r.Methods("GET").Path("/profiles/{id}/addresses/")
r := request.(getAddressesRequest)
profileID := url.QueryEscape(r.ProfileID)
req.URL.Path = "/profiles/" + profileID + "/addresses/"
return encodeRequest(ctx, req, request)
}
func encodeGetAddressRequest(ctx context.Context, req *http.Request, request interface{}) error {
// r.Methods("GET").Path("/profiles/{id}/addresses/{addressID}")
r := request.(getAddressRequest)
profileID := url.QueryEscape(r.ProfileID)
addressID := url.QueryEscape(r.AddressID)
req.URL.Path = "/profiles/" + profileID + "/addresses/" + addressID
return encodeRequest(ctx, req, request)
}
func encodePostAddressRequest(ctx context.Context, req *http.Request, request interface{}) error {
// r.Methods("POST").Path("/profiles/{id}/addresses/")
r := request.(postAddressRequest)
profileID := url.QueryEscape(r.ProfileID)
req.URL.Path = "/profiles/" + profileID + "/addresses/"
return encodeRequest(ctx, req, request)
}
func encodeDeleteAddressRequest(ctx context.Context, req *http.Request, request interface{}) error {
// r.Methods("DELETE").Path("/profiles/{id}/addresses/{addressID}")
r := request.(deleteAddressRequest)
profileID := url.QueryEscape(r.ProfileID)
addressID := url.QueryEscape(r.AddressID)
req.URL.Path = "/profiles/" + profileID + "/addresses/" + addressID
return encodeRequest(ctx, req, request)
}
func decodePostProfileResponse(_ context.Context, resp *http.Response) (interface{}, error) {
var response postProfileResponse
err := json.NewDecoder(resp.Body).Decode(&response)
return response, err
}
func decodeGetProfileResponse(_ context.Context, resp *http.Response) (interface{}, error) {
var response getProfileResponse
err := json.NewDecoder(resp.Body).Decode(&response)
return response, err
}
func decodePutProfileResponse(_ context.Context, resp *http.Response) (interface{}, error) {
var response putProfileResponse
err := json.NewDecoder(resp.Body).Decode(&response)
return response, err
}
func decodePatchProfileResponse(_ context.Context, resp *http.Response) (interface{}, error) {
var response patchProfileResponse
err := json.NewDecoder(resp.Body).Decode(&response)
return response, err
}
func decodeDeleteProfileResponse(_ context.Context, resp *http.Response) (interface{}, error) {
var response deleteProfileResponse
err := json.NewDecoder(resp.Body).Decode(&response)
return response, err
}
func decodeGetAddressesResponse(_ context.Context, resp *http.Response) (interface{}, error) {
var response getAddressesResponse
err := json.NewDecoder(resp.Body).Decode(&response)
return response, err
}
func decodeGetAddressResponse(_ context.Context, resp *http.Response) (interface{}, error) {
var response getAddressResponse
err := json.NewDecoder(resp.Body).Decode(&response)
return response, err
}
func decodePostAddressResponse(_ context.Context, resp *http.Response) (interface{}, error) {
var response postAddressResponse
err := json.NewDecoder(resp.Body).Decode(&response)
return response, err
}
func decodeDeleteAddressResponse(_ context.Context, resp *http.Response) (interface{}, error) {
var response deleteAddressResponse
err := json.NewDecoder(resp.Body).Decode(&response)
return response, err
}
// errorer is implemented by all concrete response types that may contain
// errors. It allows us to change the HTTP response code without needing to
// trigger an endpoint (transport-level) error. For more information, read the
// big comment in endpoints.go.
type errorer interface {
error() error
}
// encodeResponse is the common method to encode all response types to the
// client. I chose to do it this way because, since we're using JSON, there's no
// reason to provide anything more specific. It's certainly possible to
// specialize on a per-response (per-method) basis.
func encodeResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error {
if e, ok := response.(errorer); ok && e.error() != nil {
// Not a Go kit transport error, but a business-logic error.
// Provide those as HTTP errors.
encodeError(ctx, e.error(), w)
return nil
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
// encodeRequest likewise JSON-encodes the request to the HTTP request body.
// Don't use it directly as a transport/http.Client EncodeRequestFunc:
// profilesvc endpoints require mutating the HTTP method and request path.
func encodeRequest(_ context.Context, req *http.Request, request interface{}) error {
var buf bytes.Buffer
err := json.NewEncoder(&buf).Encode(request)
if err != nil {
return err
}
req.Body = ioutil.NopCloser(&buf)
return nil
}
func encodeError(_ context.Context, err error, w http.ResponseWriter) {
if err == nil {
panic("encodeError with nil error")
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(codeFrom(err))
json.NewEncoder(w).Encode(map[string]interface{}{
"error": err.Error(),
})
}
func codeFrom(err error) int {
switch err {
case ErrNotFound:
return http.StatusNotFound
case ErrAlreadyExists, ErrInconsistentIDs:
return http.StatusBadRequest
default:
return http.StatusInternalServerError
}
}
golang-github-go-kit-kit-0.10.0/examples/shipping/ 0000775 0000000 0000000 00000000000 13622563124 0021737 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/shipping/README.md 0000664 0000000 0000000 00000003460 13622563124 0023221 0 ustar 00root root 0000000 0000000 # shipping
This example demonstrates a more real-world application consisting of multiple services.
## Description
The implementation is based on the container shipping domain from the [Domain Driven Design](http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215) book by Eric Evans, which was [originally](http://dddsample.sourceforge.net/) implemented in Java but has since been ported to Go. This example is a somewhat stripped down version to demonstrate the use of Go kit. The [original Go application](https://github.com/marcusolsson/goddd) is maintained separately and accompanied by an [AngularJS application](https://github.com/marcusolsson/dddelivery-angularjs) as well as a mock [routing service](https://github.com/marcusolsson/pathfinder).
### Organization
The application consists of three application services, `booking`, `handling` and `tracking`. Each of these is an individual Go kit service as seen in previous examples.
- __booking__ - used by the shipping company to book and route cargos.
- __handling__ - used by our staff around the world to register whenever the cargo has been received, loaded etc.
- __tracking__ - used by the customer to track the cargo along the route
There are also a few pure domain packages that contain some intricate business-logic. They provide domain objects and services that are used by each application service to provide interesting use-cases for the user.
`inmem` contains in-memory implementations for the repositories found in the domain packages.
The `routing` package provides a _domain service_ that is used to query an external application for possible routes.
## Contributing
As with all Go kit examples you are more than welcome to contribute. If you do however, please consider contributing back to the original project as well.
golang-github-go-kit-kit-0.10.0/examples/shipping/booking/ 0000775 0000000 0000000 00000000000 13622563124 0023367 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/shipping/booking/endpoint.go 0000664 0000000 0000000 00000007342 13622563124 0025544 0 ustar 00root root 0000000 0000000 package booking
import (
"context"
"time"
"github.com/go-kit/kit/endpoint"
"github.com/go-kit/kit/examples/shipping/cargo"
"github.com/go-kit/kit/examples/shipping/location"
)
type bookCargoRequest struct {
Origin location.UNLocode
Destination location.UNLocode
ArrivalDeadline time.Time
}
type bookCargoResponse struct {
ID cargo.TrackingID `json:"tracking_id,omitempty"`
Err error `json:"error,omitempty"`
}
func (r bookCargoResponse) error() error { return r.Err }
func makeBookCargoEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(bookCargoRequest)
id, err := s.BookNewCargo(req.Origin, req.Destination, req.ArrivalDeadline)
return bookCargoResponse{ID: id, Err: err}, nil
}
}
type loadCargoRequest struct {
ID cargo.TrackingID
}
type loadCargoResponse struct {
Cargo *Cargo `json:"cargo,omitempty"`
Err error `json:"error,omitempty"`
}
func (r loadCargoResponse) error() error { return r.Err }
func makeLoadCargoEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(loadCargoRequest)
c, err := s.LoadCargo(req.ID)
return loadCargoResponse{Cargo: &c, Err: err}, nil
}
}
type requestRoutesRequest struct {
ID cargo.TrackingID
}
type requestRoutesResponse struct {
Routes []cargo.Itinerary `json:"routes,omitempty"`
Err error `json:"error,omitempty"`
}
func (r requestRoutesResponse) error() error { return r.Err }
func makeRequestRoutesEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(requestRoutesRequest)
itin := s.RequestPossibleRoutesForCargo(req.ID)
return requestRoutesResponse{Routes: itin, Err: nil}, nil
}
}
type assignToRouteRequest struct {
ID cargo.TrackingID
Itinerary cargo.Itinerary
}
type assignToRouteResponse struct {
Err error `json:"error,omitempty"`
}
func (r assignToRouteResponse) error() error { return r.Err }
func makeAssignToRouteEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(assignToRouteRequest)
err := s.AssignCargoToRoute(req.ID, req.Itinerary)
return assignToRouteResponse{Err: err}, nil
}
}
type changeDestinationRequest struct {
ID cargo.TrackingID
Destination location.UNLocode
}
type changeDestinationResponse struct {
Err error `json:"error,omitempty"`
}
func (r changeDestinationResponse) error() error { return r.Err }
func makeChangeDestinationEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(changeDestinationRequest)
err := s.ChangeDestination(req.ID, req.Destination)
return changeDestinationResponse{Err: err}, nil
}
}
type listCargosRequest struct{}
type listCargosResponse struct {
Cargos []Cargo `json:"cargos,omitempty"`
Err error `json:"error,omitempty"`
}
func (r listCargosResponse) error() error { return r.Err }
func makeListCargosEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
_ = request.(listCargosRequest)
return listCargosResponse{Cargos: s.Cargos(), Err: nil}, nil
}
}
type listLocationsRequest struct {
}
type listLocationsResponse struct {
Locations []Location `json:"locations,omitempty"`
Err error `json:"error,omitempty"`
}
func makeListLocationsEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
_ = request.(listLocationsRequest)
return listLocationsResponse{Locations: s.Locations(), Err: nil}, nil
}
}
golang-github-go-kit-kit-0.10.0/examples/shipping/booking/instrumenting.go 0000664 0000000 0000000 00000005442 13622563124 0026631 0 ustar 00root root 0000000 0000000 package booking
import (
"time"
"github.com/go-kit/kit/metrics"
"github.com/go-kit/kit/examples/shipping/cargo"
"github.com/go-kit/kit/examples/shipping/location"
)
type instrumentingService struct {
requestCount metrics.Counter
requestLatency metrics.Histogram
Service
}
// NewInstrumentingService returns an instance of an instrumenting Service.
func NewInstrumentingService(counter metrics.Counter, latency metrics.Histogram, s Service) Service {
return &instrumentingService{
requestCount: counter,
requestLatency: latency,
Service: s,
}
}
func (s *instrumentingService) BookNewCargo(origin, destination location.UNLocode, deadline time.Time) (cargo.TrackingID, error) {
defer func(begin time.Time) {
s.requestCount.With("method", "book").Add(1)
s.requestLatency.With("method", "book").Observe(time.Since(begin).Seconds())
}(time.Now())
return s.Service.BookNewCargo(origin, destination, deadline)
}
func (s *instrumentingService) LoadCargo(id cargo.TrackingID) (c Cargo, err error) {
defer func(begin time.Time) {
s.requestCount.With("method", "load").Add(1)
s.requestLatency.With("method", "load").Observe(time.Since(begin).Seconds())
}(time.Now())
return s.Service.LoadCargo(id)
}
func (s *instrumentingService) RequestPossibleRoutesForCargo(id cargo.TrackingID) []cargo.Itinerary {
defer func(begin time.Time) {
s.requestCount.With("method", "request_routes").Add(1)
s.requestLatency.With("method", "request_routes").Observe(time.Since(begin).Seconds())
}(time.Now())
return s.Service.RequestPossibleRoutesForCargo(id)
}
func (s *instrumentingService) AssignCargoToRoute(id cargo.TrackingID, itinerary cargo.Itinerary) (err error) {
defer func(begin time.Time) {
s.requestCount.With("method", "assign_to_route").Add(1)
s.requestLatency.With("method", "assign_to_route").Observe(time.Since(begin).Seconds())
}(time.Now())
return s.Service.AssignCargoToRoute(id, itinerary)
}
func (s *instrumentingService) ChangeDestination(id cargo.TrackingID, l location.UNLocode) (err error) {
defer func(begin time.Time) {
s.requestCount.With("method", "change_destination").Add(1)
s.requestLatency.With("method", "change_destination").Observe(time.Since(begin).Seconds())
}(time.Now())
return s.Service.ChangeDestination(id, l)
}
func (s *instrumentingService) Cargos() []Cargo {
defer func(begin time.Time) {
s.requestCount.With("method", "list_cargos").Add(1)
s.requestLatency.With("method", "list_cargos").Observe(time.Since(begin).Seconds())
}(time.Now())
return s.Service.Cargos()
}
func (s *instrumentingService) Locations() []Location {
defer func(begin time.Time) {
s.requestCount.With("method", "list_locations").Add(1)
s.requestLatency.With("method", "list_locations").Observe(time.Since(begin).Seconds())
}(time.Now())
return s.Service.Locations()
}
golang-github-go-kit-kit-0.10.0/examples/shipping/booking/logging.go 0000664 0000000 0000000 00000004637 13622563124 0025356 0 ustar 00root root 0000000 0000000 package booking
import (
"time"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/examples/shipping/cargo"
"github.com/go-kit/kit/examples/shipping/location"
)
type loggingService struct {
logger log.Logger
Service
}
// NewLoggingService returns a new instance of a logging Service.
func NewLoggingService(logger log.Logger, s Service) Service {
return &loggingService{logger, s}
}
func (s *loggingService) BookNewCargo(origin location.UNLocode, destination location.UNLocode, deadline time.Time) (id cargo.TrackingID, err error) {
defer func(begin time.Time) {
s.logger.Log(
"method", "book",
"origin", origin,
"destination", destination,
"arrival_deadline", deadline,
"took", time.Since(begin),
"err", err,
)
}(time.Now())
return s.Service.BookNewCargo(origin, destination, deadline)
}
func (s *loggingService) LoadCargo(id cargo.TrackingID) (c Cargo, err error) {
defer func(begin time.Time) {
s.logger.Log(
"method", "load",
"tracking_id", id,
"took", time.Since(begin),
"err", err,
)
}(time.Now())
return s.Service.LoadCargo(id)
}
func (s *loggingService) RequestPossibleRoutesForCargo(id cargo.TrackingID) []cargo.Itinerary {
defer func(begin time.Time) {
s.logger.Log(
"method", "request_routes",
"tracking_id", id,
"took", time.Since(begin),
)
}(time.Now())
return s.Service.RequestPossibleRoutesForCargo(id)
}
func (s *loggingService) AssignCargoToRoute(id cargo.TrackingID, itinerary cargo.Itinerary) (err error) {
defer func(begin time.Time) {
s.logger.Log(
"method", "assign_to_route",
"tracking_id", id,
"took", time.Since(begin),
"err", err,
)
}(time.Now())
return s.Service.AssignCargoToRoute(id, itinerary)
}
func (s *loggingService) ChangeDestination(id cargo.TrackingID, l location.UNLocode) (err error) {
defer func(begin time.Time) {
s.logger.Log(
"method", "change_destination",
"tracking_id", id,
"destination", l,
"took", time.Since(begin),
"err", err,
)
}(time.Now())
return s.Service.ChangeDestination(id, l)
}
func (s *loggingService) Cargos() []Cargo {
defer func(begin time.Time) {
s.logger.Log(
"method", "list_cargos",
"took", time.Since(begin),
)
}(time.Now())
return s.Service.Cargos()
}
func (s *loggingService) Locations() []Location {
defer func(begin time.Time) {
s.logger.Log(
"method", "list_locations",
"took", time.Since(begin),
)
}(time.Now())
return s.Service.Locations()
}
golang-github-go-kit-kit-0.10.0/examples/shipping/booking/service.go 0000664 0000000 0000000 00000012104 13622563124 0025354 0 ustar 00root root 0000000 0000000 // Package booking provides the use-case of booking a cargo. Used by views
// facing an administrator.
package booking
import (
"errors"
"time"
"github.com/go-kit/kit/examples/shipping/cargo"
"github.com/go-kit/kit/examples/shipping/location"
"github.com/go-kit/kit/examples/shipping/routing"
)
// ErrInvalidArgument is returned when one or more arguments are invalid.
var ErrInvalidArgument = errors.New("invalid argument")
// Service is the interface that provides booking methods.
type Service interface {
// BookNewCargo registers a new cargo in the tracking system, not yet
// routed.
BookNewCargo(origin location.UNLocode, destination location.UNLocode, deadline time.Time) (cargo.TrackingID, error)
// LoadCargo returns a read model of a cargo.
LoadCargo(id cargo.TrackingID) (Cargo, error)
// RequestPossibleRoutesForCargo requests a list of itineraries describing
// possible routes for this cargo.
RequestPossibleRoutesForCargo(id cargo.TrackingID) []cargo.Itinerary
// AssignCargoToRoute assigns a cargo to the route specified by the
// itinerary.
AssignCargoToRoute(id cargo.TrackingID, itinerary cargo.Itinerary) error
// ChangeDestination changes the destination of a cargo.
ChangeDestination(id cargo.TrackingID, destination location.UNLocode) error
// Cargos returns a list of all cargos that have been booked.
Cargos() []Cargo
// Locations returns a list of registered locations.
Locations() []Location
}
type service struct {
cargos cargo.Repository
locations location.Repository
handlingEvents cargo.HandlingEventRepository
routingService routing.Service
}
func (s *service) AssignCargoToRoute(id cargo.TrackingID, itinerary cargo.Itinerary) error {
if id == "" || len(itinerary.Legs) == 0 {
return ErrInvalidArgument
}
c, err := s.cargos.Find(id)
if err != nil {
return err
}
c.AssignToRoute(itinerary)
return s.cargos.Store(c)
}
func (s *service) BookNewCargo(origin, destination location.UNLocode, deadline time.Time) (cargo.TrackingID, error) {
if origin == "" || destination == "" || deadline.IsZero() {
return "", ErrInvalidArgument
}
id := cargo.NextTrackingID()
rs := cargo.RouteSpecification{
Origin: origin,
Destination: destination,
ArrivalDeadline: deadline,
}
c := cargo.New(id, rs)
if err := s.cargos.Store(c); err != nil {
return "", err
}
return c.TrackingID, nil
}
func (s *service) LoadCargo(id cargo.TrackingID) (Cargo, error) {
if id == "" {
return Cargo{}, ErrInvalidArgument
}
c, err := s.cargos.Find(id)
if err != nil {
return Cargo{}, err
}
return assemble(c, s.handlingEvents), nil
}
func (s *service) ChangeDestination(id cargo.TrackingID, destination location.UNLocode) error {
if id == "" || destination == "" {
return ErrInvalidArgument
}
c, err := s.cargos.Find(id)
if err != nil {
return err
}
l, err := s.locations.Find(destination)
if err != nil {
return err
}
c.SpecifyNewRoute(cargo.RouteSpecification{
Origin: c.Origin,
Destination: l.UNLocode,
ArrivalDeadline: c.RouteSpecification.ArrivalDeadline,
})
if err := s.cargos.Store(c); err != nil {
return err
}
return nil
}
func (s *service) RequestPossibleRoutesForCargo(id cargo.TrackingID) []cargo.Itinerary {
if id == "" {
return nil
}
c, err := s.cargos.Find(id)
if err != nil {
return []cargo.Itinerary{}
}
return s.routingService.FetchRoutesForSpecification(c.RouteSpecification)
}
func (s *service) Cargos() []Cargo {
var result []Cargo
for _, c := range s.cargos.FindAll() {
result = append(result, assemble(c, s.handlingEvents))
}
return result
}
func (s *service) Locations() []Location {
var result []Location
for _, v := range s.locations.FindAll() {
result = append(result, Location{
UNLocode: string(v.UNLocode),
Name: v.Name,
})
}
return result
}
// NewService creates a booking service with necessary dependencies.
func NewService(cargos cargo.Repository, locations location.Repository, events cargo.HandlingEventRepository, rs routing.Service) Service {
return &service{
cargos: cargos,
locations: locations,
handlingEvents: events,
routingService: rs,
}
}
// Location is a read model for booking views.
type Location struct {
UNLocode string `json:"locode"`
Name string `json:"name"`
}
// Cargo is a read model for booking views.
type Cargo struct {
ArrivalDeadline time.Time `json:"arrival_deadline"`
Destination string `json:"destination"`
Legs []cargo.Leg `json:"legs,omitempty"`
Misrouted bool `json:"misrouted"`
Origin string `json:"origin"`
Routed bool `json:"routed"`
TrackingID string `json:"tracking_id"`
}
func assemble(c *cargo.Cargo, events cargo.HandlingEventRepository) Cargo {
return Cargo{
TrackingID: string(c.TrackingID),
Origin: string(c.Origin),
Destination: string(c.RouteSpecification.Destination),
Misrouted: c.Delivery.RoutingStatus == cargo.Misrouted,
Routed: !c.Itinerary.IsEmpty(),
ArrivalDeadline: c.RouteSpecification.ArrivalDeadline,
Legs: c.Itinerary.Legs,
}
}
golang-github-go-kit-kit-0.10.0/examples/shipping/booking/transport.go 0000664 0000000 0000000 00000011767 13622563124 0025766 0 ustar 00root root 0000000 0000000 package booking
import (
"context"
"encoding/json"
"errors"
"net/http"
"time"
"github.com/gorilla/mux"
kitlog "github.com/go-kit/kit/log"
"github.com/go-kit/kit/transport"
kithttp "github.com/go-kit/kit/transport/http"
"github.com/go-kit/kit/examples/shipping/cargo"
"github.com/go-kit/kit/examples/shipping/location"
)
// MakeHandler returns a handler for the booking service.
func MakeHandler(bs Service, logger kitlog.Logger) http.Handler {
opts := []kithttp.ServerOption{
kithttp.ServerErrorHandler(transport.NewLogErrorHandler(logger)),
kithttp.ServerErrorEncoder(encodeError),
}
bookCargoHandler := kithttp.NewServer(
makeBookCargoEndpoint(bs),
decodeBookCargoRequest,
encodeResponse,
opts...,
)
loadCargoHandler := kithttp.NewServer(
makeLoadCargoEndpoint(bs),
decodeLoadCargoRequest,
encodeResponse,
opts...,
)
requestRoutesHandler := kithttp.NewServer(
makeRequestRoutesEndpoint(bs),
decodeRequestRoutesRequest,
encodeResponse,
opts...,
)
assignToRouteHandler := kithttp.NewServer(
makeAssignToRouteEndpoint(bs),
decodeAssignToRouteRequest,
encodeResponse,
opts...,
)
changeDestinationHandler := kithttp.NewServer(
makeChangeDestinationEndpoint(bs),
decodeChangeDestinationRequest,
encodeResponse,
opts...,
)
listCargosHandler := kithttp.NewServer(
makeListCargosEndpoint(bs),
decodeListCargosRequest,
encodeResponse,
opts...,
)
listLocationsHandler := kithttp.NewServer(
makeListLocationsEndpoint(bs),
decodeListLocationsRequest,
encodeResponse,
opts...,
)
r := mux.NewRouter()
r.Handle("/booking/v1/cargos", bookCargoHandler).Methods("POST")
r.Handle("/booking/v1/cargos", listCargosHandler).Methods("GET")
r.Handle("/booking/v1/cargos/{id}", loadCargoHandler).Methods("GET")
r.Handle("/booking/v1/cargos/{id}/request_routes", requestRoutesHandler).Methods("GET")
r.Handle("/booking/v1/cargos/{id}/assign_to_route", assignToRouteHandler).Methods("POST")
r.Handle("/booking/v1/cargos/{id}/change_destination", changeDestinationHandler).Methods("POST")
r.Handle("/booking/v1/locations", listLocationsHandler).Methods("GET")
return r
}
var errBadRoute = errors.New("bad route")
func decodeBookCargoRequest(_ context.Context, r *http.Request) (interface{}, error) {
var body struct {
Origin string `json:"origin"`
Destination string `json:"destination"`
ArrivalDeadline time.Time `json:"arrival_deadline"`
}
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
return nil, err
}
return bookCargoRequest{
Origin: location.UNLocode(body.Origin),
Destination: location.UNLocode(body.Destination),
ArrivalDeadline: body.ArrivalDeadline,
}, nil
}
func decodeLoadCargoRequest(_ context.Context, r *http.Request) (interface{}, error) {
vars := mux.Vars(r)
id, ok := vars["id"]
if !ok {
return nil, errBadRoute
}
return loadCargoRequest{ID: cargo.TrackingID(id)}, nil
}
func decodeRequestRoutesRequest(_ context.Context, r *http.Request) (interface{}, error) {
vars := mux.Vars(r)
id, ok := vars["id"]
if !ok {
return nil, errBadRoute
}
return requestRoutesRequest{ID: cargo.TrackingID(id)}, nil
}
func decodeAssignToRouteRequest(_ context.Context, r *http.Request) (interface{}, error) {
vars := mux.Vars(r)
id, ok := vars["id"]
if !ok {
return nil, errBadRoute
}
var itinerary cargo.Itinerary
if err := json.NewDecoder(r.Body).Decode(&itinerary); err != nil {
return nil, err
}
return assignToRouteRequest{
ID: cargo.TrackingID(id),
Itinerary: itinerary,
}, nil
}
func decodeChangeDestinationRequest(_ context.Context, r *http.Request) (interface{}, error) {
vars := mux.Vars(r)
id, ok := vars["id"]
if !ok {
return nil, errBadRoute
}
var body struct {
Destination string `json:"destination"`
}
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
return nil, err
}
return changeDestinationRequest{
ID: cargo.TrackingID(id),
Destination: location.UNLocode(body.Destination),
}, nil
}
func decodeListCargosRequest(_ context.Context, r *http.Request) (interface{}, error) {
return listCargosRequest{}, nil
}
func decodeListLocationsRequest(_ context.Context, r *http.Request) (interface{}, error) {
return listLocationsRequest{}, nil
}
func encodeResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error {
if e, ok := response.(errorer); ok && e.error() != nil {
encodeError(ctx, e.error(), w)
return nil
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
type errorer interface {
error() error
}
// encode errors from business-logic
func encodeError(_ context.Context, err error, w http.ResponseWriter) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
switch err {
case cargo.ErrUnknown:
w.WriteHeader(http.StatusNotFound)
case ErrInvalidArgument:
w.WriteHeader(http.StatusBadRequest)
default:
w.WriteHeader(http.StatusInternalServerError)
}
json.NewEncoder(w).Encode(map[string]interface{}{
"error": err.Error(),
})
}
golang-github-go-kit-kit-0.10.0/examples/shipping/cargo/ 0000775 0000000 0000000 00000000000 13622563124 0023032 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/shipping/cargo/cargo.go 0000664 0000000 0000000 00000006510 13622563124 0024456 0 ustar 00root root 0000000 0000000 // Package cargo contains the heart of the domain model.
package cargo
import (
"errors"
"strings"
"time"
"github.com/pborman/uuid"
"github.com/go-kit/kit/examples/shipping/location"
)
// TrackingID uniquely identifies a particular cargo.
type TrackingID string
// Cargo is the central class in the domain model.
type Cargo struct {
TrackingID TrackingID
Origin location.UNLocode
RouteSpecification RouteSpecification
Itinerary Itinerary
Delivery Delivery
}
// SpecifyNewRoute specifies a new route for this cargo.
func (c *Cargo) SpecifyNewRoute(rs RouteSpecification) {
c.RouteSpecification = rs
c.Delivery = c.Delivery.UpdateOnRouting(c.RouteSpecification, c.Itinerary)
}
// AssignToRoute attaches a new itinerary to this cargo.
func (c *Cargo) AssignToRoute(itinerary Itinerary) {
c.Itinerary = itinerary
c.Delivery = c.Delivery.UpdateOnRouting(c.RouteSpecification, c.Itinerary)
}
// DeriveDeliveryProgress updates all aspects of the cargo aggregate status
// based on the current route specification, itinerary and handling of the cargo.
func (c *Cargo) DeriveDeliveryProgress(history HandlingHistory) {
c.Delivery = DeriveDeliveryFrom(c.RouteSpecification, c.Itinerary, history)
}
// New creates a new, unrouted cargo.
func New(id TrackingID, rs RouteSpecification) *Cargo {
itinerary := Itinerary{}
history := HandlingHistory{make([]HandlingEvent, 0)}
return &Cargo{
TrackingID: id,
Origin: rs.Origin,
RouteSpecification: rs,
Delivery: DeriveDeliveryFrom(rs, itinerary, history),
}
}
// Repository provides access a cargo store.
type Repository interface {
Store(cargo *Cargo) error
Find(id TrackingID) (*Cargo, error)
FindAll() []*Cargo
}
// ErrUnknown is used when a cargo could not be found.
var ErrUnknown = errors.New("unknown cargo")
// NextTrackingID generates a new tracking ID.
// TODO: Move to infrastructure(?)
func NextTrackingID() TrackingID {
return TrackingID(strings.Split(strings.ToUpper(uuid.New()), "-")[0])
}
// RouteSpecification Contains information about a route: its origin,
// destination and arrival deadline.
type RouteSpecification struct {
Origin location.UNLocode
Destination location.UNLocode
ArrivalDeadline time.Time
}
// IsSatisfiedBy checks whether provided itinerary satisfies this
// specification.
func (s RouteSpecification) IsSatisfiedBy(itinerary Itinerary) bool {
return itinerary.Legs != nil &&
s.Origin == itinerary.InitialDepartureLocation() &&
s.Destination == itinerary.FinalArrivalLocation()
}
// RoutingStatus describes status of cargo routing.
type RoutingStatus int
// Valid routing statuses.
const (
NotRouted RoutingStatus = iota
Misrouted
Routed
)
func (s RoutingStatus) String() string {
switch s {
case NotRouted:
return "Not routed"
case Misrouted:
return "Misrouted"
case Routed:
return "Routed"
}
return ""
}
// TransportStatus describes status of cargo transportation.
type TransportStatus int
// Valid transport statuses.
const (
NotReceived TransportStatus = iota
InPort
OnboardCarrier
Claimed
Unknown
)
func (s TransportStatus) String() string {
switch s {
case NotReceived:
return "Not received"
case InPort:
return "In port"
case OnboardCarrier:
return "Onboard carrier"
case Claimed:
return "Claimed"
case Unknown:
return "Unknown"
}
return ""
}
golang-github-go-kit-kit-0.10.0/examples/shipping/cargo/delivery.go 0000664 0000000 0000000 00000012156 13622563124 0025211 0 ustar 00root root 0000000 0000000 package cargo
import (
"time"
"github.com/go-kit/kit/examples/shipping/location"
"github.com/go-kit/kit/examples/shipping/voyage"
)
// Delivery is the actual transportation of the cargo, as opposed to the
// customer requirement (RouteSpecification) and the plan (Itinerary).
type Delivery struct {
Itinerary Itinerary
RouteSpecification RouteSpecification
RoutingStatus RoutingStatus
TransportStatus TransportStatus
NextExpectedActivity HandlingActivity
LastEvent HandlingEvent
LastKnownLocation location.UNLocode
CurrentVoyage voyage.Number
ETA time.Time
IsMisdirected bool
IsUnloadedAtDestination bool
}
// UpdateOnRouting creates a new delivery snapshot to reflect changes in
// routing, i.e. when the route specification or the itinerary has changed but
// no additional handling of the cargo has been performed.
func (d Delivery) UpdateOnRouting(rs RouteSpecification, itinerary Itinerary) Delivery {
return newDelivery(d.LastEvent, itinerary, rs)
}
// IsOnTrack checks if the delivery is on track.
func (d Delivery) IsOnTrack() bool {
return d.RoutingStatus == Routed && !d.IsMisdirected
}
// DeriveDeliveryFrom creates a new delivery snapshot based on the complete
// handling history of a cargo, as well as its route specification and
// itinerary.
func DeriveDeliveryFrom(rs RouteSpecification, itinerary Itinerary, history HandlingHistory) Delivery {
lastEvent, _ := history.MostRecentlyCompletedEvent()
return newDelivery(lastEvent, itinerary, rs)
}
// newDelivery creates a up-to-date delivery based on an handling event,
// itinerary and a route specification.
func newDelivery(lastEvent HandlingEvent, itinerary Itinerary, rs RouteSpecification) Delivery {
var (
routingStatus = calculateRoutingStatus(itinerary, rs)
transportStatus = calculateTransportStatus(lastEvent)
lastKnownLocation = calculateLastKnownLocation(lastEvent)
isMisdirected = calculateMisdirectedStatus(lastEvent, itinerary)
isUnloadedAtDestination = calculateUnloadedAtDestination(lastEvent, rs)
currentVoyage = calculateCurrentVoyage(transportStatus, lastEvent)
)
d := Delivery{
LastEvent: lastEvent,
Itinerary: itinerary,
RouteSpecification: rs,
RoutingStatus: routingStatus,
TransportStatus: transportStatus,
LastKnownLocation: lastKnownLocation,
IsMisdirected: isMisdirected,
IsUnloadedAtDestination: isUnloadedAtDestination,
CurrentVoyage: currentVoyage,
}
d.NextExpectedActivity = calculateNextExpectedActivity(d)
d.ETA = calculateETA(d)
return d
}
// Below are internal functions used when creating a new delivery.
func calculateRoutingStatus(itinerary Itinerary, rs RouteSpecification) RoutingStatus {
if itinerary.Legs == nil {
return NotRouted
}
if rs.IsSatisfiedBy(itinerary) {
return Routed
}
return Misrouted
}
func calculateMisdirectedStatus(event HandlingEvent, itinerary Itinerary) bool {
if event.Activity.Type == NotHandled {
return false
}
return !itinerary.IsExpected(event)
}
func calculateUnloadedAtDestination(event HandlingEvent, rs RouteSpecification) bool {
if event.Activity.Type == NotHandled {
return false
}
return event.Activity.Type == Unload && rs.Destination == event.Activity.Location
}
func calculateTransportStatus(event HandlingEvent) TransportStatus {
switch event.Activity.Type {
case NotHandled:
return NotReceived
case Load:
return OnboardCarrier
case Unload:
return InPort
case Receive:
return InPort
case Customs:
return InPort
case Claim:
return Claimed
}
return Unknown
}
func calculateLastKnownLocation(event HandlingEvent) location.UNLocode {
return event.Activity.Location
}
func calculateNextExpectedActivity(d Delivery) HandlingActivity {
if !d.IsOnTrack() {
return HandlingActivity{}
}
switch d.LastEvent.Activity.Type {
case NotHandled:
return HandlingActivity{Type: Receive, Location: d.RouteSpecification.Origin}
case Receive:
l := d.Itinerary.Legs[0]
return HandlingActivity{Type: Load, Location: l.LoadLocation, VoyageNumber: l.VoyageNumber}
case Load:
for _, l := range d.Itinerary.Legs {
if l.LoadLocation == d.LastEvent.Activity.Location {
return HandlingActivity{Type: Unload, Location: l.UnloadLocation, VoyageNumber: l.VoyageNumber}
}
}
case Unload:
for i, l := range d.Itinerary.Legs {
if l.UnloadLocation == d.LastEvent.Activity.Location {
if i < len(d.Itinerary.Legs)-1 {
return HandlingActivity{Type: Load, Location: d.Itinerary.Legs[i+1].LoadLocation, VoyageNumber: d.Itinerary.Legs[i+1].VoyageNumber}
}
return HandlingActivity{Type: Claim, Location: l.UnloadLocation}
}
}
}
return HandlingActivity{}
}
func calculateCurrentVoyage(transportStatus TransportStatus, event HandlingEvent) voyage.Number {
if transportStatus == OnboardCarrier && event.Activity.Type != NotHandled {
return event.Activity.VoyageNumber
}
return voyage.Number("")
}
func calculateETA(d Delivery) time.Time {
if !d.IsOnTrack() {
return time.Time{}
}
return d.Itinerary.FinalArrivalTime()
}
golang-github-go-kit-kit-0.10.0/examples/shipping/cargo/handling.go 0000664 0000000 0000000 00000006267 13622563124 0025160 0 ustar 00root root 0000000 0000000 package cargo
// TODO: It would make sense to have this in its own package. Unfortunately,
// then there would be a circular dependency between the cargo and handling
// packages since cargo.Delivery would use handling.HandlingEvent and
// handling.HandlingEvent would use cargo.TrackingID. Also,
// HandlingEventFactory depends on the cargo repository.
//
// It would make sense not having the cargo package depend on handling.
import (
"errors"
"time"
"github.com/go-kit/kit/examples/shipping/location"
"github.com/go-kit/kit/examples/shipping/voyage"
)
// HandlingActivity represents how and where a cargo can be handled, and can
// be used to express predictions about what is expected to happen to a cargo
// in the future.
type HandlingActivity struct {
Type HandlingEventType
Location location.UNLocode
VoyageNumber voyage.Number
}
// HandlingEvent is used to register the event when, for instance, a cargo is
// unloaded from a carrier at a some location at a given time.
type HandlingEvent struct {
TrackingID TrackingID
Activity HandlingActivity
}
// HandlingEventType describes type of a handling event.
type HandlingEventType int
// Valid handling event types.
const (
NotHandled HandlingEventType = iota
Load
Unload
Receive
Claim
Customs
)
func (t HandlingEventType) String() string {
switch t {
case NotHandled:
return "Not Handled"
case Load:
return "Load"
case Unload:
return "Unload"
case Receive:
return "Receive"
case Claim:
return "Claim"
case Customs:
return "Customs"
}
return ""
}
// HandlingHistory is the handling history of a cargo.
type HandlingHistory struct {
HandlingEvents []HandlingEvent
}
// MostRecentlyCompletedEvent returns most recently completed handling event.
func (h HandlingHistory) MostRecentlyCompletedEvent() (HandlingEvent, error) {
if len(h.HandlingEvents) == 0 {
return HandlingEvent{}, errors.New("delivery history is empty")
}
return h.HandlingEvents[len(h.HandlingEvents)-1], nil
}
// HandlingEventRepository provides access a handling event store.
type HandlingEventRepository interface {
Store(e HandlingEvent)
QueryHandlingHistory(TrackingID) HandlingHistory
}
// HandlingEventFactory creates handling events.
type HandlingEventFactory struct {
CargoRepository Repository
VoyageRepository voyage.Repository
LocationRepository location.Repository
}
// CreateHandlingEvent creates a validated handling event.
func (f *HandlingEventFactory) CreateHandlingEvent(registered time.Time, completed time.Time, id TrackingID,
voyageNumber voyage.Number, unLocode location.UNLocode, eventType HandlingEventType) (HandlingEvent, error) {
if _, err := f.CargoRepository.Find(id); err != nil {
return HandlingEvent{}, err
}
if _, err := f.VoyageRepository.Find(voyageNumber); err != nil {
// TODO: This is pretty ugly, but when creating a Receive event, the voyage number is not known.
if len(voyageNumber) > 0 {
return HandlingEvent{}, err
}
}
if _, err := f.LocationRepository.Find(unLocode); err != nil {
return HandlingEvent{}, err
}
return HandlingEvent{
TrackingID: id,
Activity: HandlingActivity{
Type: eventType,
Location: unLocode,
VoyageNumber: voyageNumber,
},
}, nil
}
golang-github-go-kit-kit-0.10.0/examples/shipping/cargo/itinerary.go 0000664 0000000 0000000 00000004661 13622563124 0025376 0 ustar 00root root 0000000 0000000 package cargo
import (
"time"
"github.com/go-kit/kit/examples/shipping/location"
"github.com/go-kit/kit/examples/shipping/voyage"
)
// Leg describes the transportation between two locations on a voyage.
type Leg struct {
VoyageNumber voyage.Number `json:"voyage_number"`
LoadLocation location.UNLocode `json:"from"`
UnloadLocation location.UNLocode `json:"to"`
LoadTime time.Time `json:"load_time"`
UnloadTime time.Time `json:"unload_time"`
}
// NewLeg creates a new itinerary leg.
func NewLeg(voyageNumber voyage.Number, loadLocation, unloadLocation location.UNLocode, loadTime, unloadTime time.Time) Leg {
return Leg{
VoyageNumber: voyageNumber,
LoadLocation: loadLocation,
UnloadLocation: unloadLocation,
LoadTime: loadTime,
UnloadTime: unloadTime,
}
}
// Itinerary specifies steps required to transport a cargo from its origin to
// destination.
type Itinerary struct {
Legs []Leg `json:"legs"`
}
// InitialDepartureLocation returns the start of the itinerary.
func (i Itinerary) InitialDepartureLocation() location.UNLocode {
if i.IsEmpty() {
return location.UNLocode("")
}
return i.Legs[0].LoadLocation
}
// FinalArrivalLocation returns the end of the itinerary.
func (i Itinerary) FinalArrivalLocation() location.UNLocode {
if i.IsEmpty() {
return location.UNLocode("")
}
return i.Legs[len(i.Legs)-1].UnloadLocation
}
// FinalArrivalTime returns the expected arrival time at final destination.
func (i Itinerary) FinalArrivalTime() time.Time {
return i.Legs[len(i.Legs)-1].UnloadTime
}
// IsEmpty checks if the itinerary contains at least one leg.
func (i Itinerary) IsEmpty() bool {
return i.Legs == nil || len(i.Legs) == 0
}
// IsExpected checks if the given handling event is expected when executing
// this itinerary.
func (i Itinerary) IsExpected(event HandlingEvent) bool {
if i.IsEmpty() {
return true
}
switch event.Activity.Type {
case Receive:
return i.InitialDepartureLocation() == event.Activity.Location
case Load:
for _, l := range i.Legs {
if l.LoadLocation == event.Activity.Location && l.VoyageNumber == event.Activity.VoyageNumber {
return true
}
}
return false
case Unload:
for _, l := range i.Legs {
if l.UnloadLocation == event.Activity.Location && l.VoyageNumber == event.Activity.VoyageNumber {
return true
}
}
return false
case Claim:
return i.FinalArrivalLocation() == event.Activity.Location
}
return true
}
golang-github-go-kit-kit-0.10.0/examples/shipping/handling/ 0000775 0000000 0000000 00000000000 13622563124 0023523 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/shipping/handling/endpoint.go 0000664 0000000 0000000 00000001640 13622563124 0025673 0 ustar 00root root 0000000 0000000 package handling
import (
"context"
"time"
"github.com/go-kit/kit/endpoint"
"github.com/go-kit/kit/examples/shipping/cargo"
"github.com/go-kit/kit/examples/shipping/location"
"github.com/go-kit/kit/examples/shipping/voyage"
)
type registerIncidentRequest struct {
ID cargo.TrackingID
Location location.UNLocode
Voyage voyage.Number
EventType cargo.HandlingEventType
CompletionTime time.Time
}
type registerIncidentResponse struct {
Err error `json:"error,omitempty"`
}
func (r registerIncidentResponse) error() error { return r.Err }
func makeRegisterIncidentEndpoint(hs Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(registerIncidentRequest)
err := hs.RegisterHandlingEvent(req.CompletionTime, req.ID, req.Voyage, req.Location, req.EventType)
return registerIncidentResponse{Err: err}, nil
}
}
golang-github-go-kit-kit-0.10.0/examples/shipping/handling/instrumenting.go 0000664 0000000 0000000 00000002120 13622563124 0026753 0 ustar 00root root 0000000 0000000 package handling
import (
"time"
"github.com/go-kit/kit/metrics"
"github.com/go-kit/kit/examples/shipping/cargo"
"github.com/go-kit/kit/examples/shipping/location"
"github.com/go-kit/kit/examples/shipping/voyage"
)
type instrumentingService struct {
requestCount metrics.Counter
requestLatency metrics.Histogram
Service
}
// NewInstrumentingService returns an instance of an instrumenting Service.
func NewInstrumentingService(counter metrics.Counter, latency metrics.Histogram, s Service) Service {
return &instrumentingService{
requestCount: counter,
requestLatency: latency,
Service: s,
}
}
func (s *instrumentingService) RegisterHandlingEvent(completed time.Time, id cargo.TrackingID, voyageNumber voyage.Number,
loc location.UNLocode, eventType cargo.HandlingEventType) error {
defer func(begin time.Time) {
s.requestCount.With("method", "register_incident").Add(1)
s.requestLatency.With("method", "register_incident").Observe(time.Since(begin).Seconds())
}(time.Now())
return s.Service.RegisterHandlingEvent(completed, id, voyageNumber, loc, eventType)
}
golang-github-go-kit-kit-0.10.0/examples/shipping/handling/logging.go 0000664 0000000 0000000 00000001766 13622563124 0025512 0 ustar 00root root 0000000 0000000 package handling
import (
"time"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/examples/shipping/cargo"
"github.com/go-kit/kit/examples/shipping/location"
"github.com/go-kit/kit/examples/shipping/voyage"
)
type loggingService struct {
logger log.Logger
Service
}
// NewLoggingService returns a new instance of a logging Service.
func NewLoggingService(logger log.Logger, s Service) Service {
return &loggingService{logger, s}
}
func (s *loggingService) RegisterHandlingEvent(completed time.Time, id cargo.TrackingID, voyageNumber voyage.Number,
unLocode location.UNLocode, eventType cargo.HandlingEventType) (err error) {
defer func(begin time.Time) {
s.logger.Log(
"method", "register_incident",
"tracking_id", id,
"location", unLocode,
"voyage", voyageNumber,
"event_type", eventType,
"completion_time", completed,
"took", time.Since(begin),
"err", err,
)
}(time.Now())
return s.Service.RegisterHandlingEvent(completed, id, voyageNumber, unLocode, eventType)
}
golang-github-go-kit-kit-0.10.0/examples/shipping/handling/service.go 0000664 0000000 0000000 00000004572 13622563124 0025522 0 ustar 00root root 0000000 0000000 // Package handling provides the use-case for registering incidents. Used by
// views facing the people handling the cargo along its route.
package handling
import (
"errors"
"time"
"github.com/go-kit/kit/examples/shipping/cargo"
"github.com/go-kit/kit/examples/shipping/inspection"
"github.com/go-kit/kit/examples/shipping/location"
"github.com/go-kit/kit/examples/shipping/voyage"
)
// ErrInvalidArgument is returned when one or more arguments are invalid.
var ErrInvalidArgument = errors.New("invalid argument")
// EventHandler provides a means of subscribing to registered handling events.
type EventHandler interface {
CargoWasHandled(cargo.HandlingEvent)
}
// Service provides handling operations.
type Service interface {
// RegisterHandlingEvent registers a handling event in the system, and
// notifies interested parties that a cargo has been handled.
RegisterHandlingEvent(completed time.Time, id cargo.TrackingID, voyageNumber voyage.Number,
unLocode location.UNLocode, eventType cargo.HandlingEventType) error
}
type service struct {
handlingEventRepository cargo.HandlingEventRepository
handlingEventFactory cargo.HandlingEventFactory
handlingEventHandler EventHandler
}
func (s *service) RegisterHandlingEvent(completed time.Time, id cargo.TrackingID, voyageNumber voyage.Number,
loc location.UNLocode, eventType cargo.HandlingEventType) error {
if completed.IsZero() || id == "" || loc == "" || eventType == cargo.NotHandled {
return ErrInvalidArgument
}
e, err := s.handlingEventFactory.CreateHandlingEvent(time.Now(), completed, id, voyageNumber, loc, eventType)
if err != nil {
return err
}
s.handlingEventRepository.Store(e)
s.handlingEventHandler.CargoWasHandled(e)
return nil
}
// NewService creates a handling event service with necessary dependencies.
func NewService(r cargo.HandlingEventRepository, f cargo.HandlingEventFactory, h EventHandler) Service {
return &service{
handlingEventRepository: r,
handlingEventFactory: f,
handlingEventHandler: h,
}
}
type handlingEventHandler struct {
InspectionService inspection.Service
}
func (h *handlingEventHandler) CargoWasHandled(event cargo.HandlingEvent) {
h.InspectionService.InspectCargo(event.TrackingID)
}
// NewEventHandler returns a new instance of a EventHandler.
func NewEventHandler(s inspection.Service) EventHandler {
return &handlingEventHandler{
InspectionService: s,
}
}
golang-github-go-kit-kit-0.10.0/examples/shipping/handling/transport.go 0000664 0000000 0000000 00000005342 13622563124 0026112 0 ustar 00root root 0000000 0000000 package handling
import (
"context"
"encoding/json"
"net/http"
"time"
"github.com/gorilla/mux"
kitlog "github.com/go-kit/kit/log"
"github.com/go-kit/kit/transport"
kithttp "github.com/go-kit/kit/transport/http"
"github.com/go-kit/kit/examples/shipping/cargo"
"github.com/go-kit/kit/examples/shipping/location"
"github.com/go-kit/kit/examples/shipping/voyage"
)
// MakeHandler returns a handler for the handling service.
func MakeHandler(hs Service, logger kitlog.Logger) http.Handler {
r := mux.NewRouter()
opts := []kithttp.ServerOption{
kithttp.ServerErrorHandler(transport.NewLogErrorHandler(logger)),
kithttp.ServerErrorEncoder(encodeError),
}
registerIncidentHandler := kithttp.NewServer(
makeRegisterIncidentEndpoint(hs),
decodeRegisterIncidentRequest,
encodeResponse,
opts...,
)
r.Handle("/handling/v1/incidents", registerIncidentHandler).Methods("POST")
return r
}
func decodeRegisterIncidentRequest(_ context.Context, r *http.Request) (interface{}, error) {
var body struct {
CompletionTime time.Time `json:"completion_time"`
TrackingID string `json:"tracking_id"`
VoyageNumber string `json:"voyage"`
Location string `json:"location"`
EventType string `json:"event_type"`
}
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
return nil, err
}
return registerIncidentRequest{
CompletionTime: body.CompletionTime,
ID: cargo.TrackingID(body.TrackingID),
Voyage: voyage.Number(body.VoyageNumber),
Location: location.UNLocode(body.Location),
EventType: stringToEventType(body.EventType),
}, nil
}
func stringToEventType(s string) cargo.HandlingEventType {
types := map[string]cargo.HandlingEventType{
cargo.Receive.String(): cargo.Receive,
cargo.Load.String(): cargo.Load,
cargo.Unload.String(): cargo.Unload,
cargo.Customs.String(): cargo.Customs,
cargo.Claim.String(): cargo.Claim,
}
return types[s]
}
func encodeResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error {
if e, ok := response.(errorer); ok && e.error() != nil {
encodeError(ctx, e.error(), w)
return nil
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
type errorer interface {
error() error
}
// encode errors from business-logic
func encodeError(_ context.Context, err error, w http.ResponseWriter) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
switch err {
case cargo.ErrUnknown:
w.WriteHeader(http.StatusNotFound)
case ErrInvalidArgument:
w.WriteHeader(http.StatusBadRequest)
default:
w.WriteHeader(http.StatusInternalServerError)
}
json.NewEncoder(w).Encode(map[string]interface{}{
"error": err.Error(),
})
}
golang-github-go-kit-kit-0.10.0/examples/shipping/inmem/ 0000775 0000000 0000000 00000000000 13622563124 0023044 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/shipping/inmem/inmem.go 0000664 0000000 0000000 00000007442 13622563124 0024507 0 ustar 00root root 0000000 0000000 // Package inmem provides in-memory implementations of all the domain repositories.
package inmem
import (
"sync"
"github.com/go-kit/kit/examples/shipping/cargo"
"github.com/go-kit/kit/examples/shipping/location"
"github.com/go-kit/kit/examples/shipping/voyage"
)
type cargoRepository struct {
mtx sync.RWMutex
cargos map[cargo.TrackingID]*cargo.Cargo
}
func (r *cargoRepository) Store(c *cargo.Cargo) error {
r.mtx.Lock()
defer r.mtx.Unlock()
r.cargos[c.TrackingID] = c
return nil
}
func (r *cargoRepository) Find(id cargo.TrackingID) (*cargo.Cargo, error) {
r.mtx.RLock()
defer r.mtx.RUnlock()
if val, ok := r.cargos[id]; ok {
return val, nil
}
return nil, cargo.ErrUnknown
}
func (r *cargoRepository) FindAll() []*cargo.Cargo {
r.mtx.RLock()
defer r.mtx.RUnlock()
c := make([]*cargo.Cargo, 0, len(r.cargos))
for _, val := range r.cargos {
c = append(c, val)
}
return c
}
// NewCargoRepository returns a new instance of a in-memory cargo repository.
func NewCargoRepository() cargo.Repository {
return &cargoRepository{
cargos: make(map[cargo.TrackingID]*cargo.Cargo),
}
}
type locationRepository struct {
locations map[location.UNLocode]*location.Location
}
func (r *locationRepository) Find(locode location.UNLocode) (*location.Location, error) {
if l, ok := r.locations[locode]; ok {
return l, nil
}
return nil, location.ErrUnknown
}
func (r *locationRepository) FindAll() []*location.Location {
l := make([]*location.Location, 0, len(r.locations))
for _, val := range r.locations {
l = append(l, val)
}
return l
}
// NewLocationRepository returns a new instance of a in-memory location repository.
func NewLocationRepository() location.Repository {
r := &locationRepository{
locations: make(map[location.UNLocode]*location.Location),
}
r.locations[location.SESTO] = location.Stockholm
r.locations[location.AUMEL] = location.Melbourne
r.locations[location.CNHKG] = location.Hongkong
r.locations[location.JNTKO] = location.Tokyo
r.locations[location.NLRTM] = location.Rotterdam
r.locations[location.DEHAM] = location.Hamburg
return r
}
type voyageRepository struct {
voyages map[voyage.Number]*voyage.Voyage
}
func (r *voyageRepository) Find(voyageNumber voyage.Number) (*voyage.Voyage, error) {
if v, ok := r.voyages[voyageNumber]; ok {
return v, nil
}
return nil, voyage.ErrUnknown
}
// NewVoyageRepository returns a new instance of a in-memory voyage repository.
func NewVoyageRepository() voyage.Repository {
r := &voyageRepository{
voyages: make(map[voyage.Number]*voyage.Voyage),
}
r.voyages[voyage.V100.Number] = voyage.V100
r.voyages[voyage.V300.Number] = voyage.V300
r.voyages[voyage.V400.Number] = voyage.V400
r.voyages[voyage.V0100S.Number] = voyage.V0100S
r.voyages[voyage.V0200T.Number] = voyage.V0200T
r.voyages[voyage.V0300A.Number] = voyage.V0300A
r.voyages[voyage.V0301S.Number] = voyage.V0301S
r.voyages[voyage.V0400S.Number] = voyage.V0400S
return r
}
type handlingEventRepository struct {
mtx sync.RWMutex
events map[cargo.TrackingID][]cargo.HandlingEvent
}
func (r *handlingEventRepository) Store(e cargo.HandlingEvent) {
r.mtx.Lock()
defer r.mtx.Unlock()
// Make array if it's the first event with this tracking ID.
if _, ok := r.events[e.TrackingID]; !ok {
r.events[e.TrackingID] = make([]cargo.HandlingEvent, 0)
}
r.events[e.TrackingID] = append(r.events[e.TrackingID], e)
}
func (r *handlingEventRepository) QueryHandlingHistory(id cargo.TrackingID) cargo.HandlingHistory {
r.mtx.RLock()
defer r.mtx.RUnlock()
return cargo.HandlingHistory{HandlingEvents: r.events[id]}
}
// NewHandlingEventRepository returns a new instance of a in-memory handling event repository.
func NewHandlingEventRepository() cargo.HandlingEventRepository {
return &handlingEventRepository{
events: make(map[cargo.TrackingID][]cargo.HandlingEvent),
}
}
golang-github-go-kit-kit-0.10.0/examples/shipping/inspection/ 0000775 0000000 0000000 00000000000 13622563124 0024112 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/shipping/inspection/inspection.go 0000664 0000000 0000000 00000002446 13622563124 0026622 0 ustar 00root root 0000000 0000000 // Package inspection provides means to inspect cargos.
package inspection
import (
"github.com/go-kit/kit/examples/shipping/cargo"
)
// EventHandler provides means of subscribing to inspection events.
type EventHandler interface {
CargoWasMisdirected(*cargo.Cargo)
CargoHasArrived(*cargo.Cargo)
}
// Service provides cargo inspection operations.
type Service interface {
// InspectCargo inspects cargo and send relevant notifications to
// interested parties, for example if a cargo has been misdirected, or
// unloaded at the final destination.
InspectCargo(id cargo.TrackingID)
}
type service struct {
cargos cargo.Repository
events cargo.HandlingEventRepository
handler EventHandler
}
// TODO: Should be transactional
func (s *service) InspectCargo(id cargo.TrackingID) {
c, err := s.cargos.Find(id)
if err != nil {
return
}
h := s.events.QueryHandlingHistory(id)
c.DeriveDeliveryProgress(h)
if c.Delivery.IsMisdirected {
s.handler.CargoWasMisdirected(c)
}
if c.Delivery.IsUnloadedAtDestination {
s.handler.CargoHasArrived(c)
}
s.cargos.Store(c)
}
// NewService creates a inspection service with necessary dependencies.
func NewService(cargos cargo.Repository, events cargo.HandlingEventRepository, handler EventHandler) Service {
return &service{cargos, events, handler}
}
golang-github-go-kit-kit-0.10.0/examples/shipping/location/ 0000775 0000000 0000000 00000000000 13622563124 0023547 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/shipping/location/location.go 0000664 0000000 0000000 00000001403 13622563124 0025704 0 ustar 00root root 0000000 0000000 // Package location provides the Location aggregate.
package location
import (
"errors"
)
// UNLocode is the United Nations location code that uniquely identifies a
// particular location.
//
// http://www.unece.org/cefact/locode/
// http://www.unece.org/cefact/locode/DocColumnDescription.htm#LOCODE
type UNLocode string
// Location is a location is our model is stops on a journey, such as cargo
// origin or destination, or carrier movement endpoints.
type Location struct {
UNLocode UNLocode
Name string
}
// ErrUnknown is used when a location could not be found.
var ErrUnknown = errors.New("unknown location")
// Repository provides access a location store.
type Repository interface {
Find(locode UNLocode) (*Location, error)
FindAll() []*Location
}
golang-github-go-kit-kit-0.10.0/examples/shipping/location/sample_locations.go 0000664 0000000 0000000 00000001260 13622563124 0027431 0 ustar 00root root 0000000 0000000 package location
// Sample UN locodes.
var (
SESTO UNLocode = "SESTO"
AUMEL UNLocode = "AUMEL"
CNHKG UNLocode = "CNHKG"
USNYC UNLocode = "USNYC"
USCHI UNLocode = "USCHI"
JNTKO UNLocode = "JNTKO"
DEHAM UNLocode = "DEHAM"
NLRTM UNLocode = "NLRTM"
FIHEL UNLocode = "FIHEL"
)
// Sample locations.
var (
Stockholm = &Location{SESTO, "Stockholm"}
Melbourne = &Location{AUMEL, "Melbourne"}
Hongkong = &Location{CNHKG, "Hongkong"}
NewYork = &Location{USNYC, "New York"}
Chicago = &Location{USCHI, "Chicago"}
Tokyo = &Location{JNTKO, "Tokyo"}
Hamburg = &Location{DEHAM, "Hamburg"}
Rotterdam = &Location{NLRTM, "Rotterdam"}
Helsinki = &Location{FIHEL, "Helsinki"}
)
golang-github-go-kit-kit-0.10.0/examples/shipping/main.go 0000664 0000000 0000000 00000013136 13622563124 0023216 0 ustar 00root root 0000000 0000000 package main
import (
"context"
"flag"
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"time"
stdprometheus "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/go-kit/kit/log"
kitprometheus "github.com/go-kit/kit/metrics/prometheus"
"github.com/go-kit/kit/examples/shipping/booking"
"github.com/go-kit/kit/examples/shipping/cargo"
"github.com/go-kit/kit/examples/shipping/handling"
"github.com/go-kit/kit/examples/shipping/inmem"
"github.com/go-kit/kit/examples/shipping/inspection"
"github.com/go-kit/kit/examples/shipping/location"
"github.com/go-kit/kit/examples/shipping/routing"
"github.com/go-kit/kit/examples/shipping/tracking"
)
const (
defaultPort = "8080"
defaultRoutingServiceURL = "http://localhost:7878"
)
func main() {
var (
addr = envString("PORT", defaultPort)
rsurl = envString("ROUTINGSERVICE_URL", defaultRoutingServiceURL)
httpAddr = flag.String("http.addr", ":"+addr, "HTTP listen address")
routingServiceURL = flag.String("service.routing", rsurl, "routing service URL")
ctx = context.Background()
)
flag.Parse()
var logger log.Logger
logger = log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr))
logger = log.With(logger, "ts", log.DefaultTimestampUTC)
var (
cargos = inmem.NewCargoRepository()
locations = inmem.NewLocationRepository()
voyages = inmem.NewVoyageRepository()
handlingEvents = inmem.NewHandlingEventRepository()
)
// Configure some questionable dependencies.
var (
handlingEventFactory = cargo.HandlingEventFactory{
CargoRepository: cargos,
VoyageRepository: voyages,
LocationRepository: locations,
}
handlingEventHandler = handling.NewEventHandler(
inspection.NewService(cargos, handlingEvents, nil),
)
)
// Facilitate testing by adding some cargos.
storeTestData(cargos)
fieldKeys := []string{"method"}
var rs routing.Service
rs = routing.NewProxyingMiddleware(ctx, *routingServiceURL)(rs)
var bs booking.Service
bs = booking.NewService(cargos, locations, handlingEvents, rs)
bs = booking.NewLoggingService(log.With(logger, "component", "booking"), bs)
bs = booking.NewInstrumentingService(
kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
Namespace: "api",
Subsystem: "booking_service",
Name: "request_count",
Help: "Number of requests received.",
}, fieldKeys),
kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
Namespace: "api",
Subsystem: "booking_service",
Name: "request_latency_microseconds",
Help: "Total duration of requests in microseconds.",
}, fieldKeys),
bs,
)
var ts tracking.Service
ts = tracking.NewService(cargos, handlingEvents)
ts = tracking.NewLoggingService(log.With(logger, "component", "tracking"), ts)
ts = tracking.NewInstrumentingService(
kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
Namespace: "api",
Subsystem: "tracking_service",
Name: "request_count",
Help: "Number of requests received.",
}, fieldKeys),
kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
Namespace: "api",
Subsystem: "tracking_service",
Name: "request_latency_microseconds",
Help: "Total duration of requests in microseconds.",
}, fieldKeys),
ts,
)
var hs handling.Service
hs = handling.NewService(handlingEvents, handlingEventFactory, handlingEventHandler)
hs = handling.NewLoggingService(log.With(logger, "component", "handling"), hs)
hs = handling.NewInstrumentingService(
kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
Namespace: "api",
Subsystem: "handling_service",
Name: "request_count",
Help: "Number of requests received.",
}, fieldKeys),
kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
Namespace: "api",
Subsystem: "handling_service",
Name: "request_latency_microseconds",
Help: "Total duration of requests in microseconds.",
}, fieldKeys),
hs,
)
httpLogger := log.With(logger, "component", "http")
mux := http.NewServeMux()
mux.Handle("/booking/v1/", booking.MakeHandler(bs, httpLogger))
mux.Handle("/tracking/v1/", tracking.MakeHandler(ts, httpLogger))
mux.Handle("/handling/v1/", handling.MakeHandler(hs, httpLogger))
http.Handle("/", accessControl(mux))
http.Handle("/metrics", promhttp.Handler())
errs := make(chan error, 2)
go func() {
logger.Log("transport", "http", "address", *httpAddr, "msg", "listening")
errs <- http.ListenAndServe(*httpAddr, nil)
}()
go func() {
c := make(chan os.Signal)
signal.Notify(c, syscall.SIGINT)
errs <- fmt.Errorf("%s", <-c)
}()
logger.Log("terminated", <-errs)
}
func accessControl(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Origin, Content-Type")
if r.Method == "OPTIONS" {
return
}
h.ServeHTTP(w, r)
})
}
func envString(env, fallback string) string {
e := os.Getenv(env)
if e == "" {
return fallback
}
return e
}
func storeTestData(r cargo.Repository) {
test1 := cargo.New("FTL456", cargo.RouteSpecification{
Origin: location.AUMEL,
Destination: location.SESTO,
ArrivalDeadline: time.Now().AddDate(0, 0, 7),
})
if err := r.Store(test1); err != nil {
panic(err)
}
test2 := cargo.New("ABC123", cargo.RouteSpecification{
Origin: location.SESTO,
Destination: location.CNHKG,
ArrivalDeadline: time.Now().AddDate(0, 0, 14),
})
if err := r.Store(test2); err != nil {
panic(err)
}
}
golang-github-go-kit-kit-0.10.0/examples/shipping/routing/ 0000775 0000000 0000000 00000000000 13622563124 0023426 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/shipping/routing/proxying.go 0000664 0000000 0000000 00000005537 13622563124 0025646 0 ustar 00root root 0000000 0000000 package routing
import (
"context"
"encoding/json"
"net/http"
"net/url"
"time"
"github.com/go-kit/kit/circuitbreaker"
"github.com/go-kit/kit/endpoint"
kithttp "github.com/go-kit/kit/transport/http"
"github.com/go-kit/kit/examples/shipping/cargo"
"github.com/go-kit/kit/examples/shipping/location"
"github.com/go-kit/kit/examples/shipping/voyage"
)
type proxyService struct {
context.Context
FetchRoutesEndpoint endpoint.Endpoint
Service
}
func (s proxyService) FetchRoutesForSpecification(rs cargo.RouteSpecification) []cargo.Itinerary {
response, err := s.FetchRoutesEndpoint(s.Context, fetchRoutesRequest{
From: string(rs.Origin),
To: string(rs.Destination),
})
if err != nil {
return []cargo.Itinerary{}
}
resp := response.(fetchRoutesResponse)
var itineraries []cargo.Itinerary
for _, r := range resp.Paths {
var legs []cargo.Leg
for _, e := range r.Edges {
legs = append(legs, cargo.Leg{
VoyageNumber: voyage.Number(e.Voyage),
LoadLocation: location.UNLocode(e.Origin),
UnloadLocation: location.UNLocode(e.Destination),
LoadTime: e.Departure,
UnloadTime: e.Arrival,
})
}
itineraries = append(itineraries, cargo.Itinerary{Legs: legs})
}
return itineraries
}
// ServiceMiddleware defines a middleware for a routing service.
type ServiceMiddleware func(Service) Service
// NewProxyingMiddleware returns a new instance of a proxying middleware.
func NewProxyingMiddleware(ctx context.Context, proxyURL string) ServiceMiddleware {
return func(next Service) Service {
var e endpoint.Endpoint
e = makeFetchRoutesEndpoint(ctx, proxyURL)
e = circuitbreaker.Hystrix("fetch-routes")(e)
return proxyService{ctx, e, next}
}
}
type fetchRoutesRequest struct {
From string
To string
}
type fetchRoutesResponse struct {
Paths []struct {
Edges []struct {
Origin string `json:"origin"`
Destination string `json:"destination"`
Voyage string `json:"voyage"`
Departure time.Time `json:"departure"`
Arrival time.Time `json:"arrival"`
} `json:"edges"`
} `json:"paths"`
}
func makeFetchRoutesEndpoint(ctx context.Context, instance string) endpoint.Endpoint {
u, err := url.Parse(instance)
if err != nil {
panic(err)
}
if u.Path == "" {
u.Path = "/paths"
}
return kithttp.NewClient(
"GET", u,
encodeFetchRoutesRequest,
decodeFetchRoutesResponse,
).Endpoint()
}
func decodeFetchRoutesResponse(_ context.Context, resp *http.Response) (interface{}, error) {
var response fetchRoutesResponse
if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
return nil, err
}
return response, nil
}
func encodeFetchRoutesRequest(_ context.Context, r *http.Request, request interface{}) error {
req := request.(fetchRoutesRequest)
vals := r.URL.Query()
vals.Add("from", req.From)
vals.Add("to", req.To)
r.URL.RawQuery = vals.Encode()
return nil
}
golang-github-go-kit-kit-0.10.0/examples/shipping/routing/routing.go 0000664 0000000 0000000 00000000776 13622563124 0025456 0 ustar 00root root 0000000 0000000 // Package routing provides the routing domain service. It does not actually
// implement the routing service but merely acts as a proxy for a separate
// bounded context.
package routing
import (
"github.com/go-kit/kit/examples/shipping/cargo"
)
// Service provides access to an external routing service.
type Service interface {
// FetchRoutesForSpecification finds all possible routes that satisfy a
// given specification.
FetchRoutesForSpecification(rs cargo.RouteSpecification) []cargo.Itinerary
}
golang-github-go-kit-kit-0.10.0/examples/shipping/tracking/ 0000775 0000000 0000000 00000000000 13622563124 0023541 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/shipping/tracking/endpoint.go 0000664 0000000 0000000 00000001057 13622563124 0025713 0 ustar 00root root 0000000 0000000 package tracking
import (
"context"
"github.com/go-kit/kit/endpoint"
)
type trackCargoRequest struct {
ID string
}
type trackCargoResponse struct {
Cargo *Cargo `json:"cargo,omitempty"`
Err error `json:"error,omitempty"`
}
func (r trackCargoResponse) error() error { return r.Err }
func makeTrackCargoEndpoint(ts Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(trackCargoRequest)
c, err := ts.Track(req.ID)
return trackCargoResponse{Cargo: &c, Err: err}, nil
}
}
golang-github-go-kit-kit-0.10.0/examples/shipping/tracking/instrumenting.go 0000664 0000000 0000000 00000001351 13622563124 0026776 0 ustar 00root root 0000000 0000000 package tracking
import (
"time"
"github.com/go-kit/kit/metrics"
)
type instrumentingService struct {
requestCount metrics.Counter
requestLatency metrics.Histogram
Service
}
// NewInstrumentingService returns an instance of an instrumenting Service.
func NewInstrumentingService(counter metrics.Counter, latency metrics.Histogram, s Service) Service {
return &instrumentingService{
requestCount: counter,
requestLatency: latency,
Service: s,
}
}
func (s *instrumentingService) Track(id string) (Cargo, error) {
defer func(begin time.Time) {
s.requestCount.With("method", "track").Add(1)
s.requestLatency.With("method", "track").Observe(time.Since(begin).Seconds())
}(time.Now())
return s.Service.Track(id)
}
golang-github-go-kit-kit-0.10.0/examples/shipping/tracking/logging.go 0000664 0000000 0000000 00000001020 13622563124 0025507 0 ustar 00root root 0000000 0000000 package tracking
import (
"time"
"github.com/go-kit/kit/log"
)
type loggingService struct {
logger log.Logger
Service
}
// NewLoggingService returns a new instance of a logging Service.
func NewLoggingService(logger log.Logger, s Service) Service {
return &loggingService{logger, s}
}
func (s *loggingService) Track(id string) (c Cargo, err error) {
defer func(begin time.Time) {
s.logger.Log("method", "track", "tracking_id", id, "took", time.Since(begin), "err", err)
}(time.Now())
return s.Service.Track(id)
}
golang-github-go-kit-kit-0.10.0/examples/shipping/tracking/service.go 0000664 0000000 0000000 00000012001 13622563124 0025522 0 ustar 00root root 0000000 0000000 // Package tracking provides the use-case of tracking a cargo. Used by views
// facing the end-user.
package tracking
import (
"errors"
"fmt"
"strings"
"time"
"github.com/go-kit/kit/examples/shipping/cargo"
)
// ErrInvalidArgument is returned when one or more arguments are invalid.
var ErrInvalidArgument = errors.New("invalid argument")
// Service is the interface that provides the basic Track method.
type Service interface {
// Track returns a cargo matching a tracking ID.
Track(id string) (Cargo, error)
}
type service struct {
cargos cargo.Repository
handlingEvents cargo.HandlingEventRepository
}
func (s *service) Track(id string) (Cargo, error) {
if id == "" {
return Cargo{}, ErrInvalidArgument
}
c, err := s.cargos.Find(cargo.TrackingID(id))
if err != nil {
return Cargo{}, err
}
return assemble(c, s.handlingEvents), nil
}
// NewService returns a new instance of the default Service.
func NewService(cargos cargo.Repository, events cargo.HandlingEventRepository) Service {
return &service{
cargos: cargos,
handlingEvents: events,
}
}
// Cargo is a read model for tracking views.
type Cargo struct {
TrackingID string `json:"tracking_id"`
StatusText string `json:"status_text"`
Origin string `json:"origin"`
Destination string `json:"destination"`
ETA time.Time `json:"eta"`
NextExpectedActivity string `json:"next_expected_activity"`
ArrivalDeadline time.Time `json:"arrival_deadline"`
Events []Event `json:"events"`
}
// Leg is a read model for booking views.
type Leg struct {
VoyageNumber string `json:"voyage_number"`
From string `json:"from"`
To string `json:"to"`
LoadTime time.Time `json:"load_time"`
UnloadTime time.Time `json:"unload_time"`
}
// Event is a read model for tracking views.
type Event struct {
Description string `json:"description"`
Expected bool `json:"expected"`
}
func assemble(c *cargo.Cargo, events cargo.HandlingEventRepository) Cargo {
return Cargo{
TrackingID: string(c.TrackingID),
Origin: string(c.Origin),
Destination: string(c.RouteSpecification.Destination),
ETA: c.Delivery.ETA,
NextExpectedActivity: nextExpectedActivity(c),
ArrivalDeadline: c.RouteSpecification.ArrivalDeadline,
StatusText: assembleStatusText(c),
Events: assembleEvents(c, events),
}
}
func assembleLegs(c cargo.Cargo) []Leg {
var legs []Leg
for _, l := range c.Itinerary.Legs {
legs = append(legs, Leg{
VoyageNumber: string(l.VoyageNumber),
From: string(l.LoadLocation),
To: string(l.UnloadLocation),
LoadTime: l.LoadTime,
UnloadTime: l.UnloadTime,
})
}
return legs
}
func nextExpectedActivity(c *cargo.Cargo) string {
a := c.Delivery.NextExpectedActivity
prefix := "Next expected activity is to"
switch a.Type {
case cargo.Load:
return fmt.Sprintf("%s %s cargo onto voyage %s in %s.", prefix, strings.ToLower(a.Type.String()), a.VoyageNumber, a.Location)
case cargo.Unload:
return fmt.Sprintf("%s %s cargo off of voyage %s in %s.", prefix, strings.ToLower(a.Type.String()), a.VoyageNumber, a.Location)
case cargo.NotHandled:
return "There are currently no expected activities for this cargo."
}
return fmt.Sprintf("%s %s cargo in %s.", prefix, strings.ToLower(a.Type.String()), a.Location)
}
func assembleStatusText(c *cargo.Cargo) string {
switch c.Delivery.TransportStatus {
case cargo.NotReceived:
return "Not received"
case cargo.InPort:
return fmt.Sprintf("In port %s", c.Delivery.LastKnownLocation)
case cargo.OnboardCarrier:
return fmt.Sprintf("Onboard voyage %s", c.Delivery.CurrentVoyage)
case cargo.Claimed:
return "Claimed"
default:
return "Unknown"
}
}
func assembleEvents(c *cargo.Cargo, handlingEvents cargo.HandlingEventRepository) []Event {
h := handlingEvents.QueryHandlingHistory(c.TrackingID)
var events []Event
for _, e := range h.HandlingEvents {
var description string
switch e.Activity.Type {
case cargo.NotHandled:
description = "Cargo has not yet been received."
case cargo.Receive:
description = fmt.Sprintf("Received in %s, at %s", e.Activity.Location, time.Now().Format(time.RFC3339))
case cargo.Load:
description = fmt.Sprintf("Loaded onto voyage %s in %s, at %s.", e.Activity.VoyageNumber, e.Activity.Location, time.Now().Format(time.RFC3339))
case cargo.Unload:
description = fmt.Sprintf("Unloaded off voyage %s in %s, at %s.", e.Activity.VoyageNumber, e.Activity.Location, time.Now().Format(time.RFC3339))
case cargo.Claim:
description = fmt.Sprintf("Claimed in %s, at %s.", e.Activity.Location, time.Now().Format(time.RFC3339))
case cargo.Customs:
description = fmt.Sprintf("Cleared customs in %s, at %s.", e.Activity.Location, time.Now().Format(time.RFC3339))
default:
description = "[Unknown status]"
}
events = append(events, Event{
Description: description,
Expected: c.Itinerary.IsExpected(e),
})
}
return events
}
golang-github-go-kit-kit-0.10.0/examples/shipping/tracking/transport.go 0000664 0000000 0000000 00000003466 13622563124 0026135 0 ustar 00root root 0000000 0000000 package tracking
import (
"context"
"encoding/json"
"errors"
"net/http"
"github.com/gorilla/mux"
kitlog "github.com/go-kit/kit/log"
kittransport "github.com/go-kit/kit/transport"
kithttp "github.com/go-kit/kit/transport/http"
"github.com/go-kit/kit/examples/shipping/cargo"
)
// MakeHandler returns a handler for the tracking service.
func MakeHandler(ts Service, logger kitlog.Logger) http.Handler {
r := mux.NewRouter()
opts := []kithttp.ServerOption{
kithttp.ServerErrorHandler(kittransport.NewLogErrorHandler(logger)),
kithttp.ServerErrorEncoder(encodeError),
}
trackCargoHandler := kithttp.NewServer(
makeTrackCargoEndpoint(ts),
decodeTrackCargoRequest,
encodeResponse,
opts...,
)
r.Handle("/tracking/v1/cargos/{id}", trackCargoHandler).Methods("GET")
return r
}
func decodeTrackCargoRequest(_ context.Context, r *http.Request) (interface{}, error) {
vars := mux.Vars(r)
id, ok := vars["id"]
if !ok {
return nil, errors.New("bad route")
}
return trackCargoRequest{ID: id}, nil
}
func encodeResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error {
if e, ok := response.(errorer); ok && e.error() != nil {
encodeError(ctx, e.error(), w)
return nil
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
type errorer interface {
error() error
}
// encode errors from business-logic
func encodeError(_ context.Context, err error, w http.ResponseWriter) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
switch err {
case cargo.ErrUnknown:
w.WriteHeader(http.StatusNotFound)
case ErrInvalidArgument:
w.WriteHeader(http.StatusBadRequest)
default:
w.WriteHeader(http.StatusInternalServerError)
}
json.NewEncoder(w).Encode(map[string]interface{}{
"error": err.Error(),
})
}
golang-github-go-kit-kit-0.10.0/examples/shipping/voyage/ 0000775 0000000 0000000 00000000000 13622563124 0023231 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/shipping/voyage/sample_voyages.go 0000664 0000000 0000000 00000002443 13622563124 0026601 0 ustar 00root root 0000000 0000000 package voyage
import "github.com/go-kit/kit/examples/shipping/location"
// A set of sample voyages.
var (
V100 = New("V100", Schedule{
[]CarrierMovement{
{DepartureLocation: location.CNHKG, ArrivalLocation: location.JNTKO},
{DepartureLocation: location.JNTKO, ArrivalLocation: location.USNYC},
},
})
V300 = New("V300", Schedule{
[]CarrierMovement{
{DepartureLocation: location.JNTKO, ArrivalLocation: location.NLRTM},
{DepartureLocation: location.NLRTM, ArrivalLocation: location.DEHAM},
{DepartureLocation: location.DEHAM, ArrivalLocation: location.AUMEL},
{DepartureLocation: location.AUMEL, ArrivalLocation: location.JNTKO},
},
})
V400 = New("V400", Schedule{
[]CarrierMovement{
{DepartureLocation: location.DEHAM, ArrivalLocation: location.SESTO},
{DepartureLocation: location.SESTO, ArrivalLocation: location.FIHEL},
{DepartureLocation: location.FIHEL, ArrivalLocation: location.DEHAM},
},
})
)
// These voyages are hard-coded into the current pathfinder. Make sure
// they exist.
var (
V0100S = New("0100S", Schedule{[]CarrierMovement{}})
V0200T = New("0200T", Schedule{[]CarrierMovement{}})
V0300A = New("0300A", Schedule{[]CarrierMovement{}})
V0301S = New("0301S", Schedule{[]CarrierMovement{}})
V0400S = New("0400S", Schedule{[]CarrierMovement{}})
)
golang-github-go-kit-kit-0.10.0/examples/shipping/voyage/voyage.go 0000664 0000000 0000000 00000002025 13622563124 0025051 0 ustar 00root root 0000000 0000000 // Package voyage provides the Voyage aggregate.
package voyage
import (
"errors"
"time"
"github.com/go-kit/kit/examples/shipping/location"
)
// Number uniquely identifies a particular Voyage.
type Number string
// Voyage is a uniquely identifiable series of carrier movements.
type Voyage struct {
Number Number
Schedule Schedule
}
// New creates a voyage with a voyage number and a provided schedule.
func New(n Number, s Schedule) *Voyage {
return &Voyage{Number: n, Schedule: s}
}
// Schedule describes a voyage schedule.
type Schedule struct {
CarrierMovements []CarrierMovement
}
// CarrierMovement is a vessel voyage from one location to another.
type CarrierMovement struct {
DepartureLocation location.UNLocode
ArrivalLocation location.UNLocode
DepartureTime time.Time
ArrivalTime time.Time
}
// ErrUnknown is used when a voyage could not be found.
var ErrUnknown = errors.New("unknown voyage")
// Repository provides access a voyage store.
type Repository interface {
Find(Number) (*Voyage, error)
}
golang-github-go-kit-kit-0.10.0/examples/stringsvc1/ 0000775 0000000 0000000 00000000000 13622563124 0022221 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/stringsvc1/main.go 0000664 0000000 0000000 00000005402 13622563124 0023475 0 ustar 00root root 0000000 0000000 package main
import (
"context"
"encoding/json"
"errors"
"log"
"net/http"
"strings"
"github.com/go-kit/kit/endpoint"
httptransport "github.com/go-kit/kit/transport/http"
)
// StringService provides operations on strings.
type StringService interface {
Uppercase(string) (string, error)
Count(string) int
}
// stringService is a concrete implementation of StringService
type stringService struct{}
func (stringService) Uppercase(s string) (string, error) {
if s == "" {
return "", ErrEmpty
}
return strings.ToUpper(s), nil
}
func (stringService) Count(s string) int {
return len(s)
}
// ErrEmpty is returned when an input string is empty.
var ErrEmpty = errors.New("empty string")
// For each method, we define request and response structs
type uppercaseRequest struct {
S string `json:"s"`
}
type uppercaseResponse struct {
V string `json:"v"`
Err string `json:"err,omitempty"` // errors don't define JSON marshaling
}
type countRequest struct {
S string `json:"s"`
}
type countResponse struct {
V int `json:"v"`
}
// Endpoints are a primary abstraction in go-kit. An endpoint represents a single RPC (method in our service interface)
func makeUppercaseEndpoint(svc StringService) endpoint.Endpoint {
return func(_ context.Context, request interface{}) (interface{}, error) {
req := request.(uppercaseRequest)
v, err := svc.Uppercase(req.S)
if err != nil {
return uppercaseResponse{v, err.Error()}, nil
}
return uppercaseResponse{v, ""}, nil
}
}
func makeCountEndpoint(svc StringService) endpoint.Endpoint {
return func(_ context.Context, request interface{}) (interface{}, error) {
req := request.(countRequest)
v := svc.Count(req.S)
return countResponse{v}, nil
}
}
// Transports expose the service to the network. In this first example we utilize JSON over HTTP.
func main() {
svc := stringService{}
uppercaseHandler := httptransport.NewServer(
makeUppercaseEndpoint(svc),
decodeUppercaseRequest,
encodeResponse,
)
countHandler := httptransport.NewServer(
makeCountEndpoint(svc),
decodeCountRequest,
encodeResponse,
)
http.Handle("/uppercase", uppercaseHandler)
http.Handle("/count", countHandler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
func decodeUppercaseRequest(_ context.Context, r *http.Request) (interface{}, error) {
var request uppercaseRequest
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
return nil, err
}
return request, nil
}
func decodeCountRequest(_ context.Context, r *http.Request) (interface{}, error) {
var request countRequest
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
return nil, err
}
return request, nil
}
func encodeResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
return json.NewEncoder(w).Encode(response)
}
golang-github-go-kit-kit-0.10.0/examples/stringsvc2/ 0000775 0000000 0000000 00000000000 13622563124 0022222 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/stringsvc2/instrumenting.go 0000664 0000000 0000000 00000001660 13622563124 0025462 0 ustar 00root root 0000000 0000000 package main
import (
"fmt"
"time"
"github.com/go-kit/kit/metrics"
)
type instrumentingMiddleware struct {
requestCount metrics.Counter
requestLatency metrics.Histogram
countResult metrics.Histogram
next StringService
}
func (mw instrumentingMiddleware) Uppercase(s string) (output string, err error) {
defer func(begin time.Time) {
lvs := []string{"method", "uppercase", "error", fmt.Sprint(err != nil)}
mw.requestCount.With(lvs...).Add(1)
mw.requestLatency.With(lvs...).Observe(time.Since(begin).Seconds())
}(time.Now())
output, err = mw.next.Uppercase(s)
return
}
func (mw instrumentingMiddleware) Count(s string) (n int) {
defer func(begin time.Time) {
lvs := []string{"method", "count", "error", "false"}
mw.requestCount.With(lvs...).Add(1)
mw.requestLatency.With(lvs...).Observe(time.Since(begin).Seconds())
mw.countResult.Observe(float64(n))
}(time.Now())
n = mw.next.Count(s)
return
}
golang-github-go-kit-kit-0.10.0/examples/stringsvc2/logging.go 0000664 0000000 0000000 00000001247 13622563124 0024203 0 ustar 00root root 0000000 0000000 package main
import (
"time"
"github.com/go-kit/kit/log"
)
type loggingMiddleware struct {
logger log.Logger
next StringService
}
func (mw loggingMiddleware) Uppercase(s string) (output string, err error) {
defer func(begin time.Time) {
_ = mw.logger.Log(
"method", "uppercase",
"input", s,
"output", output,
"err", err,
"took", time.Since(begin),
)
}(time.Now())
output, err = mw.next.Uppercase(s)
return
}
func (mw loggingMiddleware) Count(s string) (n int) {
defer func(begin time.Time) {
_ = mw.logger.Log(
"method", "count",
"input", s,
"n", n,
"took", time.Since(begin),
)
}(time.Now())
n = mw.next.Count(s)
return
}
golang-github-go-kit-kit-0.10.0/examples/stringsvc2/main.go 0000664 0000000 0000000 00000003323 13622563124 0023476 0 ustar 00root root 0000000 0000000 package main
import (
"net/http"
"os"
stdprometheus "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/go-kit/kit/log"
kitprometheus "github.com/go-kit/kit/metrics/prometheus"
httptransport "github.com/go-kit/kit/transport/http"
)
func main() {
logger := log.NewLogfmtLogger(os.Stderr)
fieldKeys := []string{"method", "error"}
requestCount := kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
Namespace: "my_group",
Subsystem: "string_service",
Name: "request_count",
Help: "Number of requests received.",
}, fieldKeys)
requestLatency := kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
Namespace: "my_group",
Subsystem: "string_service",
Name: "request_latency_microseconds",
Help: "Total duration of requests in microseconds.",
}, fieldKeys)
countResult := kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
Namespace: "my_group",
Subsystem: "string_service",
Name: "count_result",
Help: "The result of each count method.",
}, []string{}) // no fields here
var svc StringService
svc = stringService{}
svc = loggingMiddleware{logger, svc}
svc = instrumentingMiddleware{requestCount, requestLatency, countResult, svc}
uppercaseHandler := httptransport.NewServer(
makeUppercaseEndpoint(svc),
decodeUppercaseRequest,
encodeResponse,
)
countHandler := httptransport.NewServer(
makeCountEndpoint(svc),
decodeCountRequest,
encodeResponse,
)
http.Handle("/uppercase", uppercaseHandler)
http.Handle("/count", countHandler)
http.Handle("/metrics", promhttp.Handler())
logger.Log("msg", "HTTP", "addr", ":8080")
logger.Log("err", http.ListenAndServe(":8080", nil))
}
golang-github-go-kit-kit-0.10.0/examples/stringsvc2/service.go 0000664 0000000 0000000 00000000770 13622563124 0024215 0 ustar 00root root 0000000 0000000 package main
import (
"errors"
"strings"
)
// StringService provides operations on strings.
type StringService interface {
Uppercase(string) (string, error)
Count(string) int
}
type stringService struct{}
func (stringService) Uppercase(s string) (string, error) {
if s == "" {
return "", ErrEmpty
}
return strings.ToUpper(s), nil
}
func (stringService) Count(s string) int {
return len(s)
}
// ErrEmpty is returned when an input string is empty.
var ErrEmpty = errors.New("empty string")
golang-github-go-kit-kit-0.10.0/examples/stringsvc2/transport.go 0000664 0000000 0000000 00000002725 13622563124 0024613 0 ustar 00root root 0000000 0000000 package main
import (
"context"
"encoding/json"
"net/http"
"github.com/go-kit/kit/endpoint"
)
func makeUppercaseEndpoint(svc StringService) endpoint.Endpoint {
return func(_ context.Context, request interface{}) (interface{}, error) {
req := request.(uppercaseRequest)
v, err := svc.Uppercase(req.S)
if err != nil {
return uppercaseResponse{v, err.Error()}, nil
}
return uppercaseResponse{v, ""}, nil
}
}
func makeCountEndpoint(svc StringService) endpoint.Endpoint {
return func(_ context.Context, request interface{}) (interface{}, error) {
req := request.(countRequest)
v := svc.Count(req.S)
return countResponse{v}, nil
}
}
func decodeUppercaseRequest(_ context.Context, r *http.Request) (interface{}, error) {
var request uppercaseRequest
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
return nil, err
}
return request, nil
}
func decodeCountRequest(_ context.Context, r *http.Request) (interface{}, error) {
var request countRequest
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
return nil, err
}
return request, nil
}
func encodeResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
return json.NewEncoder(w).Encode(response)
}
type uppercaseRequest struct {
S string `json:"s"`
}
type uppercaseResponse struct {
V string `json:"v"`
Err string `json:"err,omitempty"`
}
type countRequest struct {
S string `json:"s"`
}
type countResponse struct {
V int `json:"v"`
}
golang-github-go-kit-kit-0.10.0/examples/stringsvc3/ 0000775 0000000 0000000 00000000000 13622563124 0022223 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/stringsvc3/instrumenting.go 0000664 0000000 0000000 00000002222 13622563124 0025456 0 ustar 00root root 0000000 0000000 package main
import (
"fmt"
"time"
"github.com/go-kit/kit/metrics"
)
func instrumentingMiddleware(
requestCount metrics.Counter,
requestLatency metrics.Histogram,
countResult metrics.Histogram,
) ServiceMiddleware {
return func(next StringService) StringService {
return instrmw{requestCount, requestLatency, countResult, next}
}
}
type instrmw struct {
requestCount metrics.Counter
requestLatency metrics.Histogram
countResult metrics.Histogram
StringService
}
func (mw instrmw) Uppercase(s string) (output string, err error) {
defer func(begin time.Time) {
lvs := []string{"method", "uppercase", "error", fmt.Sprint(err != nil)}
mw.requestCount.With(lvs...).Add(1)
mw.requestLatency.With(lvs...).Observe(time.Since(begin).Seconds())
}(time.Now())
output, err = mw.StringService.Uppercase(s)
return
}
func (mw instrmw) Count(s string) (n int) {
defer func(begin time.Time) {
lvs := []string{"method", "count", "error", "false"}
mw.requestCount.With(lvs...).Add(1)
mw.requestLatency.With(lvs...).Observe(time.Since(begin).Seconds())
mw.countResult.Observe(float64(n))
}(time.Now())
n = mw.StringService.Count(s)
return
}
golang-github-go-kit-kit-0.10.0/examples/stringsvc3/logging.go 0000664 0000000 0000000 00000001440 13622563124 0024177 0 ustar 00root root 0000000 0000000 package main
import (
"time"
"github.com/go-kit/kit/log"
)
func loggingMiddleware(logger log.Logger) ServiceMiddleware {
return func(next StringService) StringService {
return logmw{logger, next}
}
}
type logmw struct {
logger log.Logger
StringService
}
func (mw logmw) Uppercase(s string) (output string, err error) {
defer func(begin time.Time) {
_ = mw.logger.Log(
"method", "uppercase",
"input", s,
"output", output,
"err", err,
"took", time.Since(begin),
)
}(time.Now())
output, err = mw.StringService.Uppercase(s)
return
}
func (mw logmw) Count(s string) (n int) {
defer func(begin time.Time) {
_ = mw.logger.Log(
"method", "count",
"input", s,
"n", n,
"took", time.Since(begin),
)
}(time.Now())
n = mw.StringService.Count(s)
return
}
golang-github-go-kit-kit-0.10.0/examples/stringsvc3/main.go 0000664 0000000 0000000 00000004074 13622563124 0023503 0 ustar 00root root 0000000 0000000 package main
import (
"context"
"flag"
"net/http"
"os"
stdprometheus "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/go-kit/kit/log"
kitprometheus "github.com/go-kit/kit/metrics/prometheus"
httptransport "github.com/go-kit/kit/transport/http"
)
func main() {
var (
listen = flag.String("listen", ":8080", "HTTP listen address")
proxy = flag.String("proxy", "", "Optional comma-separated list of URLs to proxy uppercase requests")
)
flag.Parse()
var logger log.Logger
logger = log.NewLogfmtLogger(os.Stderr)
logger = log.With(logger, "listen", *listen, "caller", log.DefaultCaller)
fieldKeys := []string{"method", "error"}
requestCount := kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
Namespace: "my_group",
Subsystem: "string_service",
Name: "request_count",
Help: "Number of requests received.",
}, fieldKeys)
requestLatency := kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
Namespace: "my_group",
Subsystem: "string_service",
Name: "request_latency_microseconds",
Help: "Total duration of requests in microseconds.",
}, fieldKeys)
countResult := kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
Namespace: "my_group",
Subsystem: "string_service",
Name: "count_result",
Help: "The result of each count method.",
}, []string{})
var svc StringService
svc = stringService{}
svc = proxyingMiddleware(context.Background(), *proxy, logger)(svc)
svc = loggingMiddleware(logger)(svc)
svc = instrumentingMiddleware(requestCount, requestLatency, countResult)(svc)
uppercaseHandler := httptransport.NewServer(
makeUppercaseEndpoint(svc),
decodeUppercaseRequest,
encodeResponse,
)
countHandler := httptransport.NewServer(
makeCountEndpoint(svc),
decodeCountRequest,
encodeResponse,
)
http.Handle("/uppercase", uppercaseHandler)
http.Handle("/count", countHandler)
http.Handle("/metrics", promhttp.Handler())
logger.Log("msg", "HTTP", "addr", *listen)
logger.Log("err", http.ListenAndServe(*listen, nil))
}
golang-github-go-kit-kit-0.10.0/examples/stringsvc3/proxying.go 0000664 0000000 0000000 00000006232 13622563124 0024434 0 ustar 00root root 0000000 0000000 package main
import (
"context"
"errors"
"fmt"
"net/url"
"strings"
"time"
"golang.org/x/time/rate"
"github.com/sony/gobreaker"
"github.com/go-kit/kit/circuitbreaker"
"github.com/go-kit/kit/endpoint"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/ratelimit"
"github.com/go-kit/kit/sd"
"github.com/go-kit/kit/sd/lb"
httptransport "github.com/go-kit/kit/transport/http"
)
func proxyingMiddleware(ctx context.Context, instances string, logger log.Logger) ServiceMiddleware {
// If instances is empty, don't proxy.
if instances == "" {
logger.Log("proxy_to", "none")
return func(next StringService) StringService { return next }
}
// Set some parameters for our client.
var (
qps = 100 // beyond which we will return an error
maxAttempts = 3 // per request, before giving up
maxTime = 250 * time.Millisecond // wallclock time, before giving up
)
// Otherwise, construct an endpoint for each instance in the list, and add
// it to a fixed set of endpoints. In a real service, rather than doing this
// by hand, you'd probably use package sd's support for your service
// discovery system.
var (
instanceList = split(instances)
endpointer sd.FixedEndpointer
)
logger.Log("proxy_to", fmt.Sprint(instanceList))
for _, instance := range instanceList {
var e endpoint.Endpoint
e = makeUppercaseProxy(ctx, instance)
e = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{}))(e)
e = ratelimit.NewErroringLimiter(rate.NewLimiter(rate.Every(time.Second), qps))(e)
endpointer = append(endpointer, e)
}
// Now, build a single, retrying, load-balancing endpoint out of all of
// those individual endpoints.
balancer := lb.NewRoundRobin(endpointer)
retry := lb.Retry(maxAttempts, maxTime, balancer)
// And finally, return the ServiceMiddleware, implemented by proxymw.
return func(next StringService) StringService {
return proxymw{ctx, next, retry}
}
}
// proxymw implements StringService, forwarding Uppercase requests to the
// provided endpoint, and serving all other (i.e. Count) requests via the
// next StringService.
type proxymw struct {
ctx context.Context
next StringService // Serve most requests via this service...
uppercase endpoint.Endpoint // ...except Uppercase, which gets served by this endpoint
}
func (mw proxymw) Count(s string) int {
return mw.next.Count(s)
}
func (mw proxymw) Uppercase(s string) (string, error) {
response, err := mw.uppercase(mw.ctx, uppercaseRequest{S: s})
if err != nil {
return "", err
}
resp := response.(uppercaseResponse)
if resp.Err != "" {
return resp.V, errors.New(resp.Err)
}
return resp.V, nil
}
func makeUppercaseProxy(ctx context.Context, instance string) endpoint.Endpoint {
if !strings.HasPrefix(instance, "http") {
instance = "http://" + instance
}
u, err := url.Parse(instance)
if err != nil {
panic(err)
}
if u.Path == "" {
u.Path = "/uppercase"
}
return httptransport.NewClient(
"GET",
u,
encodeRequest,
decodeUppercaseResponse,
).Endpoint()
}
func split(s string) []string {
a := strings.Split(s, ",")
for i := range a {
a[i] = strings.TrimSpace(a[i])
}
return a
}
golang-github-go-kit-kit-0.10.0/examples/stringsvc3/service.go 0000664 0000000 0000000 00000001173 13622563124 0024214 0 ustar 00root root 0000000 0000000 package main
import (
"errors"
"strings"
)
// StringService provides operations on strings.
type StringService interface {
Uppercase(string) (string, error)
Count(string) int
}
type stringService struct{}
func (stringService) Uppercase(s string) (string, error) {
if s == "" {
return "", ErrEmpty
}
return strings.ToUpper(s), nil
}
func (stringService) Count(s string) int {
return len(s)
}
// ErrEmpty is returned when an input string is empty.
var ErrEmpty = errors.New("empty string")
// ServiceMiddleware is a chainable behavior modifier for StringService.
type ServiceMiddleware func(StringService) StringService
golang-github-go-kit-kit-0.10.0/examples/stringsvc3/transport.go 0000664 0000000 0000000 00000003702 13622563124 0024610 0 ustar 00root root 0000000 0000000 package main
import (
"bytes"
"context"
"encoding/json"
"io/ioutil"
"net/http"
"github.com/go-kit/kit/endpoint"
)
func makeUppercaseEndpoint(svc StringService) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(uppercaseRequest)
v, err := svc.Uppercase(req.S)
if err != nil {
return uppercaseResponse{v, err.Error()}, nil
}
return uppercaseResponse{v, ""}, nil
}
}
func makeCountEndpoint(svc StringService) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(countRequest)
v := svc.Count(req.S)
return countResponse{v}, nil
}
}
func decodeUppercaseRequest(_ context.Context, r *http.Request) (interface{}, error) {
var request uppercaseRequest
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
return nil, err
}
return request, nil
}
func decodeCountRequest(_ context.Context, r *http.Request) (interface{}, error) {
var request countRequest
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
return nil, err
}
return request, nil
}
func decodeUppercaseResponse(_ context.Context, r *http.Response) (interface{}, error) {
var response uppercaseResponse
if err := json.NewDecoder(r.Body).Decode(&response); err != nil {
return nil, err
}
return response, nil
}
func encodeResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
return json.NewEncoder(w).Encode(response)
}
func encodeRequest(_ context.Context, r *http.Request, request interface{}) error {
var buf bytes.Buffer
if err := json.NewEncoder(&buf).Encode(request); err != nil {
return err
}
r.Body = ioutil.NopCloser(&buf)
return nil
}
type uppercaseRequest struct {
S string `json:"s"`
}
type uppercaseResponse struct {
V string `json:"v"`
Err string `json:"err,omitempty"`
}
type countRequest struct {
S string `json:"s"`
}
type countResponse struct {
V int `json:"v"`
}
golang-github-go-kit-kit-0.10.0/examples/stringsvc4/ 0000775 0000000 0000000 00000000000 13622563124 0022224 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/examples/stringsvc4/main.go 0000664 0000000 0000000 00000011637 13622563124 0023507 0 ustar 00root root 0000000 0000000 package main
import (
"context"
"encoding/json"
"errors"
"log"
"strings"
"flag"
"net/http"
"github.com/go-kit/kit/endpoint"
natstransport "github.com/go-kit/kit/transport/nats"
httptransport "github.com/go-kit/kit/transport/http"
"github.com/nats-io/nats.go"
)
// StringService provides operations on strings.
type StringService interface {
Uppercase(context.Context, string) (string, error)
Count(context.Context, string) int
}
// stringService is a concrete implementation of StringService
type stringService struct{}
func (stringService) Uppercase(_ context.Context, s string) (string, error) {
if s == "" {
return "", ErrEmpty
}
return strings.ToUpper(s), nil
}
func (stringService) Count(_ context.Context, s string) int {
return len(s)
}
// ErrEmpty is returned when an input string is empty.
var ErrEmpty = errors.New("empty string")
// For each method, we define request and response structs
type uppercaseRequest struct {
S string `json:"s"`
}
type uppercaseResponse struct {
V string `json:"v"`
Err string `json:"err,omitempty"` // errors don't define JSON marshaling
}
type countRequest struct {
S string `json:"s"`
}
type countResponse struct {
V int `json:"v"`
}
// Endpoints are a primary abstraction in go-kit. An endpoint represents a single RPC (method in our service interface)
func makeUppercaseHTTPEndpoint(nc *nats.Conn) endpoint.Endpoint {
return natstransport.NewPublisher(
nc,
"stringsvc.uppercase",
natstransport.EncodeJSONRequest,
decodeUppercaseResponse,
).Endpoint()
}
func makeCountHTTPEndpoint(nc *nats.Conn) endpoint.Endpoint {
return natstransport.NewPublisher(
nc,
"stringsvc.count",
natstransport.EncodeJSONRequest,
decodeCountResponse,
).Endpoint()
}
func makeUppercaseEndpoint(svc StringService) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(uppercaseRequest)
v, err := svc.Uppercase(ctx, req.S)
if err != nil {
return uppercaseResponse{v, err.Error()}, nil
}
return uppercaseResponse{v, ""}, nil
}
}
func makeCountEndpoint(svc StringService) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(countRequest)
v := svc.Count(ctx, req.S)
return countResponse{v}, nil
}
}
// Transports expose the service to the network. In this fourth example we utilize JSON over NATS and HTTP.
func main() {
svc := stringService{}
natsURL := flag.String("nats-url", nats.DefaultURL, "URL for connection to NATS")
flag.Parse()
nc, err := nats.Connect(*natsURL)
if err != nil {
log.Fatal(err)
}
defer nc.Close()
uppercaseHTTPHandler := httptransport.NewServer(
makeUppercaseHTTPEndpoint(nc),
decodeUppercaseHTTPRequest,
httptransport.EncodeJSONResponse,
)
countHTTPHandler := httptransport.NewServer(
makeCountHTTPEndpoint(nc),
decodeCountHTTPRequest,
httptransport.EncodeJSONResponse,
)
uppercaseHandler := natstransport.NewSubscriber(
makeUppercaseEndpoint(svc),
decodeUppercaseRequest,
natstransport.EncodeJSONResponse,
)
countHandler := natstransport.NewSubscriber(
makeCountEndpoint(svc),
decodeCountRequest,
natstransport.EncodeJSONResponse,
)
uSub, err := nc.QueueSubscribe("stringsvc.uppercase", "stringsvc", uppercaseHandler.ServeMsg(nc))
if err != nil {
log.Fatal(err)
}
defer uSub.Unsubscribe()
cSub, err := nc.QueueSubscribe("stringsvc.count", "stringsvc", countHandler.ServeMsg(nc))
if err != nil {
log.Fatal(err)
}
defer cSub.Unsubscribe()
http.Handle("/uppercase", uppercaseHTTPHandler)
http.Handle("/count", countHTTPHandler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
func decodeUppercaseHTTPRequest(_ context.Context, r *http.Request) (interface{}, error) {
var request uppercaseRequest
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
return nil, err
}
return request, nil
}
func decodeCountHTTPRequest(_ context.Context, r *http.Request) (interface{}, error) {
var request countRequest
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
return nil, err
}
return request, nil
}
func decodeUppercaseResponse(_ context.Context, msg *nats.Msg) (interface{}, error) {
var response uppercaseResponse
if err := json.Unmarshal(msg.Data, &response); err != nil {
return nil, err
}
return response, nil
}
func decodeCountResponse(_ context.Context, msg *nats.Msg) (interface{}, error) {
var response countResponse
if err := json.Unmarshal(msg.Data, &response); err != nil {
return nil, err
}
return response, nil
}
func decodeUppercaseRequest(_ context.Context, msg *nats.Msg) (interface{}, error) {
var request uppercaseRequest
if err := json.Unmarshal(msg.Data, &request); err != nil {
return nil, err
}
return request, nil
}
func decodeCountRequest(_ context.Context, msg *nats.Msg) (interface{}, error) {
var request countRequest
if err := json.Unmarshal(msg.Data, &request); err != nil {
return nil, err
}
return request, nil
}
golang-github-go-kit-kit-0.10.0/go.mod 0000664 0000000 0000000 00000005156 13622563124 0017415 0 ustar 00root root 0000000 0000000 module github.com/go-kit/kit
go 1.13
require (
github.com/VividCortex/gohistogram v1.0.0
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5
github.com/apache/thrift v0.13.0
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a
github.com/aws/aws-lambda-go v1.13.3
github.com/aws/aws-sdk-go v1.27.0
github.com/aws/aws-sdk-go-v2 v0.18.0
github.com/casbin/casbin/v2 v2.1.2
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec // indirect
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd // indirect
github.com/davecgh/go-spew v1.1.1
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/edsrzf/mmap-go v1.0.0 // indirect
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db // indirect
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8 // indirect
github.com/go-logfmt/logfmt v0.5.0
github.com/go-stack/stack v1.8.0
github.com/golang/protobuf v1.3.2
github.com/gorilla/mux v1.7.3
github.com/hashicorp/consul/api v1.3.0
github.com/hashicorp/go-version v1.2.0 // indirect
github.com/hudl/fargo v1.3.0
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d
github.com/lightstep/lightstep-tracer-go v0.18.1
github.com/nats-io/nats-server/v2 v2.1.2
github.com/nats-io/nats.go v1.9.1
github.com/oklog/oklog v0.3.2
github.com/oklog/run v1.0.0 // indirect
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 // indirect
github.com/opentracing/basictracer-go v1.0.0 // indirect
github.com/opentracing/opentracing-go v1.1.0
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5
github.com/openzipkin/zipkin-go v0.2.2
github.com/pact-foundation/pact-go v1.0.4
github.com/pborman/uuid v1.2.0
github.com/performancecopilot/speed v3.0.0+incompatible
github.com/pkg/errors v0.8.1
github.com/prometheus/client_golang v1.3.0
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da
github.com/sirupsen/logrus v1.4.2
github.com/smartystreets/goconvey v1.6.4 // indirect
github.com/sony/gobreaker v0.4.1
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738
go.opencensus.io v0.22.2
go.uber.org/zap v1.13.0
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
golang.org/x/time v0.0.0-20191024005414-555d28b269f0
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114
google.golang.org/grpc v1.26.0
gopkg.in/gcfg.v1 v1.2.3 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0
)
golang-github-go-kit-kit-0.10.0/go.sum 0000664 0000000 0000000 00000135265 13622563124 0017447 0 ustar 00root root 0000000 0000000 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE=
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 h1:rFw4nCn9iMW+Vajsk51NtYIcwSTkXr+JGrMd36kTDJw=
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.13.0 h1:5hryIiq9gtn+MiLVn0wP37kb/uTeRZgN08WoCsAhIhI=
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a h1:pv34s756C4pEXnjgPfGYgdhg/ZdajGhyOvzx8k+23nw=
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
github.com/aws/aws-lambda-go v1.13.3 h1:SuCy7H3NLyp+1Mrfp+m80jcbi9KYWAs9/BXwppwRDzY=
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
github.com/aws/aws-sdk-go v1.27.0 h1:0xphMHGMLBrPMfxR2AmVjZKcMEESEgWF8Kru94BNByk=
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go-v2 v0.18.0 h1:qZ+woO4SamnH/eEbjM2IDLhRNwIwND/RQyVlBLp3Jqg=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/casbin/casbin/v2 v2.1.2 h1:bTwon/ECRx9dwBy2ewRVr5OiqjeXSGiTUY74sDPQi/g=
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec h1:EdRZT3IeKQmfCSrgo8SZ8V3MEnskuJP0wCYNpe+aiXo=
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa h1:OaNxuTZr7kxeODyLWsRMC+OD03aFUH+mW6r2d+MWa5Y=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 h1:u9SHYsPQNyt5tgDm3YN7+9dYrpK96E5wFilTFWIDZOM=
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf h1:CAKfRE2YtTUIjjh1bkBtyYFaUT/WmOqsJjgtihT0vMI=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4 h1:qk/FSDDxo05wdJH28W+p5yivv7LuLYLRXPPD8KQCtZs=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db h1:gb2Z18BhTPJPpLQWj4T+rfKHYCHxRHCtRxhKKjRidVw=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8 h1:a9ENSRDFBUPkJ5lCgVZh26+ZbGyoVJG7yb5SSzF5H54=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c h1:Lh2aW+HnU2Nbe1gqD9SOJLJxW1jBMmQOktN2acDyJk8=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.5 h1:UImYN5qQ8tuGpGE16ZmjvcTtTw24zw1QAp/SlnNrZhI=
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/consul/api v1.3.0 h1:HXNYlRkkM/t+Y/Yhxtwcy02dlYwIaoxzvxPnS+cqy78=
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
github.com/hashicorp/consul/sdk v0.3.0 h1:UOxjlb4xVNF93jak1mzzoBatyFju9nrkxpVwIp/QqxQ=
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-rootcerts v1.0.0 h1:Rqb66Oo1X/eSV1x66xbDccZjhJigjg0+e82kpwzSwCI=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/hudl/fargo v1.3.0 h1:0U6+BtN6LhaYuTnIJq4Wyq5cpn6O2kWrxAtcqBmYY6w=
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d h1:/WZQPMZNsjZ7IlCpsLGdQBINg5bxKQ1K1sh6awxLtkA=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743 h1:143Bb8f8DuGWck/xpNUOckBVYfFbBTnLevfRZ1aVVqo=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
github.com/lightstep/lightstep-tracer-go v0.18.1 h1:vi1F1IQ8N7hNWytK9DpJsUfQhGuNSc19z330K6vl4zk=
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
github.com/nats-io/jwt v0.3.2 h1:+RB5hMpXUUA2dfxuhBTEkMOrYmM+gKIZYS1KjSostMI=
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
github.com/nats-io/nats-server/v2 v2.1.2 h1:i2Ly0B+1+rzNZHHWtD4ZwKi+OU5l+uQo1iDHZ2PmiIc=
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
github.com/nats-io/nats.go v1.9.1 h1:ik3HbLhZ0YABLto7iX80pZLPw/6dx3T+++MZJwLnMrQ=
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.1.3 h1:6JrEfig+HzTH85yxzhSVbjHRJv9cn0p6n3IngIcM5/k=
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/oklog/oklog v0.3.2 h1:wVfs8F+in6nTBMkA7CbRw+zZMIB7nNM825cM1wuzoTk=
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 h1:lM6RxxfUMrYL/f8bWEUqdXrANWtrL7Nndbm9iFN0DlU=
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
github.com/opentracing/basictracer-go v1.0.0 h1:YyUAhaEfjoWXclZVJ9sGoNct7j4TVk7lZWlQw5UXuoo=
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5 h1:ZCnq+JUrvXcDVhX/xRolRBZifmabN1HcS1wrPSvxhrU=
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/openzipkin/zipkin-go v0.2.2 h1:nY8Hti+WKaP0cRsSeQ026wU03QsM762XBeCXBb9NAWI=
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/pact-foundation/pact-go v1.0.4 h1:OYkFijGHoZAYbOIb1LWXrwKQbMMRUv1oQ89blD2Mh2Q=
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/performancecopilot/speed v3.0.0+incompatible h1:2WnRzIquHa5QxaJKShDkLM+sc0JPuwhXzK8OYOyt3Vg=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.3.0 h1:miYCvYqFXtl/J9FIy8eNpBfYthAEFg+Ys0XyUVEcDsc=
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.1.0 h1:ElTg5tNp4DqfV7UQjDqv2+RJlNzsDtvNAWccbItceIE=
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da h1:p3Vo3i64TCLY7gIfzeQaUJ+kppEO5WQG3cL8iE8tGHU=
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sony/gobreaker v0.4.1 h1:oMnRNZXX5j85zso6xCPRNPtmAycat+WcoKbklScLDgQ=
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271 h1:WhxRHzgeVGETMlmVfqhRn8RIeeNoPr2Czh33I4Zdccw=
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a h1:AhmOdSHeswKHBjhsLs/7+1voOxT+LLrSk/Nxvk35fug=
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8 h1:ndzgwNDnKIqyCvHTXaCqh9KlOWKvBry6nuXMJmonVsE=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738 h1:VcrIfasaLFkyjk6KNlXQSzO+B0fZcnECiDrKJsfxka0=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.22.2 h1:75k/FF0Q2YM8QYo07VPddOLBslDt1MZOdEslOHvmzAs=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU=
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f h1:68K/z8GLUxV76xGSqwTWw2gyk/jwn79LUL43rES2g8o=
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114 h1:DnSr2mCsxyCE6ZgIkmcWUQY2R5cH/6wL7eIxEmQOMSE=
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gcfg.v1 v1.2.3 h1:m8OOJ4ccYHnx2f4gQwpno8nAX5OGOh7RLaaz0pj3Ogs=
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0 h1:ucqkfpjg9WzSUubAO62csmucvxl4/JeW3F4I4909XkM=
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
golang-github-go-kit-kit-0.10.0/lint 0000775 0000000 0000000 00000001114 13622563124 0017171 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
if [ ! $(command -v gometalinter) ]
then
go get github.com/alecthomas/gometalinter
gometalinter --update --install
fi
time gometalinter \
--exclude='error return value not checked.*(Close|Log|Print).*\(errcheck\)$' \
--exclude='.*_test\.go:.*error return value not checked.*\(errcheck\)$' \
--exclude='/thrift/' \
--exclude='/pb/' \
--exclude='no args in Log call \(vet\)' \
--disable=dupl \
--disable=aligncheck \
--disable=gotype \
--cyclo-over=20 \
--tests \
--concurrency=2 \
--deadline=300s \
./...
golang-github-go-kit-kit-0.10.0/log/ 0000775 0000000 0000000 00000000000 13622563124 0017061 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/log/README.md 0000664 0000000 0000000 00000011334 13622563124 0020342 0 ustar 00root root 0000000 0000000 # package log
`package log` provides a minimal interface for structured logging in services.
It may be wrapped to encode conventions, enforce type-safety, provide leveled
logging, and so on. It can be used for both typical application log events,
and log-structured data streams.
## Structured logging
Structured logging is, basically, conceding to the reality that logs are
_data_, and warrant some level of schematic rigor. Using a stricter,
key/value-oriented message format for our logs, containing contextual and
semantic information, makes it much easier to get insight into the
operational activity of the systems we build. Consequently, `package log` is
of the strong belief that "[the benefits of structured logging outweigh the
minimal effort involved](https://www.thoughtworks.com/radar/techniques/structured-logging)".
Migrating from unstructured to structured logging is probably a lot easier
than you'd expect.
```go
// Unstructured
log.Printf("HTTP server listening on %s", addr)
// Structured
logger.Log("transport", "HTTP", "addr", addr, "msg", "listening")
```
## Usage
### Typical application logging
```go
w := log.NewSyncWriter(os.Stderr)
logger := log.NewLogfmtLogger(w)
logger.Log("question", "what is the meaning of life?", "answer", 42)
// Output:
// question="what is the meaning of life?" answer=42
```
### Contextual Loggers
```go
func main() {
var logger log.Logger
logger = log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr))
logger = log.With(logger, "instance_id", 123)
logger.Log("msg", "starting")
NewWorker(log.With(logger, "component", "worker")).Run()
NewSlacker(log.With(logger, "component", "slacker")).Run()
}
// Output:
// instance_id=123 msg=starting
// instance_id=123 component=worker msg=running
// instance_id=123 component=slacker msg=running
```
### Interact with stdlib logger
Redirect stdlib logger to Go kit logger.
```go
import (
"os"
stdlog "log"
kitlog "github.com/go-kit/kit/log"
)
func main() {
logger := kitlog.NewJSONLogger(kitlog.NewSyncWriter(os.Stdout))
stdlog.SetOutput(kitlog.NewStdlibAdapter(logger))
stdlog.Print("I sure like pie")
}
// Output:
// {"msg":"I sure like pie","ts":"2016/01/01 12:34:56"}
```
Or, if, for legacy reasons, you need to pipe all of your logging through the
stdlib log package, you can redirect Go kit logger to the stdlib logger.
```go
logger := kitlog.NewLogfmtLogger(kitlog.StdlibWriter{})
logger.Log("legacy", true, "msg", "at least it's something")
// Output:
// 2016/01/01 12:34:56 legacy=true msg="at least it's something"
```
### Timestamps and callers
```go
var logger log.Logger
logger = log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr))
logger = log.With(logger, "ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller)
logger.Log("msg", "hello")
// Output:
// ts=2016-01-01T12:34:56Z caller=main.go:15 msg=hello
```
## Levels
Log levels are supported via the [level package](https://godoc.org/github.com/go-kit/kit/log/level).
## Supported output formats
- [Logfmt](https://brandur.org/logfmt) ([see also](https://blog.codeship.com/logfmt-a-log-format-thats-easy-to-read-and-write))
- JSON
## Enhancements
`package log` is centered on the one-method Logger interface.
```go
type Logger interface {
Log(keyvals ...interface{}) error
}
```
This interface, and its supporting code like is the product of much iteration
and evaluation. For more details on the evolution of the Logger interface,
see [The Hunt for a Logger Interface](http://go-talks.appspot.com/github.com/ChrisHines/talks/structured-logging/structured-logging.slide#1),
a talk by [Chris Hines](https://github.com/ChrisHines).
Also, please see
[#63](https://github.com/go-kit/kit/issues/63),
[#76](https://github.com/go-kit/kit/pull/76),
[#131](https://github.com/go-kit/kit/issues/131),
[#157](https://github.com/go-kit/kit/pull/157),
[#164](https://github.com/go-kit/kit/issues/164), and
[#252](https://github.com/go-kit/kit/pull/252)
to review historical conversations about package log and the Logger interface.
Value-add packages and suggestions,
like improvements to [the leveled logger](https://godoc.org/github.com/go-kit/kit/log/level),
are of course welcome. Good proposals should
- Be composable with [contextual loggers](https://godoc.org/github.com/go-kit/kit/log#With),
- Not break the behavior of [log.Caller](https://godoc.org/github.com/go-kit/kit/log#Caller) in any wrapped contextual loggers, and
- Be friendly to packages that accept only an unadorned log.Logger.
## Benchmarks & comparisons
There are a few Go logging benchmarks and comparisons that include Go kit's package log.
- [imkira/go-loggers-bench](https://github.com/imkira/go-loggers-bench) includes kit/log
- [uber-common/zap](https://github.com/uber-common/zap), a zero-alloc logging library, includes a comparison with kit/log
golang-github-go-kit-kit-0.10.0/log/benchmark_test.go 0000664 0000000 0000000 00000000677 13622563124 0022413 0 ustar 00root root 0000000 0000000 package log_test
import (
"testing"
"github.com/go-kit/kit/log"
)
func benchmarkRunner(b *testing.B, logger log.Logger, f func(log.Logger)) {
lc := log.With(logger, "common_key", "common_value")
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
f(lc)
}
}
var (
baseMessage = func(logger log.Logger) { logger.Log("foo_key", "foo_value") }
withMessage = func(logger log.Logger) { log.With(logger, "a", "b").Log("c", "d") }
)
golang-github-go-kit-kit-0.10.0/log/concurrency_test.go 0000664 0000000 0000000 00000001221 13622563124 0022775 0 ustar 00root root 0000000 0000000 package log_test
import (
"math"
"testing"
"github.com/go-kit/kit/log"
)
// These test are designed to be run with the race detector.
func testConcurrency(t *testing.T, logger log.Logger, total int) {
n := int(math.Sqrt(float64(total)))
share := total / n
errC := make(chan error, n)
for i := 0; i < n; i++ {
go func() {
errC <- spam(logger, share)
}()
}
for i := 0; i < n; i++ {
err := <-errC
if err != nil {
t.Fatalf("concurrent logging error: %v", err)
}
}
}
func spam(logger log.Logger, count int) error {
for i := 0; i < count; i++ {
err := logger.Log("key", i)
if err != nil {
return err
}
}
return nil
}
golang-github-go-kit-kit-0.10.0/log/deprecated_levels/ 0000775 0000000 0000000 00000000000 13622563124 0022533 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/log/deprecated_levels/levels.go 0000664 0000000 0000000 00000007567 13622563124 0024373 0 ustar 00root root 0000000 0000000 package levels
import "github.com/go-kit/kit/log"
// Levels provides a leveled logging wrapper around a logger. It has five
// levels: debug, info, warning (warn), error, and critical (crit). If you
// want a different set of levels, you can create your own levels type very
// easily, and you can elide the configuration.
type Levels struct {
logger log.Logger
levelKey string
// We have a choice between storing level values in string fields or
// making a separate context for each level. When using string fields the
// Log method must combine the base context, the level data, and the
// logged keyvals; but the With method only requires updating one context.
// If we instead keep a separate context for each level the Log method
// must only append the new keyvals; but the With method would have to
// update all five contexts.
// Roughly speaking, storing multiple contexts breaks even if the ratio of
// Log/With calls is more than the number of levels. We have chosen to
// make the With method cheap and the Log method a bit more costly because
// we do not expect most applications to Log more than five times for each
// call to With.
debugValue string
infoValue string
warnValue string
errorValue string
critValue string
}
// New creates a new leveled logger, wrapping the passed logger.
func New(logger log.Logger, options ...Option) Levels {
l := Levels{
logger: logger,
levelKey: "level",
debugValue: "debug",
infoValue: "info",
warnValue: "warn",
errorValue: "error",
critValue: "crit",
}
for _, option := range options {
option(&l)
}
return l
}
// With returns a new leveled logger that includes keyvals in all log events.
func (l Levels) With(keyvals ...interface{}) Levels {
return Levels{
logger: log.With(l.logger, keyvals...),
levelKey: l.levelKey,
debugValue: l.debugValue,
infoValue: l.infoValue,
warnValue: l.warnValue,
errorValue: l.errorValue,
critValue: l.critValue,
}
}
// Debug returns a debug level logger.
func (l Levels) Debug() log.Logger {
return log.WithPrefix(l.logger, l.levelKey, l.debugValue)
}
// Info returns an info level logger.
func (l Levels) Info() log.Logger {
return log.WithPrefix(l.logger, l.levelKey, l.infoValue)
}
// Warn returns a warning level logger.
func (l Levels) Warn() log.Logger {
return log.WithPrefix(l.logger, l.levelKey, l.warnValue)
}
// Error returns an error level logger.
func (l Levels) Error() log.Logger {
return log.WithPrefix(l.logger, l.levelKey, l.errorValue)
}
// Crit returns a critical level logger.
func (l Levels) Crit() log.Logger {
return log.WithPrefix(l.logger, l.levelKey, l.critValue)
}
// Option sets a parameter for leveled loggers.
type Option func(*Levels)
// Key sets the key for the field used to indicate log level. By default,
// the key is "level".
func Key(key string) Option {
return func(l *Levels) { l.levelKey = key }
}
// DebugValue sets the value for the field used to indicate the debug log
// level. By default, the value is "debug".
func DebugValue(value string) Option {
return func(l *Levels) { l.debugValue = value }
}
// InfoValue sets the value for the field used to indicate the info log level.
// By default, the value is "info".
func InfoValue(value string) Option {
return func(l *Levels) { l.infoValue = value }
}
// WarnValue sets the value for the field used to indicate the warning log
// level. By default, the value is "warn".
func WarnValue(value string) Option {
return func(l *Levels) { l.warnValue = value }
}
// ErrorValue sets the value for the field used to indicate the error log
// level. By default, the value is "error".
func ErrorValue(value string) Option {
return func(l *Levels) { l.errorValue = value }
}
// CritValue sets the value for the field used to indicate the critical log
// level. By default, the value is "crit".
func CritValue(value string) Option {
return func(l *Levels) { l.critValue = value }
}
golang-github-go-kit-kit-0.10.0/log/deprecated_levels/levels_test.go 0000664 0000000 0000000 00000003277 13622563124 0025424 0 ustar 00root root 0000000 0000000 package levels_test
import (
"bytes"
"os"
"testing"
"github.com/go-kit/kit/log"
levels "github.com/go-kit/kit/log/deprecated_levels"
)
func TestDefaultLevels(t *testing.T) {
buf := bytes.Buffer{}
logger := levels.New(log.NewLogfmtLogger(&buf))
logger.Debug().Log("msg", "résumé") // of course you'd want to do this
if want, have := "level=debug msg=résumé\n", buf.String(); want != have {
t.Errorf("want %#v, have %#v", want, have)
}
buf.Reset()
logger.Info().Log("msg", "Åhus")
if want, have := "level=info msg=Åhus\n", buf.String(); want != have {
t.Errorf("want %#v, have %#v", want, have)
}
buf.Reset()
logger.Error().Log("msg", "© violation")
if want, have := "level=error msg=\"© violation\"\n", buf.String(); want != have {
t.Errorf("want %#v, have %#v", want, have)
}
buf.Reset()
logger.Crit().Log("msg", " ")
if want, have := "level=crit msg=\"\\t\"\n", buf.String(); want != have {
t.Errorf("want %#v, have %#v", want, have)
}
}
func TestModifiedLevels(t *testing.T) {
buf := bytes.Buffer{}
logger := levels.New(
log.NewJSONLogger(&buf),
levels.Key("l"),
levels.DebugValue("dbg"),
levels.InfoValue("nfo"),
levels.WarnValue("wrn"),
levels.ErrorValue("err"),
levels.CritValue("crt"),
)
logger.With("easter_island", "176°").Debug().Log("msg", "moai")
if want, have := `{"easter_island":"176°","l":"dbg","msg":"moai"}`+"\n", buf.String(); want != have {
t.Errorf("want %#v, have %#v", want, have)
}
}
func ExampleLevels() {
logger := levels.New(log.NewLogfmtLogger(os.Stdout))
logger.Debug().Log("msg", "hello")
logger.With("context", "foo").Warn().Log("err", "error")
// Output:
// level=debug msg=hello
// level=warn context=foo err=error
}
golang-github-go-kit-kit-0.10.0/log/doc.go 0000664 0000000 0000000 00000012335 13622563124 0020161 0 ustar 00root root 0000000 0000000 // Package log provides a structured logger.
//
// Structured logging produces logs easily consumed later by humans or
// machines. Humans might be interested in debugging errors, or tracing
// specific requests. Machines might be interested in counting interesting
// events, or aggregating information for off-line processing. In both cases,
// it is important that the log messages are structured and actionable.
// Package log is designed to encourage both of these best practices.
//
// Basic Usage
//
// The fundamental interface is Logger. Loggers create log events from
// key/value data. The Logger interface has a single method, Log, which
// accepts a sequence of alternating key/value pairs, which this package names
// keyvals.
//
// type Logger interface {
// Log(keyvals ...interface{}) error
// }
//
// Here is an example of a function using a Logger to create log events.
//
// func RunTask(task Task, logger log.Logger) string {
// logger.Log("taskID", task.ID, "event", "starting task")
// ...
// logger.Log("taskID", task.ID, "event", "task complete")
// }
//
// The keys in the above example are "taskID" and "event". The values are
// task.ID, "starting task", and "task complete". Every key is followed
// immediately by its value.
//
// Keys are usually plain strings. Values may be any type that has a sensible
// encoding in the chosen log format. With structured logging it is a good
// idea to log simple values without formatting them. This practice allows
// the chosen logger to encode values in the most appropriate way.
//
// Contextual Loggers
//
// A contextual logger stores keyvals that it includes in all log events.
// Building appropriate contextual loggers reduces repetition and aids
// consistency in the resulting log output. With and WithPrefix add context to
// a logger. We can use With to improve the RunTask example.
//
// func RunTask(task Task, logger log.Logger) string {
// logger = log.With(logger, "taskID", task.ID)
// logger.Log("event", "starting task")
// ...
// taskHelper(task.Cmd, logger)
// ...
// logger.Log("event", "task complete")
// }
//
// The improved version emits the same log events as the original for the
// first and last calls to Log. Passing the contextual logger to taskHelper
// enables each log event created by taskHelper to include the task.ID even
// though taskHelper does not have access to that value. Using contextual
// loggers this way simplifies producing log output that enables tracing the
// life cycle of individual tasks. (See the Contextual example for the full
// code of the above snippet.)
//
// Dynamic Contextual Values
//
// A Valuer function stored in a contextual logger generates a new value each
// time an event is logged. The Valuer example demonstrates how this feature
// works.
//
// Valuers provide the basis for consistently logging timestamps and source
// code location. The log package defines several valuers for that purpose.
// See Timestamp, DefaultTimestamp, DefaultTimestampUTC, Caller, and
// DefaultCaller. A common logger initialization sequence that ensures all log
// entries contain a timestamp and source location looks like this:
//
// logger := log.NewLogfmtLogger(log.NewSyncWriter(os.Stdout))
// logger = log.With(logger, "ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller)
//
// Concurrent Safety
//
// Applications with multiple goroutines want each log event written to the
// same logger to remain separate from other log events. Package log provides
// two simple solutions for concurrent safe logging.
//
// NewSyncWriter wraps an io.Writer and serializes each call to its Write
// method. Using a SyncWriter has the benefit that the smallest practical
// portion of the logging logic is performed within a mutex, but it requires
// the formatting Logger to make only one call to Write per log event.
//
// NewSyncLogger wraps any Logger and serializes each call to its Log method.
// Using a SyncLogger has the benefit that it guarantees each log event is
// handled atomically within the wrapped logger, but it typically serializes
// both the formatting and output logic. Use a SyncLogger if the formatting
// logger may perform multiple writes per log event.
//
// Error Handling
//
// This package relies on the practice of wrapping or decorating loggers with
// other loggers to provide composable pieces of functionality. It also means
// that Logger.Log must return an error because some
// implementations—especially those that output log data to an io.Writer—may
// encounter errors that cannot be handled locally. This in turn means that
// Loggers that wrap other loggers should return errors from the wrapped
// logger up the stack.
//
// Fortunately, the decorator pattern also provides a way to avoid the
// necessity to check for errors every time an application calls Logger.Log.
// An application required to panic whenever its Logger encounters
// an error could initialize its logger as follows.
//
// fmtlogger := log.NewLogfmtLogger(log.NewSyncWriter(os.Stdout))
// logger := log.LoggerFunc(func(keyvals ...interface{}) error {
// if err := fmtlogger.Log(keyvals...); err != nil {
// panic(err)
// }
// return nil
// })
package log
golang-github-go-kit-kit-0.10.0/log/example_test.go 0000664 0000000 0000000 00000005337 13622563124 0022112 0 ustar 00root root 0000000 0000000 package log_test
import (
"math/rand"
"os"
"sync"
"time"
"github.com/go-kit/kit/log"
)
func Example_basic() {
logger := log.NewLogfmtLogger(os.Stdout)
type Task struct {
ID int
}
RunTask := func(task Task, logger log.Logger) {
logger.Log("taskID", task.ID, "event", "starting task")
logger.Log("taskID", task.ID, "event", "task complete")
}
RunTask(Task{ID: 1}, logger)
// Output:
// taskID=1 event="starting task"
// taskID=1 event="task complete"
}
func Example_contextual() {
logger := log.NewLogfmtLogger(os.Stdout)
type Task struct {
ID int
Cmd string
}
taskHelper := func(cmd string, logger log.Logger) {
// execute(cmd)
logger.Log("cmd", cmd, "dur", 42*time.Millisecond)
}
RunTask := func(task Task, logger log.Logger) {
logger = log.With(logger, "taskID", task.ID)
logger.Log("event", "starting task")
taskHelper(task.Cmd, logger)
logger.Log("event", "task complete")
}
RunTask(Task{ID: 1, Cmd: "echo Hello, world!"}, logger)
// Output:
// taskID=1 event="starting task"
// taskID=1 cmd="echo Hello, world!" dur=42ms
// taskID=1 event="task complete"
}
func Example_valuer() {
logger := log.NewLogfmtLogger(os.Stdout)
count := 0
counter := func() interface{} {
count++
return count
}
logger = log.With(logger, "count", log.Valuer(counter))
logger.Log("call", "first")
logger.Log("call", "second")
// Output:
// count=1 call=first
// count=2 call=second
}
func Example_debugInfo() {
logger := log.NewLogfmtLogger(os.Stdout)
// make time predictable for this test
baseTime := time.Date(2015, time.February, 3, 10, 0, 0, 0, time.UTC)
mockTime := func() time.Time {
baseTime = baseTime.Add(time.Second)
return baseTime
}
logger = log.With(logger, "time", log.Timestamp(mockTime), "caller", log.DefaultCaller)
logger.Log("call", "first")
logger.Log("call", "second")
// ...
logger.Log("call", "third")
// Output:
// time=2015-02-03T10:00:01Z caller=example_test.go:93 call=first
// time=2015-02-03T10:00:02Z caller=example_test.go:94 call=second
// time=2015-02-03T10:00:03Z caller=example_test.go:98 call=third
}
func Example_syncWriter() {
w := log.NewSyncWriter(os.Stdout)
logger := log.NewLogfmtLogger(w)
type Task struct {
ID int
}
var wg sync.WaitGroup
RunTask := func(task Task, logger log.Logger) {
logger.Log("taskID", task.ID, "event", "starting task")
time.Sleep(time.Duration(rand.Intn(200)) * time.Millisecond)
logger.Log("taskID", task.ID, "event", "task complete")
wg.Done()
}
wg.Add(2)
go RunTask(Task{ID: 1}, logger)
go RunTask(Task{ID: 2}, logger)
wg.Wait()
// Unordered output:
// taskID=1 event="starting task"
// taskID=2 event="starting task"
// taskID=1 event="task complete"
// taskID=2 event="task complete"
}
golang-github-go-kit-kit-0.10.0/log/json_logger.go 0000664 0000000 0000000 00000003720 13622563124 0021722 0 ustar 00root root 0000000 0000000 package log
import (
"encoding"
"encoding/json"
"fmt"
"io"
"reflect"
)
type jsonLogger struct {
io.Writer
}
// NewJSONLogger returns a Logger that encodes keyvals to the Writer as a
// single JSON object. Each log event produces no more than one call to
// w.Write. The passed Writer must be safe for concurrent use by multiple
// goroutines if the returned Logger will be used concurrently.
func NewJSONLogger(w io.Writer) Logger {
return &jsonLogger{w}
}
func (l *jsonLogger) Log(keyvals ...interface{}) error {
n := (len(keyvals) + 1) / 2 // +1 to handle case when len is odd
m := make(map[string]interface{}, n)
for i := 0; i < len(keyvals); i += 2 {
k := keyvals[i]
var v interface{} = ErrMissingValue
if i+1 < len(keyvals) {
v = keyvals[i+1]
}
merge(m, k, v)
}
enc := json.NewEncoder(l.Writer)
enc.SetEscapeHTML(false)
return enc.Encode(m)
}
func merge(dst map[string]interface{}, k, v interface{}) {
var key string
switch x := k.(type) {
case string:
key = x
case fmt.Stringer:
key = safeString(x)
default:
key = fmt.Sprint(x)
}
// We want json.Marshaler and encoding.TextMarshaller to take priority over
// err.Error() and v.String(). But json.Marshall (called later) does that by
// default so we force a no-op if it's one of those 2 case.
switch x := v.(type) {
case json.Marshaler:
case encoding.TextMarshaler:
case error:
v = safeError(x)
case fmt.Stringer:
v = safeString(x)
}
dst[key] = v
}
func safeString(str fmt.Stringer) (s string) {
defer func() {
if panicVal := recover(); panicVal != nil {
if v := reflect.ValueOf(str); v.Kind() == reflect.Ptr && v.IsNil() {
s = "NULL"
} else {
panic(panicVal)
}
}
}()
s = str.String()
return
}
func safeError(err error) (s interface{}) {
defer func() {
if panicVal := recover(); panicVal != nil {
if v := reflect.ValueOf(err); v.Kind() == reflect.Ptr && v.IsNil() {
s = nil
} else {
panic(panicVal)
}
}
}()
s = err.Error()
return
}
golang-github-go-kit-kit-0.10.0/log/json_logger_test.go 0000664 0000000 0000000 00000007414 13622563124 0022765 0 ustar 00root root 0000000 0000000 package log_test
import (
"bytes"
"errors"
"io/ioutil"
"testing"
"github.com/go-kit/kit/log"
)
func TestJSONLoggerCaller(t *testing.T) {
t.Parallel()
buf := &bytes.Buffer{}
logger := log.NewJSONLogger(buf)
logger = log.With(logger, "caller", log.DefaultCaller)
if err := logger.Log(); err != nil {
t.Fatal(err)
}
if want, have := `{"caller":"json_logger_test.go:18"}`+"\n", buf.String(); want != have {
t.Errorf("\nwant %#v\nhave %#v", want, have)
}
}
func TestJSONLogger(t *testing.T) {
t.Parallel()
buf := &bytes.Buffer{}
logger := log.NewJSONLogger(buf)
if err := logger.Log("err", errors.New("err"), "m", map[string]int{"0": 0}, "a", []int{1, 2, 3}); err != nil {
t.Fatal(err)
}
if want, have := `{"a":[1,2,3],"err":"err","m":{"0":0}}`+"\n", buf.String(); want != have {
t.Errorf("\nwant %#v\nhave %#v", want, have)
}
}
func TestJSONLoggerMissingValue(t *testing.T) {
t.Parallel()
buf := &bytes.Buffer{}
logger := log.NewJSONLogger(buf)
if err := logger.Log("k"); err != nil {
t.Fatal(err)
}
if want, have := `{"k":"(MISSING)"}`+"\n", buf.String(); want != have {
t.Errorf("\nwant %#v\nhave %#v", want, have)
}
}
func TestJSONLoggerNilStringerKey(t *testing.T) {
t.Parallel()
buf := &bytes.Buffer{}
logger := log.NewJSONLogger(buf)
if err := logger.Log((*stringer)(nil), "v"); err != nil {
t.Fatal(err)
}
if want, have := `{"NULL":"v"}`+"\n", buf.String(); want != have {
t.Errorf("\nwant %#v\nhave %#v", want, have)
}
}
func TestJSONLoggerNilErrorValue(t *testing.T) {
t.Parallel()
buf := &bytes.Buffer{}
logger := log.NewJSONLogger(buf)
if err := logger.Log("err", (*stringError)(nil)); err != nil {
t.Fatal(err)
}
if want, have := `{"err":null}`+"\n", buf.String(); want != have {
t.Errorf("\nwant %#v\nhave %#v", want, have)
}
}
func TestJSONLoggerNoHTMLEscape(t *testing.T) {
t.Parallel()
buf := &bytes.Buffer{}
logger := log.NewJSONLogger(buf)
if err := logger.Log("k", "<&>"); err != nil {
t.Fatal(err)
}
if want, have := `{"k":"<&>"}`+"\n", buf.String(); want != have {
t.Errorf("\nwant %#v\nhave%#v", want, have)
}
}
// aller implements json.Marshaler, encoding.TextMarshaler, and fmt.Stringer.
type aller struct{}
func (aller) MarshalJSON() ([]byte, error) {
return []byte("\"json\""), nil
}
func (aller) MarshalText() ([]byte, error) {
return []byte("text"), nil
}
func (aller) String() string {
return "string"
}
func (aller) Error() string {
return "error"
}
// textstringer implements encoding.TextMarshaler and fmt.Stringer.
type textstringer struct{}
func (textstringer) MarshalText() ([]byte, error) {
return []byte("text"), nil
}
func (textstringer) String() string {
return "string"
}
func TestJSONLoggerStringValue(t *testing.T) {
t.Parallel()
tests := []struct {
v interface{}
expected string
}{
{
v: aller{},
expected: `{"v":"json"}`,
},
{
v: textstringer{},
expected: `{"v":"text"}`,
},
{
v: stringer("string"),
expected: `{"v":"string"}`,
},
}
for _, test := range tests {
buf := &bytes.Buffer{}
logger := log.NewJSONLogger(buf)
if err := logger.Log("v", test.v); err != nil {
t.Fatal(err)
}
if want, have := test.expected+"\n", buf.String(); want != have {
t.Errorf("\nwant %#v\nhave %#v", want, have)
}
}
}
type stringer string
func (s stringer) String() string {
return string(s)
}
type stringError string
func (s stringError) Error() string {
return string(s)
}
func BenchmarkJSONLoggerSimple(b *testing.B) {
benchmarkRunner(b, log.NewJSONLogger(ioutil.Discard), baseMessage)
}
func BenchmarkJSONLoggerContextual(b *testing.B) {
benchmarkRunner(b, log.NewJSONLogger(ioutil.Discard), withMessage)
}
func TestJSONLoggerConcurrency(t *testing.T) {
t.Parallel()
testConcurrency(t, log.NewJSONLogger(ioutil.Discard), 10000)
}
golang-github-go-kit-kit-0.10.0/log/level/ 0000775 0000000 0000000 00000000000 13622563124 0020170 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/log/level/benchmark_test.go 0000664 0000000 0000000 00000003215 13622563124 0023511 0 ustar 00root root 0000000 0000000 package level_test
import (
"io/ioutil"
"testing"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
)
func Benchmark(b *testing.B) {
contexts := []struct {
name string
context func(log.Logger) log.Logger
}{
{"NoContext", func(l log.Logger) log.Logger {
return l
}},
{"TimeContext", func(l log.Logger) log.Logger {
return log.With(l, "time", log.DefaultTimestampUTC)
}},
{"CallerContext", func(l log.Logger) log.Logger {
return log.With(l, "caller", log.DefaultCaller)
}},
{"TimeCallerReqIDContext", func(l log.Logger) log.Logger {
return log.With(l, "time", log.DefaultTimestampUTC, "caller", log.DefaultCaller, "reqID", 29)
}},
}
loggers := []struct {
name string
logger log.Logger
}{
{"Nop", log.NewNopLogger()},
{"Logfmt", log.NewLogfmtLogger(ioutil.Discard)},
{"JSON", log.NewJSONLogger(ioutil.Discard)},
}
filters := []struct {
name string
filter func(log.Logger) log.Logger
}{
{"Baseline", func(l log.Logger) log.Logger {
return l
}},
{"DisallowedLevel", func(l log.Logger) log.Logger {
return level.NewFilter(l, level.AllowInfo())
}},
{"AllowedLevel", func(l log.Logger) log.Logger {
return level.NewFilter(l, level.AllowAll())
}},
}
for _, c := range contexts {
b.Run(c.name, func(b *testing.B) {
for _, f := range filters {
b.Run(f.name, func(b *testing.B) {
for _, l := range loggers {
b.Run(l.name, func(b *testing.B) {
logger := c.context(f.filter(l.logger))
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
level.Debug(logger).Log("foo", "bar")
}
})
}
})
}
})
}
}
golang-github-go-kit-kit-0.10.0/log/level/doc.go 0000664 0000000 0000000 00000001650 13622563124 0021266 0 ustar 00root root 0000000 0000000 // Package level implements leveled logging on top of Go kit's log package. To
// use the level package, create a logger as per normal in your func main, and
// wrap it with level.NewFilter.
//
// var logger log.Logger
// logger = log.NewLogfmtLogger(os.Stderr)
// logger = level.NewFilter(logger, level.AllowInfo()) // <--
// logger = log.With(logger, "ts", log.DefaultTimestampUTC)
//
// Then, at the callsites, use one of the level.Debug, Info, Warn, or Error
// helper methods to emit leveled log events.
//
// logger.Log("foo", "bar") // as normal, no level
// level.Debug(logger).Log("request_id", reqID, "trace_data", trace.Get())
// if value > 100 {
// level.Error(logger).Log("value", value)
// }
//
// NewFilter allows precise control over what happens when a log event is
// emitted without a level key, or if a squelched level is used. Check the
// Option functions for details.
package level
golang-github-go-kit-kit-0.10.0/log/level/example_test.go 0000664 0000000 0000000 00000002340 13622563124 0023210 0 ustar 00root root 0000000 0000000 package level_test
import (
"errors"
"os"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
)
func Example_basic() {
logger := log.NewLogfmtLogger(os.Stdout)
level.Debug(logger).Log("msg", "this message is at the debug level")
level.Info(logger).Log("msg", "this message is at the info level")
level.Warn(logger).Log("msg", "this message is at the warn level")
level.Error(logger).Log("msg", "this message is at the error level")
// Output:
// level=debug msg="this message is at the debug level"
// level=info msg="this message is at the info level"
// level=warn msg="this message is at the warn level"
// level=error msg="this message is at the error level"
}
func Example_filtered() {
// Set up logger with level filter.
logger := log.NewLogfmtLogger(os.Stdout)
logger = level.NewFilter(logger, level.AllowInfo())
logger = log.With(logger, "caller", log.DefaultCaller)
// Use level helpers to log at different levels.
level.Error(logger).Log("err", errors.New("bad data"))
level.Info(logger).Log("event", "data saved")
level.Debug(logger).Log("next item", 17) // filtered
// Output:
// level=error caller=example_test.go:32 err="bad data"
// level=info caller=example_test.go:33 event="data saved"
}
golang-github-go-kit-kit-0.10.0/log/level/level.go 0000664 0000000 0000000 00000013435 13622563124 0021634 0 ustar 00root root 0000000 0000000 package level
import "github.com/go-kit/kit/log"
// Error returns a logger that includes a Key/ErrorValue pair.
func Error(logger log.Logger) log.Logger {
return log.WithPrefix(logger, Key(), ErrorValue())
}
// Warn returns a logger that includes a Key/WarnValue pair.
func Warn(logger log.Logger) log.Logger {
return log.WithPrefix(logger, Key(), WarnValue())
}
// Info returns a logger that includes a Key/InfoValue pair.
func Info(logger log.Logger) log.Logger {
return log.WithPrefix(logger, Key(), InfoValue())
}
// Debug returns a logger that includes a Key/DebugValue pair.
func Debug(logger log.Logger) log.Logger {
return log.WithPrefix(logger, Key(), DebugValue())
}
// NewFilter wraps next and implements level filtering. See the commentary on
// the Option functions for a detailed description of how to configure levels.
// If no options are provided, all leveled log events created with Debug,
// Info, Warn or Error helper methods are squelched and non-leveled log
// events are passed to next unmodified.
func NewFilter(next log.Logger, options ...Option) log.Logger {
l := &logger{
next: next,
}
for _, option := range options {
option(l)
}
return l
}
type logger struct {
next log.Logger
allowed level
squelchNoLevel bool
errNotAllowed error
errNoLevel error
}
func (l *logger) Log(keyvals ...interface{}) error {
var hasLevel, levelAllowed bool
for i := 1; i < len(keyvals); i += 2 {
if v, ok := keyvals[i].(*levelValue); ok {
hasLevel = true
levelAllowed = l.allowed&v.level != 0
break
}
}
if !hasLevel && l.squelchNoLevel {
return l.errNoLevel
}
if hasLevel && !levelAllowed {
return l.errNotAllowed
}
return l.next.Log(keyvals...)
}
// Option sets a parameter for the leveled logger.
type Option func(*logger)
// AllowAll is an alias for AllowDebug.
func AllowAll() Option {
return AllowDebug()
}
// AllowDebug allows error, warn, info and debug level log events to pass.
func AllowDebug() Option {
return allowed(levelError | levelWarn | levelInfo | levelDebug)
}
// AllowInfo allows error, warn and info level log events to pass.
func AllowInfo() Option {
return allowed(levelError | levelWarn | levelInfo)
}
// AllowWarn allows error and warn level log events to pass.
func AllowWarn() Option {
return allowed(levelError | levelWarn)
}
// AllowError allows only error level log events to pass.
func AllowError() Option {
return allowed(levelError)
}
// AllowNone allows no leveled log events to pass.
func AllowNone() Option {
return allowed(0)
}
func allowed(allowed level) Option {
return func(l *logger) { l.allowed = allowed }
}
// ErrNotAllowed sets the error to return from Log when it squelches a log
// event disallowed by the configured Allow[Level] option. By default,
// ErrNotAllowed is nil; in this case the log event is squelched with no
// error.
func ErrNotAllowed(err error) Option {
return func(l *logger) { l.errNotAllowed = err }
}
// SquelchNoLevel instructs Log to squelch log events with no level, so that
// they don't proceed through to the wrapped logger. If SquelchNoLevel is set
// to true and a log event is squelched in this way, the error value
// configured with ErrNoLevel is returned to the caller.
func SquelchNoLevel(squelch bool) Option {
return func(l *logger) { l.squelchNoLevel = squelch }
}
// ErrNoLevel sets the error to return from Log when it squelches a log event
// with no level. By default, ErrNoLevel is nil; in this case the log event is
// squelched with no error.
func ErrNoLevel(err error) Option {
return func(l *logger) { l.errNoLevel = err }
}
// NewInjector wraps next and returns a logger that adds a Key/level pair to
// the beginning of log events that don't already contain a level. In effect,
// this gives a default level to logs without a level.
func NewInjector(next log.Logger, level Value) log.Logger {
return &injector{
next: next,
level: level,
}
}
type injector struct {
next log.Logger
level interface{}
}
func (l *injector) Log(keyvals ...interface{}) error {
for i := 1; i < len(keyvals); i += 2 {
if _, ok := keyvals[i].(*levelValue); ok {
return l.next.Log(keyvals...)
}
}
kvs := make([]interface{}, len(keyvals)+2)
kvs[0], kvs[1] = key, l.level
copy(kvs[2:], keyvals)
return l.next.Log(kvs...)
}
// Value is the interface that each of the canonical level values implement.
// It contains unexported methods that prevent types from other packages from
// implementing it and guaranteeing that NewFilter can distinguish the levels
// defined in this package from all other values.
type Value interface {
String() string
levelVal()
}
// Key returns the unique key added to log events by the loggers in this
// package.
func Key() interface{} { return key }
// ErrorValue returns the unique value added to log events by Error.
func ErrorValue() Value { return errorValue }
// WarnValue returns the unique value added to log events by Warn.
func WarnValue() Value { return warnValue }
// InfoValue returns the unique value added to log events by Info.
func InfoValue() Value { return infoValue }
// DebugValue returns the unique value added to log events by Warn.
func DebugValue() Value { return debugValue }
var (
// key is of type interface{} so that it allocates once during package
// initialization and avoids allocating every time the value is added to a
// []interface{} later.
key interface{} = "level"
errorValue = &levelValue{level: levelError, name: "error"}
warnValue = &levelValue{level: levelWarn, name: "warn"}
infoValue = &levelValue{level: levelInfo, name: "info"}
debugValue = &levelValue{level: levelDebug, name: "debug"}
)
type level byte
const (
levelDebug level = 1 << iota
levelInfo
levelWarn
levelError
)
type levelValue struct {
name string
level
}
func (v *levelValue) String() string { return v.name }
func (v *levelValue) levelVal() {}
golang-github-go-kit-kit-0.10.0/log/level/level_test.go 0000664 0000000 0000000 00000014040 13622563124 0022664 0 ustar 00root root 0000000 0000000 package level_test
import (
"bytes"
"errors"
"io"
"strings"
"testing"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
)
func TestVariousLevels(t *testing.T) {
testCases := []struct {
name string
allowed level.Option
want string
}{
{
"AllowAll",
level.AllowAll(),
strings.Join([]string{
`{"level":"debug","this is":"debug log"}`,
`{"level":"info","this is":"info log"}`,
`{"level":"warn","this is":"warn log"}`,
`{"level":"error","this is":"error log"}`,
}, "\n"),
},
{
"AllowDebug",
level.AllowDebug(),
strings.Join([]string{
`{"level":"debug","this is":"debug log"}`,
`{"level":"info","this is":"info log"}`,
`{"level":"warn","this is":"warn log"}`,
`{"level":"error","this is":"error log"}`,
}, "\n"),
},
{
"AllowInfo",
level.AllowInfo(),
strings.Join([]string{
`{"level":"info","this is":"info log"}`,
`{"level":"warn","this is":"warn log"}`,
`{"level":"error","this is":"error log"}`,
}, "\n"),
},
{
"AllowWarn",
level.AllowWarn(),
strings.Join([]string{
`{"level":"warn","this is":"warn log"}`,
`{"level":"error","this is":"error log"}`,
}, "\n"),
},
{
"AllowError",
level.AllowError(),
strings.Join([]string{
`{"level":"error","this is":"error log"}`,
}, "\n"),
},
{
"AllowNone",
level.AllowNone(),
``,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
var buf bytes.Buffer
logger := level.NewFilter(log.NewJSONLogger(&buf), tc.allowed)
level.Debug(logger).Log("this is", "debug log")
level.Info(logger).Log("this is", "info log")
level.Warn(logger).Log("this is", "warn log")
level.Error(logger).Log("this is", "error log")
if want, have := tc.want, strings.TrimSpace(buf.String()); want != have {
t.Errorf("\nwant:\n%s\nhave:\n%s", want, have)
}
})
}
}
func TestErrNotAllowed(t *testing.T) {
myError := errors.New("squelched!")
opts := []level.Option{
level.AllowWarn(),
level.ErrNotAllowed(myError),
}
logger := level.NewFilter(log.NewNopLogger(), opts...)
if want, have := myError, level.Info(logger).Log("foo", "bar"); want != have {
t.Errorf("want %#+v, have %#+v", want, have)
}
if want, have := error(nil), level.Warn(logger).Log("foo", "bar"); want != have {
t.Errorf("want %#+v, have %#+v", want, have)
}
}
func TestErrNoLevel(t *testing.T) {
myError := errors.New("no level specified")
var buf bytes.Buffer
opts := []level.Option{
level.SquelchNoLevel(true),
level.ErrNoLevel(myError),
}
logger := level.NewFilter(log.NewJSONLogger(&buf), opts...)
if want, have := myError, logger.Log("foo", "bar"); want != have {
t.Errorf("want %v, have %v", want, have)
}
if want, have := ``, strings.TrimSpace(buf.String()); want != have {
t.Errorf("\nwant '%s'\nhave '%s'", want, have)
}
}
func TestAllowNoLevel(t *testing.T) {
var buf bytes.Buffer
opts := []level.Option{
level.SquelchNoLevel(false),
level.ErrNoLevel(errors.New("I should never be returned!")),
}
logger := level.NewFilter(log.NewJSONLogger(&buf), opts...)
if want, have := error(nil), logger.Log("foo", "bar"); want != have {
t.Errorf("want %v, have %v", want, have)
}
if want, have := `{"foo":"bar"}`, strings.TrimSpace(buf.String()); want != have {
t.Errorf("\nwant '%s'\nhave '%s'", want, have)
}
}
func TestLevelContext(t *testing.T) {
var buf bytes.Buffer
// Wrapping the level logger with a context allows users to use
// log.DefaultCaller as per normal.
var logger log.Logger
logger = log.NewLogfmtLogger(&buf)
logger = level.NewFilter(logger, level.AllowAll())
logger = log.With(logger, "caller", log.DefaultCaller)
level.Info(logger).Log("foo", "bar")
if want, have := `level=info caller=level_test.go:149 foo=bar`, strings.TrimSpace(buf.String()); want != have {
t.Errorf("\nwant '%s'\nhave '%s'", want, have)
}
}
func TestContextLevel(t *testing.T) {
var buf bytes.Buffer
// Wrapping a context with the level logger still works, but requires users
// to specify a higher callstack depth value.
var logger log.Logger
logger = log.NewLogfmtLogger(&buf)
logger = log.With(logger, "caller", log.Caller(5))
logger = level.NewFilter(logger, level.AllowAll())
level.Info(logger).Log("foo", "bar")
if want, have := `caller=level_test.go:165 level=info foo=bar`, strings.TrimSpace(buf.String()); want != have {
t.Errorf("\nwant '%s'\nhave '%s'", want, have)
}
}
func TestLevelFormatting(t *testing.T) {
testCases := []struct {
name string
format func(io.Writer) log.Logger
output string
}{
{
name: "logfmt",
format: log.NewLogfmtLogger,
output: `level=info foo=bar`,
},
{
name: "JSON",
format: log.NewJSONLogger,
output: `{"foo":"bar","level":"info"}`,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
var buf bytes.Buffer
logger := tc.format(&buf)
level.Info(logger).Log("foo", "bar")
if want, have := tc.output, strings.TrimSpace(buf.String()); want != have {
t.Errorf("\nwant: '%s'\nhave '%s'", want, have)
}
})
}
}
func TestInjector(t *testing.T) {
var (
output []interface{}
logger log.Logger
)
logger = log.LoggerFunc(func(keyvals ...interface{}) error {
output = keyvals
return nil
})
logger = level.NewInjector(logger, level.InfoValue())
logger.Log("foo", "bar")
if got, want := len(output), 4; got != want {
t.Errorf("missing level not injected: got len==%d, want len==%d", got, want)
}
if got, want := output[0], level.Key(); got != want {
t.Errorf("wrong level key: got %#v, want %#v", got, want)
}
if got, want := output[1], level.InfoValue(); got != want {
t.Errorf("wrong level value: got %#v, want %#v", got, want)
}
level.Error(logger).Log("foo", "bar")
if got, want := len(output), 4; got != want {
t.Errorf("leveled record modified: got len==%d, want len==%d", got, want)
}
if got, want := output[0], level.Key(); got != want {
t.Errorf("wrong level key: got %#v, want %#v", got, want)
}
if got, want := output[1], level.ErrorValue(); got != want {
t.Errorf("wrong level value: got %#v, want %#v", got, want)
}
}
golang-github-go-kit-kit-0.10.0/log/log.go 0000664 0000000 0000000 00000011545 13622563124 0020177 0 ustar 00root root 0000000 0000000 package log
import "errors"
// Logger is the fundamental interface for all log operations. Log creates a
// log event from keyvals, a variadic sequence of alternating keys and values.
// Implementations must be safe for concurrent use by multiple goroutines. In
// particular, any implementation of Logger that appends to keyvals or
// modifies or retains any of its elements must make a copy first.
type Logger interface {
Log(keyvals ...interface{}) error
}
// ErrMissingValue is appended to keyvals slices with odd length to substitute
// the missing value.
var ErrMissingValue = errors.New("(MISSING)")
// With returns a new contextual logger with keyvals prepended to those passed
// to calls to Log. If logger is also a contextual logger created by With or
// WithPrefix, keyvals is appended to the existing context.
//
// The returned Logger replaces all value elements (odd indexes) containing a
// Valuer with their generated value for each call to its Log method.
func With(logger Logger, keyvals ...interface{}) Logger {
if len(keyvals) == 0 {
return logger
}
l := newContext(logger)
kvs := append(l.keyvals, keyvals...)
if len(kvs)%2 != 0 {
kvs = append(kvs, ErrMissingValue)
}
return &context{
logger: l.logger,
// Limiting the capacity of the stored keyvals ensures that a new
// backing array is created if the slice must grow in Log or With.
// Using the extra capacity without copying risks a data race that
// would violate the Logger interface contract.
keyvals: kvs[:len(kvs):len(kvs)],
hasValuer: l.hasValuer || containsValuer(keyvals),
}
}
// WithPrefix returns a new contextual logger with keyvals prepended to those
// passed to calls to Log. If logger is also a contextual logger created by
// With or WithPrefix, keyvals is prepended to the existing context.
//
// The returned Logger replaces all value elements (odd indexes) containing a
// Valuer with their generated value for each call to its Log method.
func WithPrefix(logger Logger, keyvals ...interface{}) Logger {
if len(keyvals) == 0 {
return logger
}
l := newContext(logger)
// Limiting the capacity of the stored keyvals ensures that a new
// backing array is created if the slice must grow in Log or With.
// Using the extra capacity without copying risks a data race that
// would violate the Logger interface contract.
n := len(l.keyvals) + len(keyvals)
if len(keyvals)%2 != 0 {
n++
}
kvs := make([]interface{}, 0, n)
kvs = append(kvs, keyvals...)
if len(kvs)%2 != 0 {
kvs = append(kvs, ErrMissingValue)
}
kvs = append(kvs, l.keyvals...)
return &context{
logger: l.logger,
keyvals: kvs,
hasValuer: l.hasValuer || containsValuer(keyvals),
}
}
// context is the Logger implementation returned by With and WithPrefix. It
// wraps a Logger and holds keyvals that it includes in all log events. Its
// Log method calls bindValues to generate values for each Valuer in the
// context keyvals.
//
// A context must always have the same number of stack frames between calls to
// its Log method and the eventual binding of Valuers to their value. This
// requirement comes from the functional requirement to allow a context to
// resolve application call site information for a Caller stored in the
// context. To do this we must be able to predict the number of logging
// functions on the stack when bindValues is called.
//
// Two implementation details provide the needed stack depth consistency.
//
// 1. newContext avoids introducing an additional layer when asked to
// wrap another context.
// 2. With and WithPrefix avoid introducing an additional layer by
// returning a newly constructed context with a merged keyvals rather
// than simply wrapping the existing context.
type context struct {
logger Logger
keyvals []interface{}
hasValuer bool
}
func newContext(logger Logger) *context {
if c, ok := logger.(*context); ok {
return c
}
return &context{logger: logger}
}
// Log replaces all value elements (odd indexes) containing a Valuer in the
// stored context with their generated value, appends keyvals, and passes the
// result to the wrapped Logger.
func (l *context) Log(keyvals ...interface{}) error {
kvs := append(l.keyvals, keyvals...)
if len(kvs)%2 != 0 {
kvs = append(kvs, ErrMissingValue)
}
if l.hasValuer {
// If no keyvals were appended above then we must copy l.keyvals so
// that future log events will reevaluate the stored Valuers.
if len(keyvals) == 0 {
kvs = append([]interface{}{}, l.keyvals...)
}
bindValues(kvs[:len(l.keyvals)])
}
return l.logger.Log(kvs...)
}
// LoggerFunc is an adapter to allow use of ordinary functions as Loggers. If
// f is a function with the appropriate signature, LoggerFunc(f) is a Logger
// object that calls f.
type LoggerFunc func(...interface{}) error
// Log implements Logger by calling f(keyvals...).
func (f LoggerFunc) Log(keyvals ...interface{}) error {
return f(keyvals...)
}
golang-github-go-kit-kit-0.10.0/log/log_test.go 0000664 0000000 0000000 00000011071 13622563124 0021230 0 ustar 00root root 0000000 0000000 package log_test
import (
"bytes"
"fmt"
"sync"
"testing"
"github.com/go-kit/kit/log"
"github.com/go-stack/stack"
)
func TestContext(t *testing.T) {
t.Parallel()
buf := &bytes.Buffer{}
logger := log.NewLogfmtLogger(buf)
kvs := []interface{}{"a", 123}
lc := log.With(logger, kvs...)
kvs[1] = 0 // With should copy its key values
lc = log.With(lc, "b", "c") // With should stack
if err := lc.Log("msg", "message"); err != nil {
t.Fatal(err)
}
if want, have := "a=123 b=c msg=message\n", buf.String(); want != have {
t.Errorf("\nwant: %shave: %s", want, have)
}
buf.Reset()
lc = log.WithPrefix(lc, "p", "first")
if err := lc.Log("msg", "message"); err != nil {
t.Fatal(err)
}
if want, have := "p=first a=123 b=c msg=message\n", buf.String(); want != have {
t.Errorf("\nwant: %shave: %s", want, have)
}
}
func TestContextMissingValue(t *testing.T) {
t.Parallel()
var output []interface{}
logger := log.Logger(log.LoggerFunc(func(keyvals ...interface{}) error {
output = keyvals
return nil
}))
log.WithPrefix(log.With(logger, "k1"), "k0").Log("k2")
if want, have := 6, len(output); want != have {
t.Errorf("want len(output) == %v, have %v", want, have)
}
for i := 1; i < 6; i += 2 {
if want, have := log.ErrMissingValue, output[i]; want != have {
t.Errorf("want output[%d] == %#v, have %#v", i, want, have)
}
}
}
// Test that context.Log has a consistent function stack depth when binding
// Valuers, regardless of how many times With has been called.
func TestContextStackDepth(t *testing.T) {
t.Parallel()
fn := fmt.Sprintf("%n", stack.Caller(0))
var output []interface{}
logger := log.Logger(log.LoggerFunc(func(keyvals ...interface{}) error {
output = keyvals
return nil
}))
stackValuer := log.Valuer(func() interface{} {
for i, c := range stack.Trace() {
if fmt.Sprintf("%n", c) == fn {
return i
}
}
t.Fatal("Test function not found in stack trace.")
return nil
})
logger = log.With(logger, "stack", stackValuer)
// Call through interface to get baseline.
logger.Log("k", "v")
want := output[1].(int)
for len(output) < 10 {
logger.Log("k", "v")
if have := output[1]; have != want {
t.Errorf("%d Withs: have %v, want %v", len(output)/2-1, have, want)
}
wrapped := log.With(logger)
wrapped.Log("k", "v")
if have := output[1]; have != want {
t.Errorf("%d Withs: have %v, want %v", len(output)/2-1, have, want)
}
logger = log.With(logger, "k", "v")
}
}
// Test that With returns a Logger safe for concurrent use. This test
// validates that the stored logging context does not get corrupted when
// multiple clients concurrently log additional keyvals.
//
// This test must be run with go test -cpu 2 (or more) to achieve its goal.
func TestWithConcurrent(t *testing.T) {
// Create some buckets to count how many events each goroutine logs.
const goroutines = 8
counts := [goroutines]int{}
// This logger extracts a goroutine id from the last value field and
// increments the referenced bucket.
logger := log.LoggerFunc(func(kv ...interface{}) error {
goroutine := kv[len(kv)-1].(int)
counts[goroutine]++
return nil
})
// With must be careful about handling slices that can grow without
// copying the underlying array, so give it a challenge.
l := log.With(logger, make([]interface{}, 0, 2)...)
// Start logging concurrently. Each goroutine logs its id so the logger
// can bucket the event counts.
var wg sync.WaitGroup
wg.Add(goroutines)
const n = 10000
for i := 0; i < goroutines; i++ {
go func(idx int) {
defer wg.Done()
for j := 0; j < n; j++ {
l.Log("goroutineIdx", idx)
}
}(i)
}
wg.Wait()
for bucket, have := range counts {
if want := n; want != have {
t.Errorf("bucket %d: want %d, have %d", bucket, want, have) // note Errorf
}
}
}
func BenchmarkDiscard(b *testing.B) {
logger := log.NewNopLogger()
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
logger.Log("k", "v")
}
}
func BenchmarkOneWith(b *testing.B) {
logger := log.NewNopLogger()
lc := log.With(logger, "k", "v")
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
lc.Log("k", "v")
}
}
func BenchmarkTwoWith(b *testing.B) {
logger := log.NewNopLogger()
lc := log.With(logger, "k", "v")
for i := 1; i < 2; i++ {
lc = log.With(lc, "k", "v")
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
lc.Log("k", "v")
}
}
func BenchmarkTenWith(b *testing.B) {
logger := log.NewNopLogger()
lc := log.With(logger, "k", "v")
for i := 1; i < 10; i++ {
lc = log.With(lc, "k", "v")
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
lc.Log("k", "v")
}
}
golang-github-go-kit-kit-0.10.0/log/logfmt_logger.go 0000664 0000000 0000000 00000002541 13622563124 0022241 0 ustar 00root root 0000000 0000000 package log
import (
"bytes"
"io"
"sync"
"github.com/go-logfmt/logfmt"
)
type logfmtEncoder struct {
*logfmt.Encoder
buf bytes.Buffer
}
func (l *logfmtEncoder) Reset() {
l.Encoder.Reset()
l.buf.Reset()
}
var logfmtEncoderPool = sync.Pool{
New: func() interface{} {
var enc logfmtEncoder
enc.Encoder = logfmt.NewEncoder(&enc.buf)
return &enc
},
}
type logfmtLogger struct {
w io.Writer
}
// NewLogfmtLogger returns a logger that encodes keyvals to the Writer in
// logfmt format. Each log event produces no more than one call to w.Write.
// The passed Writer must be safe for concurrent use by multiple goroutines if
// the returned Logger will be used concurrently.
func NewLogfmtLogger(w io.Writer) Logger {
return &logfmtLogger{w}
}
func (l logfmtLogger) Log(keyvals ...interface{}) error {
enc := logfmtEncoderPool.Get().(*logfmtEncoder)
enc.Reset()
defer logfmtEncoderPool.Put(enc)
if err := enc.EncodeKeyvals(keyvals...); err != nil {
return err
}
// Add newline to the end of the buffer
if err := enc.EndRecord(); err != nil {
return err
}
// The Logger interface requires implementations to be safe for concurrent
// use by multiple goroutines. For this implementation that means making
// only one call to l.w.Write() for each call to Log.
if _, err := l.w.Write(enc.buf.Bytes()); err != nil {
return err
}
return nil
}
golang-github-go-kit-kit-0.10.0/log/logfmt_logger_test.go 0000664 0000000 0000000 00000002607 13622563124 0023303 0 ustar 00root root 0000000 0000000 package log_test
import (
"bytes"
"errors"
"io/ioutil"
"testing"
"github.com/go-kit/kit/log"
"github.com/go-logfmt/logfmt"
)
func TestLogfmtLogger(t *testing.T) {
t.Parallel()
buf := &bytes.Buffer{}
logger := log.NewLogfmtLogger(buf)
if err := logger.Log("hello", "world"); err != nil {
t.Fatal(err)
}
if want, have := "hello=world\n", buf.String(); want != have {
t.Errorf("want %#v, have %#v", want, have)
}
buf.Reset()
if err := logger.Log("a", 1, "err", errors.New("error")); err != nil {
t.Fatal(err)
}
if want, have := "a=1 err=error\n", buf.String(); want != have {
t.Errorf("want %#v, have %#v", want, have)
}
buf.Reset()
if err := logger.Log("std_map", map[int]int{1: 2}, "my_map", mymap{0: 0}); err != nil {
t.Fatal(err)
}
if want, have := "std_map=\""+logfmt.ErrUnsupportedValueType.Error()+"\" my_map=special_behavior\n", buf.String(); want != have {
t.Errorf("want %#v, have %#v", want, have)
}
}
func BenchmarkLogfmtLoggerSimple(b *testing.B) {
benchmarkRunner(b, log.NewLogfmtLogger(ioutil.Discard), baseMessage)
}
func BenchmarkLogfmtLoggerContextual(b *testing.B) {
benchmarkRunner(b, log.NewLogfmtLogger(ioutil.Discard), withMessage)
}
func TestLogfmtLoggerConcurrency(t *testing.T) {
t.Parallel()
testConcurrency(t, log.NewLogfmtLogger(ioutil.Discard), 10000)
}
type mymap map[int]int
func (m mymap) String() string { return "special_behavior" }
golang-github-go-kit-kit-0.10.0/log/logrus/ 0000775 0000000 0000000 00000000000 13622563124 0020374 5 ustar 00root root 0000000 0000000 golang-github-go-kit-kit-0.10.0/log/logrus/logrus_logger.go 0000664 0000000 0000000 00000001407 13622563124 0023577 0 ustar 00root root 0000000 0000000 // Package logrus provides an adapter to the
// go-kit log.Logger interface.
package logrus
import (
"errors"
"fmt"
"github.com/go-kit/kit/log"
"github.com/sirupsen/logrus"
)
type logrusLogger struct {
logrus.FieldLogger
}
var errMissingValue = errors.New("(MISSING)")
// NewLogrusLogger returns a go-kit log.Logger that sends log events to a Logrus logger.
func NewLogrusLogger(logger logrus.FieldLogger) log.Logger {
return &logrusLogger{logger}
}
func (l logrusLogger) Log(keyvals ...interface{}) error {
fields := logrus.Fields{}
for i := 0; i < len(keyvals); i += 2 {
if i+1 < len(keyvals) {
fields[fmt.Sprint(keyvals[i])] = keyvals[i+1]
} else {
fields[fmt.Sprint(keyvals[i])] = errMissingValue
}
}
l.WithFields(fields).Info()
return nil
}
golang-github-go-kit-kit-0.10.0/log/logrus/logrus_logger_test.go 0000664 0000000 0000000 00000002731 13622563124 0024637 0 ustar 00root root 0000000 0000000 package logrus_test
import (
"bytes"
"errors"
"strings"
"testing"
log "github.com/go-kit/kit/log/logrus"
"github.com/sirupsen/logrus"
)
func TestLogrusLogger(t *testing.T) {
t.Parallel()
buf := &bytes.Buffer{}
logrusLogger := logrus.New()
logrusLogger.Out = buf
logrusLogger.Formatter = &logrus.TextFormatter{TimestampFormat: "02-01-2006 15:04:05", FullTimestamp: true}
logger := log.NewLogrusLogger(logrusLogger)
if err := logger.Log("hello", "world"); err != nil {
t.Fatal(err)
}
if want, have := "hello=world\n", strings.Split(buf.String(), " ")[3]; want != have {
t.Errorf("want %#v, have %#v", want, have)
}
buf.Reset()
if err := logger.Log("a", 1, "err", errors.New("error")); err != nil {
t.Fatal(err)
}
if want, have := "a=1 err=error", strings.TrimSpace(strings.SplitAfterN(buf.String(), " ", 4)[3]); want != have {
t.Errorf("want %#v, have %#v", want, have)
}
buf.Reset()
if err := logger.Log("a", 1, "b"); err != nil {
t.Fatal(err)
}
if want, have := "a=1 b=\"(MISSING)\"", strings.TrimSpace(strings.SplitAfterN(buf.String(), " ", 4)[3]); want != have {
t.Errorf("want %#v, have %#v", want, have)
}
buf.Reset()
if err := logger.Log("my_map", mymap{0: 0}); err != nil {
t.Fatal(err)
}
if want, have := "my_map=special_behavior", strings.TrimSpace(strings.Split(buf.String(), " ")[3]); want != have {
t.Errorf("want %#v, have %#v", want, have)
}
}
type mymap map[int]int
func (m mymap) String() string { return "special_behavior" }
golang-github-go-kit-kit-0.10.0/log/nop_logger.go 0000664 0000000 0000000 00000000316 13622563124 0021543 0 ustar 00root root 0000000 0000000 package log
type nopLogger struct{}
// NewNopLogger returns a logger that doesn't do anything.
func NewNopLogger() Logger { return nopLogger{} }
func (nopLogger) Log(...interface{}) error { return nil }
golang-github-go-kit-kit-0.10.0/log/nop_logger_test.go 0000664 0000000 0000000 00000000772 13622563124 0022610 0 ustar 00root root 0000000 0000000 package log_test
import (
"testing"
"github.com/go-kit/kit/log"
)
func TestNopLogger(t *testing.T) {
t.Parallel()
logger := log.NewNopLogger()
if err := logger.Log("abc", 123); err != nil {
t.Error(err)
}
if err := log.With(logger, "def", "ghi").Log(); err != nil {
t.Error(err)
}
}
func BenchmarkNopLoggerSimple(b *testing.B) {
benchmarkRunner(b, log.NewNopLogger(), baseMessage)
}
func BenchmarkNopLoggerContextual(b *testing.B) {
benchmarkRunner(b, log.NewNopLogger(), withMessage)
}
golang-github-go-kit-kit-0.10.0/log/stdlib.go 0000664 0000000 0000000 00000006257 13622563124 0020703 0 ustar 00root root 0000000 0000000 package log
import (
"io"
"log"
"regexp"
"strings"
)
// StdlibWriter implements io.Writer by invoking the stdlib log.Print. It's
// designed to be passed to a Go kit logger as the writer, for cases where
// it's necessary to redirect all Go kit log output to the stdlib logger.
//
// If you have any choice in the matter, you shouldn't use this. Prefer to
// redirect the stdlib log to the Go kit logger via NewStdlibAdapter.
type StdlibWriter struct{}
// Write implements io.Writer.
func (w StdlibWriter) Write(p []byte) (int, error) {
log.Print(strings.TrimSpace(string(p)))
return len(p), nil
}
// StdlibAdapter wraps a Logger and allows it to be passed to the stdlib
// logger's SetOutput. It will extract date/timestamps, filenames, and
// messages, and place them under relevant keys.
type StdlibAdapter struct {
Logger
timestampKey string
fileKey string
messageKey string
}
// StdlibAdapterOption sets a parameter for the StdlibAdapter.
type StdlibAdapterOption func(*StdlibAdapter)
// TimestampKey sets the key for the timestamp field. By default, it's "ts".
func TimestampKey(key string) StdlibAdapterOption {
return func(a *StdlibAdapter) { a.timestampKey = key }
}
// FileKey sets the key for the file and line field. By default, it's "caller".
func FileKey(key string) StdlibAdapterOption {
return func(a *StdlibAdapter) { a.fileKey = key }
}
// MessageKey sets the key for the actual log message. By default, it's "msg".
func MessageKey(key string) StdlibAdapterOption {
return func(a *StdlibAdapter) { a.messageKey = key }
}
// NewStdlibAdapter returns a new StdlibAdapter wrapper around the passed
// logger. It's designed to be passed to log.SetOutput.
func NewStdlibAdapter(logger Logger, options ...StdlibAdapterOption) io.Writer {
a := StdlibAdapter{
Logger: logger,
timestampKey: "ts",
fileKey: "caller",
messageKey: "msg",
}
for _, option := range options {
option(&a)
}
return a
}
func (a StdlibAdapter) Write(p []byte) (int, error) {
result := subexps(p)
keyvals := []interface{}{}
var timestamp string
if date, ok := result["date"]; ok && date != "" {
timestamp = date
}
if time, ok := result["time"]; ok && time != "" {
if timestamp != "" {
timestamp += " "
}
timestamp += time
}
if timestamp != "" {
keyvals = append(keyvals, a.timestampKey, timestamp)
}
if file, ok := result["file"]; ok && file != "" {
keyvals = append(keyvals, a.fileKey, file)
}
if msg, ok := result["msg"]; ok {
keyvals = append(keyvals, a.messageKey, msg)
}
if err := a.Logger.Log(keyvals...); err != nil {
return 0, err
}
return len(p), nil
}
const (
logRegexpDate = `(?P[0-9]{4}/[0-9]{2}/[0-9]{2})?[ ]?`
logRegexpTime = `(?P