Repository: go-kit/kit
Pull request #1070 (2021-03-19 19:19:34)

Fix typo in jwt package
    * change JWTTokenContextKey to JWTContextKey

    * revise errors as well as comments

amidam: fixes #1071

Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0108344..7742df6 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -11,14 +11,14 @@ jobs:
     name: Build
     runs-on: ubuntu-latest
     strategy:
-      matrix:
-        go: ['1.14', '1.15']
+      matrix:  # Support latest and one minor back
+        go: ['1.15', '1.16']
     env:
       GOFLAGS: -mod=readonly
 
     services:
       etcd:
-        image: quay.io/coreos/etcd:v3.4.3
+        image: gcr.io/etcd-development/etcd:v3.5.0
         ports:
           - 2379
         env:
diff --git a/auth/jwt/README.md b/auth/jwt/README.md
index 1ed825a..8cf823c 100644
--- a/auth/jwt/README.md
+++ b/auth/jwt/README.md
@@ -7,7 +7,7 @@ through [JSON Web Tokens](https://jwt.io/).
 
 NewParser takes a key function and an expected signing method and returns an
 `endpoint.Middleware`. The middleware will parse a token passed into the
-context via the `jwt.JWTTokenContextKey`. If the token is valid, any claims
+context via the `jwt.JWTContextKey`. If the token is valid, any claims
 will be added to the context via the `jwt.JWTClaimsContextKey`.
 
 ```go
@@ -30,7 +30,7 @@ func main() {
 
 NewSigner takes a JWT key ID header, the signing key, signing method, and a
 claims object. It returns an `endpoint.Middleware`. The middleware will build
-the token string and add it to the context via the `jwt.JWTTokenContextKey`.
+the token string and add it to the context via the `jwt.JWTContextKey`.
 
 ```go
 import (
diff --git a/auth/jwt/middleware.go b/auth/jwt/middleware.go
index 0e29e6d..b1c75a6 100644
--- a/auth/jwt/middleware.go
+++ b/auth/jwt/middleware.go
@@ -12,9 +12,13 @@ import (
 type contextKey string
 
 const (
-	// JWTTokenContextKey holds the key used to store a JWT Token in the
-	// context.
-	JWTTokenContextKey contextKey = "JWTToken"
+	// JWTContextKey holds the key used to store a JWT in the context.
+	JWTContextKey contextKey = "JWTToken"
+
+	// JWTTokenContextKey is an alias for JWTContextKey.
+	//
+	// Deprecated: prefer JWTContextKey.
+	JWTTokenContextKey = JWTContextKey
 
 	// JWTClaimsContextKey holds the key used to store the JWT Claims in the
 	// context.
@@ -27,13 +31,13 @@ var (
 	ErrTokenContextMissing = errors.New("token up for parsing was not passed through the context")
 
 	// ErrTokenInvalid denotes a token was not able to be validated.
-	ErrTokenInvalid = errors.New("JWT Token was invalid")
+	ErrTokenInvalid = errors.New("JWT was invalid")
 
 	// ErrTokenExpired denotes a token's expire header (exp) has since passed.
-	ErrTokenExpired = errors.New("JWT Token is expired")
+	ErrTokenExpired = errors.New("JWT is expired")
 
-	// ErrTokenMalformed denotes a token was not formatted as a JWT token.
-	ErrTokenMalformed = errors.New("JWT Token is malformed")
+	// ErrTokenMalformed denotes a token was not formatted as a JWT.
+	ErrTokenMalformed = errors.New("JWT is malformed")
 
 	// ErrTokenNotActive denotes a token's not before header (nbf) is in the
 	// future.
@@ -44,7 +48,7 @@ var (
 	ErrUnexpectedSigningMethod = errors.New("unexpected signing method")
 )
 
-// NewSigner creates a new JWT token generating middleware, specifying key ID,
+// NewSigner creates a new JWT generating middleware, specifying key ID,
 // signing string, signing method and the claims you would like it to contain.
 // Tokens are signed with a Key ID header (kid) which is useful for determining
 // the key to use for parsing. Particularly useful for clients.
@@ -59,7 +63,7 @@ func NewSigner(kid string, key []byte, method jwt.SigningMethod, claims jwt.Clai
 			if err != nil {
 				return nil, err
 			}
-			ctx = context.WithValue(ctx, JWTTokenContextKey, tokenString)
+			ctx = context.WithValue(ctx, JWTContextKey, tokenString)
 
 			return next(ctx, request)
 		}
@@ -82,7 +86,7 @@ func StandardClaimsFactory() jwt.Claims {
 	return &jwt.StandardClaims{}
 }
 
-// NewParser creates a new JWT token parsing middleware, specifying a
+// NewParser creates a new JWT parsing middleware, specifying a
 // jwt.Keyfunc interface, the signing method and the claims type to be used. NewParser
 // adds the resulting claims to endpoint context or returns error on invalid token.
 // Particularly useful for servers.
@@ -90,7 +94,7 @@ func NewParser(keyFunc jwt.Keyfunc, method jwt.SigningMethod, newClaims ClaimsFa
 	return func(next endpoint.Endpoint) endpoint.Endpoint {
 		return func(ctx context.Context, request interface{}) (response interface{}, err error) {
 			// tokenString is stored in the context from the transport handlers.
-			tokenString, ok := ctx.Value(JWTTokenContextKey).(string)
+			tokenString, ok := ctx.Value(JWTContextKey).(string)
 			if !ok {
 				return nil, ErrTokenContextMissing
 			}
diff --git a/auth/jwt/transport.go b/auth/jwt/transport.go
index 4b7082a..e7d19c1 100644
--- a/auth/jwt/transport.go
+++ b/auth/jwt/transport.go
@@ -26,7 +26,7 @@ func HTTPToContext() http.RequestFunc {
 			return ctx
 		}
 
-		return context.WithValue(ctx, JWTTokenContextKey, token)
+		return context.WithValue(ctx, JWTContextKey, token)
 	}
 }
 
@@ -34,7 +34,7 @@ func HTTPToContext() http.RequestFunc {
 // useful for clients.
 func ContextToHTTP() http.RequestFunc {
 	return func(ctx context.Context, r *stdhttp.Request) context.Context {
-		token, ok := ctx.Value(JWTTokenContextKey).(string)
+		token, ok := ctx.Value(JWTContextKey).(string)
 		if ok {
 			r.Header.Add("Authorization", generateAuthHeaderFromToken(token))
 		}
@@ -54,7 +54,7 @@ func GRPCToContext() grpc.ServerRequestFunc {
 
 		token, ok := extractTokenFromAuthHeader(authHeader[0])
 		if ok {
-			ctx = context.WithValue(ctx, JWTTokenContextKey, token)
+			ctx = context.WithValue(ctx, JWTContextKey, token)
 		}
 
 		return ctx
@@ -65,7 +65,7 @@ func GRPCToContext() grpc.ServerRequestFunc {
 // useful for clients.
 func ContextToGRPC() grpc.ClientRequestFunc {
 	return func(ctx context.Context, md *metadata.MD) context.Context {
-		token, ok := ctx.Value(JWTTokenContextKey).(string)
+		token, ok := ctx.Value(JWTContextKey).(string)
 		if ok {
 			// capital "Key" is illegal in HTTP/2.
 			(*md)["authorization"] = []string{generateAuthHeaderFromToken(token)}
diff --git a/docker-compose-integration.yml b/docker-compose-integration.yml
index a33c5fe..9632d0f 100644
--- a/docker-compose-integration.yml
+++ b/docker-compose-integration.yml
@@ -1,7 +1,7 @@
 version: '2'
 services:
   etcd:
-    image: quay.io/coreos/etcd:v3.4.3
+    image: gcr.io/etcd-development/etcd:v3.5.0
     ports:
       - "2379:2379"
     environment:
diff --git a/examples/addsvc/thrift/gen-go/addsvc/GoUnusedProtection__.go b/examples/addsvc/thrift/gen-go/addsvc/GoUnusedProtection__.go
index 88387e1..272dacc 100644
--- a/examples/addsvc/thrift/gen-go/addsvc/GoUnusedProtection__.go
+++ b/examples/addsvc/thrift/gen-go/addsvc/GoUnusedProtection__.go
@@ -1,7 +1,5 @@
-// Autogenerated by Thrift Compiler (1.0.0-dev)
-// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+// Code generated by Thrift Compiler (0.14.1). DO NOT EDIT.
 
 package addsvc
 
-var GoUnusedProtection__ int;
-
+var GoUnusedProtection__ int
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
index ded0914..ee8ec56 100755
--- 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
@@ -1,5 +1,4 @@
-// Autogenerated by Thrift Compiler (1.0.0-dev)
-// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+// Code generated by Thrift Compiler (0.14.1). DO NOT EDIT.
 
 package main
 
@@ -17,6 +16,8 @@ import (
 	"strings"
 )
 
+var _ = addsvc.GoUnusedProtection__
+
 func Usage() {
 	fmt.Fprintln(os.Stderr, "Usage of ", os.Args[0], " [-h host:port] [-u url] [-f[ramed]] function [arg1 [arg2...]]:")
 	flag.PrintDefaults()
@@ -74,7 +75,7 @@ func main() {
 			flag.Usage()
 		}
 		host = parsedUrl.Host
-		useHttp = parsedUrl.Scheme == "" || parsedUrl.Scheme == "http" || parsedUrl.Scheme == "https"
+		useHttp = len(parsedUrl.Scheme) <= 0 || parsedUrl.Scheme == "http" || parsedUrl.Scheme == "https"
 	} else if useHttp {
 		_, err := url.Parse(fmt.Sprint("http://", host, ":", port))
 		if err != nil {
@@ -149,14 +150,14 @@ func main() {
 			fmt.Fprintln(os.Stderr, "Sum requires 2 args")
 			flag.Usage()
 		}
-		argvalue0, err6 := (strconv.ParseInt(flag.Arg(1), 10, 64))
-		if err6 != nil {
+		argvalue0, err8 := (strconv.ParseInt(flag.Arg(1), 10, 64))
+		if err8 != nil {
 			Usage()
 			return
 		}
 		value0 := argvalue0
-		argvalue1, err7 := (strconv.ParseInt(flag.Arg(2), 10, 64))
-		if err7 != nil {
+		argvalue1, err9 := (strconv.ParseInt(flag.Arg(2), 10, 64))
+		if err9 != nil {
 			Usage()
 			return
 		}
diff --git a/examples/addsvc/thrift/gen-go/addsvc/addsvc-consts.go b/examples/addsvc/thrift/gen-go/addsvc/addsvc-consts.go
index eea54fe..9e269a1 100644
--- a/examples/addsvc/thrift/gen-go/addsvc/addsvc-consts.go
+++ b/examples/addsvc/thrift/gen-go/addsvc/addsvc-consts.go
@@ -1,24 +1,21 @@
-// Autogenerated by Thrift Compiler (1.0.0-dev)
-// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+// Code generated by Thrift Compiler (0.14.1). DO NOT EDIT.
 
 package addsvc
 
 import (
 	"bytes"
 	"context"
-	"reflect"
 	"fmt"
 	"github.com/apache/thrift/lib/go/thrift"
+	"time"
 )
 
 // (needed to ensure safety because of naive import list construction.)
 var _ = thrift.ZERO
 var _ = fmt.Printf
 var _ = context.Background
-var _ = reflect.DeepEqual
+var _ = time.Now
 var _ = bytes.Equal
 
-
 func init() {
 }
-
diff --git a/examples/addsvc/thrift/gen-go/addsvc/addsvc.go b/examples/addsvc/thrift/gen-go/addsvc/addsvc.go
index 14a87e6..15dcc97 100644
--- a/examples/addsvc/thrift/gen-go/addsvc/addsvc.go
+++ b/examples/addsvc/thrift/gen-go/addsvc/addsvc.go
@@ -1,935 +1,1111 @@
-// Autogenerated by Thrift Compiler (1.0.0-dev)
-// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+// Code generated by Thrift Compiler (0.14.1). DO NOT EDIT.
 
 package addsvc
 
 import (
 	"bytes"
 	"context"
-	"reflect"
 	"fmt"
 	"github.com/apache/thrift/lib/go/thrift"
+	"time"
 )
 
 // (needed to ensure safety because of naive import list construction.)
 var _ = thrift.ZERO
 var _ = fmt.Printf
 var _ = context.Background
-var _ = reflect.DeepEqual
+var _ = time.Now
 var _ = bytes.Equal
 
 // Attributes:
 //  - Value
 //  - Err
 type SumReply struct {
-  Value int64 `thrift:"value,1" db:"value" json:"value"`
-  Err string `thrift:"err,2" db:"err" json:"err"`
+	Value int64  `thrift:"value,1" db:"value" json:"value"`
+	Err   string `thrift:"err,2" db:"err" json:"err"`
 }
 
 func NewSumReply() *SumReply {
-  return &SumReply{}
+	return &SumReply{}
 }
 
-
 func (p *SumReply) GetValue() int64 {
-  return p.Value
+	return p.Value
 }
 
 func (p *SumReply) GetErr() string {
-  return p.Err
-}
-func (p *SumReply) Read(iprot thrift.TProtocol) error {
-  if _, err := iprot.ReadStructBegin(); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
-  }
-
-
-  for {
-    _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
-    if err != nil {
-      return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
-    }
-    if fieldTypeId == thrift.STOP { break; }
-    switch fieldId {
-    case 1:
-      if fieldTypeId == thrift.I64 {
-        if err := p.ReadField1(iprot); err != nil {
-          return err
-        }
-      } else {
-        if err := iprot.Skip(fieldTypeId); err != nil {
-          return err
-        }
-      }
-    case 2:
-      if fieldTypeId == thrift.STRING {
-        if err := p.ReadField2(iprot); err != nil {
-          return err
-        }
-      } else {
-        if err := iprot.Skip(fieldTypeId); err != nil {
-          return err
-        }
-      }
-    default:
-      if err := iprot.Skip(fieldTypeId); err != nil {
-        return err
-      }
-    }
-    if err := iprot.ReadFieldEnd(); err != nil {
-      return err
-    }
-  }
-  if err := iprot.ReadStructEnd(); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
-  }
-  return nil
-}
-
-func (p *SumReply)  ReadField1(iprot thrift.TProtocol) error {
-  if v, err := iprot.ReadI64(); err != nil {
-  return thrift.PrependError("error reading field 1: ", err)
-} else {
-  p.Value = v
-}
-  return nil
-}
-
-func (p *SumReply)  ReadField2(iprot thrift.TProtocol) error {
-  if v, err := iprot.ReadString(); err != nil {
-  return thrift.PrependError("error reading field 2: ", err)
-} else {
-  p.Err = v
-}
-  return nil
-}
-
-func (p *SumReply) Write(oprot thrift.TProtocol) error {
-  if err := oprot.WriteStructBegin("SumReply"); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) }
-  if p != nil {
-    if err := p.writeField1(oprot); err != nil { return err }
-    if err := p.writeField2(oprot); err != nil { return err }
-  }
-  if err := oprot.WriteFieldStop(); err != nil {
-    return thrift.PrependError("write field stop error: ", err) }
-  if err := oprot.WriteStructEnd(); err != nil {
-    return thrift.PrependError("write struct stop error: ", err) }
-  return nil
-}
-
-func (p *SumReply) writeField1(oprot thrift.TProtocol) (err error) {
-  if err := oprot.WriteFieldBegin("value", thrift.I64, 1); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:value: ", p), err) }
-  if err := oprot.WriteI64(int64(p.Value)); err != nil {
-  return thrift.PrependError(fmt.Sprintf("%T.value (1) field write error: ", p), err) }
-  if err := oprot.WriteFieldEnd(); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T write field end error 1:value: ", p), err) }
-  return err
-}
-
-func (p *SumReply) writeField2(oprot thrift.TProtocol) (err error) {
-  if err := oprot.WriteFieldBegin("err", thrift.STRING, 2); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:err: ", p), err) }
-  if err := oprot.WriteString(string(p.Err)); err != nil {
-  return thrift.PrependError(fmt.Sprintf("%T.err (2) field write error: ", p), err) }
-  if err := oprot.WriteFieldEnd(); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T write field end error 2:err: ", p), err) }
-  return err
+	return p.Err
+}
+func (p *SumReply) Read(ctx context.Context, iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(ctx); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin(ctx)
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if fieldTypeId == thrift.I64 {
+				if err := p.ReadField1(ctx, iprot); err != nil {
+					return err
+				}
+			} else {
+				if err := iprot.Skip(ctx, fieldTypeId); err != nil {
+					return err
+				}
+			}
+		case 2:
+			if fieldTypeId == thrift.STRING {
+				if err := p.ReadField2(ctx, iprot); err != nil {
+					return err
+				}
+			} else {
+				if err := iprot.Skip(ctx, fieldTypeId); err != nil {
+					return err
+				}
+			}
+		default:
+			if err := iprot.Skip(ctx, fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(ctx); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(ctx); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	return nil
+}
+
+func (p *SumReply) ReadField1(ctx context.Context, iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(ctx); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		p.Value = v
+	}
+	return nil
+}
+
+func (p *SumReply) ReadField2(ctx context.Context, iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadString(ctx); err != nil {
+		return thrift.PrependError("error reading field 2: ", err)
+	} else {
+		p.Err = v
+	}
+	return nil
+}
+
+func (p *SumReply) Write(ctx context.Context, oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin(ctx, "SumReply"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if p != nil {
+		if err := p.writeField1(ctx, oprot); err != nil {
+			return err
+		}
+		if err := p.writeField2(ctx, oprot); err != nil {
+			return err
+		}
+	}
+	if err := oprot.WriteFieldStop(ctx); err != nil {
+		return thrift.PrependError("write field stop error: ", err)
+	}
+	if err := oprot.WriteStructEnd(ctx); err != nil {
+		return thrift.PrependError("write struct stop error: ", err)
+	}
+	return nil
+}
+
+func (p *SumReply) writeField1(ctx context.Context, oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin(ctx, "value", thrift.I64, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:value: ", p), err)
+	}
+	if err := oprot.WriteI64(ctx, int64(p.Value)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.value (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(ctx); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:value: ", p), err)
+	}
+	return err
+}
+
+func (p *SumReply) writeField2(ctx context.Context, oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin(ctx, "err", thrift.STRING, 2); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:err: ", p), err)
+	}
+	if err := oprot.WriteString(ctx, string(p.Err)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.err (2) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(ctx); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 2:err: ", p), err)
+	}
+	return err
+}
+
+func (p *SumReply) Equals(other *SumReply) bool {
+	if p == other {
+		return true
+	} else if p == nil || other == nil {
+		return false
+	}
+	if p.Value != other.Value {
+		return false
+	}
+	if p.Err != other.Err {
+		return false
+	}
+	return true
 }
 
 func (p *SumReply) String() string {
-  if p == nil {
-    return "<nil>"
-  }
-  return fmt.Sprintf("SumReply(%+v)", *p)
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("SumReply(%+v)", *p)
 }
 
 // Attributes:
 //  - Value
 //  - Err
 type ConcatReply struct {
-  Value string `thrift:"value,1" db:"value" json:"value"`
-  Err string `thrift:"err,2" db:"err" json:"err"`
+	Value string `thrift:"value,1" db:"value" json:"value"`
+	Err   string `thrift:"err,2" db:"err" json:"err"`
 }
 
 func NewConcatReply() *ConcatReply {
-  return &ConcatReply{}
+	return &ConcatReply{}
 }
 
-
 func (p *ConcatReply) GetValue() string {
-  return p.Value
+	return p.Value
 }
 
 func (p *ConcatReply) GetErr() string {
-  return p.Err
-}
-func (p *ConcatReply) Read(iprot thrift.TProtocol) error {
-  if _, err := iprot.ReadStructBegin(); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
-  }
-
-
-  for {
-    _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
-    if err != nil {
-      return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
-    }
-    if fieldTypeId == thrift.STOP { break; }
-    switch fieldId {
-    case 1:
-      if fieldTypeId == thrift.STRING {
-        if err := p.ReadField1(iprot); err != nil {
-          return err
-        }
-      } else {
-        if err := iprot.Skip(fieldTypeId); err != nil {
-          return err
-        }
-      }
-    case 2:
-      if fieldTypeId == thrift.STRING {
-        if err := p.ReadField2(iprot); err != nil {
-          return err
-        }
-      } else {
-        if err := iprot.Skip(fieldTypeId); err != nil {
-          return err
-        }
-      }
-    default:
-      if err := iprot.Skip(fieldTypeId); err != nil {
-        return err
-      }
-    }
-    if err := iprot.ReadFieldEnd(); err != nil {
-      return err
-    }
-  }
-  if err := iprot.ReadStructEnd(); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
-  }
-  return nil
-}
-
-func (p *ConcatReply)  ReadField1(iprot thrift.TProtocol) error {
-  if v, err := iprot.ReadString(); err != nil {
-  return thrift.PrependError("error reading field 1: ", err)
-} else {
-  p.Value = v
-}
-  return nil
-}
-
-func (p *ConcatReply)  ReadField2(iprot thrift.TProtocol) error {
-  if v, err := iprot.ReadString(); err != nil {
-  return thrift.PrependError("error reading field 2: ", err)
-} else {
-  p.Err = v
-}
-  return nil
-}
-
-func (p *ConcatReply) Write(oprot thrift.TProtocol) error {
-  if err := oprot.WriteStructBegin("ConcatReply"); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) }
-  if p != nil {
-    if err := p.writeField1(oprot); err != nil { return err }
-    if err := p.writeField2(oprot); err != nil { return err }
-  }
-  if err := oprot.WriteFieldStop(); err != nil {
-    return thrift.PrependError("write field stop error: ", err) }
-  if err := oprot.WriteStructEnd(); err != nil {
-    return thrift.PrependError("write struct stop error: ", err) }
-  return nil
-}
-
-func (p *ConcatReply) writeField1(oprot thrift.TProtocol) (err error) {
-  if err := oprot.WriteFieldBegin("value", thrift.STRING, 1); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:value: ", p), err) }
-  if err := oprot.WriteString(string(p.Value)); err != nil {
-  return thrift.PrependError(fmt.Sprintf("%T.value (1) field write error: ", p), err) }
-  if err := oprot.WriteFieldEnd(); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T write field end error 1:value: ", p), err) }
-  return err
-}
-
-func (p *ConcatReply) writeField2(oprot thrift.TProtocol) (err error) {
-  if err := oprot.WriteFieldBegin("err", thrift.STRING, 2); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:err: ", p), err) }
-  if err := oprot.WriteString(string(p.Err)); err != nil {
-  return thrift.PrependError(fmt.Sprintf("%T.err (2) field write error: ", p), err) }
-  if err := oprot.WriteFieldEnd(); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T write field end error 2:err: ", p), err) }
-  return err
+	return p.Err
+}
+func (p *ConcatReply) Read(ctx context.Context, iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(ctx); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin(ctx)
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if fieldTypeId == thrift.STRING {
+				if err := p.ReadField1(ctx, iprot); err != nil {
+					return err
+				}
+			} else {
+				if err := iprot.Skip(ctx, fieldTypeId); err != nil {
+					return err
+				}
+			}
+		case 2:
+			if fieldTypeId == thrift.STRING {
+				if err := p.ReadField2(ctx, iprot); err != nil {
+					return err
+				}
+			} else {
+				if err := iprot.Skip(ctx, fieldTypeId); err != nil {
+					return err
+				}
+			}
+		default:
+			if err := iprot.Skip(ctx, fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(ctx); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(ctx); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	return nil
+}
+
+func (p *ConcatReply) ReadField1(ctx context.Context, iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadString(ctx); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		p.Value = v
+	}
+	return nil
+}
+
+func (p *ConcatReply) ReadField2(ctx context.Context, iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadString(ctx); err != nil {
+		return thrift.PrependError("error reading field 2: ", err)
+	} else {
+		p.Err = v
+	}
+	return nil
+}
+
+func (p *ConcatReply) Write(ctx context.Context, oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin(ctx, "ConcatReply"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if p != nil {
+		if err := p.writeField1(ctx, oprot); err != nil {
+			return err
+		}
+		if err := p.writeField2(ctx, oprot); err != nil {
+			return err
+		}
+	}
+	if err := oprot.WriteFieldStop(ctx); err != nil {
+		return thrift.PrependError("write field stop error: ", err)
+	}
+	if err := oprot.WriteStructEnd(ctx); err != nil {
+		return thrift.PrependError("write struct stop error: ", err)
+	}
+	return nil
+}
+
+func (p *ConcatReply) writeField1(ctx context.Context, oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin(ctx, "value", thrift.STRING, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:value: ", p), err)
+	}
+	if err := oprot.WriteString(ctx, string(p.Value)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.value (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(ctx); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:value: ", p), err)
+	}
+	return err
+}
+
+func (p *ConcatReply) writeField2(ctx context.Context, oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin(ctx, "err", thrift.STRING, 2); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:err: ", p), err)
+	}
+	if err := oprot.WriteString(ctx, string(p.Err)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.err (2) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(ctx); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 2:err: ", p), err)
+	}
+	return err
+}
+
+func (p *ConcatReply) Equals(other *ConcatReply) bool {
+	if p == other {
+		return true
+	} else if p == nil || other == nil {
+		return false
+	}
+	if p.Value != other.Value {
+		return false
+	}
+	if p.Err != other.Err {
+		return false
+	}
+	return true
 }
 
 func (p *ConcatReply) String() string {
-  if p == nil {
-    return "<nil>"
-  }
-  return fmt.Sprintf("ConcatReply(%+v)", *p)
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("ConcatReply(%+v)", *p)
 }
 
 type AddService interface {
-  // Parameters:
-  //  - A
-  //  - B
-  Sum(ctx context.Context, a int64, b int64) (r *SumReply, err error)
-  // Parameters:
-  //  - A
-  //  - B
-  Concat(ctx context.Context, a string, b string) (r *ConcatReply, err error)
+	// Parameters:
+	//  - A
+	//  - B
+	Sum(ctx context.Context, a int64, b int64) (_r *SumReply, _err error)
+	// Parameters:
+	//  - A
+	//  - B
+	Concat(ctx context.Context, a string, b string) (_r *ConcatReply, _err error)
 }
 
 type AddServiceClient struct {
-  c thrift.TClient
+	c    thrift.TClient
+	meta thrift.ResponseMeta
 }
 
 func NewAddServiceClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *AddServiceClient {
-  return &AddServiceClient{
-    c: thrift.NewTStandardClient(f.GetProtocol(t), f.GetProtocol(t)),
-  }
+	return &AddServiceClient{
+		c: thrift.NewTStandardClient(f.GetProtocol(t), f.GetProtocol(t)),
+	}
 }
 
 func NewAddServiceClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *AddServiceClient {
-  return &AddServiceClient{
-    c: thrift.NewTStandardClient(iprot, oprot),
-  }
+	return &AddServiceClient{
+		c: thrift.NewTStandardClient(iprot, oprot),
+	}
 }
 
 func NewAddServiceClient(c thrift.TClient) *AddServiceClient {
-  return &AddServiceClient{
-    c: c,
-  }
+	return &AddServiceClient{
+		c: c,
+	}
 }
 
 func (p *AddServiceClient) Client_() thrift.TClient {
-  return p.c
+	return p.c
+}
+
+func (p *AddServiceClient) LastResponseMeta_() thrift.ResponseMeta {
+	return p.meta
 }
+
+func (p *AddServiceClient) SetLastResponseMeta_(meta thrift.ResponseMeta) {
+	p.meta = meta
+}
+
 // Parameters:
 //  - A
 //  - B
-func (p *AddServiceClient) Sum(ctx context.Context, a int64, b int64) (r *SumReply, err error) {
-  var _args0 AddServiceSumArgs
-  _args0.A = a
-  _args0.B = b
-  var _result1 AddServiceSumResult
-  if err = p.Client_().Call(ctx, "Sum", &_args0, &_result1); err != nil {
-    return
-  }
-  return _result1.GetSuccess(), nil
+func (p *AddServiceClient) Sum(ctx context.Context, a int64, b int64) (_r *SumReply, _err error) {
+	var _args0 AddServiceSumArgs
+	_args0.A = a
+	_args0.B = b
+	var _result2 AddServiceSumResult
+	var _meta1 thrift.ResponseMeta
+	_meta1, _err = p.Client_().Call(ctx, "Sum", &_args0, &_result2)
+	p.SetLastResponseMeta_(_meta1)
+	if _err != nil {
+		return
+	}
+	return _result2.GetSuccess(), nil
 }
 
 // Parameters:
 //  - A
 //  - B
-func (p *AddServiceClient) Concat(ctx context.Context, a string, b string) (r *ConcatReply, err error) {
-  var _args2 AddServiceConcatArgs
-  _args2.A = a
-  _args2.B = b
-  var _result3 AddServiceConcatResult
-  if err = p.Client_().Call(ctx, "Concat", &_args2, &_result3); err != nil {
-    return
-  }
-  return _result3.GetSuccess(), nil
+func (p *AddServiceClient) Concat(ctx context.Context, a string, b string) (_r *ConcatReply, _err error) {
+	var _args3 AddServiceConcatArgs
+	_args3.A = a
+	_args3.B = b
+	var _result5 AddServiceConcatResult
+	var _meta4 thrift.ResponseMeta
+	_meta4, _err = p.Client_().Call(ctx, "Concat", &_args3, &_result5)
+	p.SetLastResponseMeta_(_meta4)
+	if _err != nil {
+		return
+	}
+	return _result5.GetSuccess(), nil
 }
 
 type AddServiceProcessor struct {
-  processorMap map[string]thrift.TProcessorFunction
-  handler AddService
+	processorMap map[string]thrift.TProcessorFunction
+	handler      AddService
 }
 
 func (p *AddServiceProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) {
-  p.processorMap[key] = processor
+	p.processorMap[key] = processor
 }
 
 func (p *AddServiceProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) {
-  processor, ok = p.processorMap[key]
-  return processor, ok
+	processor, ok = p.processorMap[key]
+	return processor, ok
 }
 
 func (p *AddServiceProcessor) ProcessorMap() map[string]thrift.TProcessorFunction {
-  return p.processorMap
+	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
+	self6 := &AddServiceProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)}
+	self6.processorMap["Sum"] = &addServiceProcessorSum{handler: handler}
+	self6.processorMap["Concat"] = &addServiceProcessorConcat{handler: handler}
+	return self6
 }
 
 func (p *AddServiceProcessor) Process(ctx context.Context, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
-  name, _, seqId, err := iprot.ReadMessageBegin()
-  if err != nil { return false, err }
-  if processor, ok := p.GetProcessorFunction(name); ok {
-    return processor.Process(ctx, seqId, iprot, oprot)
-  }
-  iprot.Skip(thrift.STRUCT)
-  iprot.ReadMessageEnd()
-  x5 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function " + name)
-  oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId)
-  x5.Write(oprot)
-  oprot.WriteMessageEnd()
-  oprot.Flush(ctx)
-  return false, x5
+	name, _, seqId, err2 := iprot.ReadMessageBegin(ctx)
+	if err2 != nil {
+		return false, thrift.WrapTException(err2)
+	}
+	if processor, ok := p.GetProcessorFunction(name); ok {
+		return processor.Process(ctx, seqId, iprot, oprot)
+	}
+	iprot.Skip(ctx, thrift.STRUCT)
+	iprot.ReadMessageEnd(ctx)
+	x7 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function "+name)
+	oprot.WriteMessageBegin(ctx, name, thrift.EXCEPTION, seqId)
+	x7.Write(ctx, oprot)
+	oprot.WriteMessageEnd(ctx)
+	oprot.Flush(ctx)
+	return false, x7
 
 }
 
 type addServiceProcessorSum struct {
-  handler AddService
+	handler AddService
 }
 
 func (p *addServiceProcessorSum) Process(ctx context.Context, seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
-  args := AddServiceSumArgs{}
-  if err = args.Read(iprot); err != nil {
-    iprot.ReadMessageEnd()
-    x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error())
-    oprot.WriteMessageBegin("Sum", thrift.EXCEPTION, seqId)
-    x.Write(oprot)
-    oprot.WriteMessageEnd()
-    oprot.Flush(ctx)
-    return false, err
-  }
-
-  iprot.ReadMessageEnd()
-  result := AddServiceSumResult{}
-var retval *SumReply
-  var err2 error
-  if retval, err2 = p.handler.Sum(ctx, args.A, args.B); err2 != nil {
-    x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing Sum: " + err2.Error())
-    oprot.WriteMessageBegin("Sum", thrift.EXCEPTION, seqId)
-    x.Write(oprot)
-    oprot.WriteMessageEnd()
-    oprot.Flush(ctx)
-    return true, err2
-  } else {
-    result.Success = retval
-}
-  if err2 = oprot.WriteMessageBegin("Sum", thrift.REPLY, seqId); err2 != nil {
-    err = err2
-  }
-  if err2 = result.Write(oprot); err == nil && err2 != nil {
-    err = err2
-  }
-  if err2 = oprot.WriteMessageEnd(); err == nil && err2 != nil {
-    err = err2
-  }
-  if err2 = oprot.Flush(ctx); err == nil && err2 != nil {
-    err = err2
-  }
-  if err != nil {
-    return
-  }
-  return true, err
+	args := AddServiceSumArgs{}
+	var err2 error
+	if err2 = args.Read(ctx, iprot); err2 != nil {
+		iprot.ReadMessageEnd(ctx)
+		x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err2.Error())
+		oprot.WriteMessageBegin(ctx, "Sum", thrift.EXCEPTION, seqId)
+		x.Write(ctx, oprot)
+		oprot.WriteMessageEnd(ctx)
+		oprot.Flush(ctx)
+		return false, thrift.WrapTException(err2)
+	}
+	iprot.ReadMessageEnd(ctx)
+
+	tickerCancel := func() {}
+	// Start a goroutine to do server side connectivity check.
+	if thrift.ServerConnectivityCheckInterval > 0 {
+		var cancel context.CancelFunc
+		ctx, cancel = context.WithCancel(ctx)
+		defer cancel()
+		var tickerCtx context.Context
+		tickerCtx, tickerCancel = context.WithCancel(context.Background())
+		defer tickerCancel()
+		go func(ctx context.Context, cancel context.CancelFunc) {
+			ticker := time.NewTicker(thrift.ServerConnectivityCheckInterval)
+			defer ticker.Stop()
+			for {
+				select {
+				case <-ctx.Done():
+					return
+				case <-ticker.C:
+					if !iprot.Transport().IsOpen() {
+						cancel()
+						return
+					}
+				}
+			}
+		}(tickerCtx, cancel)
+	}
+
+	result := AddServiceSumResult{}
+	var retval *SumReply
+	if retval, err2 = p.handler.Sum(ctx, args.A, args.B); err2 != nil {
+		tickerCancel()
+		if err2 == thrift.ErrAbandonRequest {
+			return false, thrift.WrapTException(err2)
+		}
+		x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing Sum: "+err2.Error())
+		oprot.WriteMessageBegin(ctx, "Sum", thrift.EXCEPTION, seqId)
+		x.Write(ctx, oprot)
+		oprot.WriteMessageEnd(ctx)
+		oprot.Flush(ctx)
+		return true, thrift.WrapTException(err2)
+	} else {
+		result.Success = retval
+	}
+	tickerCancel()
+	if err2 = oprot.WriteMessageBegin(ctx, "Sum", thrift.REPLY, seqId); err2 != nil {
+		err = thrift.WrapTException(err2)
+	}
+	if err2 = result.Write(ctx, oprot); err == nil && err2 != nil {
+		err = thrift.WrapTException(err2)
+	}
+	if err2 = oprot.WriteMessageEnd(ctx); err == nil && err2 != nil {
+		err = thrift.WrapTException(err2)
+	}
+	if err2 = oprot.Flush(ctx); err == nil && err2 != nil {
+		err = thrift.WrapTException(err2)
+	}
+	if err != nil {
+		return
+	}
+	return true, err
 }
 
 type addServiceProcessorConcat struct {
-  handler AddService
+	handler AddService
 }
 
 func (p *addServiceProcessorConcat) Process(ctx context.Context, seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
-  args := AddServiceConcatArgs{}
-  if err = args.Read(iprot); err != nil {
-    iprot.ReadMessageEnd()
-    x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error())
-    oprot.WriteMessageBegin("Concat", thrift.EXCEPTION, seqId)
-    x.Write(oprot)
-    oprot.WriteMessageEnd()
-    oprot.Flush(ctx)
-    return false, err
-  }
-
-  iprot.ReadMessageEnd()
-  result := AddServiceConcatResult{}
-var retval *ConcatReply
-  var err2 error
-  if retval, err2 = p.handler.Concat(ctx, args.A, args.B); err2 != nil {
-    x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing Concat: " + err2.Error())
-    oprot.WriteMessageBegin("Concat", thrift.EXCEPTION, seqId)
-    x.Write(oprot)
-    oprot.WriteMessageEnd()
-    oprot.Flush(ctx)
-    return true, err2
-  } else {
-    result.Success = retval
-}
-  if err2 = oprot.WriteMessageBegin("Concat", thrift.REPLY, seqId); err2 != nil {
-    err = err2
-  }
-  if err2 = result.Write(oprot); err == nil && err2 != nil {
-    err = err2
-  }
-  if err2 = oprot.WriteMessageEnd(); err == nil && err2 != nil {
-    err = err2
-  }
-  if err2 = oprot.Flush(ctx); err == nil && err2 != nil {
-    err = err2
-  }
-  if err != nil {
-    return
-  }
-  return true, err
+	args := AddServiceConcatArgs{}
+	var err2 error
+	if err2 = args.Read(ctx, iprot); err2 != nil {
+		iprot.ReadMessageEnd(ctx)
+		x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err2.Error())
+		oprot.WriteMessageBegin(ctx, "Concat", thrift.EXCEPTION, seqId)
+		x.Write(ctx, oprot)
+		oprot.WriteMessageEnd(ctx)
+		oprot.Flush(ctx)
+		return false, thrift.WrapTException(err2)
+	}
+	iprot.ReadMessageEnd(ctx)
+
+	tickerCancel := func() {}
+	// Start a goroutine to do server side connectivity check.
+	if thrift.ServerConnectivityCheckInterval > 0 {
+		var cancel context.CancelFunc
+		ctx, cancel = context.WithCancel(ctx)
+		defer cancel()
+		var tickerCtx context.Context
+		tickerCtx, tickerCancel = context.WithCancel(context.Background())
+		defer tickerCancel()
+		go func(ctx context.Context, cancel context.CancelFunc) {
+			ticker := time.NewTicker(thrift.ServerConnectivityCheckInterval)
+			defer ticker.Stop()
+			for {
+				select {
+				case <-ctx.Done():
+					return
+				case <-ticker.C:
+					if !iprot.Transport().IsOpen() {
+						cancel()
+						return
+					}
+				}
+			}
+		}(tickerCtx, cancel)
+	}
+
+	result := AddServiceConcatResult{}
+	var retval *ConcatReply
+	if retval, err2 = p.handler.Concat(ctx, args.A, args.B); err2 != nil {
+		tickerCancel()
+		if err2 == thrift.ErrAbandonRequest {
+			return false, thrift.WrapTException(err2)
+		}
+		x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing Concat: "+err2.Error())
+		oprot.WriteMessageBegin(ctx, "Concat", thrift.EXCEPTION, seqId)
+		x.Write(ctx, oprot)
+		oprot.WriteMessageEnd(ctx)
+		oprot.Flush(ctx)
+		return true, thrift.WrapTException(err2)
+	} else {
+		result.Success = retval
+	}
+	tickerCancel()
+	if err2 = oprot.WriteMessageBegin(ctx, "Concat", thrift.REPLY, seqId); err2 != nil {
+		err = thrift.WrapTException(err2)
+	}
+	if err2 = result.Write(ctx, oprot); err == nil && err2 != nil {
+		err = thrift.WrapTException(err2)
+	}
+	if err2 = oprot.WriteMessageEnd(ctx); err == nil && err2 != nil {
+		err = thrift.WrapTException(err2)
+	}
+	if err2 = oprot.Flush(ctx); err == nil && err2 != nil {
+		err = thrift.WrapTException(err2)
+	}
+	if err != nil {
+		return
+	}
+	return true, err
 }
 
-
 // HELPER FUNCTIONS AND STRUCTURES
 
 // Attributes:
 //  - A
 //  - B
 type AddServiceSumArgs struct {
-  A int64 `thrift:"a,1" db:"a" json:"a"`
-  B int64 `thrift:"b,2" db:"b" json:"b"`
+	A int64 `thrift:"a,1" db:"a" json:"a"`
+	B int64 `thrift:"b,2" db:"b" json:"b"`
 }
 
 func NewAddServiceSumArgs() *AddServiceSumArgs {
-  return &AddServiceSumArgs{}
+	return &AddServiceSumArgs{}
 }
 
-
 func (p *AddServiceSumArgs) GetA() int64 {
-  return p.A
+	return p.A
 }
 
 func (p *AddServiceSumArgs) GetB() int64 {
-  return p.B
-}
-func (p *AddServiceSumArgs) Read(iprot thrift.TProtocol) error {
-  if _, err := iprot.ReadStructBegin(); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
-  }
-
-
-  for {
-    _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
-    if err != nil {
-      return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
-    }
-    if fieldTypeId == thrift.STOP { break; }
-    switch fieldId {
-    case 1:
-      if fieldTypeId == thrift.I64 {
-        if err := p.ReadField1(iprot); err != nil {
-          return err
-        }
-      } else {
-        if err := iprot.Skip(fieldTypeId); err != nil {
-          return err
-        }
-      }
-    case 2:
-      if fieldTypeId == thrift.I64 {
-        if err := p.ReadField2(iprot); err != nil {
-          return err
-        }
-      } else {
-        if err := iprot.Skip(fieldTypeId); err != nil {
-          return err
-        }
-      }
-    default:
-      if err := iprot.Skip(fieldTypeId); err != nil {
-        return err
-      }
-    }
-    if err := iprot.ReadFieldEnd(); err != nil {
-      return err
-    }
-  }
-  if err := iprot.ReadStructEnd(); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
-  }
-  return nil
-}
-
-func (p *AddServiceSumArgs)  ReadField1(iprot thrift.TProtocol) error {
-  if v, err := iprot.ReadI64(); err != nil {
-  return thrift.PrependError("error reading field 1: ", err)
-} else {
-  p.A = v
-}
-  return nil
-}
-
-func (p *AddServiceSumArgs)  ReadField2(iprot thrift.TProtocol) error {
-  if v, err := iprot.ReadI64(); err != nil {
-  return thrift.PrependError("error reading field 2: ", err)
-} else {
-  p.B = v
-}
-  return nil
-}
-
-func (p *AddServiceSumArgs) Write(oprot thrift.TProtocol) error {
-  if err := oprot.WriteStructBegin("Sum_args"); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) }
-  if p != nil {
-    if err := p.writeField1(oprot); err != nil { return err }
-    if err := p.writeField2(oprot); err != nil { return err }
-  }
-  if err := oprot.WriteFieldStop(); err != nil {
-    return thrift.PrependError("write field stop error: ", err) }
-  if err := oprot.WriteStructEnd(); err != nil {
-    return thrift.PrependError("write struct stop error: ", err) }
-  return nil
-}
-
-func (p *AddServiceSumArgs) writeField1(oprot thrift.TProtocol) (err error) {
-  if err := oprot.WriteFieldBegin("a", thrift.I64, 1); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:a: ", p), err) }
-  if err := oprot.WriteI64(int64(p.A)); err != nil {
-  return thrift.PrependError(fmt.Sprintf("%T.a (1) field write error: ", p), err) }
-  if err := oprot.WriteFieldEnd(); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T write field end error 1:a: ", p), err) }
-  return err
-}
-
-func (p *AddServiceSumArgs) writeField2(oprot thrift.TProtocol) (err error) {
-  if err := oprot.WriteFieldBegin("b", thrift.I64, 2); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:b: ", p), err) }
-  if err := oprot.WriteI64(int64(p.B)); err != nil {
-  return thrift.PrependError(fmt.Sprintf("%T.b (2) field write error: ", p), err) }
-  if err := oprot.WriteFieldEnd(); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T write field end error 2:b: ", p), err) }
-  return err
+	return p.B
+}
+func (p *AddServiceSumArgs) Read(ctx context.Context, iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(ctx); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin(ctx)
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if fieldTypeId == thrift.I64 {
+				if err := p.ReadField1(ctx, iprot); err != nil {
+					return err
+				}
+			} else {
+				if err := iprot.Skip(ctx, fieldTypeId); err != nil {
+					return err
+				}
+			}
+		case 2:
+			if fieldTypeId == thrift.I64 {
+				if err := p.ReadField2(ctx, iprot); err != nil {
+					return err
+				}
+			} else {
+				if err := iprot.Skip(ctx, fieldTypeId); err != nil {
+					return err
+				}
+			}
+		default:
+			if err := iprot.Skip(ctx, fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(ctx); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(ctx); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	return nil
+}
+
+func (p *AddServiceSumArgs) ReadField1(ctx context.Context, iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(ctx); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		p.A = v
+	}
+	return nil
+}
+
+func (p *AddServiceSumArgs) ReadField2(ctx context.Context, iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(ctx); err != nil {
+		return thrift.PrependError("error reading field 2: ", err)
+	} else {
+		p.B = v
+	}
+	return nil
+}
+
+func (p *AddServiceSumArgs) Write(ctx context.Context, oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin(ctx, "Sum_args"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if p != nil {
+		if err := p.writeField1(ctx, oprot); err != nil {
+			return err
+		}
+		if err := p.writeField2(ctx, oprot); err != nil {
+			return err
+		}
+	}
+	if err := oprot.WriteFieldStop(ctx); err != nil {
+		return thrift.PrependError("write field stop error: ", err)
+	}
+	if err := oprot.WriteStructEnd(ctx); err != nil {
+		return thrift.PrependError("write struct stop error: ", err)
+	}
+	return nil
+}
+
+func (p *AddServiceSumArgs) writeField1(ctx context.Context, oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin(ctx, "a", thrift.I64, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:a: ", p), err)
+	}
+	if err := oprot.WriteI64(ctx, int64(p.A)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.a (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(ctx); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:a: ", p), err)
+	}
+	return err
+}
+
+func (p *AddServiceSumArgs) writeField2(ctx context.Context, oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin(ctx, "b", thrift.I64, 2); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:b: ", p), err)
+	}
+	if err := oprot.WriteI64(ctx, int64(p.B)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.b (2) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(ctx); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 2:b: ", p), err)
+	}
+	return err
 }
 
 func (p *AddServiceSumArgs) String() string {
-  if p == nil {
-    return "<nil>"
-  }
-  return fmt.Sprintf("AddServiceSumArgs(%+v)", *p)
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("AddServiceSumArgs(%+v)", *p)
 }
 
 // Attributes:
 //  - Success
 type AddServiceSumResult struct {
-  Success *SumReply `thrift:"success,0" db:"success" json:"success,omitempty"`
+	Success *SumReply `thrift:"success,0" db:"success" json:"success,omitempty"`
 }
 
 func NewAddServiceSumResult() *AddServiceSumResult {
-  return &AddServiceSumResult{}
+	return &AddServiceSumResult{}
 }
 
 var AddServiceSumResult_Success_DEFAULT *SumReply
+
 func (p *AddServiceSumResult) GetSuccess() *SumReply {
-  if !p.IsSetSuccess() {
-    return AddServiceSumResult_Success_DEFAULT
-  }
-return p.Success
+	if !p.IsSetSuccess() {
+		return AddServiceSumResult_Success_DEFAULT
+	}
+	return p.Success
 }
 func (p *AddServiceSumResult) IsSetSuccess() bool {
-  return p.Success != nil
-}
-
-func (p *AddServiceSumResult) Read(iprot thrift.TProtocol) error {
-  if _, err := iprot.ReadStructBegin(); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
-  }
-
-
-  for {
-    _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
-    if err != nil {
-      return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
-    }
-    if fieldTypeId == thrift.STOP { break; }
-    switch fieldId {
-    case 0:
-      if fieldTypeId == thrift.STRUCT {
-        if err := p.ReadField0(iprot); err != nil {
-          return err
-        }
-      } else {
-        if err := iprot.Skip(fieldTypeId); err != nil {
-          return err
-        }
-      }
-    default:
-      if err := iprot.Skip(fieldTypeId); err != nil {
-        return err
-      }
-    }
-    if err := iprot.ReadFieldEnd(); err != nil {
-      return err
-    }
-  }
-  if err := iprot.ReadStructEnd(); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
-  }
-  return nil
-}
-
-func (p *AddServiceSumResult)  ReadField0(iprot thrift.TProtocol) error {
-  p.Success = &SumReply{}
-  if err := p.Success.Read(iprot); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Success), err)
-  }
-  return nil
-}
-
-func (p *AddServiceSumResult) Write(oprot thrift.TProtocol) error {
-  if err := oprot.WriteStructBegin("Sum_result"); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) }
-  if p != nil {
-    if err := p.writeField0(oprot); err != nil { return err }
-  }
-  if err := oprot.WriteFieldStop(); err != nil {
-    return thrift.PrependError("write field stop error: ", err) }
-  if err := oprot.WriteStructEnd(); err != nil {
-    return thrift.PrependError("write struct stop error: ", err) }
-  return nil
-}
-
-func (p *AddServiceSumResult) writeField0(oprot thrift.TProtocol) (err error) {
-  if p.IsSetSuccess() {
-    if err := oprot.WriteFieldBegin("success", thrift.STRUCT, 0); err != nil {
-      return thrift.PrependError(fmt.Sprintf("%T write field begin error 0:success: ", p), err) }
-    if err := p.Success.Write(oprot); err != nil {
-      return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Success), err)
-    }
-    if err := oprot.WriteFieldEnd(); err != nil {
-      return thrift.PrependError(fmt.Sprintf("%T write field end error 0:success: ", p), err) }
-  }
-  return err
+	return p.Success != nil
+}
+
+func (p *AddServiceSumResult) Read(ctx context.Context, iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(ctx); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin(ctx)
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 0:
+			if fieldTypeId == thrift.STRUCT {
+				if err := p.ReadField0(ctx, iprot); err != nil {
+					return err
+				}
+			} else {
+				if err := iprot.Skip(ctx, fieldTypeId); err != nil {
+					return err
+				}
+			}
+		default:
+			if err := iprot.Skip(ctx, fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(ctx); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(ctx); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	return nil
+}
+
+func (p *AddServiceSumResult) ReadField0(ctx context.Context, iprot thrift.TProtocol) error {
+	p.Success = &SumReply{}
+	if err := p.Success.Read(ctx, iprot); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Success), err)
+	}
+	return nil
+}
+
+func (p *AddServiceSumResult) Write(ctx context.Context, oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin(ctx, "Sum_result"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if p != nil {
+		if err := p.writeField0(ctx, oprot); err != nil {
+			return err
+		}
+	}
+	if err := oprot.WriteFieldStop(ctx); err != nil {
+		return thrift.PrependError("write field stop error: ", err)
+	}
+	if err := oprot.WriteStructEnd(ctx); err != nil {
+		return thrift.PrependError("write struct stop error: ", err)
+	}
+	return nil
+}
+
+func (p *AddServiceSumResult) writeField0(ctx context.Context, oprot thrift.TProtocol) (err error) {
+	if p.IsSetSuccess() {
+		if err := oprot.WriteFieldBegin(ctx, "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(ctx, oprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Success), err)
+		}
+		if err := oprot.WriteFieldEnd(ctx); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 0:success: ", p), err)
+		}
+	}
+	return err
 }
 
 func (p *AddServiceSumResult) String() string {
-  if p == nil {
-    return "<nil>"
-  }
-  return fmt.Sprintf("AddServiceSumResult(%+v)", *p)
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("AddServiceSumResult(%+v)", *p)
 }
 
 // Attributes:
 //  - A
 //  - B
 type AddServiceConcatArgs struct {
-  A string `thrift:"a,1" db:"a" json:"a"`
-  B string `thrift:"b,2" db:"b" json:"b"`
+	A string `thrift:"a,1" db:"a" json:"a"`
+	B string `thrift:"b,2" db:"b" json:"b"`
 }
 
 func NewAddServiceConcatArgs() *AddServiceConcatArgs {
-  return &AddServiceConcatArgs{}
+	return &AddServiceConcatArgs{}
 }
 
-
 func (p *AddServiceConcatArgs) GetA() string {
-  return p.A
+	return p.A
 }
 
 func (p *AddServiceConcatArgs) GetB() string {
-  return p.B
-}
-func (p *AddServiceConcatArgs) Read(iprot thrift.TProtocol) error {
-  if _, err := iprot.ReadStructBegin(); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
-  }
-
-
-  for {
-    _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
-    if err != nil {
-      return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
-    }
-    if fieldTypeId == thrift.STOP { break; }
-    switch fieldId {
-    case 1:
-      if fieldTypeId == thrift.STRING {
-        if err := p.ReadField1(iprot); err != nil {
-          return err
-        }
-      } else {
-        if err := iprot.Skip(fieldTypeId); err != nil {
-          return err
-        }
-      }
-    case 2:
-      if fieldTypeId == thrift.STRING {
-        if err := p.ReadField2(iprot); err != nil {
-          return err
-        }
-      } else {
-        if err := iprot.Skip(fieldTypeId); err != nil {
-          return err
-        }
-      }
-    default:
-      if err := iprot.Skip(fieldTypeId); err != nil {
-        return err
-      }
-    }
-    if err := iprot.ReadFieldEnd(); err != nil {
-      return err
-    }
-  }
-  if err := iprot.ReadStructEnd(); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
-  }
-  return nil
-}
-
-func (p *AddServiceConcatArgs)  ReadField1(iprot thrift.TProtocol) error {
-  if v, err := iprot.ReadString(); err != nil {
-  return thrift.PrependError("error reading field 1: ", err)
-} else {
-  p.A = v
-}
-  return nil
-}
-
-func (p *AddServiceConcatArgs)  ReadField2(iprot thrift.TProtocol) error {
-  if v, err := iprot.ReadString(); err != nil {
-  return thrift.PrependError("error reading field 2: ", err)
-} else {
-  p.B = v
-}
-  return nil
-}
-
-func (p *AddServiceConcatArgs) Write(oprot thrift.TProtocol) error {
-  if err := oprot.WriteStructBegin("Concat_args"); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) }
-  if p != nil {
-    if err := p.writeField1(oprot); err != nil { return err }
-    if err := p.writeField2(oprot); err != nil { return err }
-  }
-  if err := oprot.WriteFieldStop(); err != nil {
-    return thrift.PrependError("write field stop error: ", err) }
-  if err := oprot.WriteStructEnd(); err != nil {
-    return thrift.PrependError("write struct stop error: ", err) }
-  return nil
-}
-
-func (p *AddServiceConcatArgs) writeField1(oprot thrift.TProtocol) (err error) {
-  if err := oprot.WriteFieldBegin("a", thrift.STRING, 1); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:a: ", p), err) }
-  if err := oprot.WriteString(string(p.A)); err != nil {
-  return thrift.PrependError(fmt.Sprintf("%T.a (1) field write error: ", p), err) }
-  if err := oprot.WriteFieldEnd(); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T write field end error 1:a: ", p), err) }
-  return err
-}
-
-func (p *AddServiceConcatArgs) writeField2(oprot thrift.TProtocol) (err error) {
-  if err := oprot.WriteFieldBegin("b", thrift.STRING, 2); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:b: ", p), err) }
-  if err := oprot.WriteString(string(p.B)); err != nil {
-  return thrift.PrependError(fmt.Sprintf("%T.b (2) field write error: ", p), err) }
-  if err := oprot.WriteFieldEnd(); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T write field end error 2:b: ", p), err) }
-  return err
+	return p.B
+}
+func (p *AddServiceConcatArgs) Read(ctx context.Context, iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(ctx); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin(ctx)
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if fieldTypeId == thrift.STRING {
+				if err := p.ReadField1(ctx, iprot); err != nil {
+					return err
+				}
+			} else {
+				if err := iprot.Skip(ctx, fieldTypeId); err != nil {
+					return err
+				}
+			}
+		case 2:
+			if fieldTypeId == thrift.STRING {
+				if err := p.ReadField2(ctx, iprot); err != nil {
+					return err
+				}
+			} else {
+				if err := iprot.Skip(ctx, fieldTypeId); err != nil {
+					return err
+				}
+			}
+		default:
+			if err := iprot.Skip(ctx, fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(ctx); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(ctx); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	return nil
+}
+
+func (p *AddServiceConcatArgs) ReadField1(ctx context.Context, iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadString(ctx); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		p.A = v
+	}
+	return nil
+}
+
+func (p *AddServiceConcatArgs) ReadField2(ctx context.Context, iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadString(ctx); err != nil {
+		return thrift.PrependError("error reading field 2: ", err)
+	} else {
+		p.B = v
+	}
+	return nil
+}
+
+func (p *AddServiceConcatArgs) Write(ctx context.Context, oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin(ctx, "Concat_args"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if p != nil {
+		if err := p.writeField1(ctx, oprot); err != nil {
+			return err
+		}
+		if err := p.writeField2(ctx, oprot); err != nil {
+			return err
+		}
+	}
+	if err := oprot.WriteFieldStop(ctx); err != nil {
+		return thrift.PrependError("write field stop error: ", err)
+	}
+	if err := oprot.WriteStructEnd(ctx); err != nil {
+		return thrift.PrependError("write struct stop error: ", err)
+	}
+	return nil
+}
+
+func (p *AddServiceConcatArgs) writeField1(ctx context.Context, oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin(ctx, "a", thrift.STRING, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:a: ", p), err)
+	}
+	if err := oprot.WriteString(ctx, string(p.A)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.a (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(ctx); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:a: ", p), err)
+	}
+	return err
+}
+
+func (p *AddServiceConcatArgs) writeField2(ctx context.Context, oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin(ctx, "b", thrift.STRING, 2); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:b: ", p), err)
+	}
+	if err := oprot.WriteString(ctx, string(p.B)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.b (2) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(ctx); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 2:b: ", p), err)
+	}
+	return err
 }
 
 func (p *AddServiceConcatArgs) String() string {
-  if p == nil {
-    return "<nil>"
-  }
-  return fmt.Sprintf("AddServiceConcatArgs(%+v)", *p)
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("AddServiceConcatArgs(%+v)", *p)
 }
 
 // Attributes:
 //  - Success
 type AddServiceConcatResult struct {
-  Success *ConcatReply `thrift:"success,0" db:"success" json:"success,omitempty"`
+	Success *ConcatReply `thrift:"success,0" db:"success" json:"success,omitempty"`
 }
 
 func NewAddServiceConcatResult() *AddServiceConcatResult {
-  return &AddServiceConcatResult{}
+	return &AddServiceConcatResult{}
 }
 
 var AddServiceConcatResult_Success_DEFAULT *ConcatReply
+
 func (p *AddServiceConcatResult) GetSuccess() *ConcatReply {
-  if !p.IsSetSuccess() {
-    return AddServiceConcatResult_Success_DEFAULT
-  }
-return p.Success
+	if !p.IsSetSuccess() {
+		return AddServiceConcatResult_Success_DEFAULT
+	}
+	return p.Success
 }
 func (p *AddServiceConcatResult) IsSetSuccess() bool {
-  return p.Success != nil
-}
-
-func (p *AddServiceConcatResult) Read(iprot thrift.TProtocol) error {
-  if _, err := iprot.ReadStructBegin(); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
-  }
-
-
-  for {
-    _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
-    if err != nil {
-      return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
-    }
-    if fieldTypeId == thrift.STOP { break; }
-    switch fieldId {
-    case 0:
-      if fieldTypeId == thrift.STRUCT {
-        if err := p.ReadField0(iprot); err != nil {
-          return err
-        }
-      } else {
-        if err := iprot.Skip(fieldTypeId); err != nil {
-          return err
-        }
-      }
-    default:
-      if err := iprot.Skip(fieldTypeId); err != nil {
-        return err
-      }
-    }
-    if err := iprot.ReadFieldEnd(); err != nil {
-      return err
-    }
-  }
-  if err := iprot.ReadStructEnd(); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
-  }
-  return nil
-}
-
-func (p *AddServiceConcatResult)  ReadField0(iprot thrift.TProtocol) error {
-  p.Success = &ConcatReply{}
-  if err := p.Success.Read(iprot); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Success), err)
-  }
-  return nil
-}
-
-func (p *AddServiceConcatResult) Write(oprot thrift.TProtocol) error {
-  if err := oprot.WriteStructBegin("Concat_result"); err != nil {
-    return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) }
-  if p != nil {
-    if err := p.writeField0(oprot); err != nil { return err }
-  }
-  if err := oprot.WriteFieldStop(); err != nil {
-    return thrift.PrependError("write field stop error: ", err) }
-  if err := oprot.WriteStructEnd(); err != nil {
-    return thrift.PrependError("write struct stop error: ", err) }
-  return nil
-}
-
-func (p *AddServiceConcatResult) writeField0(oprot thrift.TProtocol) (err error) {
-  if p.IsSetSuccess() {
-    if err := oprot.WriteFieldBegin("success", thrift.STRUCT, 0); err != nil {
-      return thrift.PrependError(fmt.Sprintf("%T write field begin error 0:success: ", p), err) }
-    if err := p.Success.Write(oprot); err != nil {
-      return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Success), err)
-    }
-    if err := oprot.WriteFieldEnd(); err != nil {
-      return thrift.PrependError(fmt.Sprintf("%T write field end error 0:success: ", p), err) }
-  }
-  return err
+	return p.Success != nil
+}
+
+func (p *AddServiceConcatResult) Read(ctx context.Context, iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(ctx); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin(ctx)
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 0:
+			if fieldTypeId == thrift.STRUCT {
+				if err := p.ReadField0(ctx, iprot); err != nil {
+					return err
+				}
+			} else {
+				if err := iprot.Skip(ctx, fieldTypeId); err != nil {
+					return err
+				}
+			}
+		default:
+			if err := iprot.Skip(ctx, fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(ctx); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(ctx); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	return nil
+}
+
+func (p *AddServiceConcatResult) ReadField0(ctx context.Context, iprot thrift.TProtocol) error {
+	p.Success = &ConcatReply{}
+	if err := p.Success.Read(ctx, iprot); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Success), err)
+	}
+	return nil
+}
+
+func (p *AddServiceConcatResult) Write(ctx context.Context, oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin(ctx, "Concat_result"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if p != nil {
+		if err := p.writeField0(ctx, oprot); err != nil {
+			return err
+		}
+	}
+	if err := oprot.WriteFieldStop(ctx); err != nil {
+		return thrift.PrependError("write field stop error: ", err)
+	}
+	if err := oprot.WriteStructEnd(ctx); err != nil {
+		return thrift.PrependError("write struct stop error: ", err)
+	}
+	return nil
+}
+
+func (p *AddServiceConcatResult) writeField0(ctx context.Context, oprot thrift.TProtocol) (err error) {
+	if p.IsSetSuccess() {
+		if err := oprot.WriteFieldBegin(ctx, "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(ctx, oprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Success), err)
+		}
+		if err := oprot.WriteFieldEnd(ctx); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 0:success: ", p), err)
+		}
+	}
+	return err
 }
 
 func (p *AddServiceConcatResult) String() string {
-  if p == nil {
-    return "<nil>"
-  }
-  return fmt.Sprintf("AddServiceConcatResult(%+v)", *p)
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("AddServiceConcatResult(%+v)", *p)
 }
-
-
diff --git a/go.mod b/go.mod
index 1d66e82..50ac0c4 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,7 @@ go 1.13
 require (
 	github.com/VividCortex/gohistogram v1.0.0
 	github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5
-	github.com/apache/thrift v0.13.0
+	github.com/apache/thrift v0.14.1
 	github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a
 	github.com/aws/aws-lambda-go v1.13.3
 	github.com/aws/aws-sdk-go v1.27.0
@@ -21,7 +21,8 @@ require (
 	github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8 // indirect
 	github.com/go-logfmt/logfmt v0.5.0
 	github.com/go-stack/stack v1.8.0
-	github.com/golang/protobuf v1.3.2
+	github.com/golang/protobuf v1.5.2
+	github.com/google/btree v1.0.0 // indirect
 	github.com/gorilla/mux v1.7.3
 	github.com/hashicorp/consul/api v1.3.0
 	github.com/hashicorp/go-version v1.2.0 // indirect
@@ -29,33 +30,35 @@ require (
 	github.com/hudl/fargo v1.3.0
 	github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d
 	github.com/lightstep/lightstep-tracer-go v0.22.0
-	github.com/nats-io/nats-server/v2 v2.1.2
-	github.com/nats-io/nats.go v1.9.1
+	github.com/nats-io/nats-server/v2 v2.2.6
+	github.com/nats-io/nats.go v1.11.0
 	github.com/oklog/oklog v0.3.2
 	github.com/oklog/run v1.0.0 // indirect
 	github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 // indirect
 	github.com/opentracing/basictracer-go v1.0.0 // indirect
-	github.com/opentracing/opentracing-go v1.1.0
+	github.com/opentracing/opentracing-go v1.2.0
 	github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5
 	github.com/openzipkin/zipkin-go v0.2.2
 	github.com/pact-foundation/pact-go v1.0.4
 	github.com/pborman/uuid v1.2.0
 	github.com/performancecopilot/speed v3.0.0+incompatible
-	github.com/pkg/errors v0.8.1
-	github.com/prometheus/client_golang v1.3.0
+	github.com/pkg/errors v0.9.1
+	github.com/prometheus/client_golang v1.11.0
 	github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da
-	github.com/sirupsen/logrus v1.4.2
+	github.com/sirupsen/logrus v1.6.0
 	github.com/smartystreets/goconvey v1.6.4 // indirect
 	github.com/sony/gobreaker v0.4.1
 	github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271
 	github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a
-	go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738
+	go.etcd.io/etcd/client/pkg/v3 v3.5.0
+	go.etcd.io/etcd/client/v2 v2.305.0
+	go.etcd.io/etcd/client/v3 v3.5.0
 	go.opencensus.io v0.22.3
-	go.uber.org/zap v1.13.0
-	golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
-	golang.org/x/time v0.0.0-20191024005414-555d28b269f0
-	golang.org/x/tools v0.0.0-20200103221440-774c71fcf114
-	google.golang.org/grpc v1.26.0
+	go.uber.org/zap v1.17.0
+	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
+	golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1
+	golang.org/x/tools v0.1.2
+	google.golang.org/grpc v1.38.0
 	gopkg.in/gcfg.v1 v1.2.3 // indirect
 	gopkg.in/warnings.v0 v0.1.2 // indirect
 	sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0
diff --git a/go.sum b/go.sum
index 9a80e3e..e6da7e4 100644
--- a/go.sum
+++ b/go.sum
@@ -1,5 +1,5 @@
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
+cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw=
 github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
@@ -15,8 +15,10 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/apache/thrift v0.13.0 h1:5hryIiq9gtn+MiLVn0wP37kb/uTeRZgN08WoCsAhIhI=
-github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
+github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
+github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
+github.com/apache/thrift v0.14.1 h1:Yh8v0hpCj63p5edXOLaqTJW0IJ1p+eMW6+YSOqw1d6s=
+github.com/apache/thrift v0.14.1/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
 github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
 github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I=
 github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
@@ -44,32 +46,31 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
 github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec h1:EdRZT3IeKQmfCSrgo8SZ8V3MEnskuJP0wCYNpe+aiXo=
 github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
-github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa h1:OaNxuTZr7kxeODyLWsRMC+OD03aFUH+mW6r2d+MWa5Y=
-github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
 github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w=
 github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
-github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY=
-github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
-github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 h1:u9SHYsPQNyt5tgDm3YN7+9dYrpK96E5wFilTFWIDZOM=
-github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
-github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf h1:CAKfRE2YtTUIjjh1bkBtyYFaUT/WmOqsJjgtihT0vMI=
-github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
+github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
+github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
+github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
+github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
-github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
-github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4 h1:qk/FSDDxo05wdJH28W+p5yivv7LuLYLRXPPD8KQCtZs=
-github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
 github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
 github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
 github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
 github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
 github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
 github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
 github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db h1:gb2Z18BhTPJPpLQWj4T+rfKHYCHxRHCtRxhKKjRidVw=
@@ -81,6 +82,7 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
 github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4=
@@ -90,48 +92,56 @@ github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNI
 github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
 github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
-github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
 github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
-github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I=
 github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
 github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
 github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
-github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw=
 github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
 github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
-github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
 github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
 github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
 github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
-github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c h1:Lh2aW+HnU2Nbe1gqD9SOJLJxW1jBMmQOktN2acDyJk8=
-github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
-github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg=
-github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
-github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
-github.com/grpc-ecosystem/grpc-gateway v1.9.5 h1:UImYN5qQ8tuGpGE16ZmjvcTtTw24zw1QAp/SlnNrZhI=
-github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
+github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
 github.com/hashicorp/consul/api v1.3.0 h1:HXNYlRkkM/t+Y/Yhxtwcy02dlYwIaoxzvxPnS+cqy78=
 github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
 github.com/hashicorp/consul/sdk v0.3.0 h1:UOxjlb4xVNF93jak1mzzoBatyFju9nrkxpVwIp/QqxQ=
@@ -171,24 +181,27 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/hudl/fargo v1.3.0 h1:0U6+BtN6LhaYuTnIJq4Wyq5cpn6O2kWrxAtcqBmYY6w=
 github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
-github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
 github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d h1:/WZQPMZNsjZ7IlCpsLGdQBINg5bxKQ1K1sh6awxLtkA=
 github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
 github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
 github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
-github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo=
-github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
+github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
-github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok=
-github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
+github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
 github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
+github.com/klauspost/compress v1.11.12 h1:famVnQVu7QwryBN4jNseQdUKES71ZAOnB6UQQJPZvqk=
+github.com/klauspost/compress v1.11.12/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
+github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
 github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -202,12 +215,12 @@ github.com/lightstep/lightstep-tracer-go v0.22.0/go.mod h1:RnONwHKg89zYPmF+Uig5P
 github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
 github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
 github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
 github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
 github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA=
 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
+github.com/minio/highwayhash v1.0.1 h1:dZ6IIu8Z14VlC0VpfKofAhCy74wu/Qb5gcn52yWoz/0=
+github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
 github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
 github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0=
 github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@@ -225,23 +238,24 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
 github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
-github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
-github.com/nats-io/jwt v0.3.2 h1:+RB5hMpXUUA2dfxuhBTEkMOrYmM+gKIZYS1KjSostMI=
-github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
-github.com/nats-io/nats-server/v2 v2.1.2 h1:i2Ly0B+1+rzNZHHWtD4ZwKi+OU5l+uQo1iDHZ2PmiIc=
-github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
-github.com/nats-io/nats.go v1.9.1 h1:ik3HbLhZ0YABLto7iX80pZLPw/6dx3T+++MZJwLnMrQ=
-github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
-github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
-github.com/nats-io/nkeys v0.1.3 h1:6JrEfig+HzTH85yxzhSVbjHRJv9cn0p6n3IngIcM5/k=
-github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
+github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/nats-io/jwt v1.2.2 h1:w3GMTO969dFg+UOKTmmyuu7IGdusK+7Ytlt//OYH/uU=
+github.com/nats-io/jwt v1.2.2/go.mod h1:/xX356yQA6LuXI9xWW7mZNpxgF2mBmGecH+Fj34sP5Q=
+github.com/nats-io/jwt/v2 v2.0.2 h1:ejVCLO8gu6/4bOKIHQpmB5UhhUJfAQw55yvLWpfmKjI=
+github.com/nats-io/jwt/v2 v2.0.2/go.mod h1:VRP+deawSXyhNjXmxPCHskrR6Mq50BqpEI5SEcNiGlY=
+github.com/nats-io/nats-server/v2 v2.2.6 h1:FPK9wWx9pagxcw14s8W9rlfzfyHm61uNLnJyybZbn48=
+github.com/nats-io/nats-server/v2 v2.2.6/go.mod h1:sEnFaxqe09cDmfMgACxZbziXnhQFhwk+aKkZjBBRYrI=
+github.com/nats-io/nats.go v1.11.0 h1:L263PZkrmkRJRJT2YHU8GwWWvEvmr9/LUKuJTXsF32k=
+github.com/nats-io/nats.go v1.11.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
+github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s=
+github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8=
+github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
 github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
 github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
 github.com/oklog/oklog v0.3.2 h1:wVfs8F+in6nTBMkA7CbRw+zZMIB7nNM825cM1wuzoTk=
 github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
 github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
 github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
-github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
 github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -254,8 +268,9 @@ github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go
 github.com/opentracing/basictracer-go v1.0.0 h1:YyUAhaEfjoWXclZVJ9sGoNct7j4TVk7lZWlQw5UXuoo=
 github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
 github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
-github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
 github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
+github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
+github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
 github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5 h1:ZCnq+JUrvXcDVhX/xRolRBZifmabN1HcS1wrPSvxhrU=
 github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
 github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
@@ -271,31 +286,34 @@ github.com/performancecopilot/speed v3.0.0+incompatible h1:2WnRzIquHa5QxaJKShDkL
 github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
 github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
 github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
 github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
-github.com/prometheus/client_golang v1.3.0 h1:miYCvYqFXtl/J9FIy8eNpBfYthAEFg+Ys0XyUVEcDsc=
-github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
+github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
+github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
+github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
 github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.1.0 h1:ElTg5tNp4DqfV7UQjDqv2+RJlNzsDtvNAWccbItceIE=
-github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
+github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
-github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY=
-github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
+github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
+github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ=
+github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
-github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8=
-github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
+github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
+github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
+github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
 github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
-github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
-github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
 github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da h1:p3Vo3i64TCLY7gIfzeQaUJ+kppEO5WQG3cL8iE8tGHU=
@@ -306,19 +324,15 @@ github.com/shirou/gopsutil v2.20.1+incompatible h1:oIq9Cq4i84Hk8uQAUOG3eNdI/29hB
 github.com/shirou/gopsutil v2.20.1+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
-github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
+github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
-github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=
-github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
 github.com/sony/gobreaker v0.4.1 h1:oMnRNZXX5j85zso6xCPRNPtmAycat+WcoKbklScLDgQ=
 github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
-github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
-github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4=
-github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
 github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271 h1:WhxRHzgeVGETMlmVfqhRn8RIeeNoPr2Czh33I4Zdccw=
 github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
@@ -328,91 +342,112 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
-github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
-github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8 h1:ndzgwNDnKIqyCvHTXaCqh9KlOWKvBry6nuXMJmonVsE=
-github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
-github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
-github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
-github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
-go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
-go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
-go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738 h1:VcrIfasaLFkyjk6KNlXQSzO+B0fZcnECiDrKJsfxka0=
-go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+go.etcd.io/etcd/api/v3 v3.5.0 h1:GsV3S+OfZEOCNXdtNkBSR7kgLobAa/SO6tCxRa0GAYw=
+go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
+go.etcd.io/etcd/client/pkg/v3 v3.5.0 h1:2aQv6F436YnN7I4VbI8PPYrBhu+SmrTaADcf8Mi/6PU=
+go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
+go.etcd.io/etcd/client/v2 v2.305.0 h1:ftQ0nOOHMcbMS3KIaDQ0g5Qcd6bhaBrQT6b89DfwLTs=
+go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
+go.etcd.io/etcd/client/v3 v3.5.0 h1:62Eh0XOro+rDwkrypAGDfgmNh5Joq+z+W9HZdlXMzek=
+go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0=
 go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
 go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
-go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
-go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=
-go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
-go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
-go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc=
-go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
-go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
-go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
-go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
-go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU=
-go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
+go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
+go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
+go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
+go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U=
+go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b h1:wSOdpTq0/eI46Ez/LkDwIsAKA71YP2SRKBODiRWM0as=
+golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
-golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
 golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
 golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA=
-golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191220142924-d4481acd189f h1:68K/z8GLUxV76xGSqwTWw2gyk/jwn79LUL43rES2g8o=
-golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q=
+golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
-golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
-golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
+golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI=
+golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -420,54 +455,76 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20200103221440-774c71fcf114 h1:DnSr2mCsxyCE6ZgIkmcWUQY2R5cH/6wL7eIxEmQOMSE=
-golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.2 h1:kRBLX7v7Af8W7Gdbbc908OJcdgtK8bOz9Uaj8/F1ACA=
+golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
-google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0=
+google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
 google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
 google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
 google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
-google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
-google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg=
-google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
+google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0=
+google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
-gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
-gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
 gopkg.in/gcfg.v1 v1.2.3 h1:m8OOJ4ccYHnx2f4gQwpno8nAX5OGOh7RLaaz0pj3Ogs=
 gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
-gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
 gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
-gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
-honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
-sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
-sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
+sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
 sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0 h1:ucqkfpjg9WzSUubAO62csmucvxl4/JeW3F4I4909XkM=
 sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
diff --git a/sd/etcd/client.go b/sd/etcd/client.go
index 2a6cc9a..287b699 100644
--- a/sd/etcd/client.go
+++ b/sd/etcd/client.go
@@ -10,7 +10,7 @@ import (
 	"net/http"
 	"time"
 
-	etcd "go.etcd.io/etcd/client"
+	etcd "go.etcd.io/etcd/client/v2"
 )
 
 var (
diff --git a/sd/etcd/registrar.go b/sd/etcd/registrar.go
index a92a663..08b2f8f 100644
--- a/sd/etcd/registrar.go
+++ b/sd/etcd/registrar.go
@@ -4,7 +4,7 @@ import (
 	"sync"
 	"time"
 
-	etcd "go.etcd.io/etcd/client"
+	etcd "go.etcd.io/etcd/client/v2"
 
 	"github.com/go-kit/kit/log"
 )
diff --git a/sd/etcdv3/client.go b/sd/etcdv3/client.go
index 0ccb9e6..d826416 100644
--- a/sd/etcdv3/client.go
+++ b/sd/etcdv3/client.go
@@ -6,8 +6,8 @@ import (
 	"errors"
 	"time"
 
-	"go.etcd.io/etcd/clientv3"
-	"go.etcd.io/etcd/pkg/transport"
+	"go.etcd.io/etcd/client/pkg/v3/transport"
+	clientv3 "go.etcd.io/etcd/client/v3"
 	"google.golang.org/grpc"
 )
 
diff --git a/tracing/opentracing/endpoint.go b/tracing/opentracing/endpoint.go
index 0482e9c..4df1ef2 100644
--- a/tracing/opentracing/endpoint.go
+++ b/tracing/opentracing/endpoint.go
@@ -2,54 +2,123 @@ package opentracing
 
 import (
 	"context"
+	"strconv"
 
 	"github.com/opentracing/opentracing-go"
 	otext "github.com/opentracing/opentracing-go/ext"
+	otlog "github.com/opentracing/opentracing-go/log"
 
 	"github.com/go-kit/kit/endpoint"
+	"github.com/go-kit/kit/sd/lb"
 )
 
-// TraceServer returns a Middleware that wraps the `next` Endpoint in an
+// TraceEndpoint returns a Middleware that wraps the `next` Endpoint in an
 // OpenTracing Span called `operationName`.
 //
-// If `ctx` already has a Span, it is re-used and the operation name is
-// overwritten. If `ctx` does not yet have a Span, one is created here.
-func TraceServer(tracer opentracing.Tracer, operationName string) endpoint.Middleware {
-	return func(next endpoint.Endpoint) endpoint.Endpoint {
-		return func(ctx context.Context, request interface{}) (interface{}, error) {
-			serverSpan := opentracing.SpanFromContext(ctx)
-			if serverSpan == nil {
-				// All we can do is create a new root span.
-				serverSpan = tracer.StartSpan(operationName)
-			} else {
-				serverSpan.SetOperationName(operationName)
-			}
-			defer serverSpan.Finish()
-			otext.SpanKindRPCServer.Set(serverSpan)
-			ctx = opentracing.ContextWithSpan(ctx, serverSpan)
-			return next(ctx, request)
-		}
+// If `ctx` already has a Span, child span is created from it.
+// If `ctx` doesn't yet have a Span, the new one is created.
+func TraceEndpoint(tracer opentracing.Tracer, operationName string, opts ...EndpointOption) endpoint.Middleware {
+	cfg := &EndpointOptions{
+		Tags: make(opentracing.Tags),
+	}
+
+	for _, opt := range opts {
+		opt(cfg)
 	}
-}
 
-// TraceClient returns a Middleware that wraps the `next` Endpoint in an
-// OpenTracing Span called `operationName`.
-func TraceClient(tracer opentracing.Tracer, operationName string) endpoint.Middleware {
 	return func(next endpoint.Endpoint) endpoint.Endpoint {
-		return func(ctx context.Context, request interface{}) (interface{}, error) {
-			var clientSpan opentracing.Span
+		return func(ctx context.Context, request interface{}) (response interface{}, err error) {
+			if cfg.GetOperationName != nil {
+				if newOperationName := cfg.GetOperationName(ctx, operationName); newOperationName != "" {
+					operationName = newOperationName
+				}
+			}
+
+			var span opentracing.Span
 			if parentSpan := opentracing.SpanFromContext(ctx); parentSpan != nil {
-				clientSpan = tracer.StartSpan(
+				span = tracer.StartSpan(
 					operationName,
 					opentracing.ChildOf(parentSpan.Context()),
 				)
 			} else {
-				clientSpan = tracer.StartSpan(operationName)
+				span = tracer.StartSpan(operationName)
+			}
+			defer span.Finish()
+
+			applyTags(span, cfg.Tags)
+			if cfg.GetTags != nil {
+				extraTags := cfg.GetTags(ctx)
+				applyTags(span, extraTags)
 			}
-			defer clientSpan.Finish()
-			otext.SpanKindRPCClient.Set(clientSpan)
-			ctx = opentracing.ContextWithSpan(ctx, clientSpan)
+
+			ctx = opentracing.ContextWithSpan(ctx, span)
+
+			defer func() {
+				if err != nil {
+					if lbErr, ok := err.(lb.RetryError); ok {
+						// handle errors originating from lb.Retry
+						fields := make([]otlog.Field, 0, len(lbErr.RawErrors))
+						for idx, rawErr := range lbErr.RawErrors {
+							fields = append(fields, otlog.String(
+								"gokit.retry.error."+strconv.Itoa(idx+1), rawErr.Error(),
+							))
+						}
+
+						otext.LogError(span, lbErr, fields...)
+
+						return
+					}
+
+					// generic error
+					otext.LogError(span, err)
+
+					return
+				}
+
+				// test for business error
+				if res, ok := response.(endpoint.Failer); ok && res.Failed() != nil {
+					span.LogFields(
+						otlog.String("gokit.business.error", res.Failed().Error()),
+					)
+
+					if cfg.IgnoreBusinessError {
+						return
+					}
+
+					// treating business error as real error in span.
+					otext.LogError(span, res.Failed())
+
+					return
+				}
+			}()
+
 			return next(ctx, request)
 		}
 	}
 }
+
+// TraceServer returns a Middleware that wraps the `next` Endpoint in an
+// OpenTracing Span called `operationName` with server span.kind tag..
+func TraceServer(tracer opentracing.Tracer, operationName string, opts ...EndpointOption) endpoint.Middleware {
+	opts = append(opts, WithTags(map[string]interface{}{
+		otext.SpanKindRPCServer.Key: otext.SpanKindRPCServer.Value,
+	}))
+
+	return TraceEndpoint(tracer, operationName, opts...)
+}
+
+// TraceClient returns a Middleware that wraps the `next` Endpoint in an
+// OpenTracing Span called `operationName` with client span.kind tag.
+func TraceClient(tracer opentracing.Tracer, operationName string, opts ...EndpointOption) endpoint.Middleware {
+	opts = append(opts, WithTags(map[string]interface{}{
+		otext.SpanKindRPCClient.Key: otext.SpanKindRPCClient.Value,
+	}))
+
+	return TraceEndpoint(tracer, operationName, opts...)
+}
+
+func applyTags(span opentracing.Span, tags opentracing.Tags) {
+	for key, value := range tags {
+		span.SetTag(key, value)
+	}
+}
diff --git a/tracing/opentracing/endpoint_options.go b/tracing/opentracing/endpoint_options.go
new file mode 100644
index 0000000..6854271
--- /dev/null
+++ b/tracing/opentracing/endpoint_options.go
@@ -0,0 +1,74 @@
+package opentracing
+
+import (
+	"context"
+
+	"github.com/opentracing/opentracing-go"
+)
+
+// EndpointOptions holds the options for tracing an endpoint
+type EndpointOptions struct {
+	// IgnoreBusinessError if set to true will not treat a business error
+	// identified through the endpoint.Failer interface as a span error.
+	IgnoreBusinessError bool
+
+	// GetOperationName is an optional function that can set the span operation name based on the existing one
+	// for the endpoint and information in the context.
+	//
+	// If the function is nil, or the returned name is empty, the existing name for the endpoint is used.
+	GetOperationName func(ctx context.Context, name string) string
+
+	// Tags holds the default tags which will be set on span
+	// creation by our Endpoint middleware.
+	Tags opentracing.Tags
+
+	// GetTags is an optional function that can extract tags
+	// from the context and add them to the span.
+	GetTags func(ctx context.Context) opentracing.Tags
+}
+
+// EndpointOption allows for functional options to endpoint tracing middleware.
+type EndpointOption func(*EndpointOptions)
+
+// WithOptions sets all configuration options at once by use of the EndpointOptions struct.
+func WithOptions(options EndpointOptions) EndpointOption {
+	return func(o *EndpointOptions) {
+		*o = options
+	}
+}
+
+// WithIgnoreBusinessError if set to true will not treat a business error
+// identified through the endpoint.Failer interface as a span error.
+func WithIgnoreBusinessError(ignoreBusinessError bool) EndpointOption {
+	return func(o *EndpointOptions) {
+		o.IgnoreBusinessError = ignoreBusinessError
+	}
+}
+
+// WithOperationNameFunc allows to set function that can set the span operation name based on the existing one
+// for the endpoint and information in the context.
+func WithOperationNameFunc(getOperationName func(ctx context.Context, name string) string) EndpointOption {
+	return func(o *EndpointOptions) {
+		o.GetOperationName = getOperationName
+	}
+}
+
+// WithTags adds default tags for the spans created by the Endpoint tracer.
+func WithTags(tags opentracing.Tags) EndpointOption {
+	return func(o *EndpointOptions) {
+		if o.Tags == nil {
+			o.Tags = make(opentracing.Tags)
+		}
+
+		for key, value := range tags {
+			o.Tags[key] = value
+		}
+	}
+}
+
+// WithTagsFunc set the func to extracts additional tags from the context.
+func WithTagsFunc(getTags func(ctx context.Context) opentracing.Tags) EndpointOption {
+	return func(o *EndpointOptions) {
+		o.GetTags = getTags
+	}
+}
diff --git a/update_deps.bash b/update_deps.bash
deleted file mode 100755
index ebe79ee..0000000
--- a/update_deps.bash
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env bash
-
-# This script updates each non-stdlib, non-Go-kit dependency to its most recent
-# commit. It can be invoked to aid in debugging after a dependency-related
-# failure on continuous integration.
-
-function deps {
-	go list -deps -f '{{if and .DepOnly (not .Standard)}}{{.ImportPath}}{{end}}' ./...
-}
-
-function unique_repos {
-	cut -d '/' -f-3 | sort | uniq
-}
-
-function not_gokit {
-	grep -v 'go-kit/kit'
-}
-
-function go_get_update {
-	while read d
-	do
-		echo $d
-		go get -u $d/... || echo "failed, trying again with master" && cd $GOPATH/src/$d && git checkout master && go get -u $d
-	done
-}
-
-deps | unique_repos | not_gokit | go_get_update


Test patch:
diff --git a/auth/jwt/middleware_test.go b/auth/jwt/middleware_test.go
index 3278e13..fc7032f 100644
--- a/auth/jwt/middleware_test.go
+++ b/auth/jwt/middleware_test.go
@@ -44,13 +44,13 @@ func signingValidator(t *testing.T, signer endpoint.Endpoint, expectedKey string
 		t.Fatalf("Signer returned error: %s", err)
 	}
 
-	token, ok := ctx.(context.Context).Value(JWTTokenContextKey).(string)
+	token, ok := ctx.(context.Context).Value(JWTContextKey).(string)
 	if !ok {
 		t.Fatal("Token did not exist in context")
 	}
 
 	if token != expectedKey {
-		t.Fatalf("JWT tokens did not match: expecting %s got %s", expectedKey, token)
+		t.Fatalf("JWTs did not match: expecting %s got %s", expectedKey, token)
 	}
 }
 
@@ -87,7 +87,7 @@ func TestJWTParser(t *testing.T) {
 	}
 
 	// Invalid Token is passed into the parser
-	ctx := context.WithValue(context.Background(), JWTTokenContextKey, invalidKey)
+	ctx := context.WithValue(context.Background(), JWTContextKey, invalidKey)
 	_, err = parser(ctx, struct{}{})
 	if err == nil {
 		t.Error("Parser should have returned an error")
@@ -95,7 +95,7 @@ func TestJWTParser(t *testing.T) {
 
 	// Invalid Method is used in the parser
 	badParser := NewParser(keys, invalidMethod, MapClaimsFactory)(e)
-	ctx = context.WithValue(context.Background(), JWTTokenContextKey, signedKey)
+	ctx = context.WithValue(context.Background(), JWTContextKey, signedKey)
 	_, err = badParser(ctx, struct{}{})
 	if err == nil {
 		t.Error("Parser should have returned an error")
@@ -111,14 +111,14 @@ func TestJWTParser(t *testing.T) {
 	}
 
 	badParser = NewParser(invalidKeys, method, MapClaimsFactory)(e)
-	ctx = context.WithValue(context.Background(), JWTTokenContextKey, signedKey)
+	ctx = context.WithValue(context.Background(), JWTContextKey, signedKey)
 	_, err = badParser(ctx, struct{}{})
 	if err == nil {
 		t.Error("Parser should have returned an error")
 	}
 
 	// Correct token is passed into the parser
-	ctx = context.WithValue(context.Background(), JWTTokenContextKey, signedKey)
+	ctx = context.WithValue(context.Background(), JWTContextKey, signedKey)
 	ctx1, err := parser(ctx, struct{}{})
 	if err != nil {
 		t.Fatalf("Parser returned error: %s", err)
@@ -135,7 +135,7 @@ func TestJWTParser(t *testing.T) {
 
 	// Test for malformed token error response
 	parser = NewParser(keys, method, StandardClaimsFactory)(e)
-	ctx = context.WithValue(context.Background(), JWTTokenContextKey, malformedKey)
+	ctx = context.WithValue(context.Background(), JWTContextKey, malformedKey)
 	ctx1, err = parser(ctx, struct{}{})
 	if want, have := ErrTokenMalformed, err; want != have {
 		t.Fatalf("Expected %+v, got %+v", want, have)
@@ -148,7 +148,7 @@ func TestJWTParser(t *testing.T) {
 	if err != nil {
 		t.Fatalf("Unable to Sign Token: %+v", err)
 	}
-	ctx = context.WithValue(context.Background(), JWTTokenContextKey, token)
+	ctx = context.WithValue(context.Background(), JWTContextKey, token)
 	ctx1, err = parser(ctx, struct{}{})
 	if want, have := ErrTokenExpired, err; want != have {
 		t.Fatalf("Expected %+v, got %+v", want, have)
@@ -161,7 +161,7 @@ func TestJWTParser(t *testing.T) {
 	if err != nil {
 		t.Fatalf("Unable to Sign Token: %+v", err)
 	}
-	ctx = context.WithValue(context.Background(), JWTTokenContextKey, token)
+	ctx = context.WithValue(context.Background(), JWTContextKey, token)
 	ctx1, err = parser(ctx, struct{}{})
 	if want, have := ErrTokenNotActive, err; want != have {
 		t.Fatalf("Expected %+v, got %+v", want, have)
@@ -169,7 +169,7 @@ func TestJWTParser(t *testing.T) {
 
 	// test valid standard claims token
 	parser = NewParser(keys, method, StandardClaimsFactory)(e)
-	ctx = context.WithValue(context.Background(), JWTTokenContextKey, standardSignedKey)
+	ctx = context.WithValue(context.Background(), JWTContextKey, standardSignedKey)
 	ctx1, err = parser(ctx, struct{}{})
 	if err != nil {
 		t.Fatalf("Parser returned error: %s", err)
@@ -184,7 +184,7 @@ func TestJWTParser(t *testing.T) {
 
 	// test valid customized claims token
 	parser = NewParser(keys, method, func() jwt.Claims { return &customClaims{} })(e)
-	ctx = context.WithValue(context.Background(), JWTTokenContextKey, customSignedKey)
+	ctx = context.WithValue(context.Background(), JWTContextKey, customSignedKey)
 	ctx1, err = parser(ctx, struct{}{})
 	if err != nil {
 		t.Fatalf("Parser returned error: %s", err)
@@ -205,7 +205,7 @@ func TestIssue562(t *testing.T) {
 	var (
 		kf  = func(token *jwt.Token) (interface{}, error) { return []byte("secret"), nil }
 		e   = NewParser(kf, jwt.SigningMethodHS256, MapClaimsFactory)(endpoint.Nop)
-		key = JWTTokenContextKey
+		key = JWTContextKey
 		val = "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtpZCIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiZ28ta2l0In0.14M2VmYyApdSlV_LZ88ajjwuaLeIFplB8JpyNy0A19E"
 		ctx = context.WithValue(context.Background(), key, val)
 	)
diff --git a/auth/jwt/transport_test.go b/auth/jwt/transport_test.go
index 83d0f17..096c6ac 100644
--- a/auth/jwt/transport_test.go
+++ b/auth/jwt/transport_test.go
@@ -15,7 +15,7 @@ func TestHTTPToContext(t *testing.T) {
 	// When the header doesn't exist
 	ctx := reqFunc(context.Background(), &http.Request{})
 
-	if ctx.Value(JWTTokenContextKey) != nil {
+	if ctx.Value(JWTContextKey) != nil {
 		t.Error("Context shouldn't contain the encoded JWT")
 	}
 
@@ -24,7 +24,7 @@ func TestHTTPToContext(t *testing.T) {
 	header.Set("Authorization", "no expected auth header format value")
 	ctx = reqFunc(context.Background(), &http.Request{Header: header})
 
-	if ctx.Value(JWTTokenContextKey) != nil {
+	if ctx.Value(JWTContextKey) != nil {
 		t.Error("Context shouldn't contain the encoded JWT")
 	}
 
@@ -32,7 +32,7 @@ func TestHTTPToContext(t *testing.T) {
 	header.Set("Authorization", generateAuthHeaderFromToken(signedKey))
 	ctx = reqFunc(context.Background(), &http.Request{Header: header})
 
-	token := ctx.Value(JWTTokenContextKey).(string)
+	token := ctx.Value(JWTContextKey).(string)
 	if token != signedKey {
 		t.Errorf("Context doesn't contain the expected encoded token value; expected: %s, got: %s", signedKey, token)
 	}
@@ -41,7 +41,7 @@ func TestHTTPToContext(t *testing.T) {
 func TestContextToHTTP(t *testing.T) {
 	reqFunc := ContextToHTTP()
 
-	// No JWT Token is passed in the context
+	// No JWT is passed in the context
 	ctx := context.Background()
 	r := http.Request{}
 	reqFunc(ctx, &r)
@@ -51,8 +51,8 @@ func TestContextToHTTP(t *testing.T) {
 		t.Error("authorization key should not exist in metadata")
 	}
 
-	// Correct JWT Token is passed in the context
-	ctx = context.WithValue(context.Background(), JWTTokenContextKey, signedKey)
+	// Correct JWT is passed in the context
+	ctx = context.WithValue(context.Background(), JWTContextKey, signedKey)
 	r = http.Request{Header: http.Header{}}
 	reqFunc(ctx, &r)
 
@@ -60,7 +60,7 @@ func TestContextToHTTP(t *testing.T) {
 	expected := generateAuthHeaderFromToken(signedKey)
 
 	if token != expected {
-		t.Errorf("Authorization header does not contain the expected JWT token; expected %s, got %s", expected, token)
+		t.Errorf("Authorization header does not contain the expected JWT; expected %s, got %s", expected, token)
 	}
 }
 
@@ -70,36 +70,36 @@ func TestGRPCToContext(t *testing.T) {
 
 	// No Authorization header is passed
 	ctx := reqFunc(context.Background(), md)
-	token := ctx.Value(JWTTokenContextKey)
+	token := ctx.Value(JWTContextKey)
 	if token != nil {
-		t.Error("Context should not contain a JWT Token")
+		t.Error("Context should not contain a JWT")
 	}
 
 	// Invalid Authorization header is passed
 	md["authorization"] = []string{fmt.Sprintf("%s", signedKey)}
 	ctx = reqFunc(context.Background(), md)
-	token = ctx.Value(JWTTokenContextKey)
+	token = ctx.Value(JWTContextKey)
 	if token != nil {
-		t.Error("Context should not contain a JWT Token")
+		t.Error("Context should not contain a JWT")
 	}
 
 	// Authorization header is correct
 	md["authorization"] = []string{fmt.Sprintf("Bearer %s", signedKey)}
 	ctx = reqFunc(context.Background(), md)
-	token, ok := ctx.Value(JWTTokenContextKey).(string)
+	token, ok := ctx.Value(JWTContextKey).(string)
 	if !ok {
-		t.Fatal("JWT Token not passed to context correctly")
+		t.Fatal("JWT not passed to context correctly")
 	}
 
 	if token != signedKey {
-		t.Errorf("JWT tokens did not match: expecting %s got %s", signedKey, token)
+		t.Errorf("JWTs did not match: expecting %s got %s", signedKey, token)
 	}
 }
 
 func TestContextToGRPC(t *testing.T) {
 	reqFunc := ContextToGRPC()
 
-	// No JWT Token is passed in the context
+	// No JWT is passed in the context
 	ctx := context.Background()
 	md := metadata.MD{}
 	reqFunc(ctx, &md)
@@ -109,17 +109,17 @@ func TestContextToGRPC(t *testing.T) {
 		t.Error("authorization key should not exist in metadata")
 	}
 
-	// Correct JWT Token is passed in the context
-	ctx = context.WithValue(context.Background(), JWTTokenContextKey, signedKey)
+	// Correct JWT is passed in the context
+	ctx = context.WithValue(context.Background(), JWTContextKey, signedKey)
 	md = metadata.MD{}
 	reqFunc(ctx, &md)
 
 	token, ok := md["authorization"]
 	if !ok {
-		t.Fatal("JWT Token not passed to metadata correctly")
+		t.Fatal("JWT not passed to metadata correctly")
 	}
 
 	if token[0] != generateAuthHeaderFromToken(signedKey) {
-		t.Errorf("JWT tokens did not match: expecting %s got %s", signedKey, token[0])
+		t.Errorf("JWTs did not match: expecting %s got %s", signedKey, token[0])
 	}
 }
diff --git a/sd/etcd/client_test.go b/sd/etcd/client_test.go
index 1bdb7ae..93a7f41 100644
--- a/sd/etcd/client_test.go
+++ b/sd/etcd/client_test.go
@@ -1,13 +1,13 @@
 package etcd
 
 import (
+	"context"
 	"errors"
 	"reflect"
 	"testing"
 	"time"
-	"context"
 
-	etcd "go.etcd.io/etcd/client"
+	etcd "go.etcd.io/etcd/client/v2"
 )
 
 func TestNewClient(t *testing.T) {
diff --git a/sd/etcd/instancer_test.go b/sd/etcd/instancer_test.go
index 8631e56..2e0bb56 100644
--- a/sd/etcd/instancer_test.go
+++ b/sd/etcd/instancer_test.go
@@ -4,7 +4,7 @@ import (
 	"errors"
 	"testing"
 
-	stdetcd "go.etcd.io/etcd/client"
+	stdetcd "go.etcd.io/etcd/client/v2"
 
 	"github.com/go-kit/kit/log"
 	"github.com/go-kit/kit/sd"
diff --git a/tracing/opentracing/endpoint_test.go b/tracing/opentracing/endpoint_test.go
index a26f7ba..267415b 100644
--- a/tracing/opentracing/endpoint_test.go
+++ b/tracing/opentracing/endpoint_test.go
@@ -2,50 +2,89 @@ package opentracing_test
 
 import (
 	"context"
+	"errors"
+	"fmt"
+	"reflect"
 	"testing"
+	"time"
 
 	"github.com/opentracing/opentracing-go"
+	otext "github.com/opentracing/opentracing-go/ext"
+	otlog "github.com/opentracing/opentracing-go/log"
 	"github.com/opentracing/opentracing-go/mocktracer"
 
 	"github.com/go-kit/kit/endpoint"
+	"github.com/go-kit/kit/sd"
+	"github.com/go-kit/kit/sd/lb"
 	kitot "github.com/go-kit/kit/tracing/opentracing"
 )
 
-func TestTraceServer(t *testing.T) {
+const (
+	span1 = "SPAN-1"
+	span2 = "SPAN-2"
+	span3 = "SPAN-3"
+	span4 = "SPAN-4"
+	span5 = "SPAN-5"
+	span6 = "SPAN-6"
+	span7 = "SPAN-7"
+	span8 = "SPAN-8"
+)
+
+var (
+	err1 = errors.New("some error")
+	err2 = errors.New("some business error")
+	err3 = errors.New("other business error")
+)
+
+// compile time assertion
+var _ endpoint.Failer = failedResponse{}
+
+type failedResponse struct {
+	err error
+}
+
+func (r failedResponse) Failed() error {
+	return r.err
+}
+
+func TestTraceEndpoint(t *testing.T) {
 	tracer := mocktracer.New()
 
-	// Initialize the ctx with a nameless Span.
-	contextSpan := tracer.StartSpan("").(*mocktracer.MockSpan)
-	ctx := opentracing.ContextWithSpan(context.Background(), contextSpan)
+	// Initialize the ctx with a parent Span.
+	parentSpan := tracer.StartSpan("parent").(*mocktracer.MockSpan)
+	defer parentSpan.Finish()
+	ctx := opentracing.ContextWithSpan(context.Background(), parentSpan)
 
-	tracedEndpoint := kitot.TraceServer(tracer, "testOp")(endpoint.Nop)
+	tracedEndpoint := kitot.TraceEndpoint(tracer, "testOp")(endpoint.Nop)
 	if _, err := tracedEndpoint(ctx, struct{}{}); err != nil {
 		t.Fatal(err)
 	}
 
+	// tracedEndpoint created a new Span.
 	finishedSpans := tracer.FinishedSpans()
 	if want, have := 1, len(finishedSpans); want != have {
 		t.Fatalf("Want %v span(s), found %v", want, have)
 	}
 
-	// Test that the op name is updated
 	endpointSpan := finishedSpans[0]
 	if want, have := "testOp", endpointSpan.OperationName; want != have {
 		t.Fatalf("Want %q, have %q", want, have)
 	}
-	contextContext := contextSpan.Context().(mocktracer.MockSpanContext)
-	endpointContext := endpointSpan.Context().(mocktracer.MockSpanContext)
-	// ...and that the ID is unmodified.
-	if want, have := contextContext.SpanID, endpointContext.SpanID; want != have {
-		t.Errorf("Want SpanID %q, have %q", want, have)
+
+	parentContext := parentSpan.Context().(mocktracer.MockSpanContext)
+	endpointContext := parentSpan.Context().(mocktracer.MockSpanContext)
+
+	// ... and that the parent ID is set appropriately.
+	if want, have := parentContext.SpanID, endpointContext.SpanID; want != have {
+		t.Errorf("Want ParentID %q, have %q", want, have)
 	}
 }
 
-func TestTraceServerNoContextSpan(t *testing.T) {
+func TestTraceEndpointNoContextSpan(t *testing.T) {
 	tracer := mocktracer.New()
 
 	// Empty/background context.
-	tracedEndpoint := kitot.TraceServer(tracer, "testOp")(endpoint.Nop)
+	tracedEndpoint := kitot.TraceEndpoint(tracer, "testOp")(endpoint.Nop)
 	if _, err := tracedEndpoint(context.Background(), struct{}{}); err != nil {
 		t.Fatal(err)
 	}
@@ -57,21 +96,264 @@ func TestTraceServerNoContextSpan(t *testing.T) {
 	}
 
 	endpointSpan := finishedSpans[0]
+
 	if want, have := "testOp", endpointSpan.OperationName; want != have {
 		t.Fatalf("Want %q, have %q", want, have)
 	}
 }
 
-func TestTraceClient(t *testing.T) {
+func TestTraceEndpointWithOptions(t *testing.T) {
 	tracer := mocktracer.New()
 
-	// Initialize the ctx with a parent Span.
-	parentSpan := tracer.StartSpan("parent").(*mocktracer.MockSpan)
-	defer parentSpan.Finish()
-	ctx := opentracing.ContextWithSpan(context.Background(), parentSpan)
+	// span 1 without options
+	mw := kitot.TraceEndpoint(tracer, span1)
+	tracedEndpoint := mw(endpoint.Nop)
+	_, _ = tracedEndpoint(context.Background(), struct{}{})
 
-	tracedEndpoint := kitot.TraceClient(tracer, "testOp")(endpoint.Nop)
-	if _, err := tracedEndpoint(ctx, struct{}{}); err != nil {
+	// span 2 with options
+	mw = kitot.TraceEndpoint(
+		tracer,
+		span2,
+		kitot.WithOptions(kitot.EndpointOptions{}),
+	)
+	tracedEndpoint = mw(func(context.Context, interface{}) (interface{}, error) {
+		return nil, err1
+	})
+	_, _ = tracedEndpoint(context.Background(), struct{}{})
+
+	// span 3 with lb error
+	mw = kitot.TraceEndpoint(
+		tracer,
+		span3,
+		kitot.WithOptions(kitot.EndpointOptions{}),
+	)
+	tracedEndpoint = mw(
+		lb.Retry(
+			5,
+			1*time.Second,
+			lb.NewRoundRobin(
+				sd.FixedEndpointer{
+					func(context.Context, interface{}) (interface{}, error) {
+						return nil, err1
+					},
+				},
+			),
+		),
+	)
+	_, _ = tracedEndpoint(context.Background(), struct{}{})
+
+	// span 4 with disabled IgnoreBusinessError option
+	mw = kitot.TraceEndpoint(
+		tracer,
+		span4,
+		kitot.WithIgnoreBusinessError(false),
+	)
+	tracedEndpoint = mw(func(context.Context, interface{}) (interface{}, error) {
+		return failedResponse{
+			err: err2,
+		}, nil
+	})
+	_, _ = tracedEndpoint(context.Background(), struct{}{})
+
+	// span 5 with enabled IgnoreBusinessError option
+	mw = kitot.TraceEndpoint(tracer, span5, kitot.WithIgnoreBusinessError(true))
+	tracedEndpoint = mw(func(context.Context, interface{}) (interface{}, error) {
+		return failedResponse{
+			err: err3,
+		}, nil
+	})
+	_, _ = tracedEndpoint(context.Background(), struct{}{})
+
+	// span 6 with OperationNameFunc option
+	mw = kitot.TraceEndpoint(
+		tracer,
+		span6,
+		kitot.WithOperationNameFunc(func(ctx context.Context, name string) string {
+			return fmt.Sprintf("%s-%s", "new", name)
+		}),
+	)
+	tracedEndpoint = mw(endpoint.Nop)
+	_, _ = tracedEndpoint(context.Background(), struct{}{})
+
+	// span 7 with Tags options
+	mw = kitot.TraceEndpoint(
+		tracer,
+		span7,
+		kitot.WithTags(map[string]interface{}{
+			"tag1": "tag1",
+			"tag2": "tag2",
+		}),
+		kitot.WithTags(map[string]interface{}{
+			"tag3": "tag3",
+		}),
+	)
+	tracedEndpoint = mw(endpoint.Nop)
+	_, _ = tracedEndpoint(context.Background(), struct{}{})
+
+	// span 8 with TagsFunc options
+	mw = kitot.TraceEndpoint(
+		tracer,
+		span8,
+		kitot.WithTags(map[string]interface{}{
+			"tag1": "tag1",
+			"tag2": "tag2",
+		}),
+		kitot.WithTags(map[string]interface{}{
+			"tag3": "tag3",
+		}),
+		kitot.WithTagsFunc(func(ctx context.Context) opentracing.Tags {
+			return map[string]interface{}{
+				"tag4": "tag4",
+			}
+		}),
+	)
+	tracedEndpoint = mw(endpoint.Nop)
+	_, _ = tracedEndpoint(context.Background(), struct{}{})
+
+	finishedSpans := tracer.FinishedSpans()
+	if want, have := 8, len(finishedSpans); want != have {
+		t.Fatalf("Want %v span(s), found %v", want, have)
+	}
+
+	// test span 1
+	span := finishedSpans[0]
+
+	if want, have := span1, span.OperationName; want != have {
+		t.Fatalf("Want %q, have %q", want, have)
+	}
+
+	// test span 2
+	span = finishedSpans[1]
+
+	if want, have := span2, span.OperationName; want != have {
+		t.Fatalf("Want %q, have %q", want, have)
+	}
+
+	if want, have := true, span.Tag("error"); want != have {
+		t.Fatalf("Want %v, have %v", want, have)
+	}
+
+	// test span 3
+	span = finishedSpans[2]
+
+	if want, have := span3, span.OperationName; want != have {
+		t.Fatalf("Want %q, have %q", want, have)
+	}
+
+	if want, have := true, span.Tag("error"); want != have {
+		t.Fatalf("Want %v, have %v", want, have)
+	}
+
+	if want, have := 1, len(span.Logs()); want != have {
+		t.Fatalf("incorrect logs count, wanted %d, got %d", want, have)
+	}
+
+	if want, have := []otlog.Field{
+		otlog.String("event", "error"),
+		otlog.String("error.object", "some error (previously: some error; some error; some error; some error)"),
+		otlog.String("gokit.retry.error.1", "some error"),
+		otlog.String("gokit.retry.error.2", "some error"),
+		otlog.String("gokit.retry.error.3", "some error"),
+		otlog.String("gokit.retry.error.4", "some error"),
+		otlog.String("gokit.retry.error.5", "some error"),
+	}, span.Logs()[0].Fields; reflect.DeepEqual(want, have) {
+		t.Fatalf("Want %q, have %q", want, have)
+	}
+
+	// test span 4
+	span = finishedSpans[3]
+
+	if want, have := span4, span.OperationName; want != have {
+		t.Fatalf("Want %q, have %q", want, have)
+	}
+
+	if want, have := true, span.Tag("error"); want != have {
+		t.Fatalf("Want %v, have %v", want, have)
+	}
+
+	if want, have := 2, len(span.Logs()); want != have {
+		t.Fatalf("incorrect logs count, wanted %d, got %d", want, have)
+	}
+
+	if want, have := []otlog.Field{
+		otlog.String("gokit.business.error", "some business error"),
+	}, span.Logs()[0].Fields; reflect.DeepEqual(want, have) {
+		t.Fatalf("Want %q, have %q", want, have)
+	}
+
+	if want, have := []otlog.Field{
+		otlog.String("event", "error"),
+		otlog.String("error.object", "some business error"),
+	}, span.Logs()[1].Fields; reflect.DeepEqual(want, have) {
+		t.Fatalf("Want %q, have %q", want, have)
+	}
+
+	// test span 5
+	span = finishedSpans[4]
+
+	if want, have := span5, span.OperationName; want != have {
+		t.Fatalf("Want %q, have %q", want, have)
+	}
+
+	if want, have := (interface{})(nil), span.Tag("error"); want != have {
+		t.Fatalf("Want %q, have %q", want, have)
+	}
+
+	if want, have := 1, len(span.Logs()); want != have {
+		t.Fatalf("incorrect logs count, wanted %d, got %d", want, have)
+	}
+
+	if want, have := []otlog.Field{
+		otlog.String("gokit.business.error", "some business error"),
+	}, span.Logs()[0].Fields; reflect.DeepEqual(want, have) {
+		t.Fatalf("Want %q, have %q", want, have)
+	}
+
+	// test span 6
+	span = finishedSpans[5]
+
+	if want, have := fmt.Sprintf("%s-%s", "new", span6), span.OperationName; want != have {
+		t.Fatalf("Want %q, have %q", want, have)
+	}
+
+	// test span 7
+	span = finishedSpans[6]
+
+	if want, have := span7, span.OperationName; want != have {
+		t.Fatalf("Want %q, have %q", want, have)
+	}
+
+	if want, have := map[string]interface{}{
+		"tag1": "tag1",
+		"tag2": "tag2",
+		"tag3": "tag3",
+	}, span.Tags(); fmt.Sprint(want) != fmt.Sprint(have) {
+		t.Fatalf("Want %q, have %q", want, have)
+	}
+
+	// test span 8
+	span = finishedSpans[7]
+
+	if want, have := span8, span.OperationName; want != have {
+		t.Fatalf("Want %q, have %q", want, have)
+	}
+
+	if want, have := map[string]interface{}{
+		"tag1": "tag1",
+		"tag2": "tag2",
+		"tag3": "tag3",
+		"tag4": "tag4",
+	}, span.Tags(); fmt.Sprint(want) != fmt.Sprint(have) {
+		t.Fatalf("Want %q, have %q", want, have)
+	}
+}
+
+func TestTraceServer(t *testing.T) {
+	tracer := mocktracer.New()
+
+	// Empty/background context.
+	tracedEndpoint := kitot.TraceServer(tracer, "testOp")(endpoint.Nop)
+	if _, err := tracedEndpoint(context.Background(), struct{}{}); err != nil {
 		t.Fatal(err)
 	}
 
@@ -81,21 +363,20 @@ func TestTraceClient(t *testing.T) {
 		t.Fatalf("Want %v span(s), found %v", want, have)
 	}
 
-	endpointSpan := finishedSpans[0]
-	if want, have := "testOp", endpointSpan.OperationName; want != have {
+	span := finishedSpans[0]
+
+	if want, have := "testOp", span.OperationName; want != have {
 		t.Fatalf("Want %q, have %q", want, have)
 	}
 
-	parentContext := parentSpan.Context().(mocktracer.MockSpanContext)
-	endpointContext := parentSpan.Context().(mocktracer.MockSpanContext)
-
-	// ... and that the parent ID is set appropriately.
-	if want, have := parentContext.SpanID, endpointContext.SpanID; want != have {
-		t.Errorf("Want ParentID %q, have %q", want, have)
+	if want, have := map[string]interface{}{
+		otext.SpanKindRPCServer.Key: otext.SpanKindRPCServer.Value,
+	}, span.Tags(); fmt.Sprint(want) != fmt.Sprint(have) {
+		t.Fatalf("Want %q, have %q", want, have)
 	}
 }
 
-func TestTraceClientNoContextSpan(t *testing.T) {
+func TestTraceClient(t *testing.T) {
 	tracer := mocktracer.New()
 
 	// Empty/background context.
@@ -110,8 +391,15 @@ func TestTraceClientNoContextSpan(t *testing.T) {
 		t.Fatalf("Want %v span(s), found %v", want, have)
 	}
 
-	endpointSpan := finishedSpans[0]
-	if want, have := "testOp", endpointSpan.OperationName; want != have {
+	span := finishedSpans[0]
+
+	if want, have := "testOp", span.OperationName; want != have {
+		t.Fatalf("Want %q, have %q", want, have)
+	}
+
+	if want, have := map[string]interface{}{
+		otext.SpanKindRPCClient.Key: otext.SpanKindRPCClient.Value,
+	}, span.Tags(); fmt.Sprint(want) != fmt.Sprint(have) {
 		t.Fatalf("Want %q, have %q", want, have)
 	}
 }
diff --git a/transport/nats/publisher_test.go b/transport/nats/publisher_test.go
index a29c764..d5ece09 100644
--- a/transport/nats/publisher_test.go
+++ b/transport/nats/publisher_test.go
@@ -19,11 +19,12 @@ func TestPublisher(t *testing.T) {
 		}
 	)
 
-	nc := newNatsConn(t)
-	defer nc.Close()
+	s, c := newNATSConn(t)
+	defer func() { s.Shutdown(); s.WaitForShutdown() }()
+	defer c.Close()
 
-	sub, err := nc.QueueSubscribe("natstransport.test", "natstransport", func(msg *nats.Msg) {
-		if err := nc.Publish(msg.Reply, []byte(testdata)); err != nil {
+	sub, err := c.QueueSubscribe("natstransport.test", "natstransport", func(msg *nats.Msg) {
+		if err := c.Publish(msg.Reply, []byte(testdata)); err != nil {
 			t.Fatal(err)
 		}
 	})
@@ -33,7 +34,7 @@ func TestPublisher(t *testing.T) {
 	defer sub.Unsubscribe()
 
 	publisher := natstransport.NewPublisher(
-		nc,
+		c,
 		"natstransport.test",
 		encode,
 		decode,
@@ -63,11 +64,12 @@ func TestPublisherBefore(t *testing.T) {
 		}
 	)
 
-	nc := newNatsConn(t)
-	defer nc.Close()
+	s, c := newNATSConn(t)
+	defer func() { s.Shutdown(); s.WaitForShutdown() }()
+	defer c.Close()
 
-	sub, err := nc.QueueSubscribe("natstransport.test", "natstransport", func(msg *nats.Msg) {
-		if err := nc.Publish(msg.Reply, msg.Data); err != nil {
+	sub, err := c.QueueSubscribe("natstransport.test", "natstransport", func(msg *nats.Msg) {
+		if err := c.Publish(msg.Reply, msg.Data); err != nil {
 			t.Fatal(err)
 		}
 	})
@@ -77,7 +79,7 @@ func TestPublisherBefore(t *testing.T) {
 	defer sub.Unsubscribe()
 
 	publisher := natstransport.NewPublisher(
-		nc,
+		c,
 		"natstransport.test",
 		encode,
 		decode,
@@ -111,11 +113,12 @@ func TestPublisherAfter(t *testing.T) {
 		}
 	)
 
-	nc := newNatsConn(t)
-	defer nc.Close()
+	s, c := newNATSConn(t)
+	defer func() { s.Shutdown(); s.WaitForShutdown() }()
+	defer c.Close()
 
-	sub, err := nc.QueueSubscribe("natstransport.test", "natstransport", func(msg *nats.Msg) {
-		if err := nc.Publish(msg.Reply, []byte(testdata)); err != nil {
+	sub, err := c.QueueSubscribe("natstransport.test", "natstransport", func(msg *nats.Msg) {
+		if err := c.Publish(msg.Reply, []byte(testdata)); err != nil {
 			t.Fatal(err)
 		}
 	})
@@ -125,7 +128,7 @@ func TestPublisherAfter(t *testing.T) {
 	defer sub.Unsubscribe()
 
 	publisher := natstransport.NewPublisher(
-		nc,
+		c,
 		"natstransport.test",
 		encode,
 		decode,
@@ -158,13 +161,14 @@ func TestPublisherTimeout(t *testing.T) {
 		}
 	)
 
-	nc := newNatsConn(t)
-	defer nc.Close()
+	s, c := newNATSConn(t)
+	defer func() { s.Shutdown(); s.WaitForShutdown() }()
+	defer c.Close()
 
 	ch := make(chan struct{})
 	defer close(ch)
 
-	sub, err := nc.QueueSubscribe("natstransport.test", "natstransport", func(msg *nats.Msg) {
+	sub, err := c.QueueSubscribe("natstransport.test", "natstransport", func(msg *nats.Msg) {
 		<-ch
 	})
 	if err != nil {
@@ -173,7 +177,7 @@ func TestPublisherTimeout(t *testing.T) {
 	defer sub.Unsubscribe()
 
 	publisher := natstransport.NewPublisher(
-		nc,
+		c,
 		"natstransport.test",
 		encode,
 		decode,
@@ -195,11 +199,12 @@ func TestPublisherCancellation(t *testing.T) {
 		}
 	)
 
-	nc := newNatsConn(t)
-	defer nc.Close()
+	s, c := newNATSConn(t)
+	defer func() { s.Shutdown(); s.WaitForShutdown() }()
+	defer c.Close()
 
-	sub, err := nc.QueueSubscribe("natstransport.test", "natstransport", func(msg *nats.Msg) {
-		if err := nc.Publish(msg.Reply, []byte(testdata)); err != nil {
+	sub, err := c.QueueSubscribe("natstransport.test", "natstransport", func(msg *nats.Msg) {
+		if err := c.Publish(msg.Reply, []byte(testdata)); err != nil {
 			t.Fatal(err)
 		}
 	})
@@ -209,7 +214,7 @@ func TestPublisherCancellation(t *testing.T) {
 	defer sub.Unsubscribe()
 
 	publisher := natstransport.NewPublisher(
-		nc,
+		c,
 		"natstransport.test",
 		encode,
 		decode,
@@ -227,13 +232,14 @@ func TestPublisherCancellation(t *testing.T) {
 func TestEncodeJSONRequest(t *testing.T) {
 	var data string
 
-	nc := newNatsConn(t)
-	defer nc.Close()
+	s, c := newNATSConn(t)
+	defer func() { s.Shutdown(); s.WaitForShutdown() }()
+	defer c.Close()
 
-	sub, err := nc.QueueSubscribe("natstransport.test", "natstransport", func(msg *nats.Msg) {
+	sub, err := c.QueueSubscribe("natstransport.test", "natstransport", func(msg *nats.Msg) {
 		data = string(msg.Data)
 
-		if err := nc.Publish(msg.Reply, []byte("")); err != nil {
+		if err := c.Publish(msg.Reply, []byte("")); err != nil {
 			t.Fatal(err)
 		}
 	})
@@ -243,7 +249,7 @@ func TestEncodeJSONRequest(t *testing.T) {
 	defer sub.Unsubscribe()
 
 	publisher := natstransport.NewPublisher(
-		nc,
+		c,
 		"natstransport.test",
 		natstransport.EncodeJSONRequest,
 		func(context.Context, *nats.Msg) (interface{}, error) { return nil, nil },
diff --git a/transport/nats/subscriber_test.go b/transport/nats/subscriber_test.go
index 69a097f..2b08084 100644
--- a/transport/nats/subscriber_test.go
+++ b/transport/nats/subscriber_test.go
@@ -21,50 +21,49 @@ type TestResponse struct {
 	Error  string `json:"err"`
 }
 
-var natsServer *server.Server
-
-func init() {
-	natsServer = server.New(&server.Options{
+func newNATSConn(t *testing.T) (*server.Server, *nats.Conn) {
+	s, err := server.NewServer(&server.Options{
 		Host: "localhost",
-		Port: 4222,
+		Port: 0,
 	})
+	if err != nil {
+		t.Fatal(err)
+	}
 
-	go func() {
-		natsServer.Start()
-	}()
+	go s.Start()
 
-	if ok := natsServer.ReadyForConnections(2 * time.Second); !ok {
-		panic("Failed start of NATS")
+	for i := 0; i < 5 && !s.Running(); i++ {
+		t.Logf("Running %v", s.Running())
+		time.Sleep(time.Second)
+	}
+	if !s.Running() {
+		s.Shutdown()
+		s.WaitForShutdown()
+		t.Fatal("not yet running")
 	}
-}
 
-func newNatsConn(t *testing.T) *nats.Conn {
-	// Subscriptions and connections are closed asynchronously, so it's possible
-	// that there's still a subscription from an old connection that must be closed
-	// before the current test can be run.
-	for tries := 20; tries > 0; tries-- {
-		if natsServer.NumSubscriptions() == 0 {
-			break
-		}
+	t.Log(s.Addr().String())
 
-		time.Sleep(5 * time.Millisecond)
+	if ok := s.ReadyForConnections(5 * time.Second); !ok {
+		t.Fatal("not ready for connections")
 	}
 
-	if n := natsServer.NumSubscriptions(); n > 0 {
-		t.Fatalf("found %d active subscriptions on the server", n)
-	}
+	//if n := s.NumSubscriptions(); n > 0 {
+	//	t.Fatalf("found %d active subscriptions on the server", n)
+	//}
 
-	nc, err := nats.Connect("nats://"+natsServer.Addr().String(), nats.Name(t.Name()))
+	c, err := nats.Connect("nats://"+s.Addr().String(), nats.Name(t.Name()))
 	if err != nil {
-		t.Fatalf("failed to connect to gnatsd server: %s", err)
+		t.Fatalf("failed to connect to NATS server: %s", err)
 	}
 
-	return nc
+	return s, c
 }
 
 func TestSubscriberBadDecode(t *testing.T) {
-	nc := newNatsConn(t)
-	defer nc.Close()
+	s, c := newNATSConn(t)
+	defer func() { s.Shutdown(); s.WaitForShutdown() }()
+	defer c.Close()
 
 	handler := natstransport.NewSubscriber(
 		func(context.Context, interface{}) (interface{}, error) { return struct{}{}, nil },
@@ -72,7 +71,7 @@ func TestSubscriberBadDecode(t *testing.T) {
 		func(context.Context, string, *nats.Conn, interface{}) error { return nil },
 	)
 
-	resp := testRequest(t, nc, handler)
+	resp := testRequest(t, c, handler)
 
 	if want, have := "dang", resp.Error; want != have {
 		t.Errorf("want %s, have %s", want, have)
@@ -81,8 +80,9 @@ func TestSubscriberBadDecode(t *testing.T) {
 }
 
 func TestSubscriberBadEndpoint(t *testing.T) {
-	nc := newNatsConn(t)
-	defer nc.Close()
+	s, c := newNATSConn(t)
+	defer func() { s.Shutdown(); s.WaitForShutdown() }()
+	defer c.Close()
 
 	handler := natstransport.NewSubscriber(
 		func(context.Context, interface{}) (interface{}, error) { return struct{}{}, errors.New("dang") },
@@ -90,7 +90,7 @@ func TestSubscriberBadEndpoint(t *testing.T) {
 		func(context.Context, string, *nats.Conn, interface{}) error { return nil },
 	)
 
-	resp := testRequest(t, nc, handler)
+	resp := testRequest(t, c, handler)
 
 	if want, have := "dang", resp.Error; want != have {
 		t.Errorf("want %s, have %s", want, have)
@@ -98,8 +98,9 @@ func TestSubscriberBadEndpoint(t *testing.T) {
 }
 
 func TestSubscriberBadEncode(t *testing.T) {
-	nc := newNatsConn(t)
-	defer nc.Close()
+	s, c := newNATSConn(t)
+	defer func() { s.Shutdown(); s.WaitForShutdown() }()
+	defer c.Close()
 
 	handler := natstransport.NewSubscriber(
 		func(context.Context, interface{}) (interface{}, error) { return struct{}{}, nil },
@@ -107,7 +108,7 @@ func TestSubscriberBadEncode(t *testing.T) {
 		func(context.Context, string, *nats.Conn, interface{}) error { return errors.New("dang") },
 	)
 
-	resp := testRequest(t, nc, handler)
+	resp := testRequest(t, c, handler)
 
 	if want, have := "dang", resp.Error; want != have {
 		t.Errorf("want %s, have %s", want, have)
@@ -115,8 +116,9 @@ func TestSubscriberBadEncode(t *testing.T) {
 }
 
 func TestSubscriberErrorEncoder(t *testing.T) {
-	nc := newNatsConn(t)
-	defer nc.Close()
+	s, c := newNATSConn(t)
+	defer func() { s.Shutdown(); s.WaitForShutdown() }()
+	defer c.Close()
 
 	errTeapot := errors.New("teapot")
 	code := func(err error) error {
@@ -138,13 +140,13 @@ func TestSubscriberErrorEncoder(t *testing.T) {
 				t.Fatal(err)
 			}
 
-			if err := nc.Publish(reply, b); err != nil {
+			if err := c.Publish(reply, b); err != nil {
 				t.Fatal(err)
 			}
 		}),
 	)
 
-	resp := testRequest(t, nc, handler)
+	resp := testRequest(t, c, handler)
 
 	if want, have := errTeapot.Error(), resp.Error; want != have {
 		t.Errorf("want %s, have %s", want, have)
@@ -168,8 +170,9 @@ func TestSubscriberHappySubject(t *testing.T) {
 }
 
 func TestMultipleSubscriberBefore(t *testing.T) {
-	nc := newNatsConn(t)
-	defer nc.Close()
+	s, c := newNATSConn(t)
+	defer func() { s.Shutdown(); s.WaitForShutdown() }()
+	defer c.Close()
 
 	var (
 		response = struct{ Body string }{"go eat a fly ugly\n"}
@@ -187,7 +190,7 @@ func TestMultipleSubscriberBefore(t *testing.T) {
 				return err
 			}
 
-			return nc.Publish(reply, b)
+			return c.Publish(reply, b)
 		},
 		natstransport.SubscriberBefore(func(ctx context.Context, _ *nats.Msg) context.Context {
 			ctx = context.WithValue(ctx, "one", 1)
@@ -204,7 +207,7 @@ func TestMultipleSubscriberBefore(t *testing.T) {
 		}),
 	)
 
-	sub, err := nc.QueueSubscribe("natstransport.test", "natstransport", handler.ServeMsg(nc))
+	sub, err := c.QueueSubscribe("natstransport.test", "natstransport", handler.ServeMsg(c))
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -213,7 +216,7 @@ func TestMultipleSubscriberBefore(t *testing.T) {
 	wg.Add(1)
 	go func() {
 		defer wg.Done()
-		_, err := nc.Request("natstransport.test", []byte("test data"), 2*time.Second)
+		_, err := c.Request("natstransport.test", []byte("test data"), 2*time.Second)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -229,8 +232,9 @@ func TestMultipleSubscriberBefore(t *testing.T) {
 }
 
 func TestMultipleSubscriberAfter(t *testing.T) {
-	nc := newNatsConn(t)
-	defer nc.Close()
+	s, c := newNATSConn(t)
+	defer func() { s.Shutdown(); s.WaitForShutdown() }()
+	defer c.Close()
 
 	var (
 		response = struct{ Body string }{"go eat a fly ugly\n"}
@@ -247,25 +251,21 @@ func TestMultipleSubscriberAfter(t *testing.T) {
 			if err != nil {
 				return err
 			}
-
-			return nc.Publish(reply, b)
+			return c.Publish(reply, b)
 		},
 		natstransport.SubscriberAfter(func(ctx context.Context, nc *nats.Conn) context.Context {
-			ctx = context.WithValue(ctx, "one", 1)
-
-			return ctx
+			return context.WithValue(ctx, "one", 1)
 		}),
 		natstransport.SubscriberAfter(func(ctx context.Context, nc *nats.Conn) context.Context {
 			if _, ok := ctx.Value("one").(int); !ok {
 				t.Error("Value was not set properly when multiple ServerAfters are used")
 			}
-
 			close(done)
 			return ctx
 		}),
 	)
 
-	sub, err := nc.QueueSubscribe("natstransport.test", "natstransport", handler.ServeMsg(nc))
+	sub, err := c.QueueSubscribe("natstransport.test", "natstransport", handler.ServeMsg(c))
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -274,7 +274,7 @@ func TestMultipleSubscriberAfter(t *testing.T) {
 	wg.Add(1)
 	go func() {
 		defer wg.Done()
-		_, err := nc.Request("natstransport.test", []byte("test data"), 2*time.Second)
+		_, err := c.Request("natstransport.test", []byte("test data"), 2*time.Second)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -290,8 +290,9 @@ func TestMultipleSubscriberAfter(t *testing.T) {
 }
 
 func TestSubscriberFinalizerFunc(t *testing.T) {
-	nc := newNatsConn(t)
-	defer nc.Close()
+	s, c := newNATSConn(t)
+	defer func() { s.Shutdown(); s.WaitForShutdown() }()
+	defer c.Close()
 
 	var (
 		response = struct{ Body string }{"go eat a fly ugly\n"}
@@ -309,14 +310,14 @@ func TestSubscriberFinalizerFunc(t *testing.T) {
 				return err
 			}
 
-			return nc.Publish(reply, b)
+			return c.Publish(reply, b)
 		},
 		natstransport.SubscriberFinalizer(func(ctx context.Context, _ *nats.Msg) {
 			close(done)
 		}),
 	)
 
-	sub, err := nc.QueueSubscribe("natstransport.test", "natstransport", handler.ServeMsg(nc))
+	sub, err := c.QueueSubscribe("natstransport.test", "natstransport", handler.ServeMsg(c))
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -325,7 +326,7 @@ func TestSubscriberFinalizerFunc(t *testing.T) {
 	wg.Add(1)
 	go func() {
 		defer wg.Done()
-		_, err := nc.Request("natstransport.test", []byte("test data"), 2*time.Second)
+		_, err := c.Request("natstransport.test", []byte("test data"), 2*time.Second)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -341,8 +342,9 @@ func TestSubscriberFinalizerFunc(t *testing.T) {
 }
 
 func TestEncodeJSONResponse(t *testing.T) {
-	nc := newNatsConn(t)
-	defer nc.Close()
+	s, c := newNATSConn(t)
+	defer func() { s.Shutdown(); s.WaitForShutdown() }()
+	defer c.Close()
 
 	handler := natstransport.NewSubscriber(
 		func(context.Context, interface{}) (interface{}, error) {
@@ -354,13 +356,13 @@ func TestEncodeJSONResponse(t *testing.T) {
 		natstransport.EncodeJSONResponse,
 	)
 
-	sub, err := nc.QueueSubscribe("natstransport.test", "natstransport", handler.ServeMsg(nc))
+	sub, err := c.QueueSubscribe("natstransport.test", "natstransport", handler.ServeMsg(c))
 	if err != nil {
 		t.Fatal(err)
 	}
 	defer sub.Unsubscribe()
 
-	r, err := nc.Request("natstransport.test", []byte("test data"), 2*time.Second)
+	r, err := c.Request("natstransport.test", []byte("test data"), 2*time.Second)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -379,8 +381,9 @@ func (m responseError) Error() string {
 }
 
 func TestErrorEncoder(t *testing.T) {
-	nc := newNatsConn(t)
-	defer nc.Close()
+	s, c := newNATSConn(t)
+	defer func() { s.Shutdown(); s.WaitForShutdown() }()
+	defer c.Close()
 
 	errResp := struct {
 		Error string `json:"err"`
@@ -393,13 +396,13 @@ func TestErrorEncoder(t *testing.T) {
 		natstransport.EncodeJSONResponse,
 	)
 
-	sub, err := nc.QueueSubscribe("natstransport.test", "natstransport", handler.ServeMsg(nc))
+	sub, err := c.QueueSubscribe("natstransport.test", "natstransport", handler.ServeMsg(c))
 	if err != nil {
 		t.Fatal(err)
 	}
 	defer sub.Unsubscribe()
 
-	r, err := nc.Request("natstransport.test", []byte("test data"), 2*time.Second)
+	r, err := c.Request("natstransport.test", []byte("test data"), 2*time.Second)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -416,8 +419,9 @@ func TestErrorEncoder(t *testing.T) {
 type noContentResponse struct{}
 
 func TestEncodeNoContent(t *testing.T) {
-	nc := newNatsConn(t)
-	defer nc.Close()
+	s, c := newNATSConn(t)
+	defer func() { s.Shutdown(); s.WaitForShutdown() }()
+	defer c.Close()
 
 	handler := natstransport.NewSubscriber(
 		func(context.Context, interface{}) (interface{}, error) { return noContentResponse{}, nil },
@@ -425,13 +429,13 @@ func TestEncodeNoContent(t *testing.T) {
 		natstransport.EncodeJSONResponse,
 	)
 
-	sub, err := nc.QueueSubscribe("natstransport.test", "natstransport", handler.ServeMsg(nc))
+	sub, err := c.QueueSubscribe("natstransport.test", "natstransport", handler.ServeMsg(c))
 	if err != nil {
 		t.Fatal(err)
 	}
 	defer sub.Unsubscribe()
 
-	r, err := nc.Request("natstransport.test", []byte("test data"), 2*time.Second)
+	r, err := c.Request("natstransport.test", []byte("test data"), 2*time.Second)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -442,8 +446,9 @@ func TestEncodeNoContent(t *testing.T) {
 }
 
 func TestNoOpRequestDecoder(t *testing.T) {
-	nc := newNatsConn(t)
-	defer nc.Close()
+	s, c := newNATSConn(t)
+	defer func() { s.Shutdown(); s.WaitForShutdown() }()
+	defer c.Close()
 
 	handler := natstransport.NewSubscriber(
 		func(ctx context.Context, request interface{}) (interface{}, error) {
@@ -456,13 +461,13 @@ func TestNoOpRequestDecoder(t *testing.T) {
 		natstransport.EncodeJSONResponse,
 	)
 
-	sub, err := nc.QueueSubscribe("natstransport.test", "natstransport", handler.ServeMsg(nc))
+	sub, err := c.QueueSubscribe("natstransport.test", "natstransport", handler.ServeMsg(c))
 	if err != nil {
 		t.Fatal(err)
 	}
 	defer sub.Unsubscribe()
 
-	r, err := nc.Request("natstransport.test", []byte("test data"), 2*time.Second)
+	r, err := c.Request("natstransport.test", []byte("test data"), 2*time.Second)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -490,16 +495,17 @@ func testSubscriber(t *testing.T) (step func(), resp <-chan *nats.Msg) {
 	)
 
 	go func() {
-		nc := newNatsConn(t)
-		defer nc.Close()
+		s, c := newNATSConn(t)
+		defer func() { s.Shutdown(); s.WaitForShutdown() }()
+		defer c.Close()
 
-		sub, err := nc.QueueSubscribe("natstransport.test", "natstransport", handler.ServeMsg(nc))
+		sub, err := c.QueueSubscribe("natstransport.test", "natstransport", handler.ServeMsg(c))
 		if err != nil {
 			t.Fatal(err)
 		}
 		defer sub.Unsubscribe()
 
-		r, err := nc.Request("natstransport.test", []byte("test data"), 2*time.Second)
+		r, err := c.Request("natstransport.test", []byte("test data"), 2*time.Second)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -510,14 +516,14 @@ func testSubscriber(t *testing.T) (step func(), resp <-chan *nats.Msg) {
 	return func() { stepch <- true }, response
 }
 
-func testRequest(t *testing.T, nc *nats.Conn, handler *natstransport.Subscriber) TestResponse {
-	sub, err := nc.QueueSubscribe("natstransport.test", "natstransport", handler.ServeMsg(nc))
+func testRequest(t *testing.T, c *nats.Conn, handler *natstransport.Subscriber) TestResponse {
+	sub, err := c.QueueSubscribe("natstransport.test", "natstransport", handler.ServeMsg(c))
 	if err != nil {
 		t.Fatal(err)
 	}
 	defer sub.Unsubscribe()
 
-	r, err := nc.Request("natstransport.test", []byte("test data"), 2*time.Second)
+	r, err := c.Request("natstransport.test", []byte("test data"), 2*time.Second)
 	if err != nil {
 		t.Fatal(err)
 	}