diff --git a/examples/addsvc/client/client.go b/examples/addsvc/client/client.go deleted file mode 100644 index 7eb2968..0000000 --- a/examples/addsvc/client/client.go +++ /dev/null @@ -1,71 +0,0 @@ -package main - -import ( - "golang.org/x/net/context" - - "github.com/go-kit/kit/endpoint" - "github.com/go-kit/kit/examples/addsvc/server" - "github.com/go-kit/kit/log" -) - -// NewClient returns an AddService that's backed by the provided Endpoints -func newClient(ctx context.Context, sumEndpoint endpoint.Endpoint, concatEndpoint endpoint.Endpoint, logger log.Logger) server.AddService { - return client{ - Context: ctx, - Logger: logger, - sum: sumEndpoint, - concat: concatEndpoint, - } -} - -type client struct { - context.Context - log.Logger - sum endpoint.Endpoint - concat endpoint.Endpoint -} - -// TODO(pb): If your service interface methods don't return an error, we have -// no way to signal problems with a service client. If they don't take a -// context, we have to provide a global context for any transport that -// requires one, effectively making your service a black box to any context- -// specific information. So, we should make some recommendations: -// -// - To get started, a simple service interface is probably fine. -// -// - To properly deal with transport errors, every method on your service -// should return an error. This is probably important. -// -// - To properly deal with context information, every method on your service -// can take a context as its first argument. This may or may not be -// important. - -func (c client) Sum(a, b int) int { - request := server.SumRequest{ - A: a, - B: b, - } - reply, err := c.sum(c.Context, request) - if err != nil { - c.Logger.Log("err", err) // Without an error return parameter, we can't do anything else... - return 0 - } - - r := reply.(server.SumResponse) - return r.V -} - -func (c client) Concat(a, b string) string { - request := server.ConcatRequest{ - A: a, - B: b, - } - reply, err := c.concat(c.Context, request) - if err != nil { - c.Logger.Log("err", err) // Without an error return parameter, we can't do anything else... - return "" - } - - r := reply.(server.ConcatResponse) - return r.V -} diff --git a/examples/addsvc/client/grpc/client.go b/examples/addsvc/client/grpc/client.go new file mode 100644 index 0000000..e72bbe4 --- /dev/null +++ b/examples/addsvc/client/grpc/client.go @@ -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.SetClientBefore(opentracing.FromGRPCRequest(tracer, "Sum", 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.SetClientBefore(opentracing.FromGRPCRequest(tracer, "Concat", logger)), + ).Endpoint() + concatEndpoint = opentracing.TraceClient(tracer, "Concat")(concatEndpoint) + concatEndpoint = limiter(concatEndpoint) + sumEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{ + Name: "Concat", + Timeout: 30 * time.Second, + }))(sumEndpoint) + } + + return addsvc.Endpoints{ + SumEndpoint: sumEndpoint, + ConcatEndpoint: concatEndpoint, + } +} diff --git a/examples/addsvc/client/grpc/encode_decode.go b/examples/addsvc/client/grpc/encode_decode.go deleted file mode 100644 index 23e081d..0000000 --- a/examples/addsvc/client/grpc/encode_decode.go +++ /dev/null @@ -1,38 +0,0 @@ -package grpc - -import ( - "golang.org/x/net/context" - - "github.com/go-kit/kit/examples/addsvc/pb" - "github.com/go-kit/kit/examples/addsvc/server" -) - -func encodeSumRequest(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(server.SumRequest) - return &pb.SumRequest{ - A: int64(req.A), - B: int64(req.B), - }, nil -} - -func encodeConcatRequest(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(server.ConcatRequest) - return &pb.ConcatRequest{ - A: req.A, - B: req.B, - }, nil -} - -func decodeSumResponse(ctx context.Context, response interface{}) (interface{}, error) { - resp := response.(*pb.SumReply) - return server.SumResponse{ - V: int(resp.V), - }, nil -} - -func decodeConcatResponse(ctx context.Context, response interface{}) (interface{}, error) { - resp := response.(*pb.ConcatReply) - return server.ConcatResponse{ - V: resp.V, - }, nil -} diff --git a/examples/addsvc/client/grpc/factory.go b/examples/addsvc/client/grpc/factory.go deleted file mode 100644 index 0e59932..0000000 --- a/examples/addsvc/client/grpc/factory.go +++ /dev/null @@ -1,51 +0,0 @@ -package grpc - -import ( - "io" - - kitot "github.com/go-kit/kit/tracing/opentracing" - "github.com/opentracing/opentracing-go" - "google.golang.org/grpc" - - "github.com/go-kit/kit/endpoint" - "github.com/go-kit/kit/examples/addsvc/pb" - "github.com/go-kit/kit/loadbalancer" - "github.com/go-kit/kit/log" - grpctransport "github.com/go-kit/kit/transport/grpc" -) - -// MakeSumEndpointFactory returns a loadbalancer.Factory that transforms GRPC -// host:port strings into Endpoints that call the Sum method on a GRPC server -// at that address. -func MakeSumEndpointFactory(tracer opentracing.Tracer, tracingLogger log.Logger) loadbalancer.Factory { - return func(instance string) (endpoint.Endpoint, io.Closer, error) { - cc, err := grpc.Dial(instance, grpc.WithInsecure()) - return grpctransport.NewClient( - cc, - "Add", - "Sum", - encodeSumRequest, - decodeSumResponse, - pb.SumReply{}, - grpctransport.SetClientBefore(kitot.ToGRPCRequest(tracer, tracingLogger)), - ).Endpoint(), cc, err - } -} - -// MakeConcatEndpointFactory returns a loadbalancer.Factory that transforms -// GRPC host:port strings into Endpoints that call the Concat method on a GRPC -// server at that address. -func MakeConcatEndpointFactory(tracer opentracing.Tracer, tracingLogger log.Logger) loadbalancer.Factory { - return func(instance string) (endpoint.Endpoint, io.Closer, error) { - cc, err := grpc.Dial(instance, grpc.WithInsecure()) - return grpctransport.NewClient( - cc, - "Add", - "Concat", - encodeConcatRequest, - decodeConcatResponse, - pb.ConcatReply{}, - grpctransport.SetClientBefore(kitot.ToGRPCRequest(tracer, tracingLogger)), - ).Endpoint(), cc, err - } -} diff --git a/examples/addsvc/client/http/client.go b/examples/addsvc/client/http/client.go new file mode 100644 index 0000000..c597c98 --- /dev/null +++ b/examples/addsvc/client/http/client.go @@ -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.SetClientBefore(opentracing.FromHTTPRequest(tracer, "Sum", 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.SetClientBefore(opentracing.FromHTTPRequest(tracer, "Concat", logger)), + ).Endpoint() + concatEndpoint = opentracing.TraceClient(tracer, "Concat")(concatEndpoint) + concatEndpoint = limiter(concatEndpoint) + sumEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{ + Name: "Concat", + Timeout: 30 * time.Second, + }))(sumEndpoint) + } + + return addsvc.Endpoints{ + SumEndpoint: sumEndpoint, + ConcatEndpoint: concatEndpoint, + }, nil +} + +func copyURL(base *url.URL, path string) *url.URL { + next := *base + next.Path = path + return &next +} diff --git a/examples/addsvc/client/httpjson/factory.go b/examples/addsvc/client/httpjson/factory.go deleted file mode 100644 index f36ce4e..0000000 --- a/examples/addsvc/client/httpjson/factory.go +++ /dev/null @@ -1,65 +0,0 @@ -package httpjson - -import ( - "io" - "net/url" - - "github.com/opentracing/opentracing-go" - - "github.com/go-kit/kit/endpoint" - "github.com/go-kit/kit/examples/addsvc/server" - "github.com/go-kit/kit/loadbalancer" - "github.com/go-kit/kit/log" - kitot "github.com/go-kit/kit/tracing/opentracing" - httptransport "github.com/go-kit/kit/transport/http" -) - -// MakeSumEndpointFactory generates a Factory that transforms an http url into -// an Endpoint. -// -// The path of the url is reset to /sum. -func MakeSumEndpointFactory(tracer opentracing.Tracer, tracingLogger log.Logger) loadbalancer.Factory { - return func(instance string) (endpoint.Endpoint, io.Closer, error) { - sumURL, err := url.Parse(instance) - if err != nil { - return nil, nil, err - } - sumURL.Path = "/sum" - - client := httptransport.NewClient( - "GET", - sumURL, - server.EncodeSumRequest, - server.DecodeSumResponse, - httptransport.SetClient(nil), - httptransport.SetClientBefore(kitot.ToHTTPRequest(tracer, tracingLogger)), - ) - - return client.Endpoint(), nil, nil - } -} - -// MakeConcatEndpointFactory generates a Factory that transforms an http url -// into an Endpoint. -// -// The path of the url is reset to /concat. -func MakeConcatEndpointFactory(tracer opentracing.Tracer, tracingLogger log.Logger) loadbalancer.Factory { - return func(instance string) (endpoint.Endpoint, io.Closer, error) { - concatURL, err := url.Parse(instance) - if err != nil { - return nil, nil, err - } - concatURL.Path = "/concat" - - client := httptransport.NewClient( - "GET", - concatURL, - server.EncodeConcatRequest, - server.DecodeConcatResponse, - httptransport.SetClient(nil), - httptransport.SetClientBefore(kitot.ToHTTPRequest(tracer, tracingLogger)), - ) - - return client.Endpoint(), nil, nil - } -} diff --git a/examples/addsvc/client/main.go b/examples/addsvc/client/main.go deleted file mode 100644 index 8e01409..0000000 --- a/examples/addsvc/client/main.go +++ /dev/null @@ -1,167 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "os" - "path/filepath" - "strconv" - "strings" - "time" - - "github.com/lightstep/lightstep-tracer-go" - "github.com/opentracing/opentracing-go" - zipkin "github.com/openzipkin/zipkin-go-opentracing" - appdashot "github.com/sourcegraph/appdash/opentracing" - "golang.org/x/net/context" - "sourcegraph.com/sourcegraph/appdash" - - "github.com/go-kit/kit/endpoint" - grpcclient "github.com/go-kit/kit/examples/addsvc/client/grpc" - httpjsonclient "github.com/go-kit/kit/examples/addsvc/client/httpjson" - netrpcclient "github.com/go-kit/kit/examples/addsvc/client/netrpc" - thriftclient "github.com/go-kit/kit/examples/addsvc/client/thrift" - "github.com/go-kit/kit/loadbalancer" - "github.com/go-kit/kit/loadbalancer/static" - "github.com/go-kit/kit/log" - kitot "github.com/go-kit/kit/tracing/opentracing" -) - -func main() { - var ( - transport = flag.String("transport", "httpjson", "httpjson, grpc, netrpc, thrift") - httpAddrs = flag.String("http.addrs", "localhost:8001", "Comma-separated list of addresses for HTTP (JSON) servers") - grpcAddrs = flag.String("grpc.addrs", "localhost:8002", "Comma-separated list of addresses for gRPC servers") - netrpcAddrs = flag.String("netrpc.addrs", "localhost:8003", "Comma-separated list of addresses for net/rpc servers") - thriftAddrs = flag.String("thrift.addrs", "localhost:8004", "Comma-separated list of addresses for Thrift servers") - 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") - - // Three OpenTracing backends (to demonstrate how they can be interchanged): - zipkinAddr = flag.String("zipkin.kafka.addr", "", "Enable Zipkin tracing via a Kafka Collector host:port") - appdashAddr = flag.String("appdash.addr", "", "Enable Appdash tracing via an Appdash server host:port") - lightstepAccessToken = flag.String("lightstep.token", "", "Enable LightStep tracing via a LightStep access token") - ) - flag.Parse() - if len(os.Args) < 4 { - fmt.Fprintf(os.Stderr, "\n%s [flags] method arg1 arg2\n\n", filepath.Base(os.Args[0])) - flag.Usage() - os.Exit(1) - } - - randomSeed := time.Now().UnixNano() - - root := context.Background() - method, s1, s2 := flag.Arg(0), flag.Arg(1), flag.Arg(2) - - var logger log.Logger - logger = log.NewLogfmtLogger(os.Stdout) - logger = log.NewContext(logger).With("caller", log.DefaultCaller) - logger = log.NewContext(logger).With("transport", *transport) - tracingLogger := log.NewContext(logger).With("component", "tracing") - - // Set up OpenTracing - var tracer opentracing.Tracer - { - switch { - case *appdashAddr != "" && *lightstepAccessToken == "" && *zipkinAddr == "": - tracer = appdashot.NewTracer(appdash.NewRemoteCollector(*appdashAddr)) - case *appdashAddr == "" && *lightstepAccessToken != "" && *zipkinAddr == "": - tracer = lightstep.NewTracer(lightstep.Options{ - AccessToken: *lightstepAccessToken, - }) - defer lightstep.FlushLightStepTracer(tracer) - case *appdashAddr == "" && *lightstepAccessToken == "" && *zipkinAddr != "": - collector, err := zipkin.NewKafkaCollector( - strings.Split(*zipkinAddr, ","), - zipkin.KafkaLogger(tracingLogger), - ) - if err != nil { - tracingLogger.Log("err", "unable to create kafka collector", "fatal", err) - os.Exit(1) - } - tracer, err = zipkin.NewTracer( - zipkin.NewRecorder(collector, false, "localhost:8000", "addsvc-client"), - ) - if err != nil { - tracingLogger.Log("err", "unable to create zipkin tracer", "fatal", err) - os.Exit(1) - } - case *appdashAddr == "" && *lightstepAccessToken == "" && *zipkinAddr == "": - tracer = opentracing.GlobalTracer() // no-op - default: - tracingLogger.Log("fatal", "specify a single -appdash.addr, -lightstep.access.token or -zipkin.kafka.addr") - os.Exit(1) - } - } - - var ( - instances []string - sumFactory, concatFactory loadbalancer.Factory - ) - - switch *transport { - case "grpc": - instances = strings.Split(*grpcAddrs, ",") - sumFactory = grpcclient.MakeSumEndpointFactory(tracer, tracingLogger) - concatFactory = grpcclient.MakeConcatEndpointFactory(tracer, tracingLogger) - - case "httpjson": - instances = strings.Split(*httpAddrs, ",") - for i, rawurl := range instances { - if !strings.HasPrefix("http", rawurl) { - instances[i] = "http://" + rawurl - } - } - sumFactory = httpjsonclient.MakeSumEndpointFactory(tracer, tracingLogger) - concatFactory = httpjsonclient.MakeConcatEndpointFactory(tracer, tracingLogger) - - case "netrpc": - instances = strings.Split(*netrpcAddrs, ",") - sumFactory = netrpcclient.SumEndpointFactory - concatFactory = netrpcclient.ConcatEndpointFactory - - case "thrift": - instances = strings.Split(*thriftAddrs, ",") - thriftClient := thriftclient.New(*thriftProtocol, *thriftBufferSize, *thriftFramed, logger) - sumFactory = thriftClient.SumEndpoint - concatFactory = thriftClient.ConcatEndpoint - - default: - logger.Log("err", "invalid transport") - os.Exit(1) - } - - sum := buildEndpoint(tracer, "sum", instances, sumFactory, randomSeed, logger) - concat := buildEndpoint(tracer, "concat", instances, concatFactory, randomSeed, logger) - - svc := newClient(root, sum, concat, logger) - - begin := time.Now() - switch method { - case "sum": - a, _ := strconv.Atoi(s1) - b, _ := strconv.Atoi(s2) - v := svc.Sum(a, b) - logger.Log("method", "sum", "a", a, "b", b, "v", v, "took", time.Since(begin)) - - case "concat": - a, b := s1, s2 - v := svc.Concat(a, b) - logger.Log("method", "concat", "a", a, "b", b, "v", v, "took", time.Since(begin)) - - default: - logger.Log("err", "invalid method "+method) - os.Exit(1) - } - // wait for collector - time.Sleep(2 * time.Second) -} - -func buildEndpoint(tracer opentracing.Tracer, operationName string, instances []string, factory loadbalancer.Factory, seed int64, logger log.Logger) endpoint.Endpoint { - publisher := static.NewPublisher(instances, factory, logger) - random := loadbalancer.NewRandom(publisher, seed) - endpoint := loadbalancer.Retry(10, 10*time.Second, random) - return kitot.TraceClient(tracer, operationName)(endpoint) -} diff --git a/examples/addsvc/client/netrpc/factory.go b/examples/addsvc/client/netrpc/factory.go deleted file mode 100644 index 9f9a875..0000000 --- a/examples/addsvc/client/netrpc/factory.go +++ /dev/null @@ -1,43 +0,0 @@ -package netrpc - -import ( - "io" - "net/rpc" - - "golang.org/x/net/context" - - "github.com/go-kit/kit/endpoint" - "github.com/go-kit/kit/examples/addsvc/server" -) - -// SumEndpointFactory transforms host:port strings into Endpoints. -func SumEndpointFactory(instance string) (endpoint.Endpoint, io.Closer, error) { - client, err := rpc.DialHTTP("tcp", instance) - if err != nil { - return nil, nil, err - } - - return func(ctx context.Context, request interface{}) (interface{}, error) { - var reply server.SumResponse - if err := client.Call("addsvc.Sum", request.(server.SumRequest), &reply); err != nil { - return server.SumResponse{}, err - } - return reply, nil - }, client, nil -} - -// ConcatEndpointFactory transforms host:port strings into Endpoints. -func ConcatEndpointFactory(instance string) (endpoint.Endpoint, io.Closer, error) { - client, err := rpc.DialHTTP("tcp", instance) - if err != nil { - return nil, nil, err - } - - return func(ctx context.Context, request interface{}) (interface{}, error) { - var reply server.ConcatResponse - if err := client.Call("addsvc.Concat", request.(server.ConcatRequest), &reply); err != nil { - return server.ConcatResponse{}, err - } - return reply, nil - }, client, nil -} diff --git a/examples/addsvc/client/thrift/client.go b/examples/addsvc/client/thrift/client.go index 2234a22..a943c7b 100644 --- a/examples/addsvc/client/thrift/client.go +++ b/examples/addsvc/client/thrift/client.go @@ -1,97 +1,55 @@ +// Package thrift provides a Thrift client for the add service. package thrift import ( - "io" + "time" - "github.com/apache/thrift/lib/go/thrift" + 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/server" - thriftadd "github.com/go-kit/kit/examples/addsvc/thrift/gen-go/add" - "github.com/go-kit/kit/log" - "golang.org/x/net/context" + "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 a stateful factory for Sum and Concat Endpoints -func New(protocol string, bufferSize int, framed bool, logger log.Logger) client { - var protocolFactory thrift.TProtocolFactory - switch protocol { - case "compact": - protocolFactory = thrift.NewTCompactProtocolFactory() - case "simplejson": - protocolFactory = thrift.NewTSimpleJSONProtocolFactory() - case "json": - protocolFactory = thrift.NewTJSONProtocolFactory() - case "binary", "": - protocolFactory = thrift.NewTBinaryProtocolFactoryDefault() - default: - panic("invalid protocol") +// 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 transportFactory thrift.TTransportFactory - if bufferSize > 0 { - transportFactory = thrift.NewTBufferedTransportFactory(bufferSize) - } else { - transportFactory = thrift.NewTTransportFactory() - } - if framed { - transportFactory = thrift.NewTFramedTransportFactory(transportFactory) + var concatEndpoint endpoint.Endpoint + { + concatEndpoint = addsvc.MakeThriftConcatEndpoint(client) + concatEndpoint = limiter(concatEndpoint) + sumEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{ + Name: "Concat", + Timeout: 30 * time.Second, + }))(sumEndpoint) } - return client{transportFactory, protocolFactory, logger} + return addsvc.Endpoints{ + SumEndpoint: addsvc.MakeThriftSumEndpoint(client), + ConcatEndpoint: addsvc.MakeThriftConcatEndpoint(client), + } } - -type client struct { - thrift.TTransportFactory - thrift.TProtocolFactory - log.Logger -} - -// SumEndpointFactory transforms host:port strings into Endpoints. -func (c client) SumEndpoint(instance string) (endpoint.Endpoint, io.Closer, error) { - transportSocket, err := thrift.NewTSocket(instance) - if err != nil { - c.Logger.Log("during", "thrift.NewTSocket", "err", err) - return nil, nil, err - } - trans := c.TTransportFactory.GetTransport(transportSocket) - - if err := trans.Open(); err != nil { - c.Logger.Log("during", "thrift transport.Open", "err", err) - return nil, nil, err - } - cli := thriftadd.NewAddServiceClientFactory(trans, c.TProtocolFactory) - - return func(ctx context.Context, request interface{}) (interface{}, error) { - sumRequest := request.(server.SumRequest) - reply, err := cli.Sum(int64(sumRequest.A), int64(sumRequest.B)) - if err != nil { - return server.SumResponse{}, err - } - return server.SumResponse{V: int(reply.Value)}, nil - }, trans, nil -} - -// ConcatEndpointFactory transforms host:port strings into Endpoints. -func (c client) ConcatEndpoint(instance string) (endpoint.Endpoint, io.Closer, error) { - transportSocket, err := thrift.NewTSocket(instance) - if err != nil { - c.Logger.Log("during", "thrift.NewTSocket", "err", err) - return nil, nil, err - } - trans := c.TTransportFactory.GetTransport(transportSocket) - - if err := trans.Open(); err != nil { - c.Logger.Log("during", "thrift transport.Open", "err", err) - return nil, nil, err - } - cli := thriftadd.NewAddServiceClientFactory(trans, c.TProtocolFactory) - - return func(ctx context.Context, request interface{}) (interface{}, error) { - concatRequest := request.(server.ConcatRequest) - reply, err := cli.Concat(concatRequest.A, concatRequest.B) - if err != nil { - return server.ConcatResponse{}, err - } - return server.ConcatResponse{V: reply.Value}, nil - }, trans, nil -} diff --git a/examples/addsvc/cmd/addcli/main.go b/examples/addsvc/cmd/addcli/main.go new file mode 100644 index 0000000..870bfa8 --- /dev/null +++ b/examples/addsvc/cmd/addcli/main.go @@ -0,0 +1,178 @@ +package main + +import ( + "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" + appdashot "github.com/sourcegraph/appdash/opentracing" + "golang.org/x/net/context" + "google.golang.org/grpc" + "sourcegraph.com/sourcegraph/appdash" + + "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 Kafka Collector 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] \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 != "" { + collector, err := zipkin.NewKafkaCollector( + strings.Split(*zipkinAddr, ","), + zipkin.KafkaLogger(log.NewNopLogger()), + ) + if err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + os.Exit(1) + } + tracer, err = zipkin.NewTracer( + zipkin.NewRecorder(collector, false, "localhost:8000", "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) + } +} diff --git a/examples/addsvc/cmd/addsvc/main.go b/examples/addsvc/cmd/addsvc/main.go new file mode 100644 index 0000000..9da3118 --- /dev/null +++ b/examples/addsvc/cmd/addsvc/main.go @@ -0,0 +1,257 @@ +package main + +import ( + "flag" + "fmt" + "net" + "net/http" + "net/http/pprof" + "os" + "os/signal" + "strings" + "syscall" + "time" + + "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" + appdashot "github.com/sourcegraph/appdash/opentracing" + "golang.org/x/net/context" + "google.golang.org/grpc" + "sourcegraph.com/sourcegraph/appdash" + + "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 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.NewContext(logger).With("ts", log.DefaultTimestampUTC) + logger = log.NewContext(logger).With("caller", log.DefaultCaller) + } + logger.Log("msg", "hello") + defer logger.Log("msg", "goodbye") + + // Metrics domain + var ints, chars metrics.Counter + { + // Business level metrics + ints = prometheus.NewCounter(stdprometheus.CounterOpts{ + Namespace: "addsvc", + Name: "integers_summed", + Help: "Total count of integers summed via the Sum method.", + }, []string{}) + chars = prometheus.NewCounter(stdprometheus.CounterOpts{ + Namespace: "addsvc", + Name: "characters_concatenated", + Help: "Total count of characters concatenated via the Concat method.", + }, []string{}) + } + var duration metrics.TimeHistogram + { + // Transport level metrics + duration = metrics.NewTimeHistogram(time.Nanosecond, prometheus.NewSummary(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.NewContext(logger).With("tracer", "Zipkin") + logger.Log("addr", *zipkinAddr) + collector, err := zipkin.NewKafkaCollector( + strings.Split(*zipkinAddr, ","), + zipkin.KafkaLogger(logger), + ) + if err != nil { + logger.Log("err", err) + os.Exit(1) + } + 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.NewContext(logger).With("tracer", "Appdash") + logger.Log("addr", *appdashAddr) + tracer = appdashot.NewTracer(appdash.NewRemoteCollector(*appdashAddr)) + } else if *lightstepToken != "" { + logger := log.NewContext(logger).With("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.NewContext(logger).With("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(metrics.Field{Key: "method", Value: "Sum"}) + sumLogger := log.NewContext(logger).With("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(metrics.Field{Key: "method", Value: "Concat"}) + concatLogger := log.NewContext(logger).With("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.NewContext(logger).With("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.NewContext(logger).With("transport", "HTTP") + h := addsvc.MakeHTTPHandler(ctx, endpoints, tracer, logger) + logger.Log("addr", *httpAddr) + errc <- http.ListenAndServe(*httpAddr, h) + }() + + // gRPC transport + go func() { + logger := log.NewContext(logger).With("transport", "gRPC") + + ln, err := net.Listen("tcp", *grpcAddr) + if err != nil { + errc <- err + return + } + + srv := addsvc.MakeGRPCServer(ctx, endpoints, tracer, logger) + s := grpc.NewServer() + pb.RegisterAddServer(s, srv) + + logger.Log("addr", *grpcAddr) + errc <- s.Serve(ln) + }() + + // Thrift transport + go func() { + logger := log.NewContext(logger).With("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) +} diff --git a/examples/addsvc/doc.go b/examples/addsvc/doc.go new file mode 100644 index 0000000..8865046 --- /dev/null +++ b/examples/addsvc/doc.go @@ -0,0 +1,6 @@ +// Package addsvc implements the business and transport logic for an example +// service that 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 diff --git a/examples/addsvc/endpoint.go b/examples/addsvc/endpoint.go deleted file mode 100644 index 86f5873..0000000 --- a/examples/addsvc/endpoint.go +++ /dev/null @@ -1,24 +0,0 @@ -package main - -import ( - "golang.org/x/net/context" - - "github.com/go-kit/kit/endpoint" - "github.com/go-kit/kit/examples/addsvc/server" -) - -func makeSumEndpoint(svc server.AddService) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(*server.SumRequest) - v := svc.Sum(req.A, req.B) - return server.SumResponse{V: v}, nil - } -} - -func makeConcatEndpoint(svc server.AddService) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(*server.ConcatRequest) - v := svc.Concat(req.A, req.B) - return server.ConcatResponse{V: v}, nil - } -} diff --git a/examples/addsvc/endpoints.go b/examples/addsvc/endpoints.go new file mode 100644 index 0000000..e46d33b --- /dev/null +++ b/examples/addsvc/endpoints.go @@ -0,0 +1,131 @@ +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 ( + "fmt" + "time" + + "golang.org/x/net/context" + + "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, nil +} + +// 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, 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 != nil { + return nil, err + } + return sumResponse{ + V: v, + }, 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) + if err != nil { + return nil, err + } + return concatResponse{ + V: v, + }, 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.TimeHistogram) 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) { + f := metrics.Field{Key: "success", Value: fmt.Sprint(err == nil)} + duration.With(f).Observe(time.Since(begin)) + }(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 } + +type concatRequest struct{ A, B string } + +type concatResponse struct{ V string } diff --git a/examples/addsvc/grpc_binding.go b/examples/addsvc/grpc_binding.go deleted file mode 100644 index 101c71f..0000000 --- a/examples/addsvc/grpc_binding.go +++ /dev/null @@ -1,47 +0,0 @@ -package main - -import ( - "golang.org/x/net/context" - - "github.com/opentracing/opentracing-go" - - "github.com/go-kit/kit/examples/addsvc/pb" - "github.com/go-kit/kit/examples/addsvc/server" - servergrpc "github.com/go-kit/kit/examples/addsvc/server/grpc" - "github.com/go-kit/kit/log" - kitot "github.com/go-kit/kit/tracing/opentracing" - "github.com/go-kit/kit/transport/grpc" -) - -type grpcBinding struct { - sum, concat grpc.Handler -} - -func newGRPCBinding(ctx context.Context, tracer opentracing.Tracer, svc server.AddService, tracingLogger log.Logger) grpcBinding { - return grpcBinding{ - sum: grpc.NewServer( - ctx, - kitot.TraceServer(tracer, "sum")(makeSumEndpoint(svc)), - servergrpc.DecodeSumRequest, - servergrpc.EncodeSumResponse, - grpc.ServerBefore(kitot.FromGRPCRequest(tracer, "", tracingLogger)), - ), - concat: grpc.NewServer( - ctx, - kitot.TraceServer(tracer, "concat")(makeConcatEndpoint(svc)), - servergrpc.DecodeConcatRequest, - servergrpc.EncodeConcatResponse, - grpc.ServerBefore(kitot.FromGRPCRequest(tracer, "", tracingLogger)), - ), - } -} - -func (b grpcBinding) Sum(ctx context.Context, req *pb.SumRequest) (*pb.SumReply, error) { - _, resp, err := b.sum.ServeGRPC(ctx, req) - return resp.(*pb.SumReply), err -} - -func (b grpcBinding) Concat(ctx context.Context, req *pb.ConcatRequest) (*pb.ConcatReply, error) { - _, resp, err := b.concat.ServeGRPC(ctx, req) - return resp.(*pb.ConcatReply), err -} diff --git a/examples/addsvc/main.go b/examples/addsvc/main.go deleted file mode 100644 index 17443cf..0000000 --- a/examples/addsvc/main.go +++ /dev/null @@ -1,257 +0,0 @@ -package main - -import ( - "flag" - "fmt" - stdlog "log" - "math/rand" - "net" - "net/http" - "net/rpc" - "os" - "os/signal" - "strings" - "syscall" - "time" - - "github.com/apache/thrift/lib/go/thrift" - "github.com/lightstep/lightstep-tracer-go" - "github.com/opentracing/opentracing-go" - zipkin "github.com/openzipkin/zipkin-go-opentracing" - stdprometheus "github.com/prometheus/client_golang/prometheus" - appdashot "github.com/sourcegraph/appdash/opentracing" - "golang.org/x/net/context" - "google.golang.org/grpc" - "sourcegraph.com/sourcegraph/appdash" - - "github.com/go-kit/kit/endpoint" - "github.com/go-kit/kit/examples/addsvc/pb" - "github.com/go-kit/kit/examples/addsvc/server" - thriftadd "github.com/go-kit/kit/examples/addsvc/thrift/gen-go/add" - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/metrics" - "github.com/go-kit/kit/metrics/expvar" - "github.com/go-kit/kit/metrics/prometheus" - kitot "github.com/go-kit/kit/tracing/opentracing" - httptransport "github.com/go-kit/kit/transport/http" -) - -func main() { - // Flag domain. Note that gRPC transitively registers flags via its import - // of glog. So, we define a new flag set, to keep those domains distinct. - fs := flag.NewFlagSet("", flag.ExitOnError) - var ( - debugAddr = fs.String("debug.addr", ":8000", "Address for HTTP debug/instrumentation server") - httpAddr = fs.String("http.addr", ":8001", "Address for HTTP (JSON) server") - grpcAddr = fs.String("grpc.addr", ":8002", "Address for gRPC server") - netrpcAddr = fs.String("netrpc.addr", ":8003", "Address for net/rpc server") - thriftAddr = fs.String("thrift.addr", ":8004", "Address for Thrift server") - thriftProtocol = fs.String("thrift.protocol", "binary", "binary, compact, json, simplejson") - thriftBufferSize = fs.Int("thrift.buffer.size", 0, "0 for unbuffered") - thriftFramed = fs.Bool("thrift.framed", false, "true to enable framing") - - // Supported OpenTracing backends - zipkinAddr = fs.String("zipkin.kafka.addr", "", "Enable Zipkin tracing via a Kafka server host:port") - appdashAddr = fs.String("appdash.addr", "", "Enable Appdash tracing via an Appdash server host:port") - lightstepAccessToken = fs.String("lightstep.token", "", "Enable LightStep tracing via a LightStep access token") - ) - flag.Usage = fs.Usage // only show our flags - if err := fs.Parse(os.Args[1:]); err != nil { - fmt.Fprintf(os.Stderr, "%v", err) - os.Exit(1) - } - - // package log - var logger log.Logger - { - logger = log.NewLogfmtLogger(os.Stderr) - logger = log.NewContext(logger).With("ts", log.DefaultTimestampUTC).With("caller", log.DefaultCaller) - stdlog.SetFlags(0) // flags are handled by Go kit's logger - stdlog.SetOutput(log.NewStdlibAdapter(logger)) // redirect anything using stdlib log to us - } - - // package metrics - var requestDuration metrics.TimeHistogram - { - requestDuration = metrics.NewTimeHistogram(time.Nanosecond, metrics.NewMultiHistogram( - "request_duration_ns", - expvar.NewHistogram("request_duration_ns", 0, 5e9, 1, 50, 95, 99), - prometheus.NewSummary(stdprometheus.SummaryOpts{ - Namespace: "myorg", - Subsystem: "addsvc", - Name: "duration_ns", - Help: "Request duration in nanoseconds.", - }, []string{"method"}), - )) - } - - // Set up OpenTracing - var tracer opentracing.Tracer - { - switch { - case *appdashAddr != "" && *lightstepAccessToken == "" && *zipkinAddr == "": - tracer = appdashot.NewTracer(appdash.NewRemoteCollector(*appdashAddr)) - case *appdashAddr == "" && *lightstepAccessToken != "" && *zipkinAddr == "": - tracer = lightstep.NewTracer(lightstep.Options{ - AccessToken: *lightstepAccessToken, - }) - defer lightstep.FlushLightStepTracer(tracer) - case *appdashAddr == "" && *lightstepAccessToken == "" && *zipkinAddr != "": - collector, err := zipkin.NewKafkaCollector( - strings.Split(*zipkinAddr, ","), - zipkin.KafkaLogger(logger), - ) - if err != nil { - logger.Log("err", "unable to create collector", "fatal", err) - os.Exit(1) - } - tracer, err = zipkin.NewTracer( - zipkin.NewRecorder(collector, false, "localhost:80", "addsvc"), - ) - if err != nil { - logger.Log("err", "unable to create zipkin tracer", "fatal", err) - os.Exit(1) - } - case *appdashAddr == "" && *lightstepAccessToken == "" && *zipkinAddr == "": - tracer = opentracing.GlobalTracer() // no-op - default: - logger.Log("fatal", "specify a single -appdash.addr, -lightstep.access.token or -zipkin.kafka.addr") - os.Exit(1) - } - } - - // Business domain - var svc server.AddService - { - svc = pureAddService{} - svc = loggingMiddleware{svc, logger} - svc = instrumentingMiddleware{svc, requestDuration} - } - - // Mechanical stuff - rand.Seed(time.Now().UnixNano()) - root := context.Background() - errc := make(chan error) - - go func() { - errc <- interrupt() - }() - - // Debug/instrumentation - go func() { - transportLogger := log.NewContext(logger).With("transport", "debug") - transportLogger.Log("addr", *debugAddr) - errc <- http.ListenAndServe(*debugAddr, nil) // DefaultServeMux - }() - - // Transport: HTTP/JSON - go func() { - var ( - transportLogger = log.NewContext(logger).With("transport", "HTTP/JSON") - tracingLogger = log.NewContext(transportLogger).With("component", "tracing") - mux = http.NewServeMux() - sum, concat endpoint.Endpoint - ) - - sum = makeSumEndpoint(svc) - sum = kitot.TraceServer(tracer, "sum")(sum) - mux.Handle("/sum", httptransport.NewServer( - root, - sum, - server.DecodeSumRequest, - server.EncodeSumResponse, - httptransport.ServerErrorLogger(transportLogger), - httptransport.ServerBefore(kitot.FromHTTPRequest(tracer, "sum", tracingLogger)), - )) - - concat = makeConcatEndpoint(svc) - concat = kitot.TraceServer(tracer, "concat")(concat) - mux.Handle("/concat", httptransport.NewServer( - root, - concat, - server.DecodeConcatRequest, - server.EncodeConcatResponse, - httptransport.ServerErrorLogger(transportLogger), - httptransport.ServerBefore(kitot.FromHTTPRequest(tracer, "concat", tracingLogger)), - )) - - transportLogger.Log("addr", *httpAddr) - errc <- http.ListenAndServe(*httpAddr, mux) - }() - - // Transport: gRPC - go func() { - transportLogger := log.NewContext(logger).With("transport", "gRPC") - tracingLogger := log.NewContext(transportLogger).With("component", "tracing") - ln, err := net.Listen("tcp", *grpcAddr) - if err != nil { - errc <- err - return - } - s := grpc.NewServer() // uses its own, internal context - pb.RegisterAddServer(s, newGRPCBinding(root, tracer, svc, tracingLogger)) - transportLogger.Log("addr", *grpcAddr) - errc <- s.Serve(ln) - }() - - // Transport: net/rpc - go func() { - transportLogger := log.NewContext(logger).With("transport", "net/rpc") - s := rpc.NewServer() - if err := s.RegisterName("addsvc", netrpcBinding{svc}); err != nil { - errc <- err - return - } - s.HandleHTTP(rpc.DefaultRPCPath, rpc.DefaultDebugPath) - transportLogger.Log("addr", *netrpcAddr) - errc <- http.ListenAndServe(*netrpcAddr, s) - }() - - // Transport: Thrift - go func() { - 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 - } - transportLogger := log.NewContext(logger).With("transport", "thrift") - transportLogger.Log("addr", *thriftAddr) - errc <- thrift.NewTSimpleServer4( - thriftadd.NewAddServiceProcessor(thriftBinding{svc}), - transport, - transportFactory, - protocolFactory, - ).Serve() - }() - - logger.Log("fatal", <-errc) -} - -func interrupt() error { - c := make(chan os.Signal) - signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) - return fmt.Errorf("%s", <-c) -} diff --git a/examples/addsvc/netrpc_binding.go b/examples/addsvc/netrpc_binding.go deleted file mode 100644 index 6171a8a..0000000 --- a/examples/addsvc/netrpc_binding.go +++ /dev/null @@ -1,21 +0,0 @@ -package main - -import ( - "github.com/go-kit/kit/examples/addsvc/server" -) - -type netrpcBinding struct { - server.AddService -} - -func (b netrpcBinding) Sum(request server.SumRequest, response *server.SumResponse) error { - v := b.AddService.Sum(request.A, request.B) - (*response) = server.SumResponse{V: v} - return nil -} - -func (b netrpcBinding) Concat(request server.ConcatRequest, response *server.ConcatResponse) error { - v := b.AddService.Concat(request.A, request.B) - (*response) = server.ConcatResponse{V: v} - return nil -} diff --git a/examples/addsvc/pb/add.pb.go b/examples/addsvc/pb/add.pb.go deleted file mode 100644 index 1ac0c8e..0000000 --- a/examples/addsvc/pb/add.pb.go +++ /dev/null @@ -1,207 +0,0 @@ -// Code generated by protoc-gen-go. -// source: add.proto -// DO NOT EDIT! - -/* -Package pb is a generated protocol buffer package. - -It is generated from these files: - add.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. -const _ = proto.ProtoPackageIsVersion1 - -// 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"` -} - -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"` -} - -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.SupportPackageIsVersion2 - -// 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{}, -} - -var fileDescriptor0 = []byte{ - // 171 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x4c, 0x4c, 0x49, 0xd1, - 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, 0x09, 0x2e, - 0x0e, 0xb0, 0xca, 0x82, 0x9c, 0x4a, 0x90, 0x4c, 0x19, 0x4c, 0x5d, 0x99, 0x92, 0x36, 0x17, 0xaf, - 0x73, 0x7e, 0x5e, 0x72, 0x62, 0x09, 0x86, 0x31, 0x9c, 0x28, 0xc6, 0x70, 0x82, 0x8c, 0x91, 0xe6, - 0xe2, 0x86, 0x29, 0x46, 0x31, 0x09, 0x28, 0x59, 0x66, 0x14, 0xc3, 0xc5, 0xec, 0x98, 0x92, 0x22, - 0xa4, 0xca, 0xc5, 0x0c, 0xb4, 0x4a, 0x88, 0x4f, 0xaf, 0x20, 0x49, 0x0f, 0xe1, 0x3a, 0x29, 0x1e, - 0x38, 0x1f, 0xa8, 0x53, 0x89, 0x41, 0x48, 0x8f, 0x8b, 0x0d, 0x62, 0x94, 0x90, 0x20, 0x48, 0x06, - 0xc5, 0x0d, 0x52, 0xfc, 0xc8, 0x42, 0x60, 0xf5, 0x49, 0x6c, 0x60, 0x6f, 0x1b, 0x03, 0x02, 0x00, - 0x00, 0xff, 0xff, 0xb4, 0xc9, 0xe7, 0x58, 0x03, 0x01, 0x00, 0x00, -} diff --git a/examples/addsvc/pb/add.proto b/examples/addsvc/pb/add.proto deleted file mode 100644 index 43e33e1..0000000 --- a/examples/addsvc/pb/add.proto +++ /dev/null @@ -1,34 +0,0 @@ -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; -} - -// 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; -} diff --git a/examples/addsvc/pb/addsvc.pb.go b/examples/addsvc/pb/addsvc.pb.go new file mode 100644 index 0000000..c766982 --- /dev/null +++ b/examples/addsvc/pb/addsvc.pb.go @@ -0,0 +1,207 @@ +// 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. +const _ = proto.ProtoPackageIsVersion1 + +// 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"` +} + +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"` +} + +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.SupportPackageIsVersion2 + +// 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{}, +} + +var fileDescriptor0 = []byte{ + // 174 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, 0x09, 0x2e, 0x0e, 0xb0, 0xca, 0x82, 0x9c, 0x4a, 0x90, 0x4c, 0x19, 0x4c, 0x5d, 0x99, 0x92, + 0x36, 0x17, 0xaf, 0x73, 0x7e, 0x5e, 0x72, 0x62, 0x09, 0x86, 0x31, 0x9c, 0x28, 0xc6, 0x70, 0x82, + 0x8c, 0x91, 0xe6, 0xe2, 0x86, 0x29, 0x46, 0x31, 0x09, 0x28, 0x59, 0x66, 0x14, 0xc3, 0xc5, 0xec, + 0x98, 0x92, 0x22, 0xa4, 0xca, 0xc5, 0x0c, 0xb4, 0x4a, 0x88, 0x4f, 0xaf, 0x20, 0x49, 0x0f, 0xe1, + 0x3a, 0x29, 0x1e, 0x38, 0x1f, 0xa8, 0x53, 0x89, 0x41, 0x48, 0x8f, 0x8b, 0x0d, 0x62, 0x94, 0x90, + 0x20, 0x48, 0x06, 0xc5, 0x0d, 0x52, 0xfc, 0xc8, 0x42, 0x60, 0xf5, 0x49, 0x6c, 0x60, 0x6f, 0x1b, + 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x8b, 0x2c, 0x12, 0xb4, 0x06, 0x01, 0x00, 0x00, +} diff --git a/examples/addsvc/pb/addsvc.proto b/examples/addsvc/pb/addsvc.proto new file mode 100644 index 0000000..43e33e1 --- /dev/null +++ b/examples/addsvc/pb/addsvc.proto @@ -0,0 +1,34 @@ +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; +} + +// 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; +} diff --git a/examples/addsvc/pb/compile.sh b/examples/addsvc/pb/compile.sh index e231292..c026844 100755 --- a/examples/addsvc/pb/compile.sh +++ b/examples/addsvc/pb/compile.sh @@ -11,4 +11,4 @@ # See also # https://github.com/grpc/grpc-go/tree/master/examples -protoc add.proto --go_out=plugins=grpc:. +protoc addsvc.proto --go_out=plugins=grpc:. diff --git a/examples/addsvc/server/encode_decode.go b/examples/addsvc/server/encode_decode.go deleted file mode 100644 index bf3e803..0000000 --- a/examples/addsvc/server/encode_decode.go +++ /dev/null @@ -1,84 +0,0 @@ -package server - -import ( - "bytes" - "encoding/json" - "io/ioutil" - "net/http" - - "golang.org/x/net/context" -) - -// DecodeSumRequest decodes the request from the provided HTTP request, simply -// by JSON decoding from the request body. It's designed to be used in -// transport/http.Server. -func DecodeSumRequest(_ context.Context, r *http.Request) (interface{}, error) { - var request SumRequest - err := json.NewDecoder(r.Body).Decode(&request) - return &request, err -} - -// EncodeSumResponse encodes the response to the provided HTTP response -// writer, simply by JSON encoding to the writer. It's designed to be used in -// transport/http.Server. -func EncodeSumResponse(_ context.Context, w http.ResponseWriter, response interface{}) error { - return json.NewEncoder(w).Encode(response) -} - -// DecodeConcatRequest decodes the request from the provided HTTP request, -// simply by JSON decoding from the request body. It's designed to be used in -// transport/http.Server. -func DecodeConcatRequest(_ context.Context, r *http.Request) (interface{}, error) { - var request ConcatRequest - err := json.NewDecoder(r.Body).Decode(&request) - return &request, err -} - -// EncodeConcatResponse encodes the response to the provided HTTP response -// writer, simply by JSON encoding to the writer. It's designed to be used in -// transport/http.Server. -func EncodeConcatResponse(_ context.Context, w http.ResponseWriter, response interface{}) error { - return json.NewEncoder(w).Encode(response) -} - -// EncodeSumRequest encodes the request to the provided HTTP request, simply -// by JSON encoding to the request body. It's designed to be used in -// transport/http.Client. -func EncodeSumRequest(_ 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 -} - -// DecodeSumResponse decodes the response from the provided HTTP response, -// simply by JSON decoding from the response body. It's designed to be used in -// transport/http.Client. -func DecodeSumResponse(_ context.Context, resp *http.Response) (interface{}, error) { - var response SumResponse - err := json.NewDecoder(resp.Body).Decode(&response) - return response, err -} - -// EncodeConcatRequest encodes the request to the provided HTTP request, -// simply by JSON encoding to the request body. It's designed to be used in -// transport/http.Client. -func EncodeConcatRequest(_ 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 -} - -// DecodeConcatResponse decodes the response from the provided HTTP response, -// simply by JSON decoding from the response body. It's designed to be used in -// transport/http.Client. -func DecodeConcatResponse(_ context.Context, resp *http.Response) (interface{}, error) { - var response ConcatResponse - err := json.NewDecoder(resp.Body).Decode(&response) - return response, err -} diff --git a/examples/addsvc/server/grpc/encode_decode.go b/examples/addsvc/server/grpc/encode_decode.go deleted file mode 100644 index 05a7634..0000000 --- a/examples/addsvc/server/grpc/encode_decode.go +++ /dev/null @@ -1,42 +0,0 @@ -package grpc - -import ( - "golang.org/x/net/context" - - "github.com/go-kit/kit/examples/addsvc/pb" - "github.com/go-kit/kit/examples/addsvc/server" -) - -func DecodeSumRequest(ctx context.Context, req interface{}) (interface{}, error) { - sumRequest := req.(*pb.SumRequest) - - return &server.SumRequest{ - A: int(sumRequest.A), - B: int(sumRequest.B), - }, nil -} - -func DecodeConcatRequest(ctx context.Context, req interface{}) (interface{}, error) { - concatRequest := req.(*pb.ConcatRequest) - - return &server.ConcatRequest{ - A: concatRequest.A, - B: concatRequest.B, - }, nil -} - -func EncodeSumResponse(ctx context.Context, resp interface{}) (interface{}, error) { - domainResponse := resp.(server.SumResponse) - - return &pb.SumReply{ - V: int64(domainResponse.V), - }, nil -} - -func EncodeConcatResponse(ctx context.Context, resp interface{}) (interface{}, error) { - domainResponse := resp.(server.ConcatResponse) - - return &pb.ConcatReply{ - V: domainResponse.V, - }, nil -} diff --git a/examples/addsvc/server/request_response.go b/examples/addsvc/server/request_response.go deleted file mode 100644 index c01b249..0000000 --- a/examples/addsvc/server/request_response.go +++ /dev/null @@ -1,23 +0,0 @@ -package server - -// SumRequest is the business domain type for a Sum method request. -type SumRequest struct { - A int `json:"a"` - B int `json:"b"` -} - -// SumResponse is the business domain type for a Sum method response. -type SumResponse struct { - V int `json:"v"` -} - -// ConcatRequest is the business domain type for a Concat method request. -type ConcatRequest struct { - A string `json:"a"` - B string `json:"b"` -} - -// ConcatResponse is the business domain type for a Concat method response. -type ConcatResponse struct { - V string `json:"v"` -} diff --git a/examples/addsvc/server/service.go b/examples/addsvc/server/service.go deleted file mode 100644 index ecc6368..0000000 --- a/examples/addsvc/server/service.go +++ /dev/null @@ -1,7 +0,0 @@ -package server - -// AddService is the abstract representation of this service. -type AddService interface { - Sum(a, b int) int - Concat(a, b string) string -} diff --git a/examples/addsvc/service.go b/examples/addsvc/service.go index f0531a2..925c08b 100644 --- a/examples/addsvc/service.go +++ b/examples/addsvc/service.go @@ -1,71 +1,135 @@ -package main +package addsvc + +// This file contains the Service definition, and a basic service +// implementation. It also includes service middlewares. import ( + "errors" "time" - "github.com/go-kit/kit/examples/addsvc/server" + "golang.org/x/net/context" + "github.com/go-kit/kit/log" "github.com/go-kit/kit/metrics" ) -type pureAddService struct{} - -func (pureAddService) Sum(a, b int) int { return a + b } - -func (pureAddService) Concat(a, b string) string { return a + b } - -type loggingMiddleware struct { - server.AddService - log.Logger +// 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) } -func (m loggingMiddleware) Sum(a, b int) (v int) { +var ( + // ErrTwoZeroes is an arbitrary business rule for the Add method. + ErrTwoZeroes = errors.New("can't sum two zeroes") + + // ErrIntOverflow protects the Add method. + ErrIntOverflow = errors.New("integer overflow") + + // ErrMaxSizeExceeded protects the Concat method. + ErrMaxSizeExceeded = errors.New("result exceeds maximum size") +) + +// NewBasicService returns a naïve, stateless implementation of Service. +func NewBasicService() Service { + return basicService{} +} + +type basicService struct{} + +const ( + intMax = 1<<31 - 1 + intMin = -(intMax + 1) + maxLen = 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) { - m.Logger.Log( - "method", "sum", - "a", a, - "b", b, - "v", v, + mw.logger.Log( + "method", "Sum", + "a", a, "b", b, "result", v, "error", err, "took", time.Since(begin), ) }(time.Now()) - v = m.AddService.Sum(a, b) - return + return mw.next.Sum(ctx, a, b) } -func (m loggingMiddleware) Concat(a, b string) (v string) { +func (mw serviceLoggingMiddleware) Concat(ctx context.Context, a, b string) (v string, err error) { defer func(begin time.Time) { - m.Logger.Log( - "method", "concat", - "a", a, - "b", b, - "v", v, + mw.logger.Log( + "method", "Concat", + "a", a, "b", b, "result", v, "error", err, "took", time.Since(begin), ) }(time.Now()) - v = m.AddService.Concat(a, b) - return + return mw.next.Concat(ctx, a, b) } -type instrumentingMiddleware struct { - server.AddService - requestDuration metrics.TimeHistogram +// 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, + } + } } -func (m instrumentingMiddleware) Sum(a, b int) (v int) { - defer func(begin time.Time) { - methodField := metrics.Field{Key: "method", Value: "sum"} - m.requestDuration.With(methodField).Observe(time.Since(begin)) - }(time.Now()) - v = m.AddService.Sum(a, b) - return +type serviceInstrumentingMiddleware struct { + ints metrics.Counter + chars metrics.Counter + next Service } -func (m instrumentingMiddleware) Concat(a, b string) (v string) { - defer func(begin time.Time) { - methodField := metrics.Field{Key: "method", Value: "concat"} - m.requestDuration.With(methodField).Observe(time.Since(begin)) - }(time.Now()) - v = m.AddService.Concat(a, b) - return +func (mw serviceInstrumentingMiddleware) Sum(ctx context.Context, a, b int) (int, error) { + v, err := mw.next.Sum(ctx, a, b) + mw.ints.Add(uint64(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(uint64(len(v))) + return v, err +} diff --git a/examples/addsvc/thrift/add.thrift b/examples/addsvc/thrift/add.thrift deleted file mode 100644 index e978b38..0000000 --- a/examples/addsvc/thrift/add.thrift +++ /dev/null @@ -1,12 +0,0 @@ -struct SumReply { - 1: i64 value -} - -struct ConcatReply { - 1: string value -} - -service AddService { - SumReply Sum(1: i64 a, 2: i64 b) - ConcatReply Concat(1: string a, 2: string b) -} diff --git a/examples/addsvc/thrift/addsvc.thrift b/examples/addsvc/thrift/addsvc.thrift new file mode 100644 index 0000000..e978b38 --- /dev/null +++ b/examples/addsvc/thrift/addsvc.thrift @@ -0,0 +1,12 @@ +struct SumReply { + 1: i64 value +} + +struct ConcatReply { + 1: string value +} + +service AddService { + SumReply Sum(1: i64 a, 2: i64 b) + ConcatReply Concat(1: string a, 2: string b) +} diff --git a/examples/addsvc/thrift/compile.sh b/examples/addsvc/thrift/compile.sh index 11354b1..2ecce5b 100755 --- a/examples/addsvc/thrift/compile.sh +++ b/examples/addsvc/thrift/compile.sh @@ -2,4 +2,4 @@ # 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" add.thrift +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 diff --git a/examples/addsvc/thrift/gen-go/add/add_service-remote/add_service-remote.go b/examples/addsvc/thrift/gen-go/add/add_service-remote/add_service-remote.go deleted file mode 100755 index 79606cb..0000000 --- a/examples/addsvc/thrift/gen-go/add/add_service-remote/add_service-remote.go +++ /dev/null @@ -1,157 +0,0 @@ -// 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/add" - "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 := add.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) - } -} diff --git a/examples/addsvc/thrift/gen-go/add/addservice.go b/examples/addsvc/thrift/gen-go/add/addservice.go deleted file mode 100644 index dbeb119..0000000 --- a/examples/addsvc/thrift/gen-go/add/addservice.go +++ /dev/null @@ -1,807 +0,0 @@ -// Autogenerated by Thrift Compiler (0.9.3) -// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING - -package add - -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 "" - } - 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 "" - } - 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 "" - } - 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 "" - } - return fmt.Sprintf("AddServiceConcatResult(%+v)", *p) -} diff --git a/examples/addsvc/thrift/gen-go/add/constants.go b/examples/addsvc/thrift/gen-go/add/constants.go deleted file mode 100644 index 64a3258..0000000 --- a/examples/addsvc/thrift/gen-go/add/constants.go +++ /dev/null @@ -1,18 +0,0 @@ -// Autogenerated by Thrift Compiler (0.9.3) -// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING - -package add - -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() { -} diff --git a/examples/addsvc/thrift/gen-go/add/ttypes.go b/examples/addsvc/thrift/gen-go/add/ttypes.go deleted file mode 100644 index 744abba..0000000 --- a/examples/addsvc/thrift/gen-go/add/ttypes.go +++ /dev/null @@ -1,199 +0,0 @@ -// Autogenerated by Thrift Compiler (0.9.3) -// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING - -package add - -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 -type SumReply struct { - Value int64 `thrift:"value,1" json:"value"` -} - -func NewSumReply() *SumReply { - return &SumReply{} -} - -func (p *SumReply) GetValue() int64 { - return p.Value -} -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 - } - 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) 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 := 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) String() string { - if p == nil { - return "" - } - return fmt.Sprintf("SumReply(%+v)", *p) -} - -// Attributes: -// - Value -type ConcatReply struct { - Value string `thrift:"value,1" json:"value"` -} - -func NewConcatReply() *ConcatReply { - return &ConcatReply{} -} - -func (p *ConcatReply) GetValue() string { - return p.Value -} -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 - } - 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) 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 := 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) String() string { - if p == nil { - return "" - } - return fmt.Sprintf("ConcatReply(%+v)", *p) -} diff --git a/examples/addsvc/thrift/gen-go/addsvc/add_service-remote/add_service-remote.go b/examples/addsvc/thrift/gen-go/addsvc/add_service-remote/add_service-remote.go new file mode 100755 index 0000000..b8ce67c --- /dev/null +++ b/examples/addsvc/thrift/gen-go/addsvc/add_service-remote/add_service-remote.go @@ -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) + } +} diff --git a/examples/addsvc/thrift/gen-go/addsvc/addservice.go b/examples/addsvc/thrift/gen-go/addsvc/addservice.go new file mode 100644 index 0000000..3f3aeeb --- /dev/null +++ b/examples/addsvc/thrift/gen-go/addsvc/addservice.go @@ -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 "" + } + 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 "" + } + 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 "" + } + 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 "" + } + return fmt.Sprintf("AddServiceConcatResult(%+v)", *p) +} diff --git a/examples/addsvc/thrift/gen-go/addsvc/constants.go b/examples/addsvc/thrift/gen-go/addsvc/constants.go new file mode 100644 index 0000000..2f0079a --- /dev/null +++ b/examples/addsvc/thrift/gen-go/addsvc/constants.go @@ -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() { +} diff --git a/examples/addsvc/thrift/gen-go/addsvc/ttypes.go b/examples/addsvc/thrift/gen-go/addsvc/ttypes.go new file mode 100644 index 0000000..bbae46c --- /dev/null +++ b/examples/addsvc/thrift/gen-go/addsvc/ttypes.go @@ -0,0 +1,199 @@ +// 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 +type SumReply struct { + Value int64 `thrift:"value,1" json:"value"` +} + +func NewSumReply() *SumReply { + return &SumReply{} +} + +func (p *SumReply) GetValue() int64 { + return p.Value +} +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 + } + 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) 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 := 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) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("SumReply(%+v)", *p) +} + +// Attributes: +// - Value +type ConcatReply struct { + Value string `thrift:"value,1" json:"value"` +} + +func NewConcatReply() *ConcatReply { + return &ConcatReply{} +} + +func (p *ConcatReply) GetValue() string { + return p.Value +} +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 + } + 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) 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 := 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) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("ConcatReply(%+v)", *p) +} diff --git a/examples/addsvc/thrift_binding.go b/examples/addsvc/thrift_binding.go deleted file mode 100644 index 959fcad..0000000 --- a/examples/addsvc/thrift_binding.go +++ /dev/null @@ -1,20 +0,0 @@ -package main - -import ( - "github.com/go-kit/kit/examples/addsvc/server" - thriftadd "github.com/go-kit/kit/examples/addsvc/thrift/gen-go/add" -) - -type thriftBinding struct { - server.AddService -} - -func (tb thriftBinding) Sum(a, b int64) (*thriftadd.SumReply, error) { - v := tb.AddService.Sum(int(a), int(b)) - return &thriftadd.SumReply{Value: int64(v)}, nil -} - -func (tb thriftBinding) Concat(a, b string) (*thriftadd.ConcatReply, error) { - v := tb.AddService.Concat(a, b) - return &thriftadd.ConcatReply{Value: v}, nil -} diff --git a/examples/addsvc/transport_grpc.go b/examples/addsvc/transport_grpc.go new file mode 100644 index 0000000..dc45e4d --- /dev/null +++ b/examples/addsvc/transport_grpc.go @@ -0,0 +1,112 @@ +package addsvc + +// This file provides server-side bindings for the gRPC transport. +// It utilizes the transport/grpc.Server. + +import ( + stdopentracing "github.com/opentracing/opentracing-go" + "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(ctx context.Context, endpoints Endpoints, tracer stdopentracing.Tracer, logger log.Logger) pb.AddServer { + options := []grpctransport.ServerOption{ + grpctransport.ServerErrorLogger(logger), + } + return &grpcServer{ + sum: grpctransport.NewServer( + ctx, + endpoints.SumEndpoint, + DecodeGRPCSumRequest, + EncodeGRPCSumResponse, + append(options, grpctransport.ServerBefore(opentracing.FromGRPCRequest(tracer, "Sum", logger)))..., + ), + concat: grpctransport.NewServer( + ctx, + 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 context.Context, req *pb.SumRequest) (*pb.SumReply, error) { + _, rep, err := s.sum.ServeGRPC(ctx, req) + return rep.(*pb.SumReply), err +} + +func (s *grpcServer) Concat(ctx context.Context, req *pb.ConcatRequest) (*pb.ConcatReply, error) { + _, rep, err := s.concat.ServeGRPC(ctx, req) + return rep.(*pb.ConcatReply), err +} + +// 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)}, 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}, 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)}, 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}, 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 +} diff --git a/examples/addsvc/transport_http.go b/examples/addsvc/transport_http.go new file mode 100644 index 0000000..e2d8f6d --- /dev/null +++ b/examples/addsvc/transport_http.go @@ -0,0 +1,141 @@ +package addsvc + +// This file provides server-side bindings for the HTTP transport. +// It utilizes the transport/http.Server. + +import ( + "bytes" + "encoding/json" + "errors" + "io/ioutil" + "net/http" + + stdopentracing "github.com/opentracing/opentracing-go" + "golang.org/x/net/context" + + "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(ctx context.Context, 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( + ctx, + endpoints.SumEndpoint, + DecodeHTTPSumRequest, + EncodeHTTPGenericResponse, + append(options, httptransport.ServerBefore(opentracing.FromHTTPRequest(tracer, "Sum", logger)))..., + )) + m.Handle("/concat", httptransport.NewServer( + ctx, + 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() + + if e, ok := err.(httptransport.Error); ok { + msg = e.Err.Error() + switch e.Domain { + case httptransport.DomainDecode: + code = http.StatusBadRequest + + case httptransport.DomainDo: + switch e.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) +} diff --git a/examples/addsvc/transport_thrift.go b/examples/addsvc/transport_thrift.go new file mode 100644 index 0000000..3a44950 --- /dev/null +++ b/examples/addsvc/transport_thrift.go @@ -0,0 +1,76 @@ +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 ( + "golang.org/x/net/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)}, 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}, 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 != nil { + return nil, err + } + return sumResponse{V: int(reply.Value)}, 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) + if err != nil { + return nil, err + } + return concatResponse{V: reply.Value}, nil + } +}