Moved to google.golang.org/genproto/googleapis/api/annotations
Fixes #52
This commit is contained in:
45
vendor/github.com/go-kit/kit/.gitignore
generated
vendored
Normal file
45
vendor/github.com/go-kit/kit/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
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
|
||||
|
8
vendor/github.com/go-kit/kit/.travis.yml
generated
vendored
Normal file
8
vendor/github.com/go-kit/kit/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
language: go
|
||||
|
||||
script: go test -race -v ./...
|
||||
|
||||
go:
|
||||
- 1.7.5
|
||||
- 1.8
|
||||
- tip
|
18
vendor/github.com/go-kit/kit/CONTRIBUTING.md
generated
vendored
Normal file
18
vendor/github.com/go-kit/kit/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
# 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
|
||||
|
22
vendor/github.com/go-kit/kit/LICENSE
generated
vendored
Normal file
22
vendor/github.com/go-kit/kit/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
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.
|
||||
|
121
vendor/github.com/go-kit/kit/README.md
generated
vendored
Normal file
121
vendor/github.com/go-kit/kit/README.md
generated
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
# Go kit [](https://circleci.com/gh/go-kit/kit) [](https://travis-ci.org/go-kit/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 **distributed programming toolkit** for building microservices
|
||||
in large organizations. We solve common problems in distributed systems, so
|
||||
you can focus on your business logic.
|
||||
|
||||
- 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/))
|
||||
|
||||
## Motivation
|
||||
|
||||
Go has emerged as the language of the server, but it remains underrepresented
|
||||
in large, consumer-focused tech companies like Facebook, Twitter, Netflix, and
|
||||
SoundCloud. These organizations have largely adopted 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 a library, designed to be imported into a binary package.
|
||||
Vendoring is currently the best way for binary package authors
|
||||
to ensure reliable, reproducible builds.
|
||||
Therefore, we strongly recommend our users use vendoring for all of their dependencies,
|
||||
including Go kit.
|
||||
To avoid compatibility and availability issues,
|
||||
Go kit doesn't vendor its own dependencies,
|
||||
and doesn't recommend use of third-party import proxies.
|
||||
|
||||
There are several tools which make vendoring easier, including
|
||||
[gb](http://getgb.io),
|
||||
[glide](https://github.com/Masterminds/glide),
|
||||
[gvt](https://github.com/FiloSottile/gvt),
|
||||
[govendor](https://github.com/kardianos/govendor), and
|
||||
[vendetta](https://github.com/dpw/vendetta).
|
||||
In addition, Go kit uses a variety of continuous integration providers
|
||||
to find and fix compatibility problems as soon as they occur.
|
||||
|
||||
## 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 ★
|
||||
- [h2](https://github.com/hailocab/h2), a microservices framework ★
|
||||
- [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.github.io/gin/)
|
||||
- [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))
|
||||
|
||||
## Additional reading
|
||||
|
||||
- [Architecting for the Cloud](http://fr.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
|
||||
|
||||
---
|
||||
|
||||
Development supported by [DigitalOcean](https://digitalocean.com).
|
17
vendor/github.com/go-kit/kit/ROADMAP.md
generated
vendored
Normal file
17
vendor/github.com/go-kit/kit/ROADMAP.md
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
# Roadmap
|
||||
|
||||
This is a coarse-grained roadmap of Go kit development direction in the short
|
||||
to mid-term future. It will be kept reasonably up-to-date by the project
|
||||
maintainers. Suggest new ideas, enhancements, and features using the standard
|
||||
[issues](https://github.com/go-kit/kit/issues) model.
|
||||
|
||||
## Prioritized
|
||||
|
||||
1. kitgen code generation (#308, #70)
|
||||
1. package pubsub (#298, #295)
|
||||
|
||||
## Unprioritized
|
||||
|
||||
- package log/levels refactor (#250, #269, #252)
|
||||
- package auth/jwt (#255)
|
||||
|
122
vendor/github.com/go-kit/kit/auth/jwt/README.md
generated
vendored
Normal file
122
vendor/github.com/go-kit/kit/auth/jwt/README.md
generated
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
# 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)(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. `ToHTTPContext()`,
|
||||
`FromHTTPContext()`, `ToGRPCContext()`, and `FromGRPCContext()` 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.FromGRPCContext())).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.ToGRPCContext()))...,
|
||||
),
|
||||
getUser: grpctransport.NewServer(
|
||||
ctx,
|
||||
endpoints.GetUserEndpoint,
|
||||
DecodeGRPCGetUserRequest,
|
||||
EncodeGRPCGetUserResponse,
|
||||
options...,
|
||||
),
|
||||
}
|
||||
}
|
||||
```
|
129
vendor/github.com/go-kit/kit/auth/jwt/middleware.go
generated
vendored
Normal file
129
vendor/github.com/go-kit/kit/auth/jwt/middleware.go
generated
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
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")
|
||||
)
|
||||
|
||||
// Claims is a map of arbitrary claim data.
|
||||
type Claims map[string]interface{}
|
||||
|
||||
// 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 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, jwt.MapClaims(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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NewParser creates a new JWT token parsing middleware, specifying a
|
||||
// jwt.Keyfunc interface and the signing method. 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) 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.Parse(tokenString, 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 && e.Inner != nil {
|
||||
if e.Errors&jwt.ValidationErrorMalformed != 0 {
|
||||
// Token is malformed
|
||||
return nil, ErrTokenMalformed
|
||||
} else if e.Errors&jwt.ValidationErrorExpired != 0 {
|
||||
// Token is expired
|
||||
return nil, ErrTokenExpired
|
||||
} else if e.Errors&jwt.ValidationErrorNotValidYet != 0 {
|
||||
// Token is not active yet
|
||||
return nil, ErrTokenNotActive
|
||||
}
|
||||
|
||||
return nil, e.Inner
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !token.Valid {
|
||||
return nil, ErrTokenInvalid
|
||||
}
|
||||
|
||||
if claims, ok := token.Claims.(jwt.MapClaims); ok {
|
||||
ctx = context.WithValue(ctx, JWTClaimsContextKey, Claims(claims))
|
||||
}
|
||||
|
||||
return next(ctx, request)
|
||||
}
|
||||
}
|
||||
}
|
105
vendor/github.com/go-kit/kit/auth/jwt/middleware_test.go
generated
vendored
Normal file
105
vendor/github.com/go-kit/kit/auth/jwt/middleware_test.go
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
jwt "github.com/dgrijalva/jwt-go"
|
||||
)
|
||||
|
||||
var (
|
||||
kid = "kid"
|
||||
key = []byte("test_signing_key")
|
||||
method = jwt.SigningMethodHS256
|
||||
invalidMethod = jwt.SigningMethodRS256
|
||||
claims = Claims{"user": "go-kit"}
|
||||
// Signed tokens generated at https://jwt.io/
|
||||
signedKey = "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtpZCIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiZ28ta2l0In0.14M2VmYyApdSlV_LZ88ajjwuaLeIFplB8JpyNy0A19E"
|
||||
invalidKey = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.e30.vKVCKto-Wn6rgz3vBdaZaCBGfCBDTXOENSo_X2Gq7qA"
|
||||
)
|
||||
|
||||
func TestSigner(t *testing.T) {
|
||||
e := func(ctx context.Context, i interface{}) (interface{}, error) { return ctx, nil }
|
||||
|
||||
signer := NewSigner(kid, key, method, claims)(e)
|
||||
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 != signedKey {
|
||||
t.Fatalf("JWT tokens did not match: expecting %s got %s", signedKey, token)
|
||||
}
|
||||
}
|
||||
|
||||
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)(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)(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)(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).(Claims)
|
||||
if !ok {
|
||||
t.Fatal("Claims were not passed into context correctly")
|
||||
}
|
||||
|
||||
if cl["user"] != claims["user"] {
|
||||
t.Fatalf("JWT Claims.user did not match: expecting %s got %s", claims["user"], cl["user"])
|
||||
}
|
||||
}
|
89
vendor/github.com/go-kit/kit/auth/jwt/transport.go
generated
vendored
Normal file
89
vendor/github.com/go-kit/kit/auth/jwt/transport.go
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
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"
|
||||
)
|
||||
|
||||
// ToHTTPContext moves JWT token from request header to context. Particularly
|
||||
// useful for servers.
|
||||
func ToHTTPContext() 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)
|
||||
}
|
||||
}
|
||||
|
||||
// FromHTTPContext moves JWT token from context to request header. Particularly
|
||||
// useful for clients.
|
||||
func FromHTTPContext() 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
|
||||
}
|
||||
}
|
||||
|
||||
// ToGRPCContext moves JWT token from grpc metadata to context. Particularly
|
||||
// userful for servers.
|
||||
func ToGRPCContext() 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
|
||||
}
|
||||
}
|
||||
|
||||
// FromGRPCContext moves JWT token from context to grpc metadata. Particularly
|
||||
// useful for clients.
|
||||
func FromGRPCContext() 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.ToLower(authHeaderParts[0]) != bearer {
|
||||
return "", false
|
||||
}
|
||||
|
||||
return authHeaderParts[1], true
|
||||
}
|
||||
|
||||
func generateAuthHeaderFromToken(token string) string {
|
||||
return fmt.Sprintf(bearerFormat, token)
|
||||
}
|
125
vendor/github.com/go-kit/kit/auth/jwt/transport_test.go
generated
vendored
Normal file
125
vendor/github.com/go-kit/kit/auth/jwt/transport_test.go
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
func TestToHTTPContext(t *testing.T) {
|
||||
reqFunc := ToHTTPContext()
|
||||
|
||||
// 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 TestFromHTTPContext(t *testing.T) {
|
||||
reqFunc := FromHTTPContext()
|
||||
|
||||
// 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 TestToGRPCContext(t *testing.T) {
|
||||
md := metadata.MD{}
|
||||
reqFunc := ToGRPCContext()
|
||||
|
||||
// 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 TestFromGRPCContext(t *testing.T) {
|
||||
reqFunc := FromGRPCContext()
|
||||
|
||||
// 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])
|
||||
}
|
||||
}
|
26
vendor/github.com/go-kit/kit/circle.yml
generated
vendored
Normal file
26
vendor/github.com/go-kit/kit/circle.yml
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
machine:
|
||||
pre:
|
||||
- curl -sSL https://s3.amazonaws.com/circle-downloads/install-circleci-docker.sh | bash -s -- 1.10.0
|
||||
- sudo rm -rf /usr/local/go
|
||||
- curl -sSL https://storage.googleapis.com/golang/go1.8.linux-amd64.tar.gz | sudo tar xz -C /usr/local
|
||||
services:
|
||||
- docker
|
||||
|
||||
dependencies:
|
||||
pre:
|
||||
- sudo curl -L "https://github.com/docker/compose/releases/download/1.10.0/docker-compose-linux-x86_64" -o /usr/local/bin/docker-compose
|
||||
- sudo chmod +x /usr/local/bin/docker-compose
|
||||
- docker-compose -f docker-compose-integration.yml up -d --force-recreate
|
||||
|
||||
test:
|
||||
pre:
|
||||
- mkdir -p /home/ubuntu/.go_workspace/src/github.com/go-kit
|
||||
- mv /home/ubuntu/kit /home/ubuntu/.go_workspace/src/github.com/go-kit
|
||||
- ln -s /home/ubuntu/.go_workspace/src/github.com/go-kit/kit /home/ubuntu/kit
|
||||
- go get github.com/go-kit/kit/...
|
||||
override:
|
||||
- go test -v -race -tags integration github.com/go-kit/kit/...:
|
||||
environment:
|
||||
ETCD_ADDR: http://localhost:2379
|
||||
CONSUL_ADDR: localhost:8500
|
||||
ZK_ADDR: localhost:2181
|
10
vendor/github.com/go-kit/kit/circuitbreaker/doc.go
generated
vendored
Normal file
10
vendor/github.com/go-kit/kit/circuitbreaker/doc.go
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
// 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
|
22
vendor/github.com/go-kit/kit/circuitbreaker/gobreaker.go
generated
vendored
Normal file
22
vendor/github.com/go-kit/kit/circuitbreaker/gobreaker.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
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) })
|
||||
}
|
||||
}
|
||||
}
|
19
vendor/github.com/go-kit/kit/circuitbreaker/gobreaker_test.go
generated
vendored
Normal file
19
vendor/github.com/go-kit/kit/circuitbreaker/gobreaker_test.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
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)
|
||||
}
|
38
vendor/github.com/go-kit/kit/circuitbreaker/handy_breaker.go
generated
vendored
Normal file
38
vendor/github.com/go-kit/kit/circuitbreaker/handy_breaker.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
20
vendor/github.com/go-kit/kit/circuitbreaker/handy_breaker_test.go
generated
vendored
Normal file
20
vendor/github.com/go-kit/kit/circuitbreaker/handy_breaker_test.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
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)
|
||||
}
|
31
vendor/github.com/go-kit/kit/circuitbreaker/hystrix.go
generated
vendored
Normal file
31
vendor/github.com/go-kit/kit/circuitbreaker/hystrix.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
40
vendor/github.com/go-kit/kit/circuitbreaker/hystrix_test.go
generated
vendored
Normal file
40
vendor/github.com/go-kit/kit/circuitbreaker/hystrix_test.go
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
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)
|
||||
}
|
75
vendor/github.com/go-kit/kit/circuitbreaker/util_test.go
generated
vendored
Normal file
75
vendor/github.com/go-kit/kit/circuitbreaker/util_test.go
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
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
|
||||
}
|
47
vendor/github.com/go-kit/kit/coverage.bash
generated
vendored
Executable file
47
vendor/github.com/go-kit/kit/coverage.bash
generated
vendored
Executable file
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# This script runs the cover tool on all packages with test files. If you set a
|
||||
# WEB environment variable, it will additionally open the web-based coverage
|
||||
# visualizer for each package.
|
||||
|
||||
set -e
|
||||
|
||||
function go_files { find . -name '*_test.go' ; }
|
||||
function filter { grep -v '/_' ; }
|
||||
function remove_relative_prefix { sed -e 's/^\.\///g' ; }
|
||||
|
||||
function directories {
|
||||
go_files | filter | remove_relative_prefix | while read f
|
||||
do
|
||||
dirname $f
|
||||
done
|
||||
}
|
||||
|
||||
function unique_directories { directories | sort | uniq ; }
|
||||
|
||||
PATHS=${1:-$(unique_directories)}
|
||||
|
||||
function report {
|
||||
for path in $PATHS
|
||||
do
|
||||
go test -coverprofile=$path/cover.coverprofile ./$path
|
||||
done
|
||||
}
|
||||
|
||||
function combine {
|
||||
gover
|
||||
}
|
||||
|
||||
function clean {
|
||||
find . -name cover.coverprofile | xargs rm
|
||||
}
|
||||
|
||||
report
|
||||
combine
|
||||
clean
|
||||
|
||||
if [ -n "${WEB+x}" ]
|
||||
then
|
||||
go tool cover -html=gover.coverprofile
|
||||
fi
|
||||
|
16
vendor/github.com/go-kit/kit/docker-compose-integration.yml
generated
vendored
Normal file
16
vendor/github.com/go-kit/kit/docker-compose-integration.yml
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
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"
|
5
vendor/github.com/go-kit/kit/endpoint/doc.go
generated
vendored
Normal file
5
vendor/github.com/go-kit/kit/endpoint/doc.go
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
// 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
|
28
vendor/github.com/go-kit/kit/endpoint/endpoint.go
generated
vendored
Normal file
28
vendor/github.com/go-kit/kit/endpoint/endpoint.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
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)
|
||||
}
|
||||
}
|
49
vendor/github.com/go-kit/kit/endpoint/endpoint_example_test.go
generated
vendored
Normal file
49
vendor/github.com/go-kit/kit/endpoint/endpoint_example_test.go
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
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
|
||||
}
|
5
vendor/github.com/go-kit/kit/examples/README.md
generated
vendored
Normal file
5
vendor/github.com/go-kit/kit/examples/README.md
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# Examples
|
||||
|
||||
For more information about these examples,
|
||||
including a walkthrough of the stringsvc example,
|
||||
see [gokit.io/examples](https://gokit.io/examples).
|
75
vendor/github.com/go-kit/kit/examples/addsvc/client/grpc/client.go
generated
vendored
Normal file
75
vendor/github.com/go-kit/kit/examples/addsvc/client/grpc/client.go
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
// Package grpc provides a gRPC client for the add service.
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
jujuratelimit "github.com/juju/ratelimit"
|
||||
stdopentracing "github.com/opentracing/opentracing-go"
|
||||
"github.com/sony/gobreaker"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"github.com/go-kit/kit/circuitbreaker"
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/go-kit/kit/examples/addsvc"
|
||||
"github.com/go-kit/kit/examples/addsvc/pb"
|
||||
"github.com/go-kit/kit/log"
|
||||
"github.com/go-kit/kit/ratelimit"
|
||||
"github.com/go-kit/kit/tracing/opentracing"
|
||||
grpctransport "github.com/go-kit/kit/transport/grpc"
|
||||
)
|
||||
|
||||
// New returns an AddService backed by a gRPC client connection. It is the
|
||||
// responsibility of the caller to dial, and later close, the connection.
|
||||
func New(conn *grpc.ClientConn, tracer stdopentracing.Tracer, logger log.Logger) addsvc.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.NewTokenBucketLimiter(jujuratelimit.NewBucketWithRate(100, 100))
|
||||
|
||||
var sumEndpoint endpoint.Endpoint
|
||||
{
|
||||
sumEndpoint = grpctransport.NewClient(
|
||||
conn,
|
||||
"Add",
|
||||
"Sum",
|
||||
addsvc.EncodeGRPCSumRequest,
|
||||
addsvc.DecodeGRPCSumResponse,
|
||||
pb.SumReply{},
|
||||
grpctransport.ClientBefore(opentracing.ToGRPCRequest(tracer, logger)),
|
||||
).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 = grpctransport.NewClient(
|
||||
conn,
|
||||
"Add",
|
||||
"Concat",
|
||||
addsvc.EncodeGRPCConcatRequest,
|
||||
addsvc.DecodeGRPCConcatResponse,
|
||||
pb.ConcatReply{},
|
||||
grpctransport.ClientBefore(opentracing.ToGRPCRequest(tracer, logger)),
|
||||
).Endpoint()
|
||||
concatEndpoint = opentracing.TraceClient(tracer, "Concat")(concatEndpoint)
|
||||
concatEndpoint = limiter(concatEndpoint)
|
||||
concatEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{
|
||||
Name: "Concat",
|
||||
Timeout: 30 * time.Second,
|
||||
}))(concatEndpoint)
|
||||
}
|
||||
|
||||
return addsvc.Endpoints{
|
||||
SumEndpoint: sumEndpoint,
|
||||
ConcatEndpoint: concatEndpoint,
|
||||
}
|
||||
}
|
86
vendor/github.com/go-kit/kit/examples/addsvc/client/http/client.go
generated
vendored
Normal file
86
vendor/github.com/go-kit/kit/examples/addsvc/client/http/client.go
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
// Package http provides an HTTP client for the add service.
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
jujuratelimit "github.com/juju/ratelimit"
|
||||
stdopentracing "github.com/opentracing/opentracing-go"
|
||||
"github.com/sony/gobreaker"
|
||||
|
||||
"github.com/go-kit/kit/circuitbreaker"
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/go-kit/kit/examples/addsvc"
|
||||
"github.com/go-kit/kit/log"
|
||||
"github.com/go-kit/kit/ratelimit"
|
||||
"github.com/go-kit/kit/tracing/opentracing"
|
||||
httptransport "github.com/go-kit/kit/transport/http"
|
||||
)
|
||||
|
||||
// New 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".
|
||||
func New(instance string, tracer stdopentracing.Tracer, logger log.Logger) (addsvc.Service, error) {
|
||||
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.NewTokenBucketLimiter(jujuratelimit.NewBucketWithRate(100, 100))
|
||||
|
||||
var sumEndpoint endpoint.Endpoint
|
||||
{
|
||||
sumEndpoint = httptransport.NewClient(
|
||||
"POST",
|
||||
copyURL(u, "/sum"),
|
||||
addsvc.EncodeHTTPGenericRequest,
|
||||
addsvc.DecodeHTTPSumResponse,
|
||||
httptransport.ClientBefore(opentracing.ToHTTPRequest(tracer, logger)),
|
||||
).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 = httptransport.NewClient(
|
||||
"POST",
|
||||
copyURL(u, "/concat"),
|
||||
addsvc.EncodeHTTPGenericRequest,
|
||||
addsvc.DecodeHTTPConcatResponse,
|
||||
httptransport.ClientBefore(opentracing.ToHTTPRequest(tracer, logger)),
|
||||
).Endpoint()
|
||||
concatEndpoint = opentracing.TraceClient(tracer, "Concat")(concatEndpoint)
|
||||
concatEndpoint = limiter(concatEndpoint)
|
||||
concatEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{
|
||||
Name: "Concat",
|
||||
Timeout: 30 * time.Second,
|
||||
}))(concatEndpoint)
|
||||
}
|
||||
|
||||
return addsvc.Endpoints{
|
||||
SumEndpoint: sumEndpoint,
|
||||
ConcatEndpoint: concatEndpoint,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func copyURL(base *url.URL, path string) *url.URL {
|
||||
next := *base
|
||||
next.Path = path
|
||||
return &next
|
||||
}
|
55
vendor/github.com/go-kit/kit/examples/addsvc/client/thrift/client.go
generated
vendored
Normal file
55
vendor/github.com/go-kit/kit/examples/addsvc/client/thrift/client.go
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
// Package thrift provides a Thrift client for the add service.
|
||||
package thrift
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
jujuratelimit "github.com/juju/ratelimit"
|
||||
"github.com/sony/gobreaker"
|
||||
|
||||
"github.com/go-kit/kit/circuitbreaker"
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/go-kit/kit/examples/addsvc"
|
||||
thriftadd "github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc"
|
||||
"github.com/go-kit/kit/ratelimit"
|
||||
)
|
||||
|
||||
// New 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.
|
||||
func New(client *thriftadd.AddServiceClient) addsvc.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.NewTokenBucketLimiter(jujuratelimit.NewBucketWithRate(100, 100))
|
||||
|
||||
// Thrift does not currently have tracer bindings, so we skip tracing.
|
||||
|
||||
var sumEndpoint endpoint.Endpoint
|
||||
{
|
||||
sumEndpoint = addsvc.MakeThriftSumEndpoint(client)
|
||||
sumEndpoint = limiter(sumEndpoint)
|
||||
sumEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{
|
||||
Name: "Sum",
|
||||
Timeout: 30 * time.Second,
|
||||
}))(sumEndpoint)
|
||||
}
|
||||
|
||||
var concatEndpoint endpoint.Endpoint
|
||||
{
|
||||
concatEndpoint = addsvc.MakeThriftConcatEndpoint(client)
|
||||
concatEndpoint = limiter(concatEndpoint)
|
||||
concatEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{
|
||||
Name: "Concat",
|
||||
Timeout: 30 * time.Second,
|
||||
}))(concatEndpoint)
|
||||
}
|
||||
|
||||
return addsvc.Endpoints{
|
||||
SumEndpoint: sumEndpoint,
|
||||
ConcatEndpoint: concatEndpoint,
|
||||
}
|
||||
}
|
197
vendor/github.com/go-kit/kit/examples/addsvc/cmd/addcli/main.go
generated
vendored
Normal file
197
vendor/github.com/go-kit/kit/examples/addsvc/cmd/addcli/main.go
generated
vendored
Normal file
@@ -0,0 +1,197 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/apache/thrift/lib/go/thrift"
|
||||
"github.com/lightstep/lightstep-tracer-go"
|
||||
stdopentracing "github.com/opentracing/opentracing-go"
|
||||
zipkin "github.com/openzipkin/zipkin-go-opentracing"
|
||||
"google.golang.org/grpc"
|
||||
"sourcegraph.com/sourcegraph/appdash"
|
||||
appdashot "sourcegraph.com/sourcegraph/appdash/opentracing"
|
||||
|
||||
"github.com/go-kit/kit/examples/addsvc"
|
||||
grpcclient "github.com/go-kit/kit/examples/addsvc/client/grpc"
|
||||
httpclient "github.com/go-kit/kit/examples/addsvc/client/http"
|
||||
thriftclient "github.com/go-kit/kit/examples/addsvc/client/thrift"
|
||||
thriftadd "github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc"
|
||||
"github.com/go-kit/kit/log"
|
||||
)
|
||||
|
||||
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 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.
|
||||
|
||||
var (
|
||||
httpAddr = flag.String("http.addr", "", "HTTP address of addsvc")
|
||||
grpcAddr = flag.String("grpc.addr", "", "gRPC (HTTP) address of addsvc")
|
||||
thriftAddr = flag.String("thrift.addr", "", "Thrift address of addsvc")
|
||||
thriftProtocol = flag.String("thrift.protocol", "binary", "binary, compact, json, simplejson")
|
||||
thriftBufferSize = flag.Int("thrift.buffer.size", 0, "0 for unbuffered")
|
||||
thriftFramed = flag.Bool("thrift.framed", false, "true to enable framing")
|
||||
zipkinAddr = flag.String("zipkin.addr", "", "Enable Zipkin tracing via a Zipkin HTTP Collector endpoint")
|
||||
zipkinKafkaAddr = flag.String("zipkin.kafka.addr", "", "Enable Zipkin tracing via a Kafka server host:port")
|
||||
appdashAddr = flag.String("appdash.addr", "", "Enable Appdash tracing via an Appdash server host:port")
|
||||
lightstepToken = flag.String("lightstep.token", "", "Enable LightStep tracing via a LightStep access token")
|
||||
method = flag.String("method", "sum", "sum, concat")
|
||||
)
|
||||
flag.Parse()
|
||||
|
||||
if len(flag.Args()) != 2 {
|
||||
fmt.Fprintf(os.Stderr, "usage: addcli [flags] <a> <b>\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// This is a demonstration client, which supports multiple tracers.
|
||||
// Your clients will probably just use one tracer.
|
||||
var tracer stdopentracing.Tracer
|
||||
{
|
||||
if *zipkinAddr != "" {
|
||||
// endpoint typically looks like: http://zipkinhost:9411/api/v1/spans
|
||||
collector, err := zipkin.NewHTTPCollector(*zipkinAddr)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer collector.Close()
|
||||
|
||||
tracer, err = zipkin.NewTracer(
|
||||
zipkin.NewRecorder(collector, false, "0.0.0.0:0", "addcli"),
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
} else if *zipkinKafkaAddr != "" {
|
||||
collector, err := zipkin.NewKafkaCollector(
|
||||
strings.Split(*zipkinKafkaAddr, ","),
|
||||
zipkin.KafkaLogger(log.NewNopLogger()),
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer collector.Close()
|
||||
|
||||
tracer, err = zipkin.NewTracer(
|
||||
zipkin.NewRecorder(collector, false, "0.0.0.0:0", "addcli"),
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
} else if *appdashAddr != "" {
|
||||
tracer = appdashot.NewTracer(appdash.NewRemoteCollector(*appdashAddr))
|
||||
} else if *lightstepToken != "" {
|
||||
tracer = lightstep.NewTracer(lightstep.Options{
|
||||
AccessToken: *lightstepToken,
|
||||
})
|
||||
defer lightstep.FlushLightStepTracer(tracer)
|
||||
} else {
|
||||
tracer = 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 (
|
||||
service addsvc.Service
|
||||
err error
|
||||
)
|
||||
if *httpAddr != "" {
|
||||
service, err = httpclient.New(*httpAddr, tracer, 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()
|
||||
service = grpcclient.New(conn, tracer, 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 *thriftBufferSize > 0 {
|
||||
transportFactory = thrift.NewTBufferedTransportFactory(*thriftBufferSize)
|
||||
} 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 := transportFactory.GetTransport(transportSocket)
|
||||
if err := transport.Open(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer transport.Close()
|
||||
client := thriftadd.NewAddServiceClientFactory(transport, protocolFactory)
|
||||
service = thriftclient.New(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(flag.Args()[0], 10, 64)
|
||||
b, _ := strconv.ParseInt(flag.Args()[1], 10, 64)
|
||||
v, err := service.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 := flag.Args()[0]
|
||||
b := flag.Args()[1]
|
||||
v, err := service.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)
|
||||
}
|
||||
}
|
279
vendor/github.com/go-kit/kit/examples/addsvc/cmd/addsvc/main.go
generated
vendored
Normal file
279
vendor/github.com/go-kit/kit/examples/addsvc/cmd/addsvc/main.go
generated
vendored
Normal file
@@ -0,0 +1,279 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/pprof"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/apache/thrift/lib/go/thrift"
|
||||
lightstep "github.com/lightstep/lightstep-tracer-go"
|
||||
stdopentracing "github.com/opentracing/opentracing-go"
|
||||
zipkin "github.com/openzipkin/zipkin-go-opentracing"
|
||||
stdprometheus "github.com/prometheus/client_golang/prometheus"
|
||||
"google.golang.org/grpc"
|
||||
"sourcegraph.com/sourcegraph/appdash"
|
||||
appdashot "sourcegraph.com/sourcegraph/appdash/opentracing"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/go-kit/kit/examples/addsvc"
|
||||
"github.com/go-kit/kit/examples/addsvc/pb"
|
||||
thriftadd "github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc"
|
||||
"github.com/go-kit/kit/log"
|
||||
"github.com/go-kit/kit/metrics"
|
||||
"github.com/go-kit/kit/metrics/prometheus"
|
||||
"github.com/go-kit/kit/tracing/opentracing"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var (
|
||||
debugAddr = flag.String("debug.addr", ":8080", "Debug and metrics listen address")
|
||||
httpAddr = flag.String("http.addr", ":8081", "HTTP listen address")
|
||||
grpcAddr = flag.String("grpc.addr", ":8082", "gRPC (HTTP) listen address")
|
||||
thriftAddr = flag.String("thrift.addr", ":8083", "Thrift listen address")
|
||||
thriftProtocol = flag.String("thrift.protocol", "binary", "binary, compact, json, simplejson")
|
||||
thriftBufferSize = flag.Int("thrift.buffer.size", 0, "0 for unbuffered")
|
||||
thriftFramed = flag.Bool("thrift.framed", false, "true to enable framing")
|
||||
zipkinAddr = flag.String("zipkin.addr", "", "Enable Zipkin tracing via a Zipkin HTTP Collector endpoint")
|
||||
zipkinKafkaAddr = flag.String("zipkin.kafka.addr", "", "Enable Zipkin tracing via a Kafka server host:port")
|
||||
appdashAddr = flag.String("appdash.addr", "", "Enable Appdash tracing via an Appdash server host:port")
|
||||
lightstepToken = flag.String("lightstep.token", "", "Enable LightStep tracing via a LightStep access token")
|
||||
)
|
||||
flag.Parse()
|
||||
|
||||
// Logging domain.
|
||||
var logger log.Logger
|
||||
{
|
||||
logger = log.NewLogfmtLogger(os.Stdout)
|
||||
logger = log.With(logger, "ts", log.DefaultTimestampUTC)
|
||||
logger = log.With(logger, "caller", log.DefaultCaller)
|
||||
}
|
||||
logger.Log("msg", "hello")
|
||||
defer logger.Log("msg", "goodbye")
|
||||
|
||||
// Metrics domain.
|
||||
var ints, chars metrics.Counter
|
||||
{
|
||||
// Business level metrics.
|
||||
ints = prometheus.NewCounterFrom(stdprometheus.CounterOpts{
|
||||
Namespace: "addsvc",
|
||||
Name: "integers_summed",
|
||||
Help: "Total count of integers summed via the Sum method.",
|
||||
}, []string{})
|
||||
chars = prometheus.NewCounterFrom(stdprometheus.CounterOpts{
|
||||
Namespace: "addsvc",
|
||||
Name: "characters_concatenated",
|
||||
Help: "Total count of characters concatenated via the Concat method.",
|
||||
}, []string{})
|
||||
}
|
||||
var duration metrics.Histogram
|
||||
{
|
||||
// Transport level metrics.
|
||||
duration = prometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
|
||||
Namespace: "addsvc",
|
||||
Name: "request_duration_ns",
|
||||
Help: "Request duration in nanoseconds.",
|
||||
}, []string{"method", "success"})
|
||||
}
|
||||
|
||||
// Tracing domain.
|
||||
var tracer stdopentracing.Tracer
|
||||
{
|
||||
if *zipkinAddr != "" {
|
||||
logger := log.With(logger, "tracer", "ZipkinHTTP")
|
||||
logger.Log("addr", *zipkinAddr)
|
||||
|
||||
// endpoint typically looks like: http://zipkinhost:9411/api/v1/spans
|
||||
collector, err := zipkin.NewHTTPCollector(*zipkinAddr)
|
||||
if err != nil {
|
||||
logger.Log("err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer collector.Close()
|
||||
|
||||
tracer, err = zipkin.NewTracer(
|
||||
zipkin.NewRecorder(collector, false, "localhost:80", "addsvc"),
|
||||
)
|
||||
if err != nil {
|
||||
logger.Log("err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
} else if *zipkinKafkaAddr != "" {
|
||||
logger := log.With(logger, "tracer", "ZipkinKafka")
|
||||
logger.Log("addr", *zipkinKafkaAddr)
|
||||
|
||||
collector, err := zipkin.NewKafkaCollector(
|
||||
strings.Split(*zipkinKafkaAddr, ","),
|
||||
zipkin.KafkaLogger(log.NewNopLogger()),
|
||||
)
|
||||
if err != nil {
|
||||
logger.Log("err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer collector.Close()
|
||||
|
||||
tracer, err = zipkin.NewTracer(
|
||||
zipkin.NewRecorder(collector, false, "localhost:80", "addsvc"),
|
||||
)
|
||||
if err != nil {
|
||||
logger.Log("err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
} else if *appdashAddr != "" {
|
||||
logger := log.With(logger, "tracer", "Appdash")
|
||||
logger.Log("addr", *appdashAddr)
|
||||
tracer = appdashot.NewTracer(appdash.NewRemoteCollector(*appdashAddr))
|
||||
} else if *lightstepToken != "" {
|
||||
logger := log.With(logger, "tracer", "LightStep")
|
||||
logger.Log() // probably don't want to print out the token :)
|
||||
tracer = lightstep.NewTracer(lightstep.Options{
|
||||
AccessToken: *lightstepToken,
|
||||
})
|
||||
defer lightstep.FlushLightStepTracer(tracer)
|
||||
} else {
|
||||
logger := log.With(logger, "tracer", "none")
|
||||
logger.Log()
|
||||
tracer = stdopentracing.GlobalTracer() // no-op
|
||||
}
|
||||
}
|
||||
|
||||
// Business domain.
|
||||
var service addsvc.Service
|
||||
{
|
||||
service = addsvc.NewBasicService()
|
||||
service = addsvc.ServiceLoggingMiddleware(logger)(service)
|
||||
service = addsvc.ServiceInstrumentingMiddleware(ints, chars)(service)
|
||||
}
|
||||
|
||||
// Endpoint domain.
|
||||
var sumEndpoint endpoint.Endpoint
|
||||
{
|
||||
sumDuration := duration.With("method", "Sum")
|
||||
sumLogger := log.With(logger, "method", "Sum")
|
||||
|
||||
sumEndpoint = addsvc.MakeSumEndpoint(service)
|
||||
sumEndpoint = opentracing.TraceServer(tracer, "Sum")(sumEndpoint)
|
||||
sumEndpoint = addsvc.EndpointInstrumentingMiddleware(sumDuration)(sumEndpoint)
|
||||
sumEndpoint = addsvc.EndpointLoggingMiddleware(sumLogger)(sumEndpoint)
|
||||
}
|
||||
var concatEndpoint endpoint.Endpoint
|
||||
{
|
||||
concatDuration := duration.With("method", "Concat")
|
||||
concatLogger := log.With(logger, "method", "Concat")
|
||||
|
||||
concatEndpoint = addsvc.MakeConcatEndpoint(service)
|
||||
concatEndpoint = opentracing.TraceServer(tracer, "Concat")(concatEndpoint)
|
||||
concatEndpoint = addsvc.EndpointInstrumentingMiddleware(concatDuration)(concatEndpoint)
|
||||
concatEndpoint = addsvc.EndpointLoggingMiddleware(concatLogger)(concatEndpoint)
|
||||
}
|
||||
endpoints := addsvc.Endpoints{
|
||||
SumEndpoint: sumEndpoint,
|
||||
ConcatEndpoint: concatEndpoint,
|
||||
}
|
||||
|
||||
// Mechanical domain.
|
||||
errc := make(chan error)
|
||||
ctx := context.Background()
|
||||
|
||||
// Interrupt handler.
|
||||
go func() {
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
|
||||
errc <- fmt.Errorf("%s", <-c)
|
||||
}()
|
||||
|
||||
// Debug listener.
|
||||
go func() {
|
||||
logger := log.With(logger, "transport", "debug")
|
||||
|
||||
m := http.NewServeMux()
|
||||
m.Handle("/debug/pprof/", http.HandlerFunc(pprof.Index))
|
||||
m.Handle("/debug/pprof/cmdline", http.HandlerFunc(pprof.Cmdline))
|
||||
m.Handle("/debug/pprof/profile", http.HandlerFunc(pprof.Profile))
|
||||
m.Handle("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol))
|
||||
m.Handle("/debug/pprof/trace", http.HandlerFunc(pprof.Trace))
|
||||
m.Handle("/metrics", stdprometheus.Handler())
|
||||
|
||||
logger.Log("addr", *debugAddr)
|
||||
errc <- http.ListenAndServe(*debugAddr, m)
|
||||
}()
|
||||
|
||||
// HTTP transport.
|
||||
go func() {
|
||||
logger := log.With(logger, "transport", "HTTP")
|
||||
h := addsvc.MakeHTTPHandler(endpoints, tracer, logger)
|
||||
logger.Log("addr", *httpAddr)
|
||||
errc <- http.ListenAndServe(*httpAddr, h)
|
||||
}()
|
||||
|
||||
// gRPC transport.
|
||||
go func() {
|
||||
logger := log.With(logger, "transport", "gRPC")
|
||||
|
||||
ln, err := net.Listen("tcp", *grpcAddr)
|
||||
if err != nil {
|
||||
errc <- err
|
||||
return
|
||||
}
|
||||
|
||||
srv := addsvc.MakeGRPCServer(endpoints, tracer, logger)
|
||||
s := grpc.NewServer()
|
||||
pb.RegisterAddServer(s, srv)
|
||||
|
||||
logger.Log("addr", *grpcAddr)
|
||||
errc <- s.Serve(ln)
|
||||
}()
|
||||
|
||||
// Thrift transport.
|
||||
go func() {
|
||||
logger := log.With(logger, "transport", "Thrift")
|
||||
|
||||
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:
|
||||
errc <- fmt.Errorf("invalid Thrift protocol %q", *thriftProtocol)
|
||||
return
|
||||
}
|
||||
|
||||
var transportFactory thrift.TTransportFactory
|
||||
if *thriftBufferSize > 0 {
|
||||
transportFactory = thrift.NewTBufferedTransportFactory(*thriftBufferSize)
|
||||
} else {
|
||||
transportFactory = thrift.NewTTransportFactory()
|
||||
}
|
||||
if *thriftFramed {
|
||||
transportFactory = thrift.NewTFramedTransportFactory(transportFactory)
|
||||
}
|
||||
|
||||
transport, err := thrift.NewTServerSocket(*thriftAddr)
|
||||
if err != nil {
|
||||
errc <- err
|
||||
return
|
||||
}
|
||||
|
||||
logger.Log("addr", *thriftAddr)
|
||||
errc <- thrift.NewTSimpleServer4(
|
||||
thriftadd.NewAddServiceProcessor(addsvc.MakeThriftHandler(ctx, endpoints)),
|
||||
transport,
|
||||
transportFactory,
|
||||
protocolFactory,
|
||||
).Serve()
|
||||
}()
|
||||
|
||||
// Run!
|
||||
logger.Log("exit", <-errc)
|
||||
}
|
5
vendor/github.com/go-kit/kit/examples/addsvc/doc.go
generated
vendored
Normal file
5
vendor/github.com/go-kit/kit/examples/addsvc/doc.go
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
// Package addsvc is an example microservice, useful for education. It can sum
|
||||
// integers and concatenate strings. A client library is available in the client
|
||||
// subdirectory. A server binary is available in cmd/addsrv. An example client
|
||||
// binary is available in cmd/addcli.
|
||||
package addsvc
|
134
vendor/github.com/go-kit/kit/examples/addsvc/endpoints.go
generated
vendored
Normal file
134
vendor/github.com/go-kit/kit/examples/addsvc/endpoints.go
generated
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
package addsvc
|
||||
|
||||
// This file contains methods to make individual endpoints from services,
|
||||
// request and response types to serve those endpoints, as well as encoders and
|
||||
// decoders for those types, for all of our supported transport serialization
|
||||
// formats. It also includes endpoint middlewares.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/go-kit/kit/log"
|
||||
"github.com/go-kit/kit/metrics"
|
||||
)
|
||||
|
||||
// Endpoints 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.
|
||||
//
|
||||
// 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 {
|
||||
SumEndpoint endpoint.Endpoint
|
||||
ConcatEndpoint endpoint.Endpoint
|
||||
}
|
||||
|
||||
// Sum implements Service. Primarily useful in a client.
|
||||
func (e Endpoints) Sum(ctx context.Context, a, b int) (int, error) {
|
||||
request := sumRequest{A: a, B: b}
|
||||
response, err := e.SumEndpoint(ctx, request)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return response.(sumResponse).V, response.(sumResponse).Err
|
||||
}
|
||||
|
||||
// Concat implements Service. Primarily useful in a client.
|
||||
func (e Endpoints) Concat(ctx context.Context, a, b string) (string, error) {
|
||||
request := concatRequest{A: a, B: b}
|
||||
response, err := e.ConcatEndpoint(ctx, request)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return response.(concatResponse).V, response.(concatResponse).Err
|
||||
}
|
||||
|
||||
// MakeSumEndpoint returns an endpoint that invokes Sum on the service.
|
||||
// Primarily useful in a server.
|
||||
func MakeSumEndpoint(s Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
sumReq := request.(sumRequest)
|
||||
v, err := s.Sum(ctx, sumReq.A, sumReq.B)
|
||||
if err == ErrIntOverflow {
|
||||
return nil, err // special case; see comment on ErrIntOverflow
|
||||
}
|
||||
return sumResponse{
|
||||
V: v,
|
||||
Err: err,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// MakeConcatEndpoint returns an endpoint that invokes Concat on the service.
|
||||
// Primarily useful in a server.
|
||||
func MakeConcatEndpoint(s Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
concatReq := request.(concatRequest)
|
||||
v, err := s.Concat(ctx, concatReq.A, concatReq.B)
|
||||
return concatResponse{
|
||||
V: v,
|
||||
Err: err,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// EndpointInstrumentingMiddleware 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 EndpointInstrumentingMiddleware(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)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// EndpointLoggingMiddleware returns an endpoint middleware that logs the
|
||||
// duration of each invocation, and the resulting error, if any.
|
||||
func EndpointLoggingMiddleware(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("error", err, "took", time.Since(begin))
|
||||
}(time.Now())
|
||||
return next(ctx, request)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// These types are unexported because they only exist to serve the endpoint
|
||||
// domain, which is totally encapsulated in this package. They are otherwise
|
||||
// opaque to all callers.
|
||||
|
||||
type sumRequest struct{ A, B int }
|
||||
|
||||
type sumResponse struct {
|
||||
V int
|
||||
Err error
|
||||
}
|
||||
|
||||
type concatRequest struct{ A, B string }
|
||||
|
||||
type concatResponse struct {
|
||||
V string
|
||||
Err error
|
||||
}
|
215
vendor/github.com/go-kit/kit/examples/addsvc/pb/addsvc.pb.go
generated
vendored
Normal file
215
vendor/github.com/go-kit/kit/examples/addsvc/pb/addsvc.pb.go
generated
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
// Code generated by protoc-gen-go.
|
||||
// source: addsvc.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package pb is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
addsvc.proto
|
||||
|
||||
It has these top-level messages:
|
||||
SumRequest
|
||||
SumReply
|
||||
ConcatRequest
|
||||
ConcatReply
|
||||
*/
|
||||
package pb
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// 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.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// The sum request contains two parameters.
|
||||
type SumRequest struct {
|
||||
A int64 `protobuf:"varint,1,opt,name=a" json:"a,omitempty"`
|
||||
B int64 `protobuf:"varint,2,opt,name=b" json:"b,omitempty"`
|
||||
}
|
||||
|
||||
func (m *SumRequest) Reset() { *m = SumRequest{} }
|
||||
func (m *SumRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*SumRequest) ProtoMessage() {}
|
||||
func (*SumRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
// The sum response contains the result of the calculation.
|
||||
type SumReply struct {
|
||||
V int64 `protobuf:"varint,1,opt,name=v" json:"v,omitempty"`
|
||||
Err string `protobuf:"bytes,2,opt,name=err" json:"err,omitempty"`
|
||||
}
|
||||
|
||||
func (m *SumReply) Reset() { *m = SumReply{} }
|
||||
func (m *SumReply) String() string { return proto.CompactTextString(m) }
|
||||
func (*SumReply) ProtoMessage() {}
|
||||
func (*SumReply) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
// The Concat request contains two parameters.
|
||||
type ConcatRequest struct {
|
||||
A string `protobuf:"bytes,1,opt,name=a" json:"a,omitempty"`
|
||||
B string `protobuf:"bytes,2,opt,name=b" json:"b,omitempty"`
|
||||
}
|
||||
|
||||
func (m *ConcatRequest) Reset() { *m = ConcatRequest{} }
|
||||
func (m *ConcatRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ConcatRequest) ProtoMessage() {}
|
||||
func (*ConcatRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
|
||||
|
||||
// The Concat response contains the result of the concatenation.
|
||||
type ConcatReply struct {
|
||||
V string `protobuf:"bytes,1,opt,name=v" json:"v,omitempty"`
|
||||
Err string `protobuf:"bytes,2,opt,name=err" json:"err,omitempty"`
|
||||
}
|
||||
|
||||
func (m *ConcatReply) Reset() { *m = ConcatReply{} }
|
||||
func (m *ConcatReply) String() string { return proto.CompactTextString(m) }
|
||||
func (*ConcatReply) ProtoMessage() {}
|
||||
func (*ConcatReply) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
// Client API for Add service
|
||||
|
||||
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 := grpc.Invoke(ctx, "/pb.Add/Sum", in, out, c.cc, 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 := grpc.Invoke(ctx, "/pb.Add/Concat", in, out, c.cc, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// 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",
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("addsvc.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 189 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 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,
|
||||
}
|
36
vendor/github.com/go-kit/kit/examples/addsvc/pb/addsvc.proto
generated
vendored
Normal file
36
vendor/github.com/go-kit/kit/examples/addsvc/pb/addsvc.proto
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
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;
|
||||
}
|
14
vendor/github.com/go-kit/kit/examples/addsvc/pb/compile.sh
generated
vendored
Executable file
14
vendor/github.com/go-kit/kit/examples/addsvc/pb/compile.sh
generated
vendored
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/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:.
|
163
vendor/github.com/go-kit/kit/examples/addsvc/service.go
generated
vendored
Normal file
163
vendor/github.com/go-kit/kit/examples/addsvc/service.go
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
package addsvc
|
||||
|
||||
// This file contains the Service definition, and a basic service
|
||||
// implementation. It also includes service middlewares.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"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)
|
||||
}
|
||||
|
||||
// Business-domain errors like these may be served in two ways: returned
|
||||
// directly by endpoints, or bundled into the response struct. Both methods can
|
||||
// be made to work, but errors returned directly by endpoints are counted by
|
||||
// middlewares that check errors, like circuit breakers.
|
||||
//
|
||||
// If you don't want that behavior -- and you probably don't -- then it's better
|
||||
// to bundle errors into the response struct.
|
||||
|
||||
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")
|
||||
)
|
||||
|
||||
// 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()
|
||||
}
|
||||
|
||||
// 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 = 102400
|
||||
)
|
||||
|
||||
// Sum implements Service.
|
||||
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
|
||||
}
|
||||
|
||||
// Middleware describes a service (as opposed to endpoint) middleware.
|
||||
type Middleware func(Service) Service
|
||||
|
||||
// ServiceLoggingMiddleware returns a service middleware that logs the
|
||||
// parameters and result of each method invocation.
|
||||
func ServiceLoggingMiddleware(logger log.Logger) Middleware {
|
||||
return func(next Service) Service {
|
||||
return serviceLoggingMiddleware{
|
||||
logger: logger,
|
||||
next: next,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type serviceLoggingMiddleware struct {
|
||||
logger log.Logger
|
||||
next Service
|
||||
}
|
||||
|
||||
func (mw serviceLoggingMiddleware) Sum(ctx context.Context, a, b int) (v int, err error) {
|
||||
defer func(begin time.Time) {
|
||||
mw.logger.Log(
|
||||
"method", "Sum",
|
||||
"a", a, "b", b, "result", v, "error", err,
|
||||
"took", time.Since(begin),
|
||||
)
|
||||
}(time.Now())
|
||||
return mw.next.Sum(ctx, a, b)
|
||||
}
|
||||
|
||||
func (mw serviceLoggingMiddleware) Concat(ctx context.Context, a, b string) (v string, err error) {
|
||||
defer func(begin time.Time) {
|
||||
mw.logger.Log(
|
||||
"method", "Concat",
|
||||
"a", a, "b", b, "result", v, "error", err,
|
||||
"took", time.Since(begin),
|
||||
)
|
||||
}(time.Now())
|
||||
return mw.next.Concat(ctx, a, b)
|
||||
}
|
||||
|
||||
// ServiceInstrumentingMiddleware returns a service middleware that instruments
|
||||
// the number of integers summed and characters concatenated over the lifetime of
|
||||
// the service.
|
||||
func ServiceInstrumentingMiddleware(ints, chars metrics.Counter) Middleware {
|
||||
return func(next Service) Service {
|
||||
return serviceInstrumentingMiddleware{
|
||||
ints: ints,
|
||||
chars: chars,
|
||||
next: next,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type serviceInstrumentingMiddleware struct {
|
||||
ints metrics.Counter
|
||||
chars metrics.Counter
|
||||
next Service
|
||||
}
|
||||
|
||||
func (mw serviceInstrumentingMiddleware) 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 serviceInstrumentingMiddleware) 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
|
||||
}
|
14
vendor/github.com/go-kit/kit/examples/addsvc/thrift/addsvc.thrift
generated
vendored
Normal file
14
vendor/github.com/go-kit/kit/examples/addsvc/thrift/addsvc.thrift
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
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)
|
||||
}
|
5
vendor/github.com/go-kit/kit/examples/addsvc/thrift/compile.sh
generated
vendored
Executable file
5
vendor/github.com/go-kit/kit/examples/addsvc/thrift/compile.sh
generated
vendored
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# See also https://thrift.apache.org/tutorial/go
|
||||
|
||||
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
|
157
vendor/github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc/add_service-remote/add_service-remote.go
generated
vendored
Executable file
157
vendor/github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc/add_service-remote/add_service-remote.go
generated
vendored
Executable file
@@ -0,0 +1,157 @@
|
||||
// Autogenerated by Thrift Compiler (0.9.3)
|
||||
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"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)
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = Usage
|
||||
var host string
|
||||
var port int
|
||||
var protocol string
|
||||
var urlString string
|
||||
var framed bool
|
||||
var useHttp bool
|
||||
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.Parse()
|
||||
|
||||
if len(urlString) > 0 {
|
||||
parsedUrl, err := url.Parse(urlString)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "Error parsing URL: ", err)
|
||||
flag.Usage()
|
||||
}
|
||||
host = parsedUrl.Host
|
||||
useHttp = len(parsedUrl.Scheme) <= 0 || parsedUrl.Scheme == "http"
|
||||
} 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())
|
||||
} 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)
|
||||
}
|
||||
client := addsvc.NewAddServiceClientFactory(trans, protocolFactory)
|
||||
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(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(value0, value1))
|
||||
fmt.Print("\n")
|
||||
break
|
||||
case "":
|
||||
Usage()
|
||||
break
|
||||
default:
|
||||
fmt.Fprintln(os.Stderr, "Invalid function ", cmd)
|
||||
}
|
||||
}
|
807
vendor/github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc/addservice.go
generated
vendored
Normal file
807
vendor/github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc/addservice.go
generated
vendored
Normal file
@@ -0,0 +1,807 @@
|
||||
// Autogenerated by Thrift Compiler (0.9.3)
|
||||
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
|
||||
|
||||
package addsvc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"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 _ = bytes.Equal
|
||||
|
||||
type AddService interface {
|
||||
// Parameters:
|
||||
// - A
|
||||
// - B
|
||||
Sum(a int64, b int64) (r *SumReply, err error)
|
||||
// Parameters:
|
||||
// - A
|
||||
// - B
|
||||
Concat(a string, b string) (r *ConcatReply, err error)
|
||||
}
|
||||
|
||||
type AddServiceClient struct {
|
||||
Transport thrift.TTransport
|
||||
ProtocolFactory thrift.TProtocolFactory
|
||||
InputProtocol thrift.TProtocol
|
||||
OutputProtocol thrift.TProtocol
|
||||
SeqId int32
|
||||
}
|
||||
|
||||
func NewAddServiceClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *AddServiceClient {
|
||||
return &AddServiceClient{Transport: t,
|
||||
ProtocolFactory: f,
|
||||
InputProtocol: f.GetProtocol(t),
|
||||
OutputProtocol: f.GetProtocol(t),
|
||||
SeqId: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func NewAddServiceClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *AddServiceClient {
|
||||
return &AddServiceClient{Transport: t,
|
||||
ProtocolFactory: nil,
|
||||
InputProtocol: iprot,
|
||||
OutputProtocol: oprot,
|
||||
SeqId: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// Parameters:
|
||||
// - A
|
||||
// - B
|
||||
func (p *AddServiceClient) Sum(a int64, b int64) (r *SumReply, err error) {
|
||||
if err = p.sendSum(a, b); err != nil {
|
||||
return
|
||||
}
|
||||
return p.recvSum()
|
||||
}
|
||||
|
||||
func (p *AddServiceClient) sendSum(a int64, b int64) (err error) {
|
||||
oprot := p.OutputProtocol
|
||||
if oprot == nil {
|
||||
oprot = p.ProtocolFactory.GetProtocol(p.Transport)
|
||||
p.OutputProtocol = oprot
|
||||
}
|
||||
p.SeqId++
|
||||
if err = oprot.WriteMessageBegin("Sum", thrift.CALL, p.SeqId); err != nil {
|
||||
return
|
||||
}
|
||||
args := AddServiceSumArgs{
|
||||
A: a,
|
||||
B: b,
|
||||
}
|
||||
if err = args.Write(oprot); err != nil {
|
||||
return
|
||||
}
|
||||
if err = oprot.WriteMessageEnd(); err != nil {
|
||||
return
|
||||
}
|
||||
return oprot.Flush()
|
||||
}
|
||||
|
||||
func (p *AddServiceClient) recvSum() (value *SumReply, err error) {
|
||||
iprot := p.InputProtocol
|
||||
if iprot == nil {
|
||||
iprot = p.ProtocolFactory.GetProtocol(p.Transport)
|
||||
p.InputProtocol = iprot
|
||||
}
|
||||
method, mTypeId, seqId, err := iprot.ReadMessageBegin()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if method != "Sum" {
|
||||
err = thrift.NewTApplicationException(thrift.WRONG_METHOD_NAME, "Sum failed: wrong method name")
|
||||
return
|
||||
}
|
||||
if p.SeqId != seqId {
|
||||
err = thrift.NewTApplicationException(thrift.BAD_SEQUENCE_ID, "Sum failed: out of sequence response")
|
||||
return
|
||||
}
|
||||
if mTypeId == thrift.EXCEPTION {
|
||||
error0 := thrift.NewTApplicationException(thrift.UNKNOWN_APPLICATION_EXCEPTION, "Unknown Exception")
|
||||
var error1 error
|
||||
error1, err = error0.Read(iprot)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err = iprot.ReadMessageEnd(); err != nil {
|
||||
return
|
||||
}
|
||||
err = error1
|
||||
return
|
||||
}
|
||||
if mTypeId != thrift.REPLY {
|
||||
err = thrift.NewTApplicationException(thrift.INVALID_MESSAGE_TYPE_EXCEPTION, "Sum failed: invalid message type")
|
||||
return
|
||||
}
|
||||
result := AddServiceSumResult{}
|
||||
if err = result.Read(iprot); err != nil {
|
||||
return
|
||||
}
|
||||
if err = iprot.ReadMessageEnd(); err != nil {
|
||||
return
|
||||
}
|
||||
value = result.GetSuccess()
|
||||
return
|
||||
}
|
||||
|
||||
// Parameters:
|
||||
// - A
|
||||
// - B
|
||||
func (p *AddServiceClient) Concat(a string, b string) (r *ConcatReply, err error) {
|
||||
if err = p.sendConcat(a, b); err != nil {
|
||||
return
|
||||
}
|
||||
return p.recvConcat()
|
||||
}
|
||||
|
||||
func (p *AddServiceClient) sendConcat(a string, b string) (err error) {
|
||||
oprot := p.OutputProtocol
|
||||
if oprot == nil {
|
||||
oprot = p.ProtocolFactory.GetProtocol(p.Transport)
|
||||
p.OutputProtocol = oprot
|
||||
}
|
||||
p.SeqId++
|
||||
if err = oprot.WriteMessageBegin("Concat", thrift.CALL, p.SeqId); err != nil {
|
||||
return
|
||||
}
|
||||
args := AddServiceConcatArgs{
|
||||
A: a,
|
||||
B: b,
|
||||
}
|
||||
if err = args.Write(oprot); err != nil {
|
||||
return
|
||||
}
|
||||
if err = oprot.WriteMessageEnd(); err != nil {
|
||||
return
|
||||
}
|
||||
return oprot.Flush()
|
||||
}
|
||||
|
||||
func (p *AddServiceClient) recvConcat() (value *ConcatReply, err error) {
|
||||
iprot := p.InputProtocol
|
||||
if iprot == nil {
|
||||
iprot = p.ProtocolFactory.GetProtocol(p.Transport)
|
||||
p.InputProtocol = iprot
|
||||
}
|
||||
method, mTypeId, seqId, err := iprot.ReadMessageBegin()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if method != "Concat" {
|
||||
err = thrift.NewTApplicationException(thrift.WRONG_METHOD_NAME, "Concat failed: wrong method name")
|
||||
return
|
||||
}
|
||||
if p.SeqId != seqId {
|
||||
err = thrift.NewTApplicationException(thrift.BAD_SEQUENCE_ID, "Concat failed: out of sequence response")
|
||||
return
|
||||
}
|
||||
if mTypeId == thrift.EXCEPTION {
|
||||
error2 := thrift.NewTApplicationException(thrift.UNKNOWN_APPLICATION_EXCEPTION, "Unknown Exception")
|
||||
var error3 error
|
||||
error3, err = error2.Read(iprot)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err = iprot.ReadMessageEnd(); err != nil {
|
||||
return
|
||||
}
|
||||
err = error3
|
||||
return
|
||||
}
|
||||
if mTypeId != thrift.REPLY {
|
||||
err = thrift.NewTApplicationException(thrift.INVALID_MESSAGE_TYPE_EXCEPTION, "Concat failed: invalid message type")
|
||||
return
|
||||
}
|
||||
result := AddServiceConcatResult{}
|
||||
if err = result.Read(iprot); err != nil {
|
||||
return
|
||||
}
|
||||
if err = iprot.ReadMessageEnd(); err != nil {
|
||||
return
|
||||
}
|
||||
value = result.GetSuccess()
|
||||
return
|
||||
}
|
||||
|
||||
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(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(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()
|
||||
return false, x5
|
||||
|
||||
}
|
||||
|
||||
type addServiceProcessorSum struct {
|
||||
handler AddService
|
||||
}
|
||||
|
||||
func (p *addServiceProcessorSum) Process(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()
|
||||
return false, err
|
||||
}
|
||||
|
||||
iprot.ReadMessageEnd()
|
||||
result := AddServiceSumResult{}
|
||||
var retval *SumReply
|
||||
var err2 error
|
||||
if retval, err2 = p.handler.Sum(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()
|
||||
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(); err == nil && err2 != nil {
|
||||
err = err2
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return true, err
|
||||
}
|
||||
|
||||
type addServiceProcessorConcat struct {
|
||||
handler AddService
|
||||
}
|
||||
|
||||
func (p *addServiceProcessorConcat) Process(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()
|
||||
return false, err
|
||||
}
|
||||
|
||||
iprot.ReadMessageEnd()
|
||||
result := AddServiceConcatResult{}
|
||||
var retval *ConcatReply
|
||||
var err2 error
|
||||
if retval, err2 = p.handler.Concat(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()
|
||||
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(); 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" json:"a"`
|
||||
B int64 `thrift:"b,2" 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 err := p.readField1(iprot); err != nil {
|
||||
return err
|
||||
}
|
||||
case 2:
|
||||
if err := p.readField2(iprot); 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 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 "<nil>"
|
||||
}
|
||||
return fmt.Sprintf("AddServiceSumArgs(%+v)", *p)
|
||||
}
|
||||
|
||||
// Attributes:
|
||||
// - Success
|
||||
type AddServiceSumResult struct {
|
||||
Success *SumReply `thrift:"success,0" 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 err := p.readField0(iprot); 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 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 "<nil>"
|
||||
}
|
||||
return fmt.Sprintf("AddServiceSumResult(%+v)", *p)
|
||||
}
|
||||
|
||||
// Attributes:
|
||||
// - A
|
||||
// - B
|
||||
type AddServiceConcatArgs struct {
|
||||
A string `thrift:"a,1" json:"a"`
|
||||
B string `thrift:"b,2" 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 err := p.readField1(iprot); err != nil {
|
||||
return err
|
||||
}
|
||||
case 2:
|
||||
if err := p.readField2(iprot); 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 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 "<nil>"
|
||||
}
|
||||
return fmt.Sprintf("AddServiceConcatArgs(%+v)", *p)
|
||||
}
|
||||
|
||||
// Attributes:
|
||||
// - Success
|
||||
type AddServiceConcatResult struct {
|
||||
Success *ConcatReply `thrift:"success,0" 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 err := p.readField0(iprot); 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 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 "<nil>"
|
||||
}
|
||||
return fmt.Sprintf("AddServiceConcatResult(%+v)", *p)
|
||||
}
|
18
vendor/github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc/constants.go
generated
vendored
Normal file
18
vendor/github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc/constants.go
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
// Autogenerated by Thrift Compiler (0.9.3)
|
||||
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
|
||||
|
||||
package addsvc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"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 _ = bytes.Equal
|
||||
|
||||
func init() {
|
||||
}
|
269
vendor/github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc/ttypes.go
generated
vendored
Normal file
269
vendor/github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc/ttypes.go
generated
vendored
Normal file
@@ -0,0 +1,269 @@
|
||||
// Autogenerated by Thrift Compiler (0.9.3)
|
||||
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
|
||||
|
||||
package addsvc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"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 _ = bytes.Equal
|
||||
|
||||
var GoUnusedProtection__ int
|
||||
|
||||
// Attributes:
|
||||
// - Value
|
||||
// - Err
|
||||
type SumReply struct {
|
||||
Value int64 `thrift:"value,1" json:"value"`
|
||||
Err string `thrift:"err,2" 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 err := p.readField1(iprot); err != nil {
|
||||
return err
|
||||
}
|
||||
case 2:
|
||||
if err := p.readField2(iprot); 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 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 "<nil>"
|
||||
}
|
||||
return fmt.Sprintf("SumReply(%+v)", *p)
|
||||
}
|
||||
|
||||
// Attributes:
|
||||
// - Value
|
||||
// - Err
|
||||
type ConcatReply struct {
|
||||
Value string `thrift:"value,1" json:"value"`
|
||||
Err string `thrift:"err,2" 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 err := p.readField1(iprot); err != nil {
|
||||
return err
|
||||
}
|
||||
case 2:
|
||||
if err := p.readField2(iprot); 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 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 "<nil>"
|
||||
}
|
||||
return fmt.Sprintf("ConcatReply(%+v)", *p)
|
||||
}
|
118
vendor/github.com/go-kit/kit/examples/addsvc/transport_grpc.go
generated
vendored
Normal file
118
vendor/github.com/go-kit/kit/examples/addsvc/transport_grpc.go
generated
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
package addsvc
|
||||
|
||||
// This file provides server-side bindings for the gRPC transport.
|
||||
// It utilizes the transport/grpc.Server.
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
stdopentracing "github.com/opentracing/opentracing-go"
|
||||
oldcontext "golang.org/x/net/context"
|
||||
|
||||
"github.com/go-kit/kit/examples/addsvc/pb"
|
||||
"github.com/go-kit/kit/log"
|
||||
"github.com/go-kit/kit/tracing/opentracing"
|
||||
grpctransport "github.com/go-kit/kit/transport/grpc"
|
||||
)
|
||||
|
||||
// MakeGRPCServer makes a set of endpoints available as a gRPC AddServer.
|
||||
func MakeGRPCServer(endpoints Endpoints, tracer stdopentracing.Tracer, logger log.Logger) pb.AddServer {
|
||||
options := []grpctransport.ServerOption{
|
||||
grpctransport.ServerErrorLogger(logger),
|
||||
}
|
||||
return &grpcServer{
|
||||
sum: grpctransport.NewServer(
|
||||
endpoints.SumEndpoint,
|
||||
DecodeGRPCSumRequest,
|
||||
EncodeGRPCSumResponse,
|
||||
append(options, grpctransport.ServerBefore(opentracing.FromGRPCRequest(tracer, "Sum", logger)))...,
|
||||
),
|
||||
concat: grpctransport.NewServer(
|
||||
endpoints.ConcatEndpoint,
|
||||
DecodeGRPCConcatRequest,
|
||||
EncodeGRPCConcatResponse,
|
||||
append(options, grpctransport.ServerBefore(opentracing.FromGRPCRequest(tracer, "Concat", logger)))...,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
type grpcServer struct {
|
||||
sum grpctransport.Handler
|
||||
concat grpctransport.Handler
|
||||
}
|
||||
|
||||
func (s *grpcServer) Sum(ctx oldcontext.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 oldcontext.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
|
||||
}
|
||||
|
||||
// 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 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 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 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 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.(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.(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.(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.(concatRequest)
|
||||
return &pb.ConcatRequest{A: req.A, B: req.B}, nil
|
||||
}
|
130
vendor/github.com/go-kit/kit/examples/addsvc/transport_http.go
generated
vendored
Normal file
130
vendor/github.com/go-kit/kit/examples/addsvc/transport_http.go
generated
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
package addsvc
|
||||
|
||||
// This file provides server-side bindings for the HTTP transport.
|
||||
// It utilizes the transport/http.Server.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
stdopentracing "github.com/opentracing/opentracing-go"
|
||||
|
||||
"github.com/go-kit/kit/log"
|
||||
"github.com/go-kit/kit/tracing/opentracing"
|
||||
httptransport "github.com/go-kit/kit/transport/http"
|
||||
)
|
||||
|
||||
// MakeHTTPHandler returns a handler that makes a set of endpoints available
|
||||
// on predefined paths.
|
||||
func MakeHTTPHandler(endpoints Endpoints, tracer stdopentracing.Tracer, logger log.Logger) http.Handler {
|
||||
options := []httptransport.ServerOption{
|
||||
httptransport.ServerErrorEncoder(errorEncoder),
|
||||
httptransport.ServerErrorLogger(logger),
|
||||
}
|
||||
m := http.NewServeMux()
|
||||
m.Handle("/sum", httptransport.NewServer(
|
||||
endpoints.SumEndpoint,
|
||||
DecodeHTTPSumRequest,
|
||||
EncodeHTTPGenericResponse,
|
||||
append(options, httptransport.ServerBefore(opentracing.FromHTTPRequest(tracer, "Sum", logger)))...,
|
||||
))
|
||||
m.Handle("/concat", httptransport.NewServer(
|
||||
endpoints.ConcatEndpoint,
|
||||
DecodeHTTPConcatRequest,
|
||||
EncodeHTTPGenericResponse,
|
||||
append(options, httptransport.ServerBefore(opentracing.FromHTTPRequest(tracer, "Concat", logger)))...,
|
||||
))
|
||||
return m
|
||||
}
|
||||
|
||||
func errorEncoder(_ context.Context, err error, w http.ResponseWriter) {
|
||||
code := http.StatusInternalServerError
|
||||
msg := err.Error()
|
||||
|
||||
switch err {
|
||||
case ErrTwoZeroes, ErrMaxSizeExceeded, ErrIntOverflow:
|
||||
code = http.StatusBadRequest
|
||||
}
|
||||
|
||||
w.WriteHeader(code)
|
||||
json.NewEncoder(w).Encode(errorWrapper{Error: msg})
|
||||
}
|
||||
|
||||
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 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 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, errorDecoder(r)
|
||||
}
|
||||
var resp 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, errorDecoder(r)
|
||||
}
|
||||
var resp 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(_ context.Context, w http.ResponseWriter, response interface{}) error {
|
||||
return json.NewEncoder(w).Encode(response)
|
||||
}
|
73
vendor/github.com/go-kit/kit/examples/addsvc/transport_thrift.go
generated
vendored
Normal file
73
vendor/github.com/go-kit/kit/examples/addsvc/transport_thrift.go
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
package addsvc
|
||||
|
||||
// This file provides server-side bindings for the Thrift transport.
|
||||
//
|
||||
// This file also provides endpoint constructors that utilize a Thrift client,
|
||||
// for use in client packages, because package transport/thrift doesn't exist
|
||||
// yet. See https://github.com/go-kit/kit/issues/184.
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
thriftadd "github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc"
|
||||
)
|
||||
|
||||
// MakeThriftHandler makes a set of endpoints available as a Thrift service.
|
||||
func MakeThriftHandler(ctx context.Context, e Endpoints) thriftadd.AddService {
|
||||
return &thriftServer{
|
||||
ctx: ctx,
|
||||
sum: e.SumEndpoint,
|
||||
concat: e.ConcatEndpoint,
|
||||
}
|
||||
}
|
||||
|
||||
type thriftServer struct {
|
||||
ctx context.Context
|
||||
sum endpoint.Endpoint
|
||||
concat endpoint.Endpoint
|
||||
}
|
||||
|
||||
func (s *thriftServer) Sum(a int64, b int64) (*thriftadd.SumReply, error) {
|
||||
request := sumRequest{A: int(a), B: int(b)}
|
||||
response, err := s.sum(s.ctx, request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp := response.(sumResponse)
|
||||
return &thriftadd.SumReply{Value: int64(resp.V), Err: err2str(resp.Err)}, nil
|
||||
}
|
||||
|
||||
func (s *thriftServer) Concat(a string, b string) (*thriftadd.ConcatReply, error) {
|
||||
request := concatRequest{A: a, B: b}
|
||||
response, err := s.concat(s.ctx, request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp := response.(concatResponse)
|
||||
return &thriftadd.ConcatReply{Value: resp.V, Err: err2str(resp.Err)}, nil
|
||||
}
|
||||
|
||||
// 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 *thriftadd.AddServiceClient) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(sumRequest)
|
||||
reply, err := client.Sum(int64(req.A), int64(req.B))
|
||||
if err == ErrIntOverflow {
|
||||
return nil, err // special case; see comment on ErrIntOverflow
|
||||
}
|
||||
return 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 *thriftadd.AddServiceClient) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(concatRequest)
|
||||
reply, err := client.Concat(req.A, req.B)
|
||||
return concatResponse{V: reply.Value, Err: err}, nil
|
||||
}
|
||||
}
|
282
vendor/github.com/go-kit/kit/examples/apigateway/main.go
generated
vendored
Normal file
282
vendor/github.com/go-kit/kit/examples/apigateway/main.go
generated
vendored
Normal file
@@ -0,0 +1,282 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/hashicorp/consul/api"
|
||||
stdopentracing "github.com/opentracing/opentracing-go"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/go-kit/kit/examples/addsvc"
|
||||
addsvcgrpcclient "github.com/go-kit/kit/examples/addsvc/client/grpc"
|
||||
"github.com/go-kit/kit/log"
|
||||
"github.com/go-kit/kit/sd"
|
||||
consulsd "github.com/go-kit/kit/sd/consul"
|
||||
"github.com/go-kit/kit/sd/lb"
|
||||
httptransport "github.com/go-kit/kit/transport/http"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
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
|
||||
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 = addsvc.Endpoints{}
|
||||
)
|
||||
{
|
||||
factory := addsvcFactory(addsvc.MakeSumEndpoint, tracer, logger)
|
||||
subscriber := consulsd.NewSubscriber(client, factory, logger, "addsvc", tags, passingOnly)
|
||||
balancer := lb.NewRoundRobin(subscriber)
|
||||
retry := lb.Retry(*retryMax, *retryTimeout, balancer)
|
||||
endpoints.SumEndpoint = retry
|
||||
}
|
||||
{
|
||||
factory := addsvcFactory(addsvc.MakeConcatEndpoint, tracer, logger)
|
||||
subscriber := consulsd.NewSubscriber(client, factory, logger, "addsvc", tags, passingOnly)
|
||||
balancer := lb.NewRoundRobin(subscriber)
|
||||
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", addsvc.MakeHTTPHandler(endpoints, tracer, 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
|
||||
)
|
||||
{
|
||||
factory := stringsvcFactory(ctx, "GET", "/uppercase")
|
||||
subscriber := consulsd.NewSubscriber(client, factory, logger, "stringsvc", tags, passingOnly)
|
||||
balancer := lb.NewRoundRobin(subscriber)
|
||||
retry := lb.Retry(*retryMax, *retryTimeout, balancer)
|
||||
uppercase = retry
|
||||
}
|
||||
{
|
||||
factory := stringsvcFactory(ctx, "GET", "/count")
|
||||
subscriber := consulsd.NewSubscriber(client, factory, logger, "stringsvc", tags, passingOnly)
|
||||
balancer := lb.NewRoundRobin(subscriber)
|
||||
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(addsvc.Service) endpoint.Endpoint, tracer stdopentracing.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 := addsvcgrpcclient.New(conn, tracer, 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
|
||||
}
|
4
vendor/github.com/go-kit/kit/examples/profilesvc/README.md
generated
vendored
Normal file
4
vendor/github.com/go-kit/kit/examples/profilesvc/README.md
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# 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.
|
120
vendor/github.com/go-kit/kit/examples/profilesvc/client/client.go
generated
vendored
Normal file
120
vendor/github.com/go-kit/kit/examples/profilesvc/client/client.go
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
// 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)
|
||||
endpoints profilesvc.Endpoints
|
||||
)
|
||||
{
|
||||
factory := factoryFor(profilesvc.MakePostProfileEndpoint)
|
||||
subscriber := consul.NewSubscriber(sdclient, factory, logger, consulService, consulTags, passingOnly)
|
||||
balancer := lb.NewRoundRobin(subscriber)
|
||||
retry := lb.Retry(retryMax, retryTimeout, balancer)
|
||||
endpoints.PostProfileEndpoint = retry
|
||||
}
|
||||
{
|
||||
factory := factoryFor(profilesvc.MakeGetProfileEndpoint)
|
||||
subscriber := consul.NewSubscriber(sdclient, factory, logger, consulService, consulTags, passingOnly)
|
||||
balancer := lb.NewRoundRobin(subscriber)
|
||||
retry := lb.Retry(retryMax, retryTimeout, balancer)
|
||||
endpoints.GetProfileEndpoint = retry
|
||||
}
|
||||
{
|
||||
factory := factoryFor(profilesvc.MakePutProfileEndpoint)
|
||||
subscriber := consul.NewSubscriber(sdclient, factory, logger, consulService, consulTags, passingOnly)
|
||||
balancer := lb.NewRoundRobin(subscriber)
|
||||
retry := lb.Retry(retryMax, retryTimeout, balancer)
|
||||
endpoints.PutProfileEndpoint = retry
|
||||
}
|
||||
{
|
||||
factory := factoryFor(profilesvc.MakePatchProfileEndpoint)
|
||||
subscriber := consul.NewSubscriber(sdclient, factory, logger, consulService, consulTags, passingOnly)
|
||||
balancer := lb.NewRoundRobin(subscriber)
|
||||
retry := lb.Retry(retryMax, retryTimeout, balancer)
|
||||
endpoints.PatchProfileEndpoint = retry
|
||||
}
|
||||
{
|
||||
factory := factoryFor(profilesvc.MakeDeleteProfileEndpoint)
|
||||
subscriber := consul.NewSubscriber(sdclient, factory, logger, consulService, consulTags, passingOnly)
|
||||
balancer := lb.NewRoundRobin(subscriber)
|
||||
retry := lb.Retry(retryMax, retryTimeout, balancer)
|
||||
endpoints.DeleteProfileEndpoint = retry
|
||||
}
|
||||
{
|
||||
factory := factoryFor(profilesvc.MakeGetAddressesEndpoint)
|
||||
subscriber := consul.NewSubscriber(sdclient, factory, logger, consulService, consulTags, passingOnly)
|
||||
balancer := lb.NewRoundRobin(subscriber)
|
||||
retry := lb.Retry(retryMax, retryTimeout, balancer)
|
||||
endpoints.GetAddressesEndpoint = retry
|
||||
}
|
||||
{
|
||||
factory := factoryFor(profilesvc.MakeGetAddressEndpoint)
|
||||
subscriber := consul.NewSubscriber(sdclient, factory, logger, consulService, consulTags, passingOnly)
|
||||
balancer := lb.NewRoundRobin(subscriber)
|
||||
retry := lb.Retry(retryMax, retryTimeout, balancer)
|
||||
endpoints.GetAddressEndpoint = retry
|
||||
}
|
||||
{
|
||||
factory := factoryFor(profilesvc.MakePostAddressEndpoint)
|
||||
subscriber := consul.NewSubscriber(sdclient, factory, logger, consulService, consulTags, passingOnly)
|
||||
balancer := lb.NewRoundRobin(subscriber)
|
||||
retry := lb.Retry(retryMax, retryTimeout, balancer)
|
||||
endpoints.PostAddressEndpoint = retry
|
||||
}
|
||||
{
|
||||
factory := factoryFor(profilesvc.MakeDeleteAddressEndpoint)
|
||||
subscriber := consul.NewSubscriber(sdclient, factory, logger, consulService, consulTags, passingOnly)
|
||||
balancer := lb.NewRoundRobin(subscriber)
|
||||
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
|
||||
}
|
||||
}
|
52
vendor/github.com/go-kit/kit/examples/profilesvc/cmd/profilesvc/main.go
generated
vendored
Normal file
52
vendor/github.com/go-kit/kit/examples/profilesvc/cmd/profilesvc/main.go
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
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)
|
||||
}
|
387
vendor/github.com/go-kit/kit/examples/profilesvc/endpoints.go
generated
vendored
Normal file
387
vendor/github.com/go-kit/kit/examples/profilesvc/endpoints.go
generated
vendored
Normal file
@@ -0,0 +1,387 @@
|
||||
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 and method. 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 }
|
88
vendor/github.com/go-kit/kit/examples/profilesvc/middlewares.go
generated
vendored
Normal file
88
vendor/github.com/go-kit/kit/examples/profilesvc/middlewares.go
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
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)
|
||||
}
|
185
vendor/github.com/go-kit/kit/examples/profilesvc/service.go
generated
vendored
Normal file
185
vendor/github.com/go-kit/kit/examples/profilesvc/service.go
generated
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
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
|
||||
}
|
400
vendor/github.com/go-kit/kit/examples/profilesvc/transport.go
generated
vendored
Normal file
400
vendor/github.com/go-kit/kit/examples/profilesvc/transport.go
generated
vendored
Normal file
@@ -0,0 +1,400 @@
|
||||
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"
|
||||
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.ServerErrorLogger(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.Method, req.URL.Path = "POST", "/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.Method, req.URL.Path = "GET", "/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.Method, req.URL.Path = "PUT", "/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.Method, req.URL.Path = "PATCH", "/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.Method, req.URL.Path = "DELETE", "/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.Method, req.URL.Path = "GET", "/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.Method, req.URL.Path = "GET", "/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.Method, req.URL.Path = "POST", "/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.Method, req.URL.Path = "DELETE", "/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
|
||||
}
|
||||
}
|
25
vendor/github.com/go-kit/kit/examples/shipping/README.md
generated
vendored
Normal file
25
vendor/github.com/go-kit/kit/examples/shipping/README.md
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# 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.
|
139
vendor/github.com/go-kit/kit/examples/shipping/booking/endpoint.go
generated
vendored
Normal file
139
vendor/github.com/go-kit/kit/examples/shipping/booking/endpoint.go
generated
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
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
|
||||
}
|
||||
}
|
88
vendor/github.com/go-kit/kit/examples/shipping/booking/instrumenting.go
generated
vendored
Normal file
88
vendor/github.com/go-kit/kit/examples/shipping/booking/instrumenting.go
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
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()
|
||||
}
|
102
vendor/github.com/go-kit/kit/examples/shipping/booking/logging.go
generated
vendored
Normal file
102
vendor/github.com/go-kit/kit/examples/shipping/booking/logging.go
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
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()
|
||||
}
|
197
vendor/github.com/go-kit/kit/examples/shipping/booking/service.go
generated
vendored
Normal file
197
vendor/github.com/go-kit/kit/examples/shipping/booking/service.go
generated
vendored
Normal file
@@ -0,0 +1,197 @@
|
||||
// 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,
|
||||
}
|
||||
}
|
194
vendor/github.com/go-kit/kit/examples/shipping/booking/transport.go
generated
vendored
Normal file
194
vendor/github.com/go-kit/kit/examples/shipping/booking/transport.go
generated
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
package booking
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
kitlog "github.com/go-kit/kit/log"
|
||||
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.ServerErrorLogger(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) {
|
||||
switch err {
|
||||
case cargo.ErrUnknown:
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
case ErrInvalidArgument:
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
default:
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
137
vendor/github.com/go-kit/kit/examples/shipping/cargo/cargo.go
generated
vendored
Normal file
137
vendor/github.com/go-kit/kit/examples/shipping/cargo/cargo.go
generated
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
// 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 ""
|
||||
}
|
174
vendor/github.com/go-kit/kit/examples/shipping/cargo/delivery.go
generated
vendored
Normal file
174
vendor/github.com/go-kit/kit/examples/shipping/cargo/delivery.go
generated
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
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()
|
||||
}
|
121
vendor/github.com/go-kit/kit/examples/shipping/cargo/handling.go
generated
vendored
Normal file
121
vendor/github.com/go-kit/kit/examples/shipping/cargo/handling.go
generated
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
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
|
||||
}
|
91
vendor/github.com/go-kit/kit/examples/shipping/cargo/itinerary.go
generated
vendored
Normal file
91
vendor/github.com/go-kit/kit/examples/shipping/cargo/itinerary.go
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
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
|
||||
}
|
34
vendor/github.com/go-kit/kit/examples/shipping/handling/endpoint.go
generated
vendored
Normal file
34
vendor/github.com/go-kit/kit/examples/shipping/handling/endpoint.go
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
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
|
||||
}
|
||||
}
|
37
vendor/github.com/go-kit/kit/examples/shipping/handling/instrumenting.go
generated
vendored
Normal file
37
vendor/github.com/go-kit/kit/examples/shipping/handling/instrumenting.go
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
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)
|
||||
}
|
38
vendor/github.com/go-kit/kit/examples/shipping/handling/logging.go
generated
vendored
Normal file
38
vendor/github.com/go-kit/kit/examples/shipping/handling/logging.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
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)
|
||||
}
|
76
vendor/github.com/go-kit/kit/examples/shipping/handling/service.go
generated
vendored
Normal file
76
vendor/github.com/go-kit/kit/examples/shipping/handling/service.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
// 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,
|
||||
}
|
||||
}
|
100
vendor/github.com/go-kit/kit/examples/shipping/handling/transport.go
generated
vendored
Normal file
100
vendor/github.com/go-kit/kit/examples/shipping/handling/transport.go
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
package handling
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
kitlog "github.com/go-kit/kit/log"
|
||||
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.ServerErrorLogger(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) {
|
||||
switch err {
|
||||
case cargo.ErrUnknown:
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
case ErrInvalidArgument:
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
default:
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
142
vendor/github.com/go-kit/kit/examples/shipping/inmem/inmem.go
generated
vendored
Normal file
142
vendor/github.com/go-kit/kit/examples/shipping/inmem/inmem.go
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
// 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),
|
||||
}
|
||||
}
|
53
vendor/github.com/go-kit/kit/examples/shipping/inspection/inspection.go
generated
vendored
Normal file
53
vendor/github.com/go-kit/kit/examples/shipping/inspection/inspection.go
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
// 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}
|
||||
}
|
29
vendor/github.com/go-kit/kit/examples/shipping/location/location.go
generated
vendored
Normal file
29
vendor/github.com/go-kit/kit/examples/shipping/location/location.go
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
// 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
|
||||
}
|
27
vendor/github.com/go-kit/kit/examples/shipping/location/sample_locations.go
generated
vendored
Normal file
27
vendor/github.com/go-kit/kit/examples/shipping/location/sample_locations.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
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"}
|
||||
)
|
212
vendor/github.com/go-kit/kit/examples/shipping/main.go
generated
vendored
Normal file
212
vendor/github.com/go-kit/kit/examples/shipping/main.go
generated
vendored
Normal file
@@ -0,0 +1,212 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
stdprometheus "github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
"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(os.Stderr)
|
||||
logger = &serializedLogger{Logger: logger}
|
||||
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", stdprometheus.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)
|
||||
}
|
||||
}
|
||||
|
||||
type serializedLogger struct {
|
||||
mtx sync.Mutex
|
||||
log.Logger
|
||||
}
|
||||
|
||||
func (l *serializedLogger) Log(keyvals ...interface{}) error {
|
||||
l.mtx.Lock()
|
||||
defer l.mtx.Unlock()
|
||||
return l.Logger.Log(keyvals...)
|
||||
}
|
117
vendor/github.com/go-kit/kit/examples/shipping/routing/proxying.go
generated
vendored
Normal file
117
vendor/github.com/go-kit/kit/examples/shipping/routing/proxying.go
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
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
|
||||
}
|
15
vendor/github.com/go-kit/kit/examples/shipping/routing/routing.go
generated
vendored
Normal file
15
vendor/github.com/go-kit/kit/examples/shipping/routing/routing.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// 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
|
||||
}
|
26
vendor/github.com/go-kit/kit/examples/shipping/tracking/endpoint.go
generated
vendored
Normal file
26
vendor/github.com/go-kit/kit/examples/shipping/tracking/endpoint.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
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
|
||||
}
|
||||
}
|
31
vendor/github.com/go-kit/kit/examples/shipping/tracking/instrumenting.go
generated
vendored
Normal file
31
vendor/github.com/go-kit/kit/examples/shipping/tracking/instrumenting.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
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)
|
||||
}
|
24
vendor/github.com/go-kit/kit/examples/shipping/tracking/logging.go
generated
vendored
Normal file
24
vendor/github.com/go-kit/kit/examples/shipping/tracking/logging.go
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
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)
|
||||
}
|
163
vendor/github.com/go-kit/kit/examples/shipping/tracking/service.go
generated
vendored
Normal file
163
vendor/github.com/go-kit/kit/examples/shipping/tracking/service.go
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
// 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
|
||||
}
|
74
vendor/github.com/go-kit/kit/examples/shipping/tracking/transport.go
generated
vendored
Normal file
74
vendor/github.com/go-kit/kit/examples/shipping/tracking/transport.go
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
package tracking
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
kitlog "github.com/go-kit/kit/log"
|
||||
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.ServerErrorLogger(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) {
|
||||
switch err {
|
||||
case cargo.ErrUnknown:
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
case ErrInvalidArgument:
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
default:
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
40
vendor/github.com/go-kit/kit/examples/shipping/voyage/sample_voyages.go
generated
vendored
Normal file
40
vendor/github.com/go-kit/kit/examples/shipping/voyage/sample_voyages.go
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
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{}})
|
||||
)
|
44
vendor/github.com/go-kit/kit/examples/shipping/voyage/voyage.go
generated
vendored
Normal file
44
vendor/github.com/go-kit/kit/examples/shipping/voyage/voyage.go
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
// 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)
|
||||
}
|
111
vendor/github.com/go-kit/kit/examples/stringsvc1/main.go
generated
vendored
Normal file
111
vendor/github.com/go-kit/kit/examples/stringsvc1/main.go
generated
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
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
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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 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 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"` // errors don't define JSON marshaling
|
||||
}
|
||||
|
||||
type countRequest struct {
|
||||
S string `json:"s"`
|
||||
}
|
||||
|
||||
type countResponse struct {
|
||||
V int `json:"v"`
|
||||
}
|
||||
|
||||
// ErrEmpty is returned when an input string is empty.
|
||||
var ErrEmpty = errors.New("empty string")
|
38
vendor/github.com/go-kit/kit/examples/stringsvc2/instrumenting.go
generated
vendored
Normal file
38
vendor/github.com/go-kit/kit/examples/stringsvc2/instrumenting.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
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
|
||||
}
|
41
vendor/github.com/go-kit/kit/examples/stringsvc2/logging.go
generated
vendored
Normal file
41
vendor/github.com/go-kit/kit/examples/stringsvc2/logging.go
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
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
|
||||
}
|
59
vendor/github.com/go-kit/kit/examples/stringsvc2/main.go
generated
vendored
Normal file
59
vendor/github.com/go-kit/kit/examples/stringsvc2/main.go
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
stdprometheus "github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
"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", stdprometheus.Handler())
|
||||
logger.Log("msg", "HTTP", "addr", ":8080")
|
||||
logger.Log("err", http.ListenAndServe(":8080", nil))
|
||||
}
|
28
vendor/github.com/go-kit/kit/examples/stringsvc2/service.go
generated
vendored
Normal file
28
vendor/github.com/go-kit/kit/examples/stringsvc2/service.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
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")
|
65
vendor/github.com/go-kit/kit/examples/stringsvc2/transport.go
generated
vendored
Normal file
65
vendor/github.com/go-kit/kit/examples/stringsvc2/transport.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"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 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"`
|
||||
}
|
48
vendor/github.com/go-kit/kit/examples/stringsvc3/instrumenting.go
generated
vendored
Normal file
48
vendor/github.com/go-kit/kit/examples/stringsvc3/instrumenting.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
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
|
||||
}
|
47
vendor/github.com/go-kit/kit/examples/stringsvc3/logging.go
generated
vendored
Normal file
47
vendor/github.com/go-kit/kit/examples/stringsvc3/logging.go
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
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
|
||||
}
|
69
vendor/github.com/go-kit/kit/examples/stringsvc3/main.go
generated
vendored
Normal file
69
vendor/github.com/go-kit/kit/examples/stringsvc3/main.go
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
stdprometheus "github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
"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", stdprometheus.Handler())
|
||||
logger.Log("msg", "HTTP", "addr", *listen)
|
||||
logger.Log("err", http.ListenAndServe(*listen, nil))
|
||||
}
|
116
vendor/github.com/go-kit/kit/examples/stringsvc3/proxying.go
generated
vendored
Normal file
116
vendor/github.com/go-kit/kit/examples/stringsvc3/proxying.go
generated
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
jujuratelimit "github.com/juju/ratelimit"
|
||||
"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)
|
||||
subscriber sd.FixedSubscriber
|
||||
)
|
||||
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.NewTokenBucketLimiter(jujuratelimit.NewBucketWithRate(float64(qps), int64(qps)))(e)
|
||||
subscriber = append(subscriber, e)
|
||||
}
|
||||
|
||||
// Now, build a single, retrying, load-balancing endpoint out of all of
|
||||
// those individual endpoints.
|
||||
balancer := lb.NewRoundRobin(subscriber)
|
||||
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
|
||||
}
|
31
vendor/github.com/go-kit/kit/examples/stringsvc3/service.go
generated
vendored
Normal file
31
vendor/github.com/go-kit/kit/examples/stringsvc3/service.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
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
|
84
vendor/github.com/go-kit/kit/examples/stringsvc3/transport.go
generated
vendored
Normal file
84
vendor/github.com/go-kit/kit/examples/stringsvc3/transport.go
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
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"`
|
||||
}
|
26
vendor/github.com/go-kit/kit/lint
generated
vendored
Executable file
26
vendor/github.com/go-kit/kit/lint
generated
vendored
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/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 \
|
||||
./...
|
147
vendor/github.com/go-kit/kit/log/README.md
generated
vendored
Normal file
147
vendor/github.com/go-kit/kit/log/README.md
generated
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
# 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
|
||||
```
|
||||
|
||||
## 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
|
21
vendor/github.com/go-kit/kit/log/benchmark_test.go
generated
vendored
Normal file
21
vendor/github.com/go-kit/kit/log/benchmark_test.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
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") }
|
||||
)
|
40
vendor/github.com/go-kit/kit/log/concurrency_test.go
generated
vendored
Normal file
40
vendor/github.com/go-kit/kit/log/concurrency_test.go
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
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
|
||||
}
|
127
vendor/github.com/go-kit/kit/log/deprecated_levels/levels.go
generated
vendored
Normal file
127
vendor/github.com/go-kit/kit/log/deprecated_levels/levels.go
generated
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
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 }
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user