From c6c0d035225c240d686e046af2f1c1799d0f4b71 Mon Sep 17 00:00:00 2001 From: Jingyi Hu Date: Fri, 10 Aug 2018 11:10:08 -0700 Subject: [PATCH] vendor: add go-grpc-middleware Rebased to master PR #9994. Fixed a Go format issue in v3rpc/interceptor.go. Updated vendor to include go-grpc-middleware. --- bill-of-materials.json | 27 +++ etcdserver/api/v3rpc/interceptor.go | 23 ++- etcdserver/server.go | 4 - .../go-grpc-middleware/chain.go | 183 ++++++++++++++++++ .../grpc-ecosystem/go-grpc-middleware/doc.go | 69 +++++++ .../go-grpc-middleware/wrappers.go | 29 +++ 6 files changed, 319 insertions(+), 16 deletions(-) create mode 100644 vendor/github.com/grpc-ecosystem/go-grpc-middleware/chain.go create mode 100644 vendor/github.com/grpc-ecosystem/go-grpc-middleware/doc.go create mode 100644 vendor/github.com/grpc-ecosystem/go-grpc-middleware/wrappers.go diff --git a/bill-of-materials.json b/bill-of-materials.json index d22f6caba..98e282262 100644 --- a/bill-of-materials.json +++ b/bill-of-materials.json @@ -336,6 +336,33 @@ } ] }, + { + "project": "go.uber.org/atomic", + "licenses": [ + { + "type": "MIT License", + "confidence": 0.9891304347826086 + } + ] + }, + { + "project": "go.uber.org/multierr", + "licenses": [ + { + "type": "MIT License", + "confidence": 0.9891304347826086 + } + ] + }, + { + "project": "go.uber.org/zap", + "licenses": [ + { + "type": "MIT License", + "confidence": 0.9891304347826086 + } + ] + }, { "project": "golang.org/x/crypto", "licenses": [ diff --git a/etcdserver/api/v3rpc/interceptor.go b/etcdserver/api/v3rpc/interceptor.go index 1e3a82617..32022b933 100644 --- a/etcdserver/api/v3rpc/interceptor.go +++ b/etcdserver/api/v3rpc/interceptor.go @@ -65,7 +65,7 @@ func newLogUnaryInterceptor(s *etcdserver.EtcdServer) grpc.UnaryServerIntercepto return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { startTime := time.Now() resp, err := handler(ctx, req) - defer logUnaryRequestStats(ctx, s.Logger(), info, startTime, req, resp) + defer logUnaryRequestStats(ctx, nil, info, startTime, req, resp) return resp, err } } @@ -78,8 +78,8 @@ func logUnaryRequestStats(ctx context.Context, lg *zap.Logger, info *grpc.UnaryS remote = peerInfo.Addr.String() } var responseType string = info.FullMethod - var reqCount, respCount int64 = 0, 0 - var reqSize, respSize int = 0, 0 + var reqCount, respCount int64 + var reqSize, respSize int var reqContent string switch _resp := resp.(type) { case *pb.RangeResponse: @@ -152,15 +152,14 @@ func logUnaryRequestStats(ctx context.Context, lg *zap.Logger, info *grpc.UnaryS func logGenericRequestStats(lg *zap.Logger, startTime time.Time, duration time.Duration, remote string, responseType string, reqCount int64, reqSize int, respCount int64, respSize int, reqContent string) { if lg == nil { - plog.Debugf( - "start time = %v, " + - "time spent = %v, " + - "remote = %s, " + - "response type = %s, " + - "request count = %d, " + - "request size = %d, " + - "response count = %d, " + - "response size = %d, " + + plog.Debugf("start time = %v, "+ + "time spent = %v, "+ + "remote = %s, "+ + "response type = %s, "+ + "request count = %d, "+ + "request size = %d, "+ + "response count = %d, "+ + "response size = %d, "+ "request content = %s", startTime, duration, remote, responseType, reqCount, reqSize, respCount, respSize, reqContent, ) diff --git a/etcdserver/server.go b/etcdserver/server.go index 059037af0..f891c8623 100644 --- a/etcdserver/server.go +++ b/etcdserver/server.go @@ -1741,7 +1741,3 @@ func (s *EtcdServer) goAttach(f func()) { func (s *EtcdServer) Alarms() []*pb.AlarmMember { return s.alarmStore.Get(pb.AlarmType_NONE) } - -func (s *EtcdServer) Logger() *zap.Logger { - return s.lg -} diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/chain.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/chain.go new file mode 100644 index 000000000..45a2f5f49 --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/chain.go @@ -0,0 +1,183 @@ +// Copyright 2016 Michal Witkowski. All Rights Reserved. +// See LICENSE for licensing terms. + +// gRPC Server Interceptor chaining middleware. + +package grpc_middleware + +import ( + "golang.org/x/net/context" + "google.golang.org/grpc" +) + +// ChainUnaryServer creates a single interceptor out of a chain of many interceptors. +// +// Execution is done in left-to-right order, including passing of context. +// For example ChainUnaryServer(one, two, three) will execute one before two before three, and three +// will see context changes of one and two. +func ChainUnaryServer(interceptors ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor { + n := len(interceptors) + + if n > 1 { + lastI := n - 1 + return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + var ( + chainHandler grpc.UnaryHandler + curI int + ) + + chainHandler = func(currentCtx context.Context, currentReq interface{}) (interface{}, error) { + if curI == lastI { + return handler(currentCtx, currentReq) + } + curI++ + resp, err := interceptors[curI](currentCtx, currentReq, info, chainHandler) + curI-- + return resp, err + } + + return interceptors[0](ctx, req, info, chainHandler) + } + } + + if n == 1 { + return interceptors[0] + } + + // n == 0; Dummy interceptor maintained for backward compatibility to avoid returning nil. + return func(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + return handler(ctx, req) + } +} + +// ChainStreamServer creates a single interceptor out of a chain of many interceptors. +// +// Execution is done in left-to-right order, including passing of context. +// For example ChainUnaryServer(one, two, three) will execute one before two before three. +// If you want to pass context between interceptors, use WrapServerStream. +func ChainStreamServer(interceptors ...grpc.StreamServerInterceptor) grpc.StreamServerInterceptor { + n := len(interceptors) + + if n > 1 { + lastI := n - 1 + return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + var ( + chainHandler grpc.StreamHandler + curI int + ) + + chainHandler = func(currentSrv interface{}, currentStream grpc.ServerStream) error { + if curI == lastI { + return handler(currentSrv, currentStream) + } + curI++ + err := interceptors[curI](currentSrv, currentStream, info, chainHandler) + curI-- + return err + } + + return interceptors[0](srv, stream, info, chainHandler) + } + } + + if n == 1 { + return interceptors[0] + } + + // n == 0; Dummy interceptor maintained for backward compatibility to avoid returning nil. + return func(srv interface{}, stream grpc.ServerStream, _ *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + return handler(srv, stream) + } +} + +// ChainUnaryClient creates a single interceptor out of a chain of many interceptors. +// +// Execution is done in left-to-right order, including passing of context. +// For example ChainUnaryClient(one, two, three) will execute one before two before three. +func ChainUnaryClient(interceptors ...grpc.UnaryClientInterceptor) grpc.UnaryClientInterceptor { + n := len(interceptors) + + if n > 1 { + lastI := n - 1 + return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { + var ( + chainHandler grpc.UnaryInvoker + curI int + ) + + chainHandler = func(currentCtx context.Context, currentMethod string, currentReq, currentRepl interface{}, currentConn *grpc.ClientConn, currentOpts ...grpc.CallOption) error { + if curI == lastI { + return invoker(currentCtx, currentMethod, currentReq, currentRepl, currentConn, currentOpts...) + } + curI++ + err := interceptors[curI](currentCtx, currentMethod, currentReq, currentRepl, currentConn, chainHandler, currentOpts...) + curI-- + return err + } + + return interceptors[0](ctx, method, req, reply, cc, chainHandler, opts...) + } + } + + if n == 1 { + return interceptors[0] + } + + // n == 0; Dummy interceptor maintained for backward compatibility to avoid returning nil. + return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { + return invoker(ctx, method, req, reply, cc, opts...) + } +} + +// ChainStreamClient creates a single interceptor out of a chain of many interceptors. +// +// Execution is done in left-to-right order, including passing of context. +// For example ChainStreamClient(one, two, three) will execute one before two before three. +func ChainStreamClient(interceptors ...grpc.StreamClientInterceptor) grpc.StreamClientInterceptor { + n := len(interceptors) + + if n > 1 { + lastI := n - 1 + return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) { + var ( + chainHandler grpc.Streamer + curI int + ) + + chainHandler = func(currentCtx context.Context, currentDesc *grpc.StreamDesc, currentConn *grpc.ClientConn, currentMethod string, currentOpts ...grpc.CallOption) (grpc.ClientStream, error) { + if curI == lastI { + return streamer(currentCtx, currentDesc, currentConn, currentMethod, currentOpts...) + } + curI++ + stream, err := interceptors[curI](currentCtx, currentDesc, currentConn, currentMethod, chainHandler, currentOpts...) + curI-- + return stream, err + } + + return interceptors[0](ctx, desc, cc, method, chainHandler, opts...) + } + } + + if n == 1 { + return interceptors[0] + } + + // n == 0; Dummy interceptor maintained for backward compatibility to avoid returning nil. + return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) { + return streamer(ctx, desc, cc, method, opts...) + } +} + +// Chain creates a single interceptor out of a chain of many interceptors. +// +// WithUnaryServerChain is a grpc.Server config option that accepts multiple unary interceptors. +// Basically syntactic sugar. +func WithUnaryServerChain(interceptors ...grpc.UnaryServerInterceptor) grpc.ServerOption { + return grpc.UnaryInterceptor(ChainUnaryServer(interceptors...)) +} + +// WithStreamServerChain is a grpc.Server config option that accepts multiple stream interceptors. +// Basically syntactic sugar. +func WithStreamServerChain(interceptors ...grpc.StreamServerInterceptor) grpc.ServerOption { + return grpc.StreamInterceptor(ChainStreamServer(interceptors...)) +} diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/doc.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/doc.go new file mode 100644 index 000000000..716895036 --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/doc.go @@ -0,0 +1,69 @@ +// Copyright 2016 Michal Witkowski. All Rights Reserved. +// See LICENSE for licensing terms. + +/* +`grpc_middleware` is a collection of gRPC middleware packages: interceptors, helpers and tools. + +Middleware + +gRPC is a fantastic RPC middleware, which sees a lot of adoption in the Golang world. However, the +upstream gRPC codebase is relatively bare bones. + +This package, and most of its child packages provides commonly needed middleware for gRPC: +client-side interceptors for retires, server-side interceptors for input validation and auth, +functions for chaining said interceptors, metadata convenience methods and more. + +Chaining + +By default, gRPC doesn't allow one to have more than one interceptor either on the client nor on +the server side. `grpc_middleware` provides convenient chaining methods + +Simple way of turning a multiple interceptors into a single interceptor. Here's an example for +server chaining: + + myServer := grpc.NewServer( + grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(loggingStream, monitoringStream, authStream)), + grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(loggingUnary, monitoringUnary, authUnary), + ) + +These interceptors will be executed from left to right: logging, monitoring and auth. + +Here's an example for client side chaining: + + clientConn, err = grpc.Dial( + address, + grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(monitoringClientUnary, retryUnary)), + grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(monitoringClientStream, retryStream)), + ) + client = pb_testproto.NewTestServiceClient(clientConn) + resp, err := client.PingEmpty(s.ctx, &myservice.Request{Msg: "hello"}) + +These interceptors will be executed from left to right: monitoring and then retry logic. + +The retry interceptor will call every interceptor that follows it whenever when a retry happens. + +Writing Your Own + +Implementing your own interceptor is pretty trivial: there are interfaces for that. But the interesting +bit exposing common data to handlers (and other middleware), similarly to HTTP Middleware design. +For example, you may want to pass the identity of the caller from the auth interceptor all the way +to the handling function. + +For example, a client side interceptor example for auth looks like: + + func FakeAuthUnaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + newCtx := context.WithValue(ctx, "user_id", "john@example.com") + return handler(newCtx, req) + } + +Unfortunately, it's not as easy for streaming RPCs. These have the `context.Context` embedded within +the `grpc.ServerStream` object. To pass values through context, a wrapper (`WrappedServerStream`) is +needed. For example: + + func FakeAuthStreamingInterceptor(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + newStream := grpc_middleware.WrapServerStream(stream) + newStream.WrappedContext = context.WithValue(ctx, "user_id", "john@example.com") + return handler(srv, stream) + } +*/ +package grpc_middleware diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/wrappers.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/wrappers.go new file mode 100644 index 000000000..597b86244 --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/wrappers.go @@ -0,0 +1,29 @@ +// Copyright 2016 Michal Witkowski. All Rights Reserved. +// See LICENSE for licensing terms. + +package grpc_middleware + +import ( + "golang.org/x/net/context" + "google.golang.org/grpc" +) + +// WrappedServerStream is a thin wrapper around grpc.ServerStream that allows modifying context. +type WrappedServerStream struct { + grpc.ServerStream + // WrappedContext is the wrapper's own Context. You can assign it. + WrappedContext context.Context +} + +// Context returns the wrapper's WrappedContext, overwriting the nested grpc.ServerStream.Context() +func (w *WrappedServerStream) Context() context.Context { + return w.WrappedContext +} + +// WrapServerStream returns a ServerStream that has the ability to overwrite context. +func WrapServerStream(stream grpc.ServerStream) *WrappedServerStream { + if existing, ok := stream.(*WrappedServerStream); ok { + return existing + } + return &WrappedServerStream{ServerStream: stream, WrappedContext: stream.Context()} +}