VOL-3419: Replicate voltha flows in openolt agent
- The scale-tester-app will adhere to new openolt.proto interface (version 4.0.2)
and will pass necessary information for openolt-agent to replicate the flows.
- upgrade to voltha-lib-go version 4.0.0

Change-Id: I9d862929ae8ac4468d4e93096f8cd8e16f26ec93
diff --git a/.gitignore b/.gitignore
index 4a23d30..22df6a2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
 .idea
 openolt-scale-tester
 tests
+**/*.bak
diff --git a/Makefile b/Makefile
index b3f6d8a..29fde94 100644
--- a/Makefile
+++ b/Makefile
@@ -57,6 +57,21 @@
 	@echo "test              : Run unit tests, if any"
 	@echo
 
+## Local Development Helpers
+local-protos: ## Copies a local version of the voltha-protos dependency into the vendor directory
+ifdef LOCAL_PROTOS
+	rm -rf vendor/github.com/opencord/voltha-protos/v4/go
+	mkdir -p vendor/github.com/opencord/voltha-protos/v4/go
+	cp -r ${LOCAL_PROTOS}/go/* vendor/github.com/opencord/voltha-protos/v4/go
+	rm -rf vendor/github.com/opencord/voltha-protos/v4/go/vendor
+endif
+
+local-lib-go: ## Copies a local version of the voltha-lib-go dependency into the vendor directory
+ifdef LOCAL_LIB_GO
+	mkdir -p vendor/github.com/opencord/voltha-lib-go/v4/pkg
+	cp -r ${LOCAL_LIB_GO}/pkg/* vendor/github.com/opencord/voltha-lib-go/v4/pkg/
+endif
+
 ## Docker targets
 
 build: docker-build
diff --git a/VERSION b/VERSION
index 9084fa2..227cea2 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.1.0
+2.0.0
diff --git a/config/config.go b/config/config.go
index 6b9f7c0..07dfb1e 100644
--- a/config/config.go
+++ b/config/config.go
@@ -22,7 +22,7 @@
 	"strconv"
 	"strings"
 
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
+	"github.com/opencord/voltha-lib-go/v4/pkg/log"
 )
 
 // Open OLT default constants
@@ -58,8 +58,15 @@
 	IsGroupTest             bool
 }
 
+var logger log.CLogger
+
 func init() {
-	_, _ = log.AddPackage(log.JSON, log.WarnLevel, nil)
+	// Setup this package so that it's log level can be modified at run time
+	var err error
+	logger, err = log.RegisterPackage(log.JSON, log.DebugLevel, log.Fields{})
+	if err != nil {
+		panic(err)
+	}
 }
 
 func GetTpIDList(tpIDsStr string) []int {
@@ -70,7 +77,7 @@
 			tpIDSlice = append(tpIDSlice, tpID)
 		}
 	}
-	log.Debugw("parsed-tp-id-slice", log.Fields{"tpIDSlice": tpIDSlice})
+	logger.Debugw(nil, "parsed-tp-id-slice", log.Fields{"tpIDSlice": tpIDSlice})
 	return tpIDSlice
 }
 
diff --git a/core/att_workflow.go b/core/att_workflow.go
index f673ee0..d98cbeb 100644
--- a/core/att_workflow.go
+++ b/core/att_workflow.go
@@ -21,24 +21,20 @@
 	"strings"
 
 	"github.com/opencord/openolt-scale-tester/config"
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-	oop "github.com/opencord/voltha-protos/v3/go/openolt"
-	tp_pb "github.com/opencord/voltha-protos/v3/go/tech_profile"
+	"github.com/opencord/voltha-lib-go/v4/pkg/log"
+	oop "github.com/opencord/voltha-protos/v4/go/openolt"
+	tp_pb "github.com/opencord/voltha-protos/v4/go/tech_profile"
 	"golang.org/x/net/context"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 )
 
-func init() {
-	_, _ = log.AddPackage(log.JSON, log.DebugLevel, nil)
-}
-
 // A dummy struct to comply with the WorkFlow interface.
 type AttWorkFlow struct {
 }
 
 func AddDhcpIPV4Flow(oo oop.OpenoltClient, config *config.OpenOltScaleTesterConfig, rsrMgr *OpenOltResourceMgr) error {
-	var flowID uint32
+	var flowID uint64
 	var err error
 
 	if flowID, err = rsrMgr.GetFlowID(context.Background(), uint32(config.NniIntfID)); err != nil {
@@ -59,21 +55,21 @@
 
 	st, _ := status.FromError(err)
 	if st.Code() == codes.AlreadyExists {
-		log.Debugw("Flow already exists", log.Fields{"err": err, "deviceFlow": flow})
+		logger.Debugw(nil, "Flow already exists", log.Fields{"err": err, "deviceFlow": flow})
 		return nil
 	}
 
 	if err != nil {
-		log.Errorw("Failed to Add DHCP IPv4 to device", log.Fields{"err": err, "deviceFlow": flow})
+		logger.Errorw(nil, "Failed to Add DHCP IPv4 to device", log.Fields{"err": err, "deviceFlow": flow})
 		return err
 	}
-	log.Debugw("DHCP IPV4 added to device successfully ", log.Fields{"flow": flow})
+	logger.Debugw(nil, "DHCP IPV4 added to device successfully ", log.Fields{"flow": flow})
 
 	return nil
 }
 
 func AddDhcpIPV6Flow(oo oop.OpenoltClient, config *config.OpenOltScaleTesterConfig, rsrMgr *OpenOltResourceMgr) error {
-	var flowID uint32
+	var flowID uint64
 	var err error
 
 	if flowID, err = rsrMgr.GetFlowID(context.Background(), uint32(config.NniIntfID)); err != nil {
@@ -94,15 +90,15 @@
 
 	st, _ := status.FromError(err)
 	if st.Code() == codes.AlreadyExists {
-		log.Debugw("Flow already exists", log.Fields{"err": err, "deviceFlow": flow})
+		logger.Debugw(nil, "Flow already exists", log.Fields{"err": err, "deviceFlow": flow})
 		return nil
 	}
 
 	if err != nil {
-		log.Errorw("Failed to Add DHCP IPV6 to device", log.Fields{"err": err, "deviceFlow": flow})
+		logger.Errorw(nil, "Failed to Add DHCP IPV6 to device", log.Fields{"err": err, "deviceFlow": flow})
 		return err
 	}
-	log.Debugw("DHCP IPV6 added to device successfully ", log.Fields{"flow": flow})
+	logger.Debugw(nil, "DHCP IPV6 added to device successfully ", log.Fields{"flow": flow})
 
 	return nil
 }
@@ -118,75 +114,75 @@
 func (att AttWorkFlow) ProvisionScheds(subs *Subscriber) error {
 	var trafficSched []*tp_pb.TrafficScheduler
 
-	log.Info("provisioning-scheds")
+	logger.Info(nil, "provisioning-scheds")
 
 	if trafficSched = getTrafficSched(subs, tp_pb.Direction_DOWNSTREAM); trafficSched == nil {
-		log.Error("ds-traffic-sched-is-nil")
+		logger.Error(nil, "ds-traffic-sched-is-nil")
 		return errors.New(ReasonCodeToReasonString(SCHED_CREATION_FAILED))
 	}
 
-	log.Debugw("Sending Traffic scheduler create to device",
+	logger.Debugw(nil, "Sending Traffic scheduler create to device",
 		log.Fields{"Direction": tp_pb.Direction_DOWNSTREAM, "TrafficScheds": trafficSched})
 	if _, err := subs.OpenOltClient.CreateTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
 		IntfId: subs.PonIntf, OnuId: subs.OnuID,
 		UniId: subs.UniID, PortNo: subs.UniPortNo,
 		TrafficScheds: trafficSched}); err != nil {
-		log.Errorw("Failed to create traffic schedulers", log.Fields{"error": err})
+		logger.Errorw(nil, "Failed to create traffic schedulers", log.Fields{"error": err})
 		return errors.New(ReasonCodeToReasonString(SCHED_CREATION_FAILED))
 	}
 
 	if trafficSched = getTrafficSched(subs, tp_pb.Direction_UPSTREAM); trafficSched == nil {
-		log.Error("us-traffic-sched-is-nil")
+		logger.Error(nil, "us-traffic-sched-is-nil")
 		return errors.New(ReasonCodeToReasonString(SCHED_CREATION_FAILED))
 	}
 
-	log.Debugw("Sending Traffic scheduler create to device",
+	logger.Debugw(nil, "Sending Traffic scheduler create to device",
 		log.Fields{"Direction": tp_pb.Direction_UPSTREAM, "TrafficScheds": trafficSched})
 	if _, err := subs.OpenOltClient.CreateTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
 		IntfId: subs.PonIntf, OnuId: subs.OnuID,
 		UniId: subs.UniID, PortNo: subs.UniPortNo,
 		TrafficScheds: trafficSched}); err != nil {
-		log.Errorw("Failed to create traffic schedulers", log.Fields{"error": err})
+		logger.Errorw(nil, "Failed to create traffic schedulers", log.Fields{"error": err})
 		return errors.New(ReasonCodeToReasonString(SCHED_CREATION_FAILED))
 	}
 	return nil
 }
 
 func (att AttWorkFlow) ProvisionQueues(subs *Subscriber) error {
-	log.Info("provisioning-queues")
+	logger.Info(nil, "provisioning-queues")
 
 	var trafficQueues []*tp_pb.TrafficQueue
 	if trafficQueues = getTrafficQueues(subs, tp_pb.Direction_DOWNSTREAM); trafficQueues == nil {
-		log.Error("Failed to create traffic queues")
+		logger.Error(nil, "Failed to create traffic queues")
 		return errors.New(ReasonCodeToReasonString(QUEUE_CREATION_FAILED))
 	}
 
 	// On receiving the CreateTrafficQueues request, the driver should create corresponding
 	// downstream queues.
-	log.Debugw("Sending Traffic Queues create to device",
+	logger.Debugw(nil, "Sending Traffic Queues create to device",
 		log.Fields{"Direction": tp_pb.Direction_DOWNSTREAM, "TrafficQueues": trafficQueues})
 	if _, err := subs.OpenOltClient.CreateTrafficQueues(context.Background(),
 		&tp_pb.TrafficQueues{IntfId: subs.PonIntf, OnuId: subs.OnuID,
 			UniId: subs.UniID, PortNo: subs.UniPortNo,
 			TrafficQueues: trafficQueues}); err != nil {
-		log.Errorw("Failed to create traffic queues in device", log.Fields{"error": err})
+		logger.Errorw(nil, "Failed to create traffic queues in device", log.Fields{"error": err})
 		return errors.New(ReasonCodeToReasonString(QUEUE_CREATION_FAILED))
 	}
 
 	if trafficQueues = getTrafficQueues(subs, tp_pb.Direction_UPSTREAM); trafficQueues == nil {
-		log.Error("Failed to create traffic queues")
+		logger.Error(nil, "Failed to create traffic queues")
 		return errors.New(ReasonCodeToReasonString(QUEUE_CREATION_FAILED))
 	}
 
 	// On receiving the CreateTrafficQueues request, the driver should create corresponding
 	// upstream queues.
-	log.Debugw("Sending Traffic Queues create to device",
+	logger.Debugw(nil, "Sending Traffic Queues create to device",
 		log.Fields{"Direction": tp_pb.Direction_UPSTREAM, "TrafficQueues": trafficQueues})
 	if _, err := subs.OpenOltClient.CreateTrafficQueues(context.Background(),
 		&tp_pb.TrafficQueues{IntfId: subs.PonIntf, OnuId: subs.OnuID,
 			UniId: subs.UniID, PortNo: subs.UniPortNo,
 			TrafficQueues: trafficQueues}); err != nil {
-		log.Errorw("Failed to create traffic queues in device", log.Fields{"error": err})
+		logger.Errorw(nil, "Failed to create traffic queues in device", log.Fields{"error": err})
 		return errors.New(ReasonCodeToReasonString(QUEUE_CREATION_FAILED))
 	}
 
@@ -195,8 +191,9 @@
 
 func (att AttWorkFlow) ProvisionEapFlow(subs *Subscriber) error {
 	var err error
-	var flowID uint32
+	var flowID uint64
 	var gemPortIDs []uint32
+	pbitToGem := make(map[uint32]uint32)
 
 	var allocID = subs.TpInstance[subs.TestConfig.TpIDList[0]].UsScheduler.AllocID
 	for _, gem := range subs.TpInstance[subs.TestConfig.TpIDList[0]].UpstreamGemPortAttributeList {
@@ -208,23 +205,27 @@
 		for pos, pbitSet := range strings.TrimPrefix(pBitMap, "0b") {
 			if pbitSet == '1' {
 				pcp := uint32(len(strings.TrimPrefix(pBitMap, "0b"))) - 1 - uint32(pos)
-				if flowID, err = subs.RsrMgr.GetFlowID(context.Background(), uint32(subs.PonIntf)); err != nil {
-					return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
-				} else {
-					if err := AddFlow(subs, EapolFlow, Upstream, flowID, allocID, gemID, pcp); err != nil {
-						return err
-					}
-				}
+				pbitToGem[pcp] = gemID
 			}
 		}
 	}
+	// This flowID is not the BAL flow ID now, it is the voltha-flow-id
+	if flowID, err = subs.RsrMgr.GetFlowID(context.Background(), uint32(subs.PonIntf)); err != nil {
+		return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
+	}
+	if err := AddFlow(subs, EapolFlow, Upstream, flowID, allocID, 0, 0xff,
+		true, 0, pbitToGem); err != nil {
+		return err
+	}
+
 	return nil
 }
 
 func (att AttWorkFlow) ProvisionDhcpIPV4Flow(subs *Subscriber) error {
 	var err error
-	var flowID uint32
+	var flowID uint64
 	var gemPortIDs []uint32
+	pbitToGem := make(map[uint32]uint32)
 
 	var allocID = subs.TpInstance[subs.TestConfig.TpIDList[0]].UsScheduler.AllocID
 	for _, gem := range subs.TpInstance[subs.TestConfig.TpIDList[0]].UpstreamGemPortAttributeList {
@@ -236,23 +237,27 @@
 		for pos, pbitSet := range strings.TrimPrefix(pBitMap, "0b") {
 			if pbitSet == '1' {
 				pcp := uint32(len(strings.TrimPrefix(pBitMap, "0b"))) - 1 - uint32(pos)
-				if flowID, err = subs.RsrMgr.GetFlowID(context.Background(), uint32(subs.PonIntf)); err != nil {
-					return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
-				} else {
-					if err := AddFlow(subs, DhcpFlowIPV4, Upstream, flowID, allocID, gemID, pcp); err != nil {
-						return err
-					}
-				}
+				pbitToGem[pcp] = gemID
 			}
 		}
 	}
+
+	// This flowID is not the BAL flow ID now, it is the voltha-flow-id
+	if flowID, err = subs.RsrMgr.GetFlowID(context.Background(), uint32(subs.PonIntf)); err != nil {
+		return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
+	}
+	if err := AddFlow(subs, DhcpFlowIPV4, Upstream, flowID, allocID, 0, 0xff,
+		true, 0, pbitToGem); err != nil {
+		return err
+	}
 	return nil
 }
 
 func (att AttWorkFlow) ProvisionDhcpIPV6Flow(subs *Subscriber) error {
 	var err error
-	var flowID uint32
+	var flowID uint64
 	var gemPortIDs []uint32
+	pbitToGem := make(map[uint32]uint32)
 
 	var allocID = subs.TpInstance[subs.TestConfig.TpIDList[0]].UsScheduler.AllocID
 	for _, gem := range subs.TpInstance[subs.TestConfig.TpIDList[0]].UpstreamGemPortAttributeList {
@@ -264,28 +269,32 @@
 		for pos, pbitSet := range strings.TrimPrefix(pBitMap, "0b") {
 			if pbitSet == '1' {
 				pcp := uint32(len(strings.TrimPrefix(pBitMap, "0b"))) - 1 - uint32(pos)
-				if flowID, err = subs.RsrMgr.GetFlowID(context.Background(), uint32(subs.PonIntf)); err != nil {
-					return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
-				} else {
-					if err := AddFlow(subs, DhcpFlowIPV6, Upstream, flowID, allocID, gemID, pcp); err != nil {
-						return err
-					}
-				}
+				pbitToGem[pcp] = gemID
 			}
 		}
 	}
+
+	// This flowID is not the BAL flow ID now, it is the voltha-flow-id
+	if flowID, err = subs.RsrMgr.GetFlowID(context.Background(), uint32(subs.PonIntf)); err != nil {
+		return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
+	}
+	if err := AddFlow(subs, DhcpFlowIPV6, Upstream, flowID, allocID, 0, 0xff,
+		true, 0, pbitToGem); err != nil {
+		return err
+	}
 	return nil
 }
 
 func (att AttWorkFlow) ProvisionIgmpFlow(subs *Subscriber) error {
-	log.Info("att-workflow-does-not-support-igmp-yet--nothing-to-do")
+	logger.Info(nil, "att-workflow-does-not-support-igmp-yet--nothing-to-do")
 	return nil
 }
 
 func (att AttWorkFlow) ProvisionHsiaFlow(subs *Subscriber) error {
 	var err error
-	var flowID uint32
+	var flowIDUs, flowIDDs uint64
 	var gemPortIDs []uint32
+	pbitToGem := make(map[uint32]uint32)
 
 	var allocID = subs.TpInstance[subs.TestConfig.TpIDList[0]].UsScheduler.AllocID
 	for _, gem := range subs.TpInstance[subs.TestConfig.TpIDList[0]].UpstreamGemPortAttributeList {
@@ -297,49 +306,45 @@
 		for pos, pbitSet := range strings.TrimPrefix(pBitMap, "0b") {
 			if pbitSet == '1' {
 				pcp := uint32(len(strings.TrimPrefix(pBitMap, "0b"))) - 1 - uint32(pos)
-				if flowID, err = subs.RsrMgr.GetFlowID(context.Background(), uint32(subs.PonIntf)); err != nil {
-					return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
-				} else {
-					var errUs, errDs error
-					if errUs = AddFlow(subs, HsiaFlow, Upstream, flowID, allocID, gemID, pcp); errUs != nil {
-						log.Errorw("failed to install US HSIA flow",
-							log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
-					}
-					if errDs = AddFlow(subs, HsiaFlow, Downstream, flowID, allocID, gemID, pcp); errDs != nil {
-						log.Errorw("failed to install US HSIA flow",
-							log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
-					}
-					if errUs != nil && errDs != nil {
-					}
-					if errUs != nil || errDs != nil {
-						if errUs != nil {
-							return errUs
-						}
-						return errDs
-					}
-				}
+				pbitToGem[pcp] = gemID
 			}
 		}
 	}
+
+	// This flowID is not the BAL flow ID now, it is the voltha-flow-id
+	if flowIDUs, err = subs.RsrMgr.GetFlowID(context.Background(), uint32(subs.PonIntf)); err != nil {
+		return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
+	}
+	if err := AddFlow(subs, HsiaFlow, Upstream, flowIDUs, allocID, 0, 0xff,
+		true, 0, pbitToGem); err != nil {
+		return err
+	}
+	if flowIDDs, err = subs.RsrMgr.GetFlowID(context.Background(), uint32(subs.PonIntf)); err != nil {
+		return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
+	}
+	if err := AddFlow(subs, HsiaFlow, Downstream, flowIDDs, allocID, 0, 0xff,
+		true, flowIDUs, pbitToGem); err != nil {
+		return err
+	}
 	return nil
 }
 
 func (att AttWorkFlow) ProvisionVoipFlow(subs *Subscriber) error {
-	log.Info("att-workflow-does-not-support-voip-yet--nothing-to-do")
+	logger.Info(nil, "att-workflow-does-not-support-voip-yet--nothing-to-do")
 	return nil
 }
 
 func (att AttWorkFlow) ProvisionVodFlow(subs *Subscriber) error {
-	log.Info("att-workflow-does-not-support-vod-yet--nothing-to-do")
+	logger.Info(nil, "att-workflow-does-not-support-vod-yet--nothing-to-do")
 	return nil
 }
 
 func (att AttWorkFlow) ProvisionMgmtFlow(subs *Subscriber) error {
-	log.Info("att-workflow-does-not-support-mgmt-yet--nothing-to-do")
+	logger.Info(nil, "att-workflow-does-not-support-mgmt-yet--nothing-to-do")
 	return nil
 }
 
 func (att AttWorkFlow) ProvisionMulticastFlow(subs *Subscriber) error {
-	log.Info("att-workflow-does-not-support-multicast-yet--nothing-to-do")
+	logger.Info(nil, "att-workflow-does-not-support-multicast-yet--nothing-to-do")
 	return nil
 }
diff --git a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/common.go b/core/common.go
similarity index 78%
copy from vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/common.go
copy to core/common.go
index a5a79ae..b03022e 100644
--- a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/common.go
+++ b/core/common.go
@@ -13,22 +13,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package db
+
+//Package core Common Logger initialization
+package core
 
 import (
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
+	"github.com/opencord/voltha-lib-go/v4/pkg/log"
 )
 
-const (
-	logLevel = log.ErrorLevel
-)
-
-var logger log.Logger
+var logger log.CLogger
 
 func init() {
 	// Setup this package so that it's log level can be modified at run time
 	var err error
-	logger, err = log.AddPackage(log.JSON, logLevel, log.Fields{"pkg": "db"})
+	logger, err = log.RegisterPackage(log.JSON, log.DebugLevel, log.Fields{})
 	if err != nil {
 		panic(err)
 	}
diff --git a/core/dt_workflow.go b/core/dt_workflow.go
index 5c8b345..97870ee 100644
--- a/core/dt_workflow.go
+++ b/core/dt_workflow.go
@@ -21,16 +21,12 @@
 	"strings"
 
 	"github.com/opencord/openolt-scale-tester/config"
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-	oop "github.com/opencord/voltha-protos/v3/go/openolt"
-	tp_pb "github.com/opencord/voltha-protos/v3/go/tech_profile"
+	"github.com/opencord/voltha-lib-go/v4/pkg/log"
+	oop "github.com/opencord/voltha-protos/v4/go/openolt"
+	tp_pb "github.com/opencord/voltha-protos/v4/go/tech_profile"
 	"golang.org/x/net/context"
 )
 
-func init() {
-	_, _ = log.AddPackage(log.JSON, log.DebugLevel, nil)
-}
-
 // A dummy struct to comply with the WorkFlow interface.
 type DtWorkFlow struct {
 }
@@ -44,35 +40,35 @@
 func (dt DtWorkFlow) ProvisionScheds(subs *Subscriber) error {
 	var trafficSched []*tp_pb.TrafficScheduler
 
-	log.Info("provisioning-scheds")
+	logger.Info(nil, "provisioning-scheds")
 
 	if trafficSched = getTrafficSched(subs, tp_pb.Direction_DOWNSTREAM); trafficSched == nil {
-		log.Error("ds-traffic-sched-is-nil")
+		logger.Error(nil, "ds-traffic-sched-is-nil")
 		return errors.New(ReasonCodeToReasonString(SCHED_CREATION_FAILED))
 	}
 
-	log.Debugw("Sending Traffic scheduler create to device",
+	logger.Debugw(nil, "Sending Traffic scheduler create to device",
 		log.Fields{"Direction": tp_pb.Direction_DOWNSTREAM, "TrafficScheds": trafficSched})
 	if _, err := subs.OpenOltClient.CreateTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
 		IntfId: subs.PonIntf, OnuId: subs.OnuID,
 		UniId: subs.UniID, PortNo: subs.UniPortNo,
 		TrafficScheds: trafficSched}); err != nil {
-		log.Errorw("Failed to create traffic schedulers", log.Fields{"error": err})
+		logger.Errorw(nil, "Failed to create traffic schedulers", log.Fields{"error": err})
 		return errors.New(ReasonCodeToReasonString(SCHED_CREATION_FAILED))
 	}
 
 	if trafficSched = getTrafficSched(subs, tp_pb.Direction_UPSTREAM); trafficSched == nil {
-		log.Error("us-traffic-sched-is-nil")
+		logger.Error(nil, "us-traffic-sched-is-nil")
 		return errors.New(ReasonCodeToReasonString(SCHED_CREATION_FAILED))
 	}
 
-	log.Debugw("Sending Traffic scheduler create to device",
+	logger.Debugw(nil, "Sending Traffic scheduler create to device",
 		log.Fields{"Direction": tp_pb.Direction_UPSTREAM, "TrafficScheds": trafficSched})
 	if _, err := subs.OpenOltClient.CreateTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
 		IntfId: subs.PonIntf, OnuId: subs.OnuID,
 		UniId: subs.UniID, PortNo: subs.UniPortNo,
 		TrafficScheds: trafficSched}); err != nil {
-		log.Errorw("Failed to create traffic schedulers", log.Fields{"error": err})
+		logger.Errorw(nil, "Failed to create traffic schedulers", log.Fields{"error": err})
 		return errors.New(ReasonCodeToReasonString(SCHED_CREATION_FAILED))
 	}
 
@@ -80,40 +76,40 @@
 }
 
 func (dt DtWorkFlow) ProvisionQueues(subs *Subscriber) error {
-	log.Info("provisioning-queues")
+	logger.Info(nil, "provisioning-queues")
 
 	var trafficQueues []*tp_pb.TrafficQueue
 	if trafficQueues = getTrafficQueues(subs, tp_pb.Direction_DOWNSTREAM); trafficQueues == nil {
-		log.Error("Failed to create traffic queues")
+		logger.Error(nil, "Failed to create traffic queues")
 		return errors.New(ReasonCodeToReasonString(QUEUE_CREATION_FAILED))
 	}
 
 	// On receiving the CreateTrafficQueues request, the driver should create corresponding
 	// downstream queues.
-	log.Debugw("Sending Traffic Queues create to device",
+	logger.Debugw(nil, "Sending Traffic Queues create to device",
 		log.Fields{"Direction": tp_pb.Direction_DOWNSTREAM, "TrafficQueues": trafficQueues})
 	if _, err := subs.OpenOltClient.CreateTrafficQueues(context.Background(),
 		&tp_pb.TrafficQueues{IntfId: subs.PonIntf, OnuId: subs.OnuID,
 			UniId: subs.UniID, PortNo: subs.UniPortNo,
 			TrafficQueues: trafficQueues}); err != nil {
-		log.Errorw("Failed to create traffic queues in device", log.Fields{"error": err})
+		logger.Errorw(nil, "Failed to create traffic queues in device", log.Fields{"error": err})
 		return errors.New(ReasonCodeToReasonString(QUEUE_CREATION_FAILED))
 	}
 
 	if trafficQueues = getTrafficQueues(subs, tp_pb.Direction_UPSTREAM); trafficQueues == nil {
-		log.Error("Failed to create traffic queues")
+		logger.Error(nil, "Failed to create traffic queues")
 		return errors.New(ReasonCodeToReasonString(QUEUE_CREATION_FAILED))
 	}
 
 	// On receiving the CreateTrafficQueues request, the driver should create corresponding
 	// upstream queues.
-	log.Debugw("Sending Traffic Queues create to device",
+	logger.Debugw(nil, "Sending Traffic Queues create to device",
 		log.Fields{"Direction": tp_pb.Direction_UPSTREAM, "TrafficQueues": trafficQueues})
 	if _, err := subs.OpenOltClient.CreateTrafficQueues(context.Background(),
 		&tp_pb.TrafficQueues{IntfId: subs.PonIntf, OnuId: subs.OnuID,
 			UniId: subs.UniID, PortNo: subs.UniPortNo,
 			TrafficQueues: trafficQueues}); err != nil {
-		log.Errorw("Failed to create traffic queues in device", log.Fields{"error": err})
+		logger.Errorw(nil, "Failed to create traffic queues in device", log.Fields{"error": err})
 		return errors.New(ReasonCodeToReasonString(QUEUE_CREATION_FAILED))
 	}
 
@@ -121,29 +117,30 @@
 }
 
 func (dt DtWorkFlow) ProvisionEapFlow(subs *Subscriber) error {
-	log.Info("dt-workflow-does-not-require-eap-support--nothing-to-do")
+	logger.Info(nil, "dt-workflow-does-not-require-eap-support--nothing-to-do")
 	return nil
 }
 
 func (dt DtWorkFlow) ProvisionDhcpIPV4Flow(subs *Subscriber) error {
-	log.Info("dt-workflow-does-not-require-dhcp-ipv4-support--nothing-to-do")
+	logger.Info(nil, "dt-workflow-does-not-require-dhcp-ipv4-support--nothing-to-do")
 	return nil
 }
 
 func (dt DtWorkFlow) ProvisionDhcpIPV6Flow(subs *Subscriber) error {
-	log.Info("dt-workflow-does-not-require-dhcp-ipv6-support--nothing-to-do")
+	logger.Info(nil, "dt-workflow-does-not-require-dhcp-ipv6-support--nothing-to-do")
 	return nil
 }
 
 func (dt DtWorkFlow) ProvisionIgmpFlow(subs *Subscriber) error {
-	log.Info("dt-workflow-does-not-support-igmp-yet--nothing-to-do")
+	logger.Info(nil, "dt-workflow-does-not-support-igmp-yet--nothing-to-do")
 	return nil
 }
 
 func (dt DtWorkFlow) ProvisionHsiaFlow(subs *Subscriber) error {
 	var err error
-	var flowID uint32
+	var flowIDUs, flowIDDs uint64
 	var gemPortIDs []uint32
+	pbitToGem := make(map[uint32]uint32)
 
 	var allocID = subs.TpInstance[subs.TestConfig.TpIDList[0]].UsScheduler.AllocID
 	for _, gem := range subs.TpInstance[subs.TestConfig.TpIDList[0]].UpstreamGemPortAttributeList {
@@ -155,38 +152,46 @@
 		for pos, pbitSet := range strings.TrimPrefix(pBitMap, "0b") {
 			if pbitSet == '1' {
 				pcp := uint32(len(strings.TrimPrefix(pBitMap, "0b"))) - 1 - uint32(pos)
-				if flowID, err = subs.RsrMgr.GetFlowID(context.Background(), uint32(subs.PonIntf)); err != nil {
-					return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
-				} else {
-					if err := AddFlow(subs, HsiaFlow, Upstream, flowID, allocID, gemID, pcp); err != nil {
-						return err
-					}
-					if err := AddFlow(subs, HsiaFlow, Downstream, flowID, allocID, gemID, pcp); err != nil {
-						return err
-					}
-				}
+				pbitToGem[pcp] = gemID
 			}
 		}
 	}
+
+	// This flowID is not the BAL flow ID now, it is the voltha-flow-id
+	if flowIDUs, err = subs.RsrMgr.GetFlowID(context.Background(), uint32(subs.PonIntf)); err != nil {
+		return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
+	}
+	if err := AddFlow(subs, HsiaFlow, Upstream, flowIDUs, allocID, 0, 0xff,
+		true, 0, pbitToGem); err != nil {
+		return err
+	}
+	if flowIDDs, err = subs.RsrMgr.GetFlowID(context.Background(), uint32(subs.PonIntf)); err != nil {
+		return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
+	}
+	if err := AddFlow(subs, HsiaFlow, Downstream, flowIDDs, allocID, 0, 0xff,
+		true, flowIDUs, pbitToGem); err != nil {
+		return err
+	}
+
 	return nil
 }
 
 func (dt DtWorkFlow) ProvisionVoipFlow(subs *Subscriber) error {
-	log.Info("dt-workflow-does-not-support-voip-yet--nothing-to-do")
+	logger.Info(nil, "dt-workflow-does-not-support-voip-yet--nothing-to-do")
 	return nil
 }
 
 func (dt DtWorkFlow) ProvisionVodFlow(subs *Subscriber) error {
-	log.Info("dt-workflow-does-not-support-vod-yet--nothing-to-do")
+	logger.Info(nil, "dt-workflow-does-not-support-vod-yet--nothing-to-do")
 	return nil
 }
 
 func (dt DtWorkFlow) ProvisionMgmtFlow(subs *Subscriber) error {
-	log.Info("dt-workflow-does-not-support-mgmt-yet--nothing-to-do")
+	logger.Info(nil, "dt-workflow-does-not-support-mgmt-yet--nothing-to-do")
 	return nil
 }
 
 func (dt DtWorkFlow) ProvisionMulticastFlow(subs *Subscriber) error {
-	log.Info("dt-workflow-does-not-support-multicast-yet--nothing-to-do")
+	logger.Info(nil, "dt-workflow-does-not-support-multicast-yet--nothing-to-do")
 	return nil
 }
diff --git a/core/olt_manager.go b/core/olt_manager.go
index f4e3143..ab171ef 100644
--- a/core/olt_manager.go
+++ b/core/olt_manager.go
@@ -32,10 +32,10 @@
 
 	"github.com/cenkalti/backoff/v3"
 	"github.com/opencord/openolt-scale-tester/config"
-	"github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore"
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-	"github.com/opencord/voltha-lib-go/v3/pkg/techprofile"
-	oop "github.com/opencord/voltha-protos/v3/go/openolt"
+	"github.com/opencord/voltha-lib-go/v4/pkg/db/kvstore"
+	"github.com/opencord/voltha-lib-go/v4/pkg/log"
+	"github.com/opencord/voltha-lib-go/v4/pkg/techprofile"
+	oop "github.com/opencord/voltha-protos/v4/go/openolt"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
@@ -52,28 +52,24 @@
 }
 
 type OpenOltManager struct {
-	ipPort        string
-	deviceInfo    *oop.DeviceInfo
-	OnuDeviceMap  map[OnuDeviceKey]*OnuDevice `json:"onuDeviceMap"`
-	TechProfile   map[uint32]*techprofile.TechProfileIf
-	clientConn    *grpc.ClientConn
-	openOltClient oop.OpenoltClient
-	testConfig    *config.OpenOltScaleTesterConfig
-	rsrMgr        *OpenOltResourceMgr
-	lockRsrAlloc  sync.RWMutex
+	ipPort             string
+	deviceInfo         *oop.DeviceInfo
+	OnuDeviceMap       map[OnuDeviceKey]*OnuDevice `json:"onuDeviceMap"`
+	TechProfile        map[uint32]*techprofile.TechProfileIf
+	clientConn         *grpc.ClientConn
+	openOltClient      oop.OpenoltClient
+	testConfig         *config.OpenOltScaleTesterConfig
+	rsrMgr             *OpenOltResourceMgr
+	lockRsrAlloc       sync.RWMutex
 	lockOpenOltManager sync.RWMutex
 }
 
-func init() {
-	_, _ = log.AddPackage(log.JSON, log.DebugLevel, nil)
-}
-
 func NewOpenOltManager(ipPort string) *OpenOltManager {
-	log.Infow("initialized openolt manager with ipPort", log.Fields{"ipPort": ipPort})
+	logger.Infow(nil, "initialized openolt manager with ipPort", log.Fields{"ipPort": ipPort})
 	return &OpenOltManager{
-		ipPort:       ipPort,
-		OnuDeviceMap: make(map[OnuDeviceKey]*OnuDevice),
-		lockRsrAlloc: sync.RWMutex{},
+		ipPort:             ipPort,
+		OnuDeviceMap:       make(map[OnuDeviceKey]*OnuDevice),
+		lockRsrAlloc:       sync.RWMutex{},
 		lockOpenOltManager: sync.RWMutex{},
 	}
 }
@@ -83,9 +79,9 @@
 	var err error
 	// Verify that etcd is up before starting the application.
 	etcdIpPort := "http://" + om.testConfig.KVStoreHost + ":" + strconv.Itoa(om.testConfig.KVStorePort)
-	client, err := kvstore.NewEtcdClient(etcdIpPort, 5)
+	client, err := kvstore.NewEtcdClient(context.Background(), etcdIpPort, 5*time.Second, log.FatalLevel)
 	if err != nil || client == nil {
-		log.Fatal("error-initializing-etcd-client")
+		logger.Fatal(nil, "error-initializing-etcd-client")
 		return
 	}
 
@@ -98,40 +94,40 @@
 		jsonFile, err := os.Open(tpFilePath)
 		// if we os.Open returns an error then handle it
 		if err != nil {
-			log.Fatalw("could-not-find-tech-profile", log.Fields{"err": err, "tpFile": tpFilePath})
+			logger.Fatalw(nil, "could-not-find-tech-profile", log.Fields{"err": err, "tpFile": tpFilePath})
 		}
-		log.Debugw("tp-file-opened-successfully", log.Fields{"tpFile": tpFilePath})
+		logger.Debugw(nil, "tp-file-opened-successfully", log.Fields{"tpFile": tpFilePath})
 
 		// read our opened json file as a byte array.
 		if byteValue, err = ioutil.ReadAll(jsonFile); err != nil {
-			log.Fatalw("could-not-read-tp-file", log.Fields{"err": err, "tpFile": tpFilePath})
+			logger.Fatalw(nil, "could-not-read-tp-file", log.Fields{"err": err, "tpFile": tpFilePath})
 		}
 
 		var tp techprofile.TechProfile
 
 		if err = json.Unmarshal(byteValue, &tp); err != nil {
-			log.Fatalw("could-not-unmarshal-tp", log.Fields{"err": err, "tpFile": tpFilePath})
+			logger.Fatalw(nil, "could-not-unmarshal-tp", log.Fields{"err": err, "tpFile": tpFilePath})
 		} else {
-			log.Infow("tp-read-from-file", log.Fields{"tp": tp, "tpFile": tpFilePath})
+			logger.Infow(nil, "tp-read-from-file", log.Fields{"tp": tp, "tpFile": tpFilePath})
 		}
 		kvPath := fmt.Sprintf(TechProfileKVPath, om.deviceInfo.Technology, tpID)
 		tpJson, err := json.Marshal(tp)
 		err = client.Put(context.Background(), kvPath, tpJson)
 		if err != nil {
-			log.Fatalw("tp-put-to-etcd-failed", log.Fields{"tpPath": kvPath, "err": err})
+			logger.Fatalw(nil, "tp-put-to-etcd-failed", log.Fields{"tpPath": kvPath, "err": err})
 		}
 		// verify the PUT succeeded.
 		kvResult, err := client.Get(context.Background(), kvPath)
 		if kvResult == nil {
-			log.Fatal("tp-not-found-on-kv-after-load", log.Fields{"key": kvPath, "err": err})
+			logger.Fatal(nil, "tp-not-found-on-kv-after-load", log.Fields{"key": kvPath, "err": err})
 		} else {
 			var KvTpIns techprofile.TechProfile
 			var resPtr = &KvTpIns
 			if value, err := kvstore.ToByte(kvResult.Value); err == nil {
 				if err = json.Unmarshal(value, resPtr); err != nil {
-					log.Fatal("error-unmarshal-kv-result", log.Fields{"err": err, "key": kvPath, "value": value})
+					logger.Fatal(nil, "error-unmarshal-kv-result", log.Fields{"err": err, "key": kvPath, "value": value})
 				} else {
-					log.Infow("verified-ok-that-tp-load-was-good", log.Fields{"tpID": tpID, "kvPath": kvPath})
+					logger.Infow(nil, "verified-ok-that-tp-load-was-good", log.Fields{"tpID": tpID, "kvPath": kvPath})
 					_ = jsonFile.Close()
 					continue
 				}
@@ -146,31 +142,31 @@
 
 	// Establish gRPC connection with the device
 	if om.clientConn, err = grpc.Dial(om.ipPort, grpc.WithInsecure(), grpc.WithBlock()); err != nil {
-		log.Errorw("Failed to dial device", log.Fields{"ipPort": om.ipPort, "err": err})
+		logger.Errorw(nil, "Failed to dial device", log.Fields{"ipPort": om.ipPort, "err": err})
 		return err
 	}
 	om.openOltClient = oop.NewOpenoltClient(om.clientConn)
 
 	// Populate Device Info
 	if deviceInfo, err := om.populateDeviceInfo(); err != nil {
-		log.Error("error fetching device info", log.Fields{"err": err, "deviceInfo": deviceInfo})
+		logger.Error(nil, "error fetching device info", log.Fields{"err": err, "deviceInfo": deviceInfo})
 		return err
 	}
 
 	// Read and load TPs to etcd.
 	om.readAndLoadTPsToEtcd()
 
-	log.Info("etcd-up-and-running--tp-loaded-successfully")
+	logger.Info(nil, "etcd-up-and-running--tp-loaded-successfully")
 
 	if om.rsrMgr = NewResourceMgr("ABCD", om.testConfig.KVStoreHost+":"+strconv.Itoa(om.testConfig.KVStorePort),
 		"etcd", "openolt", om.deviceInfo); om.rsrMgr == nil {
-		log.Error("Error while instantiating resource manager")
+		logger.Error(nil, "Error while instantiating resource manager")
 		return errors.New("instantiating resource manager failed")
 	}
 
 	om.TechProfile = make(map[uint32]*techprofile.TechProfileIf)
 	if err = om.populateTechProfilePerPonPort(); err != nil {
-		log.Error("Error while populating tech profile mgr\n")
+		logger.Error(nil, "Error while populating tech profile mgr\n")
 		return errors.New("error-loading-tech-profile-per-ponPort")
 	}
 
@@ -179,7 +175,7 @@
 
 	// Provision OLT NNI Trap flows as needed by the Workflow
 	if err = ProvisionNniTrapFlow(om.openOltClient, om.testConfig, om.rsrMgr); err != nil {
-		log.Error("failed-to-add-nni-trap-flow", log.Fields{"err": err})
+		logger.Error(nil, "failed-to-add-nni-trap-flow", log.Fields{"err": err})
 	}
 
 	// Provision ONUs one by one
@@ -193,16 +189,16 @@
 	var err error
 
 	if om.deviceInfo, err = om.openOltClient.GetDeviceInfo(context.Background(), new(oop.Empty)); err != nil {
-		log.Errorw("Failed to fetch device info", log.Fields{"err": err})
+		logger.Errorw(nil, "Failed to fetch device info", log.Fields{"err": err})
 		return nil, err
 	}
 
 	if om.deviceInfo == nil {
-		log.Errorw("Device info is nil", log.Fields{})
+		logger.Errorw(nil, "Device info is nil", log.Fields{})
 		return nil, errors.New("failed to get device info from OLT")
 	}
 
-	log.Debugw("Fetched device info", log.Fields{"deviceInfo": om.deviceInfo})
+	logger.Debugw(nil, "Fetched device info", log.Fields{"deviceInfo": om.deviceInfo})
 
 	return om.deviceInfo, nil
 }
@@ -221,20 +217,20 @@
 	// If the number of ONUs to provision is not a power of 2, stop execution
 	// This is needed for ensure even distribution of ONUs across all PONs
 	if !isPowerOfTwo(om.testConfig.NumOfOnu) {
-		log.Errorw("num-of-onus-to-provision-is-not-a-power-of-2", log.Fields{"numOfOnus": om.testConfig.NumOfOnu})
+		logger.Errorw(nil, "num-of-onus-to-provision-is-not-a-power-of-2", log.Fields{"numOfOnus": om.testConfig.NumOfOnu})
 		return
 	}
 
 	// Number of ONUs to provision should not be less than the number of PON ports.
 	// We need at least one ONU per PON
 	if om.testConfig.NumOfOnu < uint(om.deviceInfo.PonPorts) {
-		log.Errorw("num-of-onu-is-less-than-num-of-pon-port", log.Fields{"numOfOnus":om.testConfig.NumOfOnu, "numOfPon": om.deviceInfo.PonPorts})
+		logger.Errorw(nil, "num-of-onu-is-less-than-num-of-pon-port", log.Fields{"numOfOnus": om.testConfig.NumOfOnu, "numOfPon": om.deviceInfo.PonPorts})
 		return
 	}
 
 	numOfONUsPerPon = om.testConfig.NumOfOnu / uint(om.deviceInfo.PonPorts)
 	totalOnusToProvision := numOfONUsPerPon * uint(om.deviceInfo.PonPorts)
-	log.Infow("***** all-onu-provision-started ******",
+	logger.Infow(nil, "***** all-onu-provision-started ******",
 		log.Fields{"totalNumOnus": totalOnusToProvision,
 			"numOfOnusPerPon": numOfONUsPerPon,
 			"numOfPons":       om.deviceInfo.PonPorts})
@@ -258,12 +254,12 @@
 				om.lockRsrAlloc.Lock()
 				sn := GenerateNextONUSerialNumber()
 				om.lockRsrAlloc.Unlock()
-				log.Debugw("provisioning onu", log.Fields{"onuID": j, "ponPort": i, "serialNum": sn})
+				logger.Debugw(nil, "provisioning onu", log.Fields{"onuID": j, "ponPort": i, "serialNum": sn})
 				if onuID, err = om.rsrMgr.GetONUID(j); err != nil {
-					log.Errorw("error getting onu id", log.Fields{"err": err})
+					logger.Errorw(nil, "error getting onu id", log.Fields{"err": err})
 					continue
 				}
-				log.Infow("onu-provision-started-from-olt-manager", log.Fields{"onuId": onuID, "ponIntf": i})
+				logger.Infow(nil, "onu-provision-started-from-olt-manager", log.Fields{"onuId": onuID, "ponIntf": i})
 
 				onuWg.Add(1)
 				go om.activateONU(j, onuID, sn, om.stringifySerialNumber(sn), &onuWg)
@@ -273,10 +269,10 @@
 		onuWg.Wait()
 	}
 	endTime := time.Now()
-	log.Info("******** all-onu-provisioning-completed *******")
+	logger.Info(nil, "******** all-onu-provisioning-completed *******")
 	totalTime := endTime.Sub(startTime)
 	out := time.Time{}.Add(totalTime)
-	log.Infof("****** Total Time to provision all the ONUs is => %s", out.Format("15:04:05"))
+	logger.Infof(nil, "****** Total Time to provision all the ONUs is => %s", out.Format("15:04:05"))
 
 	// TODO: We need to dump the results at the end. But below json marshall does not work. We will need custom Marshal function.
 	/*
@@ -290,7 +286,7 @@
 }
 
 func (om *OpenOltManager) activateONU(intfID uint32, onuID uint32, serialNum *oop.SerialNumber, serialNumber string, onuWg *sync.WaitGroup) {
-	log.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
+	logger.Debugw(nil, "activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
 	// TODO: need resource manager
 	var pir uint32 = 1000000
 	var onuDevice = OnuDevice{
@@ -312,13 +308,13 @@
 	if _, err = om.openOltClient.ActivateOnu(context.Background(), &Onu); err != nil {
 		st, _ := status.FromError(err)
 		if st.Code() == codes.AlreadyExists {
-			log.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
+			logger.Debug(nil, "ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
 		} else {
 			nanos = now.UnixNano()
 			milliEnd := nanos / 1000000
 			onuDevice.OnuProvisionEndTime = time.Unix(0, nanos)
 			onuDevice.OnuProvisionDurationInMs = milliEnd - milliStart
-			log.Errorw("activate-onu-failed", log.Fields{"Onu": Onu, "err ": err})
+			logger.Errorw(nil, "activate-onu-failed", log.Fields{"Onu": Onu, "err ": err})
 			onuDevice.Reason = err.Error()
 		}
 	} else {
@@ -327,7 +323,7 @@
 		onuDevice.OnuProvisionEndTime = time.Unix(0, nanos)
 		onuDevice.OnuProvisionDurationInMs = milliEnd - milliStart
 		onuDevice.Reason = ReasonOk
-		log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
+		logger.Infow(nil, "activated-onu", log.Fields{"SerialNumber": serialNumber})
 	}
 
 	om.lockOpenOltManager.Lock()
@@ -364,14 +360,14 @@
 
 // readIndications to read the indications from the OLT device
 func (om *OpenOltManager) readIndications() {
-	defer log.Errorw("Indications ended", log.Fields{})
+	defer logger.Errorw(nil, "Indications ended", log.Fields{})
 	indications, err := om.openOltClient.EnableIndication(context.Background(), new(oop.Empty))
 	if err != nil {
-		log.Errorw("Failed to read indications", log.Fields{"err": err})
+		logger.Errorw(nil, "Failed to read indications", log.Fields{"err": err})
 		return
 	}
 	if indications == nil {
-		log.Errorw("Indications is nil", log.Fields{})
+		logger.Errorw(nil, "Indications is nil", log.Fields{})
 		return
 	}
 
@@ -385,26 +381,26 @@
 	for {
 		indication, err := indications.Recv()
 		if err == io.EOF {
-			log.Infow("EOF for  indications", log.Fields{"err": err})
+			logger.Infow(nil, "EOF for  indications", log.Fields{"err": err})
 			// Use an exponential back off to prevent getting into a tight loop
 			duration := indicationBackoff.NextBackOff()
 			if duration == backoff.Stop {
 				// If we reach a maximum then warn and reset the backoff
 				// timer and keep attempting.
-				log.Warnw("Maximum indication backoff reached, resetting backoff timer",
+				logger.Warnw(nil, "Maximum indication backoff reached, resetting backoff timer",
 					log.Fields{"max_indication_backoff": indicationBackoff.MaxElapsedTime})
 				indicationBackoff.Reset()
 			}
 			time.Sleep(indicationBackoff.NextBackOff())
 			indications, err = om.openOltClient.EnableIndication(context.Background(), new(oop.Empty))
 			if err != nil {
-				log.Errorw("Failed to read indications", log.Fields{"err": err})
+				logger.Errorw(nil, "Failed to read indications", log.Fields{"err": err})
 				return
 			}
 			continue
 		}
 		if err != nil {
-			log.Infow("Failed to read from indications", log.Fields{"err": err})
+			logger.Infow(nil, "Failed to read from indications", log.Fields{"err": err})
 			break
 		}
 		// Reset backoff if we have a successful receive
@@ -417,42 +413,42 @@
 func (om *OpenOltManager) handleIndication(indication *oop.Indication) {
 	switch indication.Data.(type) {
 	case *oop.Indication_OltInd:
-		log.Info("received olt indication")
+		logger.Info(nil, "received olt indication")
 	case *oop.Indication_IntfInd:
 		intfInd := indication.GetIntfInd()
-		log.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
+		logger.Infow(nil, "Received interface indication ", log.Fields{"InterfaceInd": intfInd})
 	case *oop.Indication_IntfOperInd:
 		intfOperInd := indication.GetIntfOperInd()
 		if intfOperInd.GetType() == "nni" {
-			log.Info("received interface oper indication for nni port")
+			logger.Info(nil, "received interface oper indication for nni port")
 		} else if intfOperInd.GetType() == "pon" {
-			log.Info("received interface oper indication for pon port")
+			logger.Info(nil, "received interface oper indication for pon port")
 		}
 		/*
 			case *oop.Indication_OnuDiscInd:
 				onuDiscInd := indication.GetOnuDiscInd()
-				log.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
+				logger.Infow(nil, "Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
 		*/
 	case *oop.Indication_OnuInd:
 		onuInd := indication.GetOnuInd()
-		log.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
+		logger.Infow(nil, "Received Onu indication ", log.Fields{"OnuInd": onuInd})
 	case *oop.Indication_OmciInd:
 		omciInd := indication.GetOmciInd()
-		log.Debugw("Received Omci indication ", log.Fields{"IntfId": omciInd.IntfId, "OnuId": omciInd.OnuId, "pkt": hex.EncodeToString(omciInd.Pkt)})
+		logger.Debugw(nil, "Received Omci indication ", log.Fields{"IntfId": omciInd.IntfId, "OnuId": omciInd.OnuId, "pkt": hex.EncodeToString(omciInd.Pkt)})
 	case *oop.Indication_PktInd:
 		pktInd := indication.GetPktInd()
-		log.Infow("Received packet indication ", log.Fields{"PktInd": pktInd})
+		logger.Infow(nil, "Received packet indication ", log.Fields{"PktInd": pktInd})
 		/*
 				case *oop.Indication_PortStats:
 				portStats := indication.GetPortStats()
-				log.Infow("Received port stats", log.Fields{"portStats": portStats})
+				logger.Infow(nil, "Received port stats", log.Fields{"portStats": portStats})
 			case *oop.Indication_FlowStats:
 				flowStats := indication.GetFlowStats()
-				log.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
+				logger.Infow(nil, "Received flow stats", log.Fields{"FlowStats": flowStats})
 		*/
 	case *oop.Indication_AlarmInd:
 		alarmInd := indication.GetAlarmInd()
-		log.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
+		logger.Infow(nil, "Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
 	}
 }
 
@@ -462,20 +458,20 @@
 		for _, intfID := range techRange.IntfIds {
 			om.TechProfile[intfID] = &(om.rsrMgr.ResourceMgrs[intfID].TechProfileMgr)
 			tpCount++
-			log.Debugw("Init tech profile done", log.Fields{"intfID": intfID})
+			logger.Debugw(nil, "Init tech profile done", log.Fields{"intfID": intfID})
 		}
 	}
 	//Make sure we have as many tech_profiles as there are pon ports on the device
 	if tpCount != int(om.deviceInfo.GetPonPorts()) {
-		log.Errorw("Error while populating techprofile",
+		logger.Errorw(nil, "Error while populating techprofile",
 			log.Fields{"numofTech": tpCount, "numPonPorts": om.deviceInfo.GetPonPorts()})
 		return errors.New("error while populating techprofile mgrs")
 	}
-	log.Infow("Populated techprofile for ponports successfully",
+	logger.Infow(nil, "Populated techprofile for ponports successfully",
 		log.Fields{"numofTech": tpCount, "numPonPorts": om.deviceInfo.GetPonPorts()})
 	return nil
 }
 
 func isPowerOfTwo(numOfOnus uint) bool {
 	return (numOfOnus & (numOfOnus - 1)) == 0
-}
\ No newline at end of file
+}
diff --git a/core/onu_manager.go b/core/onu_manager.go
index 4fd665b..5b44b28 100644
--- a/core/onu_manager.go
+++ b/core/onu_manager.go
@@ -22,14 +22,10 @@
 	"time"
 
 	"github.com/opencord/openolt-scale-tester/config"
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-	oop "github.com/opencord/voltha-protos/v3/go/openolt"
+	"github.com/opencord/voltha-lib-go/v4/pkg/log"
+	oop "github.com/opencord/voltha-protos/v4/go/openolt"
 )
 
-func init() {
-	_, _ = log.AddPackage(log.JSON, log.DebugLevel, nil)
-}
-
 type SubscriberKey struct {
 	SubscriberName string
 }
@@ -53,7 +49,7 @@
 	onu.SubscriberMap = make(map[SubscriberKey]*Subscriber)
 	var subs uint
 	var subWg sync.WaitGroup
-	log.Infow("onu-provision-started-from-onu-manager", log.Fields{"onuID": onu.OnuID, "ponIntf": onu.PonIntf})
+	logger.Infow(nil, "onu-provision-started-from-onu-manager", log.Fields{"onuID": onu.OnuID, "ponIntf": onu.PonIntf})
 
 	for subs = 0; subs < onu.testConfig.SubscribersPerOnu; subs++ {
 		subsName := onu.SerialNum + "-" + strconv.Itoa(int(subs))
@@ -74,7 +70,7 @@
 		onu.SubscriberMap[subsKey] = &subs
 
 		subWg.Add(1)
-		log.Infow("subscriber-provision-started-from-onu-manager", log.Fields{"subsName": subsName})
+		logger.Infow(nil, "subscriber-provision-started-from-onu-manager", log.Fields{"subsName": subsName})
 		// Start provisioning the subscriber
 		go subs.Start(onu.testConfig.IsGroupTest)
 
@@ -85,5 +81,5 @@
 	// Signal that ONU provisioning is complete
 	onu.onuWg.Done()
 
-	log.Infow("onu-provision-completed-from-onu-manager", log.Fields{"onuID": onu.OnuID, "ponIntf": onu.PonIntf})
+	logger.Infow(nil, "onu-provision-completed-from-onu-manager", log.Fields{"onuID": onu.OnuID, "ponIntf": onu.PonIntf})
 }
diff --git a/core/resource_manager.go b/core/resource_manager.go
index d8674c9..255e1be 100644
--- a/core/resource_manager.go
+++ b/core/resource_manager.go
@@ -18,20 +18,14 @@
 package core
 
 import (
-	"strconv"
-	"strings"
 	"sync"
 
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-	ponrmgr "github.com/opencord/voltha-lib-go/v3/pkg/ponresourcemanager"
-	"github.com/opencord/voltha-protos/v3/go/openolt"
+	"github.com/opencord/voltha-lib-go/v4/pkg/log"
+	ponrmgr "github.com/opencord/voltha-lib-go/v4/pkg/ponresourcemanager"
+	"github.com/opencord/voltha-protos/v4/go/openolt"
 	"golang.org/x/net/context"
 )
 
-func init() {
-	_, _ = log.AddPackage(log.JSON, log.DebugLevel, nil)
-}
-
 // OpenOltResourceMgr holds resource related information as provided below for each field
 type OpenOltResourceMgr struct {
 	deviceInfo *openolt.DeviceInfo
@@ -47,6 +41,8 @@
 
 	// array of pon resource managers per interface technology
 	ResourceMgrs map[uint32]*ponrmgr.PONResourceManager
+
+	flow_id uint64
 }
 
 // NewResourceMgr init a New resource manager instance which in turn instantiates pon resource manager
@@ -54,7 +50,7 @@
 // the resources.
 func NewResourceMgr(deviceID string, KVStoreHostPort string, kvStoreType string, deviceType string, devInfo *openolt.DeviceInfo) *OpenOltResourceMgr {
 	var ResourceMgr OpenOltResourceMgr
-	log.Debugf("Init new resource manager")
+	logger.Debugf(nil, "Init new resource manager")
 
 	ResourceMgr.deviceInfo = devInfo
 	NumPONPorts := devInfo.GetPonPorts()
@@ -118,16 +114,14 @@
 	// each technology is represented by only a single range
 	var GlobalPONRsrcMgr *ponrmgr.PONResourceManager
 	var err error
-	IPPort := strings.Split(KVStoreHostPort, ":")
 	for _, TechRange := range devInfo.Ranges {
 		technology := TechRange.Technology
-		log.Debugf("Device info technology %s", technology)
+		logger.Debugf(nil, "Device info technology %s", technology)
 		Ranges[technology] = TechRange
-		port, _ := strconv.Atoi(IPPort[1])
-		RsrcMgrsByTech[technology], err = ponrmgr.NewPONResourceManager(technology, deviceType, deviceID,
-			kvStoreType, IPPort[0], port)
+		RsrcMgrsByTech[technology], err = ponrmgr.NewPONResourceManager(nil, technology, deviceType, deviceID,
+			kvStoreType, KVStoreHostPort)
 		if err != nil {
-			log.Errorf("Failed to create pon resource manager instance for technology %s", technology)
+			logger.Errorf(nil, "Failed to create pon resource manager instance for technology %s", technology)
 			return nil
 		}
 		// resource_mgrs_by_tech[technology] = resource_mgr
@@ -146,7 +140,7 @@
 	for _, PONRMgr := range RsrcMgrsByTech {
 		_ = PONRMgr.InitDeviceResourcePool(context.Background())
 	}
-	log.Info("Initialization of  resource manager success!")
+	logger.Info(nil, "Initialization of  resource manager success!")
 	return &ResourceMgr
 }
 
@@ -159,11 +153,11 @@
 
 	// init the resource range pool according to the sharing type
 
-	log.Debugf("Resource range pool init for technology %s", ponRMgr.Technology)
+	logger.Debugf(nil, "Resource range pool init for technology %s", ponRMgr.Technology)
 	// first load from KV profiles
 	status := ponRMgr.InitResourceRangesFromKVStore(context.Background())
 	if !status {
-		log.Debugf("Failed to load resource ranges from KV store for tech %s", ponRMgr.Technology)
+		logger.Debugf(nil, "Failed to load resource ranges from KV store for tech %s", ponRMgr.Technology)
 	}
 
 	/*
@@ -171,7 +165,7 @@
 	   or is broader than the device, the device's information will
 	   dictate the range limits
 	*/
-	log.Debugf("Using device info to init pon resource ranges for tech", ponRMgr.Technology)
+	logger.Debugf(nil, "Using device info to init pon resource ranges for tech", ponRMgr.Technology)
 
 	ONUIDStart := devInfo.OnuIdStart
 	ONUIDEnd := devInfo.OnuIdEnd
@@ -236,7 +230,7 @@
 		}
 	}
 
-	log.Debugw("Device info init", log.Fields{"technology": techRange.Technology,
+	logger.Debugw(nil, "Device info init", log.Fields{"technology": techRange.Technology,
 		"onu_id_start": ONUIDStart, "onu_id_end": ONUIDEnd, "onu_id_shared_pool_id": ONUIDSharedPoolID,
 		"alloc_id_start": AllocIDStart, "alloc_id_end": AllocIDEnd,
 		"alloc_id_shared_pool_id": AllocIDSharedPoolID,
@@ -250,7 +244,7 @@
 		"uni_id_end_idx":            1, /*MaxUNIIDperONU()*/
 	})
 
-	ponRMgr.InitDefaultPONResourceRanges(ONUIDStart, ONUIDEnd, ONUIDSharedPoolID,
+	ponRMgr.InitDefaultPONResourceRanges(nil, ONUIDStart, ONUIDEnd, ONUIDSharedPoolID,
 		AllocIDStart, AllocIDEnd, AllocIDSharedPoolID,
 		GEMPortIDStart, GEMPortIDEnd, GEMPortIDSharedPoolID,
 		FlowIDStart, FlowIDEnd, FlowIDSharedPoolID, 0, 1,
@@ -259,44 +253,44 @@
 	// For global sharing, make sure to refresh both local and global resource manager instances' range
 
 	if ONUIDShared == openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH {
-		globalPONRMgr.UpdateRanges(ponrmgr.ONU_ID_START_IDX, ONUIDStart, ponrmgr.ONU_ID_END_IDX, ONUIDEnd,
+		globalPONRMgr.UpdateRanges(nil, ponrmgr.ONU_ID_START_IDX, ONUIDStart, ponrmgr.ONU_ID_END_IDX, ONUIDEnd,
 			"", 0, nil)
-		ponRMgr.UpdateRanges(ponrmgr.ONU_ID_START_IDX, ONUIDStart, ponrmgr.ONU_ID_END_IDX, ONUIDEnd,
+		ponRMgr.UpdateRanges(nil, ponrmgr.ONU_ID_START_IDX, ONUIDStart, ponrmgr.ONU_ID_END_IDX, ONUIDEnd,
 			"", 0, globalPONRMgr)
 	}
 	if AllocIDShared == openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH {
-		globalPONRMgr.UpdateRanges(ponrmgr.ALLOC_ID_START_IDX, AllocIDStart, ponrmgr.ALLOC_ID_END_IDX, AllocIDEnd,
+		globalPONRMgr.UpdateRanges(nil, ponrmgr.ALLOC_ID_START_IDX, AllocIDStart, ponrmgr.ALLOC_ID_END_IDX, AllocIDEnd,
 			"", 0, nil)
 
-		ponRMgr.UpdateRanges(ponrmgr.ALLOC_ID_START_IDX, AllocIDStart, ponrmgr.ALLOC_ID_END_IDX, AllocIDEnd,
+		ponRMgr.UpdateRanges(nil, ponrmgr.ALLOC_ID_START_IDX, AllocIDStart, ponrmgr.ALLOC_ID_END_IDX, AllocIDEnd,
 			"", 0, globalPONRMgr)
 	}
 	if GEMPortIDShared == openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH {
-		globalPONRMgr.UpdateRanges(ponrmgr.GEMPORT_ID_START_IDX, GEMPortIDStart, ponrmgr.GEMPORT_ID_END_IDX, GEMPortIDEnd,
+		globalPONRMgr.UpdateRanges(nil, ponrmgr.GEMPORT_ID_START_IDX, GEMPortIDStart, ponrmgr.GEMPORT_ID_END_IDX, GEMPortIDEnd,
 			"", 0, nil)
-		ponRMgr.UpdateRanges(ponrmgr.GEMPORT_ID_START_IDX, GEMPortIDStart, ponrmgr.GEMPORT_ID_END_IDX, GEMPortIDEnd,
+		ponRMgr.UpdateRanges(nil, ponrmgr.GEMPORT_ID_START_IDX, GEMPortIDStart, ponrmgr.GEMPORT_ID_END_IDX, GEMPortIDEnd,
 			"", 0, globalPONRMgr)
 	}
 	if FlowIDShared == openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH {
-		globalPONRMgr.UpdateRanges(ponrmgr.FLOW_ID_START_IDX, FlowIDStart, ponrmgr.FLOW_ID_END_IDX, FlowIDEnd,
+		globalPONRMgr.UpdateRanges(nil, ponrmgr.FLOW_ID_START_IDX, FlowIDStart, ponrmgr.FLOW_ID_END_IDX, FlowIDEnd,
 			"", 0, nil)
-		ponRMgr.UpdateRanges(ponrmgr.FLOW_ID_START_IDX, FlowIDStart, ponrmgr.FLOW_ID_END_IDX, FlowIDEnd,
+		ponRMgr.UpdateRanges(nil, ponrmgr.FLOW_ID_START_IDX, FlowIDStart, ponrmgr.FLOW_ID_END_IDX, FlowIDEnd,
 			"", 0, globalPONRMgr)
 	}
 
 	// Make sure loaded range fits the platform bit encoding ranges
-	ponRMgr.UpdateRanges(ponrmgr.UNI_ID_START_IDX, 0, ponrmgr.UNI_ID_END_IDX /* TODO =OpenOltPlatform.MAX_UNIS_PER_ONU-1*/, 1, "", 0, nil)
+	ponRMgr.UpdateRanges(nil, ponrmgr.UNI_ID_START_IDX, 0, ponrmgr.UNI_ID_END_IDX /* TODO =OpenOltPlatform.MAX_UNIS_PER_ONU-1*/, 1, "", 0, nil)
 }
 
 // Delete clears used resources for the particular olt device being deleted
 func (RsrcMgr *OpenOltResourceMgr) Delete() error {
 	for _, rsrcMgr := range RsrcMgr.ResourceMgrs {
 		if err := rsrcMgr.ClearDeviceResourcePool(context.Background()); err != nil {
-			log.Debug("Failed to clear device resource pool")
+			logger.Debug(nil, "Failed to clear device resource pool")
 			return err
 		}
 	}
-	log.Debug("Cleared device resource pool")
+	logger.Debug(nil, "Cleared device resource pool")
 	return nil
 }
 
@@ -308,7 +302,7 @@
 	ONUIDs, err := RsrcMgr.ResourceMgrs[ponIntfID].GetResourceID(context.Background(), ponIntfID,
 		ponrmgr.ONU_ID, 1)
 	if err != nil {
-		log.Errorf("Failed to get resource for interface %d for type %s",
+		logger.Errorf(nil, "Failed to get resource for interface %d for type %s",
 			ponIntfID, ponrmgr.ONU_ID)
 		return uint32(0), err
 	}
@@ -316,15 +310,9 @@
 }
 
 // GetFlowID return flow ID for a given pon interface id, onu id and uni id
-func (RsrcMgr *OpenOltResourceMgr) GetFlowID(ctx context.Context, ponIntfID uint32) (uint32, error) {
+func (RsrcMgr *OpenOltResourceMgr) GetFlowID(ctx context.Context, ponIntfID uint32) (uint64, error) {
 	RsrcMgr.FlowIDMgmtLock.Lock()
 	defer RsrcMgr.FlowIDMgmtLock.Unlock()
-	FlowIDs, err := RsrcMgr.ResourceMgrs[ponIntfID].GetResourceID(context.Background(), ponIntfID,
-		ponrmgr.FLOW_ID, 1)
-	if err != nil {
-		log.Errorf("Failed to get resource for interface %d for type %s",
-			ponIntfID, ponrmgr.FLOW_ID)
-		return uint32(0), err
-	}
-	return FlowIDs[0], err
+	RsrcMgr.flow_id++
+	return RsrcMgr.flow_id, nil
 }
diff --git a/core/subscriber_manager.go b/core/subscriber_manager.go
index 3cf65ad..9abec13 100644
--- a/core/subscriber_manager.go
+++ b/core/subscriber_manager.go
@@ -21,16 +21,12 @@
 	"sync"
 
 	"github.com/opencord/openolt-scale-tester/config"
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-	"github.com/opencord/voltha-lib-go/v3/pkg/techprofile"
-	oop "github.com/opencord/voltha-protos/v3/go/openolt"
+	"github.com/opencord/voltha-lib-go/v4/pkg/log"
+	"github.com/opencord/voltha-lib-go/v4/pkg/techprofile"
+	oop "github.com/opencord/voltha-protos/v4/go/openolt"
 	"golang.org/x/net/context"
 )
 
-func init() {
-	_, _ = log.AddPackage(log.JSON, log.DebugLevel, nil)
-}
-
 const (
 	SUBSCRIBER_PROVISION_SUCCESS = iota
 	TP_INSTANCE_CREATION_FAILED
@@ -41,7 +37,7 @@
 )
 
 const (
-	UniPortName = "pon-{%d}/onu-{%d}/uni-{%d}"
+	UniPortName = "olt-{1}/pon-{%d}/onu-{%d}/uni-{%d}"
 )
 
 var Reason = [...]string{
@@ -92,20 +88,20 @@
 
 func (subs *Subscriber) Start(isGroup bool) {
 
-	var err error
-
-	log.Infow("workflow-deploy-started-for-subscriber", log.Fields{"subsName": subs.SubscriberName})
+	logger.Infow(nil, "workflow-deploy-started-for-subscriber", log.Fields{"subsName": subs.SubscriberName})
 
 	subs.TpInstance = make(map[int]*techprofile.TechProfile)
 
 	for _, tpID := range subs.TestConfig.TpIDList {
 		uniPortName := fmt.Sprintf(UniPortName, subs.PonIntf, subs.OnuID, subs.UniID)
 		subs.RsrMgr.GemIDAllocIDLock[subs.PonIntf].Lock()
-		subs.TpInstance[tpID], err = subs.RsrMgr.ResourceMgrs[subs.PonIntf].TechProfileMgr.CreateTechProfInstance(context.Background(),
-			uint32(tpID), uniPortName, subs.PonIntf)
+		tpInstInterface, err := subs.RsrMgr.ResourceMgrs[subs.PonIntf].TechProfileMgr.CreateTechProfInstance(context.Background(), uint32(tpID), uniPortName, subs.PonIntf)
+		// TODO: Assumes the techprofile is of type TechProfile (XGPON, GPON). But it could also be EPON TechProfile type. But we do not support that at the moment, so it is OK.
+		subs.TpInstance[tpID] = tpInstInterface.(*techprofile.TechProfile)
+
 		subs.RsrMgr.GemIDAllocIDLock[subs.PonIntf].Unlock()
 		if err != nil {
-			log.Errorw("error-creating-tp-instance-for-subs",
+			logger.Errorw(nil, "error-creating-tp-instance-for-subs",
 				log.Fields{"subsName": subs.SubscriberName, "onuID": subs.OnuID, "tpID": tpID})
 
 			subs.Reason = ReasonCodeToReasonString(TP_INSTANCE_CREATION_FAILED)
@@ -115,5 +111,5 @@
 
 	go DeployWorkflow(subs, isGroup)
 
-	log.Infow("workflow-deploy-started-for-subscriber", log.Fields{"subsName": subs.SubscriberName})
+	logger.Infow(nil, "workflow-deploy-started-for-subscriber", log.Fields{"subsName": subs.SubscriberName})
 }
diff --git a/core/tt_workflow.go b/core/tt_workflow.go
index 7b14007..783dfe6 100644
--- a/core/tt_workflow.go
+++ b/core/tt_workflow.go
@@ -22,9 +22,9 @@
 	"sync/atomic"
 
 	"github.com/opencord/openolt-scale-tester/config"
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-	oop "github.com/opencord/voltha-protos/v3/go/openolt"
-	tp_pb "github.com/opencord/voltha-protos/v3/go/tech_profile"
+	"github.com/opencord/voltha-lib-go/v4/pkg/log"
+	oop "github.com/opencord/voltha-protos/v4/go/openolt"
+	tp_pb "github.com/opencord/voltha-protos/v4/go/tech_profile"
 	"golang.org/x/net/context"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
@@ -32,16 +32,12 @@
 
 var lastPonIntf *uint32 = new(uint32)
 
-func init() {
-	_, _ = log.AddPackage(log.JSON, log.DebugLevel, nil)
-}
-
 // A dummy struct to comply with the WorkFlow interface.
 type TtWorkFlow struct {
 }
 
 func AddTtDhcpIPV4Flow(oo oop.OpenoltClient, config *config.OpenOltScaleTesterConfig, rsrMgr *OpenOltResourceMgr) error {
-	var flowID uint32
+	var flowID uint64
 	var err error
 
 	// Allocating flowID from PON0 pool for an trap-from-nni flow
@@ -63,21 +59,21 @@
 
 	st, _ := status.FromError(err)
 	if st.Code() == codes.AlreadyExists {
-		log.Debugw("Flow already exists", log.Fields{"err": err, "deviceFlow": flow})
+		logger.Debugw(nil, "Flow already exists", log.Fields{"err": err, "deviceFlow": flow})
 		return nil
 	}
 
 	if err != nil {
-		log.Errorw("Failed to Add DHCP IPv4 to device", log.Fields{"err": err, "deviceFlow": flow})
+		logger.Errorw(nil, "Failed to Add DHCP IPv4 to device", log.Fields{"err": err, "deviceFlow": flow})
 		return err
 	}
-	log.Debugw("DHCP IPV4 added to device successfully ", log.Fields{"flow": flow})
+	logger.Debugw(nil, "DHCP IPV4 added to device successfully ", log.Fields{"flow": flow})
 
 	return nil
 }
 
 func AddTtDhcpIPV6Flow(oo oop.OpenoltClient, config *config.OpenOltScaleTesterConfig, rsrMgr *OpenOltResourceMgr) error {
-	log.Info("tt-workflow-does-not-require-dhcp-ipv6-support--nothing-to-do")
+	logger.Info(nil, "tt-workflow-does-not-require-dhcp-ipv6-support--nothing-to-do")
 	return nil
 }
 
@@ -140,13 +136,13 @@
 			flowClassifier.OVid = 75
 			flowClassifier.PktTagType = SingleTag
 		default:
-			log.Errorw("Unsupported TT flow type", log.Fields{"flowtype": flowType,
+			logger.Errorw(nil, "Unsupported TT flow type", log.Fields{"flowtype": flowType,
 				"direction": direction})
 		}
 	} else if direction == Downstream {
 		switch flowType {
 		case IgmpFlow:
-			log.Errorw("Downstream IGMP flows are not required instead we have "+
+			logger.Errorw(nil, "Downstream IGMP flows are not required instead we have "+
 				"IGMP trap flows already installed", log.Fields{"flowtype": flowType,
 				"direction": direction})
 		case HsiaFlow:
@@ -192,41 +188,46 @@
 			flowClassifier.DstMac = GenerateMac(true)
 			flowClassifier.PktTagType = DoubleTag
 		default:
-			log.Errorw("Unsupported TT flow type", log.Fields{"flowtype": flowType,
+			logger.Errorw(nil, "Unsupported TT flow type", log.Fields{"flowtype": flowType,
 				"direction": direction})
 		}
 	}
 	return flowClassifier, actionInfo
 }
 
-func AddTtFlow(subs *Subscriber, flowType string, direction string, flowID uint32,
-	allocID uint32, gemID uint32, pcp uint32) error {
-	log.Infow("add-flow", log.Fields{"WorkFlow": subs.TestConfig.WorkflowName, "FlowType": flowType,
+func AddTtFlow(subs *Subscriber, flowType string, direction string, flowID uint64,
+	allocID uint32, gemID uint32, pcp uint32, replicateFlow bool, symmetricFlowID uint64,
+	pbitToGem map[uint32]uint32) error {
+	logger.Infow(nil, "add-flow", log.Fields{"WorkFlow": subs.TestConfig.WorkflowName, "FlowType": flowType,
 		"direction": direction, "flowID": flowID})
 	var err error
 
 	flowClassifier, actionInfo := FormatTtClassfierAction(flowType, direction, subs)
-	// Update the o_pbit for which this flow has to be classified
-	flowClassifier.OPbits = pcp
+	// Update the o_pbit (if valid) for which this flow has to be classified
+	if pcp != 0xff {
+		flowClassifier.OPbits = pcp
+	}
 	flow := oop.Flow{AccessIntfId: int32(subs.PonIntf), OnuId: int32(subs.OnuID),
 		UniId: int32(subs.UniID), FlowId: flowID,
 		FlowType: direction, AllocId: int32(allocID), GemportId: int32(gemID),
 		Classifier: &flowClassifier, Action: &actionInfo,
-		Priority: 1000, PortNo: subs.UniPortNo}
+		Priority: 1000, PortNo: subs.UniPortNo,
+		SymmetricFlowId: symmetricFlowID,
+		ReplicateFlow:   replicateFlow, PbitToGemport: pbitToGem}
 
 	_, err = subs.OpenOltClient.FlowAdd(context.Background(), &flow)
 
 	st, _ := status.FromError(err)
 	if st.Code() == codes.AlreadyExists {
-		log.Debugw("Flow already exists", log.Fields{"err": err, "deviceFlow": flow})
+		logger.Debugw(nil, "Flow already exists", log.Fields{"err": err, "deviceFlow": flow})
 		return nil
 	}
 
 	if err != nil {
-		log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": flow})
+		logger.Errorw(nil, "Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": flow})
 		return errors.New(ReasonCodeToReasonString(FLOW_ADD_FAILED))
 	}
-	log.Debugw("Flow added to device successfully ", log.Fields{"flow": flow})
+	logger.Debugw(nil, "Flow added to device successfully ", log.Fields{"flow": flow})
 
 	return nil
 }
@@ -234,75 +235,75 @@
 func (tt TtWorkFlow) ProvisionScheds(subs *Subscriber) error {
 	var trafficSched []*tp_pb.TrafficScheduler
 
-	log.Info("provisioning-scheds")
+	logger.Info(nil, "provisioning-scheds")
 
 	if trafficSched = getTrafficSched(subs, tp_pb.Direction_DOWNSTREAM); trafficSched == nil {
-		log.Error("ds-traffic-sched-is-nil")
+		logger.Error(nil, "ds-traffic-sched-is-nil")
 		return errors.New(ReasonCodeToReasonString(SCHED_CREATION_FAILED))
 	}
 
-	log.Debugw("Sending Traffic scheduler create to device",
+	logger.Debugw(nil, "Sending Traffic scheduler create to device",
 		log.Fields{"Direction": tp_pb.Direction_DOWNSTREAM, "TrafficScheds": trafficSched})
 	if _, err := subs.OpenOltClient.CreateTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
 		IntfId: subs.PonIntf, OnuId: subs.OnuID,
 		UniId: subs.UniID, PortNo: subs.UniPortNo,
 		TrafficScheds: trafficSched}); err != nil {
-		log.Errorw("Failed to create traffic schedulers", log.Fields{"error": err})
+		logger.Errorw(nil, "Failed to create traffic schedulers", log.Fields{"error": err})
 		return errors.New(ReasonCodeToReasonString(SCHED_CREATION_FAILED))
 	}
 
 	if trafficSched = getTrafficSched(subs, tp_pb.Direction_UPSTREAM); trafficSched == nil {
-		log.Error("us-traffic-sched-is-nil")
+		logger.Error(nil, "us-traffic-sched-is-nil")
 		return errors.New(ReasonCodeToReasonString(SCHED_CREATION_FAILED))
 	}
 
-	log.Debugw("Sending Traffic scheduler create to device",
+	logger.Debugw(nil, "Sending Traffic scheduler create to device",
 		log.Fields{"Direction": tp_pb.Direction_UPSTREAM, "TrafficScheds": trafficSched})
 	if _, err := subs.OpenOltClient.CreateTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
 		IntfId: subs.PonIntf, OnuId: subs.OnuID,
 		UniId: subs.UniID, PortNo: subs.UniPortNo,
 		TrafficScheds: trafficSched}); err != nil {
-		log.Errorw("Failed to create traffic schedulers", log.Fields{"error": err})
+		logger.Errorw(nil, "Failed to create traffic schedulers", log.Fields{"error": err})
 		return errors.New(ReasonCodeToReasonString(SCHED_CREATION_FAILED))
 	}
 	return nil
 }
 
 func (tt TtWorkFlow) ProvisionQueues(subs *Subscriber) error {
-	log.Info("provisioning-queues")
+	logger.Info(nil, "provisioning-queues")
 
 	var trafficQueues []*tp_pb.TrafficQueue
 	if trafficQueues = getTrafficQueues(subs, tp_pb.Direction_DOWNSTREAM); trafficQueues == nil {
-		log.Error("Failed to create traffic queues")
+		logger.Error(nil, "Failed to create traffic queues")
 		return errors.New(ReasonCodeToReasonString(QUEUE_CREATION_FAILED))
 	}
 
 	// On receiving the CreateTrafficQueues request, the driver should create corresponding
 	// downstream queues.
-	log.Debugw("Sending Traffic Queues create to device",
+	logger.Debugw(nil, "Sending Traffic Queues create to device",
 		log.Fields{"Direction": tp_pb.Direction_DOWNSTREAM, "TrafficQueues": trafficQueues})
 	if _, err := subs.OpenOltClient.CreateTrafficQueues(context.Background(),
 		&tp_pb.TrafficQueues{IntfId: subs.PonIntf, OnuId: subs.OnuID,
 			UniId: subs.UniID, PortNo: subs.UniPortNo,
 			TrafficQueues: trafficQueues}); err != nil {
-		log.Errorw("Failed to create traffic queues in device", log.Fields{"error": err})
+		logger.Errorw(nil, "Failed to create traffic queues in device", log.Fields{"error": err})
 		return errors.New(ReasonCodeToReasonString(QUEUE_CREATION_FAILED))
 	}
 
 	if trafficQueues = getTrafficQueues(subs, tp_pb.Direction_UPSTREAM); trafficQueues == nil {
-		log.Error("Failed to create traffic queues")
+		logger.Error(nil, "Failed to create traffic queues")
 		return errors.New(ReasonCodeToReasonString(QUEUE_CREATION_FAILED))
 	}
 
 	// On receiving the CreateTrafficQueues request, the driver should create corresponding
 	// upstream queues.
-	log.Debugw("Sending Traffic Queues create to device",
+	logger.Debugw(nil, "Sending Traffic Queues create to device",
 		log.Fields{"Direction": tp_pb.Direction_UPSTREAM, "TrafficQueues": trafficQueues})
 	if _, err := subs.OpenOltClient.CreateTrafficQueues(context.Background(),
 		&tp_pb.TrafficQueues{IntfId: subs.PonIntf, OnuId: subs.OnuID,
 			UniId: subs.UniID, PortNo: subs.UniPortNo,
 			TrafficQueues: trafficQueues}); err != nil {
-		log.Errorw("Failed to create traffic queues in device", log.Fields{"error": err})
+		logger.Errorw(nil, "Failed to create traffic queues in device", log.Fields{"error": err})
 		return errors.New(ReasonCodeToReasonString(QUEUE_CREATION_FAILED))
 	}
 
@@ -310,29 +311,31 @@
 }
 
 func (tt TtWorkFlow) ProvisionEapFlow(subs *Subscriber) error {
-	log.Info("tt-workflow-does-not-support-eap-yet--nothing-to-do")
+	logger.Info(nil, "tt-workflow-does-not-support-eap-yet--nothing-to-do")
 	return nil
 }
 
 func (tt TtWorkFlow) ProvisionDhcpIPV4Flow(subs *Subscriber) error {
-	log.Info("tt-workflow-does-not-require-dhcp-ipv4-yet--nothing-to-do")
+	logger.Info(nil, "tt-workflow-does-not-require-dhcp-ipv4-yet--nothing-to-do")
 	return nil
 }
 
 func (tt TtWorkFlow) ProvisionDhcpIPV6Flow(subs *Subscriber) error {
-	log.Info("tt-workflow-does-not-require-dhcp-ipv6-support--nothing-to-do")
+	logger.Info(nil, "tt-workflow-does-not-require-dhcp-ipv6-support--nothing-to-do")
 	return nil
 }
 
 func (tt TtWorkFlow) ProvisionIgmpFlow(subs *Subscriber) error {
-	log.Info("tt-workflow-does-not-require-igmp-support--nothing-to-do")
+	logger.Info(nil, "tt-workflow-does-not-require-igmp-support--nothing-to-do")
 	return nil
 }
 
 func (tt TtWorkFlow) ProvisionHsiaFlow(subs *Subscriber) error {
-	var err error
-	var flowID uint32
 	var gemPortIDs []uint32
+	var err error
+	var flowIDUs, flowIDDs uint64
+	pbitToGem := make(map[uint32]uint32)
+	var pcp uint32
 
 	var allocID = subs.TpInstance[subs.TestConfig.TpIDList[0]].UsScheduler.AllocID
 	for _, gem := range subs.TpInstance[subs.TestConfig.TpIDList[0]].UpstreamGemPortAttributeList {
@@ -343,37 +346,45 @@
 		pBitMap := subs.TpInstance[subs.TestConfig.TpIDList[0]].UpstreamGemPortAttributeList[idx].PbitMap
 		for pos, pbitSet := range strings.TrimPrefix(pBitMap, "0b") {
 			if pbitSet == '1' {
-				pcp := uint32(len(strings.TrimPrefix(pBitMap, "0b"))) - 1 - uint32(pos)
-				if flowID, err = subs.RsrMgr.GetFlowID(context.Background(), uint32(subs.PonIntf)); err != nil {
+				pcp = uint32(len(strings.TrimPrefix(pBitMap, "0b"))) - 1 - uint32(pos)
+				var errUs, errDs error
+				if flowIDUs, err = subs.RsrMgr.GetFlowID(context.Background(), subs.PonIntf); err != nil {
 					return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
-				} else {
-					var errUs, errDs error
-					if errUs = AddTtFlow(subs, HsiaFlow, Upstream, flowID, allocID, gemID, pcp); errUs != nil {
-						log.Errorw("failed to install US HSIA flow",
-							log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
-					}
-					if errDs = AddTtFlow(subs, HsiaFlow, Downstream, flowID, allocID, gemID, pcp); errDs != nil {
-						log.Errorw("failed to install DS HSIA flow",
-							log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
-					}
+				}
+				if errUs = AddTtFlow(subs, HsiaFlow, Upstream, flowIDUs, allocID, gemID, pcp, false,
+					0, pbitToGem); errUs != nil {
+					logger.Errorw(nil, "failed to install US HSIA flow",
+						log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
+				}
+				if flowIDDs, err = subs.RsrMgr.GetFlowID(context.Background(), subs.PonIntf); err != nil {
+					return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
+				}
+				if errDs = AddTtFlow(subs, HsiaFlow, Downstream, flowIDDs, allocID, gemID, pcp, false,
+					flowIDUs, pbitToGem); errDs != nil {
+					logger.Errorw(nil, "failed to install DS HSIA flow",
+						log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
+				}
 
-					if errUs != nil || errDs != nil {
-						if errUs != nil {
-							return errUs
-						}
-						return errDs
+				if errUs != nil || errDs != nil {
+					if errUs != nil {
+						return errUs
 					}
+					return errDs
 				}
 			}
 		}
 	}
+
 	return nil
 }
 
 func (tt TtWorkFlow) ProvisionVoipFlow(subs *Subscriber) error {
 	var err error
-	var flowID uint32
 	var gemPortIDs []uint32
+	var errUs, errDs, errDhcp error
+	var flowIDUs, flowIDDs, flowIDDhcp uint64
+	pbitToGem := make(map[uint32]uint32)
+	var pcp uint32
 
 	var allocID = subs.TpInstance[subs.TestConfig.TpIDList[0]].UsScheduler.AllocID
 	for _, gem := range subs.TpInstance[subs.TestConfig.TpIDList[0]].UpstreamGemPortAttributeList {
@@ -384,44 +395,55 @@
 		pBitMap := subs.TpInstance[subs.TestConfig.TpIDList[0]].UpstreamGemPortAttributeList[idx].PbitMap
 		for pos, pbitSet := range strings.TrimPrefix(pBitMap, "0b") {
 			if pbitSet == '1' {
-				pcp := uint32(len(strings.TrimPrefix(pBitMap, "0b"))) - 1 - uint32(pos)
-				if flowID, err = subs.RsrMgr.GetFlowID(context.Background(), uint32(subs.PonIntf)); err != nil {
+				pcp = uint32(len(strings.TrimPrefix(pBitMap, "0b"))) - 1 - uint32(pos)
+				if flowIDUs, err = subs.RsrMgr.GetFlowID(context.Background(), subs.PonIntf); err != nil {
 					return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
-				} else {
-					var errUs, errDs, errDhcp error
-					if errUs = AddTtFlow(subs, VoipFlow, Upstream, flowID, allocID, gemID, pcp); errUs != nil {
-						log.Errorw("failed to install US VOIP flow",
-							log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
-					}
-					if errDs = AddTtFlow(subs, VoipFlow, Downstream, flowID, allocID, gemID, pcp); errDs != nil {
-						log.Errorw("failed to install DS VOIP flow",
-							log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
-					}
-					if errDhcp = AddFlow(subs, DhcpFlowIPV4, Upstream, flowID, allocID, gemID, pcp); errDhcp != nil {
-						log.Errorw("failed to install US VOIP-DHCP flow",
-							log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
-					}
+				}
+				if errUs = AddTtFlow(subs, VoipFlow, Upstream, flowIDUs, allocID, gemID, pcp, false,
+					0, pbitToGem); errUs != nil {
+					logger.Errorw(nil, "failed to install US VOIP flow",
+						log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
+				}
+				if flowIDDs, err = subs.RsrMgr.GetFlowID(context.Background(), subs.PonIntf); err != nil {
+					return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
+				}
+				if errDs = AddTtFlow(subs, VoipFlow, Downstream, flowIDDs, allocID, gemID, pcp, false,
+					flowIDUs, pbitToGem); errDs != nil {
+					logger.Errorw(nil, "failed to install DS VOIP flow",
+						log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
+				}
+				if flowIDDhcp, err = subs.RsrMgr.GetFlowID(context.Background(), subs.PonIntf); err != nil {
+					return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
+				}
+				if errDhcp = AddFlow(subs, DhcpFlowIPV4, Upstream, flowIDDhcp, allocID, gemID, pcp, false,
+					0, pbitToGem); errDhcp != nil {
+					logger.Errorw(nil, "failed to install US VOIP-DHCP flow",
+						log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
+				}
 
-					if errUs != nil || errDs != nil || errDhcp != nil {
-						if errUs != nil {
-							return errUs
-						}
-						if errDs != nil {
-							return errDs
-						}
-						return errDhcp
+				if errUs != nil || errDs != nil || errDhcp != nil {
+					if errUs != nil {
+						return errUs
 					}
+					if errDs != nil {
+						return errDs
+					}
+					return errDhcp
 				}
 			}
 		}
 	}
+
 	return nil
 }
 
 func (tt TtWorkFlow) ProvisionVodFlow(subs *Subscriber) error {
 	var err error
-	var flowID uint32
 	var gemPortIDs []uint32
+	var errUs, errDs, errDhcp, errIgmp error
+	var flowIDUs, flowIDDs, flowIDDhcp, flowIDIgmp uint64
+	pbitToGem := make(map[uint32]uint32)
+	var pcp uint32
 
 	var allocID = subs.TpInstance[subs.TestConfig.TpIDList[0]].UsScheduler.AllocID
 	for _, gem := range subs.TpInstance[subs.TestConfig.TpIDList[0]].UpstreamGemPortAttributeList {
@@ -432,40 +454,51 @@
 		pBitMap := subs.TpInstance[subs.TestConfig.TpIDList[0]].UpstreamGemPortAttributeList[idx].PbitMap
 		for pos, pbitSet := range strings.TrimPrefix(pBitMap, "0b") {
 			if pbitSet == '1' {
-				pcp := uint32(len(strings.TrimPrefix(pBitMap, "0b"))) - 1 - uint32(pos)
-				if flowID, err = subs.RsrMgr.GetFlowID(context.Background(), uint32(subs.PonIntf)); err != nil {
+				pcp = uint32(len(strings.TrimPrefix(pBitMap, "0b"))) - 1 - uint32(pos)
+				if flowIDUs, err = subs.RsrMgr.GetFlowID(context.Background(), subs.PonIntf); err != nil {
 					return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
-				} else {
-					var errUs, errDs, errDhcp, errIgmp error
-					if errUs = AddTtFlow(subs, VodFlow, Upstream, flowID, allocID, gemID, pcp); errUs != nil {
-						log.Errorw("failed to install US VOIP flow",
-							log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
-					}
-					if errDs = AddTtFlow(subs, VodFlow, Downstream, flowID, allocID, gemID, pcp); errDs != nil {
-						log.Errorw("failed to install DS VOIP flow",
-							log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
-					}
-					if errDhcp = AddFlow(subs, DhcpFlowIPV4, Upstream, flowID, allocID, gemID, pcp); errDhcp != nil {
-						log.Errorw("failed to install US VOIP-DHCP flow",
-							log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
-					}
-					if errIgmp = AddTtFlow(subs, IgmpFlow, Upstream, flowID, allocID, gemID, pcp); errIgmp != nil {
-						log.Errorw("failed to install US VOIP-IGMP flow",
-							log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
-					}
+				}
+				if errUs = AddTtFlow(subs, VodFlow, Upstream, flowIDUs, allocID, gemID, pcp, false,
+					0, pbitToGem); errUs != nil {
+					logger.Errorw(nil, "failed to install US VOIP flow",
+						log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
+				}
+				if flowIDDs, err = subs.RsrMgr.GetFlowID(context.Background(), subs.PonIntf); err != nil {
+					return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
+				}
+				if errDs = AddTtFlow(subs, VodFlow, Downstream, flowIDDs, allocID, gemID, pcp, false,
+					flowIDUs, pbitToGem); errDs != nil {
+					logger.Errorw(nil, "failed to install DS VOIP flow",
+						log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
+				}
+				if flowIDDhcp, err = subs.RsrMgr.GetFlowID(context.Background(), subs.PonIntf); err != nil {
+					return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
+				}
+				if errDhcp = AddFlow(subs, DhcpFlowIPV4, Upstream, flowIDDhcp, allocID, gemID, pcp, false,
+					0, pbitToGem); errDhcp != nil {
+					logger.Errorw(nil, "failed to install US VOIP-DHCP flow",
+						log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
+				}
+				if flowIDIgmp, err = subs.RsrMgr.GetFlowID(context.Background(), subs.PonIntf); err != nil {
+					return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
+				}
+				if errIgmp = AddTtFlow(subs, IgmpFlow, Upstream, flowIDIgmp, allocID, gemID, pcp, false,
+					0, pbitToGem); errIgmp != nil {
+					logger.Errorw(nil, "failed to install US VOIP-IGMP flow",
+						log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
+				}
 
-					if errUs != nil || errDs != nil || errDhcp != nil || errIgmp != nil {
-						if errUs != nil {
-							return errUs
-						}
-						if errDs != nil {
-							return errDs
-						}
-						if errDhcp != nil {
-							return errDhcp
-						}
-						return errIgmp
+				if errUs != nil || errDs != nil || errDhcp != nil || errIgmp != nil {
+					if errUs != nil {
+						return errUs
 					}
+					if errDs != nil {
+						return errDs
+					}
+					if errDhcp != nil {
+						return errDhcp
+					}
+					return errIgmp
 				}
 			}
 		}
@@ -475,8 +508,10 @@
 
 func (tt TtWorkFlow) ProvisionMgmtFlow(subs *Subscriber) error {
 	var err error
-	var flowID uint32
+	pbitToGem := make(map[uint32]uint32)
+	var flowIDUs, flowIDDs, flowIDDhcp uint64
 	var gemPortIDs []uint32
+	var pcp uint32
 
 	var allocID = subs.TpInstance[subs.TestConfig.TpIDList[0]].UsScheduler.AllocID
 	for _, gem := range subs.TpInstance[subs.TestConfig.TpIDList[0]].UpstreamGemPortAttributeList {
@@ -487,33 +522,41 @@
 		pBitMap := subs.TpInstance[subs.TestConfig.TpIDList[0]].UpstreamGemPortAttributeList[idx].PbitMap
 		for pos, pbitSet := range strings.TrimPrefix(pBitMap, "0b") {
 			if pbitSet == '1' {
-				pcp := uint32(len(strings.TrimPrefix(pBitMap, "0b"))) - 1 - uint32(pos)
-				if flowID, err = subs.RsrMgr.GetFlowID(context.Background(), uint32(subs.PonIntf)); err != nil {
+				pcp = uint32(len(strings.TrimPrefix(pBitMap, "0b"))) - 1 - uint32(pos)
+				var errUs, errDs, errDhcp error
+				if flowIDUs, err = subs.RsrMgr.GetFlowID(context.Background(), subs.PonIntf); err != nil {
 					return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
-				} else {
-					var errUs, errDs, errDhcp error
-					if errUs = AddTtFlow(subs, MgmtFlow, Upstream, flowID, allocID, gemID, pcp); errUs != nil {
-						log.Errorw("failed to install US MGMT flow",
-							log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
-					}
-					if errDs = AddTtFlow(subs, MgmtFlow, Downstream, flowID, allocID, gemID, pcp); errDs != nil {
-						log.Errorw("failed to install DS MGMT flow",
-							log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
-					}
-					if errDhcp = AddFlow(subs, DhcpFlowIPV4, Upstream, flowID, allocID, gemID, pcp); errDhcp != nil {
-						log.Errorw("failed to install US MGMT-DHCP flow",
-							log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
-					}
+				}
+				if errUs = AddTtFlow(subs, MgmtFlow, Upstream, flowIDUs, allocID, gemID, pcp, false,
+					0, pbitToGem); errUs != nil {
+					logger.Errorw(nil, "failed to install US MGMT flow",
+						log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
+				}
+				if flowIDDs, err = subs.RsrMgr.GetFlowID(context.Background(), subs.PonIntf); err != nil {
+					return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
+				}
+				if errDs = AddTtFlow(subs, MgmtFlow, Downstream, flowIDDs, allocID, gemID, pcp, false,
+					flowIDUs, pbitToGem); errDs != nil {
+					logger.Errorw(nil, "failed to install DS MGMT flow",
+						log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
+				}
+				if flowIDDhcp, err = subs.RsrMgr.GetFlowID(context.Background(), subs.PonIntf); err != nil {
+					return errors.New(ReasonCodeToReasonString(FLOW_ID_GENERATION_FAILED))
+				}
+				if errDhcp = AddFlow(subs, DhcpFlowIPV4, Upstream, flowIDDhcp, allocID, gemID, pcp, false,
+					0, pbitToGem); errDhcp != nil {
+					logger.Errorw(nil, "failed to install US MGMT-DHCP flow",
+						log.Fields{"onuID": subs.OnuID, "uniID": subs.UniID, "intf": subs.PonIntf})
+				}
 
-					if errUs != nil || errDs != nil || errDhcp != nil {
-						if errUs != nil {
-							return errUs
-						}
-						if errDs != nil {
-							return errDs
-						}
-						return errDhcp
+				if errUs != nil || errDs != nil || errDhcp != nil {
+					if errUs != nil {
+						return errUs
 					}
+					if errDs != nil {
+						return errDs
+					}
+					return errDhcp
 				}
 			}
 		}
@@ -536,7 +579,7 @@
 	grp.GemPortID = 4069
 	grp.SchedPolicy = tp_pb.SchedulingPolicy_WRR
 
-	log.Debugw("Group data", log.Fields{"OnuID": subs.OnuID, "GroupID": grp.GroupID, "numOfONUsPerPon": numOfONUsPerPon})
+	logger.Debugw(nil, "Group data", log.Fields{"OnuID": subs.OnuID, "GroupID": grp.GroupID, "numOfONUsPerPon": numOfONUsPerPon})
 
 	grp.GroupID = subs.OnuID
 
@@ -562,7 +605,7 @@
 	err = AddMulticastQueueFlow(&grp)
 
 	if err != nil {
-		log.Errorw("Failed to add multicast flow", log.Fields{"error": err})
+		logger.Errorw(nil, "Failed to add multicast flow", log.Fields{"error": err})
 	}
 
 	return err
diff --git a/core/utils.go b/core/utils.go
index b239443..1bcdedd 100644
--- a/core/utils.go
+++ b/core/utils.go
@@ -19,8 +19,8 @@
 import (
 	"fmt"
 
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-	"github.com/opencord/voltha-protos/v3/go/openolt"
+	"github.com/opencord/voltha-lib-go/v4/pkg/log"
+	"github.com/opencord/voltha-protos/v4/go/openolt"
 )
 
 type DtStagKey struct {
@@ -34,7 +34,6 @@
 var TtCtag map[uint32]uint32
 
 func init() {
-	_, _ = log.AddPackage(log.JSON, log.DebugLevel, nil)
 	AttCtag = make(map[uint32]uint32)
 	DtCtag = make(map[uint32]uint32)
 	DtStag = make(map[DtStagKey]uint32)
@@ -59,9 +58,9 @@
 
 	vendorSpecificId += 1
 	vs := []byte(fmt.Sprint(vendorSpecificId))
-	// log.Infow("vendor-id-and-vendor-specific", log.Fields{"vi":vi, "vs":vs})
+	// logger.Infow(nil, "vendor-id-and-vendor-specific", log.Fields{"vi":vi, "vs":vs})
 	sn := &openolt.SerialNumber{VendorId: vi, VendorSpecific: vs}
-	// log.Infow("serial-num", log.Fields{"sn":sn})
+	// logger.Infow(nil, "serial-num", log.Fields{"sn":sn})
 
 	return sn
 }
@@ -70,7 +69,7 @@
 func MkUniPortNum(intfID, onuID, uniID uint32) uint32 {
 	var limit = int(onuID)
 	if limit > MaxOnusPerPon {
-		log.Warn("Warning: exceeded the MAX ONUS per PON")
+		logger.Warn(nil, "Warning: exceeded the MAX ONUS per PON")
 	}
 	return (intfID << (bitsForUniID + bitsForONUID)) | (onuID << bitsForUniID) | uniID
 }
@@ -144,7 +143,7 @@
 	case "TT":
 		return GetTtCtag(ponIntf)
 	default:
-		log.Errorw("unknown-workflowname", log.Fields{"workflow": workFlowName})
+		logger.Errorw(nil, "unknown-workflowname", log.Fields{"workflow": workFlowName})
 	}
 	return 0
 }
@@ -158,7 +157,7 @@
 	case "TT":
 		return GetTtStag(ponIntf)
 	default:
-		log.Errorw("unknown-workflowname", log.Fields{"workflow": workFlowName})
+		logger.Errorw(nil, "unknown-workflowname", log.Fields{"workflow": workFlowName})
 	}
 	return 0
 }
diff --git a/core/workflow_manager.go b/core/workflow_manager.go
index e9bb24e..f642eb5 100644
--- a/core/workflow_manager.go
+++ b/core/workflow_manager.go
@@ -20,14 +20,10 @@
 	"errors"
 
 	"github.com/opencord/openolt-scale-tester/config"
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-	oop "github.com/opencord/voltha-protos/v3/go/openolt"
+	"github.com/opencord/voltha-lib-go/v4/pkg/log"
+	oop "github.com/opencord/voltha-protos/v4/go/openolt"
 )
 
-func init() {
-	_, _ = log.AddPackage(log.JSON, log.DebugLevel, nil)
-}
-
 type WorkFlow interface {
 	ProvisionScheds(subs *Subscriber) error
 	ProvisionQueues(subs *Subscriber) error
@@ -107,24 +103,24 @@
 		}
 	}
 
-	log.Infow("subscriber-provision-completed-from-onu-manager", log.Fields{"subsName": subs.SubscriberName})
+	logger.Infow(nil, "subscriber-provision-completed-from-onu-manager", log.Fields{"subsName": subs.SubscriberName})
 	subs.Reason = ReasonCodeToReasonString(SUBSCRIBER_PROVISION_SUCCESS)
 }
 
 func getWorkFlow(subs *Subscriber) WorkFlow {
 	switch subs.TestConfig.WorkflowName {
 	case "ATT":
-		log.Info("chosen-att-workflow")
+		logger.Info(nil, "chosen-att-workflow")
 		return AttWorkFlow{}
 	case "DT":
-		log.Info("chosen-dt-workflow")
+		logger.Info(nil, "chosen-dt-workflow")
 		return DtWorkFlow{}
 	case "TT":
-		log.Info("chosen-tt-workflow")
+		logger.Info(nil, "chosen-tt-workflow")
 		return TtWorkFlow{}
 	// TODO: Add new workflow here
 	default:
-		log.Errorw("operator-workflow-not-supported-yet", log.Fields{"workflowName": subs.TestConfig.WorkflowName})
+		logger.Errorw(nil, "operator-workflow-not-supported-yet", log.Fields{"workflowName": subs.TestConfig.WorkflowName})
 	}
 	return nil
 }
@@ -135,22 +131,22 @@
 	switch config.WorkflowName {
 	case "ATT":
 		if err := ProvisionAttNniTrapFlow(oo, config, rsrMgr); err != nil {
-			log.Error("error-installing-flow", log.Fields{"err": err})
+			logger.Error(nil, "error-installing-flow", log.Fields{"err": err})
 			return err
 		}
 	case "DT":
 		if err := ProvisionDtNniTrapFlow(oo, config, rsrMgr); err != nil {
-			log.Error("error-installing-flow", log.Fields{"err": err})
+			logger.Error(nil, "error-installing-flow", log.Fields{"err": err})
 			return err
 		}
 	case "TT":
 		if err := ProvisionTtNniTrapFlow(oo, config, rsrMgr); err != nil {
-			log.Error("error-installing-flow", log.Fields{"err": err})
+			logger.Error(nil, "error-installing-flow", log.Fields{"err": err})
 			return err
 		}
 	// TODO: Add new items here
 	default:
-		log.Errorw("operator-workflow-not-supported-yet", log.Fields{"workflowName": config.WorkflowName})
+		logger.Errorw(nil, "operator-workflow-not-supported-yet", log.Fields{"workflowName": config.WorkflowName})
 		return errors.New("workflow-not-supported")
 	}
 	return nil
diff --git a/core/workflow_utils.go b/core/workflow_utils.go
index a223c02..818b3ec 100644
--- a/core/workflow_utils.go
+++ b/core/workflow_utils.go
@@ -22,10 +22,9 @@
 	"time"
 
 	"github.com/opencord/openolt-scale-tester/config"
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-	"github.com/opencord/voltha-lib-go/v3/pkg/ponresourcemanager"
-	oop "github.com/opencord/voltha-protos/v3/go/openolt"
-	tp_pb "github.com/opencord/voltha-protos/v3/go/tech_profile"
+	"github.com/opencord/voltha-lib-go/v4/pkg/log"
+	oop "github.com/opencord/voltha-protos/v4/go/openolt"
+	tp_pb "github.com/opencord/voltha-protos/v4/go/tech_profile"
 	"golang.org/x/net/context"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
@@ -102,14 +101,14 @@
 
 	if direction == tp_pb.Direction_DOWNSTREAM {
 		SchedCfg, err = subs.RsrMgr.ResourceMgrs[subs.PonIntf].TechProfileMgr.
-			GetDsScheduler(subs.TpInstance[subs.TestConfig.TpIDList[0]])
+			GetDsScheduler(nil, subs.TpInstance[subs.TestConfig.TpIDList[0]])
 	} else {
 		SchedCfg, err = subs.RsrMgr.ResourceMgrs[subs.PonIntf].TechProfileMgr.
-			GetUsScheduler(subs.TpInstance[subs.TestConfig.TpIDList[0]])
+			GetUsScheduler(nil, subs.TpInstance[subs.TestConfig.TpIDList[0]])
 	}
 
 	if err != nil {
-		log.Errorw("Failed to create traffic schedulers", log.Fields{"direction": direction, "error": err})
+		logger.Errorw(nil, "Failed to create traffic schedulers", log.Fields{"direction": direction, "error": err})
 		return nil
 	}
 
@@ -132,13 +131,13 @@
 func getTrafficQueues(subs *Subscriber, direction tp_pb.Direction) []*tp_pb.TrafficQueue {
 
 	trafficQueues, err := subs.RsrMgr.ResourceMgrs[subs.PonIntf].TechProfileMgr.
-		GetTrafficQueues(subs.TpInstance[subs.TestConfig.TpIDList[0]], direction)
+		GetTrafficQueues(nil, subs.TpInstance[subs.TestConfig.TpIDList[0]], direction)
 
 	if err == nil {
 		return trafficQueues
 	}
 
-	log.Errorw("Failed to create traffic queues", log.Fields{"direction": direction, "error": err})
+	logger.Errorw(nil, "Failed to create traffic queues", log.Fields{"direction": direction, "error": err})
 	return nil
 }
 
@@ -178,21 +177,21 @@
 			actionInfo.Cmd = &actionCmd
 			actionInfo.OVid = subs.Stag
 		default:
-			log.Errorw("Unsupported flow type", log.Fields{"flowtype": flowType,
+			logger.Errorw(nil, "Unsupported flow type", log.Fields{"flowtype": flowType,
 				"direction": direction})
 		}
 	} else if direction == Downstream {
 		switch flowType {
 		case EapolFlow:
-			log.Errorw("Downstream EAP flows are not required instead controller "+
+			logger.Errorw(nil, "Downstream EAP flows are not required instead controller "+
 				"packet outs EAP response directly to onu in downstream", log.Fields{"flowtype": flowType,
 				"direction": direction})
 		case DhcpFlowIPV4:
-			log.Errorw("Downstream DHCPIPV4 flows are not required instead we have "+
+			logger.Errorw(nil, "Downstream DHCPIPV4 flows are not required instead we have "+
 				"NNI trap flows already installed", log.Fields{"flowtype": flowType,
 				"direction": direction})
 		case DhcpFlowIPV6:
-			log.Errorw("Downstream DHCPIPV6 flows are not required instead we have "+
+			logger.Errorw(nil, "Downstream DHCPIPV6 flows are not required instead we have "+
 				"NNI trap flows already installed", log.Fields{"flowtype": flowType,
 				"direction": direction})
 		case HsiaFlow:
@@ -203,51 +202,54 @@
 			actionInfo.Cmd = &actionCmd
 			actionInfo.OVid = subs.Stag
 		default:
-			log.Errorw("Unsupported flow type", log.Fields{"flowtype": flowType,
+			logger.Errorw(nil, "Unsupported flow type", log.Fields{"flowtype": flowType,
 				"direction": direction})
 		}
 	}
 	return flowClassifier, actionInfo
 }
 
-func AddFlow(subs *Subscriber, flowType string, direction string, flowID uint32,
-	allocID uint32, gemID uint32, pcp uint32) error {
-	log.Infow("add-flow", log.Fields{"WorkFlow": subs.TestConfig.WorkflowName, "FlowType": flowType,
+func AddFlow(subs *Subscriber, flowType string, direction string, flowID uint64,
+	allocID uint32, gemID uint32, pcp uint32, replicateFlow bool, symmetricFlowID uint64,
+	pbitToGem map[uint32]uint32) error {
+	logger.Infow(nil, "add-flow", log.Fields{"WorkFlow": subs.TestConfig.WorkflowName, "FlowType": flowType,
 		"direction": direction, "flowID": flowID})
 	var err error
 
 	flowClassifier, actionInfo := FormatClassfierAction(flowType, direction, subs)
-	// Update the o_pbit for which this flow has to be classified
-	flowClassifier.OPbits = pcp
+	// Update the o_pbit (if valid) for which this flow has to be classified
+	if pcp != 0xff {
+		flowClassifier.OPbits = pcp
+	}
 	flow := oop.Flow{AccessIntfId: int32(subs.PonIntf), OnuId: int32(subs.OnuID),
 		UniId: int32(subs.UniID), FlowId: flowID,
 		FlowType: direction, AllocId: int32(allocID), GemportId: int32(gemID),
 		Classifier: &flowClassifier, Action: &actionInfo,
-		Priority: 1000, PortNo: subs.UniPortNo}
+		Priority: 1000, PortNo: subs.UniPortNo, SymmetricFlowId: symmetricFlowID,
+		ReplicateFlow: replicateFlow, PbitToGemport: pbitToGem}
 
 	_, err = subs.OpenOltClient.FlowAdd(context.Background(), &flow)
 
 	st, _ := status.FromError(err)
 	if st.Code() == codes.AlreadyExists {
-		log.Debugw("Flow already exists", log.Fields{"err": err, "deviceFlow": flow})
+		logger.Debugw(nil, "Flow already exists", log.Fields{"err": err, "deviceFlow": flow})
 		return nil
 	}
 
 	if err != nil {
-		log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": flow})
+		logger.Errorw(nil, "Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": flow})
 		return errors.New(ReasonCodeToReasonString(FLOW_ADD_FAILED))
 	}
-	log.Debugw("Flow added to device successfully ", log.Fields{"flow": flow})
+	logger.Debugw(nil, "Flow added to device successfully ", log.Fields{"flow": flow})
 
 	return nil
 }
 
 func AddLldpFlow(oo oop.OpenoltClient, config *config.OpenOltScaleTesterConfig, rsrMgr *OpenOltResourceMgr) error {
-	var flowID []uint32
+	var flowID uint64
 	var err error
 
-	if flowID, err = rsrMgr.ResourceMgrs[uint32(config.NniIntfID)].GetResourceID(context.Background(), uint32(config.NniIntfID),
-		ponresourcemanager.FLOW_ID, 1); err != nil {
+	if flowID, err = rsrMgr.GetFlowID(context.Background(), uint32(config.NniIntfID)); err != nil {
 		return err
 	}
 
@@ -255,7 +257,7 @@
 	actionCmd := &oop.ActionCmd{TrapToHost: true}
 	actionInfo := &oop.Action{Cmd: actionCmd}
 
-	flow := oop.Flow{AccessIntfId: -1, OnuId: -1, UniId: -1, FlowId: flowID[0],
+	flow := oop.Flow{AccessIntfId: -1, OnuId: -1, UniId: -1, FlowId: flowID,
 		FlowType: "downstream", AllocId: -1, GemportId: -1,
 		Classifier: flowClassifier, Action: actionInfo,
 		Priority: 1000, PortNo: uint32(config.NniIntfID)}
@@ -264,17 +266,15 @@
 
 	st, _ := status.FromError(err)
 	if st.Code() == codes.AlreadyExists {
-		log.Debugw("Flow already exists", log.Fields{"err": err, "deviceFlow": flow})
+		logger.Debugw(nil, "Flow already exists", log.Fields{"err": err, "deviceFlow": flow})
 		return nil
 	}
 
 	if err != nil {
-		log.Errorw("Failed to Add LLDP flow to device", log.Fields{"err": err, "deviceFlow": flow})
-		rsrMgr.ResourceMgrs[uint32(config.NniIntfID)].FreeResourceID(context.Background(), uint32(config.NniIntfID),
-			ponresourcemanager.FLOW_ID, flowID)
+		logger.Errorw(nil, "Failed to Add LLDP flow to device", log.Fields{"err": err, "deviceFlow": flow})
 		return err
 	}
-	log.Debugw("LLDP flow added to device successfully ", log.Fields{"flow": flow})
+	logger.Debugw(nil, "LLDP flow added to device successfully ", log.Fields{"flow": flow})
 
 	return nil
 }
@@ -312,11 +312,11 @@
 	var res *oop.Empty
 
 	if res, err = oop.OpenoltClient.PerformGroupOperation(oo, context.Background(), groupCfg); err != nil {
-		log.Errorw("Failed to perform - PerformGroupOperation()", log.Fields{"err": err})
+		logger.Errorw(nil, "Failed to perform - PerformGroupOperation()", log.Fields{"err": err})
 		return nil, err
 	}
 
-	log.Info("Successfully called - PerformGroupOperation()")
+	logger.Info(nil, "Successfully called - PerformGroupOperation()")
 
 	return res, nil
 }
@@ -324,7 +324,7 @@
 func CreateGroup(grp *GroupData) (*oop.Empty, error) {
 	var groupCfg oop.Group
 
-	log.Infow("creating group", log.Fields{"GroupID": grp.GroupID})
+	logger.Infow(nil, "creating group", log.Fields{"GroupID": grp.GroupID})
 
 	groupCfg.Command = oop.Group_SET_MEMBERS
 	groupCfg.GroupId = grp.GroupID
@@ -333,7 +333,7 @@
 }
 
 func OpMulticastTrafficQueue(grp *GroupData, isCreating bool) (*oop.Empty, error) {
-	log.Infow("operating on multicast traffic queue", log.Fields{"Creating": isCreating, "GroupID": grp.GroupID})
+	logger.Infow(nil, "operating on multicast traffic queue", log.Fields{"Creating": isCreating, "GroupID": grp.GroupID})
 
 	oo := grp.Subs.OpenOltClient
 
@@ -360,35 +360,34 @@
 
 	if isCreating {
 		if res, err = oop.OpenoltClient.CreateTrafficQueues(oo, context.Background(), &request); err != nil {
-			log.Errorw("Failed to perform - CreateTrafficQueues()", log.Fields{"err": err})
+			logger.Errorw(nil, "Failed to perform - CreateTrafficQueues()", log.Fields{"err": err})
 			return nil, err
 		}
 
-		log.Info("Successfully called - CreateTrafficQueues()")
+		logger.Info(nil, "Successfully called - CreateTrafficQueues()")
 	} else {
 		if res, err = oop.OpenoltClient.RemoveTrafficQueues(oo, context.Background(), &request); err != nil {
-			log.Errorw("Failed to perform - RemoveTrafficQueues()", log.Fields{"err": err})
+			logger.Errorw(nil, "Failed to perform - RemoveTrafficQueues()", log.Fields{"err": err})
 			return nil, err
 		}
 
-		log.Info("Successfully called - RemoveTrafficQueues()")
+		logger.Info(nil, "Successfully called - RemoveTrafficQueues()")
 	}
 
 	return res, nil
 }
 
 func AddMulticastFlow(grp *GroupData) error {
-	log.Infow("add multicast flow", log.Fields{"GroupID": grp.GroupID})
+	logger.Infow(nil, "add multicast flow", log.Fields{"GroupID": grp.GroupID})
 
 	oo := grp.Subs.OpenOltClient
 	config := grp.Subs.TestConfig
 	rsrMgr := grp.Subs.RsrMgr
 
-	var flowID []uint32
+	var flowID uint64
 	var err error
 
-	if flowID, err = rsrMgr.ResourceMgrs[uint32(config.NniIntfID)].GetResourceID(context.Background(), uint32(config.NniIntfID),
-		ponresourcemanager.FLOW_ID, 1); err != nil {
+	if flowID, err = rsrMgr.GetFlowID(context.Background(), uint32(config.NniIntfID)); err != nil {
 		return err
 	}
 
@@ -400,7 +399,7 @@
 		DstMac:     GenerateMulticastMac(grp.Subs.OnuID, grp.GroupID),
 		PktTagType: DoubleTag}
 
-	flow := oop.Flow{AccessIntfId: int32(grp.Subs.PonIntf), OnuId: int32(grp.Subs.OnuID), UniId: int32(grp.Subs.UniID), FlowId: flowID[0],
+	flow := oop.Flow{AccessIntfId: int32(grp.Subs.PonIntf), OnuId: int32(grp.Subs.OnuID), UniId: int32(grp.Subs.UniID), FlowId: flowID,
 		FlowType: "multicast", AllocId: int32(grp.AllocID), GemportId: int32(grp.GemPortID),
 		Classifier: flowClassifier, Priority: int32(grp.Priority), PortNo: uint32(grp.Subs.UniPortNo), GroupId: uint32(grp.GroupID)}
 
@@ -408,24 +407,22 @@
 
 	st, _ := status.FromError(err)
 	if st.Code() == codes.AlreadyExists {
-		log.Debugw("Flow already exists", log.Fields{"err": err, "deviceFlow": flow})
+		logger.Debugw(nil, "Flow already exists", log.Fields{"err": err, "deviceFlow": flow})
 		return nil
 	}
 
 	if err != nil {
-		log.Errorw("Failed to add multicast flow to device", log.Fields{"err": err, "deviceFlow": flow})
-		rsrMgr.ResourceMgrs[uint32(grp.Subs.PonIntf)].FreeResourceID(context.Background(), uint32(config.NniIntfID),
-			ponresourcemanager.FLOW_ID, flowID)
+		logger.Errorw(nil, "Failed to add multicast flow to device", log.Fields{"err": err, "deviceFlow": flow})
 		return err
 	}
 
-	log.Debugw("Multicast flow added to device successfully ", log.Fields{"flow": flow})
+	logger.Debugw(nil, "Multicast flow added to device successfully ", log.Fields{"flow": flow})
 
 	return nil
 }
 
 func AddMulticastSched(grp *GroupData) error {
-	log.Infow("creating multicast sched", log.Fields{"GroupID": grp.GroupID})
+	logger.Infow(nil, "creating multicast sched", log.Fields{"GroupID": grp.GroupID})
 
 	SchedCfg := &tp_pb.SchedulerConfig{
 		Direction:    tp_pb.Direction_DOWNSTREAM,
@@ -448,18 +445,18 @@
 		GetTrafficScheduler(grp.Subs.TpInstance[grp.Subs.TestConfig.TpIDList[0]], SchedCfg, TfShInfo)}
 
 	if TrafficSched == nil {
-		log.Error("Create scheduler for multicast traffic failed")
+		logger.Error(nil, "Create scheduler for multicast traffic failed")
 		return errors.New(ReasonCodeToReasonString(SCHED_CREATION_FAILED))
 	}
 
-	log.Debugw("Sending Traffic scheduler create to device",
+	logger.Debugw(nil, "Sending Traffic scheduler create to device",
 		log.Fields{"Direction": tp_pb.Direction_DOWNSTREAM, "TrafficScheds": TrafficSched})
 
 	if _, err := grp.Subs.OpenOltClient.CreateTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
 		IntfId: grp.Subs.PonIntf, OnuId: grp.Subs.OnuID,
 		UniId: grp.Subs.UniID, PortNo: grp.Subs.UniPortNo,
 		TrafficScheds: TrafficSched}); err != nil {
-		log.Errorw("Failed to create traffic schedulers", log.Fields{"error": err})
+		logger.Errorw(nil, "Failed to create traffic schedulers", log.Fields{"error": err})
 		return errors.New(ReasonCodeToReasonString(SCHED_CREATION_FAILED))
 	}
 
@@ -467,7 +464,7 @@
 }
 
 func OpMemberToGroup(grp *GroupData, isAdding bool) (*oop.Empty, error) {
-	log.Infow("operating on group", log.Fields{"Adding": isAdding})
+	logger.Infow(nil, "operating on group", log.Fields{"Adding": isAdding})
 
 	var groupCfg oop.Group
 
@@ -498,40 +495,40 @@
 func AddMulticastQueueFlow(grp *GroupData) error {
 	var err error
 
-	log.Debugw("Create multicast queue flow", log.Fields{"GroupID": grp.GroupID, "AddGroup": grp.AddGroup,
+	logger.Debugw(nil, "Create multicast queue flow", log.Fields{"GroupID": grp.GroupID, "AddGroup": grp.AddGroup,
 		"AddFlow": grp.AddFlow, "AddSched": grp.AddSched, "AddQueue": grp.AddQueue, "AddMember": grp.AddMember})
 
 	if grp.AddGroup {
 		if _, err = CreateGroup(grp); err != nil {
-			log.Error("Failed to add group to device")
+			logger.Error(nil, "Failed to add group to device")
 			return err
 		}
 	}
 
 	if grp.AddFlow {
 		if err = AddMulticastFlow(grp); err != nil {
-			log.Error("Failed to add multicast flow to device")
+			logger.Error(nil, "Failed to add multicast flow to device")
 			return err
 		}
 	}
 
 	if grp.AddSched {
 		if err = AddMulticastSched(grp); err != nil {
-			log.Error("Failed to add multicast sched to device")
+			logger.Error(nil, "Failed to add multicast sched to device")
 			return err
 		}
 	}
 
 	if grp.AddQueue {
 		if _, err = OpMulticastTrafficQueue(grp, true); err != nil {
-			log.Error("Failed to add multicast queue to device")
+			logger.Error(nil, "Failed to add multicast queue to device")
 			return err
 		}
 	}
 
 	if grp.AddMember {
 		if _, err = OpMemberToGroup(grp, true); err != nil {
-			log.Error("Failed to add member to group")
+			logger.Error(nil, "Failed to add member to group")
 			return err
 		}
 	}
@@ -542,18 +539,18 @@
 func CreateTrafficSchedWithRetry(OpenOltClient oop.OpenoltClient, sched *oop.TrafficSchedulers) error {
 	maxRetry := 20
 	if _, err := OpenOltClient.CreateTrafficSchedulers(context.Background(), sched); err == nil {
-		log.Info("succeeded in first attempt")
+		logger.Info(nil, "succeeded in first attempt")
 		return nil
 	} else {
-		log.Info("going for a retry")
+		logger.Info(nil, "going for a retry")
 	}
 	for i := 0; i < maxRetry; i++ {
 		if _, err := OpenOltClient.CreateTrafficSchedulers(context.Background(), sched); err != nil {
-			log.Error("retying after delay")
+			logger.Error(nil, "retying after delay")
 			time.Sleep(50 * time.Millisecond)
 			continue
 		} else {
-			log.Infow("succeeded in retry iteration=%d!!", log.Fields{"i": i})
+			logger.Infow(nil, "succeeded in retry iteration=%d!!", log.Fields{"i": i})
 			return nil
 		}
 	}
@@ -564,7 +561,7 @@
 func CreateTrafficQueuesWithRetry(OpenOltClient oop.OpenoltClient, queue *oop.TrafficQueues) error {
 	maxRetry := 20
 	if _, err := OpenOltClient.CreateTrafficQueues(context.Background(), queue); err == nil {
-		log.Info("succeeded in first attempt")
+		logger.Info(nil, "succeeded in first attempt")
 		return nil
 	}
 	for i := 0; i < maxRetry; i++ {
@@ -572,7 +569,7 @@
 			time.Sleep(50 * time.Millisecond)
 			continue
 		} else {
-			log.Infow("succeeded in retry iteration=%d!!", log.Fields{"i": i})
+			logger.Infow(nil, "succeeded in retry iteration=%d!!", log.Fields{"i": i})
 			return nil
 		}
 	}
@@ -589,7 +586,7 @@
 
 	st, _ := status.FromError(err)
 	if st.Code() == codes.AlreadyExists {
-		log.Debugw("Flow already exists", log.Fields{"err": err, "deviceFlow": flow})
+		logger.Debugw(nil, "Flow already exists", log.Fields{"err": err, "deviceFlow": flow})
 		return nil
 	}
 	if st.Code() == codes.ResourceExhausted {
@@ -597,17 +594,17 @@
 			_, err = OpenOltClient.FlowAdd(context.Background(), flow)
 			st, _ := status.FromError(err)
 			if st.Code() == codes.ResourceExhausted {
-				log.Error("flow-install-failed--retrying")
+				logger.Error(nil, "flow-install-failed--retrying")
 				continue
 			} else if st.Code() == codes.OK {
-				log.Infow("flow-install-succeeded-on-retry", log.Fields{"i": i, "flow": flow})
+				logger.Infow(nil, "flow-install-succeeded-on-retry", log.Fields{"i": i, "flow": flow})
 				return nil
 			}
 		}
 
 	}
 
-	log.Debugw("Flow install failed on all retries ", log.Fields{"flow": flow})
+	logger.Debugw(nil, "Flow install failed on all retries ", log.Fields{"flow": flow})
 
 	return err
 }
diff --git a/go.mod b/go.mod
index 6100676..2a734dc 100644
--- a/go.mod
+++ b/go.mod
@@ -4,8 +4,8 @@
 
 require (
 	github.com/cenkalti/backoff/v3 v3.1.1
-	github.com/opencord/voltha-lib-go/v3 v3.0.20
-	github.com/opencord/voltha-protos/v3 v3.2.6
+	github.com/opencord/voltha-lib-go/v4 v4.0.0
+	github.com/opencord/voltha-protos/v4 v4.0.2
 	golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3
 	google.golang.org/grpc v1.24.0
 )
diff --git a/go.sum b/go.sum
index 521d915..79b12e5 100644
--- a/go.sum
+++ b/go.sum
@@ -4,6 +4,7 @@
 github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
 github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM=
 github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
+github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
 github.com/Shopify/sarama v1.23.1 h1:XxJBCZEoWJtoWjf/xRbmGUpAmTZGnuuF0ON0EvxxBrs=
 github.com/Shopify/sarama v1.23.1/go.mod h1:XLH1GYJnLVE0XCr6KdJGVJRTwY30moWNJ4sERjXX6fs=
 github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc=
@@ -23,8 +24,10 @@
 github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d/go.mod h1:f1iKL6ZhUWvbk7PdWVmOaak10o86cqMUYEmn1CZNGEI=
 github.com/bsm/sarama-cluster v2.1.15+incompatible h1:RkV6WiNRnqEEbp81druK8zYhmnIgdOjqSVi0+9Cnl2A=
 github.com/bsm/sarama-cluster v2.1.15+incompatible/go.mod h1:r7ao+4tTNXvWm+VRpRJchr2kQhqxgmAp2iEX5W96gMM=
+github.com/buraksezer/consistent v0.0.0-20191006190839-693edf70fd72/go.mod h1:OEE5igu/CDjGegM1Jn6ZMo7R6LlV/JChAkjfQQIRLpg=
 github.com/cenkalti/backoff/v3 v3.1.1 h1:UBHElAnr3ODEbpqPzX8g5sBcASjoLFtt3L/xwJ01L6E=
 github.com/cenkalti/backoff/v3 v3.1.1/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
+github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
 github.com/cevaris/ordered_map v0.0.0-20190319150403-3adeae072e73 h1:q1g9lSyo/nOIC3W5E3FK3Unrz8b9LdLXCyuC+ZcpPC0=
 github.com/cevaris/ordered_map v0.0.0-20190319150403-3adeae072e73/go.mod h1:507vXsotcZop7NZfBWdhPmVeOse4ko2R7AagJYrpoEg=
 github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
@@ -32,6 +35,8 @@
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
 github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa h1:OaNxuTZr7kxeODyLWsRMC+OD03aFUH+mW6r2d+MWa5Y=
 github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
+github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w=
+github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
 github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY=
 github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
@@ -190,11 +195,12 @@
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/gomega v1.4.2 h1:3mYCb7aPxS/RU7TI1y4rkEn1oKmPRjNJLNEXgw7MH2I=
 github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
-github.com/opencord/voltha-lib-go/v3 v3.0.20 h1:b3r4tKOREX63jOxDDioipPP/hkCcVwmRu8MXLx/LNMk=
-github.com/opencord/voltha-lib-go/v3 v3.0.20/go.mod h1:QuAohPQ+InSw+8XgCFxnp4cpHWcxO2efVTtiBFUmuOY=
-github.com/opencord/voltha-protos/v3 v3.2.3/go.mod h1:RIGHt7b80BHpHh3ceodknh0DxUjUHCWSbYbZqRx7Og0=
-github.com/opencord/voltha-protos/v3 v3.2.6 h1:Wf7PJ1Ekv9WYcbKBa9bgLNig1Y9krmy3zr6QRCug1LU=
-github.com/opencord/voltha-protos/v3 v3.2.6/go.mod h1:nl1ETp5Iw3avxOaKD8BJlYY5wYI4KeV95aT1pL63nto=
+github.com/opencord/voltha-lib-go/v4 v4.0.0 h1:D5dK5LQ6Z/UbUEsuQuP9OoAODQuNSY1qQnuF2PsxTKw=
+github.com/opencord/voltha-lib-go/v4 v4.0.0/go.mod h1:QgdIa7PlU0jhZT3qCPtcVt8/CpingKm4dUEROBrUBZg=
+github.com/opencord/voltha-protos/v4 v4.0.2 h1:SI25ljqftc8Tc28CgfqSE4IGCLJ5MgCmBQlE96hl9X8=
+github.com/opencord/voltha-protos/v4 v4.0.2/go.mod h1:W/OIFIyvFh/C0vchRUuarIsMylEhzCRM9pNxLvkPtKc=
+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/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
 github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
 github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
@@ -235,6 +241,7 @@
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=
 github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
+github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
 github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
 github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
@@ -248,6 +255,10 @@
 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/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
+github.com/uber/jaeger-client-go v2.23.1+incompatible h1:uArBYHQR0HqLFFAypI7RsWTzPSj/bDpmZZuQjMLSg1A=
+github.com/uber/jaeger-client-go v2.23.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
+github.com/uber/jaeger-lib v2.2.0+incompatible h1:MxZXOiR2JuoANZ3J6DE/U0kSFv/eJ/GfSYVCjK7dyaw=
+github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
 github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
 github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
 github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
diff --git a/main.go b/main.go
index 7a22df3..7b45bcb 100644
--- a/main.go
+++ b/main.go
@@ -28,11 +28,18 @@
 	"github.com/opencord/openolt-scale-tester/core"
 
 	"github.com/opencord/openolt-scale-tester/config"
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
+	"github.com/opencord/voltha-lib-go/v4/pkg/log"
 )
 
+var logger log.CLogger
+
 func init() {
-	_, _ = log.AddPackage(log.JSON, log.DebugLevel, nil)
+	// Setup this package so that it's log level can be modified at run time
+	var err error
+	logger, err = log.RegisterPackage(log.JSON, log.DebugLevel, log.Fields{})
+	if err != nil {
+		panic(err)
+	}
 }
 
 const (
@@ -63,10 +70,10 @@
 			syscall.SIGINT,
 			syscall.SIGTERM,
 			syscall.SIGQUIT:
-			log.Infow("closing-signal-received", log.Fields{"signal": s})
+			logger.Infow(nil, "closing-signal-received", log.Fields{"signal": s})
 			exitChannel <- 0
 		default:
-			log.Infow("unexpected-signal-received", log.Fields{"signal": s})
+			logger.Infow(nil, "unexpected-signal-received", log.Fields{"signal": s})
 			exitChannel <- 1
 		}
 	}()
@@ -97,23 +104,23 @@
 
 	// Setup default logger - applies for packages that do not have specific logger set
 	if _, err := log.SetDefaultLogger(log.JSON, 0, log.Fields{"instanceId": 0}); err != nil {
-		log.With(log.Fields{"error": err}).Fatal("Cannot setup logging")
+		logger.With(log.Fields{"error": err}).Fatal(nil, "Cannot setup logging")
 	}
 
 	// Update all loggers (provisioned via init) with a common field
 	if err := log.UpdateAllLoggers(log.Fields{"instanceId": 0}); err != nil {
-		log.With(log.Fields{"error": err}).Fatal("Cannot setup logging")
+		logger.With(log.Fields{"error": err}).Fatal(nil, "Cannot setup logging")
 	}
 
-	log.SetPackageLogLevel("github.com/opencord/voltha-lib-go/v3/pkg/adapters/common", log.DebugLevel)
+	log.SetPackageLogLevel("github.com/opencord/voltha-lib-go/v4/pkg/adapters/common", log.DebugLevel)
 
-	log.Infow("config", log.Fields{"config": *cf})
+	logger.Infow(nil, "config", log.Fields{"config": *cf})
 
 	go sc.openOltManager.Start(cf)
 
 	code := waitForExit()
-	log.Infow("received-a-closing-signal", log.Fields{"code": code})
+	logger.Infow(nil, "received-a-closing-signal", log.Fields{"code": code})
 
 	elapsed := time.Since(start)
-	log.Infow("run-time", log.Fields{"instanceId": 0, "time": elapsed / time.Second})
+	logger.Infow(nil, "run-time", log.Fields{"instanceId": 0, "time": elapsed / time.Second})
 }
diff --git a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/log/log.go b/vendor/github.com/opencord/voltha-lib-go/v3/pkg/log/log.go
deleted file mode 100644
index 47fa3fb..0000000
--- a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/log/log.go
+++ /dev/null
@@ -1,798 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
-
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
-
- * http://www.apache.org/licenses/LICENSE-2.0
-
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//Package log provides a structured Logger interface implemented using zap logger. It provides the following capabilities:
-//1. Package level logging - a go package can register itself (AddPackage) and have a logger created for that package.
-//2. Dynamic log level change - for all registered packages (SetAllLogLevel)
-//3. Dynamic log level change - for a given package (SetPackageLogLevel)
-//4. Provides a default logger for unregistered packages
-//5. Allow key-value pairs to be added to a logger(UpdateLogger) or all loggers (UpdateAllLoggers) at run time
-//6. Add to the log output the location where the log was invoked (filename.functionname.linenumber)
-//
-// Using package-level logging (recommended approach).  In the examples below, log refers to this log package.
-// 1.  In the appropriate package add the following in the init section of the package.  The log level can be changed
-// and any number of default fields can be added as well. The log level specifies the lowest log level that will be
-// in the output while the fields will be automatically added to all log printouts.
-//
-//	log.AddPackage(mylog.JSON, log.WarnLevel, log.Fields{"anyFieldName": "any value"})
-//
-//2. In the calling package, just invoke any of the publicly available functions of the logger.  Here is an  example
-// to write an Info log with additional fields:
-//
-//log.Infow("An example", mylog.Fields{"myStringOutput": "output", "myIntOutput": 2})
-//
-//3. To dynamically change the log level, you can use 1)SetLogLevel from inside your package or 2) SetPackageLogLevel
-// from anywhere or 3)  SetAllLogLevel from anywhere.
-//
-
-package log
-
-import (
-	"errors"
-	"fmt"
-	zp "go.uber.org/zap"
-	zc "go.uber.org/zap/zapcore"
-	"path"
-	"runtime"
-	"strings"
-)
-
-type LogLevel int8
-
-const (
-	// DebugLevel logs a message at debug level
-	DebugLevel = LogLevel(iota)
-	// InfoLevel logs a message at info level
-	InfoLevel
-	// WarnLevel logs a message at warning level
-	WarnLevel
-	// ErrorLevel logs a message at error level
-	ErrorLevel
-	// FatalLevel logs a message, then calls os.Exit(1).
-	FatalLevel
-)
-
-// CONSOLE formats the log for the console, mostly used during development
-const CONSOLE = "console"
-
-// JSON formats the log using json format, mostly used by an automated logging system consumption
-const JSON = "json"
-
-// Logger represents an abstract logging interface.  Any logging implementation used
-// will need to abide by this interface
-type Logger interface {
-	Debug(...interface{})
-	Debugln(...interface{})
-	Debugf(string, ...interface{})
-	Debugw(string, Fields)
-
-	Info(...interface{})
-	Infoln(...interface{})
-	Infof(string, ...interface{})
-	Infow(string, Fields)
-
-	Warn(...interface{})
-	Warnln(...interface{})
-	Warnf(string, ...interface{})
-	Warnw(string, Fields)
-
-	Error(...interface{})
-	Errorln(...interface{})
-	Errorf(string, ...interface{})
-	Errorw(string, Fields)
-
-	Fatal(...interface{})
-	Fatalln(...interface{})
-	Fatalf(string, ...interface{})
-	Fatalw(string, Fields)
-
-	With(Fields) Logger
-
-	// The following are added to be able to use this logger as a gRPC LoggerV2 if needed
-	//
-	Warning(...interface{})
-	Warningln(...interface{})
-	Warningf(string, ...interface{})
-
-	// V reports whether verbosity level l is at least the requested verbose level.
-	V(l LogLevel) bool
-
-	//Returns the log level of this specific logger
-	GetLogLevel() LogLevel
-}
-
-// Fields is used as key-value pairs for structured logging
-type Fields map[string]interface{}
-
-var defaultLogger *logger
-var cfg zp.Config
-
-var loggers map[string]*logger
-var cfgs map[string]zp.Config
-
-type logger struct {
-	log         *zp.SugaredLogger
-	parent      *zp.Logger
-	packageName string
-}
-
-func logLevelToAtomicLevel(l LogLevel) zp.AtomicLevel {
-	switch l {
-	case DebugLevel:
-		return zp.NewAtomicLevelAt(zc.DebugLevel)
-	case InfoLevel:
-		return zp.NewAtomicLevelAt(zc.InfoLevel)
-	case WarnLevel:
-		return zp.NewAtomicLevelAt(zc.WarnLevel)
-	case ErrorLevel:
-		return zp.NewAtomicLevelAt(zc.ErrorLevel)
-	case FatalLevel:
-		return zp.NewAtomicLevelAt(zc.FatalLevel)
-	}
-	return zp.NewAtomicLevelAt(zc.ErrorLevel)
-}
-
-func logLevelToLevel(l LogLevel) zc.Level {
-	switch l {
-	case DebugLevel:
-		return zc.DebugLevel
-	case InfoLevel:
-		return zc.InfoLevel
-	case WarnLevel:
-		return zc.WarnLevel
-	case ErrorLevel:
-		return zc.ErrorLevel
-	case FatalLevel:
-		return zc.FatalLevel
-	}
-	return zc.ErrorLevel
-}
-
-func levelToLogLevel(l zc.Level) LogLevel {
-	switch l {
-	case zc.DebugLevel:
-		return DebugLevel
-	case zc.InfoLevel:
-		return InfoLevel
-	case zc.WarnLevel:
-		return WarnLevel
-	case zc.ErrorLevel:
-		return ErrorLevel
-	case zc.FatalLevel:
-		return FatalLevel
-	}
-	return ErrorLevel
-}
-
-func StringToLogLevel(l string) (LogLevel, error) {
-	switch strings.ToUpper(l) {
-	case "DEBUG":
-		return DebugLevel, nil
-	case "INFO":
-		return InfoLevel, nil
-	case "WARN":
-		return WarnLevel, nil
-	case "ERROR":
-		return ErrorLevel, nil
-	case "FATAL":
-		return FatalLevel, nil
-	}
-	return 0, errors.New("Given LogLevel is invalid : " + l)
-}
-
-func LogLevelToString(l LogLevel) (string, error) {
-	switch l {
-	case DebugLevel:
-		return "DEBUG", nil
-	case InfoLevel:
-		return "INFO", nil
-	case WarnLevel:
-		return "WARN", nil
-	case ErrorLevel:
-		return "ERROR", nil
-	case FatalLevel:
-		return "FATAL", nil
-	}
-	return "", errors.New("Given LogLevel is invalid " + string(l))
-}
-
-func getDefaultConfig(outputType string, level LogLevel, defaultFields Fields) zp.Config {
-	return zp.Config{
-		Level:            logLevelToAtomicLevel(level),
-		Encoding:         outputType,
-		Development:      true,
-		OutputPaths:      []string{"stdout"},
-		ErrorOutputPaths: []string{"stderr"},
-		InitialFields:    defaultFields,
-		EncoderConfig: zc.EncoderConfig{
-			LevelKey:       "level",
-			MessageKey:     "msg",
-			TimeKey:        "ts",
-			CallerKey:      "caller",
-			StacktraceKey:  "stacktrace",
-			LineEnding:     zc.DefaultLineEnding,
-			EncodeLevel:    zc.LowercaseLevelEncoder,
-			EncodeTime:     zc.ISO8601TimeEncoder,
-			EncodeDuration: zc.SecondsDurationEncoder,
-			EncodeCaller:   zc.ShortCallerEncoder,
-		},
-	}
-}
-
-// SetLogger needs to be invoked before the logger API can be invoked.  This function
-// initialize the default logger (zap's sugaredlogger)
-func SetDefaultLogger(outputType string, level LogLevel, defaultFields Fields) (Logger, error) {
-	// Build a custom config using zap
-	cfg = getDefaultConfig(outputType, level, defaultFields)
-
-	l, err := cfg.Build(zp.AddCallerSkip(1))
-	if err != nil {
-		return nil, err
-	}
-
-	defaultLogger = &logger{
-		log:    l.Sugar(),
-		parent: l,
-	}
-
-	return defaultLogger, nil
-}
-
-// AddPackage registers a package to the log map.  Each package gets its own logger which allows
-// its config (loglevel) to be changed dynamically without interacting with the other packages.
-// outputType is JSON, level is the lowest level log to output with this logger and defaultFields is a map of
-// key-value pairs to always add to the output.
-// Note: AddPackage also returns a reference to the actual logger.  If a calling package uses this reference directly
-//instead of using the publicly available functions in this log package then a number of functionalities will not
-// be available to it, notably log tracing with filename.functionname.linenumber annotation.
-//
-// pkgNames parameter should be used for testing only as this function detects the caller's package.
-func AddPackage(outputType string, level LogLevel, defaultFields Fields, pkgNames ...string) (Logger, error) {
-	if cfgs == nil {
-		cfgs = make(map[string]zp.Config)
-	}
-	if loggers == nil {
-		loggers = make(map[string]*logger)
-	}
-
-	var pkgName string
-	for _, name := range pkgNames {
-		pkgName = name
-		break
-	}
-	if pkgName == "" {
-		pkgName, _, _, _ = getCallerInfo()
-	}
-
-	if _, exist := loggers[pkgName]; exist {
-		return loggers[pkgName], nil
-	}
-
-	cfgs[pkgName] = getDefaultConfig(outputType, level, defaultFields)
-
-	l, err := cfgs[pkgName].Build(zp.AddCallerSkip(1))
-	if err != nil {
-		return nil, err
-	}
-
-	loggers[pkgName] = &logger{
-		log:         l.Sugar(),
-		parent:      l,
-		packageName: pkgName,
-	}
-	return loggers[pkgName], nil
-}
-
-//UpdateAllLoggers create new loggers for all registered pacakges with the defaultFields.
-func UpdateAllLoggers(defaultFields Fields) error {
-	for pkgName, cfg := range cfgs {
-		for k, v := range defaultFields {
-			if cfg.InitialFields == nil {
-				cfg.InitialFields = make(map[string]interface{})
-			}
-			cfg.InitialFields[k] = v
-		}
-		l, err := cfg.Build(zp.AddCallerSkip(1))
-		if err != nil {
-			return err
-		}
-
-		// Update the existing zap logger instance
-		loggers[pkgName].log = l.Sugar()
-		loggers[pkgName].parent = l
-	}
-	return nil
-}
-
-// Return a list of all packages that have individually-configured loggers
-func GetPackageNames() []string {
-	i := 0
-	keys := make([]string, len(loggers))
-	for k := range loggers {
-		keys[i] = k
-		i++
-	}
-	return keys
-}
-
-// UpdateLogger updates the logger associated with a caller's package with supplied defaultFields
-func UpdateLogger(defaultFields Fields) error {
-	pkgName, _, _, _ := getCallerInfo()
-	if _, exist := loggers[pkgName]; !exist {
-		return fmt.Errorf("package-%s-not-registered", pkgName)
-	}
-
-	// Build a new logger
-	if _, exist := cfgs[pkgName]; !exist {
-		return fmt.Errorf("config-%s-not-registered", pkgName)
-	}
-
-	cfg := cfgs[pkgName]
-	for k, v := range defaultFields {
-		if cfg.InitialFields == nil {
-			cfg.InitialFields = make(map[string]interface{})
-		}
-		cfg.InitialFields[k] = v
-	}
-	l, err := cfg.Build(zp.AddCallerSkip(1))
-	if err != nil {
-		return err
-	}
-
-	// Update the existing zap logger instance
-	loggers[pkgName].log = l.Sugar()
-	loggers[pkgName].parent = l
-
-	return nil
-}
-
-func setLevel(cfg zp.Config, level LogLevel) {
-	switch level {
-	case DebugLevel:
-		cfg.Level.SetLevel(zc.DebugLevel)
-	case InfoLevel:
-		cfg.Level.SetLevel(zc.InfoLevel)
-	case WarnLevel:
-		cfg.Level.SetLevel(zc.WarnLevel)
-	case ErrorLevel:
-		cfg.Level.SetLevel(zc.ErrorLevel)
-	case FatalLevel:
-		cfg.Level.SetLevel(zc.FatalLevel)
-	default:
-		cfg.Level.SetLevel(zc.ErrorLevel)
-	}
-}
-
-//SetPackageLogLevel dynamically sets the log level of a given package to level.  This is typically invoked at an
-// application level during debugging
-func SetPackageLogLevel(packageName string, level LogLevel) {
-	// Get proper config
-	if cfg, ok := cfgs[packageName]; ok {
-		setLevel(cfg, level)
-	}
-}
-
-//SetAllLogLevel sets the log level of all registered packages to level
-func SetAllLogLevel(level LogLevel) {
-	// Get proper config
-	for _, cfg := range cfgs {
-		setLevel(cfg, level)
-	}
-}
-
-//GetPackageLogLevel returns the current log level of a package.
-func GetPackageLogLevel(packageName ...string) (LogLevel, error) {
-	var name string
-	if len(packageName) == 1 {
-		name = packageName[0]
-	} else {
-		name, _, _, _ = getCallerInfo()
-	}
-	if cfg, ok := cfgs[name]; ok {
-		return levelToLogLevel(cfg.Level.Level()), nil
-	}
-	return 0, fmt.Errorf("unknown-package-%s", name)
-}
-
-//GetDefaultLogLevel gets the log level used for packages that don't have specific loggers
-func GetDefaultLogLevel() LogLevel {
-	return levelToLogLevel(cfg.Level.Level())
-}
-
-//SetLogLevel sets the log level for the logger corresponding to the caller's package
-func SetLogLevel(level LogLevel) error {
-	pkgName, _, _, _ := getCallerInfo()
-	if _, exist := cfgs[pkgName]; !exist {
-		return fmt.Errorf("unregistered-package-%s", pkgName)
-	}
-	cfg := cfgs[pkgName]
-	setLevel(cfg, level)
-	return nil
-}
-
-//SetDefaultLogLevel sets the log level used for packages that don't have specific loggers
-func SetDefaultLogLevel(level LogLevel) {
-	setLevel(cfg, level)
-}
-
-// CleanUp flushed any buffered log entries. Applications should take care to call
-// CleanUp before exiting.
-func CleanUp() error {
-	for _, logger := range loggers {
-		if logger != nil {
-			if logger.parent != nil {
-				if err := logger.parent.Sync(); err != nil {
-					return err
-				}
-			}
-		}
-	}
-	if defaultLogger != nil {
-		if defaultLogger.parent != nil {
-			if err := defaultLogger.parent.Sync(); err != nil {
-				return err
-			}
-		}
-	}
-	return nil
-}
-
-func getCallerInfo() (string, string, string, int) {
-	// Since the caller of a log function is one stack frame before (in terms of stack higher level) the log.go
-	// filename, then first look for the last log.go filename and then grab the caller info one level higher.
-	maxLevel := 3
-	skiplevel := 3 // Level with the most empirical success to see the last log.go stack frame.
-	pc := make([]uintptr, maxLevel)
-	n := runtime.Callers(skiplevel, pc)
-	packageName := ""
-	funcName := ""
-	fileName := ""
-	var line int
-	if n == 0 {
-		return packageName, fileName, funcName, line
-	}
-	frames := runtime.CallersFrames(pc[:n])
-	var frame runtime.Frame
-	var foundFrame runtime.Frame
-	more := true
-	for more {
-		frame, more = frames.Next()
-		_, fileName = path.Split(frame.File)
-		if fileName != "log.go" {
-			foundFrame = frame // First frame after log.go in the frame stack
-			break
-		}
-	}
-	parts := strings.Split(foundFrame.Function, ".")
-	pl := len(parts)
-	if pl >= 2 {
-		funcName = parts[pl-1]
-		if parts[pl-2][0] == '(' {
-			packageName = strings.Join(parts[0:pl-2], ".")
-		} else {
-			packageName = strings.Join(parts[0:pl-1], ".")
-		}
-	}
-
-	if strings.HasSuffix(packageName, ".init") {
-		packageName = strings.TrimSuffix(packageName, ".init")
-	}
-
-	if strings.HasSuffix(fileName, ".go") {
-		fileName = strings.TrimSuffix(fileName, ".go")
-	}
-
-	return packageName, fileName, funcName, foundFrame.Line
-}
-
-func getPackageLevelSugaredLogger() *zp.SugaredLogger {
-	pkgName, fileName, funcName, line := getCallerInfo()
-	if _, exist := loggers[pkgName]; exist {
-		return loggers[pkgName].log.With("caller", fmt.Sprintf("%s.%s:%d", fileName, funcName, line))
-	}
-	return defaultLogger.log.With("caller", fmt.Sprintf("%s.%s:%d", fileName, funcName, line))
-}
-
-func getPackageLevelLogger() Logger {
-	pkgName, _, _, _ := getCallerInfo()
-	if _, exist := loggers[pkgName]; exist {
-		return loggers[pkgName]
-	}
-	return defaultLogger
-}
-
-func serializeMap(fields Fields) []interface{} {
-	data := make([]interface{}, len(fields)*2)
-	i := 0
-	for k, v := range fields {
-		data[i] = k
-		data[i+1] = v
-		i = i + 2
-	}
-	return data
-}
-
-// With returns a logger initialized with the key-value pairs
-func (l logger) With(keysAndValues Fields) Logger {
-	return logger{log: l.log.With(serializeMap(keysAndValues)...), parent: l.parent}
-}
-
-// Debug logs a message at level Debug on the standard logger.
-func (l logger) Debug(args ...interface{}) {
-	l.log.Debug(args...)
-}
-
-// Debugln logs a message at level Debug on the standard logger with a line feed. Default in any case.
-func (l logger) Debugln(args ...interface{}) {
-	l.log.Debug(args...)
-}
-
-// Debugw logs a message at level Debug on the standard logger.
-func (l logger) Debugf(format string, args ...interface{}) {
-	l.log.Debugf(format, args...)
-}
-
-// Debugw logs a message with some additional context. The variadic key-value
-// pairs are treated as they are in With.
-func (l logger) Debugw(msg string, keysAndValues Fields) {
-	l.log.Debugw(msg, serializeMap(keysAndValues)...)
-}
-
-// Info logs a message at level Info on the standard logger.
-func (l logger) Info(args ...interface{}) {
-	l.log.Info(args...)
-}
-
-// Infoln logs a message at level Info on the standard logger with a line feed. Default in any case.
-func (l logger) Infoln(args ...interface{}) {
-	l.log.Info(args...)
-	//msg := fmt.Sprintln(args...)
-	//l.sourced().Info(msg[:len(msg)-1])
-}
-
-// Infof logs a message at level Info on the standard logger.
-func (l logger) Infof(format string, args ...interface{}) {
-	l.log.Infof(format, args...)
-}
-
-// Infow logs a message with some additional context. The variadic key-value
-// pairs are treated as they are in With.
-func (l logger) Infow(msg string, keysAndValues Fields) {
-	l.log.Infow(msg, serializeMap(keysAndValues)...)
-}
-
-// Warn logs a message at level Warn on the standard logger.
-func (l logger) Warn(args ...interface{}) {
-	l.log.Warn(args...)
-}
-
-// Warnln logs a message at level Warn on the standard logger with a line feed. Default in any case.
-func (l logger) Warnln(args ...interface{}) {
-	l.log.Warn(args...)
-}
-
-// Warnf logs a message at level Warn on the standard logger.
-func (l logger) Warnf(format string, args ...interface{}) {
-	l.log.Warnf(format, args...)
-}
-
-// Warnw logs a message with some additional context. The variadic key-value
-// pairs are treated as they are in With.
-func (l logger) Warnw(msg string, keysAndValues Fields) {
-	l.log.Warnw(msg, serializeMap(keysAndValues)...)
-}
-
-// Error logs a message at level Error on the standard logger.
-func (l logger) Error(args ...interface{}) {
-	l.log.Error(args...)
-}
-
-// Errorln logs a message at level Error on the standard logger with a line feed. Default in any case.
-func (l logger) Errorln(args ...interface{}) {
-	l.log.Error(args...)
-}
-
-// Errorf logs a message at level Error on the standard logger.
-func (l logger) Errorf(format string, args ...interface{}) {
-	l.log.Errorf(format, args...)
-}
-
-// Errorw logs a message with some additional context. The variadic key-value
-// pairs are treated as they are in With.
-func (l logger) Errorw(msg string, keysAndValues Fields) {
-	l.log.Errorw(msg, serializeMap(keysAndValues)...)
-}
-
-// Fatal logs a message at level Fatal on the standard logger.
-func (l logger) Fatal(args ...interface{}) {
-	l.log.Fatal(args...)
-}
-
-// Fatalln logs a message at level Fatal on the standard logger with a line feed. Default in any case.
-func (l logger) Fatalln(args ...interface{}) {
-	l.log.Fatal(args...)
-}
-
-// Fatalf logs a message at level Fatal on the standard logger.
-func (l logger) Fatalf(format string, args ...interface{}) {
-	l.log.Fatalf(format, args...)
-}
-
-// Fatalw logs a message with some additional context. The variadic key-value
-// pairs are treated as they are in With.
-func (l logger) Fatalw(msg string, keysAndValues Fields) {
-	l.log.Fatalw(msg, serializeMap(keysAndValues)...)
-}
-
-// Warning logs a message at level Warn on the standard logger.
-func (l logger) Warning(args ...interface{}) {
-	l.log.Warn(args...)
-}
-
-// Warningln logs a message at level Warn on the standard logger with a line feed. Default in any case.
-func (l logger) Warningln(args ...interface{}) {
-	l.log.Warn(args...)
-}
-
-// Warningf logs a message at level Warn on the standard logger.
-func (l logger) Warningf(format string, args ...interface{}) {
-	l.log.Warnf(format, args...)
-}
-
-// V reports whether verbosity level l is at least the requested verbose level.
-func (l logger) V(level LogLevel) bool {
-	return l.parent.Core().Enabled(logLevelToLevel(level))
-}
-
-// GetLogLevel returns the current level of the logger
-func (l logger) GetLogLevel() LogLevel {
-	return levelToLogLevel(cfgs[l.packageName].Level.Level())
-}
-
-// With returns a logger initialized with the key-value pairs
-func With(keysAndValues Fields) Logger {
-	return logger{log: getPackageLevelSugaredLogger().With(serializeMap(keysAndValues)...), parent: defaultLogger.parent}
-}
-
-// Debug logs a message at level Debug on the standard logger.
-func Debug(args ...interface{}) {
-	getPackageLevelSugaredLogger().Debug(args...)
-}
-
-// Debugln logs a message at level Debug on the standard logger.
-func Debugln(args ...interface{}) {
-	getPackageLevelSugaredLogger().Debug(args...)
-}
-
-// Debugf logs a message at level Debug on the standard logger.
-func Debugf(format string, args ...interface{}) {
-	getPackageLevelSugaredLogger().Debugf(format, args...)
-}
-
-// Debugw logs a message with some additional context. The variadic key-value
-// pairs are treated as they are in With.
-func Debugw(msg string, keysAndValues Fields) {
-	getPackageLevelSugaredLogger().Debugw(msg, serializeMap(keysAndValues)...)
-}
-
-// Info logs a message at level Info on the standard logger.
-func Info(args ...interface{}) {
-	getPackageLevelSugaredLogger().Info(args...)
-}
-
-// Infoln logs a message at level Info on the standard logger.
-func Infoln(args ...interface{}) {
-	getPackageLevelSugaredLogger().Info(args...)
-}
-
-// Infof logs a message at level Info on the standard logger.
-func Infof(format string, args ...interface{}) {
-	getPackageLevelSugaredLogger().Infof(format, args...)
-}
-
-//Infow logs a message with some additional context. The variadic key-value
-//pairs are treated as they are in With.
-func Infow(msg string, keysAndValues Fields) {
-	getPackageLevelSugaredLogger().Infow(msg, serializeMap(keysAndValues)...)
-}
-
-// Warn logs a message at level Warn on the standard logger.
-func Warn(args ...interface{}) {
-	getPackageLevelSugaredLogger().Warn(args...)
-}
-
-// Warnln logs a message at level Warn on the standard logger.
-func Warnln(args ...interface{}) {
-	getPackageLevelSugaredLogger().Warn(args...)
-}
-
-// Warnf logs a message at level Warn on the standard logger.
-func Warnf(format string, args ...interface{}) {
-	getPackageLevelSugaredLogger().Warnf(format, args...)
-}
-
-// Warnw logs a message with some additional context. The variadic key-value
-// pairs are treated as they are in With.
-func Warnw(msg string, keysAndValues Fields) {
-	getPackageLevelSugaredLogger().Warnw(msg, serializeMap(keysAndValues)...)
-}
-
-// Error logs a message at level Error on the standard logger.
-func Error(args ...interface{}) {
-	getPackageLevelSugaredLogger().Error(args...)
-}
-
-// Errorln logs a message at level Error on the standard logger.
-func Errorln(args ...interface{}) {
-	getPackageLevelSugaredLogger().Error(args...)
-}
-
-// Errorf logs a message at level Error on the standard logger.
-func Errorf(format string, args ...interface{}) {
-	getPackageLevelSugaredLogger().Errorf(format, args...)
-}
-
-// Errorw logs a message with some additional context. The variadic key-value
-// pairs are treated as they are in With.
-func Errorw(msg string, keysAndValues Fields) {
-	getPackageLevelSugaredLogger().Errorw(msg, serializeMap(keysAndValues)...)
-}
-
-// Fatal logs a message at level Fatal on the standard logger.
-func Fatal(args ...interface{}) {
-	getPackageLevelSugaredLogger().Fatal(args...)
-}
-
-// Fatalln logs a message at level Fatal on the standard logger.
-func Fatalln(args ...interface{}) {
-	getPackageLevelSugaredLogger().Fatal(args...)
-}
-
-// Fatalf logs a message at level Fatal on the standard logger.
-func Fatalf(format string, args ...interface{}) {
-	getPackageLevelSugaredLogger().Fatalf(format, args...)
-}
-
-// Fatalw logs a message with some additional context. The variadic key-value
-// pairs are treated as they are in With.
-func Fatalw(msg string, keysAndValues Fields) {
-	getPackageLevelSugaredLogger().Fatalw(msg, serializeMap(keysAndValues)...)
-}
-
-// Warning logs a message at level Warn on the standard logger.
-func Warning(args ...interface{}) {
-	getPackageLevelSugaredLogger().Warn(args...)
-}
-
-// Warningln logs a message at level Warn on the standard logger.
-func Warningln(args ...interface{}) {
-	getPackageLevelSugaredLogger().Warn(args...)
-}
-
-// Warningf logs a message at level Warn on the standard logger.
-func Warningf(format string, args ...interface{}) {
-	getPackageLevelSugaredLogger().Warnf(format, args...)
-}
-
-// V reports whether verbosity level l is at least the requested verbose level.
-func V(level LogLevel) bool {
-	return getPackageLevelLogger().V(level)
-}
-
-//GetLogLevel returns the log level of the invoking package
-func GetLogLevel() LogLevel {
-	return getPackageLevelLogger().GetLogLevel()
-}
diff --git a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/techprofile/tech_profile.go b/vendor/github.com/opencord/voltha-lib-go/v3/pkg/techprofile/tech_profile.go
deleted file mode 100644
index ba8855f..0000000
--- a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/techprofile/tech_profile.go
+++ /dev/null
@@ -1,923 +0,0 @@
-/*
- * Copyright 2019-present Open Networking Foundation
-
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
-
- * http://www.apache.org/licenses/LICENSE-2.0
-
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package techprofile
-
-import (
-	"context"
-	"encoding/json"
-	"errors"
-	"fmt"
-	"regexp"
-	"strconv"
-
-	"github.com/opencord/voltha-lib-go/v3/pkg/db"
-
-	"github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore"
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-	tp_pb "github.com/opencord/voltha-protos/v3/go/tech_profile"
-)
-
-// Interface to pon resource manager APIs
-type iPonResourceMgr interface {
-	GetResourceID(ctx context.Context, IntfID uint32, ResourceType string, NumIDs uint32) ([]uint32, error)
-	GetResourceTypeAllocID() string
-	GetResourceTypeGemPortID() string
-	GetTechnology() string
-}
-
-type Direction int32
-
-const (
-	Direction_UPSTREAM      Direction = 0
-	Direction_DOWNSTREAM    Direction = 1
-	Direction_BIDIRECTIONAL Direction = 2
-)
-
-var Direction_name = map[Direction]string{
-	0: "UPSTREAM",
-	1: "DOWNSTREAM",
-	2: "BIDIRECTIONAL",
-}
-
-type SchedulingPolicy int32
-
-const (
-	SchedulingPolicy_WRR            SchedulingPolicy = 0
-	SchedulingPolicy_StrictPriority SchedulingPolicy = 1
-	SchedulingPolicy_Hybrid         SchedulingPolicy = 2
-)
-
-var SchedulingPolicy_name = map[SchedulingPolicy]string{
-	0: "WRR",
-	1: "StrictPriority",
-	2: "Hybrid",
-}
-
-type AdditionalBW int32
-
-const (
-	AdditionalBW_AdditionalBW_None       AdditionalBW = 0
-	AdditionalBW_AdditionalBW_NA         AdditionalBW = 1
-	AdditionalBW_AdditionalBW_BestEffort AdditionalBW = 2
-	AdditionalBW_AdditionalBW_Auto       AdditionalBW = 3
-)
-
-var AdditionalBW_name = map[AdditionalBW]string{
-	0: "AdditionalBW_None",
-	1: "AdditionalBW_NA",
-	2: "AdditionalBW_BestEffort",
-	3: "AdditionalBW_Auto",
-}
-
-type DiscardPolicy int32
-
-const (
-	DiscardPolicy_TailDrop  DiscardPolicy = 0
-	DiscardPolicy_WTailDrop DiscardPolicy = 1
-	DiscardPolicy_Red       DiscardPolicy = 2
-	DiscardPolicy_WRed      DiscardPolicy = 3
-)
-
-var DiscardPolicy_name = map[DiscardPolicy]string{
-	0: "TailDrop",
-	1: "WTailDrop",
-	2: "Red",
-	3: "WRed",
-}
-
-// Required uniPortName format
-var uniPortNameFormat = regexp.MustCompile(`^pon-{[0-9]+}/onu-{[0-9]+}/uni-{[0-9]+}$`)
-
-/*
-type InferredAdditionBWIndication int32
-
-const (
-	InferredAdditionBWIndication_InferredAdditionBWIndication_None       InferredAdditionBWIndication = 0
-	InferredAdditionBWIndication_InferredAdditionBWIndication_Assured    InferredAdditionBWIndication = 1
-	InferredAdditionBWIndication_InferredAdditionBWIndication_BestEffort InferredAdditionBWIndication = 2
-)
-
-var InferredAdditionBWIndication_name = map[int32]string{
-	0: "InferredAdditionBWIndication_None",
-	1: "InferredAdditionBWIndication_Assured",
-	2: "InferredAdditionBWIndication_BestEffort",
-}
-*/
-// instance control defaults
-const (
-	defaultOnuInstance    = "multi-instance"
-	defaultUniInstance    = "single-instance"
-	defaultGemPayloadSize = "auto"
-)
-
-const MAX_GEM_PAYLOAD = "max_gem_payload_size"
-
-type InstanceControl struct {
-	Onu               string `json:"ONU"`
-	Uni               string `json:"uni"`
-	MaxGemPayloadSize string `json:"max_gem_payload_size"`
-}
-
-// default discard config constants
-const (
-	defaultMinThreshold   = 0
-	defaultMaxThreshold   = 0
-	defaultMaxProbability = 0
-)
-
-type DiscardConfig struct {
-	MinThreshold   int `json:"min_threshold"`
-	MaxThreshold   int `json:"max_threshold"`
-	MaxProbability int `json:"max_probability"`
-}
-
-// default scheduler contants
-const (
-	defaultAdditionalBw     = AdditionalBW_AdditionalBW_BestEffort
-	defaultPriority         = 0
-	defaultWeight           = 0
-	defaultQueueSchedPolicy = SchedulingPolicy_Hybrid
-)
-
-type Scheduler struct {
-	Direction    string `json:"direction"`
-	AdditionalBw string `json:"additional_bw"`
-	Priority     uint32 `json:"priority"`
-	Weight       uint32 `json:"weight"`
-	QSchedPolicy string `json:"q_sched_policy"`
-}
-
-// default GEM attribute constants
-const (
-	defaultAESEncryption     = "True"
-	defaultPriorityQueue     = 0
-	defaultQueueWeight       = 0
-	defaultMaxQueueSize      = "auto"
-	defaultdropPolicy        = DiscardPolicy_TailDrop
-	defaultSchedulePolicy    = SchedulingPolicy_WRR
-	defaultIsMulticast       = "False"
-	defaultAccessControlList = "224.0.0.0-239.255.255.255"
-	defaultMcastGemID        = 4069
-)
-
-type GemPortAttribute struct {
-	MaxQueueSize     string        `json:"max_q_size"`
-	PbitMap          string        `json:"pbit_map"`
-	AesEncryption    string        `json:"aes_encryption"`
-	SchedulingPolicy string        `json:"scheduling_policy"`
-	PriorityQueue    uint32        `json:"priority_q"`
-	Weight           uint32        `json:"weight"`
-	DiscardPolicy    string        `json:"discard_policy"`
-	DiscardConfig    DiscardConfig `json:"discard_config"`
-	IsMulticast      string        `json:"is_multicast"`
-	DControlList     string        `json:"dynamic_access_control_list"`
-	SControlList     string        `json:"static_access_control_list"`
-	McastGemID       uint32        `json:"multicast_gem_id"`
-}
-
-type iScheduler struct {
-	AllocID      uint32 `json:"alloc_id"`
-	Direction    string `json:"direction"`
-	AdditionalBw string `json:"additional_bw"`
-	Priority     uint32 `json:"priority"`
-	Weight       uint32 `json:"weight"`
-	QSchedPolicy string `json:"q_sched_policy"`
-}
-type iGemPortAttribute struct {
-	GemportID        uint32        `json:"gemport_id"`
-	MaxQueueSize     string        `json:"max_q_size"`
-	PbitMap          string        `json:"pbit_map"`
-	AesEncryption    string        `json:"aes_encryption"`
-	SchedulingPolicy string        `json:"scheduling_policy"`
-	PriorityQueue    uint32        `json:"priority_q"`
-	Weight           uint32        `json:"weight"`
-	DiscardPolicy    string        `json:"discard_policy"`
-	DiscardConfig    DiscardConfig `json:"discard_config"`
-	IsMulticast      string        `json:"is_multicast"`
-	DControlList     string        `json:"dynamic_access_control_list"`
-	SControlList     string        `json:"static_access_control_list"`
-	McastGemID       uint32        `json:"multicast_gem_id"`
-}
-
-type TechProfileMgr struct {
-	config      *TechProfileFlags
-	resourceMgr iPonResourceMgr
-}
-type DefaultTechProfile struct {
-	Name                           string             `json:"name"`
-	ProfileType                    string             `json:"profile_type"`
-	Version                        int                `json:"version"`
-	NumGemPorts                    uint32             `json:"num_gem_ports"`
-	InstanceCtrl                   InstanceControl    `json:"instance_control"`
-	UsScheduler                    Scheduler          `json:"us_scheduler"`
-	DsScheduler                    Scheduler          `json:"ds_scheduler"`
-	UpstreamGemPortAttributeList   []GemPortAttribute `json:"upstream_gem_port_attribute_list"`
-	DownstreamGemPortAttributeList []GemPortAttribute `json:"downstream_gem_port_attribute_list"`
-}
-type TechProfile struct {
-	Name                           string              `json:"name"`
-	SubscriberIdentifier           string              `json:"subscriber_identifier"`
-	ProfileType                    string              `json:"profile_type"`
-	Version                        int                 `json:"version"`
-	NumGemPorts                    uint32              `json:"num_gem_ports"`
-	InstanceCtrl                   InstanceControl     `json:"instance_control"`
-	UsScheduler                    iScheduler          `json:"us_scheduler"`
-	DsScheduler                    iScheduler          `json:"ds_scheduler"`
-	UpstreamGemPortAttributeList   []iGemPortAttribute `json:"upstream_gem_port_attribute_list"`
-	DownstreamGemPortAttributeList []iGemPortAttribute `json:"downstream_gem_port_attribute_list"`
-}
-
-func (t *TechProfileMgr) SetKVClient() *db.Backend {
-	addr := t.config.KVStoreHost + ":" + strconv.Itoa(t.config.KVStorePort)
-	kvClient, err := newKVClient(t.config.KVStoreType, addr, t.config.KVStoreTimeout)
-	if err != nil {
-		log.Errorw("failed-to-create-kv-client",
-			log.Fields{
-				"type": t.config.KVStoreType, "host": t.config.KVStoreHost, "port": t.config.KVStorePort,
-				"timeout": t.config.KVStoreTimeout, "prefix": t.config.TPKVPathPrefix,
-				"error": err.Error(),
-			})
-		return nil
-	}
-	return &db.Backend{
-		Client:     kvClient,
-		StoreType:  t.config.KVStoreType,
-		Host:       t.config.KVStoreHost,
-		Port:       t.config.KVStorePort,
-		Timeout:    t.config.KVStoreTimeout,
-		PathPrefix: t.config.TPKVPathPrefix}
-
-	/* TODO : Make sure direct call to NewBackend is working fine with backend , currently there is some
-	            issue between kv store and backend , core is not calling NewBackend directly
-		   kv := model.NewBackend(t.config.KVStoreType, t.config.KVStoreHost, t.config.KVStorePort,
-										t.config.KVStoreTimeout,  kvStoreTechProfilePathPrefix)
-	*/
-}
-
-func newKVClient(storeType string, address string, timeout int) (kvstore.Client, error) {
-
-	log.Infow("kv-store", log.Fields{"storeType": storeType, "address": address})
-	switch storeType {
-	case "consul":
-		return kvstore.NewConsulClient(address, timeout)
-	case "etcd":
-		return kvstore.NewEtcdClient(address, timeout)
-	}
-	return nil, errors.New("unsupported-kv-store")
-}
-
-func NewTechProfile(resourceMgr iPonResourceMgr, KVStoreType string, KVStoreHost string, KVStorePort int) (*TechProfileMgr, error) {
-	var techprofileObj TechProfileMgr
-	log.Debug("Initializing techprofile Manager")
-	techprofileObj.config = NewTechProfileFlags(KVStoreType, KVStoreHost, KVStorePort)
-	techprofileObj.config.KVBackend = techprofileObj.SetKVClient()
-	if techprofileObj.config.KVBackend == nil {
-		log.Error("Failed to initialize KV backend\n")
-		return nil, errors.New("KV backend init failed")
-	}
-	techprofileObj.resourceMgr = resourceMgr
-	log.Debug("Initializing techprofile object instance success")
-	return &techprofileObj, nil
-}
-
-func (t *TechProfileMgr) GetTechProfileInstanceKVPath(techProfiletblID uint32, uniPortName string) string {
-	return fmt.Sprintf(t.config.TPInstanceKVPath, t.resourceMgr.GetTechnology(), techProfiletblID, uniPortName)
-}
-
-func (t *TechProfileMgr) GetTPInstanceFromKVStore(ctx context.Context, techProfiletblID uint32, path string) (*TechProfile, error) {
-	var KvTpIns TechProfile
-	var resPtr *TechProfile = &KvTpIns
-	var err error
-	var kvResult *kvstore.KVPair
-
-	kvResult, _ = t.config.KVBackend.Get(ctx, path)
-	if kvResult == nil {
-		log.Infow("tp-instance-not-found-on-kv", log.Fields{"key": path})
-		return nil, nil
-	} else {
-		if value, err := kvstore.ToByte(kvResult.Value); err == nil {
-			if err = json.Unmarshal(value, resPtr); err != nil {
-				log.Errorw("error-unmarshal-kv-result", log.Fields{"key": path, "value": value})
-				return nil, errors.New("error-unmarshal-kv-result")
-			} else {
-				return resPtr, nil
-			}
-		}
-	}
-	return nil, err
-}
-
-func (t *TechProfileMgr) addTechProfInstanceToKVStore(ctx context.Context, techProfiletblID uint32, uniPortName string, tpInstance *TechProfile) error {
-	path := t.GetTechProfileInstanceKVPath(techProfiletblID, uniPortName)
-	log.Debugw("Adding techprof instance to kvstore", log.Fields{"key": path, "tpinstance": tpInstance})
-	tpInstanceJson, err := json.Marshal(*tpInstance)
-	if err == nil {
-		// Backend will convert JSON byte array into string format
-		log.Debugw("Storing tech profile instance to KV Store", log.Fields{"key": path, "val": tpInstanceJson})
-		err = t.config.KVBackend.Put(ctx, path, tpInstanceJson)
-	} else {
-		log.Errorw("Error in marshaling into Json format", log.Fields{"key": path, "tpinstance": tpInstance})
-	}
-	return err
-}
-func (t *TechProfileMgr) getTPFromKVStore(ctx context.Context, techProfiletblID uint32) *DefaultTechProfile {
-	var kvtechprofile DefaultTechProfile
-	key := fmt.Sprintf(t.config.TPFileKVPath, t.resourceMgr.GetTechnology(), techProfiletblID)
-	log.Debugw("Getting techprofile from KV store", log.Fields{"techProfiletblID": techProfiletblID, "Key": key})
-	kvresult, err := t.config.KVBackend.Get(ctx, key)
-	if err != nil {
-		log.Errorw("Error while fetching value from KV store", log.Fields{"key": key})
-		return nil
-	}
-	if kvresult != nil {
-		/* Backend will return Value in string format,needs to be converted to []byte before unmarshal*/
-		if value, err := kvstore.ToByte(kvresult.Value); err == nil {
-			if err = json.Unmarshal(value, &kvtechprofile); err != nil {
-				log.Errorw("Error unmarshaling techprofile fetched from KV store", log.Fields{"techProfiletblID": techProfiletblID, "error": err, "techprofile_json": value})
-				return nil
-			}
-
-			log.Debugw("Success fetched techprofile from KV store", log.Fields{"techProfiletblID": techProfiletblID, "value": kvtechprofile})
-			return &kvtechprofile
-		}
-	}
-	return nil
-}
-
-func (t *TechProfileMgr) CreateTechProfInstance(ctx context.Context, techProfiletblID uint32, uniPortName string, intfId uint32) (*TechProfile, error) {
-	var tpInstance *TechProfile
-	log.Infow("creating-tp-instance", log.Fields{"tableid": techProfiletblID, "uni": uniPortName, "intId": intfId})
-
-	// Make sure the uniPortName is as per format pon-{[0-9]+}/onu-{[0-9]+}/uni-{[0-9]+}
-	if !uniPortNameFormat.Match([]byte(uniPortName)) {
-		log.Errorw("uni-port-name-not-confirming-to-format", log.Fields{"uniPortName": uniPortName})
-		return nil, errors.New("uni-port-name-not-confirming-to-format")
-	}
-
-	tp := t.getTPFromKVStore(ctx, techProfiletblID)
-	if tp != nil {
-		if err := t.validateInstanceControlAttr(tp.InstanceCtrl); err != nil {
-			log.Error("invalid-instance-ctrl-attr--using-default-tp")
-			tp = t.getDefaultTechProfile()
-		} else {
-			log.Infow("using-specified-tp-from-kv-store", log.Fields{"tpid": techProfiletblID})
-		}
-	} else {
-		log.Info("tp-not-found-on-kv--creating-default-tp")
-		tp = t.getDefaultTechProfile()
-	}
-	tpInstancePath := t.GetTechProfileInstanceKVPath(techProfiletblID, uniPortName)
-	if tpInstance = t.allocateTPInstance(ctx, uniPortName, tp, intfId, tpInstancePath); tpInstance == nil {
-		log.Error("tp-intance-allocation-failed")
-		return nil, errors.New("tp-intance-allocation-failed")
-	}
-	if err := t.addTechProfInstanceToKVStore(ctx, techProfiletblID, uniPortName, tpInstance); err != nil {
-		log.Errorw("error-adding-tp-to-kv-store", log.Fields{"tableid": techProfiletblID, "uni": uniPortName})
-		return nil, errors.New("error-adding-tp-to-kv-store")
-	}
-	log.Infow("tp-added-to-kv-store-successfully",
-		log.Fields{"tpid": techProfiletblID, "uni": uniPortName, "intfId": intfId})
-	return tpInstance, nil
-}
-
-func (t *TechProfileMgr) DeleteTechProfileInstance(ctx context.Context, techProfiletblID uint32, uniPortName string) error {
-	path := t.GetTechProfileInstanceKVPath(techProfiletblID, uniPortName)
-	return t.config.KVBackend.Delete(ctx, path)
-}
-
-func (t *TechProfileMgr) validateInstanceControlAttr(instCtl InstanceControl) error {
-	if instCtl.Onu != "single-instance" && instCtl.Onu != "multi-instance" {
-		log.Errorw("invalid-onu-instance-control-attribute", log.Fields{"onu-inst": instCtl.Onu})
-		return errors.New("invalid-onu-instance-ctl-attr")
-	}
-
-	if instCtl.Uni != "single-instance" && instCtl.Uni != "multi-instance" {
-		log.Errorw("invalid-uni-instance-control-attribute", log.Fields{"uni-inst": instCtl.Uni})
-		return errors.New("invalid-uni-instance-ctl-attr")
-	}
-
-	if instCtl.Uni == "multi-instance" {
-		log.Error("uni-multi-instance-tp-not-supported")
-		return errors.New("uni-multi-instance-tp-not-supported")
-	}
-
-	return nil
-}
-
-func (t *TechProfileMgr) allocateTPInstance(ctx context.Context, uniPortName string, tp *DefaultTechProfile, intfId uint32, tpInstPath string) *TechProfile {
-
-	var usGemPortAttributeList []iGemPortAttribute
-	var dsGemPortAttributeList []iGemPortAttribute
-	var dsMulticastGemAttributeList []iGemPortAttribute
-	var dsUnicastGemAttributeList []iGemPortAttribute
-	var tcontIDs []uint32
-	var gemPorts []uint32
-	var err error
-
-	log.Infow("Allocating TechProfileMgr instance from techprofile template", log.Fields{"uniPortName": uniPortName, "intfId": intfId, "numGem": tp.NumGemPorts})
-
-	if tp.InstanceCtrl.Onu == "multi-instance" {
-		if tcontIDs, err = t.resourceMgr.GetResourceID(ctx, intfId, t.resourceMgr.GetResourceTypeAllocID(), 1); err != nil {
-			log.Errorw("Error getting alloc id from rsrcrMgr", log.Fields{"intfId": intfId})
-			return nil
-		}
-	} else { // "single-instance"
-		if tpInst, err := t.getSingleInstanceTp(ctx, tpInstPath); err != nil {
-			log.Errorw("Error getting alloc id from rsrcrMgr", log.Fields{"intfId": intfId})
-			return nil
-		} else if tpInst == nil {
-			// No "single-instance" tp found on one any uni port for the given TP ID
-			// Allocate a new TcontID or AllocID
-			if tcontIDs, err = t.resourceMgr.GetResourceID(ctx, intfId, t.resourceMgr.GetResourceTypeAllocID(), 1); err != nil {
-				log.Errorw("Error getting alloc id from rsrcrMgr", log.Fields{"intfId": intfId})
-				return nil
-			}
-		} else {
-			// Use the alloc-id from the existing TpInstance
-			tcontIDs = append(tcontIDs, tpInst.UsScheduler.AllocID)
-		}
-	}
-	log.Debugw("Num GEM ports in TP:", log.Fields{"NumGemPorts": tp.NumGemPorts})
-	if gemPorts, err = t.resourceMgr.GetResourceID(ctx, intfId, t.resourceMgr.GetResourceTypeGemPortID(), tp.NumGemPorts); err != nil {
-		log.Errorw("Error getting gemport ids from rsrcrMgr", log.Fields{"intfId": intfId, "numGemports": tp.NumGemPorts})
-		return nil
-	}
-	log.Infow("Allocated tconts and GEM ports successfully", log.Fields{"tconts": tcontIDs, "gemports": gemPorts})
-	for index := 0; index < int(tp.NumGemPorts); index++ {
-		usGemPortAttributeList = append(usGemPortAttributeList,
-			iGemPortAttribute{GemportID: gemPorts[index],
-				MaxQueueSize:     tp.UpstreamGemPortAttributeList[index].MaxQueueSize,
-				PbitMap:          tp.UpstreamGemPortAttributeList[index].PbitMap,
-				AesEncryption:    tp.UpstreamGemPortAttributeList[index].AesEncryption,
-				SchedulingPolicy: tp.UpstreamGemPortAttributeList[index].SchedulingPolicy,
-				PriorityQueue:    tp.UpstreamGemPortAttributeList[index].PriorityQueue,
-				Weight:           tp.UpstreamGemPortAttributeList[index].Weight,
-				DiscardPolicy:    tp.UpstreamGemPortAttributeList[index].DiscardPolicy,
-				DiscardConfig:    tp.UpstreamGemPortAttributeList[index].DiscardConfig})
-	}
-
-	log.Info("length of DownstreamGemPortAttributeList", len(tp.DownstreamGemPortAttributeList))
-	//put multicast and unicast downstream GEM port attributes in different lists first
-	for index := 0; index < int(len(tp.DownstreamGemPortAttributeList)); index++ {
-		if isMulticastGem(tp.DownstreamGemPortAttributeList[index].IsMulticast) {
-			dsMulticastGemAttributeList = append(dsMulticastGemAttributeList,
-				iGemPortAttribute{
-					McastGemID:       tp.DownstreamGemPortAttributeList[index].McastGemID,
-					MaxQueueSize:     tp.DownstreamGemPortAttributeList[index].MaxQueueSize,
-					PbitMap:          tp.DownstreamGemPortAttributeList[index].PbitMap,
-					AesEncryption:    tp.DownstreamGemPortAttributeList[index].AesEncryption,
-					SchedulingPolicy: tp.DownstreamGemPortAttributeList[index].SchedulingPolicy,
-					PriorityQueue:    tp.DownstreamGemPortAttributeList[index].PriorityQueue,
-					Weight:           tp.DownstreamGemPortAttributeList[index].Weight,
-					DiscardPolicy:    tp.DownstreamGemPortAttributeList[index].DiscardPolicy,
-					DiscardConfig:    tp.DownstreamGemPortAttributeList[index].DiscardConfig,
-					IsMulticast:      tp.DownstreamGemPortAttributeList[index].IsMulticast,
-					DControlList:     tp.DownstreamGemPortAttributeList[index].DControlList,
-					SControlList:     tp.DownstreamGemPortAttributeList[index].SControlList})
-		} else {
-			dsUnicastGemAttributeList = append(dsUnicastGemAttributeList,
-				iGemPortAttribute{
-					MaxQueueSize:     tp.DownstreamGemPortAttributeList[index].MaxQueueSize,
-					PbitMap:          tp.DownstreamGemPortAttributeList[index].PbitMap,
-					AesEncryption:    tp.DownstreamGemPortAttributeList[index].AesEncryption,
-					SchedulingPolicy: tp.DownstreamGemPortAttributeList[index].SchedulingPolicy,
-					PriorityQueue:    tp.DownstreamGemPortAttributeList[index].PriorityQueue,
-					Weight:           tp.DownstreamGemPortAttributeList[index].Weight,
-					DiscardPolicy:    tp.DownstreamGemPortAttributeList[index].DiscardPolicy,
-					DiscardConfig:    tp.DownstreamGemPortAttributeList[index].DiscardConfig})
-		}
-	}
-	//add unicast downstream GEM ports to dsGemPortAttributeList
-	for index := 0; index < int(tp.NumGemPorts); index++ {
-		dsGemPortAttributeList = append(dsGemPortAttributeList,
-			iGemPortAttribute{GemportID: gemPorts[index],
-				MaxQueueSize:     dsUnicastGemAttributeList[index].MaxQueueSize,
-				PbitMap:          dsUnicastGemAttributeList[index].PbitMap,
-				AesEncryption:    dsUnicastGemAttributeList[index].AesEncryption,
-				SchedulingPolicy: dsUnicastGemAttributeList[index].SchedulingPolicy,
-				PriorityQueue:    dsUnicastGemAttributeList[index].PriorityQueue,
-				Weight:           dsUnicastGemAttributeList[index].Weight,
-				DiscardPolicy:    dsUnicastGemAttributeList[index].DiscardPolicy,
-				DiscardConfig:    dsUnicastGemAttributeList[index].DiscardConfig})
-	}
-	//add multicast GEM ports to dsGemPortAttributeList afterwards
-	for k := range dsMulticastGemAttributeList {
-		dsGemPortAttributeList = append(dsGemPortAttributeList, dsMulticastGemAttributeList[k])
-	}
-
-	return &TechProfile{
-		SubscriberIdentifier: uniPortName,
-		Name:                 tp.Name,
-		ProfileType:          tp.ProfileType,
-		Version:              tp.Version,
-		NumGemPorts:          tp.NumGemPorts,
-		InstanceCtrl:         tp.InstanceCtrl,
-		UsScheduler: iScheduler{
-			AllocID:      tcontIDs[0],
-			Direction:    tp.UsScheduler.Direction,
-			AdditionalBw: tp.UsScheduler.AdditionalBw,
-			Priority:     tp.UsScheduler.Priority,
-			Weight:       tp.UsScheduler.Weight,
-			QSchedPolicy: tp.UsScheduler.QSchedPolicy},
-		DsScheduler: iScheduler{
-			AllocID:      tcontIDs[0],
-			Direction:    tp.DsScheduler.Direction,
-			AdditionalBw: tp.DsScheduler.AdditionalBw,
-			Priority:     tp.DsScheduler.Priority,
-			Weight:       tp.DsScheduler.Weight,
-			QSchedPolicy: tp.DsScheduler.QSchedPolicy},
-		UpstreamGemPortAttributeList:   usGemPortAttributeList,
-		DownstreamGemPortAttributeList: dsGemPortAttributeList}
-}
-
-// getSingleInstanceTp returns another TpInstance for an ONU on a different
-// uni port for the same TP ID, if it finds one, else nil.
-func (t *TechProfileMgr) getSingleInstanceTp(ctx context.Context, tpPath string) (*TechProfile, error) {
-	var tpInst TechProfile
-
-	// For example:
-	// tpPath like "service/voltha/technology_profiles/xgspon/64/pon-{0}/onu-{1}/uni-{1}"
-	// is broken into ["service/voltha/technology_profiles/xgspon/64/pon-{0}/onu-{1}" ""]
-	uniPathSlice := regexp.MustCompile(`/uni-{[0-9]+}$`).Split(tpPath, 2)
-	kvPairs, _ := t.config.KVBackend.List(ctx, uniPathSlice[0])
-
-	// Find a valid TP Instance among all the UNIs of that ONU for the given TP ID
-	for keyPath, kvPair := range kvPairs {
-		if value, err := kvstore.ToByte(kvPair.Value); err == nil {
-			if err = json.Unmarshal(value, &tpInst); err != nil {
-				log.Errorw("error-unmarshal-kv-pair", log.Fields{"keyPath": keyPath, "value": value})
-				return nil, errors.New("error-unmarshal-kv-pair")
-			} else {
-				log.Debugw("found-valid-tp-instance-on-another-uni", log.Fields{"keyPath": keyPath})
-				return &tpInst, nil
-			}
-		}
-	}
-	return nil, nil
-}
-
-func (t *TechProfileMgr) getDefaultTechProfile() *DefaultTechProfile {
-
-	var usGemPortAttributeList []GemPortAttribute
-	var dsGemPortAttributeList []GemPortAttribute
-
-	for _, pbit := range t.config.DefaultPbits {
-		log.Debugw("Creating GEM port", log.Fields{"pbit": pbit})
-		usGemPortAttributeList = append(usGemPortAttributeList,
-			GemPortAttribute{
-				MaxQueueSize:     defaultMaxQueueSize,
-				PbitMap:          pbit,
-				AesEncryption:    defaultAESEncryption,
-				SchedulingPolicy: SchedulingPolicy_name[defaultSchedulePolicy],
-				PriorityQueue:    defaultPriorityQueue,
-				Weight:           defaultQueueWeight,
-				DiscardPolicy:    DiscardPolicy_name[defaultdropPolicy],
-				DiscardConfig: DiscardConfig{
-					MinThreshold:   defaultMinThreshold,
-					MaxThreshold:   defaultMaxThreshold,
-					MaxProbability: defaultMaxProbability}})
-		dsGemPortAttributeList = append(dsGemPortAttributeList,
-			GemPortAttribute{
-				MaxQueueSize:     defaultMaxQueueSize,
-				PbitMap:          pbit,
-				AesEncryption:    defaultAESEncryption,
-				SchedulingPolicy: SchedulingPolicy_name[defaultSchedulePolicy],
-				PriorityQueue:    defaultPriorityQueue,
-				Weight:           defaultQueueWeight,
-				DiscardPolicy:    DiscardPolicy_name[defaultdropPolicy],
-				DiscardConfig: DiscardConfig{
-					MinThreshold:   defaultMinThreshold,
-					MaxThreshold:   defaultMaxThreshold,
-					MaxProbability: defaultMaxProbability},
-				IsMulticast:  defaultIsMulticast,
-				DControlList: defaultAccessControlList,
-				SControlList: defaultAccessControlList,
-				McastGemID:   defaultMcastGemID})
-	}
-	return &DefaultTechProfile{
-		Name:        t.config.DefaultTPName,
-		ProfileType: t.resourceMgr.GetTechnology(),
-		Version:     t.config.TPVersion,
-		NumGemPorts: uint32(len(usGemPortAttributeList)),
-		InstanceCtrl: InstanceControl{
-			Onu:               defaultOnuInstance,
-			Uni:               defaultUniInstance,
-			MaxGemPayloadSize: defaultGemPayloadSize},
-		UsScheduler: Scheduler{
-			Direction:    Direction_name[Direction_UPSTREAM],
-			AdditionalBw: AdditionalBW_name[defaultAdditionalBw],
-			Priority:     defaultPriority,
-			Weight:       defaultWeight,
-			QSchedPolicy: SchedulingPolicy_name[defaultQueueSchedPolicy]},
-		DsScheduler: Scheduler{
-			Direction:    Direction_name[Direction_DOWNSTREAM],
-			AdditionalBw: AdditionalBW_name[defaultAdditionalBw],
-			Priority:     defaultPriority,
-			Weight:       defaultWeight,
-			QSchedPolicy: SchedulingPolicy_name[defaultQueueSchedPolicy]},
-		UpstreamGemPortAttributeList:   usGemPortAttributeList,
-		DownstreamGemPortAttributeList: dsGemPortAttributeList}
-}
-
-func (t *TechProfileMgr) GetprotoBufParamValue(paramType string, paramKey string) int32 {
-	var result int32 = -1
-
-	if paramType == "direction" {
-		for key, val := range tp_pb.Direction_value {
-			if key == paramKey {
-				result = val
-			}
-		}
-	} else if paramType == "discard_policy" {
-		for key, val := range tp_pb.DiscardPolicy_value {
-			if key == paramKey {
-				result = val
-			}
-		}
-	} else if paramType == "sched_policy" {
-		for key, val := range tp_pb.SchedulingPolicy_value {
-			if key == paramKey {
-				log.Debugw("Got value in proto", log.Fields{"key": key, "value": val})
-				result = val
-			}
-		}
-	} else if paramType == "additional_bw" {
-		for key, val := range tp_pb.AdditionalBW_value {
-			if key == paramKey {
-				result = val
-			}
-		}
-	} else {
-		log.Error("Could not find proto parameter", log.Fields{"paramType": paramType, "key": paramKey})
-		return -1
-	}
-	log.Debugw("Got value in proto", log.Fields{"key": paramKey, "value": result})
-	return result
-}
-
-func (t *TechProfileMgr) GetUsScheduler(tpInstance *TechProfile) (*tp_pb.SchedulerConfig, error) {
-	dir := tp_pb.Direction(t.GetprotoBufParamValue("direction", tpInstance.UsScheduler.Direction))
-	if dir == -1 {
-		log.Errorf("Error in getting proto id for direction %s for upstream scheduler", tpInstance.UsScheduler.Direction)
-		return nil, fmt.Errorf("unable to get proto id for direction %s for upstream scheduler", tpInstance.UsScheduler.Direction)
-	}
-
-	bw := tp_pb.AdditionalBW(t.GetprotoBufParamValue("additional_bw", tpInstance.UsScheduler.AdditionalBw))
-	if bw == -1 {
-		log.Errorf("Error in getting proto id for bandwidth %s for upstream scheduler", tpInstance.UsScheduler.AdditionalBw)
-		return nil, fmt.Errorf("unable to get proto id for bandwidth %s for upstream scheduler", tpInstance.UsScheduler.AdditionalBw)
-	}
-
-	policy := tp_pb.SchedulingPolicy(t.GetprotoBufParamValue("sched_policy", tpInstance.UsScheduler.QSchedPolicy))
-	if policy == -1 {
-		log.Errorf("Error in getting proto id for scheduling policy %s for upstream scheduler", tpInstance.UsScheduler.QSchedPolicy)
-		return nil, fmt.Errorf("unable to get proto id for scheduling policy %s for upstream scheduler", tpInstance.UsScheduler.QSchedPolicy)
-	}
-
-	return &tp_pb.SchedulerConfig{
-		Direction:    dir,
-		AdditionalBw: bw,
-		Priority:     tpInstance.UsScheduler.Priority,
-		Weight:       tpInstance.UsScheduler.Weight,
-		SchedPolicy:  policy}, nil
-}
-
-func (t *TechProfileMgr) GetDsScheduler(tpInstance *TechProfile) (*tp_pb.SchedulerConfig, error) {
-
-	dir := tp_pb.Direction(t.GetprotoBufParamValue("direction", tpInstance.DsScheduler.Direction))
-	if dir == -1 {
-		log.Errorf("Error in getting proto id for direction %s for downstream scheduler", tpInstance.DsScheduler.Direction)
-		return nil, fmt.Errorf("unable to get proto id for direction %s for downstream scheduler", tpInstance.DsScheduler.Direction)
-	}
-
-	bw := tp_pb.AdditionalBW(t.GetprotoBufParamValue("additional_bw", tpInstance.DsScheduler.AdditionalBw))
-	if bw == -1 {
-		log.Errorf("Error in getting proto id for bandwidth %s for downstream scheduler", tpInstance.DsScheduler.AdditionalBw)
-		return nil, fmt.Errorf("unable to get proto id for bandwidth %s for downstream scheduler", tpInstance.DsScheduler.AdditionalBw)
-	}
-
-	policy := tp_pb.SchedulingPolicy(t.GetprotoBufParamValue("sched_policy", tpInstance.DsScheduler.QSchedPolicy))
-	if policy == -1 {
-		log.Errorf("Error in getting proto id for scheduling policy %s for downstream scheduler", tpInstance.DsScheduler.QSchedPolicy)
-		return nil, fmt.Errorf("unable to get proto id for scheduling policy %s for downstream scheduler", tpInstance.DsScheduler.QSchedPolicy)
-	}
-
-	return &tp_pb.SchedulerConfig{
-		Direction:    dir,
-		AdditionalBw: bw,
-		Priority:     tpInstance.DsScheduler.Priority,
-		Weight:       tpInstance.DsScheduler.Weight,
-		SchedPolicy:  policy}, nil
-}
-
-func (t *TechProfileMgr) GetTrafficScheduler(tpInstance *TechProfile, SchedCfg *tp_pb.SchedulerConfig,
-	ShapingCfg *tp_pb.TrafficShapingInfo) *tp_pb.TrafficScheduler {
-
-	tSched := &tp_pb.TrafficScheduler{
-		Direction:          SchedCfg.Direction,
-		AllocId:            tpInstance.UsScheduler.AllocID,
-		TrafficShapingInfo: ShapingCfg,
-		Scheduler:          SchedCfg}
-
-	return tSched
-}
-
-func (tpm *TechProfileMgr) GetTrafficQueues(tp *TechProfile, Dir tp_pb.Direction) ([]*tp_pb.TrafficQueue, error) {
-
-	var encryp bool
-	if Dir == tp_pb.Direction_UPSTREAM {
-		// upstream GEM ports
-		NumGemPorts := len(tp.UpstreamGemPortAttributeList)
-		GemPorts := make([]*tp_pb.TrafficQueue, 0)
-		for Count := 0; Count < NumGemPorts; Count++ {
-			if tp.UpstreamGemPortAttributeList[Count].AesEncryption == "True" {
-				encryp = true
-			} else {
-				encryp = false
-			}
-
-			schedPolicy := tpm.GetprotoBufParamValue("sched_policy", tp.UpstreamGemPortAttributeList[Count].SchedulingPolicy)
-			if schedPolicy == -1 {
-				log.Errorf("Error in getting Proto Id for scheduling policy %s for Upstream Gem Port %d", tp.UpstreamGemPortAttributeList[Count].SchedulingPolicy, Count)
-				return nil, fmt.Errorf("upstream gem port traffic queue creation failed due to unrecognized scheduling policy %s", tp.UpstreamGemPortAttributeList[Count].SchedulingPolicy)
-			}
-
-			discardPolicy := tpm.GetprotoBufParamValue("discard_policy", tp.UpstreamGemPortAttributeList[Count].DiscardPolicy)
-			if discardPolicy == -1 {
-				log.Errorf("Error in getting Proto Id for discard policy %s for Upstream Gem Port %d", tp.UpstreamGemPortAttributeList[Count].DiscardPolicy, Count)
-				return nil, fmt.Errorf("upstream gem port traffic queue creation failed due to unrecognized discard policy %s", tp.UpstreamGemPortAttributeList[Count].DiscardPolicy)
-			}
-
-			GemPorts = append(GemPorts, &tp_pb.TrafficQueue{
-				Direction:     tp_pb.Direction(tpm.GetprotoBufParamValue("direction", tp.UsScheduler.Direction)),
-				GemportId:     tp.UpstreamGemPortAttributeList[Count].GemportID,
-				PbitMap:       tp.UpstreamGemPortAttributeList[Count].PbitMap,
-				AesEncryption: encryp,
-				SchedPolicy:   tp_pb.SchedulingPolicy(schedPolicy),
-				Priority:      tp.UpstreamGemPortAttributeList[Count].PriorityQueue,
-				Weight:        tp.UpstreamGemPortAttributeList[Count].Weight,
-				DiscardPolicy: tp_pb.DiscardPolicy(discardPolicy),
-			})
-		}
-		log.Debugw("Upstream Traffic queue list ", log.Fields{"queuelist": GemPorts})
-		return GemPorts, nil
-	} else if Dir == tp_pb.Direction_DOWNSTREAM {
-		//downstream GEM ports
-		NumGemPorts := len(tp.DownstreamGemPortAttributeList)
-		GemPorts := make([]*tp_pb.TrafficQueue, 0)
-		for Count := 0; Count < NumGemPorts; Count++ {
-			if isMulticastGem(tp.DownstreamGemPortAttributeList[Count].IsMulticast) {
-				//do not take multicast GEM ports. They are handled separately.
-				continue
-			}
-			if tp.DownstreamGemPortAttributeList[Count].AesEncryption == "True" {
-				encryp = true
-			} else {
-				encryp = false
-			}
-
-			schedPolicy := tpm.GetprotoBufParamValue("sched_policy", tp.DownstreamGemPortAttributeList[Count].SchedulingPolicy)
-			if schedPolicy == -1 {
-				log.Errorf("Error in getting Proto Id for scheduling policy %s for Downstream Gem Port %d", tp.DownstreamGemPortAttributeList[Count].SchedulingPolicy, Count)
-				return nil, fmt.Errorf("downstream gem port traffic queue creation failed due to unrecognized scheduling policy %s", tp.DownstreamGemPortAttributeList[Count].SchedulingPolicy)
-			}
-
-			discardPolicy := tpm.GetprotoBufParamValue("discard_policy", tp.DownstreamGemPortAttributeList[Count].DiscardPolicy)
-			if discardPolicy == -1 {
-				log.Errorf("Error in getting Proto Id for discard policy %s for Downstream Gem Port %d", tp.DownstreamGemPortAttributeList[Count].DiscardPolicy, Count)
-				return nil, fmt.Errorf("downstream gem port traffic queue creation failed due to unrecognized discard policy %s", tp.DownstreamGemPortAttributeList[Count].DiscardPolicy)
-			}
-
-			GemPorts = append(GemPorts, &tp_pb.TrafficQueue{
-				Direction:     tp_pb.Direction(tpm.GetprotoBufParamValue("direction", tp.DsScheduler.Direction)),
-				GemportId:     tp.DownstreamGemPortAttributeList[Count].GemportID,
-				PbitMap:       tp.DownstreamGemPortAttributeList[Count].PbitMap,
-				AesEncryption: encryp,
-				SchedPolicy:   tp_pb.SchedulingPolicy(schedPolicy),
-				Priority:      tp.DownstreamGemPortAttributeList[Count].PriorityQueue,
-				Weight:        tp.DownstreamGemPortAttributeList[Count].Weight,
-				DiscardPolicy: tp_pb.DiscardPolicy(discardPolicy),
-			})
-		}
-		log.Debugw("Downstream Traffic queue list ", log.Fields{"queuelist": GemPorts})
-		return GemPorts, nil
-	}
-
-	log.Errorf("Unsupported direction %s used for generating Traffic Queue list", Dir)
-	return nil, fmt.Errorf("downstream gem port traffic queue creation failed due to unsupported direction %s", Dir)
-}
-
-//isMulticastGem returns true if isMulticast attribute value of a GEM port is true; false otherwise
-func isMulticastGem(isMulticastAttrValue string) bool {
-	return isMulticastAttrValue != "" &&
-		(isMulticastAttrValue == "True" || isMulticastAttrValue == "true" || isMulticastAttrValue == "TRUE")
-}
-
-func (tpm *TechProfileMgr) GetMulticastTrafficQueues(tp *TechProfile) []*tp_pb.TrafficQueue {
-	var encryp bool
-	NumGemPorts := len(tp.DownstreamGemPortAttributeList)
-	mcastTrafficQueues := make([]*tp_pb.TrafficQueue, 0)
-	for Count := 0; Count < NumGemPorts; Count++ {
-		if !isMulticastGem(tp.DownstreamGemPortAttributeList[Count].IsMulticast) {
-			continue
-		}
-		if tp.DownstreamGemPortAttributeList[Count].AesEncryption == "True" {
-			encryp = true
-		} else {
-			encryp = false
-		}
-		mcastTrafficQueues = append(mcastTrafficQueues, &tp_pb.TrafficQueue{
-			Direction:     tp_pb.Direction(tpm.GetprotoBufParamValue("direction", tp.DsScheduler.Direction)),
-			GemportId:     tp.DownstreamGemPortAttributeList[Count].McastGemID,
-			PbitMap:       tp.DownstreamGemPortAttributeList[Count].PbitMap,
-			AesEncryption: encryp,
-			SchedPolicy:   tp_pb.SchedulingPolicy(tpm.GetprotoBufParamValue("sched_policy", tp.DownstreamGemPortAttributeList[Count].SchedulingPolicy)),
-			Priority:      tp.DownstreamGemPortAttributeList[Count].PriorityQueue,
-			Weight:        tp.DownstreamGemPortAttributeList[Count].Weight,
-			DiscardPolicy: tp_pb.DiscardPolicy(tpm.GetprotoBufParamValue("discard_policy", tp.DownstreamGemPortAttributeList[Count].DiscardPolicy)),
-		})
-	}
-	log.Debugw("Downstream Multicast Traffic queue list ", log.Fields{"queuelist": mcastTrafficQueues})
-	return mcastTrafficQueues
-}
-
-func (tpm *TechProfileMgr) GetUsTrafficScheduler(tp *TechProfile) *tp_pb.TrafficScheduler {
-	UsScheduler, _ := tpm.GetUsScheduler(tp)
-
-	return &tp_pb.TrafficScheduler{Direction: UsScheduler.Direction,
-		AllocId:   tp.UsScheduler.AllocID,
-		Scheduler: UsScheduler}
-}
-
-func (t *TechProfileMgr) GetGemportIDForPbit(tp *TechProfile, Dir tp_pb.Direction, pbit uint32) uint32 {
-	/*
-	   Function to get the Gemport ID mapped to a pbit.
-	*/
-	if Dir == tp_pb.Direction_UPSTREAM {
-		// upstream GEM ports
-		NumGemPorts := len(tp.UpstreamGemPortAttributeList)
-		for Count := 0; Count < NumGemPorts; Count++ {
-			NumPbitMaps := len(tp.UpstreamGemPortAttributeList[Count].PbitMap)
-			for ICount := 2; ICount < NumPbitMaps; ICount++ {
-				if p, err := strconv.Atoi(string(tp.UpstreamGemPortAttributeList[Count].PbitMap[ICount])); err == nil {
-					if uint32(ICount-2) == pbit && p == 1 { // Check this p-bit is set
-						log.Debugw("Found-US-GEMport-for-Pcp", log.Fields{"pbit": pbit, "GEMport": tp.UpstreamGemPortAttributeList[Count].GemportID})
-						return tp.UpstreamGemPortAttributeList[Count].GemportID
-					}
-				}
-			}
-		}
-	} else if Dir == tp_pb.Direction_DOWNSTREAM {
-		//downstream GEM ports
-		NumGemPorts := len(tp.DownstreamGemPortAttributeList)
-		for Count := 0; Count < NumGemPorts; Count++ {
-			NumPbitMaps := len(tp.DownstreamGemPortAttributeList[Count].PbitMap)
-			for ICount := 2; ICount < NumPbitMaps; ICount++ {
-				if p, err := strconv.Atoi(string(tp.DownstreamGemPortAttributeList[Count].PbitMap[ICount])); err == nil {
-					if uint32(ICount-2) == pbit && p == 1 { // Check this p-bit is set
-						log.Debugw("Found-DS-GEMport-for-Pcp", log.Fields{"pbit": pbit, "GEMport": tp.DownstreamGemPortAttributeList[Count].GemportID})
-						return tp.DownstreamGemPortAttributeList[Count].GemportID
-					}
-				}
-			}
-		}
-	}
-	log.Errorw("No-GemportId-Found-For-Pcp", log.Fields{"pcpVlan": pbit})
-	return 0
-}
-
-// FindAllTpInstances returns all TechProfile instances for a given TechProfile table-id, pon interface ID and onu ID.
-func (t *TechProfileMgr) FindAllTpInstances(ctx context.Context, techProfiletblID uint32, ponIntf uint32, onuID uint32) []TechProfile {
-	var tp TechProfile
-	onuTpInstancePath := fmt.Sprintf("%s/%d/pon-{%d}/onu-{%d}", t.resourceMgr.GetTechnology(), techProfiletblID, ponIntf, onuID)
-
-	if kvPairs, _ := t.config.KVBackend.List(ctx, onuTpInstancePath); kvPairs != nil {
-		tpInstances := make([]TechProfile, 0, len(kvPairs))
-		for kvPath, kvPair := range kvPairs {
-			if value, err := kvstore.ToByte(kvPair.Value); err == nil {
-				if err = json.Unmarshal(value, &tp); err != nil {
-					log.Errorw("error-unmarshal-kv-pair", log.Fields{"kvPath": kvPath, "value": value})
-					continue
-				} else {
-					tpInstances = append(tpInstances, tp)
-				}
-			}
-		}
-		return tpInstances
-	}
-	return nil
-}
diff --git a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/techprofile/tech_profile_if.go b/vendor/github.com/opencord/voltha-lib-go/v3/pkg/techprofile/tech_profile_if.go
deleted file mode 100644
index e605d49..0000000
--- a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/techprofile/tech_profile_if.go
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2019-present Open Networking Foundation
-
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
-
- * http://www.apache.org/licenses/LICENSE-2.0
-
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package techprofile
-
-import (
-	"context"
-
-	"github.com/opencord/voltha-lib-go/v3/pkg/db"
-	tp_pb "github.com/opencord/voltha-protos/v3/go/tech_profile"
-)
-
-type TechProfileIf interface {
-	SetKVClient() *db.Backend
-	GetTechProfileInstanceKVPath(techProfiletblID uint32, uniPortName string) string
-	GetTPInstanceFromKVStore(ctx context.Context, techProfiletblID uint32, path string) (*TechProfile, error)
-	CreateTechProfInstance(ctx context.Context, techProfiletblID uint32, uniPortName string, intfId uint32) (*TechProfile, error)
-	DeleteTechProfileInstance(ctx context.Context, techProfiletblID uint32, uniPortName string) error
-	GetprotoBufParamValue(paramType string, paramKey string) int32
-	GetUsScheduler(tpInstance *TechProfile) (*tp_pb.SchedulerConfig, error)
-	GetDsScheduler(tpInstance *TechProfile) (*tp_pb.SchedulerConfig, error)
-	GetTrafficScheduler(tpInstance *TechProfile, SchedCfg *tp_pb.SchedulerConfig,
-		ShapingCfg *tp_pb.TrafficShapingInfo) *tp_pb.TrafficScheduler
-	GetTrafficQueues(tp *TechProfile, Dir tp_pb.Direction) ([]*tp_pb.TrafficQueue, error)
-	GetMulticastTrafficQueues(tp *TechProfile) []*tp_pb.TrafficQueue
-	GetGemportIDForPbit(tp *TechProfile, Dir tp_pb.Direction, pbit uint32) uint32
-	FindAllTpInstances(ctx context.Context, techProfiletblID uint32, ponIntf uint32, onuID uint32) []TechProfile
-}
diff --git a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/backend.go b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/db/backend.go
similarity index 62%
rename from vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/backend.go
rename to vendor/github.com/opencord/voltha-lib-go/v4/pkg/db/backend.go
index faa86ed..d6867a5 100644
--- a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/backend.go
+++ b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/db/backend.go
@@ -20,12 +20,11 @@
 	"context"
 	"errors"
 	"fmt"
-	"strconv"
 	"sync"
 	"time"
 
-	"github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore"
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
+	"github.com/opencord/voltha-lib-go/v4/pkg/db/kvstore"
+	"github.com/opencord/voltha-lib-go/v4/pkg/log"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 )
@@ -37,38 +36,35 @@
 
 // Backend structure holds details for accessing the kv store
 type Backend struct {
-	sync.RWMutex
 	Client                  kvstore.Client
 	StoreType               string
-	Host                    string
-	Port                    int
-	Timeout                 int
+	Timeout                 time.Duration
+	Address                 string
 	PathPrefix              string
-	alive                   bool          // Is this backend connection alive?
+	alive                   bool // Is this backend connection alive?
+	livenessMutex           sync.Mutex
 	liveness                chan bool     // channel to post alive state
 	LivenessChannelInterval time.Duration // regularly push alive state beyond this interval
 	lastLivenessTime        time.Time     // Instant of last alive state push
 }
 
 // NewBackend creates a new instance of a Backend structure
-func NewBackend(storeType string, host string, port int, timeout int, pathPrefix string) *Backend {
+func NewBackend(ctx context.Context, storeType string, address string, timeout time.Duration, pathPrefix string) *Backend {
 	var err error
 
 	b := &Backend{
 		StoreType:               storeType,
-		Host:                    host,
-		Port:                    port,
+		Address:                 address,
 		Timeout:                 timeout,
 		LivenessChannelInterval: DefaultLivenessChannelInterval,
 		PathPrefix:              pathPrefix,
 		alive:                   false, // connection considered down at start
 	}
 
-	address := host + ":" + strconv.Itoa(port)
-	if b.Client, err = b.newClient(address, timeout); err != nil {
-		logger.Errorw("failed-to-create-kv-client",
+	if b.Client, err = b.newClient(ctx, address, timeout); err != nil {
+		logger.Errorw(ctx, "failed-to-create-kv-client",
 			log.Fields{
-				"type": storeType, "host": host, "port": port,
+				"type": storeType, "address": address,
 				"timeout": timeout, "prefix": pathPrefix,
 				"error": err.Error(),
 			})
@@ -77,34 +73,35 @@
 	return b
 }
 
-func (b *Backend) newClient(address string, timeout int) (kvstore.Client, error) {
+func (b *Backend) newClient(ctx context.Context, address string, timeout time.Duration) (kvstore.Client, error) {
 	switch b.StoreType {
 	case "consul":
-		return kvstore.NewConsulClient(address, timeout)
+		return kvstore.NewConsulClient(ctx, address, timeout)
 	case "etcd":
-		return kvstore.NewEtcdClient(address, timeout)
+		return kvstore.NewEtcdClient(ctx, address, timeout, log.WarnLevel)
 	}
 	return nil, errors.New("unsupported-kv-store")
 }
 
-func (b *Backend) makePath(key string) string {
+func (b *Backend) makePath(ctx context.Context, key string) string {
 	path := fmt.Sprintf("%s/%s", b.PathPrefix, key)
 	return path
 }
 
-func (b *Backend) updateLiveness(alive bool) {
+func (b *Backend) updateLiveness(ctx context.Context, alive bool) {
 	// Periodically push stream of liveness data to the channel,
 	// so that in a live state, the core does not timeout and
 	// send a forced liveness message. Push alive state if the
 	// last push to channel was beyond livenessChannelInterval
+	b.livenessMutex.Lock()
+	defer b.livenessMutex.Unlock()
 	if b.liveness != nil {
-
 		if b.alive != alive {
-			logger.Debug("update-liveness-channel-reason-change")
+			logger.Debug(ctx, "update-liveness-channel-reason-change")
 			b.liveness <- alive
 			b.lastLivenessTime = time.Now()
 		} else if time.Since(b.lastLivenessTime) > b.LivenessChannelInterval {
-			logger.Debug("update-liveness-channel-reason-interval")
+			logger.Debug(ctx, "update-liveness-channel-reason-interval")
 			b.liveness <- alive
 			b.lastLivenessTime = time.Now()
 		}
@@ -112,7 +109,7 @@
 
 	// Emit log message only for alive state change
 	if b.alive != alive {
-		logger.Debugw("change-kvstore-alive-status", log.Fields{"alive": alive})
+		logger.Debugw(ctx, "change-kvstore-alive-status", log.Fields{"alive": alive})
 		b.alive = alive
 	}
 }
@@ -121,9 +118,9 @@
 // post on Liveness channel
 func (b *Backend) PerformLivenessCheck(ctx context.Context) bool {
 	alive := b.Client.IsConnectionUp(ctx)
-	logger.Debugw("kvstore-liveness-check-result", log.Fields{"alive": alive})
+	logger.Debugw(ctx, "kvstore-liveness-check-result", log.Fields{"alive": alive})
 
-	b.updateLiveness(alive)
+	b.updateLiveness(ctx, alive)
 	return alive
 }
 
@@ -132,16 +129,12 @@
 // or not the connection is still Live. This channel is then picked up
 // by the service (i.e. rw_core / ro_core) to update readiness status
 // and/or take other actions.
-func (b *Backend) EnableLivenessChannel() chan bool {
-	logger.Debug("enable-kvstore-liveness-channel")
-
+func (b *Backend) EnableLivenessChannel(ctx context.Context) chan bool {
+	logger.Debug(ctx, "enable-kvstore-liveness-channel")
+	b.livenessMutex.Lock()
+	defer b.livenessMutex.Unlock()
 	if b.liveness == nil {
-		logger.Debug("create-kvstore-liveness-channel")
-
-		// Channel size of 10 to avoid any possibility of blocking in Load conditions
 		b.liveness = make(chan bool, 10)
-
-		// Post initial alive state
 		b.liveness <- b.alive
 		b.lastLivenessTime = time.Now()
 	}
@@ -150,7 +143,7 @@
 }
 
 // Extract Alive status of Kvstore based on type of error
-func (b *Backend) isErrorIndicatingAliveKvstore(err error) bool {
+func (b *Backend) isErrorIndicatingAliveKvstore(ctx context.Context, err error) bool {
 	// Alive unless observed an error indicating so
 	alive := true
 
@@ -188,82 +181,82 @@
 
 // List retrieves one or more items that match the specified key
 func (b *Backend) List(ctx context.Context, key string) (map[string]*kvstore.KVPair, error) {
-	b.Lock()
-	defer b.Unlock()
+	span, ctx := log.CreateChildSpan(ctx, "etcd-list")
+	defer span.Finish()
 
-	formattedPath := b.makePath(key)
-	logger.Debugw("listing-key", log.Fields{"key": key, "path": formattedPath})
+	formattedPath := b.makePath(ctx, key)
+	logger.Debugw(ctx, "listing-key", log.Fields{"key": key, "path": formattedPath})
 
 	pair, err := b.Client.List(ctx, formattedPath)
 
-	b.updateLiveness(b.isErrorIndicatingAliveKvstore(err))
+	b.updateLiveness(ctx, b.isErrorIndicatingAliveKvstore(ctx, err))
 
 	return pair, err
 }
 
 // Get retrieves an item that matches the specified key
 func (b *Backend) Get(ctx context.Context, key string) (*kvstore.KVPair, error) {
-	b.Lock()
-	defer b.Unlock()
+	span, ctx := log.CreateChildSpan(ctx, "etcd-get")
+	defer span.Finish()
 
-	formattedPath := b.makePath(key)
-	logger.Debugw("getting-key", log.Fields{"key": key, "path": formattedPath})
+	formattedPath := b.makePath(ctx, key)
+	logger.Debugw(ctx, "getting-key", log.Fields{"key": key, "path": formattedPath})
 
 	pair, err := b.Client.Get(ctx, formattedPath)
 
-	b.updateLiveness(b.isErrorIndicatingAliveKvstore(err))
+	b.updateLiveness(ctx, b.isErrorIndicatingAliveKvstore(ctx, err))
 
 	return pair, err
 }
 
 // Put stores an item value under the specifed key
 func (b *Backend) Put(ctx context.Context, key string, value interface{}) error {
-	b.Lock()
-	defer b.Unlock()
+	span, ctx := log.CreateChildSpan(ctx, "etcd-put")
+	defer span.Finish()
 
-	formattedPath := b.makePath(key)
-	logger.Debugw("putting-key", log.Fields{"key": key, "value": value, "path": formattedPath})
+	formattedPath := b.makePath(ctx, key)
+	logger.Debugw(ctx, "putting-key", log.Fields{"key": key, "path": formattedPath})
 
 	err := b.Client.Put(ctx, formattedPath, value)
 
-	b.updateLiveness(b.isErrorIndicatingAliveKvstore(err))
+	b.updateLiveness(ctx, b.isErrorIndicatingAliveKvstore(ctx, err))
 
 	return err
 }
 
 // Delete removes an item under the specified key
 func (b *Backend) Delete(ctx context.Context, key string) error {
-	b.Lock()
-	defer b.Unlock()
+	span, ctx := log.CreateChildSpan(ctx, "etcd-delete")
+	defer span.Finish()
 
-	formattedPath := b.makePath(key)
-	logger.Debugw("deleting-key", log.Fields{"key": key, "path": formattedPath})
+	formattedPath := b.makePath(ctx, key)
+	logger.Debugw(ctx, "deleting-key", log.Fields{"key": key, "path": formattedPath})
 
 	err := b.Client.Delete(ctx, formattedPath)
 
-	b.updateLiveness(b.isErrorIndicatingAliveKvstore(err))
+	b.updateLiveness(ctx, b.isErrorIndicatingAliveKvstore(ctx, err))
 
 	return err
 }
 
 // CreateWatch starts watching events for the specified key
 func (b *Backend) CreateWatch(ctx context.Context, key string, withPrefix bool) chan *kvstore.Event {
-	b.Lock()
-	defer b.Unlock()
+	span, ctx := log.CreateChildSpan(ctx, "etcd-create-watch")
+	defer span.Finish()
 
-	formattedPath := b.makePath(key)
-	logger.Debugw("creating-key-watch", log.Fields{"key": key, "path": formattedPath})
+	formattedPath := b.makePath(ctx, key)
+	logger.Debugw(ctx, "creating-key-watch", log.Fields{"key": key, "path": formattedPath})
 
 	return b.Client.Watch(ctx, formattedPath, withPrefix)
 }
 
 // DeleteWatch stops watching events for the specified key
-func (b *Backend) DeleteWatch(key string, ch chan *kvstore.Event) {
-	b.Lock()
-	defer b.Unlock()
+func (b *Backend) DeleteWatch(ctx context.Context, key string, ch chan *kvstore.Event) {
+	span, ctx := log.CreateChildSpan(ctx, "etcd-delete-watch")
+	defer span.Finish()
 
-	formattedPath := b.makePath(key)
-	logger.Debugw("deleting-key-watch", log.Fields{"key": key, "path": formattedPath})
+	formattedPath := b.makePath(ctx, key)
+	logger.Debugw(ctx, "deleting-key-watch", log.Fields{"key": key, "path": formattedPath})
 
-	b.Client.CloseWatch(formattedPath, ch)
+	b.Client.CloseWatch(ctx, formattedPath, ch)
 }
diff --git a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/common.go b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/db/common.go
similarity index 80%
rename from vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/common.go
rename to vendor/github.com/opencord/voltha-lib-go/v4/pkg/db/common.go
index a5a79ae..25cddf5 100644
--- a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/common.go
+++ b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/db/common.go
@@ -16,19 +16,15 @@
 package db
 
 import (
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
+	"github.com/opencord/voltha-lib-go/v4/pkg/log"
 )
 
-const (
-	logLevel = log.ErrorLevel
-)
-
-var logger log.Logger
+var logger log.CLogger
 
 func init() {
 	// Setup this package so that it's log level can be modified at run time
 	var err error
-	logger, err = log.AddPackage(log.JSON, logLevel, log.Fields{"pkg": "db"})
+	logger, err = log.RegisterPackage(log.JSON, log.ErrorLevel, log.Fields{})
 	if err != nil {
 		panic(err)
 	}
diff --git a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore/client.go b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/db/kvstore/client.go
similarity index 89%
rename from vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore/client.go
rename to vendor/github.com/opencord/voltha-lib-go/v4/pkg/db/kvstore/client.go
index b9cb1ee..480d476 100644
--- a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore/client.go
+++ b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/db/kvstore/client.go
@@ -15,11 +15,14 @@
  */
 package kvstore
 
-import "context"
+import (
+	"context"
+	"time"
+)
 
 const (
 	// Default timeout in seconds when making a kvstore request
-	defaultKVGetTimeout = 5
+	defaultKVGetTimeout = 5 * time.Second
 	// Maximum channel buffer between publisher/subscriber goroutines
 	maxClientChannelBufferSize = 10
 )
@@ -77,14 +80,14 @@
 	Get(ctx context.Context, key string) (*KVPair, error)
 	Put(ctx context.Context, key string, value interface{}) error
 	Delete(ctx context.Context, key string) error
-	Reserve(ctx context.Context, key string, value interface{}, ttl int64) (interface{}, error)
+	Reserve(ctx context.Context, key string, value interface{}, ttl time.Duration) (interface{}, error)
 	ReleaseReservation(ctx context.Context, key string) error
 	ReleaseAllReservations(ctx context.Context) error
 	RenewReservation(ctx context.Context, key string) error
 	Watch(ctx context.Context, key string, withPrefix bool) chan *Event
-	AcquireLock(ctx context.Context, lockName string, timeout int) error
+	AcquireLock(ctx context.Context, lockName string, timeout time.Duration) error
 	ReleaseLock(lockName string) error
 	IsConnectionUp(ctx context.Context) bool // timeout in second
-	CloseWatch(key string, ch chan *Event)
-	Close()
+	CloseWatch(ctx context.Context, key string, ch chan *Event)
+	Close(ctx context.Context)
 }
diff --git a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore/common.go b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/db/kvstore/common.go
similarity index 80%
rename from vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore/common.go
rename to vendor/github.com/opencord/voltha-lib-go/v4/pkg/db/kvstore/common.go
index 2d2a6a6..99c603d 100644
--- a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore/common.go
+++ b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/db/kvstore/common.go
@@ -16,19 +16,15 @@
 package kvstore
 
 import (
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
+	"github.com/opencord/voltha-lib-go/v4/pkg/log"
 )
 
-const (
-	logLevel = log.ErrorLevel
-)
-
-var logger log.Logger
+var logger log.CLogger
 
 func init() {
 	// Setup this package so that it's log level can be modified at run time
 	var err error
-	logger, err = log.AddPackage(log.JSON, logLevel, log.Fields{"pkg": "kvstore"})
+	logger, err = log.RegisterPackage(log.JSON, log.ErrorLevel, log.Fields{})
 	if err != nil {
 		panic(err)
 	}
diff --git a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore/consulclient.go b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/db/kvstore/consulclient.go
similarity index 79%
rename from vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore/consulclient.go
rename to vendor/github.com/opencord/voltha-lib-go/v4/pkg/db/kvstore/consulclient.go
index bdf2d10..2593608 100644
--- a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore/consulclient.go
+++ b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/db/kvstore/consulclient.go
@@ -19,7 +19,7 @@
 	"bytes"
 	"context"
 	"errors"
-	log "github.com/opencord/voltha-lib-go/v3/pkg/log"
+	log "github.com/opencord/voltha-lib-go/v4/pkg/log"
 	"sync"
 	"time"
 	//log "ciena.com/coordinator/common"
@@ -44,16 +44,13 @@
 }
 
 // NewConsulClient returns a new client for the Consul KV store
-func NewConsulClient(addr string, timeout int) (*ConsulClient, error) {
-
-	duration := GetDuration(timeout)
-
+func NewConsulClient(ctx context.Context, addr string, timeout time.Duration) (*ConsulClient, error) {
 	config := consulapi.DefaultConfig()
 	config.Address = addr
-	config.WaitTime = duration
+	config.WaitTime = timeout
 	consul, err := consulapi.NewClient(config)
 	if err != nil {
-		logger.Error(err)
+		logger.Error(ctx, err)
 		return nil, err
 	}
 
@@ -65,7 +62,7 @@
 
 // IsConnectionUp returns whether the connection to the Consul KV store is up
 func (c *ConsulClient) IsConnectionUp(ctx context.Context) bool {
-	logger.Error("Unimplemented function")
+	logger.Error(ctx, "Unimplemented function")
 	return false
 }
 
@@ -76,11 +73,13 @@
 	deadline, _ := ctx.Deadline()
 	kv := c.consul.KV()
 	var queryOptions consulapi.QueryOptions
-	queryOptions.WaitTime = GetDuration(deadline.Second())
+	// Substract current time from deadline to get the waitTime duration
+	queryOptions.WaitTime = time.Until(deadline)
+
 	// For now we ignore meta data
 	kvps, _, err := kv.List(key, &queryOptions)
 	if err != nil {
-		logger.Error(err)
+		logger.Error(ctx, err)
 		return nil, err
 	}
 	m := make(map[string]*KVPair)
@@ -97,11 +96,13 @@
 	deadline, _ := ctx.Deadline()
 	kv := c.consul.KV()
 	var queryOptions consulapi.QueryOptions
-	queryOptions.WaitTime = GetDuration(deadline.Second())
+	// Substract current time from deadline to get the waitTime duration
+	queryOptions.WaitTime = time.Until(deadline)
+
 	// For now we ignore meta data
 	kvp, _, err := kv.Get(key, &queryOptions)
 	if err != nil {
-		logger.Error(err)
+		logger.Error(ctx, err)
 		return nil, err
 	}
 	if kvp != nil {
@@ -120,7 +121,7 @@
 	var val []byte
 	var er error
 	if val, er = ToByte(value); er != nil {
-		logger.Error(er)
+		logger.Error(ctx, er)
 		return er
 	}
 
@@ -132,7 +133,7 @@
 	defer c.writeLock.Unlock()
 	_, err := kv.Put(&kvp, &writeOptions)
 	if err != nil {
-		logger.Error(err)
+		logger.Error(ctx, err)
 		return err
 	}
 	return nil
@@ -147,46 +148,46 @@
 	defer c.writeLock.Unlock()
 	_, err := kv.Delete(key, &writeOptions)
 	if err != nil {
-		logger.Error(err)
+		logger.Error(ctx, err)
 		return err
 	}
 	return nil
 }
 
-func (c *ConsulClient) deleteSession() {
+func (c *ConsulClient) deleteSession(ctx context.Context) {
 	if c.sessionID != "" {
-		logger.Debug("cleaning-up-session")
+		logger.Debug(ctx, "cleaning-up-session")
 		session := c.consul.Session()
 		_, err := session.Destroy(c.sessionID, nil)
 		if err != nil {
-			logger.Errorw("error-cleaning-session", log.Fields{"session": c.sessionID, "error": err})
+			logger.Errorw(ctx, "error-cleaning-session", log.Fields{"session": c.sessionID, "error": err})
 		}
 	}
 	c.sessionID = ""
 	c.session = nil
 }
 
-func (c *ConsulClient) createSession(ttl int64, retries int) (*consulapi.Session, string, error) {
+func (c *ConsulClient) createSession(ctx context.Context, ttl time.Duration, retries int) (*consulapi.Session, string, error) {
 	session := c.consul.Session()
 	entry := &consulapi.SessionEntry{
 		Behavior: consulapi.SessionBehaviorDelete,
-		TTL:      "10s", // strconv.FormatInt(ttl, 10) + "s", // disable ttl
+		TTL:      ttl.String(),
 	}
 
 	for {
 		id, meta, err := session.Create(entry, nil)
 		if err != nil {
-			logger.Errorw("create-session-error", log.Fields{"error": err})
+			logger.Errorw(ctx, "create-session-error", log.Fields{"error": err})
 			if retries == 0 {
 				return nil, "", err
 			}
 		} else if meta.RequestTime == 0 {
-			logger.Errorw("create-session-bad-meta-data", log.Fields{"meta-data": meta})
+			logger.Errorw(ctx, "create-session-bad-meta-data", log.Fields{"meta-data": meta})
 			if retries == 0 {
 				return nil, "", errors.New("bad-meta-data")
 			}
 		} else if id == "" {
-			logger.Error("create-session-nil-id")
+			logger.Error(ctx, "create-session-nil-id")
 			if retries == 0 {
 				return nil, "", errors.New("ID-nil")
 			}
@@ -197,7 +198,7 @@
 		if retries > 0 {
 			retries--
 		}
-		logger.Debug("retrying-session-create-after-a-second-delay")
+		logger.Debug(ctx, "retrying-session-create-after-a-second-delay")
 		time.Sleep(time.Duration(1) * time.Second)
 	}
 }
@@ -218,36 +219,36 @@
 // defines how long that reservation is valid.  When TTL expires the key is unreserved by the KV store itself.
 // If the key is acquired then the value returned will be the value passed in.  If the key is already acquired
 // then the value assigned to that key will be returned.
-func (c *ConsulClient) Reserve(ctx context.Context, key string, value interface{}, ttl int64) (interface{}, error) {
+func (c *ConsulClient) Reserve(ctx context.Context, key string, value interface{}, ttl time.Duration) (interface{}, error) {
 
 	// Validate that we can create a byte array from the value as consul API expects a byte array
 	var val []byte
 	var er error
 	if val, er = ToByte(value); er != nil {
-		logger.Error(er)
+		logger.Error(ctx, er)
 		return nil, er
 	}
 
 	// Cleanup any existing session and recreate new ones.  A key is reserved against a session
 	if c.sessionID != "" {
-		c.deleteSession()
+		c.deleteSession(ctx)
 	}
 
 	// Clear session if reservation is not successful
 	reservationSuccessful := false
 	defer func() {
 		if !reservationSuccessful {
-			logger.Debug("deleting-session")
-			c.deleteSession()
+			logger.Debug(ctx, "deleting-session")
+			c.deleteSession(ctx)
 		}
 	}()
 
-	session, sessionID, err := c.createSession(ttl, -1)
+	session, sessionID, err := c.createSession(ctx, ttl, -1)
 	if err != nil {
-		logger.Errorw("no-session-created", log.Fields{"error": err})
+		logger.Errorw(ctx, "no-session-created", log.Fields{"error": err})
 		return "", errors.New("no-session-created")
 	}
-	logger.Debugw("session-created", log.Fields{"session-id": sessionID})
+	logger.Debugw(ctx, "session-created", log.Fields{"session-id": sessionID})
 	c.sessionID = sessionID
 	c.session = session
 
@@ -256,11 +257,11 @@
 	kvp := consulapi.KVPair{Key: key, Value: val, Session: c.sessionID}
 	result, _, err := kv.Acquire(&kvp, nil)
 	if err != nil {
-		logger.Errorw("error-acquiring-keys", log.Fields{"error": err})
+		logger.Errorw(ctx, "error-acquiring-keys", log.Fields{"error": err})
 		return nil, err
 	}
 
-	logger.Debugw("key-acquired", log.Fields{"key": key, "status": result})
+	logger.Debugw(ctx, "key-acquired", log.Fields{"key": key, "status": result})
 
 	// Irrespective whether we were successful in acquiring the key, let's read it back and see if it's us.
 	m, err := c.Get(ctx, key)
@@ -268,7 +269,7 @@
 		return nil, err
 	}
 	if m != nil {
-		logger.Debugw("response-received", log.Fields{"key": m.Key, "m.value": string(m.Value.([]byte)), "value": value})
+		logger.Debugw(ctx, "response-received", log.Fields{"key": m.Key, "m.value": string(m.Value.([]byte)), "value": value})
 		if m.Key == key && isEqual(m.Value, value) {
 			// My reservation is successful - register it.  For now, support is only for 1 reservation per key
 			// per session.
@@ -298,11 +299,11 @@
 		kvp = consulapi.KVPair{Key: key, Value: value.([]byte), Session: c.sessionID}
 		result, _, err = kv.Release(&kvp, nil)
 		if err != nil {
-			logger.Errorw("cannot-release-reservation", log.Fields{"key": key, "error": err})
+			logger.Errorw(ctx, "cannot-release-reservation", log.Fields{"key": key, "error": err})
 			return err
 		}
 		if !result {
-			logger.Errorw("cannot-release-reservation", log.Fields{"key": key})
+			logger.Errorw(ctx, "cannot-release-reservation", log.Fields{"key": key})
 		}
 		delete(c.keyReservations, key)
 	}
@@ -382,21 +383,21 @@
 
 // CloseWatch closes a specific watch. Both the key and the channel are required when closing a watch as there
 // may be multiple listeners on the same key.  The previously created channel serves as a key
-func (c *ConsulClient) CloseWatch(key string, ch chan *Event) {
+func (c *ConsulClient) CloseWatch(ctx context.Context, key string, ch chan *Event) {
 	// First close the context
 	var ok bool
 	var watchedChannelsContexts []*channelContextMap
 	c.writeLock.Lock()
 	defer c.writeLock.Unlock()
 	if watchedChannelsContexts, ok = c.watchedChannelsContext[key]; !ok {
-		logger.Errorw("key-has-no-watched-context-or-channel", log.Fields{"key": key})
+		logger.Errorw(ctx, "key-has-no-watched-context-or-channel", log.Fields{"key": key})
 		return
 	}
 	// Look for the channels
 	var pos = -1
 	for i, chCtxMap := range watchedChannelsContexts {
 		if chCtxMap.channel == ch {
-			logger.Debug("channel-found")
+			logger.Debug(ctx, "channel-found")
 			chCtxMap.cancel()
 			//close the channel
 			close(ch)
@@ -408,7 +409,7 @@
 	if pos >= 0 {
 		c.watchedChannelsContext[key] = append(c.watchedChannelsContext[key][:pos], c.watchedChannelsContext[key][pos+1:]...)
 	}
-	logger.Debugw("watched-channel-exiting", log.Fields{"key": key, "channel": c.watchedChannelsContext[key]})
+	logger.Debugw(ctx, "watched-channel-exiting", log.Fields{"key": key, "channel": c.watchedChannelsContext[key]})
 }
 
 func (c *ConsulClient) isKVEqual(kv1 *consulapi.KVPair, kv2 *consulapi.KVPair) bool {
@@ -428,19 +429,18 @@
 	return true
 }
 
-func (c *ConsulClient) listenForKeyChange(watchContext context.Context, key string, ch chan *Event) {
-	logger.Debugw("start-watching-channel", log.Fields{"key": key, "channel": ch})
+func (c *ConsulClient) listenForKeyChange(ctx context.Context, key string, ch chan *Event) {
+	logger.Debugw(ctx, "start-watching-channel", log.Fields{"key": key, "channel": ch})
 
-	defer c.CloseWatch(key, ch)
-	duration := GetDuration(defaultKVGetTimeout)
+	defer c.CloseWatch(ctx, key, ch)
 	kv := c.consul.KV()
 	var queryOptions consulapi.QueryOptions
-	queryOptions.WaitTime = duration
+	queryOptions.WaitTime = defaultKVGetTimeout
 
 	// Get the existing value, if any
 	previousKVPair, meta, err := kv.Get(key, &queryOptions)
 	if err != nil {
-		logger.Debug(err)
+		logger.Debug(ctx, err)
 	}
 	lastIndex := meta.LastIndex
 
@@ -448,37 +448,37 @@
 	//var waitOptions consulapi.QueryOptions
 	var pair *consulapi.KVPair
 	//watchContext, _ := context.WithCancel(context.Background())
-	waitOptions := queryOptions.WithContext(watchContext)
+	waitOptions := queryOptions.WithContext(ctx)
 	for {
 		//waitOptions = consulapi.QueryOptions{WaitIndex: lastIndex}
 		waitOptions.WaitIndex = lastIndex
 		pair, meta, err = kv.Get(key, waitOptions)
 		select {
-		case <-watchContext.Done():
-			logger.Debug("done-event-received-exiting")
+		case <-ctx.Done():
+			logger.Debug(ctx, "done-event-received-exiting")
 			return
 		default:
 			if err != nil {
-				logger.Warnw("error-from-watch", log.Fields{"error": err})
+				logger.Warnw(ctx, "error-from-watch", log.Fields{"error": err})
 				ch <- NewEvent(CONNECTIONDOWN, key, []byte(""), -1)
 			} else {
-				logger.Debugw("index-state", log.Fields{"lastindex": lastIndex, "newindex": meta.LastIndex, "key": key})
+				logger.Debugw(ctx, "index-state", log.Fields{"lastindex": lastIndex, "newindex": meta.LastIndex, "key": key})
 			}
 		}
 		if err != nil {
-			logger.Debug(err)
+			logger.Debug(ctx, err)
 			// On error, block for 10 milliseconds to prevent endless loop
 			time.Sleep(10 * time.Millisecond)
 		} else if meta.LastIndex <= lastIndex {
-			logger.Info("no-index-change-or-negative")
+			logger.Info(ctx, "no-index-change-or-negative")
 		} else {
-			logger.Debugw("update-received", log.Fields{"pair": pair})
+			logger.Debugw(ctx, "update-received", log.Fields{"pair": pair})
 			if pair == nil {
 				ch <- NewEvent(DELETE, key, []byte(""), -1)
 			} else if !c.isKVEqual(pair, previousKVPair) {
 				// Push the change onto the channel if the data has changed
 				// For now just assume it's a PUT change
-				logger.Debugw("pair-details", log.Fields{"session": pair.Session, "key": pair.Key, "value": pair.Value})
+				logger.Debugw(ctx, "pair-details", log.Fields{"session": pair.Session, "key": pair.Key, "value": pair.Value})
 				ch <- NewEvent(PUT, pair.Key, pair.Value, -1)
 			}
 			previousKVPair = pair
@@ -488,7 +488,7 @@
 }
 
 // Close closes the KV store client
-func (c *ConsulClient) Close() {
+func (c *ConsulClient) Close(ctx context.Context) {
 	var writeOptions consulapi.WriteOptions
 	// Inform any goroutine it's time to say goodbye.
 	c.writeLock.Lock()
@@ -499,11 +499,11 @@
 
 	// Clear the sessionID
 	if _, err := c.consul.Session().Destroy(c.sessionID, &writeOptions); err != nil {
-		logger.Errorw("error-closing-client", log.Fields{"error": err})
+		logger.Errorw(ctx, "error-closing-client", log.Fields{"error": err})
 	}
 }
 
-func (c *ConsulClient) AcquireLock(ctx context.Context, lockName string, timeout int) error {
+func (c *ConsulClient) AcquireLock(ctx context.Context, lockName string, timeout time.Duration) error {
 	return nil
 }
 
diff --git a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore/etcdclient.go b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/db/kvstore/etcdclient.go
similarity index 85%
rename from vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore/etcdclient.go
rename to vendor/github.com/opencord/voltha-lib-go/v4/pkg/db/kvstore/etcdclient.go
index d38f0f6..aa5adbf 100644
--- a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore/etcdclient.go
+++ b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/db/kvstore/etcdclient.go
@@ -20,8 +20,9 @@
 	"errors"
 	"fmt"
 	"sync"
+	"time"
 
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
+	"github.com/opencord/voltha-lib-go/v4/pkg/log"
 	v3Client "go.etcd.io/etcd/clientv3"
 	v3Concurrency "go.etcd.io/etcd/clientv3/concurrency"
 	v3rpcTypes "go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes"
@@ -39,15 +40,16 @@
 }
 
 // NewEtcdClient returns a new client for the Etcd KV store
-func NewEtcdClient(addr string, timeout int) (*EtcdClient, error) {
-	duration := GetDuration(timeout)
+func NewEtcdClient(ctx context.Context, addr string, timeout time.Duration, level log.LogLevel) (*EtcdClient, error) {
+	logconfig := log.ConstructZapConfig(log.JSON, level, log.Fields{})
 
 	c, err := v3Client.New(v3Client.Config{
 		Endpoints:   []string{addr},
-		DialTimeout: duration,
+		DialTimeout: timeout,
+		LogConfig:   &logconfig,
 	})
 	if err != nil {
-		logger.Error(err)
+		logger.Error(ctx, err)
 		return nil, err
 	}
 
@@ -75,7 +77,7 @@
 func (c *EtcdClient) List(ctx context.Context, key string) (map[string]*KVPair, error) {
 	resp, err := c.ectdAPI.Get(ctx, key, v3Client.WithPrefix())
 	if err != nil {
-		logger.Error(err)
+		logger.Error(ctx, err)
 		return nil, err
 	}
 	m := make(map[string]*KVPair)
@@ -92,7 +94,7 @@
 	resp, err := c.ectdAPI.Get(ctx, key)
 
 	if err != nil {
-		logger.Error(err)
+		logger.Error(ctx, err)
 		return nil, err
 	}
 	for _, ev := range resp.Kvs {
@@ -129,13 +131,13 @@
 	if err != nil {
 		switch err {
 		case context.Canceled:
-			logger.Warnw("context-cancelled", log.Fields{"error": err})
+			logger.Warnw(ctx, "context-cancelled", log.Fields{"error": err})
 		case context.DeadlineExceeded:
-			logger.Warnw("context-deadline-exceeded", log.Fields{"error": err})
+			logger.Warnw(ctx, "context-deadline-exceeded", log.Fields{"error": err})
 		case v3rpcTypes.ErrEmptyKey:
-			logger.Warnw("etcd-client-error", log.Fields{"error": err})
+			logger.Warnw(ctx, "etcd-client-error", log.Fields{"error": err})
 		default:
-			logger.Warnw("bad-endpoints", log.Fields{"error": err})
+			logger.Warnw(ctx, "bad-endpoints", log.Fields{"error": err})
 		}
 		return err
 	}
@@ -148,10 +150,10 @@
 
 	// delete the key
 	if _, err := c.ectdAPI.Delete(ctx, key); err != nil {
-		logger.Errorw("failed-to-delete-key", log.Fields{"key": key, "error": err})
+		logger.Errorw(ctx, "failed-to-delete-key", log.Fields{"key": key, "error": err})
 		return err
 	}
-	logger.Debugw("key(s)-deleted", log.Fields{"key": key})
+	logger.Debugw(ctx, "key(s)-deleted", log.Fields{"key": key})
 	return nil
 }
 
@@ -160,7 +162,7 @@
 // defines how long that reservation is valid.  When TTL expires the key is unreserved by the KV store itself.
 // If the key is acquired then the value returned will be the value passed in.  If the key is already acquired
 // then the value assigned to that key will be returned.
-func (c *EtcdClient) Reserve(ctx context.Context, key string, value interface{}, ttl int64) (interface{}, error) {
+func (c *EtcdClient) Reserve(ctx context.Context, key string, value interface{}, ttl time.Duration) (interface{}, error) {
 	// Validate that we can convert value to a string as etcd API expects a string
 	var val string
 	var er error
@@ -168,9 +170,9 @@
 		return nil, fmt.Errorf("unexpected-type%T", value)
 	}
 
-	resp, err := c.ectdAPI.Grant(ctx, ttl)
+	resp, err := c.ectdAPI.Grant(ctx, int64(ttl.Seconds()))
 	if err != nil {
-		logger.Error(err)
+		logger.Error(ctx, err)
 		return nil, err
 	}
 	// Register the lease id
@@ -183,7 +185,7 @@
 	defer func() {
 		if !reservationSuccessful {
 			if err = c.ReleaseReservation(context.Background(), key); err != nil {
-				logger.Error("cannot-release-lease")
+				logger.Error(ctx, "cannot-release-lease")
 			}
 		}
 	}()
@@ -238,7 +240,7 @@
 	for key, leaseID := range c.keyReservations {
 		_, err := c.ectdAPI.Revoke(ctx, *leaseID)
 		if err != nil {
-			logger.Errorw("cannot-release-reservation", log.Fields{"key": key, "error": err})
+			logger.Errorw(ctx, "cannot-release-reservation", log.Fields{"key": key, "error": err})
 			return err
 		}
 		delete(c.keyReservations, key)
@@ -249,7 +251,7 @@
 // ReleaseReservation releases reservation for a specific key.
 func (c *EtcdClient) ReleaseReservation(ctx context.Context, key string) error {
 	// Get the leaseid using the key
-	logger.Debugw("Release-reservation", log.Fields{"key": key})
+	logger.Debugw(ctx, "Release-reservation", log.Fields{"key": key})
 	var ok bool
 	var leaseID *v3Client.LeaseID
 	c.keyReservationsLock.Lock()
@@ -261,7 +263,7 @@
 	if leaseID != nil {
 		_, err := c.ectdAPI.Revoke(ctx, *leaseID)
 		if err != nil {
-			logger.Error(err)
+			logger.Error(ctx, err)
 			return err
 		}
 		delete(c.keyReservations, key)
@@ -286,7 +288,7 @@
 	if leaseID != nil {
 		_, err := c.ectdAPI.KeepAliveOnce(ctx, *leaseID)
 		if err != nil {
-			logger.Errorw("lease-may-have-expired", log.Fields{"error": err})
+			logger.Errorw(ctx, "lease-may-have-expired", log.Fields{"error": err})
 			return err
 		}
 	} else {
@@ -318,9 +320,9 @@
 
 	// Changing the log field (from channelMaps) as the underlying logger cannot format the map of channels into a
 	// json format.
-	logger.Debugw("watched-channels", log.Fields{"len": len(channelMaps)})
+	logger.Debugw(ctx, "watched-channels", log.Fields{"len": len(channelMaps)})
 	// Launch a go routine to listen for updates
-	go c.listenForKeyChange(channel, ch, cancel)
+	go c.listenForKeyChange(ctx, channel, ch, cancel)
 
 	return ch
 
@@ -367,23 +369,23 @@
 
 // CloseWatch closes a specific watch. Both the key and the channel are required when closing a watch as there
 // may be multiple listeners on the same key.  The previously created channel serves as a key
-func (c *EtcdClient) CloseWatch(key string, ch chan *Event) {
+func (c *EtcdClient) CloseWatch(ctx context.Context, key string, ch chan *Event) {
 	// Get the array of channels mapping
 	var watchedChannels []map[chan *Event]v3Client.Watcher
 	var ok bool
 
 	if watchedChannels, ok = c.getChannelMaps(key); !ok {
-		logger.Warnw("key-has-no-watched-channels", log.Fields{"key": key})
+		logger.Warnw(ctx, "key-has-no-watched-channels", log.Fields{"key": key})
 		return
 	}
 	// Look for the channels
 	var pos = -1
 	for i, chMap := range watchedChannels {
 		if t, ok := chMap[ch]; ok {
-			logger.Debug("channel-found")
+			logger.Debug(ctx, "channel-found")
 			// Close the etcd watcher before the client channel.  This should close the etcd channel as well
 			if err := t.Close(); err != nil {
-				logger.Errorw("watcher-cannot-be-closed", log.Fields{"key": key, "error": err})
+				logger.Errorw(ctx, "watcher-cannot-be-closed", log.Fields{"key": key, "error": err})
 			}
 			pos = i
 			break
@@ -395,11 +397,11 @@
 	if pos >= 0 {
 		channelMaps = c.removeChannelMap(key, pos)
 	}
-	logger.Infow("watcher-channel-exiting", log.Fields{"key": key, "channel": channelMaps})
+	logger.Infow(ctx, "watcher-channel-exiting", log.Fields{"key": key, "channel": channelMaps})
 }
 
-func (c *EtcdClient) listenForKeyChange(channel v3Client.WatchChan, ch chan<- *Event, cancel context.CancelFunc) {
-	logger.Debug("start-listening-on-channel ...")
+func (c *EtcdClient) listenForKeyChange(ctx context.Context, channel v3Client.WatchChan, ch chan<- *Event, cancel context.CancelFunc) {
+	logger.Debug(ctx, "start-listening-on-channel ...")
 	defer cancel()
 	defer close(ch)
 	for resp := range channel {
@@ -407,7 +409,7 @@
 			ch <- NewEvent(getEventType(ev), ev.Kv.Key, ev.Kv.Value, ev.Kv.Version)
 		}
 	}
-	logger.Debug("stop-listening-on-channel ...")
+	logger.Debug(ctx, "stop-listening-on-channel ...")
 }
 
 func getEventType(event *v3Client.Event) int {
@@ -421,9 +423,9 @@
 }
 
 // Close closes the KV store client
-func (c *EtcdClient) Close() {
+func (c *EtcdClient) Close(ctx context.Context) {
 	if err := c.ectdAPI.Close(); err != nil {
-		logger.Errorw("error-closing-client", log.Fields{"error": err})
+		logger.Errorw(ctx, "error-closing-client", log.Fields{"error": err})
 	}
 }
 
@@ -455,7 +457,7 @@
 	return lock, session
 }
 
-func (c *EtcdClient) AcquireLock(ctx context.Context, lockName string, timeout int) error {
+func (c *EtcdClient) AcquireLock(ctx context.Context, lockName string, timeout time.Duration) error {
 	session, _ := v3Concurrency.NewSession(c.ectdAPI, v3Concurrency.WithContext(ctx))
 	mu := v3Concurrency.NewMutex(session, "/devicelock_"+lockName)
 	if err := mu.Lock(context.Background()); err != nil {
diff --git a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore/kvutils.go b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/db/kvstore/kvutils.go
similarity index 79%
rename from vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore/kvutils.go
rename to vendor/github.com/opencord/voltha-lib-go/v4/pkg/db/kvstore/kvutils.go
index cf9a95c..64e7d30 100644
--- a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore/kvutils.go
+++ b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/db/kvstore/kvutils.go
@@ -15,19 +15,7 @@
  */
 package kvstore
 
-import (
-	"fmt"
-	"time"
-)
-
-// GetDuration converts a timeout value from int to duration.  If the timeout value is
-// either not set of -ve then we default KV timeout (configurable) is used.
-func GetDuration(timeout int) time.Duration {
-	if timeout <= 0 {
-		return defaultKVGetTimeout * time.Second
-	}
-	return time.Duration(timeout) * time.Second
-}
+import "fmt"
 
 // ToString converts an interface value to a string.  The interface should either be of
 // a string type or []byte.  Otherwise, an error is returned.
diff --git a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/common.go b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/log/common.go
similarity index 78%
copy from vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/common.go
copy to vendor/github.com/opencord/voltha-lib-go/v4/pkg/log/common.go
index a5a79ae..b0ce81b 100644
--- a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/common.go
+++ b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/log/common.go
@@ -13,22 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package db
+package log
 
-import (
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-)
-
-const (
-	logLevel = log.ErrorLevel
-)
-
-var logger log.Logger
+var logger CLogger
 
 func init() {
 	// Setup this package so that it's log level can be modified at run time
 	var err error
-	logger, err = log.AddPackage(log.JSON, logLevel, log.Fields{"pkg": "db"})
+	logger, err = RegisterPackage(JSON, ErrorLevel, Fields{})
 	if err != nil {
 		panic(err)
 	}
diff --git a/vendor/github.com/opencord/voltha-lib-go/v4/pkg/log/log.go b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/log/log.go
new file mode 100644
index 0000000..b8d498c
--- /dev/null
+++ b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/log/log.go
@@ -0,0 +1,661 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Package log provides a structured Logger interface implemented using zap logger. It provides the following capabilities:
+// 1. Package level logging - a go package can register itself (AddPackage) and have a logger created for that package.
+// 2. Dynamic log level change - for all registered packages (SetAllLogLevel)
+// 3. Dynamic log level change - for a given package (SetPackageLogLevel)
+// 4. Provides a default logger for unregistered packages (however avoid its usage)
+// 5. Allow key-value pairs to be added to a logger(UpdateLogger) or all loggers (UpdateAllLoggers) at run time
+// 6. Add to the log output the location where the log was invoked (filename.functionname.linenumber)
+//
+// Using package-level logging (recommended approach).  In the examples below, log refers to this log package.
+//
+// 1. In the appropriate package, add the following in the init section of the package (usually in a common.go file)
+//    The log level can be changed and any number of default fields can be added as well. The log level specifies
+//    the lowest log level that will be in the output while the fields will be automatically added to all log printouts.
+//    However, as voltha components re-initialize the log level of each registered package to default initial loglevel
+//    passed as CLI argument, the log level passed in RegisterPackage call effectively has no effect.
+//
+//    var logger log.CLogger
+//    func init() {
+//              logger, err = log.RegisterPackage(log.JSON, log.ErrorLevel, log.Fields{"key1": "value1"})
+//    }
+//
+// 2. In the calling package, use any of the publicly available functions of local package-level logger instance created
+//    in previous step.  Here is an example to write an Info log with additional fields:
+//
+//    logger.Infow("An example", mylog.Fields{"myStringOutput": "output", "myIntOutput": 2})
+//
+// 3. To dynamically change the log level, you can use
+//          a) SetLogLevel from inside your package or
+//          b) SetPackageLogLevel from anywhere or
+//          c) SetAllLogLevel from anywhere.
+//
+//    Dynamic Loglevel configuration feature also uses SetPackageLogLevel method based on triggers received due to
+//    Changes to configured loglevels
+
+package log
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	zp "go.uber.org/zap"
+	zc "go.uber.org/zap/zapcore"
+	"path"
+	"runtime"
+	"strings"
+)
+
+type LogLevel int8
+
+const (
+	// DebugLevel logs a message at debug level
+	DebugLevel = LogLevel(iota)
+	// InfoLevel logs a message at info level
+	InfoLevel
+	// WarnLevel logs a message at warning level
+	WarnLevel
+	// ErrorLevel logs a message at error level
+	ErrorLevel
+	// FatalLevel logs a message, then calls os.Exit(1).
+	FatalLevel
+)
+
+// CONSOLE formats the log for the console, mostly used during development
+const CONSOLE = "console"
+
+// JSON formats the log using json format, mostly used by an automated logging system consumption
+const JSON = "json"
+
+// Context Aware Logger represents an abstract logging interface.  Any logging implementation used
+// will need to abide by this interface
+type CLogger interface {
+	Debug(context.Context, ...interface{})
+	Debugln(context.Context, ...interface{})
+	Debugf(context.Context, string, ...interface{})
+	Debugw(context.Context, string, Fields)
+
+	Info(context.Context, ...interface{})
+	Infoln(context.Context, ...interface{})
+	Infof(context.Context, string, ...interface{})
+	Infow(context.Context, string, Fields)
+
+	Warn(context.Context, ...interface{})
+	Warnln(context.Context, ...interface{})
+	Warnf(context.Context, string, ...interface{})
+	Warnw(context.Context, string, Fields)
+
+	Error(context.Context, ...interface{})
+	Errorln(context.Context, ...interface{})
+	Errorf(context.Context, string, ...interface{})
+	Errorw(context.Context, string, Fields)
+
+	Fatal(context.Context, ...interface{})
+	Fatalln(context.Context, ...interface{})
+	Fatalf(context.Context, string, ...interface{})
+	Fatalw(context.Context, string, Fields)
+
+	With(Fields) CLogger
+
+	// The following are added to be able to use this logger as a gRPC LoggerV2 if needed
+	//
+	Warning(context.Context, ...interface{})
+	Warningln(context.Context, ...interface{})
+	Warningf(context.Context, string, ...interface{})
+
+	// V reports whether verbosity level l is at least the requested verbose level.
+	V(l LogLevel) bool
+
+	//Returns the log level of this specific logger
+	GetLogLevel() LogLevel
+}
+
+// Fields is used as key-value pairs for structured logging
+type Fields map[string]interface{}
+
+var defaultLogger *clogger
+var cfg zp.Config
+
+var loggers map[string]*clogger
+var cfgs map[string]zp.Config
+
+type clogger struct {
+	log         *zp.SugaredLogger
+	parent      *zp.Logger
+	packageName string
+}
+
+func logLevelToAtomicLevel(l LogLevel) zp.AtomicLevel {
+	switch l {
+	case DebugLevel:
+		return zp.NewAtomicLevelAt(zc.DebugLevel)
+	case InfoLevel:
+		return zp.NewAtomicLevelAt(zc.InfoLevel)
+	case WarnLevel:
+		return zp.NewAtomicLevelAt(zc.WarnLevel)
+	case ErrorLevel:
+		return zp.NewAtomicLevelAt(zc.ErrorLevel)
+	case FatalLevel:
+		return zp.NewAtomicLevelAt(zc.FatalLevel)
+	}
+	return zp.NewAtomicLevelAt(zc.ErrorLevel)
+}
+
+func logLevelToLevel(l LogLevel) zc.Level {
+	switch l {
+	case DebugLevel:
+		return zc.DebugLevel
+	case InfoLevel:
+		return zc.InfoLevel
+	case WarnLevel:
+		return zc.WarnLevel
+	case ErrorLevel:
+		return zc.ErrorLevel
+	case FatalLevel:
+		return zc.FatalLevel
+	}
+	return zc.ErrorLevel
+}
+
+func levelToLogLevel(l zc.Level) LogLevel {
+	switch l {
+	case zc.DebugLevel:
+		return DebugLevel
+	case zc.InfoLevel:
+		return InfoLevel
+	case zc.WarnLevel:
+		return WarnLevel
+	case zc.ErrorLevel:
+		return ErrorLevel
+	case zc.FatalLevel:
+		return FatalLevel
+	}
+	return ErrorLevel
+}
+
+func StringToLogLevel(l string) (LogLevel, error) {
+	switch strings.ToUpper(l) {
+	case "DEBUG":
+		return DebugLevel, nil
+	case "INFO":
+		return InfoLevel, nil
+	case "WARN":
+		return WarnLevel, nil
+	case "ERROR":
+		return ErrorLevel, nil
+	case "FATAL":
+		return FatalLevel, nil
+	}
+	return 0, errors.New("Given LogLevel is invalid : " + l)
+}
+
+func LogLevelToString(l LogLevel) (string, error) {
+	switch l {
+	case DebugLevel:
+		return "DEBUG", nil
+	case InfoLevel:
+		return "INFO", nil
+	case WarnLevel:
+		return "WARN", nil
+	case ErrorLevel:
+		return "ERROR", nil
+	case FatalLevel:
+		return "FATAL", nil
+	}
+	return "", errors.New("Given LogLevel is invalid " + string(l))
+}
+
+func getDefaultConfig(outputType string, level LogLevel, defaultFields Fields) zp.Config {
+	return zp.Config{
+		Level:            logLevelToAtomicLevel(level),
+		Encoding:         outputType,
+		Development:      true,
+		OutputPaths:      []string{"stdout"},
+		ErrorOutputPaths: []string{"stderr"},
+		InitialFields:    defaultFields,
+		EncoderConfig: zc.EncoderConfig{
+			LevelKey:       "level",
+			MessageKey:     "msg",
+			TimeKey:        "ts",
+			CallerKey:      "caller",
+			StacktraceKey:  "stacktrace",
+			LineEnding:     zc.DefaultLineEnding,
+			EncodeLevel:    zc.LowercaseLevelEncoder,
+			EncodeTime:     zc.ISO8601TimeEncoder,
+			EncodeDuration: zc.SecondsDurationEncoder,
+			EncodeCaller:   zc.ShortCallerEncoder,
+		},
+	}
+}
+
+func ConstructZapConfig(outputType string, level LogLevel, fields Fields) zp.Config {
+	return getDefaultConfig(outputType, level, fields)
+}
+
+// SetLogger needs to be invoked before the logger API can be invoked.  This function
+// initialize the default logger (zap's sugaredlogger)
+func SetDefaultLogger(outputType string, level LogLevel, defaultFields Fields) (CLogger, error) {
+	// Build a custom config using zap
+	cfg = getDefaultConfig(outputType, level, defaultFields)
+
+	l, err := cfg.Build(zp.AddCallerSkip(1))
+	if err != nil {
+		return nil, err
+	}
+
+	defaultLogger = &clogger{
+		log:    l.Sugar(),
+		parent: l,
+	}
+
+	return defaultLogger, nil
+}
+
+// AddPackage registers a package to the log map.  Each package gets its own logger which allows
+// its config (loglevel) to be changed dynamically without interacting with the other packages.
+// outputType is JSON, level is the lowest level log to output with this logger and defaultFields is a map of
+// key-value pairs to always add to the output.
+// Note: AddPackage also returns a reference to the actual logger.  If a calling package uses this reference directly
+//instead of using the publicly available functions in this log package then a number of functionalities will not
+// be available to it, notably log tracing with filename.functionname.linenumber annotation.
+//
+// pkgNames parameter should be used for testing only as this function detects the caller's package.
+func RegisterPackage(outputType string, level LogLevel, defaultFields Fields, pkgNames ...string) (CLogger, error) {
+	if cfgs == nil {
+		cfgs = make(map[string]zp.Config)
+	}
+	if loggers == nil {
+		loggers = make(map[string]*clogger)
+	}
+
+	var pkgName string
+	for _, name := range pkgNames {
+		pkgName = name
+		break
+	}
+	if pkgName == "" {
+		pkgName, _, _, _ = getCallerInfo()
+	}
+
+	if _, exist := loggers[pkgName]; exist {
+		return loggers[pkgName], nil
+	}
+
+	cfgs[pkgName] = getDefaultConfig(outputType, level, defaultFields)
+
+	l, err := cfgs[pkgName].Build(zp.AddCallerSkip(1))
+	if err != nil {
+		return nil, err
+	}
+
+	loggers[pkgName] = &clogger{
+		log:         l.Sugar(),
+		parent:      l,
+		packageName: pkgName,
+	}
+	return loggers[pkgName], nil
+}
+
+//UpdateAllLoggers create new loggers for all registered pacakges with the defaultFields.
+func UpdateAllLoggers(defaultFields Fields) error {
+	for pkgName, cfg := range cfgs {
+		for k, v := range defaultFields {
+			if cfg.InitialFields == nil {
+				cfg.InitialFields = make(map[string]interface{})
+			}
+			cfg.InitialFields[k] = v
+		}
+		l, err := cfg.Build(zp.AddCallerSkip(1))
+		if err != nil {
+			return err
+		}
+
+		// Update the existing zap logger instance
+		loggers[pkgName].log = l.Sugar()
+		loggers[pkgName].parent = l
+	}
+	return nil
+}
+
+// Return a list of all packages that have individually-configured loggers
+func GetPackageNames() []string {
+	i := 0
+	keys := make([]string, len(loggers))
+	for k := range loggers {
+		keys[i] = k
+		i++
+	}
+	return keys
+}
+
+// UpdateLogger updates the logger associated with a caller's package with supplied defaultFields
+func UpdateLogger(defaultFields Fields) error {
+	pkgName, _, _, _ := getCallerInfo()
+	if _, exist := loggers[pkgName]; !exist {
+		return fmt.Errorf("package-%s-not-registered", pkgName)
+	}
+
+	// Build a new logger
+	if _, exist := cfgs[pkgName]; !exist {
+		return fmt.Errorf("config-%s-not-registered", pkgName)
+	}
+
+	cfg := cfgs[pkgName]
+	for k, v := range defaultFields {
+		if cfg.InitialFields == nil {
+			cfg.InitialFields = make(map[string]interface{})
+		}
+		cfg.InitialFields[k] = v
+	}
+	l, err := cfg.Build(zp.AddCallerSkip(1))
+	if err != nil {
+		return err
+	}
+
+	// Update the existing zap logger instance
+	loggers[pkgName].log = l.Sugar()
+	loggers[pkgName].parent = l
+
+	return nil
+}
+
+func setLevel(cfg zp.Config, level LogLevel) {
+	switch level {
+	case DebugLevel:
+		cfg.Level.SetLevel(zc.DebugLevel)
+	case InfoLevel:
+		cfg.Level.SetLevel(zc.InfoLevel)
+	case WarnLevel:
+		cfg.Level.SetLevel(zc.WarnLevel)
+	case ErrorLevel:
+		cfg.Level.SetLevel(zc.ErrorLevel)
+	case FatalLevel:
+		cfg.Level.SetLevel(zc.FatalLevel)
+	default:
+		cfg.Level.SetLevel(zc.ErrorLevel)
+	}
+}
+
+//SetPackageLogLevel dynamically sets the log level of a given package to level.  This is typically invoked at an
+// application level during debugging
+func SetPackageLogLevel(packageName string, level LogLevel) {
+	// Get proper config
+	if cfg, ok := cfgs[packageName]; ok {
+		setLevel(cfg, level)
+	}
+}
+
+//SetAllLogLevel sets the log level of all registered packages to level
+func SetAllLogLevel(level LogLevel) {
+	// Get proper config
+	for _, cfg := range cfgs {
+		setLevel(cfg, level)
+	}
+}
+
+//GetPackageLogLevel returns the current log level of a package.
+func GetPackageLogLevel(packageName ...string) (LogLevel, error) {
+	var name string
+	if len(packageName) == 1 {
+		name = packageName[0]
+	} else {
+		name, _, _, _ = getCallerInfo()
+	}
+	if cfg, ok := cfgs[name]; ok {
+		return levelToLogLevel(cfg.Level.Level()), nil
+	}
+	return 0, fmt.Errorf("unknown-package-%s", name)
+}
+
+//GetDefaultLogLevel gets the log level used for packages that don't have specific loggers
+func GetDefaultLogLevel() LogLevel {
+	return levelToLogLevel(cfg.Level.Level())
+}
+
+//SetLogLevel sets the log level for the logger corresponding to the caller's package
+func SetLogLevel(level LogLevel) error {
+	pkgName, _, _, _ := getCallerInfo()
+	if _, exist := cfgs[pkgName]; !exist {
+		return fmt.Errorf("unregistered-package-%s", pkgName)
+	}
+	cfg := cfgs[pkgName]
+	setLevel(cfg, level)
+	return nil
+}
+
+//SetDefaultLogLevel sets the log level used for packages that don't have specific loggers
+func SetDefaultLogLevel(level LogLevel) {
+	setLevel(cfg, level)
+}
+
+// CleanUp flushed any buffered log entries. Applications should take care to call
+// CleanUp before exiting.
+func CleanUp() error {
+	for _, logger := range loggers {
+		if logger != nil {
+			if logger.parent != nil {
+				if err := logger.parent.Sync(); err != nil {
+					return err
+				}
+			}
+		}
+	}
+	if defaultLogger != nil {
+		if defaultLogger.parent != nil {
+			if err := defaultLogger.parent.Sync(); err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+func getCallerInfo() (string, string, string, int) {
+	// Since the caller of a log function is one stack frame before (in terms of stack higher level) the log.go
+	// filename, then first look for the last log.go filename and then grab the caller info one level higher.
+	maxLevel := 3
+	skiplevel := 3 // Level with the most empirical success to see the last log.go stack frame.
+	pc := make([]uintptr, maxLevel)
+	n := runtime.Callers(skiplevel, pc)
+	packageName := ""
+	funcName := ""
+	fileName := ""
+	var line int
+	if n == 0 {
+		return packageName, fileName, funcName, line
+	}
+	frames := runtime.CallersFrames(pc[:n])
+	var frame runtime.Frame
+	var foundFrame runtime.Frame
+	more := true
+	for more {
+		frame, more = frames.Next()
+		_, fileName = path.Split(frame.File)
+		if fileName != "log.go" {
+			foundFrame = frame // First frame after log.go in the frame stack
+			break
+		}
+	}
+	parts := strings.Split(foundFrame.Function, ".")
+	pl := len(parts)
+	if pl >= 2 {
+		funcName = parts[pl-1]
+		if parts[pl-2][0] == '(' {
+			packageName = strings.Join(parts[0:pl-2], ".")
+		} else {
+			packageName = strings.Join(parts[0:pl-1], ".")
+		}
+	}
+
+	if strings.HasSuffix(packageName, ".init") {
+		packageName = strings.TrimSuffix(packageName, ".init")
+	}
+
+	if strings.HasSuffix(fileName, ".go") {
+		fileName = strings.TrimSuffix(fileName, ".go")
+	}
+
+	return packageName, fileName, funcName, foundFrame.Line
+}
+
+// With returns a logger initialized with the key-value pairs
+func (l clogger) With(keysAndValues Fields) CLogger {
+	return clogger{log: l.log.With(serializeMap(keysAndValues)...), parent: l.parent}
+}
+
+// Debug logs a message at level Debug on the standard logger.
+func (l clogger) Debug(ctx context.Context, args ...interface{}) {
+	l.log.With(GetGlobalLFM().ExtractContextAttributes(ctx)...).Debug(args...)
+}
+
+// Debugln logs a message at level Debug on the standard logger with a line feed. Default in any case.
+func (l clogger) Debugln(ctx context.Context, args ...interface{}) {
+	l.log.With(GetGlobalLFM().ExtractContextAttributes(ctx)...).Debug(args...)
+}
+
+// Debugw logs a message at level Debug on the standard logger.
+func (l clogger) Debugf(ctx context.Context, format string, args ...interface{}) {
+	l.log.With(GetGlobalLFM().ExtractContextAttributes(ctx)...).Debugf(format, args...)
+}
+
+// Debugw logs a message with some additional context. The variadic key-value
+// pairs are treated as they are in With.
+func (l clogger) Debugw(ctx context.Context, msg string, keysAndValues Fields) {
+	if l.V(DebugLevel) {
+		l.log.With(GetGlobalLFM().ExtractContextAttributes(ctx)...).Debugw(msg, serializeMap(keysAndValues)...)
+	}
+}
+
+// Info logs a message at level Info on the standard logger.
+func (l clogger) Info(ctx context.Context, args ...interface{}) {
+	l.log.With(GetGlobalLFM().ExtractContextAttributes(ctx)...).Info(args...)
+}
+
+// Infoln logs a message at level Info on the standard logger with a line feed. Default in any case.
+func (l clogger) Infoln(ctx context.Context, args ...interface{}) {
+	l.log.With(GetGlobalLFM().ExtractContextAttributes(ctx)...).Info(args...)
+	//msg := fmt.Sprintln(args...)
+	//l.sourced().Info(msg[:len(msg)-1])
+}
+
+// Infof logs a message at level Info on the standard logger.
+func (l clogger) Infof(ctx context.Context, format string, args ...interface{}) {
+	l.log.With(GetGlobalLFM().ExtractContextAttributes(ctx)...).Infof(format, args...)
+}
+
+// Infow logs a message with some additional context. The variadic key-value
+// pairs are treated as they are in With.
+func (l clogger) Infow(ctx context.Context, msg string, keysAndValues Fields) {
+	if l.V(InfoLevel) {
+		l.log.With(GetGlobalLFM().ExtractContextAttributes(ctx)...).Infow(msg, serializeMap(keysAndValues)...)
+	}
+}
+
+// Warn logs a message at level Warn on the standard logger.
+func (l clogger) Warn(ctx context.Context, args ...interface{}) {
+	l.log.With(GetGlobalLFM().ExtractContextAttributes(ctx)...).Warn(args...)
+}
+
+// Warnln logs a message at level Warn on the standard logger with a line feed. Default in any case.
+func (l clogger) Warnln(ctx context.Context, args ...interface{}) {
+	l.log.With(GetGlobalLFM().ExtractContextAttributes(ctx)...).Warn(args...)
+}
+
+// Warnf logs a message at level Warn on the standard logger.
+func (l clogger) Warnf(ctx context.Context, format string, args ...interface{}) {
+	l.log.With(GetGlobalLFM().ExtractContextAttributes(ctx)...).Warnf(format, args...)
+}
+
+// Warnw logs a message with some additional context. The variadic key-value
+// pairs are treated as they are in With.
+func (l clogger) Warnw(ctx context.Context, msg string, keysAndValues Fields) {
+	if l.V(WarnLevel) {
+		l.log.With(GetGlobalLFM().ExtractContextAttributes(ctx)...).Warnw(msg, serializeMap(keysAndValues)...)
+	}
+}
+
+// Error logs a message at level Error on the standard logger.
+func (l clogger) Error(ctx context.Context, args ...interface{}) {
+	l.log.With(GetGlobalLFM().ExtractContextAttributes(ctx)...).Error(args...)
+}
+
+// Errorln logs a message at level Error on the standard logger with a line feed. Default in any case.
+func (l clogger) Errorln(ctx context.Context, args ...interface{}) {
+	l.log.With(GetGlobalLFM().ExtractContextAttributes(ctx)...).Error(args...)
+}
+
+// Errorf logs a message at level Error on the standard logger.
+func (l clogger) Errorf(ctx context.Context, format string, args ...interface{}) {
+	l.log.With(GetGlobalLFM().ExtractContextAttributes(ctx)...).Errorf(format, args...)
+}
+
+// Errorw logs a message with some additional context. The variadic key-value
+// pairs are treated as they are in With.
+func (l clogger) Errorw(ctx context.Context, msg string, keysAndValues Fields) {
+	if l.V(ErrorLevel) {
+		l.log.With(GetGlobalLFM().ExtractContextAttributes(ctx)...).Errorw(msg, serializeMap(keysAndValues)...)
+	}
+}
+
+// Fatal logs a message at level Fatal on the standard logger.
+func (l clogger) Fatal(ctx context.Context, args ...interface{}) {
+	l.log.With(GetGlobalLFM().ExtractContextAttributes(ctx)...).Fatal(args...)
+}
+
+// Fatalln logs a message at level Fatal on the standard logger with a line feed. Default in any case.
+func (l clogger) Fatalln(ctx context.Context, args ...interface{}) {
+	l.log.With(GetGlobalLFM().ExtractContextAttributes(ctx)...).Fatal(args...)
+}
+
+// Fatalf logs a message at level Fatal on the standard logger.
+func (l clogger) Fatalf(ctx context.Context, format string, args ...interface{}) {
+	l.log.With(GetGlobalLFM().ExtractContextAttributes(ctx)...).Fatalf(format, args...)
+}
+
+// Fatalw logs a message with some additional context. The variadic key-value
+// pairs are treated as they are in With.
+func (l clogger) Fatalw(ctx context.Context, msg string, keysAndValues Fields) {
+	if l.V(FatalLevel) {
+		l.log.With(GetGlobalLFM().ExtractContextAttributes(ctx)...).Fatalw(msg, serializeMap(keysAndValues)...)
+	}
+}
+
+// Warning logs a message at level Warn on the standard logger.
+func (l clogger) Warning(ctx context.Context, args ...interface{}) {
+	l.log.With(GetGlobalLFM().ExtractContextAttributes(ctx)...).Warn(args...)
+}
+
+// Warningln logs a message at level Warn on the standard logger with a line feed. Default in any case.
+func (l clogger) Warningln(ctx context.Context, args ...interface{}) {
+	l.log.With(GetGlobalLFM().ExtractContextAttributes(ctx)...).Warn(args...)
+}
+
+// Warningf logs a message at level Warn on the standard logger.
+func (l clogger) Warningf(ctx context.Context, format string, args ...interface{}) {
+	l.log.With(GetGlobalLFM().ExtractContextAttributes(ctx)...).Warnf(format, args...)
+}
+
+// V reports whether verbosity level l is at least the requested verbose level.
+func (l clogger) V(level LogLevel) bool {
+	return l.parent.Core().Enabled(logLevelToLevel(level))
+}
+
+// GetLogLevel returns the current level of the logger
+func (l clogger) GetLogLevel() LogLevel {
+	return levelToLogLevel(cfgs[l.packageName].Level.Level())
+}
diff --git a/vendor/github.com/opencord/voltha-lib-go/v4/pkg/log/utils.go b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/log/utils.go
new file mode 100644
index 0000000..82c3d7d
--- /dev/null
+++ b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/log/utils.go
@@ -0,0 +1,468 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// File contains utility functions to support Open Tracing in conjunction with
+// Enhanced Logging based on context propagation
+
+package log
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"github.com/opentracing/opentracing-go"
+	jtracing "github.com/uber/jaeger-client-go"
+	jcfg "github.com/uber/jaeger-client-go/config"
+	"io"
+	"os"
+	"strings"
+	"sync"
+)
+
+const (
+	RootSpanNameKey = "op-name"
+)
+
+// Global Settings governing the Log Correlation and Tracing features. Should only
+// be updated through the exposed public methods
+type LogFeaturesManager struct {
+	isTracePublishingEnabled bool
+	isLogCorrelationEnabled  bool
+	componentName            string // Name of component extracted from ENV variable
+	activeTraceAgentAddress  string
+	lock                     sync.Mutex
+}
+
+var globalLFM *LogFeaturesManager = &LogFeaturesManager{}
+
+func GetGlobalLFM() *LogFeaturesManager {
+	return globalLFM
+}
+
+// A Wrapper to utilize currently Active Tracer instance. The middleware library being used for generating
+// Spans for GRPC API calls does not support dynamically setting the Active Tracer similar to the SetGlobalTracer method
+// provided by OpenTracing API
+type ActiveTracerProxy struct {
+}
+
+func (atw ActiveTracerProxy) StartSpan(operationName string, opts ...opentracing.StartSpanOption) opentracing.Span {
+	return opentracing.GlobalTracer().StartSpan(operationName, opts...)
+}
+
+func (atw ActiveTracerProxy) Inject(sm opentracing.SpanContext, format interface{}, carrier interface{}) error {
+	return opentracing.GlobalTracer().Inject(sm, format, carrier)
+}
+
+func (atw ActiveTracerProxy) Extract(format interface{}, carrier interface{}) (opentracing.SpanContext, error) {
+	return opentracing.GlobalTracer().Extract(format, carrier)
+}
+
+// Jaeger complaint Logger instance to redirect logs to Default Logger
+type traceLogger struct {
+	logger *clogger
+}
+
+func (tl traceLogger) Error(msg string) {
+	tl.logger.Error(context.Background(), msg)
+}
+
+func (tl traceLogger) Infof(msg string, args ...interface{}) {
+	// Tracing logs should be performed only at Debug Verbosity
+	tl.logger.Debugf(context.Background(), msg, args...)
+}
+
+// Wrapper to handle correct Closer call at the time of Process Termination
+type traceCloser struct {
+}
+
+func (c traceCloser) Close() error {
+	currentActiveTracer := opentracing.GlobalTracer()
+	if currentActiveTracer != nil {
+		if jTracer, ok := currentActiveTracer.(*jtracing.Tracer); ok {
+			jTracer.Close()
+		}
+	}
+
+	return nil
+}
+
+// Method to Initialize Jaeger based Tracing client based on initial status of Tracing Publish and Log Correlation
+func (lfm *LogFeaturesManager) InitTracingAndLogCorrelation(tracePublishEnabled bool, traceAgentAddress string, logCorrelationEnabled bool) (io.Closer, error) {
+	lfm.componentName = os.Getenv("COMPONENT_NAME")
+	if lfm.componentName == "" {
+		return nil, errors.New("Unable to retrieve PoD Component Name from Runtime env")
+	}
+
+	lfm.lock.Lock()
+	defer lfm.lock.Unlock()
+
+	// Use NoopTracer when both Tracing Publishing and Log Correlation are disabled
+	if !tracePublishEnabled && !logCorrelationEnabled {
+		logger.Info(context.Background(), "Skipping Global Tracer initialization as both Trace publish and Log correlation are configured as disabled")
+		lfm.isTracePublishingEnabled = false
+		lfm.isLogCorrelationEnabled = false
+		opentracing.SetGlobalTracer(opentracing.NoopTracer{})
+		return traceCloser{}, nil
+	}
+
+	tracer, _, err := lfm.constructJaegerTracer(tracePublishEnabled, traceAgentAddress, true)
+	if err != nil {
+		return nil, err
+	}
+
+	// Initialize variables representing Active Status
+	opentracing.SetGlobalTracer(tracer)
+	lfm.isTracePublishingEnabled = tracePublishEnabled
+	lfm.activeTraceAgentAddress = traceAgentAddress
+	lfm.isLogCorrelationEnabled = logCorrelationEnabled
+	return traceCloser{}, nil
+}
+
+// Method to replace Active Tracer along with graceful closer of previous tracer
+func (lfm *LogFeaturesManager) replaceActiveTracer(tracer opentracing.Tracer) {
+	currentActiveTracer := opentracing.GlobalTracer()
+	opentracing.SetGlobalTracer(tracer)
+
+	if currentActiveTracer != nil {
+		if jTracer, ok := currentActiveTracer.(*jtracing.Tracer); ok {
+			jTracer.Close()
+		}
+	}
+}
+
+func (lfm *LogFeaturesManager) GetLogCorrelationStatus() bool {
+	lfm.lock.Lock()
+	defer lfm.lock.Unlock()
+
+	return lfm.isLogCorrelationEnabled
+}
+
+func (lfm *LogFeaturesManager) SetLogCorrelationStatus(isEnabled bool) {
+	lfm.lock.Lock()
+	defer lfm.lock.Unlock()
+
+	if isEnabled == lfm.isLogCorrelationEnabled {
+		logger.Debugf(context.Background(), "Ignoring Log Correlation Set operation with value %t; current Status same as desired", isEnabled)
+		return
+	}
+
+	if isEnabled {
+		// Construct new Tracer instance if Log Correlation has been enabled and current active tracer is a NoopTracer instance.
+		// Continue using the earlier tracer instance in case of any error
+		if _, ok := opentracing.GlobalTracer().(opentracing.NoopTracer); ok {
+			tracer, _, err := lfm.constructJaegerTracer(lfm.isTracePublishingEnabled, lfm.activeTraceAgentAddress, false)
+			if err != nil {
+				logger.Warnf(context.Background(), "Log Correlation Enable operation failed with error: %s", err.Error())
+				return
+			}
+
+			lfm.replaceActiveTracer(tracer)
+		}
+
+		lfm.isLogCorrelationEnabled = true
+		logger.Info(context.Background(), "Log Correlation has been enabled")
+
+	} else {
+		// Switch to NoopTracer when Log Correlation has been disabled and Tracing Publish is already disabled
+		if _, ok := opentracing.GlobalTracer().(opentracing.NoopTracer); !ok && !lfm.isTracePublishingEnabled {
+			lfm.replaceActiveTracer(opentracing.NoopTracer{})
+		}
+
+		lfm.isLogCorrelationEnabled = false
+		logger.Info(context.Background(), "Log Correlation has been disabled")
+	}
+}
+
+func (lfm *LogFeaturesManager) GetTracePublishingStatus() bool {
+	lfm.lock.Lock()
+	defer lfm.lock.Unlock()
+
+	return lfm.isTracePublishingEnabled
+}
+
+func (lfm *LogFeaturesManager) SetTracePublishingStatus(isEnabled bool) {
+	lfm.lock.Lock()
+	defer lfm.lock.Unlock()
+
+	if isEnabled == lfm.isTracePublishingEnabled {
+		logger.Debugf(context.Background(), "Ignoring Trace Publishing Set operation with value %t; current Status same as desired", isEnabled)
+		return
+	}
+
+	if isEnabled {
+		// Construct new Tracer instance if Tracing Publish has been enabled (even if a Jaeger instance is already active)
+		// This is needed to ensure that a fresh lookup of Jaeger Agent address is performed again while performing
+		// Disable-Enable of Tracing
+		tracer, _, err := lfm.constructJaegerTracer(isEnabled, lfm.activeTraceAgentAddress, false)
+		if err != nil {
+			logger.Warnf(context.Background(), "Trace Publishing Enable operation failed with error: %s", err.Error())
+			return
+		}
+		lfm.replaceActiveTracer(tracer)
+
+		lfm.isTracePublishingEnabled = true
+		logger.Info(context.Background(), "Tracing Publishing has been enabled")
+	} else {
+		// Switch to NoopTracer when Tracing Publish has been disabled and Log Correlation is already disabled
+		if !lfm.isLogCorrelationEnabled {
+			lfm.replaceActiveTracer(opentracing.NoopTracer{})
+		} else {
+			// Else construct a new Jaeger Instance with publishing disabled
+			tracer, _, err := lfm.constructJaegerTracer(isEnabled, lfm.activeTraceAgentAddress, false)
+			if err != nil {
+				logger.Warnf(context.Background(), "Trace Publishing Disable operation failed with error: %s", err.Error())
+				return
+			}
+			lfm.replaceActiveTracer(tracer)
+		}
+
+		lfm.isTracePublishingEnabled = false
+		logger.Info(context.Background(), "Tracing Publishing has been disabled")
+	}
+}
+
+// Method to contruct a new Jaeger Tracer instance based on given Trace Agent address and Publish status.
+// The last attribute indicates whether to use Loopback IP for creating Jaeger Client when the DNS lookup
+// of supplied Trace Agent address has failed. It is fine to fallback during the initialization step, but
+// not later (when enabling/disabling the status dynamically)
+func (lfm *LogFeaturesManager) constructJaegerTracer(tracePublishEnabled bool, traceAgentAddress string, fallbackToLoopbackAllowed bool) (opentracing.Tracer, io.Closer, error) {
+	cfg := jcfg.Configuration{ServiceName: lfm.componentName}
+
+	var err error
+	var jReporterConfig jcfg.ReporterConfig
+	var jReporterCfgOption jtracing.Reporter
+
+	logger.Info(context.Background(), "Constructing new Jaeger Tracer instance")
+
+	// Attempt Trace Agent Address first; will fallback to Loopback IP if it fails
+	jReporterConfig = jcfg.ReporterConfig{LocalAgentHostPort: traceAgentAddress, LogSpans: true}
+	jReporterCfgOption, err = jReporterConfig.NewReporter(lfm.componentName, jtracing.NewNullMetrics(), traceLogger{logger: logger.(*clogger)})
+
+	if err != nil {
+		if !fallbackToLoopbackAllowed {
+			return nil, nil, errors.New("Reporter Creation for given Trace Agent address " + traceAgentAddress + " failed with error : " + err.Error())
+		}
+
+		logger.Infow(context.Background(), "Unable to create Reporter with given Trace Agent address",
+			Fields{"error": err, "address": traceAgentAddress})
+		// The Reporter initialization may fail due to Invalid Agent address or non-existent Agent (DNS lookup failure).
+		// It is essential for Tracer Instance to still start for correct Span propagation needed for log correlation.
+		// Thus, falback to use loopback IP for Reporter initialization before throwing back any error
+		tracePublishEnabled = false
+
+		jReporterConfig.LocalAgentHostPort = "127.0.0.1:6831"
+		jReporterCfgOption, err = jReporterConfig.NewReporter(lfm.componentName, jtracing.NewNullMetrics(), traceLogger{logger: logger.(*clogger)})
+		if err != nil {
+			return nil, nil, errors.New("Failed to initialize Jaeger Tracing due to Reporter creation error : " + err.Error())
+		}
+	}
+
+	// To start with, we are using Constant Sampling type
+	samplerParam := 0 // 0: Do not publish span, 1: Publish
+	if tracePublishEnabled {
+		samplerParam = 1
+	}
+	jSamplerConfig := jcfg.SamplerConfig{Type: "const", Param: float64(samplerParam)}
+	jSamplerCfgOption, err := jSamplerConfig.NewSampler(lfm.componentName, jtracing.NewNullMetrics())
+	if err != nil {
+		return nil, nil, errors.New("Unable to create Sampler : " + err.Error())
+	}
+
+	return cfg.NewTracer(jcfg.Reporter(jReporterCfgOption), jcfg.Sampler(jSamplerCfgOption))
+}
+
+func TerminateTracing(c io.Closer) {
+	err := c.Close()
+	if err != nil {
+		logger.Error(context.Background(), "error-while-closing-jaeger-tracer", Fields{"err": err})
+	}
+}
+
+// Extracts details of Execution Context as log fields from the Tracing Span injected into the
+// context instance. Following log fields are extracted:
+// 1. Operation Name : key as 'op-name' and value as Span operation name
+// 2. Operation Id : key as 'op-id' and value as 64 bit Span Id in hex digits string
+//
+// Additionally, any tags present in Span are also extracted to use as log fields e.g. device-id.
+//
+// If no Span is found associated with context, blank slice is returned without any log fields
+func (lfm *LogFeaturesManager) ExtractContextAttributes(ctx context.Context) []interface{} {
+	if !lfm.isLogCorrelationEnabled {
+		return make([]interface{}, 0)
+	}
+
+	attrMap := make(map[string]interface{})
+
+	if ctx != nil {
+		if span := opentracing.SpanFromContext(ctx); span != nil {
+			if jspan, ok := span.(*jtracing.Span); ok {
+				// Add Log fields for operation identified by Root Level Span (Trace)
+				opId := fmt.Sprintf("%016x", jspan.SpanContext().TraceID().Low) // Using Sprintf to avoid removal of leading 0s
+				opName := jspan.BaggageItem(RootSpanNameKey)
+
+				taskId := fmt.Sprintf("%016x", uint64(jspan.SpanContext().SpanID())) // Using Sprintf to avoid removal of leading 0s
+				taskName := jspan.OperationName()
+
+				if opName == "" {
+					span.SetBaggageItem(RootSpanNameKey, taskName)
+					opName = taskName
+				}
+
+				attrMap["op-id"] = opId
+				attrMap["op-name"] = opName
+
+				// Add Log fields for task identified by Current Span, if it is different
+				// than operation
+				if taskId != opId {
+					attrMap["task-id"] = taskId
+					attrMap["task-name"] = taskName
+				}
+
+				for k, v := range jspan.Tags() {
+					// Ignore the special tags added by Jaeger, middleware (sampler.type, span.*) present in the span
+					if strings.HasPrefix(k, "sampler.") || strings.HasPrefix(k, "span.") || k == "component" {
+						continue
+					}
+
+					attrMap[k] = v
+				}
+
+				processBaggageItems := func(k, v string) bool {
+					if k != "rpc-span-name" {
+						attrMap[k] = v
+					}
+					return true
+				}
+
+				jspan.SpanContext().ForeachBaggageItem(processBaggageItems)
+			}
+		}
+	}
+
+	return serializeMap(attrMap)
+}
+
+// Method to inject additional log fields into Span e.g. device-id
+func EnrichSpan(ctx context.Context, keyAndValues ...Fields) {
+	span := opentracing.SpanFromContext(ctx)
+	if span != nil {
+		if jspan, ok := span.(*jtracing.Span); ok {
+			// Inject as a BaggageItem when the Span is the Root Span so that it propagates
+			// across the components along with Root Span (called as Trace)
+			// Else, inject as a Tag so that it is attached to the Child Task
+			isRootSpan := false
+			if jspan.SpanContext().TraceID().String() == jspan.SpanContext().SpanID().String() {
+				isRootSpan = true
+			}
+
+			for _, field := range keyAndValues {
+				for k, v := range field {
+					if isRootSpan {
+						span.SetBaggageItem(k, v.(string))
+					} else {
+						span.SetTag(k, v)
+					}
+				}
+			}
+		}
+	}
+}
+
+// Method to inject Error into the Span in event of any operation failure
+func MarkSpanError(ctx context.Context, err error) {
+	span := opentracing.SpanFromContext(ctx)
+	if span != nil {
+		span.SetTag("error", true)
+		span.SetTag("err", err)
+	}
+}
+
+// Creates a Child Span from Parent Span embedded in passed context. Should be used before starting a new major
+// operation in Synchronous or Asynchronous mode (go routine), such as following:
+// 1. Start of all implemented External API methods unless using a interceptor for auto-injection of Span (Server side impl)
+// 2. Just before calling an Third-Party lib which is invoking a External API (etcd, kafka)
+// 3. In start of a Go Routine responsible for performing a major task involving significant duration
+// 4. Any method which is suspected to be time consuming...
+func CreateChildSpan(ctx context.Context, taskName string, keyAndValues ...Fields) (opentracing.Span, context.Context) {
+	if !GetGlobalLFM().GetLogCorrelationStatus() && !GetGlobalLFM().GetTracePublishingStatus() {
+		return opentracing.NoopTracer{}.StartSpan(taskName), ctx
+	}
+
+	parentSpan := opentracing.SpanFromContext(ctx)
+	childSpan, newCtx := opentracing.StartSpanFromContext(ctx, taskName)
+
+	if parentSpan == nil || parentSpan.BaggageItem(RootSpanNameKey) == "" {
+		childSpan.SetBaggageItem(RootSpanNameKey, taskName)
+	}
+
+	EnrichSpan(newCtx, keyAndValues...)
+	return childSpan, newCtx
+}
+
+// Creates a Async Child Span with Follows-From relationship from Parent Span embedded in passed context.
+// Should be used only in scenarios when
+// a) There is dis-continuation in execution and thus result of Child span does not affect the Parent flow at all
+// b) The execution of Child Span is guaranteed to start after the completion of Parent Span
+// In case of any confusion, use CreateChildSpan method
+// Some situations where this method would be suitable includes Kafka Async RPC call, Propagation of Event across
+// a channel etc.
+func CreateAsyncSpan(ctx context.Context, taskName string, keyAndValues ...Fields) (opentracing.Span, context.Context) {
+	if !GetGlobalLFM().GetLogCorrelationStatus() && !GetGlobalLFM().GetTracePublishingStatus() {
+		return opentracing.NoopTracer{}.StartSpan(taskName), ctx
+	}
+
+	var asyncSpan opentracing.Span
+	var newCtx context.Context
+
+	parentSpan := opentracing.SpanFromContext(ctx)
+
+	// We should always be creating Aysnc span from a Valid parent span. If not, create a Child span instead
+	if parentSpan == nil {
+		logger.Warn(context.Background(), "Async span must be created with a Valid parent span only")
+		asyncSpan, newCtx = opentracing.StartSpanFromContext(ctx, taskName)
+	} else {
+		// Use Background context as the base for Follows-from case; else new span is getting both Child and FollowsFrom relationship
+		asyncSpan, newCtx = opentracing.StartSpanFromContext(context.Background(), taskName, opentracing.FollowsFrom(parentSpan.Context()))
+	}
+
+	if parentSpan == nil || parentSpan.BaggageItem(RootSpanNameKey) == "" {
+		asyncSpan.SetBaggageItem(RootSpanNameKey, taskName)
+	}
+
+	EnrichSpan(newCtx, keyAndValues...)
+	return asyncSpan, newCtx
+}
+
+// Extracts the span from Source context and injects into the supplied Target context.
+// This should be used in situations wherein we are calling a time-sensitive operation (etcd update) and hence
+// had a context.Background() used earlier to avoid any cancellation/timeout of operation by passed context.
+// This will allow propagation of span with a different base context (and not the original context)
+func WithSpanFromContext(targetCtx, sourceCtx context.Context) context.Context {
+	span := opentracing.SpanFromContext(sourceCtx)
+	return opentracing.ContextWithSpan(targetCtx, span)
+}
+
+// Utility method to convert log Fields into array of interfaces expected by zap logger methods
+func serializeMap(fields Fields) []interface{} {
+	data := make([]interface{}, len(fields)*2)
+	i := 0
+	for k, v := range fields {
+		data[i] = k
+		data[i+1] = v
+		i = i + 2
+	}
+	return data
+}
diff --git a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/common.go b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/ponresourcemanager/common.go
similarity index 79%
copy from vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/common.go
copy to vendor/github.com/opencord/voltha-lib-go/v4/pkg/ponresourcemanager/common.go
index a5a79ae..1c9a5b1 100644
--- a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/common.go
+++ b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/ponresourcemanager/common.go
@@ -13,22 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package db
+package ponresourcemanager
 
 import (
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
+	"github.com/opencord/voltha-lib-go/v4/pkg/log"
 )
 
-const (
-	logLevel = log.ErrorLevel
-)
-
-var logger log.Logger
+var logger log.CLogger
 
 func init() {
 	// Setup this package so that it's log level can be modified at run time
 	var err error
-	logger, err = log.AddPackage(log.JSON, logLevel, log.Fields{"pkg": "db"})
+	logger, err = log.RegisterPackage(log.JSON, log.ErrorLevel, log.Fields{})
 	if err != nil {
 		panic(err)
 	}
diff --git a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/ponresourcemanager/ponresourcemanager.go b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/ponresourcemanager/ponresourcemanager.go
similarity index 79%
rename from vendor/github.com/opencord/voltha-lib-go/v3/pkg/ponresourcemanager/ponresourcemanager.go
rename to vendor/github.com/opencord/voltha-lib-go/v4/pkg/ponresourcemanager/ponresourcemanager.go
index 79fefc5..bbfebe3 100644
--- a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/ponresourcemanager/ponresourcemanager.go
+++ b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/ponresourcemanager/ponresourcemanager.go
@@ -22,13 +22,13 @@
 	"encoding/json"
 	"errors"
 	"fmt"
-	"strconv"
+	"time"
 
 	bitmap "github.com/boljen/go-bitmap"
-	"github.com/opencord/voltha-lib-go/v3/pkg/db"
-	"github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore"
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-	tp "github.com/opencord/voltha-lib-go/v3/pkg/techprofile"
+	"github.com/opencord/voltha-lib-go/v4/pkg/db"
+	"github.com/opencord/voltha-lib-go/v4/pkg/db/kvstore"
+	"github.com/opencord/voltha-lib-go/v4/pkg/log"
+	tp "github.com/opencord/voltha-lib-go/v4/pkg/techprofile"
 )
 
 const (
@@ -124,7 +124,7 @@
 	POOL            = "pool"
 	NUM_OF_PON_INTF = 16
 
-	KVSTORE_RETRY_TIMEOUT = 5
+	KVSTORE_RETRY_TIMEOUT = 5 * time.Second
 	//Path on the KV store for storing reserved gem ports
 	//Format: reserved_gemport_ids
 	RESERVED_GEMPORT_IDS_PATH = "reserved_gemport_ids"
@@ -139,8 +139,7 @@
 	DeviceType       string
 	DeviceID         string
 	Backend          string // ETCD, or consul
-	Host             string // host ip of the KV store
-	Port             int    // port number for the KV store
+	Address          string // address of the KV store
 	OLTModel         string
 	KVStore          *db.Backend
 	KVStoreForConfig *db.Backend
@@ -155,24 +154,23 @@
 	Globalorlocal      string
 }
 
-func newKVClient(storeType string, address string, timeout int) (kvstore.Client, error) {
-	log.Infow("kv-store-type", log.Fields{"store": storeType})
+func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
+	logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
 	switch storeType {
 	case "consul":
-		return kvstore.NewConsulClient(address, timeout)
+		return kvstore.NewConsulClient(ctx, address, timeout)
 	case "etcd":
-		return kvstore.NewEtcdClient(address, timeout)
+		return kvstore.NewEtcdClient(ctx, address, timeout, log.WarnLevel)
 	}
 	return nil, errors.New("unsupported-kv-store")
 }
 
-func SetKVClient(Technology string, Backend string, Host string, Port int, configClient bool) *db.Backend {
-	addr := Host + ":" + strconv.Itoa(Port)
+func SetKVClient(ctx context.Context, Technology string, Backend string, Addr string, configClient bool) *db.Backend {
 	// TODO : Make sure direct call to NewBackend is working fine with backend , currently there is some
 	// issue between kv store and backend , core is not calling NewBackend directly
-	kvClient, err := newKVClient(Backend, addr, KVSTORE_RETRY_TIMEOUT)
+	kvClient, err := newKVClient(ctx, Backend, Addr, KVSTORE_RETRY_TIMEOUT)
 	if err != nil {
-		log.Fatalw("Failed to init KV client\n", log.Fields{"err": err})
+		logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
 		return nil
 	}
 
@@ -186,8 +184,7 @@
 	kvbackend := &db.Backend{
 		Client:     kvClient,
 		StoreType:  Backend,
-		Host:       Host,
-		Port:       Port,
+		Address:    Addr,
 		Timeout:    KVSTORE_RETRY_TIMEOUT,
 		PathPrefix: pathPrefix}
 
@@ -195,28 +192,27 @@
 }
 
 // NewPONResourceManager creates a new PON resource manager.
-func NewPONResourceManager(Technology string, DeviceType string, DeviceID string, Backend string, Host string, Port int) (*PONResourceManager, error) {
+func NewPONResourceManager(ctx context.Context, Technology string, DeviceType string, DeviceID string, Backend string, Address string) (*PONResourceManager, error) {
 	var PONMgr PONResourceManager
 	PONMgr.Technology = Technology
 	PONMgr.DeviceType = DeviceType
 	PONMgr.DeviceID = DeviceID
 	PONMgr.Backend = Backend
-	PONMgr.Host = Host
-	PONMgr.Port = Port
-	PONMgr.KVStore = SetKVClient(Technology, Backend, Host, Port, false)
+	PONMgr.Address = Address
+	PONMgr.KVStore = SetKVClient(ctx, Technology, Backend, Address, false)
 	if PONMgr.KVStore == nil {
-		log.Error("KV Client initilization failed")
+		logger.Error(ctx, "KV Client initilization failed")
 		return nil, errors.New("Failed to init KV client")
 	}
 	// init kv client to read from the config path
-	PONMgr.KVStoreForConfig = SetKVClient(Technology, Backend, Host, Port, true)
+	PONMgr.KVStoreForConfig = SetKVClient(ctx, Technology, Backend, Address, true)
 	if PONMgr.KVStoreForConfig == nil {
-		log.Error("KV Config Client initilization failed")
+		logger.Error(ctx, "KV Config Client initilization failed")
 		return nil, errors.New("Failed to init KV Config client")
 	}
 	// Initialize techprofile for this technology
-	if PONMgr.TechProfileMgr, _ = tp.NewTechProfile(&PONMgr, Backend, Host, Port); PONMgr.TechProfileMgr == nil {
-		log.Error("Techprofile initialization failed")
+	if PONMgr.TechProfileMgr, _ = tp.NewTechProfile(ctx, &PONMgr, Backend, Address); PONMgr.TechProfileMgr == nil {
+		logger.Error(ctx, "Techprofile initialization failed")
 		return nil, errors.New("Failed to init tech profile")
 	}
 	PONMgr.PonResourceRanges = make(map[string]interface{})
@@ -244,36 +240,36 @@
 	// Try to initialize the PON Resource Ranges from KV store based on the
 	// OLT model key, if available
 	if PONRMgr.OLTModel == "" {
-		log.Error("Failed to get OLT model")
+		logger.Error(ctx, "Failed to get OLT model")
 		return false
 	}
 	Path := fmt.Sprintf(PON_RESOURCE_RANGE_CONFIG_PATH, PONRMgr.OLTModel)
 	//get resource from kv store
 	Result, err := PONRMgr.KVStore.Get(ctx, Path)
 	if err != nil {
-		log.Debugf("Error in fetching resource %s from KV strore", Path)
+		logger.Debugf(ctx, "Error in fetching resource %s from KV strore", Path)
 		return false
 	}
 	if Result == nil {
-		log.Debug("There may be no resources in the KV store in case of fresh bootup, return true")
+		logger.Debug(ctx, "There may be no resources in the KV store in case of fresh bootup, return true")
 		return false
 	}
 	//update internal ranges from kv ranges. If there are missing
 	// values in the KV profile, continue to use the defaults
 	Value, err := ToByte(Result.Value)
 	if err != nil {
-		log.Error("Failed to convert kvpair to byte string")
+		logger.Error(ctx, "Failed to convert kvpair to byte string")
 		return false
 	}
 	if err := json.Unmarshal(Value, &PONRMgr.PonResourceRanges); err != nil {
-		log.Error("Failed to Unmarshal json byte")
+		logger.Error(ctx, "Failed to Unmarshal json byte")
 		return false
 	}
-	log.Debug("Init resource ranges from kvstore success")
+	logger.Debug(ctx, "Init resource ranges from kvstore success")
 	return true
 }
 
-func (PONRMgr *PONResourceManager) UpdateRanges(StartIDx string, StartID uint32, EndIDx string, EndID uint32,
+func (PONRMgr *PONResourceManager) UpdateRanges(ctx context.Context, StartIDx string, StartID uint32, EndIDx string, EndID uint32,
 	SharedIDx string, SharedPoolID uint32, RMgr *PONResourceManager) {
 	/*
 	   Update the ranges for all reosurce type in the intermnal maps
@@ -285,7 +281,7 @@
 	   param: shared pool id
 	   param: global resource manager
 	*/
-	log.Debugf("update ranges for %s, %d", StartIDx, StartID)
+	logger.Debugf(ctx, "update ranges for %s, %d", StartIDx, StartID)
 
 	if StartID != 0 {
 		if (PONRMgr.PonResourceRanges[StartIDx] == nil) || (PONRMgr.PonResourceRanges[StartIDx].(uint32) < StartID) {
@@ -305,7 +301,8 @@
 	}
 }
 
-func (PONRMgr *PONResourceManager) InitDefaultPONResourceRanges(ONUIDStart uint32,
+func (PONRMgr *PONResourceManager) InitDefaultPONResourceRanges(ctx context.Context,
+	ONUIDStart uint32,
 	ONUIDEnd uint32,
 	ONUIDSharedPoolID uint32,
 	AllocIDStart uint32,
@@ -339,12 +336,12 @@
 	  :param num_of_pon_ports: number of PON ports
 	  :param intf_ids: interfaces serviced by this manager
 	*/
-	PONRMgr.UpdateRanges(ONU_ID_START_IDX, ONUIDStart, ONU_ID_END_IDX, ONUIDEnd, ONU_ID_SHARED_IDX, ONUIDSharedPoolID, nil)
-	PONRMgr.UpdateRanges(ALLOC_ID_START_IDX, AllocIDStart, ALLOC_ID_END_IDX, AllocIDEnd, ALLOC_ID_SHARED_IDX, AllocIDSharedPoolID, nil)
-	PONRMgr.UpdateRanges(GEMPORT_ID_START_IDX, GEMPortIDStart, GEMPORT_ID_END_IDX, GEMPortIDEnd, GEMPORT_ID_SHARED_IDX, GEMPortIDSharedPoolID, nil)
-	PONRMgr.UpdateRanges(FLOW_ID_START_IDX, FlowIDStart, FLOW_ID_END_IDX, FlowIDEnd, FLOW_ID_SHARED_IDX, FlowIDSharedPoolID, nil)
-	PONRMgr.UpdateRanges(UNI_ID_START_IDX, UNIIDStart, UNI_ID_END_IDX, UNIIDEnd, "", 0, nil)
-	log.Debug("Initialize default range values")
+	PONRMgr.UpdateRanges(ctx, ONU_ID_START_IDX, ONUIDStart, ONU_ID_END_IDX, ONUIDEnd, ONU_ID_SHARED_IDX, ONUIDSharedPoolID, nil)
+	PONRMgr.UpdateRanges(ctx, ALLOC_ID_START_IDX, AllocIDStart, ALLOC_ID_END_IDX, AllocIDEnd, ALLOC_ID_SHARED_IDX, AllocIDSharedPoolID, nil)
+	PONRMgr.UpdateRanges(ctx, GEMPORT_ID_START_IDX, GEMPortIDStart, GEMPORT_ID_END_IDX, GEMPortIDEnd, GEMPORT_ID_SHARED_IDX, GEMPortIDSharedPoolID, nil)
+	PONRMgr.UpdateRanges(ctx, FLOW_ID_START_IDX, FlowIDStart, FLOW_ID_END_IDX, FlowIDEnd, FLOW_ID_SHARED_IDX, FlowIDSharedPoolID, nil)
+	PONRMgr.UpdateRanges(ctx, UNI_ID_START_IDX, UNIIDStart, UNI_ID_END_IDX, UNIIDEnd, "", 0, nil)
+	logger.Debug(ctx, "Initialize default range values")
 	var i uint32
 	if IntfIDs == nil {
 		for i = 0; i < NoOfPONPorts; i++ {
@@ -360,7 +357,7 @@
 
 	//Initialize resource pool for all PON ports.
 
-	log.Debug("Init resource ranges")
+	logger.Debug(ctx, "Init resource ranges")
 
 	var err error
 	for _, Intf := range PONRMgr.IntfIDs {
@@ -371,7 +368,7 @@
 		if err = PONRMgr.InitResourceIDPool(ctx, Intf, ONU_ID,
 			PONRMgr.PonResourceRanges[ONU_ID_START_IDX].(uint32),
 			PONRMgr.PonResourceRanges[ONU_ID_END_IDX].(uint32)); err != nil {
-			log.Error("Failed to init ONU ID resource pool")
+			logger.Error(ctx, "Failed to init ONU ID resource pool")
 			return err
 		}
 		if SharedPoolID != 0 {
@@ -387,7 +384,7 @@
 		if err = PONRMgr.InitResourceIDPool(ctx, Intf, ALLOC_ID,
 			PONRMgr.PonResourceRanges[ALLOC_ID_START_IDX].(uint32),
 			PONRMgr.PonResourceRanges[ALLOC_ID_END_IDX].(uint32)); err != nil {
-			log.Error("Failed to init ALLOC ID resource pool ")
+			logger.Error(ctx, "Failed to init ALLOC ID resource pool ")
 			return err
 		}
 		if SharedPoolID != 0 {
@@ -402,7 +399,7 @@
 		if err = PONRMgr.InitResourceIDPool(ctx, Intf, GEMPORT_ID,
 			PONRMgr.PonResourceRanges[GEMPORT_ID_START_IDX].(uint32),
 			PONRMgr.PonResourceRanges[GEMPORT_ID_END_IDX].(uint32)); err != nil {
-			log.Error("Failed to init GEMPORT ID resource pool")
+			logger.Error(ctx, "Failed to init GEMPORT ID resource pool")
 			return err
 		}
 		if SharedPoolID != 0 {
@@ -418,7 +415,7 @@
 		if err = PONRMgr.InitResourceIDPool(ctx, Intf, FLOW_ID,
 			PONRMgr.PonResourceRanges[FLOW_ID_START_IDX].(uint32),
 			PONRMgr.PonResourceRanges[FLOW_ID_END_IDX].(uint32)); err != nil {
-			log.Error("Failed to init FLOW ID resource pool")
+			logger.Error(ctx, "Failed to init FLOW ID resource pool")
 			return err
 		}
 		if SharedPoolID != 0 {
@@ -432,7 +429,7 @@
 
 	//Clear resource pool for all PON ports.
 
-	log.Debug("Clear resource ranges")
+	logger.Debug(ctx, "Clear resource ranges")
 
 	for _, Intf := range PONRMgr.IntfIDs {
 		SharedPoolID := PONRMgr.PonResourceRanges[ONU_ID_SHARED_IDX].(uint32)
@@ -440,7 +437,7 @@
 			Intf = SharedPoolID
 		}
 		if status := PONRMgr.ClearResourceIDPool(ctx, Intf, ONU_ID); !status {
-			log.Error("Failed to clear ONU ID resource pool")
+			logger.Error(ctx, "Failed to clear ONU ID resource pool")
 			return errors.New("Failed to clear ONU ID resource pool")
 		}
 		if SharedPoolID != 0 {
@@ -454,7 +451,7 @@
 			Intf = SharedPoolID
 		}
 		if status := PONRMgr.ClearResourceIDPool(ctx, Intf, ALLOC_ID); !status {
-			log.Error("Failed to clear ALLOC ID resource pool ")
+			logger.Error(ctx, "Failed to clear ALLOC ID resource pool ")
 			return errors.New("Failed to clear ALLOC ID resource pool")
 		}
 		if SharedPoolID != 0 {
@@ -467,7 +464,7 @@
 			Intf = SharedPoolID
 		}
 		if status := PONRMgr.ClearResourceIDPool(ctx, Intf, GEMPORT_ID); !status {
-			log.Error("Failed to clear GEMPORT ID resource pool")
+			logger.Error(ctx, "Failed to clear GEMPORT ID resource pool")
 			return errors.New("Failed to clear GEMPORT ID resource pool")
 		}
 		if SharedPoolID != 0 {
@@ -481,7 +478,7 @@
 			Intf = SharedPoolID
 		}
 		if status := PONRMgr.ClearResourceIDPool(ctx, Intf, FLOW_ID); !status {
-			log.Error("Failed to clear FLOW ID resource pool")
+			logger.Error(ctx, "Failed to clear FLOW ID resource pool")
 			return errors.New("Failed to clear FLOW ID resource pool")
 		}
 		if SharedPoolID != 0 {
@@ -508,9 +505,9 @@
 		return SharedResourceMgr.InitResourceIDPool(ctx, Intf, ResourceType, StartID, EndID)
 	}
 
-	Path := PONRMgr.GetPath(Intf, ResourceType)
+	Path := PONRMgr.GetPath(ctx, Intf, ResourceType)
 	if Path == "" {
-		log.Errorf("Failed to get path for resource type %s", ResourceType)
+		logger.Errorf(ctx, "Failed to get path for resource type %s", ResourceType)
 		return fmt.Errorf("Failed to get path for resource type %s", ResourceType)
 	}
 
@@ -518,7 +515,7 @@
 	//checked for its presence if not kv store update happens
 	Res, err := PONRMgr.GetResource(ctx, Path)
 	if (err == nil) && (Res != nil) {
-		log.Debugf("Resource %s already present in store ", Path)
+		logger.Debugf(ctx, "Resource %s already present in store ", Path)
 		return nil
 	} else {
 		var excluded []uint32
@@ -526,23 +523,23 @@
 			//get gem port ids defined in the KV store, if any, and exclude them from the gem port id pool
 			if reservedGemPortIds, defined := PONRMgr.getReservedGemPortIdsFromKVStore(ctx); defined {
 				excluded = reservedGemPortIds
-				log.Debugw("Excluding some ports from GEM port id pool", log.Fields{"excluded gem ports": excluded})
+				logger.Debugw(ctx, "Excluding some ports from GEM port id pool", log.Fields{"excluded gem ports": excluded})
 			}
 		}
-		FormatResult, err := PONRMgr.FormatResource(Intf, StartID, EndID, excluded)
+		FormatResult, err := PONRMgr.FormatResource(ctx, Intf, StartID, EndID, excluded)
 		if err != nil {
-			log.Errorf("Failed to format resource")
+			logger.Errorf(ctx, "Failed to format resource")
 			return err
 		}
 		// Add resource as json in kv store.
 		err = PONRMgr.KVStore.Put(ctx, Path, FormatResult)
 		if err == nil {
-			log.Debug("Successfuly posted to kv store")
+			logger.Debug(ctx, "Successfuly posted to kv store")
 			return err
 		}
 	}
 
-	log.Debug("Error initializing pool")
+	logger.Debug(ctx, "Error initializing pool")
 
 	return err
 }
@@ -552,7 +549,7 @@
 	// read reserved gem ports from the config path
 	KvPair, err := PONRMgr.KVStoreForConfig.Get(ctx, RESERVED_GEMPORT_IDS_PATH)
 	if err != nil {
-		log.Errorw("Unable to get reserved GEM port ids from the kv store", log.Fields{"err": err})
+		logger.Errorw(ctx, "Unable to get reserved GEM port ids from the kv store", log.Fields{"err": err})
 		return reservedGemPortIds, false
 	}
 	if KvPair == nil || KvPair.Value == nil {
@@ -561,17 +558,17 @@
 	}
 	Val, err := kvstore.ToByte(KvPair.Value)
 	if err != nil {
-		log.Errorw("Failed to convert reserved gem port ids into byte array", log.Fields{"err": err})
+		logger.Errorw(ctx, "Failed to convert reserved gem port ids into byte array", log.Fields{"err": err})
 		return reservedGemPortIds, false
 	}
 	if err = json.Unmarshal(Val, &reservedGemPortIds); err != nil {
-		log.Errorw("Failed to unmarshal reservedGemPortIds", log.Fields{"err": err})
+		logger.Errorw(ctx, "Failed to unmarshal reservedGemPortIds", log.Fields{"err": err})
 		return reservedGemPortIds, false
 	}
 	return reservedGemPortIds, true
 }
 
-func (PONRMgr *PONResourceManager) FormatResource(IntfID uint32, StartIDx uint32, EndIDx uint32,
+func (PONRMgr *PONResourceManager) FormatResource(ctx context.Context, IntfID uint32, StartIDx uint32, EndIDx uint32,
 	Excluded []uint32) ([]byte, error) {
 	/*
 	   Format resource as json.
@@ -593,22 +590,22 @@
 	*/
 	var TSData *bitmap.Threadsafe
 	if TSData = bitmap.NewTS(int(EndIDx)); TSData == nil {
-		log.Error("Failed to create a bitmap")
+		logger.Error(ctx, "Failed to create a bitmap")
 		return nil, errors.New("Failed to create bitmap")
 	}
 	for _, excludedID := range Excluded {
 		if excludedID < StartIDx || excludedID > EndIDx {
-			log.Warnf("Cannot reserve %d. It must be in the range of [%d, %d]", excludedID,
+			logger.Warnf(ctx, "Cannot reserve %d. It must be in the range of [%d, %d]", excludedID,
 				StartIDx, EndIDx)
 			continue
 		}
-		PONRMgr.reserveID(TSData, StartIDx, excludedID)
+		PONRMgr.reserveID(ctx, TSData, StartIDx, excludedID)
 	}
 	Resource[POOL] = TSData.Data(false) //we pass false so as the TSData lib api does not do a copy of the data and return
 
 	Value, err := json.Marshal(Resource)
 	if err != nil {
-		log.Errorf("Failed to marshall resource")
+		logger.Errorf(ctx, "Failed to marshall resource")
 		return nil, err
 	}
 	return Value, err
@@ -628,7 +625,7 @@
 
 	Resource, err := PONRMgr.KVStore.Get(ctx, Path)
 	if (err != nil) || (Resource == nil) {
-		log.Debugf("Resource  unavailable at %s", Path)
+		logger.Debugf(ctx, "Resource  unavailable at %s", Path)
 		return nil, err
 	}
 
@@ -640,7 +637,7 @@
 	// decode resource fetched from backend store to dictionary
 	err = json.Unmarshal(Value, &Result)
 	if err != nil {
-		log.Error("Failed to decode resource")
+		logger.Error(ctx, "Failed to decode resource")
 		return Result, err
 	}
 	/*
@@ -650,20 +647,20 @@
 	*/
 	Str, err = ToString(Result[POOL])
 	if err != nil {
-		log.Error("Failed to conver to kv pair to string")
+		logger.Error(ctx, "Failed to conver to kv pair to string")
 		return Result, err
 	}
 	Decode64, _ := base64.StdEncoding.DecodeString(Str)
 	Result[POOL], err = ToByte(Decode64)
 	if err != nil {
-		log.Error("Failed to convert resource pool to byte")
+		logger.Error(ctx, "Failed to convert resource pool to byte")
 		return Result, err
 	}
 
 	return Result, err
 }
 
-func (PONRMgr *PONResourceManager) GetPath(IntfID uint32, ResourceType string) string {
+func (PONRMgr *PONResourceManager) GetPath(ctx context.Context, IntfID uint32, ResourceType string) string {
 	/*
 	   Get path for given resource type.
 	   :param pon_intf_id: OLT PON interface id
@@ -689,7 +686,7 @@
 	} else if ResourceType == FLOW_ID {
 		Path = fmt.Sprintf(FLOW_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
 	} else {
-		log.Error("Invalid resource pool identifier")
+		logger.Error(ctx, "Invalid resource pool identifier")
 	}
 	return Path
 }
@@ -704,7 +701,7 @@
 	    alloc_id/gemport_id, onu_id or invalid type respectively
 	*/
 	if NumIDs < 1 {
-		log.Error("Invalid number of resources requested")
+		logger.Error(ctx, "Invalid number of resources requested")
 		return nil, fmt.Errorf("Invalid number of resources requested %d", NumIDs)
 	}
 	// delegate to the master instance if sharing enabled across instances
@@ -713,34 +710,34 @@
 	if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
 		return SharedResourceMgr.GetResourceID(ctx, IntfID, ResourceType, NumIDs)
 	}
-	log.Debugf("Fetching resource from %s rsrc mgr for resource %s", PONRMgr.Globalorlocal, ResourceType)
+	logger.Debugf(ctx, "Fetching resource from %s rsrc mgr for resource %s", PONRMgr.Globalorlocal, ResourceType)
 
-	Path := PONRMgr.GetPath(IntfID, ResourceType)
+	Path := PONRMgr.GetPath(ctx, IntfID, ResourceType)
 	if Path == "" {
-		log.Errorf("Failed to get path for resource type %s", ResourceType)
+		logger.Errorf(ctx, "Failed to get path for resource type %s", ResourceType)
 		return nil, fmt.Errorf("Failed to get path for resource type %s", ResourceType)
 	}
-	log.Debugf("Get resource for type %s on path %s", ResourceType, Path)
+	logger.Debugf(ctx, "Get resource for type %s on path %s", ResourceType, Path)
 	var Result []uint32
 	var NextID uint32
 	Resource, err := PONRMgr.GetResource(ctx, Path)
 	if (err == nil) && (ResourceType == ONU_ID) || (ResourceType == FLOW_ID) {
-		if NextID, err = PONRMgr.GenerateNextID(Resource); err != nil {
-			log.Error("Failed to Generate ID")
+		if NextID, err = PONRMgr.GenerateNextID(ctx, Resource); err != nil {
+			logger.Error(ctx, "Failed to Generate ID")
 			return Result, err
 		}
 		Result = append(Result, NextID)
 	} else if (err == nil) && ((ResourceType == GEMPORT_ID) || (ResourceType == ALLOC_ID)) {
 		if NumIDs == 1 {
-			if NextID, err = PONRMgr.GenerateNextID(Resource); err != nil {
-				log.Error("Failed to Generate ID")
+			if NextID, err = PONRMgr.GenerateNextID(ctx, Resource); err != nil {
+				logger.Error(ctx, "Failed to Generate ID")
 				return Result, err
 			}
 			Result = append(Result, NextID)
 		} else {
 			for NumIDs > 0 {
-				if NextID, err = PONRMgr.GenerateNextID(Resource); err != nil {
-					log.Error("Failed to Generate ID")
+				if NextID, err = PONRMgr.GenerateNextID(ctx, Resource); err != nil {
+					logger.Error(ctx, "Failed to Generate ID")
 					return Result, err
 				}
 				Result = append(Result, NextID)
@@ -748,13 +745,13 @@
 			}
 		}
 	} else {
-		log.Error("get resource failed")
+		logger.Error(ctx, "get resource failed")
 		return Result, err
 	}
 
 	//Update resource in kv store
 	if PONRMgr.UpdateResource(ctx, Path, Resource) != nil {
-		log.Errorf("Failed to update resource %s", Path)
+		logger.Errorf(ctx, "Failed to update resource %s", Path)
 		return nil, fmt.Errorf("Failed to update resource %s", Path)
 	}
 	return Result, nil
@@ -780,11 +777,11 @@
 	   :return boolean: True if all IDs in given release_content release else False
 	*/
 	if !checkValidResourceType(ResourceType) {
-		log.Error("Invalid resource type")
+		logger.Error(ctx, "Invalid resource type")
 		return false
 	}
 	if ReleaseContent == nil {
-		log.Debug("Nothing to release")
+		logger.Debug(ctx, "Nothing to release")
 		return true
 	}
 	// delegate to the master instance if sharing enabled across instances
@@ -792,21 +789,21 @@
 	if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
 		return SharedResourceMgr.FreeResourceID(ctx, IntfID, ResourceType, ReleaseContent)
 	}
-	Path := PONRMgr.GetPath(IntfID, ResourceType)
+	Path := PONRMgr.GetPath(ctx, IntfID, ResourceType)
 	if Path == "" {
-		log.Error("Failed to get path")
+		logger.Error(ctx, "Failed to get path")
 		return false
 	}
 	Resource, err := PONRMgr.GetResource(ctx, Path)
 	if err != nil {
-		log.Error("Failed to get resource")
+		logger.Error(ctx, "Failed to get resource")
 		return false
 	}
 	for _, Val := range ReleaseContent {
-		PONRMgr.ReleaseID(Resource, Val)
+		PONRMgr.ReleaseID(ctx, Resource, Val)
 	}
 	if PONRMgr.UpdateResource(ctx, Path, Resource) != nil {
-		log.Errorf("Free resource for %s failed", Path)
+		logger.Errorf(ctx, "Free resource for %s failed", Path)
 		return false
 	}
 	return true
@@ -822,12 +819,12 @@
 	// TODO resource[POOL] = resource[POOL].bin
 	Value, err := json.Marshal(Resource)
 	if err != nil {
-		log.Error("failed to Marshal")
+		logger.Error(ctx, "failed to Marshal")
 		return err
 	}
 	err = PONRMgr.KVStore.Put(ctx, Path, Value)
 	if err != nil {
-		log.Error("failed to put data to kv store %s", Path)
+		logger.Error(ctx, "failed to put data to kv store %s", Path)
 		return err
 	}
 	return nil
@@ -844,17 +841,17 @@
 	if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
 		return SharedResourceMgr.ClearResourceIDPool(ctx, contIntfID, ResourceType)
 	}
-	Path := PONRMgr.GetPath(contIntfID, ResourceType)
+	Path := PONRMgr.GetPath(ctx, contIntfID, ResourceType)
 	if Path == "" {
-		log.Error("Failed to get path")
+		logger.Error(ctx, "Failed to get path")
 		return false
 	}
 
 	if err := PONRMgr.KVStore.Delete(ctx, Path); err != nil {
-		log.Errorf("Failed to delete resource %s", Path)
+		logger.Errorf(ctx, "Failed to delete resource %s", Path)
 		return false
 	}
-	log.Debugf("Cleared resource %s", Path)
+	logger.Debugf(ctx, "Cleared resource %s", Path)
 	return true
 }
 
@@ -868,7 +865,7 @@
 	var AllocIDs []byte
 	Result := PONRMgr.KVStore.Put(ctx, AllocIDPath, AllocIDs)
 	if Result != nil {
-		log.Error("Failed to update the KV store")
+		logger.Error(ctx, "Failed to update the KV store")
 		return
 	}
 	// initialize pon_intf_onu_id tuple to gemport_ids map
@@ -876,7 +873,7 @@
 	var GEMPortIDs []byte
 	Result = PONRMgr.KVStore.Put(ctx, GEMPortIDPath, GEMPortIDs)
 	if Result != nil {
-		log.Error("Failed to update the KV store")
+		logger.Error(ctx, "Failed to update the KV store")
 		return
 	}
 }
@@ -890,14 +887,14 @@
 	var err error
 	AllocIDPath := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
 	if err = PONRMgr.KVStore.Delete(ctx, AllocIDPath); err != nil {
-		log.Errorf("Failed to remove resource %s", AllocIDPath)
+		logger.Errorf(ctx, "Failed to remove resource %s", AllocIDPath)
 		return false
 	}
 	// remove pon_intf_onu_id tuple to gemport_ids map
 	GEMPortIDPath := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
 	err = PONRMgr.KVStore.Delete(ctx, GEMPortIDPath)
 	if err != nil {
-		log.Errorf("Failed to remove resource %s", GEMPortIDPath)
+		logger.Errorf(ctx, "Failed to remove resource %s", GEMPortIDPath)
 		return false
 	}
 
@@ -906,14 +903,14 @@
 		for _, Flow := range FlowIDs {
 			FlowIDInfoPath := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, PONIntfONUID, Flow.Value)
 			if err = PONRMgr.KVStore.Delete(ctx, FlowIDInfoPath); err != nil {
-				log.Errorf("Failed to remove resource %s", FlowIDInfoPath)
+				logger.Errorf(ctx, "Failed to remove resource %s", FlowIDInfoPath)
 				return false
 			}
 		}
 	}
 
 	if err = PONRMgr.KVStore.Delete(ctx, FlowIDPath); err != nil {
-		log.Errorf("Failed to remove resource %s", FlowIDPath)
+		logger.Errorf(ctx, "Failed to remove resource %s", FlowIDPath)
 		return false
 	}
 
@@ -934,11 +931,11 @@
 		if Value != nil {
 			Val, err := ToByte(Value.Value)
 			if err != nil {
-				log.Errorw("Failed to convert into byte array", log.Fields{"error": err})
+				logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"error": err})
 				return Data
 			}
 			if err = json.Unmarshal(Val, &Data); err != nil {
-				log.Error("Failed to unmarshal", log.Fields{"error": err})
+				logger.Error(ctx, "Failed to unmarshal", log.Fields{"error": err})
 				return Data
 			}
 		}
@@ -954,19 +951,19 @@
 	*/
 
 	Path := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
-	log.Debugf("Getting current gemports for %s", Path)
+	logger.Debugf(ctx, "Getting current gemports for %s", Path)
 	var Data []uint32
 	Value, err := PONRMgr.KVStore.Get(ctx, Path)
 	if err == nil {
 		if Value != nil {
 			Val, _ := ToByte(Value.Value)
 			if err = json.Unmarshal(Val, &Data); err != nil {
-				log.Errorw("Failed to unmarshal", log.Fields{"error": err})
+				logger.Errorw(ctx, "Failed to unmarshal", log.Fields{"error": err})
 				return Data
 			}
 		}
 	} else {
-		log.Errorf("Failed to get data from kvstore for %s", Path)
+		logger.Errorf(ctx, "Failed to get data from kvstore for %s", Path)
 	}
 	return Data
 }
@@ -986,7 +983,7 @@
 		if Value != nil {
 			Val, _ := ToByte(Value.Value)
 			if err = json.Unmarshal(Val, &Data); err != nil {
-				log.Error("Failed to unmarshal")
+				logger.Error(ctx, "Failed to unmarshal")
 				return Data
 			}
 		}
@@ -1010,11 +1007,11 @@
 		if Value != nil {
 			Val, err := ToByte(Value.Value)
 			if err != nil {
-				log.Errorw("Failed to convert flowinfo into byte array", log.Fields{"error": err})
+				logger.Errorw(ctx, "Failed to convert flowinfo into byte array", log.Fields{"error": err})
 				return err
 			}
 			if err = json.Unmarshal(Val, Data); err != nil {
-				log.Errorw("Failed to unmarshal", log.Fields{"error": err})
+				logger.Errorw(ctx, "Failed to unmarshal", log.Fields{"error": err})
 				return err
 			}
 		}
@@ -1031,7 +1028,7 @@
 	Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
 
 	if err := PONRMgr.KVStore.Delete(ctx, Path); err != nil {
-		log.Errorf("Falied to remove resource %s", Path)
+		logger.Errorf(ctx, "Falied to remove resource %s", Path)
 		return false
 	}
 	return true
@@ -1048,12 +1045,12 @@
 	Path := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
 	Value, err = json.Marshal(AllocIDs)
 	if err != nil {
-		log.Error("failed to Marshal")
+		logger.Error(ctx, "failed to Marshal")
 		return err
 	}
 
 	if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
-		log.Errorf("Failed to update resource %s", Path)
+		logger.Errorf(ctx, "Failed to update resource %s", Path)
 		return err
 	}
 	return err
@@ -1069,15 +1066,15 @@
 	var Value []byte
 	var err error
 	Path := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
-	log.Debugf("Updating gemport ids for %s", Path)
+	logger.Debugf(ctx, "Updating gemport ids for %s", Path)
 	Value, err = json.Marshal(GEMPortIDs)
 	if err != nil {
-		log.Error("failed to Marshal")
+		logger.Error(ctx, "failed to Marshal")
 		return err
 	}
 
 	if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
-		log.Errorf("Failed to update resource %s", Path)
+		logger.Errorf(ctx, "Failed to update resource %s", Path)
 		return err
 	}
 	return err
@@ -1128,12 +1125,12 @@
 	}
 	Value, err = json.Marshal(FlowIDs)
 	if err != nil {
-		log.Error("Failed to Marshal")
+		logger.Error(ctx, "Failed to Marshal")
 		return err
 	}
 
 	if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
-		log.Errorf("Failed to update resource %s", Path)
+		logger.Errorf(ctx, "Failed to update resource %s", Path)
 		return err
 	}
 	return err
@@ -1152,18 +1149,18 @@
 	Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
 	Value, err = json.Marshal(FlowData)
 	if err != nil {
-		log.Error("failed to Marshal")
+		logger.Error(ctx, "failed to Marshal")
 		return err
 	}
 
 	if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
-		log.Errorf("Failed to update resource %s", Path)
+		logger.Errorf(ctx, "Failed to update resource %s", Path)
 		return err
 	}
 	return err
 }
 
-func (PONRMgr *PONResourceManager) GenerateNextID(Resource map[string]interface{}) (uint32, error) {
+func (PONRMgr *PONResourceManager) GenerateNextID(ctx context.Context, Resource map[string]interface{}) (uint32, error) {
 	/*
 	   Generate unique id having OFFSET as start
 	   :param resource: resource used to generate ID
@@ -1171,12 +1168,12 @@
 	*/
 	ByteArray, err := ToByte(Resource[POOL])
 	if err != nil {
-		log.Error("Failed to convert resource to byte array")
+		logger.Error(ctx, "Failed to convert resource to byte array")
 		return 0, err
 	}
 	Data := bitmap.TSFromData(ByteArray, false)
 	if Data == nil {
-		log.Error("Failed to get data from byte array")
+		logger.Error(ctx, "Failed to get data from byte array")
 		return 0, errors.New("Failed to get data from byte array")
 	}
 
@@ -1190,11 +1187,11 @@
 	Data.Set(Idx, true)
 	res := uint32(Resource[START_IDX].(float64))
 	Resource[POOL] = Data.Data(false)
-	log.Debugf("Generated ID for %d", (uint32(Idx) + res))
+	logger.Debugf(ctx, "Generated ID for %d", (uint32(Idx) + res))
 	return (uint32(Idx) + res), err
 }
 
-func (PONRMgr *PONResourceManager) ReleaseID(Resource map[string]interface{}, Id uint32) bool {
+func (PONRMgr *PONResourceManager) ReleaseID(ctx context.Context, Resource map[string]interface{}, Id uint32) bool {
 	/*
 	   Release unique id having OFFSET as start index.
 	   :param resource: resource used to release ID
@@ -1202,12 +1199,12 @@
 	*/
 	ByteArray, err := ToByte(Resource[POOL])
 	if err != nil {
-		log.Error("Failed to convert resource to byte array")
+		logger.Error(ctx, "Failed to convert resource to byte array")
 		return false
 	}
 	Data := bitmap.TSFromData(ByteArray, false)
 	if Data == nil {
-		log.Error("Failed to get resource pool")
+		logger.Error(ctx, "Failed to get resource pool")
 		return false
 	}
 	Idx := Id - uint32(Resource[START_IDX].(float64))
@@ -1221,10 +1218,10 @@
 :param Resource: resource used to reserve ID
 :param Id: ID to be reserved
 */
-func (PONRMgr *PONResourceManager) reserveID(TSData *bitmap.Threadsafe, StartIndex uint32, Id uint32) bool {
+func (PONRMgr *PONResourceManager) reserveID(ctx context.Context, TSData *bitmap.Threadsafe, StartIndex uint32, Id uint32) bool {
 	Data := bitmap.TSFromData(TSData.Data(false), false)
 	if Data == nil {
-		log.Error("Failed to get resource pool")
+		logger.Error(ctx, "Failed to get resource pool")
 		return false
 	}
 	Idx := Id - StartIndex
@@ -1281,12 +1278,12 @@
 	Path := fmt.Sprintf(ONU_GEM_INFO_PATH, PONRMgr.DeviceID, intfID)
 	Value, err = json.Marshal(onuGemData)
 	if err != nil {
-		log.Error("failed to Marshal")
+		logger.Error(ctx, "failed to Marshal")
 		return err
 	}
 
 	if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
-		log.Errorf("Failed to update resource %s", Path)
+		logger.Errorf(ctx, "Failed to update resource %s", Path)
 		return err
 	}
 	return err
@@ -1303,22 +1300,22 @@
 	path := fmt.Sprintf(ONU_GEM_INFO_PATH, PONRMgr.DeviceID, IntfId)
 	value, err := PONRMgr.KVStore.Get(ctx, path)
 	if err != nil {
-		log.Errorw("Failed to get from kv store", log.Fields{"path": path})
+		logger.Errorw(ctx, "Failed to get from kv store", log.Fields{"path": path})
 		return err
 	} else if value == nil {
-		log.Debug("No onuinfo for path", log.Fields{"path": path})
+		logger.Debug(ctx, "No onuinfo for path", log.Fields{"path": path})
 		return nil // returning nil as this could happen if there are no onus for the interface yet
 	}
 	if Val, err = kvstore.ToByte(value.Value); err != nil {
-		log.Error("Failed to convert to byte array")
+		logger.Error(ctx, "Failed to convert to byte array")
 		return err
 	}
 
 	if err = json.Unmarshal(Val, &onuGemInfo); err != nil {
-		log.Error("Failed to unmarshall")
+		logger.Error(ctx, "Failed to unmarshall")
 		return err
 	}
-	log.Debugw("found onuinfo from path", log.Fields{"path": path, "onuinfo": onuGemInfo})
+	logger.Debugw(ctx, "found onuinfo from path", log.Fields{"path": path, "onuinfo": onuGemInfo})
 	return err
 }
 
@@ -1330,7 +1327,7 @@
 
 	path := fmt.Sprintf(ONU_GEM_INFO_PATH, PONRMgr.DeviceID, intfId)
 	if err := PONRMgr.KVStore.Delete(ctx, path); err != nil {
-		log.Errorf("Falied to remove resource %s", path)
+		logger.Errorf(ctx, "Falied to remove resource %s", path)
 		return err
 	}
 	return nil
diff --git a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/techprofile/4QueueHybridProfileMap1.json b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/techprofile/4QueueHybridProfileMap1.json
similarity index 100%
rename from vendor/github.com/opencord/voltha-lib-go/v3/pkg/techprofile/4QueueHybridProfileMap1.json
rename to vendor/github.com/opencord/voltha-lib-go/v4/pkg/techprofile/4QueueHybridProfileMap1.json
diff --git a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/techprofile/README.md b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/techprofile/README.md
similarity index 81%
rename from vendor/github.com/opencord/voltha-lib-go/v3/pkg/techprofile/README.md
rename to vendor/github.com/opencord/voltha-lib-go/v4/pkg/techprofile/README.md
index 03a396d..88d6564 100644
--- a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/techprofile/README.md
+++ b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/techprofile/README.md
@@ -158,13 +158,13 @@
 Assuming the Technology template is stored in a local file 4QueueHybridProfileMap1.json the following commands could be used to store or update the technical template into the proper location in the etcd key/value store:
 
 # Store a Technology template using etcdctl
-jq -c . 4QueueHybridProfileMap1.json | kubectl exec -i etcd-cluster-0000 -- etcdctl set service/voltha/technology_profiles/xgspon/64
+jq -c . 4QueueHybridProfileMap1.json | kubectl exec -i etcd-cluster-0000 -- etcdctl set service/voltha/technology_profiles/XGS-PON/64
 
-jq -c . 4QueueHybridProfileMap1.json |  etcdctl --endpoints=<ETCDIP>:2379 put service/voltha/technology_profiles/xgspon/64
+jq -c . 4QueueHybridProfileMap1.json |  etcdctl --endpoints=<ETCDIP>:2379 put service/voltha/technology_profiles/XGS-PON/64
 
 
 # Store a Technology template using curl
-curl -sSL -XPUT http://10.233.53.161:2379/v2/keys/service/voltha/technology_profiles/xgspon/64 -d value="$(jq -c . 4QueueHybridProfileMap1.json)"
+curl -sSL -XPUT http://10.233.53.161:2379/v2/keys/service/voltha/technology_profiles/XGS-PON/64 -d value="$(jq -c . 4QueueHybridProfileMap1.json)"
 In the examples above, the command jq is used. This command can be installed using standard package management tools on most Linux systems. In the examples the "-c" option is used to compress the JSON. Using this tool is not necessary, and if you choose not to use the tool, you can replace "jq -c ," in the above examples with the "cat" command. More on jq can be found at https://stedolan.github.io/jq/.
 
 Listing Technical Profiles for a given Technology
@@ -172,18 +172,18 @@
 
 
 #List Tech profile 
-etcdctl --endpoints=<EtcdIPAddres>:2379 get  service/voltha/technology_profiles/xgspon/64
+etcdctl --endpoints=<EtcdIPAddres>:2379 get  service/voltha/technology_profiles/XGS-PON/64
 
 
 # Example output
 A specified Technology profile can be viewed with the etcdctl get command. (Again, jq is used for presentation purposes, and is not required)
 
 # Display a specified Technology profile, using jq to pretty print
-kubectl exec -i etcd-cluster-0000 -- etcdctl get /xgspon/64 | jq .
+kubectl exec -i etcd-cluster-0000 -- etcdctl get service/voltha/technology_profiles/XGS-PON/64 | jq .
 
-etcdctl --endpoints=<ETCDIP>:2379 get  service/voltha/technology_profiles/xgspon/64
+etcdctl --endpoints=<ETCDIP>:2379 get  service/voltha/technology_profiles/XGS-PON/64
 # Example outpout
-service/voltha/technology_profiles/xgspon/64/uni-1
+service/voltha/technology_profiles/XGS-PON/64/uni-1
 {
   "name": "4QueueHybridProfileMap1",
   "profile_type": "XPON",
@@ -326,11 +326,19 @@
   ]
 }
 
-#Deleting Technology Profiles
+# Display a specified Technology profile instance, using jq to pretty print
+kubectl exec -i etcd-cluster-0000 -- etcdctl get service/voltha/technology_profiles/XGS-PON/64/pon-{0}/onu-{1}/uni-{0} | jq .
+
+etcdctl --endpoints=<ETCDIP>:2379 get  service/voltha/technology_profiles/XGS-PON/64/pon-{0}/onu-{1}/uni-{0}
+# Example outpout
+service/voltha/technology_profiles/XGS-PON/64/pon-{0}/onu-{1}/uni-{0}
+{"name":"Default_1tcont_1gem_Profile","subscriber_identifier":"pon-{0}/onu-{1}/uni-{0}","profile_type":"XGS-PON","version":1,"num_gem_ports":1,"instance_control":{"ONU":"multi-instance","uni":"single-instance","max_gem_payload_size":"auto"},"us_scheduler":{"alloc_id":1024,"direction":"UPSTREAM","additional_bw":"AdditionalBW_BestEffort","priority":0,"weight":0,"q_sched_policy":"Hybrid"},"ds_scheduler":{"alloc_id":1024,"direction":"DOWNSTREAM","additional_bw":"AdditionalBW_BestEffort","priority":0,"weight":0,"q_sched_policy":"Hybrid"},"upstream_gem_port_attribute_list":[{"gemport_id":1024,"max_q_size":"auto","pbit_map":"0b11111111","aes_encryption":"True","scheduling_policy":"WRR","priority_q":0,"weight":0,"discard_policy":"TailDrop","discard_config":{"min_threshold":0,"max_threshold":0,"max_probability":0},"is_multicast":"","dynamic_access_control_list":"","static_access_control_list":"","multicast_gem_id":0}],"downstream_gem_port_attribute_list":[{"gemport_id":1024,"max_q_size":"auto","pbit_map":"0b11111111","aes_encryption":"True","scheduling_policy":"WRR","priority_q":0,"weight":0,"discard_policy":"TailDrop","discard_config":{"min_threshold":0,"max_threshold":0,"max_probability":0},"is_multicast":"","dynamic_access_control_list":"","static_access_control_list":"","multicast_gem_id":0}]}
+
+# Deleting Technology Profiles
 A technology profile or a technology profile tree can be removed using etcdctl rm.
 
 # Remove a specific technology profile
-kubectl exec -i etcd-cluster-0000 -- etcdctl rm /xgspon/64
+kubectl exec -i etcd-cluster-0000 -- etcdctl rm /XGS-PON/64
 
 # Remove all technology profiles associated with Technology xgspon and ID 64(including the profile ID key)
-kubectl exec -i etcd-cluster-0000 -- etcdctl rm --dir -r /xgspon/64
+kubectl exec -i etcd-cluster-0000 -- etcdctl rm --dir -r /XGS-PON/64
diff --git a/vendor/github.com/opencord/voltha-lib-go/v4/pkg/techprofile/SingleQueueEponProfile.json b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/techprofile/SingleQueueEponProfile.json
new file mode 100644
index 0000000..00476a2
--- /dev/null
+++ b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/techprofile/SingleQueueEponProfile.json
@@ -0,0 +1,61 @@
+{

+    "name": "SingleQueueEponProfile",

+    "profile_type": "EPON",

+    "version": 1,

+    "num_gem_ports": 1,

+    "instance_control": {

+      "onu": "multi-instance",

+      "uni": "single-instance",

+      "max_gem_payload_size": "auto"

+    },

+    "epon_attribute": {

+        "package_type": "B"

+    },

+    "upstream_queue_attribute_list": [

+      {

+        "pbit_map": "0b11111111",

+        "aes_encryption": "False",

+        "traffic_type": "BE",

+        "unsolicited_grant_size": 0,

+        "nominal_interval": 0,

+        "tolerated_poll_jitter": 0,

+        "request_transmission_policy": 0,

+        "num_q_sets": 2,

+        "q_thresholds": {

+          "q_threshold1":5500,

+          "q_threshold2":0,

+          "q_threshold3":0,

+          "q_threshold4":0,

+          "q_threshold5":0,

+          "q_threshold6":0,

+          "q_threshold7":0

+        },

+        "scheduling_policy": "StrictPriority",

+        "priority_q": 4,

+        "weight": 0,

+        "discard_policy": "TailDrop",

+        "max_q_size": "auto",

+        "discard_config": {

+          "min_threshold": 0,

+          "max_threshold": 0,

+          "max_probability": 0

+        }

+      }

+    ],

+    "downstream_queue_attribute_list": [

+      {

+        "pbit_map": "0b11111111",

+        "aes_encryption": "True",

+        "scheduling_policy": "StrictPriority",

+        "priority_q": 4,

+        "weight": 0,

+        "discard_policy": "TailDrop",

+        "max_q_size": "auto",

+        "discard_config": {

+          "min_threshold": 0,

+          "max_threshold": 0,

+          "max_probability": 0

+        }

+      }

+    ]

+}
\ No newline at end of file
diff --git a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/common.go b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/techprofile/common.go
similarity index 79%
copy from vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/common.go
copy to vendor/github.com/opencord/voltha-lib-go/v4/pkg/techprofile/common.go
index a5a79ae..544c780 100644
--- a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/db/common.go
+++ b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/techprofile/common.go
@@ -13,22 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package db
+package techprofile
 
 import (
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
+	"github.com/opencord/voltha-lib-go/v4/pkg/log"
 )
 
-const (
-	logLevel = log.ErrorLevel
-)
-
-var logger log.Logger
+var logger log.CLogger
 
 func init() {
 	// Setup this package so that it's log level can be modified at run time
 	var err error
-	logger, err = log.AddPackage(log.JSON, logLevel, log.Fields{"pkg": "db"})
+	logger, err = log.RegisterPackage(log.JSON, log.ErrorLevel, log.Fields{})
 	if err != nil {
 		panic(err)
 	}
diff --git a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/techprofile/config.go b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/techprofile/config.go
similarity index 78%
rename from vendor/github.com/opencord/voltha-lib-go/v3/pkg/techprofile/config.go
rename to vendor/github.com/opencord/voltha-lib-go/v4/pkg/techprofile/config.go
index 4af2bd5..bcec75e 100644
--- a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/techprofile/config.go
+++ b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/techprofile/config.go
@@ -16,7 +16,8 @@
 package techprofile
 
 import (
-	"github.com/opencord/voltha-lib-go/v3/pkg/db"
+	"github.com/opencord/voltha-lib-go/v4/pkg/db"
+	"time"
 )
 
 // tech profile default constants
@@ -28,7 +29,7 @@
 	defaultGemportsCount          = 1
 	defaultPbits                  = "0b11111111"
 
-	defaultKVStoreTimeout = 5 //in seconds
+	defaultKVStoreTimeout = 5 * time.Second //in seconds
 
 	// Tech profile path prefix in kv store
 	defaultKVPathPrefix = "service/voltha/technology_profiles"
@@ -71,14 +72,30 @@
 	SCHEDULING_POLICY                  = "scheduling_policy"
 	MAX_Q_SIZE                         = "max_q_size"
 	AES_ENCRYPTION                     = "aes_encryption"
+	// String Keys for EPON
+	EPON_ATTRIBUTE              = "epon_attribute"
+	PACKAGE_TYPE                = "package_type"
+	TRAFFIC_TYPE                = "traffic type"
+	UNSOLICITED_GRANT_SIZE      = "unsolicited_grant_size"
+	NOMINAL_INTERVAL            = "nominal_interval"
+	TOLERATED_POLL_JITTER       = "tolerated_poll_jitter"
+	REQUEST_TRANSMISSION_POLICY = "request_transmission_policy"
+	NUM_Q_SETS                  = "num_q_sets"
+	Q_THRESHOLDS                = "q_thresholds"
+	Q_THRESHOLD1                = "q_threshold1"
+	Q_THRESHOLD2                = "q_threshold2"
+	Q_THRESHOLD3                = "q_threshold3"
+	Q_THRESHOLD4                = "q_threshold4"
+	Q_THRESHOLD5                = "q_threshold5"
+	Q_THRESHOLD6                = "q_threshold6"
+	Q_THRESHOLD7                = "q_threshold7"
 )
 
 // TechprofileFlags represents the set of configurations used
 type TechProfileFlags struct {
-	KVStoreHost          string
-	KVStorePort          int
+	KVStoreAddress       string
 	KVStoreType          string
-	KVStoreTimeout       int
+	KVStoreTimeout       time.Duration
 	KVBackend            *db.Backend
 	TPKVPathPrefix       string
 	TPFileKVPath         string
@@ -92,12 +109,11 @@
 	DefaultNumGemPorts   uint32
 }
 
-func NewTechProfileFlags(KVStoreType string, KVStoreHost string, KVStorePort int) *TechProfileFlags {
+func NewTechProfileFlags(KVStoreType string, KVStoreAddress string) *TechProfileFlags {
 	// initialize with default values
 	var techProfileFlags = TechProfileFlags{
 		KVBackend:            nil,
-		KVStoreHost:          KVStoreHost,
-		KVStorePort:          KVStorePort,
+		KVStoreAddress:       KVStoreAddress,
 		KVStoreType:          KVStoreType,
 		KVStoreTimeout:       defaultKVStoreTimeout,
 		DefaultTPName:        defaultTechProfileName,
diff --git a/vendor/github.com/opencord/voltha-lib-go/v4/pkg/techprofile/tech_profile.go b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/techprofile/tech_profile.go
new file mode 100644
index 0000000..b80f136
--- /dev/null
+++ b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/techprofile/tech_profile.go
@@ -0,0 +1,1400 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package techprofile
+
+import (
+	"context"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"regexp"
+	"strconv"
+	"sync"
+	"time"
+
+	"github.com/opencord/voltha-lib-go/v4/pkg/db"
+
+	"github.com/opencord/voltha-lib-go/v4/pkg/db/kvstore"
+	"github.com/opencord/voltha-lib-go/v4/pkg/log"
+	tp_pb "github.com/opencord/voltha-protos/v4/go/tech_profile"
+)
+
+// Interface to pon resource manager APIs
+type iPonResourceMgr interface {
+	GetResourceID(ctx context.Context, IntfID uint32, ResourceType string, NumIDs uint32) ([]uint32, error)
+	GetResourceTypeAllocID() string
+	GetResourceTypeGemPortID() string
+	GetTechnology() string
+}
+
+type Direction int32
+
+const (
+	Direction_UPSTREAM      Direction = 0
+	Direction_DOWNSTREAM    Direction = 1
+	Direction_BIDIRECTIONAL Direction = 2
+)
+
+var Direction_name = map[Direction]string{
+	0: "UPSTREAM",
+	1: "DOWNSTREAM",
+	2: "BIDIRECTIONAL",
+}
+
+type SchedulingPolicy int32
+
+const (
+	SchedulingPolicy_WRR            SchedulingPolicy = 0
+	SchedulingPolicy_StrictPriority SchedulingPolicy = 1
+	SchedulingPolicy_Hybrid         SchedulingPolicy = 2
+)
+
+var SchedulingPolicy_name = map[SchedulingPolicy]string{
+	0: "WRR",
+	1: "StrictPriority",
+	2: "Hybrid",
+}
+
+type AdditionalBW int32
+
+const (
+	AdditionalBW_AdditionalBW_None       AdditionalBW = 0
+	AdditionalBW_AdditionalBW_NA         AdditionalBW = 1
+	AdditionalBW_AdditionalBW_BestEffort AdditionalBW = 2
+	AdditionalBW_AdditionalBW_Auto       AdditionalBW = 3
+)
+
+var AdditionalBW_name = map[AdditionalBW]string{
+	0: "AdditionalBW_None",
+	1: "AdditionalBW_NA",
+	2: "AdditionalBW_BestEffort",
+	3: "AdditionalBW_Auto",
+}
+
+type DiscardPolicy int32
+
+const (
+	DiscardPolicy_TailDrop  DiscardPolicy = 0
+	DiscardPolicy_WTailDrop DiscardPolicy = 1
+	DiscardPolicy_Red       DiscardPolicy = 2
+	DiscardPolicy_WRed      DiscardPolicy = 3
+)
+
+var DiscardPolicy_name = map[DiscardPolicy]string{
+	0: "TailDrop",
+	1: "WTailDrop",
+	2: "Red",
+	3: "WRed",
+}
+
+// Required uniPortName format
+var uniPortNameFormat = regexp.MustCompile(`^olt-{[a-z0-9\-]+}/pon-{[0-9]+}/onu-{[0-9]+}/uni-{[0-9]+}$`)
+
+/*
+  type InferredAdditionBWIndication int32
+
+  const (
+	  InferredAdditionBWIndication_InferredAdditionBWIndication_None       InferredAdditionBWIndication = 0
+	  InferredAdditionBWIndication_InferredAdditionBWIndication_Assured    InferredAdditionBWIndication = 1
+	  InferredAdditionBWIndication_InferredAdditionBWIndication_BestEffort InferredAdditionBWIndication = 2
+  )
+
+  var InferredAdditionBWIndication_name = map[int32]string{
+	  0: "InferredAdditionBWIndication_None",
+	  1: "InferredAdditionBWIndication_Assured",
+	  2: "InferredAdditionBWIndication_BestEffort",
+  }
+*/
+// instance control defaults
+const (
+	defaultOnuInstance    = "multi-instance"
+	defaultUniInstance    = "single-instance"
+	defaultGemPayloadSize = "auto"
+)
+
+const MAX_GEM_PAYLOAD = "max_gem_payload_size"
+
+type InstanceControl struct {
+	Onu               string `json:"ONU"`
+	Uni               string `json:"uni"`
+	MaxGemPayloadSize string `json:"max_gem_payload_size"`
+}
+
+// default discard config constants
+const (
+	defaultMinThreshold   = 0
+	defaultMaxThreshold   = 0
+	defaultMaxProbability = 0
+)
+
+type DiscardConfig struct {
+	MinThreshold   int `json:"min_threshold"`
+	MaxThreshold   int `json:"max_threshold"`
+	MaxProbability int `json:"max_probability"`
+}
+
+// default scheduler contants
+const (
+	defaultAdditionalBw     = AdditionalBW_AdditionalBW_BestEffort
+	defaultPriority         = 0
+	defaultWeight           = 0
+	defaultQueueSchedPolicy = SchedulingPolicy_Hybrid
+)
+
+type Scheduler struct {
+	Direction    string `json:"direction"`
+	AdditionalBw string `json:"additional_bw"`
+	Priority     uint32 `json:"priority"`
+	Weight       uint32 `json:"weight"`
+	QSchedPolicy string `json:"q_sched_policy"`
+}
+
+// default GEM attribute constants
+const (
+	defaultAESEncryption     = "True"
+	defaultPriorityQueue     = 0
+	defaultQueueWeight       = 0
+	defaultMaxQueueSize      = "auto"
+	defaultdropPolicy        = DiscardPolicy_TailDrop
+	defaultSchedulePolicy    = SchedulingPolicy_WRR
+	defaultIsMulticast       = "False"
+	defaultAccessControlList = "224.0.0.0-239.255.255.255"
+	defaultMcastGemID        = 4069
+)
+
+type GemPortAttribute struct {
+	MaxQueueSize     string        `json:"max_q_size"`
+	PbitMap          string        `json:"pbit_map"`
+	AesEncryption    string        `json:"aes_encryption"`
+	SchedulingPolicy string        `json:"scheduling_policy"`
+	PriorityQueue    uint32        `json:"priority_q"`
+	Weight           uint32        `json:"weight"`
+	DiscardPolicy    string        `json:"discard_policy"`
+	DiscardConfig    DiscardConfig `json:"discard_config"`
+	IsMulticast      string        `json:"is_multicast"`
+	DControlList     string        `json:"dynamic_access_control_list"`
+	SControlList     string        `json:"static_access_control_list"`
+	McastGemID       uint32        `json:"multicast_gem_id"`
+}
+
+// Instance of Scheduler
+type IScheduler struct {
+	AllocID      uint32 `json:"alloc_id"`
+	Direction    string `json:"direction"`
+	AdditionalBw string `json:"additional_bw"`
+	Priority     uint32 `json:"priority"`
+	Weight       uint32 `json:"weight"`
+	QSchedPolicy string `json:"q_sched_policy"`
+}
+
+// Instance of GemPortAttribute
+type IGemPortAttribute struct {
+	GemportID        uint32        `json:"gemport_id"`
+	MaxQueueSize     string        `json:"max_q_size"`
+	PbitMap          string        `json:"pbit_map"`
+	AesEncryption    string        `json:"aes_encryption"`
+	SchedulingPolicy string        `json:"scheduling_policy"`
+	PriorityQueue    uint32        `json:"priority_q"`
+	Weight           uint32        `json:"weight"`
+	DiscardPolicy    string        `json:"discard_policy"`
+	DiscardConfig    DiscardConfig `json:"discard_config"`
+	IsMulticast      string        `json:"is_multicast"`
+	DControlList     string        `json:"dynamic_access_control_list"`
+	SControlList     string        `json:"static_access_control_list"`
+	McastGemID       uint32        `json:"multicast_gem_id"`
+}
+
+type TechProfileMgr struct {
+	config            *TechProfileFlags
+	resourceMgr       iPonResourceMgr
+	GemPortIDMgmtLock sync.RWMutex
+	AllocIDMgmtLock   sync.RWMutex
+}
+type DefaultTechProfile struct {
+	Name                           string             `json:"name"`
+	ProfileType                    string             `json:"profile_type"`
+	Version                        int                `json:"version"`
+	NumGemPorts                    uint32             `json:"num_gem_ports"`
+	InstanceCtrl                   InstanceControl    `json:"instance_control"`
+	UsScheduler                    Scheduler          `json:"us_scheduler"`
+	DsScheduler                    Scheduler          `json:"ds_scheduler"`
+	UpstreamGemPortAttributeList   []GemPortAttribute `json:"upstream_gem_port_attribute_list"`
+	DownstreamGemPortAttributeList []GemPortAttribute `json:"downstream_gem_port_attribute_list"`
+}
+type TechProfile struct {
+	Name                           string              `json:"name"`
+	SubscriberIdentifier           string              `json:"subscriber_identifier"`
+	ProfileType                    string              `json:"profile_type"`
+	Version                        int                 `json:"version"`
+	NumGemPorts                    uint32              `json:"num_gem_ports"`
+	InstanceCtrl                   InstanceControl     `json:"instance_control"`
+	UsScheduler                    IScheduler          `json:"us_scheduler"`
+	DsScheduler                    IScheduler          `json:"ds_scheduler"`
+	UpstreamGemPortAttributeList   []IGemPortAttribute `json:"upstream_gem_port_attribute_list"`
+	DownstreamGemPortAttributeList []IGemPortAttribute `json:"downstream_gem_port_attribute_list"`
+}
+
+// QThresholds struct for EPON
+type QThresholds struct {
+	QThreshold1 uint32 `json:"q_threshold1"`
+	QThreshold2 uint32 `json:"q_threshold2"`
+	QThreshold3 uint32 `json:"q_threshold3"`
+	QThreshold4 uint32 `json:"q_threshold4"`
+	QThreshold5 uint32 `json:"q_threshold5"`
+	QThreshold6 uint32 `json:"q_threshold6"`
+	QThreshold7 uint32 `json:"q_threshold7"`
+}
+
+// UpstreamQueueAttribute struct for EPON
+type UpstreamQueueAttribute struct {
+	MaxQueueSize              string        `json:"max_q_size"`
+	PbitMap                   string        `json:"pbit_map"`
+	AesEncryption             string        `json:"aes_encryption"`
+	TrafficType               string        `json:"traffic_type"`
+	UnsolicitedGrantSize      uint32        `json:"unsolicited_grant_size"`
+	NominalInterval           uint32        `json:"nominal_interval"`
+	ToleratedPollJitter       uint32        `json:"tolerated_poll_jitter"`
+	RequestTransmissionPolicy uint32        `json:"request_transmission_policy"`
+	NumQueueSet               uint32        `json:"num_q_sets"`
+	QThresholds               QThresholds   `json:"q_thresholds"`
+	SchedulingPolicy          string        `json:"scheduling_policy"`
+	PriorityQueue             uint32        `json:"priority_q"`
+	Weight                    uint32        `json:"weight"`
+	DiscardPolicy             string        `json:"discard_policy"`
+	DiscardConfig             DiscardConfig `json:"discard_config"`
+}
+
+// Default EPON constants
+const (
+	defaultPakageType = "B"
+)
+const (
+	defaultTrafficType               = "BE"
+	defaultUnsolicitedGrantSize      = 0
+	defaultNominalInterval           = 0
+	defaultToleratedPollJitter       = 0
+	defaultRequestTransmissionPolicy = 0
+	defaultNumQueueSet               = 2
+)
+const (
+	defaultQThreshold1 = 5500
+	defaultQThreshold2 = 0
+	defaultQThreshold3 = 0
+	defaultQThreshold4 = 0
+	defaultQThreshold5 = 0
+	defaultQThreshold6 = 0
+	defaultQThreshold7 = 0
+)
+
+// DownstreamQueueAttribute struct for EPON
+type DownstreamQueueAttribute struct {
+	MaxQueueSize     string        `json:"max_q_size"`
+	PbitMap          string        `json:"pbit_map"`
+	AesEncryption    string        `json:"aes_encryption"`
+	SchedulingPolicy string        `json:"scheduling_policy"`
+	PriorityQueue    uint32        `json:"priority_q"`
+	Weight           uint32        `json:"weight"`
+	DiscardPolicy    string        `json:"discard_policy"`
+	DiscardConfig    DiscardConfig `json:"discard_config"`
+}
+
+// iUpstreamQueueAttribute struct for EPON
+type iUpstreamQueueAttribute struct {
+	GemportID                 uint32        `json:"q_id"`
+	MaxQueueSize              string        `json:"max_q_size"`
+	PbitMap                   string        `json:"pbit_map"`
+	AesEncryption             string        `json:"aes_encryption"`
+	TrafficType               string        `json:"traffic_type"`
+	UnsolicitedGrantSize      uint32        `json:"unsolicited_grant_size"`
+	NominalInterval           uint32        `json:"nominal_interval"`
+	ToleratedPollJitter       uint32        `json:"tolerated_poll_jitter"`
+	RequestTransmissionPolicy uint32        `json:"request_transmission_policy"`
+	NumQueueSet               uint32        `json:"num_q_sets"`
+	QThresholds               QThresholds   `json:"q_thresholds"`
+	SchedulingPolicy          string        `json:"scheduling_policy"`
+	PriorityQueue             uint32        `json:"priority_q"`
+	Weight                    uint32        `json:"weight"`
+	DiscardPolicy             string        `json:"discard_policy"`
+	DiscardConfig             DiscardConfig `json:"discard_config"`
+}
+
+// iDownstreamQueueAttribute struct for EPON
+type iDownstreamQueueAttribute struct {
+	GemportID        uint32        `json:"q_id"`
+	MaxQueueSize     string        `json:"max_q_size"`
+	PbitMap          string        `json:"pbit_map"`
+	AesEncryption    string        `json:"aes_encryption"`
+	SchedulingPolicy string        `json:"scheduling_policy"`
+	PriorityQueue    uint32        `json:"priority_q"`
+	Weight           uint32        `json:"weight"`
+	DiscardPolicy    string        `json:"discard_policy"`
+	DiscardConfig    DiscardConfig `json:"discard_config"`
+}
+
+// EponAttribute struct for EPON
+type EponAttribute struct {
+	PackageType string `json:"pakage_type"`
+}
+
+// DefaultTechProfile struct for EPON
+type DefaultEponProfile struct {
+	Name                         string                     `json:"name"`
+	ProfileType                  string                     `json:"profile_type"`
+	Version                      int                        `json:"version"`
+	NumGemPorts                  uint32                     `json:"num_gem_ports"`
+	InstanceCtrl                 InstanceControl            `json:"instance_control"`
+	EponAttribute                EponAttribute              `json:"epon_attribute"`
+	UpstreamQueueAttributeList   []UpstreamQueueAttribute   `json:"upstream_queue_attribute_list"`
+	DownstreamQueueAttributeList []DownstreamQueueAttribute `json:"downstream_queue_attribute_list"`
+}
+
+// TechProfile struct for EPON
+type EponProfile struct {
+	Name                         string                      `json:"name"`
+	SubscriberIdentifier         string                      `json:"subscriber_identifier"`
+	ProfileType                  string                      `json:"profile_type"`
+	Version                      int                         `json:"version"`
+	NumGemPorts                  uint32                      `json:"num_gem_ports"`
+	InstanceCtrl                 InstanceControl             `json:"instance_control"`
+	EponAttribute                EponAttribute               `json:"epon_attribute"`
+	AllocID                      uint32                      `json:"llid"`
+	UpstreamQueueAttributeList   []iUpstreamQueueAttribute   `json:"upstream_queue_attribute_list"`
+	DownstreamQueueAttributeList []iDownstreamQueueAttribute `json:"downstream_queue_attribute_list"`
+}
+
+const (
+	xgspon = "XGS-PON"
+	gpon   = "GPON"
+	epon   = "EPON"
+)
+
+func (t *TechProfileMgr) SetKVClient(ctx context.Context) *db.Backend {
+	kvClient, err := newKVClient(ctx, t.config.KVStoreType, t.config.KVStoreAddress, t.config.KVStoreTimeout)
+	if err != nil {
+		logger.Errorw(ctx, "failed-to-create-kv-client",
+			log.Fields{
+				"type": t.config.KVStoreType, "address": t.config.KVStoreAddress,
+				"timeout": t.config.KVStoreTimeout, "prefix": t.config.TPKVPathPrefix,
+				"error": err.Error(),
+			})
+		return nil
+	}
+	return &db.Backend{
+		Client:     kvClient,
+		StoreType:  t.config.KVStoreType,
+		Address:    t.config.KVStoreAddress,
+		Timeout:    t.config.KVStoreTimeout,
+		PathPrefix: t.config.TPKVPathPrefix}
+
+	/* TODO : Make sure direct call to NewBackend is working fine with backend , currently there is some
+		  issue between kv store and backend , core is not calling NewBackend directly
+	 kv := model.NewBackend(t.config.KVStoreType, t.config.KVStoreHost, t.config.KVStorePort,
+								  t.config.KVStoreTimeout,  kvStoreTechProfilePathPrefix)
+	*/
+}
+
+func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
+
+	logger.Infow(ctx, "kv-store", log.Fields{"storeType": storeType, "address": address})
+	switch storeType {
+	case "consul":
+		return kvstore.NewConsulClient(ctx, address, timeout)
+	case "etcd":
+		return kvstore.NewEtcdClient(ctx, address, timeout, log.WarnLevel)
+	}
+	return nil, errors.New("unsupported-kv-store")
+}
+
+func NewTechProfile(ctx context.Context, resourceMgr iPonResourceMgr, KVStoreType string, KVStoreAddress string) (*TechProfileMgr, error) {
+	var techprofileObj TechProfileMgr
+	logger.Debug(ctx, "Initializing techprofile Manager")
+	techprofileObj.config = NewTechProfileFlags(KVStoreType, KVStoreAddress)
+	techprofileObj.config.KVBackend = techprofileObj.SetKVClient(ctx)
+	if techprofileObj.config.KVBackend == nil {
+		logger.Error(ctx, "Failed to initialize KV backend\n")
+		return nil, errors.New("KV backend init failed")
+	}
+	techprofileObj.resourceMgr = resourceMgr
+	logger.Debug(ctx, "Initializing techprofile object instance success")
+	return &techprofileObj, nil
+}
+
+func (t *TechProfileMgr) GetTechProfileInstanceKVPath(ctx context.Context, techProfiletblID uint32, uniPortName string) string {
+	logger.Debugw(ctx, "get-tp-instance-kv-path", log.Fields{
+		"uniPortName": uniPortName,
+		"tpId":        techProfiletblID,
+	})
+	return fmt.Sprintf(t.config.TPInstanceKVPath, t.resourceMgr.GetTechnology(), techProfiletblID, uniPortName)
+}
+
+func (t *TechProfileMgr) GetTPInstanceFromKVStore(ctx context.Context, techProfiletblID uint32, path string) (interface{}, error) {
+	var err error
+	var kvResult *kvstore.KVPair
+	var KvTpIns TechProfile
+	var KvEponIns EponProfile
+	var resPtr interface{}
+	// For example:
+	// tpInstPath like "XGS-PON/64/uni_port_name"
+	// is broken into ["XGS-PON" "64" ...]
+	pathSlice := regexp.MustCompile(`/`).Split(path, -1)
+	switch pathSlice[0] {
+	case xgspon, gpon:
+		resPtr = &KvTpIns
+	case epon:
+		resPtr = &KvEponIns
+	default:
+		logger.Errorw(ctx, "unknown-tech", log.Fields{"tech": pathSlice[0]})
+		return nil, fmt.Errorf("unknown-tech-%s", pathSlice[0])
+	}
+
+	kvResult, _ = t.config.KVBackend.Get(ctx, path)
+	if kvResult == nil {
+		logger.Infow(ctx, "tp-instance-not-found-on-kv", log.Fields{"key": path})
+		return nil, nil
+	} else {
+		if value, err := kvstore.ToByte(kvResult.Value); err == nil {
+			if err = json.Unmarshal(value, resPtr); err != nil {
+				logger.Errorw(ctx, "error-unmarshal-kv-result", log.Fields{"key": path, "value": value})
+				return nil, errors.New("error-unmarshal-kv-result")
+			} else {
+				return resPtr, nil
+			}
+		}
+	}
+	return nil, err
+}
+
+func (t *TechProfileMgr) addTechProfInstanceToKVStore(ctx context.Context, techProfiletblID uint32, uniPortName string, tpInstance *TechProfile) error {
+	path := t.GetTechProfileInstanceKVPath(ctx, techProfiletblID, uniPortName)
+	logger.Debugw(ctx, "Adding techprof instance to kvstore", log.Fields{"key": path, "tpinstance": tpInstance})
+	tpInstanceJson, err := json.Marshal(*tpInstance)
+	if err == nil {
+		// Backend will convert JSON byte array into string format
+		logger.Debugw(ctx, "Storing tech profile instance to KV Store", log.Fields{"key": path, "val": tpInstanceJson})
+		err = t.config.KVBackend.Put(ctx, path, tpInstanceJson)
+	} else {
+		logger.Errorw(ctx, "Error in marshaling into Json format", log.Fields{"key": path, "tpinstance": tpInstance})
+	}
+	return err
+}
+
+func (t *TechProfileMgr) addEponProfInstanceToKVStore(ctx context.Context, techProfiletblID uint32, uniPortName string, tpInstance *EponProfile) error {
+	path := t.GetTechProfileInstanceKVPath(ctx, techProfiletblID, uniPortName)
+	logger.Debugw(ctx, "Adding techprof instance to kvstore", log.Fields{"key": path, "tpinstance": tpInstance})
+	tpInstanceJson, err := json.Marshal(*tpInstance)
+	if err == nil {
+		// Backend will convert JSON byte array into string format
+		logger.Debugw(ctx, "Storing tech profile instance to KV Store", log.Fields{"key": path, "val": tpInstanceJson})
+		err = t.config.KVBackend.Put(ctx, path, tpInstanceJson)
+	} else {
+		logger.Errorw(ctx, "Error in marshaling into Json format", log.Fields{"key": path, "tpinstance": tpInstance})
+	}
+	return err
+}
+
+func (t *TechProfileMgr) getTPFromKVStore(ctx context.Context, techProfiletblID uint32) *DefaultTechProfile {
+	var kvtechprofile DefaultTechProfile
+	key := fmt.Sprintf(t.config.TPFileKVPath, t.resourceMgr.GetTechnology(), techProfiletblID)
+	logger.Debugw(ctx, "Getting techprofile from KV store", log.Fields{"techProfiletblID": techProfiletblID, "Key": key})
+	kvresult, err := t.config.KVBackend.Get(ctx, key)
+	if err != nil {
+		logger.Errorw(ctx, "Error while fetching value from KV store", log.Fields{"key": key})
+		return nil
+	}
+	if kvresult != nil {
+		/* Backend will return Value in string format,needs to be converted to []byte before unmarshal*/
+		if value, err := kvstore.ToByte(kvresult.Value); err == nil {
+			if err = json.Unmarshal(value, &kvtechprofile); err != nil {
+				logger.Errorw(ctx, "Error unmarshaling techprofile fetched from KV store", log.Fields{"techProfiletblID": techProfiletblID, "error": err, "techprofile_json": value})
+				return nil
+			}
+
+			logger.Debugw(ctx, "Success fetched techprofile from KV store", log.Fields{"techProfiletblID": techProfiletblID, "value": kvtechprofile})
+			return &kvtechprofile
+		}
+	}
+	return nil
+}
+
+func (t *TechProfileMgr) getEponTPFromKVStore(ctx context.Context, techProfiletblID uint32) *DefaultEponProfile {
+	var kvtechprofile DefaultEponProfile
+	key := fmt.Sprintf(t.config.TPFileKVPath, t.resourceMgr.GetTechnology(), techProfiletblID)
+	logger.Debugw(ctx, "Getting techprofile from KV store", log.Fields{"techProfiletblID": techProfiletblID, "Key": key})
+	kvresult, err := t.config.KVBackend.Get(ctx, key)
+	if err != nil {
+		logger.Errorw(ctx, "Error while fetching value from KV store", log.Fields{"key": key})
+		return nil
+	}
+	if kvresult != nil {
+		/* Backend will return Value in string format,needs to be converted to []byte before unmarshal*/
+		if value, err := kvstore.ToByte(kvresult.Value); err == nil {
+			if err = json.Unmarshal(value, &kvtechprofile); err != nil {
+				logger.Errorw(ctx, "Error unmarshaling techprofile fetched from KV store", log.Fields{"techProfiletblID": techProfiletblID, "error": err, "techprofile_json": value})
+				return nil
+			}
+
+			logger.Debugw(ctx, "Success fetched techprofile from KV store", log.Fields{"techProfiletblID": techProfiletblID, "value": kvtechprofile})
+			return &kvtechprofile
+		}
+	}
+	return nil
+}
+
+func (t *TechProfileMgr) CreateTechProfInstance(ctx context.Context, techProfiletblID uint32, uniPortName string, intfId uint32) (interface{}, error) {
+	var tpInstance *TechProfile
+	var tpEponInstance *EponProfile
+
+	logger.Infow(ctx, "creating-tp-instance", log.Fields{"tableid": techProfiletblID, "uni": uniPortName, "intId": intfId})
+
+	// Make sure the uniPortName is as per format pon-{[0-9]+}/onu-{[0-9]+}/uni-{[0-9]+}
+	if !uniPortNameFormat.Match([]byte(uniPortName)) {
+		logger.Errorw(ctx, "uni-port-name-not-confirming-to-format", log.Fields{"uniPortName": uniPortName})
+		return nil, errors.New("uni-port-name-not-confirming-to-format")
+	}
+	tpInstancePath := t.GetTechProfileInstanceKVPath(ctx, techProfiletblID, uniPortName)
+	// For example:
+	// tpInstPath like "XGS-PON/64/uni_port_name"
+	// is broken into ["XGS-PON" "64" ...]
+	pathSlice := regexp.MustCompile(`/`).Split(tpInstancePath, -1)
+	if pathSlice[0] == epon {
+		tp := t.getEponTPFromKVStore(ctx, techProfiletblID)
+		if tp != nil {
+			if err := t.validateInstanceControlAttr(ctx, tp.InstanceCtrl); err != nil {
+				logger.Error(ctx, "invalid-instance-ctrl-attr--using-default-tp")
+				tp = t.getDefaultEponProfile(ctx)
+			} else {
+				logger.Infow(ctx, "using-specified-tp-from-kv-store", log.Fields{"tpid": techProfiletblID})
+			}
+		} else {
+			logger.Info(ctx, "tp-not-found-on-kv--creating-default-tp")
+			tp = t.getDefaultEponProfile(ctx)
+		}
+
+		if tpEponInstance = t.allocateEponTPInstance(ctx, uniPortName, tp, intfId, tpInstancePath); tpEponInstance == nil {
+			logger.Error(ctx, "tp-intance-allocation-failed")
+			return nil, errors.New("tp-intance-allocation-failed")
+		}
+		if err := t.addEponProfInstanceToKVStore(ctx, techProfiletblID, uniPortName, tpEponInstance); err != nil {
+			logger.Errorw(ctx, "error-adding-tp-to-kv-store", log.Fields{"tableid": techProfiletblID, "uni": uniPortName})
+			return nil, errors.New("error-adding-tp-to-kv-store")
+		}
+		logger.Infow(ctx, "tp-added-to-kv-store-successfully",
+			log.Fields{"tpid": techProfiletblID, "uni": uniPortName, "intfId": intfId})
+		return tpEponInstance, nil
+	} else {
+		tp := t.getTPFromKVStore(ctx, techProfiletblID)
+		if tp != nil {
+			if err := t.validateInstanceControlAttr(ctx, tp.InstanceCtrl); err != nil {
+				logger.Error(ctx, "invalid-instance-ctrl-attr--using-default-tp")
+				tp = t.getDefaultTechProfile(ctx)
+			} else {
+				logger.Infow(ctx, "using-specified-tp-from-kv-store", log.Fields{"tpid": techProfiletblID})
+			}
+		} else {
+			logger.Info(ctx, "tp-not-found-on-kv--creating-default-tp")
+			tp = t.getDefaultTechProfile(ctx)
+		}
+
+		if tpInstance = t.allocateTPInstance(ctx, uniPortName, tp, intfId, tpInstancePath); tpInstance == nil {
+			logger.Error(ctx, "tp-intance-allocation-failed")
+			return nil, errors.New("tp-intance-allocation-failed")
+		}
+		if err := t.addTechProfInstanceToKVStore(ctx, techProfiletblID, uniPortName, tpInstance); err != nil {
+			logger.Errorw(ctx, "error-adding-tp-to-kv-store", log.Fields{"tableid": techProfiletblID, "uni": uniPortName})
+			return nil, errors.New("error-adding-tp-to-kv-store")
+		}
+		logger.Infow(ctx, "tp-added-to-kv-store-successfully",
+			log.Fields{"tpid": techProfiletblID, "uni": uniPortName, "intfId": intfId})
+		return tpInstance, nil
+	}
+}
+
+func (t *TechProfileMgr) DeleteTechProfileInstance(ctx context.Context, techProfiletblID uint32, uniPortName string) error {
+	path := t.GetTechProfileInstanceKVPath(ctx, techProfiletblID, uniPortName)
+	return t.config.KVBackend.Delete(ctx, path)
+}
+
+func (t *TechProfileMgr) validateInstanceControlAttr(ctx context.Context, instCtl InstanceControl) error {
+	if instCtl.Onu != "single-instance" && instCtl.Onu != "multi-instance" {
+		logger.Errorw(ctx, "invalid-onu-instance-control-attribute", log.Fields{"onu-inst": instCtl.Onu})
+		return errors.New("invalid-onu-instance-ctl-attr")
+	}
+
+	if instCtl.Uni != "single-instance" && instCtl.Uni != "multi-instance" {
+		logger.Errorw(ctx, "invalid-uni-instance-control-attribute", log.Fields{"uni-inst": instCtl.Uni})
+		return errors.New("invalid-uni-instance-ctl-attr")
+	}
+
+	if instCtl.Uni == "multi-instance" {
+		logger.Error(ctx, "uni-multi-instance-tp-not-supported")
+		return errors.New("uni-multi-instance-tp-not-supported")
+	}
+
+	return nil
+}
+
+func (t *TechProfileMgr) allocateTPInstance(ctx context.Context, uniPortName string, tp *DefaultTechProfile, intfId uint32, tpInstPath string) *TechProfile {
+
+	var usGemPortAttributeList []IGemPortAttribute
+	var dsGemPortAttributeList []IGemPortAttribute
+	var dsMulticastGemAttributeList []IGemPortAttribute
+	var dsUnicastGemAttributeList []IGemPortAttribute
+	var tcontIDs []uint32
+	var gemPorts []uint32
+	var err error
+
+	logger.Infow(ctx, "Allocating TechProfileMgr instance from techprofile template", log.Fields{"uniPortName": uniPortName, "intfId": intfId, "numGem": tp.NumGemPorts})
+
+	if tp.InstanceCtrl.Onu == "multi-instance" {
+		t.AllocIDMgmtLock.Lock()
+		tcontIDs, err = t.resourceMgr.GetResourceID(ctx, intfId, t.resourceMgr.GetResourceTypeAllocID(), 1)
+		t.AllocIDMgmtLock.Unlock()
+		if err != nil {
+			logger.Errorw(ctx, "Error getting alloc id from rsrcrMgr", log.Fields{"intfId": intfId})
+			return nil
+		}
+	} else { // "single-instance"
+		if tpInst, err := t.getSingleInstanceTp(ctx, tpInstPath); err != nil {
+			logger.Errorw(ctx, "Error getting alloc id from rsrcrMgr", log.Fields{"intfId": intfId})
+			return nil
+		} else if tpInst == nil {
+			// No "single-instance" tp found on one any uni port for the given TP ID
+			// Allocate a new TcontID or AllocID
+			t.AllocIDMgmtLock.Lock()
+			tcontIDs, err = t.resourceMgr.GetResourceID(ctx, intfId, t.resourceMgr.GetResourceTypeAllocID(), 1)
+			t.AllocIDMgmtLock.Unlock()
+			if err != nil {
+				logger.Errorw(ctx, "Error getting alloc id from rsrcrMgr", log.Fields{"intfId": intfId})
+				return nil
+			}
+		} else {
+			// Use the alloc-id from the existing TpInstance
+			tcontIDs = append(tcontIDs, tpInst.UsScheduler.AllocID)
+		}
+	}
+	logger.Debugw(ctx, "Num GEM ports in TP:", log.Fields{"NumGemPorts": tp.NumGemPorts})
+	t.GemPortIDMgmtLock.Lock()
+	gemPorts, err = t.resourceMgr.GetResourceID(ctx, intfId, t.resourceMgr.GetResourceTypeGemPortID(), tp.NumGemPorts)
+	t.GemPortIDMgmtLock.Unlock()
+	if err != nil {
+		logger.Errorw(ctx, "Error getting gemport ids from rsrcrMgr", log.Fields{"intfId": intfId, "numGemports": tp.NumGemPorts})
+		return nil
+	}
+	logger.Infow(ctx, "Allocated tconts and GEM ports successfully", log.Fields{"tconts": tcontIDs, "gemports": gemPorts})
+	for index := 0; index < int(tp.NumGemPorts); index++ {
+		usGemPortAttributeList = append(usGemPortAttributeList,
+			IGemPortAttribute{GemportID: gemPorts[index],
+				MaxQueueSize:     tp.UpstreamGemPortAttributeList[index].MaxQueueSize,
+				PbitMap:          tp.UpstreamGemPortAttributeList[index].PbitMap,
+				AesEncryption:    tp.UpstreamGemPortAttributeList[index].AesEncryption,
+				SchedulingPolicy: tp.UpstreamGemPortAttributeList[index].SchedulingPolicy,
+				PriorityQueue:    tp.UpstreamGemPortAttributeList[index].PriorityQueue,
+				Weight:           tp.UpstreamGemPortAttributeList[index].Weight,
+				DiscardPolicy:    tp.UpstreamGemPortAttributeList[index].DiscardPolicy,
+				DiscardConfig:    tp.UpstreamGemPortAttributeList[index].DiscardConfig})
+	}
+
+	logger.Info(ctx, "length of DownstreamGemPortAttributeList", len(tp.DownstreamGemPortAttributeList))
+	//put multicast and unicast downstream GEM port attributes in different lists first
+	for index := 0; index < int(len(tp.DownstreamGemPortAttributeList)); index++ {
+		if isMulticastGem(tp.DownstreamGemPortAttributeList[index].IsMulticast) {
+			dsMulticastGemAttributeList = append(dsMulticastGemAttributeList,
+				IGemPortAttribute{
+					McastGemID:       tp.DownstreamGemPortAttributeList[index].McastGemID,
+					MaxQueueSize:     tp.DownstreamGemPortAttributeList[index].MaxQueueSize,
+					PbitMap:          tp.DownstreamGemPortAttributeList[index].PbitMap,
+					AesEncryption:    tp.DownstreamGemPortAttributeList[index].AesEncryption,
+					SchedulingPolicy: tp.DownstreamGemPortAttributeList[index].SchedulingPolicy,
+					PriorityQueue:    tp.DownstreamGemPortAttributeList[index].PriorityQueue,
+					Weight:           tp.DownstreamGemPortAttributeList[index].Weight,
+					DiscardPolicy:    tp.DownstreamGemPortAttributeList[index].DiscardPolicy,
+					DiscardConfig:    tp.DownstreamGemPortAttributeList[index].DiscardConfig,
+					IsMulticast:      tp.DownstreamGemPortAttributeList[index].IsMulticast,
+					DControlList:     tp.DownstreamGemPortAttributeList[index].DControlList,
+					SControlList:     tp.DownstreamGemPortAttributeList[index].SControlList})
+		} else {
+			dsUnicastGemAttributeList = append(dsUnicastGemAttributeList,
+				IGemPortAttribute{
+					MaxQueueSize:     tp.DownstreamGemPortAttributeList[index].MaxQueueSize,
+					PbitMap:          tp.DownstreamGemPortAttributeList[index].PbitMap,
+					AesEncryption:    tp.DownstreamGemPortAttributeList[index].AesEncryption,
+					SchedulingPolicy: tp.DownstreamGemPortAttributeList[index].SchedulingPolicy,
+					PriorityQueue:    tp.DownstreamGemPortAttributeList[index].PriorityQueue,
+					Weight:           tp.DownstreamGemPortAttributeList[index].Weight,
+					DiscardPolicy:    tp.DownstreamGemPortAttributeList[index].DiscardPolicy,
+					DiscardConfig:    tp.DownstreamGemPortAttributeList[index].DiscardConfig})
+		}
+	}
+	//add unicast downstream GEM ports to dsGemPortAttributeList
+	for index := 0; index < int(tp.NumGemPorts); index++ {
+		dsGemPortAttributeList = append(dsGemPortAttributeList,
+			IGemPortAttribute{GemportID: gemPorts[index],
+				MaxQueueSize:     dsUnicastGemAttributeList[index].MaxQueueSize,
+				PbitMap:          dsUnicastGemAttributeList[index].PbitMap,
+				AesEncryption:    dsUnicastGemAttributeList[index].AesEncryption,
+				SchedulingPolicy: dsUnicastGemAttributeList[index].SchedulingPolicy,
+				PriorityQueue:    dsUnicastGemAttributeList[index].PriorityQueue,
+				Weight:           dsUnicastGemAttributeList[index].Weight,
+				DiscardPolicy:    dsUnicastGemAttributeList[index].DiscardPolicy,
+				DiscardConfig:    dsUnicastGemAttributeList[index].DiscardConfig})
+	}
+	//add multicast GEM ports to dsGemPortAttributeList afterwards
+	for k := range dsMulticastGemAttributeList {
+		dsGemPortAttributeList = append(dsGemPortAttributeList, dsMulticastGemAttributeList[k])
+	}
+
+	return &TechProfile{
+		SubscriberIdentifier: uniPortName,
+		Name:                 tp.Name,
+		ProfileType:          tp.ProfileType,
+		Version:              tp.Version,
+		NumGemPorts:          tp.NumGemPorts,
+		InstanceCtrl:         tp.InstanceCtrl,
+		UsScheduler: IScheduler{
+			AllocID:      tcontIDs[0],
+			Direction:    tp.UsScheduler.Direction,
+			AdditionalBw: tp.UsScheduler.AdditionalBw,
+			Priority:     tp.UsScheduler.Priority,
+			Weight:       tp.UsScheduler.Weight,
+			QSchedPolicy: tp.UsScheduler.QSchedPolicy},
+		DsScheduler: IScheduler{
+			AllocID:      tcontIDs[0],
+			Direction:    tp.DsScheduler.Direction,
+			AdditionalBw: tp.DsScheduler.AdditionalBw,
+			Priority:     tp.DsScheduler.Priority,
+			Weight:       tp.DsScheduler.Weight,
+			QSchedPolicy: tp.DsScheduler.QSchedPolicy},
+		UpstreamGemPortAttributeList:   usGemPortAttributeList,
+		DownstreamGemPortAttributeList: dsGemPortAttributeList}
+}
+
+// allocateTPInstance function for EPON
+func (t *TechProfileMgr) allocateEponTPInstance(ctx context.Context, uniPortName string, tp *DefaultEponProfile, intfId uint32, tpInstPath string) *EponProfile {
+
+	var usQueueAttributeList []iUpstreamQueueAttribute
+	var dsQueueAttributeList []iDownstreamQueueAttribute
+	var tcontIDs []uint32
+	var gemPorts []uint32
+	var err error
+
+	logger.Infow(ctx, "Allocating TechProfileMgr instance from techprofile template", log.Fields{"uniPortName": uniPortName, "intfId": intfId, "numGem": tp.NumGemPorts})
+
+	if tp.InstanceCtrl.Onu == "multi-instance" {
+		if tcontIDs, err = t.resourceMgr.GetResourceID(ctx, intfId, t.resourceMgr.GetResourceTypeAllocID(), 1); err != nil {
+			logger.Errorw(ctx, "Error getting alloc id from rsrcrMgr", log.Fields{"intfId": intfId})
+			return nil
+		}
+	} else { // "single-instance"
+		if tpInst, err := t.getSingleInstanceEponTp(ctx, tpInstPath); err != nil {
+			logger.Errorw(ctx, "Error getting alloc id from rsrcrMgr", log.Fields{"intfId": intfId})
+			return nil
+		} else if tpInst == nil {
+			// No "single-instance" tp found on one any uni port for the given TP ID
+			// Allocate a new TcontID or AllocID
+			if tcontIDs, err = t.resourceMgr.GetResourceID(ctx, intfId, t.resourceMgr.GetResourceTypeAllocID(), 1); err != nil {
+				logger.Errorw(ctx, "Error getting alloc id from rsrcrMgr", log.Fields{"intfId": intfId})
+				return nil
+			}
+		} else {
+			// Use the alloc-id from the existing TpInstance
+			tcontIDs = append(tcontIDs, tpInst.AllocID)
+		}
+	}
+	logger.Debugw(ctx, "Num GEM ports in TP:", log.Fields{"NumGemPorts": tp.NumGemPorts})
+	if gemPorts, err = t.resourceMgr.GetResourceID(ctx, intfId, t.resourceMgr.GetResourceTypeGemPortID(), tp.NumGemPorts); err != nil {
+		logger.Errorw(ctx, "Error getting gemport ids from rsrcrMgr", log.Fields{"intfId": intfId, "numGemports": tp.NumGemPorts})
+		return nil
+	}
+	logger.Infow(ctx, "Allocated tconts and GEM ports successfully", log.Fields{"tconts": tcontIDs, "gemports": gemPorts})
+	for index := 0; index < int(tp.NumGemPorts); index++ {
+		usQueueAttributeList = append(usQueueAttributeList,
+			iUpstreamQueueAttribute{GemportID: gemPorts[index],
+				MaxQueueSize:              tp.UpstreamQueueAttributeList[index].MaxQueueSize,
+				PbitMap:                   tp.UpstreamQueueAttributeList[index].PbitMap,
+				AesEncryption:             tp.UpstreamQueueAttributeList[index].AesEncryption,
+				TrafficType:               tp.UpstreamQueueAttributeList[index].TrafficType,
+				UnsolicitedGrantSize:      tp.UpstreamQueueAttributeList[index].UnsolicitedGrantSize,
+				NominalInterval:           tp.UpstreamQueueAttributeList[index].NominalInterval,
+				ToleratedPollJitter:       tp.UpstreamQueueAttributeList[index].ToleratedPollJitter,
+				RequestTransmissionPolicy: tp.UpstreamQueueAttributeList[index].RequestTransmissionPolicy,
+				NumQueueSet:               tp.UpstreamQueueAttributeList[index].NumQueueSet,
+				QThresholds:               tp.UpstreamQueueAttributeList[index].QThresholds,
+				SchedulingPolicy:          tp.UpstreamQueueAttributeList[index].SchedulingPolicy,
+				PriorityQueue:             tp.UpstreamQueueAttributeList[index].PriorityQueue,
+				Weight:                    tp.UpstreamQueueAttributeList[index].Weight,
+				DiscardPolicy:             tp.UpstreamQueueAttributeList[index].DiscardPolicy,
+				DiscardConfig:             tp.UpstreamQueueAttributeList[index].DiscardConfig})
+	}
+
+	logger.Info(ctx, "length of DownstreamGemPortAttributeList", len(tp.DownstreamQueueAttributeList))
+	for index := 0; index < int(tp.NumGemPorts); index++ {
+		dsQueueAttributeList = append(dsQueueAttributeList,
+			iDownstreamQueueAttribute{GemportID: gemPorts[index],
+				MaxQueueSize:     tp.DownstreamQueueAttributeList[index].MaxQueueSize,
+				PbitMap:          tp.DownstreamQueueAttributeList[index].PbitMap,
+				AesEncryption:    tp.DownstreamQueueAttributeList[index].AesEncryption,
+				SchedulingPolicy: tp.DownstreamQueueAttributeList[index].SchedulingPolicy,
+				PriorityQueue:    tp.DownstreamQueueAttributeList[index].PriorityQueue,
+				Weight:           tp.DownstreamQueueAttributeList[index].Weight,
+				DiscardPolicy:    tp.DownstreamQueueAttributeList[index].DiscardPolicy,
+				DiscardConfig:    tp.DownstreamQueueAttributeList[index].DiscardConfig})
+	}
+
+	return &EponProfile{
+		SubscriberIdentifier:         uniPortName,
+		Name:                         tp.Name,
+		ProfileType:                  tp.ProfileType,
+		Version:                      tp.Version,
+		NumGemPorts:                  tp.NumGemPorts,
+		InstanceCtrl:                 tp.InstanceCtrl,
+		EponAttribute:                tp.EponAttribute,
+		AllocID:                      tcontIDs[0],
+		UpstreamQueueAttributeList:   usQueueAttributeList,
+		DownstreamQueueAttributeList: dsQueueAttributeList}
+}
+
+// getSingleInstanceTp returns another TpInstance for an ONU on a different
+// uni port for the same TP ID, if it finds one, else nil.
+func (t *TechProfileMgr) getSingleInstanceTp(ctx context.Context, tpPath string) (*TechProfile, error) {
+	var tpInst TechProfile
+
+	// For example:
+	// tpPath like "service/voltha/technology_profiles/xgspon/64/pon-{0}/onu-{1}/uni-{1}"
+	// is broken into ["service/voltha/technology_profiles/xgspon/64/pon-{0}/onu-{1}" ""]
+	uniPathSlice := regexp.MustCompile(`/uni-{[0-9]+}$`).Split(tpPath, 2)
+	kvPairs, _ := t.config.KVBackend.List(ctx, uniPathSlice[0])
+
+	// Find a valid TP Instance among all the UNIs of that ONU for the given TP ID
+	for keyPath, kvPair := range kvPairs {
+		if value, err := kvstore.ToByte(kvPair.Value); err == nil {
+			if err = json.Unmarshal(value, &tpInst); err != nil {
+				logger.Errorw(ctx, "error-unmarshal-kv-pair", log.Fields{"keyPath": keyPath, "value": value})
+				return nil, errors.New("error-unmarshal-kv-pair")
+			} else {
+				logger.Debugw(ctx, "found-valid-tp-instance-on-another-uni", log.Fields{"keyPath": keyPath})
+				return &tpInst, nil
+			}
+		}
+	}
+	return nil, nil
+}
+
+func (t *TechProfileMgr) getSingleInstanceEponTp(ctx context.Context, tpPath string) (*EponProfile, error) {
+	var tpInst EponProfile
+
+	// For example:
+	// tpPath like "service/voltha/technology_profiles/xgspon/64/pon-{0}/onu-{1}/uni-{1}"
+	// is broken into ["service/voltha/technology_profiles/xgspon/64/pon-{0}/onu-{1}" ""]
+	uniPathSlice := regexp.MustCompile(`/uni-{[0-9]+}$`).Split(tpPath, 2)
+	kvPairs, _ := t.config.KVBackend.List(ctx, uniPathSlice[0])
+
+	// Find a valid TP Instance among all the UNIs of that ONU for the given TP ID
+	for keyPath, kvPair := range kvPairs {
+		if value, err := kvstore.ToByte(kvPair.Value); err == nil {
+			if err = json.Unmarshal(value, &tpInst); err != nil {
+				logger.Errorw(ctx, "error-unmarshal-kv-pair", log.Fields{"keyPath": keyPath, "value": value})
+				return nil, errors.New("error-unmarshal-kv-pair")
+			} else {
+				logger.Debugw(ctx, "found-valid-tp-instance-on-another-uni", log.Fields{"keyPath": keyPath})
+				return &tpInst, nil
+			}
+		}
+	}
+	return nil, nil
+}
+
+func (t *TechProfileMgr) getDefaultTechProfile(ctx context.Context) *DefaultTechProfile {
+	var usGemPortAttributeList []GemPortAttribute
+	var dsGemPortAttributeList []GemPortAttribute
+
+	for _, pbit := range t.config.DefaultPbits {
+		logger.Debugw(ctx, "Creating GEM port", log.Fields{"pbit": pbit})
+		usGemPortAttributeList = append(usGemPortAttributeList,
+			GemPortAttribute{
+				MaxQueueSize:     defaultMaxQueueSize,
+				PbitMap:          pbit,
+				AesEncryption:    defaultAESEncryption,
+				SchedulingPolicy: SchedulingPolicy_name[defaultSchedulePolicy],
+				PriorityQueue:    defaultPriorityQueue,
+				Weight:           defaultQueueWeight,
+				DiscardPolicy:    DiscardPolicy_name[defaultdropPolicy],
+				DiscardConfig: DiscardConfig{
+					MinThreshold:   defaultMinThreshold,
+					MaxThreshold:   defaultMaxThreshold,
+					MaxProbability: defaultMaxProbability}})
+		dsGemPortAttributeList = append(dsGemPortAttributeList,
+			GemPortAttribute{
+				MaxQueueSize:     defaultMaxQueueSize,
+				PbitMap:          pbit,
+				AesEncryption:    defaultAESEncryption,
+				SchedulingPolicy: SchedulingPolicy_name[defaultSchedulePolicy],
+				PriorityQueue:    defaultPriorityQueue,
+				Weight:           defaultQueueWeight,
+				DiscardPolicy:    DiscardPolicy_name[defaultdropPolicy],
+				DiscardConfig: DiscardConfig{
+					MinThreshold:   defaultMinThreshold,
+					MaxThreshold:   defaultMaxThreshold,
+					MaxProbability: defaultMaxProbability},
+				IsMulticast:  defaultIsMulticast,
+				DControlList: defaultAccessControlList,
+				SControlList: defaultAccessControlList,
+				McastGemID:   defaultMcastGemID})
+	}
+	return &DefaultTechProfile{
+		Name:        t.config.DefaultTPName,
+		ProfileType: t.resourceMgr.GetTechnology(),
+		Version:     t.config.TPVersion,
+		NumGemPorts: uint32(len(usGemPortAttributeList)),
+		InstanceCtrl: InstanceControl{
+			Onu:               defaultOnuInstance,
+			Uni:               defaultUniInstance,
+			MaxGemPayloadSize: defaultGemPayloadSize},
+		UsScheduler: Scheduler{
+			Direction:    Direction_name[Direction_UPSTREAM],
+			AdditionalBw: AdditionalBW_name[defaultAdditionalBw],
+			Priority:     defaultPriority,
+			Weight:       defaultWeight,
+			QSchedPolicy: SchedulingPolicy_name[defaultQueueSchedPolicy]},
+		DsScheduler: Scheduler{
+			Direction:    Direction_name[Direction_DOWNSTREAM],
+			AdditionalBw: AdditionalBW_name[defaultAdditionalBw],
+			Priority:     defaultPriority,
+			Weight:       defaultWeight,
+			QSchedPolicy: SchedulingPolicy_name[defaultQueueSchedPolicy]},
+		UpstreamGemPortAttributeList:   usGemPortAttributeList,
+		DownstreamGemPortAttributeList: dsGemPortAttributeList}
+}
+
+// getDefaultTechProfile function for EPON
+func (t *TechProfileMgr) getDefaultEponProfile(ctx context.Context) *DefaultEponProfile {
+
+	var usQueueAttributeList []UpstreamQueueAttribute
+	var dsQueueAttributeList []DownstreamQueueAttribute
+
+	for _, pbit := range t.config.DefaultPbits {
+		logger.Debugw(ctx, "Creating Queue", log.Fields{"pbit": pbit})
+		usQueueAttributeList = append(usQueueAttributeList,
+			UpstreamQueueAttribute{
+				MaxQueueSize:              defaultMaxQueueSize,
+				PbitMap:                   pbit,
+				AesEncryption:             defaultAESEncryption,
+				TrafficType:               defaultTrafficType,
+				UnsolicitedGrantSize:      defaultUnsolicitedGrantSize,
+				NominalInterval:           defaultNominalInterval,
+				ToleratedPollJitter:       defaultToleratedPollJitter,
+				RequestTransmissionPolicy: defaultRequestTransmissionPolicy,
+				NumQueueSet:               defaultNumQueueSet,
+				QThresholds: QThresholds{
+					QThreshold1: defaultQThreshold1,
+					QThreshold2: defaultQThreshold2,
+					QThreshold3: defaultQThreshold3,
+					QThreshold4: defaultQThreshold4,
+					QThreshold5: defaultQThreshold5,
+					QThreshold6: defaultQThreshold6,
+					QThreshold7: defaultQThreshold7},
+				SchedulingPolicy: SchedulingPolicy_name[defaultSchedulePolicy],
+				PriorityQueue:    defaultPriorityQueue,
+				Weight:           defaultQueueWeight,
+				DiscardPolicy:    DiscardPolicy_name[defaultdropPolicy],
+				DiscardConfig: DiscardConfig{
+					MinThreshold:   defaultMinThreshold,
+					MaxThreshold:   defaultMaxThreshold,
+					MaxProbability: defaultMaxProbability}})
+		dsQueueAttributeList = append(dsQueueAttributeList,
+			DownstreamQueueAttribute{
+				MaxQueueSize:     defaultMaxQueueSize,
+				PbitMap:          pbit,
+				AesEncryption:    defaultAESEncryption,
+				SchedulingPolicy: SchedulingPolicy_name[defaultSchedulePolicy],
+				PriorityQueue:    defaultPriorityQueue,
+				Weight:           defaultQueueWeight,
+				DiscardPolicy:    DiscardPolicy_name[defaultdropPolicy],
+				DiscardConfig: DiscardConfig{
+					MinThreshold:   defaultMinThreshold,
+					MaxThreshold:   defaultMaxThreshold,
+					MaxProbability: defaultMaxProbability}})
+	}
+	return &DefaultEponProfile{
+		Name:        t.config.DefaultTPName,
+		ProfileType: t.resourceMgr.GetTechnology(),
+		Version:     t.config.TPVersion,
+		NumGemPorts: uint32(len(usQueueAttributeList)),
+		InstanceCtrl: InstanceControl{
+			Onu:               defaultOnuInstance,
+			Uni:               defaultUniInstance,
+			MaxGemPayloadSize: defaultGemPayloadSize},
+		EponAttribute: EponAttribute{
+			PackageType: defaultPakageType},
+		UpstreamQueueAttributeList:   usQueueAttributeList,
+		DownstreamQueueAttributeList: dsQueueAttributeList}
+}
+
+func (t *TechProfileMgr) GetprotoBufParamValue(ctx context.Context, paramType string, paramKey string) int32 {
+	var result int32 = -1
+
+	if paramType == "direction" {
+		for key, val := range tp_pb.Direction_value {
+			if key == paramKey {
+				result = val
+			}
+		}
+	} else if paramType == "discard_policy" {
+		for key, val := range tp_pb.DiscardPolicy_value {
+			if key == paramKey {
+				result = val
+			}
+		}
+	} else if paramType == "sched_policy" {
+		for key, val := range tp_pb.SchedulingPolicy_value {
+			if key == paramKey {
+				logger.Debugw(ctx, "Got value in proto", log.Fields{"key": key, "value": val})
+				result = val
+			}
+		}
+	} else if paramType == "additional_bw" {
+		for key, val := range tp_pb.AdditionalBW_value {
+			if key == paramKey {
+				result = val
+			}
+		}
+	} else {
+		logger.Error(ctx, "Could not find proto parameter", log.Fields{"paramType": paramType, "key": paramKey})
+		return -1
+	}
+	logger.Debugw(ctx, "Got value in proto", log.Fields{"key": paramKey, "value": result})
+	return result
+}
+
+func (t *TechProfileMgr) GetUsScheduler(ctx context.Context, tpInstance *TechProfile) (*tp_pb.SchedulerConfig, error) {
+	dir := tp_pb.Direction(t.GetprotoBufParamValue(ctx, "direction", tpInstance.UsScheduler.Direction))
+	if dir == -1 {
+		logger.Errorf(ctx, "Error in getting proto id for direction %s for upstream scheduler", tpInstance.UsScheduler.Direction)
+		return nil, fmt.Errorf("unable to get proto id for direction %s for upstream scheduler", tpInstance.UsScheduler.Direction)
+	}
+
+	bw := tp_pb.AdditionalBW(t.GetprotoBufParamValue(ctx, "additional_bw", tpInstance.UsScheduler.AdditionalBw))
+	if bw == -1 {
+		logger.Errorf(ctx, "Error in getting proto id for bandwidth %s for upstream scheduler", tpInstance.UsScheduler.AdditionalBw)
+		return nil, fmt.Errorf("unable to get proto id for bandwidth %s for upstream scheduler", tpInstance.UsScheduler.AdditionalBw)
+	}
+
+	policy := tp_pb.SchedulingPolicy(t.GetprotoBufParamValue(ctx, "sched_policy", tpInstance.UsScheduler.QSchedPolicy))
+	if policy == -1 {
+		logger.Errorf(ctx, "Error in getting proto id for scheduling policy %s for upstream scheduler", tpInstance.UsScheduler.QSchedPolicy)
+		return nil, fmt.Errorf("unable to get proto id for scheduling policy %s for upstream scheduler", tpInstance.UsScheduler.QSchedPolicy)
+	}
+
+	return &tp_pb.SchedulerConfig{
+		Direction:    dir,
+		AdditionalBw: bw,
+		Priority:     tpInstance.UsScheduler.Priority,
+		Weight:       tpInstance.UsScheduler.Weight,
+		SchedPolicy:  policy}, nil
+}
+
+func (t *TechProfileMgr) GetDsScheduler(ctx context.Context, tpInstance *TechProfile) (*tp_pb.SchedulerConfig, error) {
+
+	dir := tp_pb.Direction(t.GetprotoBufParamValue(ctx, "direction", tpInstance.DsScheduler.Direction))
+	if dir == -1 {
+		logger.Errorf(ctx, "Error in getting proto id for direction %s for downstream scheduler", tpInstance.DsScheduler.Direction)
+		return nil, fmt.Errorf("unable to get proto id for direction %s for downstream scheduler", tpInstance.DsScheduler.Direction)
+	}
+
+	bw := tp_pb.AdditionalBW(t.GetprotoBufParamValue(ctx, "additional_bw", tpInstance.DsScheduler.AdditionalBw))
+	if bw == -1 {
+		logger.Errorf(ctx, "Error in getting proto id for bandwidth %s for downstream scheduler", tpInstance.DsScheduler.AdditionalBw)
+		return nil, fmt.Errorf("unable to get proto id for bandwidth %s for downstream scheduler", tpInstance.DsScheduler.AdditionalBw)
+	}
+
+	policy := tp_pb.SchedulingPolicy(t.GetprotoBufParamValue(ctx, "sched_policy", tpInstance.DsScheduler.QSchedPolicy))
+	if policy == -1 {
+		logger.Errorf(ctx, "Error in getting proto id for scheduling policy %s for downstream scheduler", tpInstance.DsScheduler.QSchedPolicy)
+		return nil, fmt.Errorf("unable to get proto id for scheduling policy %s for downstream scheduler", tpInstance.DsScheduler.QSchedPolicy)
+	}
+
+	return &tp_pb.SchedulerConfig{
+		Direction:    dir,
+		AdditionalBw: bw,
+		Priority:     tpInstance.DsScheduler.Priority,
+		Weight:       tpInstance.DsScheduler.Weight,
+		SchedPolicy:  policy}, nil
+}
+
+func (t *TechProfileMgr) GetTrafficScheduler(tpInstance *TechProfile, SchedCfg *tp_pb.SchedulerConfig,
+	ShapingCfg *tp_pb.TrafficShapingInfo) *tp_pb.TrafficScheduler {
+
+	tSched := &tp_pb.TrafficScheduler{
+		Direction:          SchedCfg.Direction,
+		AllocId:            tpInstance.UsScheduler.AllocID,
+		TrafficShapingInfo: ShapingCfg,
+		Scheduler:          SchedCfg}
+
+	return tSched
+}
+
+func (tpm *TechProfileMgr) GetTrafficQueues(ctx context.Context, tp *TechProfile, Dir tp_pb.Direction) ([]*tp_pb.TrafficQueue, error) {
+
+	var encryp bool
+	if Dir == tp_pb.Direction_UPSTREAM {
+		// upstream GEM ports
+		NumGemPorts := len(tp.UpstreamGemPortAttributeList)
+		GemPorts := make([]*tp_pb.TrafficQueue, 0)
+		for Count := 0; Count < NumGemPorts; Count++ {
+			if tp.UpstreamGemPortAttributeList[Count].AesEncryption == "True" {
+				encryp = true
+			} else {
+				encryp = false
+			}
+
+			schedPolicy := tpm.GetprotoBufParamValue(ctx, "sched_policy", tp.UpstreamGemPortAttributeList[Count].SchedulingPolicy)
+			if schedPolicy == -1 {
+				logger.Errorf(ctx, "Error in getting Proto Id for scheduling policy %s for Upstream Gem Port %d", tp.UpstreamGemPortAttributeList[Count].SchedulingPolicy, Count)
+				return nil, fmt.Errorf("upstream gem port traffic queue creation failed due to unrecognized scheduling policy %s", tp.UpstreamGemPortAttributeList[Count].SchedulingPolicy)
+			}
+
+			discardPolicy := tpm.GetprotoBufParamValue(ctx, "discard_policy", tp.UpstreamGemPortAttributeList[Count].DiscardPolicy)
+			if discardPolicy == -1 {
+				logger.Errorf(ctx, "Error in getting Proto Id for discard policy %s for Upstream Gem Port %d", tp.UpstreamGemPortAttributeList[Count].DiscardPolicy, Count)
+				return nil, fmt.Errorf("upstream gem port traffic queue creation failed due to unrecognized discard policy %s", tp.UpstreamGemPortAttributeList[Count].DiscardPolicy)
+			}
+
+			GemPorts = append(GemPorts, &tp_pb.TrafficQueue{
+				Direction:     tp_pb.Direction(tpm.GetprotoBufParamValue(ctx, "direction", tp.UsScheduler.Direction)),
+				GemportId:     tp.UpstreamGemPortAttributeList[Count].GemportID,
+				PbitMap:       tp.UpstreamGemPortAttributeList[Count].PbitMap,
+				AesEncryption: encryp,
+				SchedPolicy:   tp_pb.SchedulingPolicy(schedPolicy),
+				Priority:      tp.UpstreamGemPortAttributeList[Count].PriorityQueue,
+				Weight:        tp.UpstreamGemPortAttributeList[Count].Weight,
+				DiscardPolicy: tp_pb.DiscardPolicy(discardPolicy),
+			})
+		}
+		logger.Debugw(ctx, "Upstream Traffic queue list ", log.Fields{"queuelist": GemPorts})
+		return GemPorts, nil
+	} else if Dir == tp_pb.Direction_DOWNSTREAM {
+		//downstream GEM ports
+		NumGemPorts := len(tp.DownstreamGemPortAttributeList)
+		GemPorts := make([]*tp_pb.TrafficQueue, 0)
+		for Count := 0; Count < NumGemPorts; Count++ {
+			if isMulticastGem(tp.DownstreamGemPortAttributeList[Count].IsMulticast) {
+				//do not take multicast GEM ports. They are handled separately.
+				continue
+			}
+			if tp.DownstreamGemPortAttributeList[Count].AesEncryption == "True" {
+				encryp = true
+			} else {
+				encryp = false
+			}
+
+			schedPolicy := tpm.GetprotoBufParamValue(ctx, "sched_policy", tp.DownstreamGemPortAttributeList[Count].SchedulingPolicy)
+			if schedPolicy == -1 {
+				logger.Errorf(ctx, "Error in getting Proto Id for scheduling policy %s for Downstream Gem Port %d", tp.DownstreamGemPortAttributeList[Count].SchedulingPolicy, Count)
+				return nil, fmt.Errorf("downstream gem port traffic queue creation failed due to unrecognized scheduling policy %s", tp.DownstreamGemPortAttributeList[Count].SchedulingPolicy)
+			}
+
+			discardPolicy := tpm.GetprotoBufParamValue(ctx, "discard_policy", tp.DownstreamGemPortAttributeList[Count].DiscardPolicy)
+			if discardPolicy == -1 {
+				logger.Errorf(ctx, "Error in getting Proto Id for discard policy %s for Downstream Gem Port %d", tp.DownstreamGemPortAttributeList[Count].DiscardPolicy, Count)
+				return nil, fmt.Errorf("downstream gem port traffic queue creation failed due to unrecognized discard policy %s", tp.DownstreamGemPortAttributeList[Count].DiscardPolicy)
+			}
+
+			GemPorts = append(GemPorts, &tp_pb.TrafficQueue{
+				Direction:     tp_pb.Direction(tpm.GetprotoBufParamValue(ctx, "direction", tp.DsScheduler.Direction)),
+				GemportId:     tp.DownstreamGemPortAttributeList[Count].GemportID,
+				PbitMap:       tp.DownstreamGemPortAttributeList[Count].PbitMap,
+				AesEncryption: encryp,
+				SchedPolicy:   tp_pb.SchedulingPolicy(schedPolicy),
+				Priority:      tp.DownstreamGemPortAttributeList[Count].PriorityQueue,
+				Weight:        tp.DownstreamGemPortAttributeList[Count].Weight,
+				DiscardPolicy: tp_pb.DiscardPolicy(discardPolicy),
+			})
+		}
+		logger.Debugw(ctx, "Downstream Traffic queue list ", log.Fields{"queuelist": GemPorts})
+		return GemPorts, nil
+	}
+
+	logger.Errorf(ctx, "Unsupported direction %s used for generating Traffic Queue list", Dir)
+	return nil, fmt.Errorf("downstream gem port traffic queue creation failed due to unsupported direction %s", Dir)
+}
+
+//isMulticastGem returns true if isMulticast attribute value of a GEM port is true; false otherwise
+func isMulticastGem(isMulticastAttrValue string) bool {
+	return isMulticastAttrValue != "" &&
+		(isMulticastAttrValue == "True" || isMulticastAttrValue == "true" || isMulticastAttrValue == "TRUE")
+}
+
+func (tpm *TechProfileMgr) GetMulticastTrafficQueues(ctx context.Context, tp *TechProfile) []*tp_pb.TrafficQueue {
+	var encryp bool
+	NumGemPorts := len(tp.DownstreamGemPortAttributeList)
+	mcastTrafficQueues := make([]*tp_pb.TrafficQueue, 0)
+	for Count := 0; Count < NumGemPorts; Count++ {
+		if !isMulticastGem(tp.DownstreamGemPortAttributeList[Count].IsMulticast) {
+			continue
+		}
+		if tp.DownstreamGemPortAttributeList[Count].AesEncryption == "True" {
+			encryp = true
+		} else {
+			encryp = false
+		}
+		mcastTrafficQueues = append(mcastTrafficQueues, &tp_pb.TrafficQueue{
+			Direction:     tp_pb.Direction(tpm.GetprotoBufParamValue(ctx, "direction", tp.DsScheduler.Direction)),
+			GemportId:     tp.DownstreamGemPortAttributeList[Count].McastGemID,
+			PbitMap:       tp.DownstreamGemPortAttributeList[Count].PbitMap,
+			AesEncryption: encryp,
+			SchedPolicy:   tp_pb.SchedulingPolicy(tpm.GetprotoBufParamValue(ctx, "sched_policy", tp.DownstreamGemPortAttributeList[Count].SchedulingPolicy)),
+			Priority:      tp.DownstreamGemPortAttributeList[Count].PriorityQueue,
+			Weight:        tp.DownstreamGemPortAttributeList[Count].Weight,
+			DiscardPolicy: tp_pb.DiscardPolicy(tpm.GetprotoBufParamValue(ctx, "discard_policy", tp.DownstreamGemPortAttributeList[Count].DiscardPolicy)),
+		})
+	}
+	logger.Debugw(ctx, "Downstream Multicast Traffic queue list ", log.Fields{"queuelist": mcastTrafficQueues})
+	return mcastTrafficQueues
+}
+
+func (tpm *TechProfileMgr) GetUsTrafficScheduler(ctx context.Context, tp *TechProfile) *tp_pb.TrafficScheduler {
+	UsScheduler, _ := tpm.GetUsScheduler(ctx, tp)
+
+	return &tp_pb.TrafficScheduler{Direction: UsScheduler.Direction,
+		AllocId:   tp.UsScheduler.AllocID,
+		Scheduler: UsScheduler}
+}
+
+func (t *TechProfileMgr) GetGemportIDForPbit(ctx context.Context, tp interface{}, dir tp_pb.Direction, pbit uint32) uint32 {
+	/*
+	  Function to get the Gemport ID mapped to a pbit.
+	*/
+	switch tp := tp.(type) {
+	case *TechProfile:
+		if dir == tp_pb.Direction_UPSTREAM {
+			// upstream GEM ports
+			numGemPorts := len(tp.UpstreamGemPortAttributeList)
+			for gemCnt := 0; gemCnt < numGemPorts; gemCnt++ {
+				lenOfPbitMap := len(tp.UpstreamGemPortAttributeList[gemCnt].PbitMap)
+				for pbitMapIdx := 2; pbitMapIdx < lenOfPbitMap; pbitMapIdx++ {
+					// Given a sample pbit map string "0b00000001", lenOfPbitMap is 10
+					// "lenOfPbitMap - pbitMapIdx + 1" will give pbit-i th value from LSB position in the pbit map string
+					if p, err := strconv.Atoi(string(tp.UpstreamGemPortAttributeList[gemCnt].PbitMap[lenOfPbitMap-pbitMapIdx+1])); err == nil {
+						if uint32(pbitMapIdx-2) == pbit && p == 1 { // Check this p-bit is set
+							logger.Debugw(ctx, "Found-US-GEMport-for-Pcp", log.Fields{"pbit": pbit, "GEMport": tp.UpstreamGemPortAttributeList[gemCnt].GemportID})
+							return tp.UpstreamGemPortAttributeList[gemCnt].GemportID
+						}
+					}
+				}
+			}
+		} else if dir == tp_pb.Direction_DOWNSTREAM {
+			//downstream GEM ports
+			numGemPorts := len(tp.DownstreamGemPortAttributeList)
+			for gemCnt := 0; gemCnt < numGemPorts; gemCnt++ {
+				lenOfPbitMap := len(tp.DownstreamGemPortAttributeList[gemCnt].PbitMap)
+				for pbitMapIdx := 2; pbitMapIdx < lenOfPbitMap; pbitMapIdx++ {
+					// Given a sample pbit map string "0b00000001", lenOfPbitMap is 10
+					// "lenOfPbitMap - pbitMapIdx + 1" will give pbit-i th value from LSB position in the pbit map string
+					if p, err := strconv.Atoi(string(tp.DownstreamGemPortAttributeList[gemCnt].PbitMap[lenOfPbitMap-pbitMapIdx+1])); err == nil {
+						if uint32(pbitMapIdx-2) == pbit && p == 1 { // Check this p-bit is set
+							logger.Debugw(ctx, "Found-DS-GEMport-for-Pcp", log.Fields{"pbit": pbit, "GEMport": tp.DownstreamGemPortAttributeList[gemCnt].GemportID})
+							return tp.DownstreamGemPortAttributeList[gemCnt].GemportID
+						}
+					}
+				}
+			}
+		}
+		logger.Errorw(ctx, "No-GemportId-Found-For-Pcp", log.Fields{"pcpVlan": pbit})
+	case *EponProfile:
+		if dir == tp_pb.Direction_UPSTREAM {
+			// upstream GEM ports
+			numGemPorts := len(tp.UpstreamQueueAttributeList)
+			for gemCnt := 0; gemCnt < numGemPorts; gemCnt++ {
+				lenOfPbitMap := len(tp.UpstreamQueueAttributeList[gemCnt].PbitMap)
+				for pbitMapIdx := 2; pbitMapIdx < lenOfPbitMap; pbitMapIdx++ {
+					// Given a sample pbit map string "0b00000001", lenOfPbitMap is 10
+					// "lenOfPbitMap - pbitMapIdx + 1" will give pbit-i th value from LSB position in the pbit map string
+					if p, err := strconv.Atoi(string(tp.UpstreamQueueAttributeList[gemCnt].PbitMap[lenOfPbitMap-pbitMapIdx+1])); err == nil {
+						if uint32(pbitMapIdx-2) == pbit && p == 1 { // Check this p-bit is set
+							logger.Debugw(ctx, "Found-US-Queue-for-Pcp", log.Fields{"pbit": pbit, "Queue": tp.UpstreamQueueAttributeList[gemCnt].GemportID})
+							return tp.UpstreamQueueAttributeList[gemCnt].GemportID
+						}
+					}
+				}
+			}
+		} else if dir == tp_pb.Direction_DOWNSTREAM {
+			//downstream GEM ports
+			numGemPorts := len(tp.DownstreamQueueAttributeList)
+			for gemCnt := 0; gemCnt < numGemPorts; gemCnt++ {
+				lenOfPbitMap := len(tp.DownstreamQueueAttributeList[gemCnt].PbitMap)
+				for pbitMapIdx := 2; pbitMapIdx < lenOfPbitMap; pbitMapIdx++ {
+					// Given a sample pbit map string "0b00000001", lenOfPbitMap is 10
+					// "lenOfPbitMap - pbitMapIdx + 1" will give pbit-i th value from LSB position in the pbit map string
+					if p, err := strconv.Atoi(string(tp.DownstreamQueueAttributeList[gemCnt].PbitMap[lenOfPbitMap-pbitMapIdx+1])); err == nil {
+						if uint32(pbitMapIdx-2) == pbit && p == 1 { // Check this p-bit is set
+							logger.Debugw(ctx, "Found-DS-Queue-for-Pcp", log.Fields{"pbit": pbit, "Queue": tp.DownstreamQueueAttributeList[gemCnt].GemportID})
+							return tp.DownstreamQueueAttributeList[gemCnt].GemportID
+						}
+					}
+				}
+			}
+		}
+		logger.Errorw(ctx, "No-QueueId-Found-For-Pcp", log.Fields{"pcpVlan": pbit})
+	default:
+		logger.Errorw(ctx, "unknown-tech", log.Fields{"tp": tp})
+	}
+	return 0
+}
+
+// FindAllTpInstances returns all TechProfile instances for a given TechProfile table-id, pon interface ID and onu ID.
+func (t *TechProfileMgr) FindAllTpInstances(ctx context.Context, techProfiletblID uint32, ponIntf uint32, onuID uint32) interface{} {
+	var tpTech TechProfile
+	var tpEpon EponProfile
+
+	onuTpInstancePath := fmt.Sprintf("%s/%d/pon-{%d}/onu-{%d}", t.resourceMgr.GetTechnology(), techProfiletblID, ponIntf, onuID)
+
+	if kvPairs, _ := t.config.KVBackend.List(ctx, onuTpInstancePath); kvPairs != nil {
+		tech := t.resourceMgr.GetTechnology()
+		tpInstancesTech := make([]TechProfile, 0, len(kvPairs))
+		tpInstancesEpon := make([]EponProfile, 0, len(kvPairs))
+
+		for kvPath, kvPair := range kvPairs {
+			if value, err := kvstore.ToByte(kvPair.Value); err == nil {
+				if tech == xgspon || tech == gpon {
+					if err = json.Unmarshal(value, &tpTech); err != nil {
+						logger.Errorw(ctx, "error-unmarshal-kv-pair", log.Fields{"kvPath": kvPath, "value": value})
+						continue
+					} else {
+						tpInstancesTech = append(tpInstancesTech, tpTech)
+					}
+				} else if tech == epon {
+					if err = json.Unmarshal(value, &tpEpon); err != nil {
+						logger.Errorw(ctx, "error-unmarshal-kv-pair", log.Fields{"kvPath": kvPath, "value": value})
+						continue
+					} else {
+						tpInstancesEpon = append(tpInstancesEpon, tpEpon)
+					}
+				}
+			}
+		}
+
+		switch tech {
+		case xgspon, gpon:
+			return tpInstancesTech
+		case epon:
+			return tpInstancesEpon
+		default:
+			logger.Errorw(ctx, "unknown-technology", log.Fields{"tech": tech})
+			return nil
+		}
+	}
+	return nil
+}
diff --git a/vendor/github.com/opencord/voltha-lib-go/v4/pkg/techprofile/tech_profile_if.go b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/techprofile/tech_profile_if.go
new file mode 100644
index 0000000..0c5e273
--- /dev/null
+++ b/vendor/github.com/opencord/voltha-lib-go/v4/pkg/techprofile/tech_profile_if.go
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package techprofile
+
+import (
+	"context"
+
+	"github.com/opencord/voltha-lib-go/v4/pkg/db"
+	tp_pb "github.com/opencord/voltha-protos/v4/go/tech_profile"
+)
+
+type TechProfileIf interface {
+	SetKVClient(ctx context.Context) *db.Backend
+	GetTechProfileInstanceKVPath(ctx context.Context, techProfiletblID uint32, uniPortName string) string
+	GetTPInstanceFromKVStore(ctx context.Context, techProfiletblID uint32, path string) (interface{}, error)
+	CreateTechProfInstance(ctx context.Context, techProfiletblID uint32, uniPortName string, intfId uint32) (interface{}, error)
+	DeleteTechProfileInstance(ctx context.Context, techProfiletblID uint32, uniPortName string) error
+	GetprotoBufParamValue(ctx context.Context, paramType string, paramKey string) int32
+	GetUsScheduler(ctx context.Context, tpInstance *TechProfile) (*tp_pb.SchedulerConfig, error)
+	GetDsScheduler(ctx context.Context, tpInstance *TechProfile) (*tp_pb.SchedulerConfig, error)
+	GetTrafficScheduler(tpInstance *TechProfile, SchedCfg *tp_pb.SchedulerConfig,
+		ShapingCfg *tp_pb.TrafficShapingInfo) *tp_pb.TrafficScheduler
+	GetTrafficQueues(ctx context.Context, tp *TechProfile, Dir tp_pb.Direction) ([]*tp_pb.TrafficQueue, error)
+	GetMulticastTrafficQueues(ctx context.Context, tp *TechProfile) []*tp_pb.TrafficQueue
+	GetGemportIDForPbit(ctx context.Context, tp interface{}, Dir tp_pb.Direction, pbit uint32) uint32
+	FindAllTpInstances(ctx context.Context, techProfiletblID uint32, ponIntf uint32, onuID uint32) interface{}
+}
diff --git a/vendor/github.com/opencord/voltha-protos/v4/go/common/common.pb.go b/vendor/github.com/opencord/voltha-protos/v4/go/common/common.pb.go
new file mode 100644
index 0000000..c476a08
--- /dev/null
+++ b/vendor/github.com/opencord/voltha-protos/v4/go/common/common.pb.go
@@ -0,0 +1,647 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: voltha_protos/common.proto
+
+package common
+
+import (
+	fmt "fmt"
+	proto "github.com/golang/protobuf/proto"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type TestModeKeys int32
+
+const (
+	TestModeKeys_api_test TestModeKeys = 0
+)
+
+var TestModeKeys_name = map[int32]string{
+	0: "api_test",
+}
+
+var TestModeKeys_value = map[string]int32{
+	"api_test": 0,
+}
+
+func (x TestModeKeys) String() string {
+	return proto.EnumName(TestModeKeys_name, int32(x))
+}
+
+func (TestModeKeys) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_c2e3fd231961e826, []int{0}
+}
+
+// Administrative State
+type AdminState_Types int32
+
+const (
+	// The administrative state of the device is unknown
+	AdminState_UNKNOWN AdminState_Types = 0
+	// The device is pre-provisioned into Voltha, but not contacted by it
+	AdminState_PREPROVISIONED AdminState_Types = 1
+	// The device is enabled for activation and operation
+	AdminState_ENABLED AdminState_Types = 2
+	// The device is disabled and shall not perform its intended forwarding
+	// functions other than being available for re-activation.
+	AdminState_DISABLED AdminState_Types = 3
+	// The device is in the state of image download
+	AdminState_DOWNLOADING_IMAGE AdminState_Types = 4
+	// The device is marked to be deleted
+	AdminState_DELETED AdminState_Types = 5
+	// The device is marked to be in deleting state
+	AdminState_DELETING AdminState_Types = 6
+)
+
+var AdminState_Types_name = map[int32]string{
+	0: "UNKNOWN",
+	1: "PREPROVISIONED",
+	2: "ENABLED",
+	3: "DISABLED",
+	4: "DOWNLOADING_IMAGE",
+	5: "DELETED",
+	6: "DELETING",
+}
+
+var AdminState_Types_value = map[string]int32{
+	"UNKNOWN":           0,
+	"PREPROVISIONED":    1,
+	"ENABLED":           2,
+	"DISABLED":          3,
+	"DOWNLOADING_IMAGE": 4,
+	"DELETED":           5,
+	"DELETING":          6,
+}
+
+func (x AdminState_Types) String() string {
+	return proto.EnumName(AdminState_Types_name, int32(x))
+}
+
+func (AdminState_Types) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_c2e3fd231961e826, []int{2, 0}
+}
+
+// Operational Status
+type OperStatus_Types int32
+
+const (
+	// The status of the device is unknown at this point
+	OperStatus_UNKNOWN OperStatus_Types = 0
+	// The device has been discovered, but not yet activated
+	OperStatus_DISCOVERED OperStatus_Types = 1
+	// The device is being activated (booted, rebooted, upgraded, etc.)
+	OperStatus_ACTIVATING OperStatus_Types = 2
+	// Service impacting tests are being conducted
+	OperStatus_TESTING OperStatus_Types = 3
+	// The device is up and active
+	OperStatus_ACTIVE OperStatus_Types = 4
+	// The device has failed and cannot fulfill its intended role
+	OperStatus_FAILED OperStatus_Types = 5
+)
+
+var OperStatus_Types_name = map[int32]string{
+	0: "UNKNOWN",
+	1: "DISCOVERED",
+	2: "ACTIVATING",
+	3: "TESTING",
+	4: "ACTIVE",
+	5: "FAILED",
+}
+
+var OperStatus_Types_value = map[string]int32{
+	"UNKNOWN":    0,
+	"DISCOVERED": 1,
+	"ACTIVATING": 2,
+	"TESTING":    3,
+	"ACTIVE":     4,
+	"FAILED":     5,
+}
+
+func (x OperStatus_Types) String() string {
+	return proto.EnumName(OperStatus_Types_name, int32(x))
+}
+
+func (OperStatus_Types) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_c2e3fd231961e826, []int{3, 0}
+}
+
+// Connectivity Status
+type ConnectStatus_Types int32
+
+const (
+	// The device connectivity status is unknown
+	ConnectStatus_UNKNOWN ConnectStatus_Types = 0
+	// The device cannot be reached by Voltha
+	ConnectStatus_UNREACHABLE ConnectStatus_Types = 1
+	// There is live communication between device and Voltha
+	ConnectStatus_REACHABLE ConnectStatus_Types = 2
+)
+
+var ConnectStatus_Types_name = map[int32]string{
+	0: "UNKNOWN",
+	1: "UNREACHABLE",
+	2: "REACHABLE",
+}
+
+var ConnectStatus_Types_value = map[string]int32{
+	"UNKNOWN":     0,
+	"UNREACHABLE": 1,
+	"REACHABLE":   2,
+}
+
+func (x ConnectStatus_Types) String() string {
+	return proto.EnumName(ConnectStatus_Types_name, int32(x))
+}
+
+func (ConnectStatus_Types) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_c2e3fd231961e826, []int{4, 0}
+}
+
+type OperationResp_OperationReturnCode int32
+
+const (
+	OperationResp_OPERATION_SUCCESS     OperationResp_OperationReturnCode = 0
+	OperationResp_OPERATION_FAILURE     OperationResp_OperationReturnCode = 1
+	OperationResp_OPERATION_UNSUPPORTED OperationResp_OperationReturnCode = 2
+)
+
+var OperationResp_OperationReturnCode_name = map[int32]string{
+	0: "OPERATION_SUCCESS",
+	1: "OPERATION_FAILURE",
+	2: "OPERATION_UNSUPPORTED",
+}
+
+var OperationResp_OperationReturnCode_value = map[string]int32{
+	"OPERATION_SUCCESS":     0,
+	"OPERATION_FAILURE":     1,
+	"OPERATION_UNSUPPORTED": 2,
+}
+
+func (x OperationResp_OperationReturnCode) String() string {
+	return proto.EnumName(OperationResp_OperationReturnCode_name, int32(x))
+}
+
+func (OperationResp_OperationReturnCode) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_c2e3fd231961e826, []int{5, 0}
+}
+
+type ValueType_Type int32
+
+const (
+	ValueType_EMPTY    ValueType_Type = 0
+	ValueType_DISTANCE ValueType_Type = 1
+)
+
+var ValueType_Type_name = map[int32]string{
+	0: "EMPTY",
+	1: "DISTANCE",
+}
+
+var ValueType_Type_value = map[string]int32{
+	"EMPTY":    0,
+	"DISTANCE": 1,
+}
+
+func (x ValueType_Type) String() string {
+	return proto.EnumName(ValueType_Type_name, int32(x))
+}
+
+func (ValueType_Type) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_c2e3fd231961e826, []int{6, 0}
+}
+
+// Convey a resource identifier
+type ID struct {
+	Id                   string   `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ID) Reset()         { *m = ID{} }
+func (m *ID) String() string { return proto.CompactTextString(m) }
+func (*ID) ProtoMessage()    {}
+func (*ID) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c2e3fd231961e826, []int{0}
+}
+
+func (m *ID) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ID.Unmarshal(m, b)
+}
+func (m *ID) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ID.Marshal(b, m, deterministic)
+}
+func (m *ID) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ID.Merge(m, src)
+}
+func (m *ID) XXX_Size() int {
+	return xxx_messageInfo_ID.Size(m)
+}
+func (m *ID) XXX_DiscardUnknown() {
+	xxx_messageInfo_ID.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ID proto.InternalMessageInfo
+
+func (m *ID) GetId() string {
+	if m != nil {
+		return m.Id
+	}
+	return ""
+}
+
+// Represents a list of IDs
+type IDs struct {
+	Items                []*ID    `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *IDs) Reset()         { *m = IDs{} }
+func (m *IDs) String() string { return proto.CompactTextString(m) }
+func (*IDs) ProtoMessage()    {}
+func (*IDs) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c2e3fd231961e826, []int{1}
+}
+
+func (m *IDs) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_IDs.Unmarshal(m, b)
+}
+func (m *IDs) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_IDs.Marshal(b, m, deterministic)
+}
+func (m *IDs) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_IDs.Merge(m, src)
+}
+func (m *IDs) XXX_Size() int {
+	return xxx_messageInfo_IDs.Size(m)
+}
+func (m *IDs) XXX_DiscardUnknown() {
+	xxx_messageInfo_IDs.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_IDs proto.InternalMessageInfo
+
+func (m *IDs) GetItems() []*ID {
+	if m != nil {
+		return m.Items
+	}
+	return nil
+}
+
+type AdminState struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *AdminState) Reset()         { *m = AdminState{} }
+func (m *AdminState) String() string { return proto.CompactTextString(m) }
+func (*AdminState) ProtoMessage()    {}
+func (*AdminState) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c2e3fd231961e826, []int{2}
+}
+
+func (m *AdminState) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_AdminState.Unmarshal(m, b)
+}
+func (m *AdminState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_AdminState.Marshal(b, m, deterministic)
+}
+func (m *AdminState) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_AdminState.Merge(m, src)
+}
+func (m *AdminState) XXX_Size() int {
+	return xxx_messageInfo_AdminState.Size(m)
+}
+func (m *AdminState) XXX_DiscardUnknown() {
+	xxx_messageInfo_AdminState.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_AdminState proto.InternalMessageInfo
+
+type OperStatus struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *OperStatus) Reset()         { *m = OperStatus{} }
+func (m *OperStatus) String() string { return proto.CompactTextString(m) }
+func (*OperStatus) ProtoMessage()    {}
+func (*OperStatus) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c2e3fd231961e826, []int{3}
+}
+
+func (m *OperStatus) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_OperStatus.Unmarshal(m, b)
+}
+func (m *OperStatus) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_OperStatus.Marshal(b, m, deterministic)
+}
+func (m *OperStatus) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_OperStatus.Merge(m, src)
+}
+func (m *OperStatus) XXX_Size() int {
+	return xxx_messageInfo_OperStatus.Size(m)
+}
+func (m *OperStatus) XXX_DiscardUnknown() {
+	xxx_messageInfo_OperStatus.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OperStatus proto.InternalMessageInfo
+
+type ConnectStatus struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ConnectStatus) Reset()         { *m = ConnectStatus{} }
+func (m *ConnectStatus) String() string { return proto.CompactTextString(m) }
+func (*ConnectStatus) ProtoMessage()    {}
+func (*ConnectStatus) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c2e3fd231961e826, []int{4}
+}
+
+func (m *ConnectStatus) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ConnectStatus.Unmarshal(m, b)
+}
+func (m *ConnectStatus) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ConnectStatus.Marshal(b, m, deterministic)
+}
+func (m *ConnectStatus) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ConnectStatus.Merge(m, src)
+}
+func (m *ConnectStatus) XXX_Size() int {
+	return xxx_messageInfo_ConnectStatus.Size(m)
+}
+func (m *ConnectStatus) XXX_DiscardUnknown() {
+	xxx_messageInfo_ConnectStatus.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ConnectStatus proto.InternalMessageInfo
+
+type OperationResp struct {
+	// Return code
+	Code OperationResp_OperationReturnCode `protobuf:"varint,1,opt,name=code,proto3,enum=common.OperationResp_OperationReturnCode" json:"code,omitempty"`
+	// Additional Info
+	AdditionalInfo       string   `protobuf:"bytes,2,opt,name=additional_info,json=additionalInfo,proto3" json:"additional_info,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *OperationResp) Reset()         { *m = OperationResp{} }
+func (m *OperationResp) String() string { return proto.CompactTextString(m) }
+func (*OperationResp) ProtoMessage()    {}
+func (*OperationResp) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c2e3fd231961e826, []int{5}
+}
+
+func (m *OperationResp) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_OperationResp.Unmarshal(m, b)
+}
+func (m *OperationResp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_OperationResp.Marshal(b, m, deterministic)
+}
+func (m *OperationResp) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_OperationResp.Merge(m, src)
+}
+func (m *OperationResp) XXX_Size() int {
+	return xxx_messageInfo_OperationResp.Size(m)
+}
+func (m *OperationResp) XXX_DiscardUnknown() {
+	xxx_messageInfo_OperationResp.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OperationResp proto.InternalMessageInfo
+
+func (m *OperationResp) GetCode() OperationResp_OperationReturnCode {
+	if m != nil {
+		return m.Code
+	}
+	return OperationResp_OPERATION_SUCCESS
+}
+
+func (m *OperationResp) GetAdditionalInfo() string {
+	if m != nil {
+		return m.AdditionalInfo
+	}
+	return ""
+}
+
+type ValueType struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ValueType) Reset()         { *m = ValueType{} }
+func (m *ValueType) String() string { return proto.CompactTextString(m) }
+func (*ValueType) ProtoMessage()    {}
+func (*ValueType) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c2e3fd231961e826, []int{6}
+}
+
+func (m *ValueType) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ValueType.Unmarshal(m, b)
+}
+func (m *ValueType) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ValueType.Marshal(b, m, deterministic)
+}
+func (m *ValueType) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ValueType.Merge(m, src)
+}
+func (m *ValueType) XXX_Size() int {
+	return xxx_messageInfo_ValueType.Size(m)
+}
+func (m *ValueType) XXX_DiscardUnknown() {
+	xxx_messageInfo_ValueType.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ValueType proto.InternalMessageInfo
+
+type ValueSpecifier struct {
+	Id                   string         `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	Value                ValueType_Type `protobuf:"varint,2,opt,name=value,proto3,enum=common.ValueType_Type" json:"value,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}       `json:"-"`
+	XXX_unrecognized     []byte         `json:"-"`
+	XXX_sizecache        int32          `json:"-"`
+}
+
+func (m *ValueSpecifier) Reset()         { *m = ValueSpecifier{} }
+func (m *ValueSpecifier) String() string { return proto.CompactTextString(m) }
+func (*ValueSpecifier) ProtoMessage()    {}
+func (*ValueSpecifier) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c2e3fd231961e826, []int{7}
+}
+
+func (m *ValueSpecifier) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ValueSpecifier.Unmarshal(m, b)
+}
+func (m *ValueSpecifier) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ValueSpecifier.Marshal(b, m, deterministic)
+}
+func (m *ValueSpecifier) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ValueSpecifier.Merge(m, src)
+}
+func (m *ValueSpecifier) XXX_Size() int {
+	return xxx_messageInfo_ValueSpecifier.Size(m)
+}
+func (m *ValueSpecifier) XXX_DiscardUnknown() {
+	xxx_messageInfo_ValueSpecifier.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ValueSpecifier proto.InternalMessageInfo
+
+func (m *ValueSpecifier) GetId() string {
+	if m != nil {
+		return m.Id
+	}
+	return ""
+}
+
+func (m *ValueSpecifier) GetValue() ValueType_Type {
+	if m != nil {
+		return m.Value
+	}
+	return ValueType_EMPTY
+}
+
+type ReturnValues struct {
+	Set                  uint32   `protobuf:"varint,1,opt,name=Set,proto3" json:"Set,omitempty"`
+	Unsupported          uint32   `protobuf:"varint,2,opt,name=Unsupported,proto3" json:"Unsupported,omitempty"`
+	Error                uint32   `protobuf:"varint,3,opt,name=Error,proto3" json:"Error,omitempty"`
+	Distance             uint32   `protobuf:"varint,4,opt,name=Distance,proto3" json:"Distance,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ReturnValues) Reset()         { *m = ReturnValues{} }
+func (m *ReturnValues) String() string { return proto.CompactTextString(m) }
+func (*ReturnValues) ProtoMessage()    {}
+func (*ReturnValues) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c2e3fd231961e826, []int{8}
+}
+
+func (m *ReturnValues) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ReturnValues.Unmarshal(m, b)
+}
+func (m *ReturnValues) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ReturnValues.Marshal(b, m, deterministic)
+}
+func (m *ReturnValues) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ReturnValues.Merge(m, src)
+}
+func (m *ReturnValues) XXX_Size() int {
+	return xxx_messageInfo_ReturnValues.Size(m)
+}
+func (m *ReturnValues) XXX_DiscardUnknown() {
+	xxx_messageInfo_ReturnValues.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ReturnValues proto.InternalMessageInfo
+
+func (m *ReturnValues) GetSet() uint32 {
+	if m != nil {
+		return m.Set
+	}
+	return 0
+}
+
+func (m *ReturnValues) GetUnsupported() uint32 {
+	if m != nil {
+		return m.Unsupported
+	}
+	return 0
+}
+
+func (m *ReturnValues) GetError() uint32 {
+	if m != nil {
+		return m.Error
+	}
+	return 0
+}
+
+func (m *ReturnValues) GetDistance() uint32 {
+	if m != nil {
+		return m.Distance
+	}
+	return 0
+}
+
+func init() {
+	proto.RegisterEnum("common.TestModeKeys", TestModeKeys_name, TestModeKeys_value)
+	proto.RegisterEnum("common.AdminState_Types", AdminState_Types_name, AdminState_Types_value)
+	proto.RegisterEnum("common.OperStatus_Types", OperStatus_Types_name, OperStatus_Types_value)
+	proto.RegisterEnum("common.ConnectStatus_Types", ConnectStatus_Types_name, ConnectStatus_Types_value)
+	proto.RegisterEnum("common.OperationResp_OperationReturnCode", OperationResp_OperationReturnCode_name, OperationResp_OperationReturnCode_value)
+	proto.RegisterEnum("common.ValueType_Type", ValueType_Type_name, ValueType_Type_value)
+	proto.RegisterType((*ID)(nil), "common.ID")
+	proto.RegisterType((*IDs)(nil), "common.IDs")
+	proto.RegisterType((*AdminState)(nil), "common.AdminState")
+	proto.RegisterType((*OperStatus)(nil), "common.OperStatus")
+	proto.RegisterType((*ConnectStatus)(nil), "common.ConnectStatus")
+	proto.RegisterType((*OperationResp)(nil), "common.OperationResp")
+	proto.RegisterType((*ValueType)(nil), "common.ValueType")
+	proto.RegisterType((*ValueSpecifier)(nil), "common.ValueSpecifier")
+	proto.RegisterType((*ReturnValues)(nil), "common.ReturnValues")
+}
+
+func init() { proto.RegisterFile("voltha_protos/common.proto", fileDescriptor_c2e3fd231961e826) }
+
+var fileDescriptor_c2e3fd231961e826 = []byte{
+	// 614 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x53, 0x4f, 0x4f, 0xdb, 0x4e,
+	0x10, 0x8d, 0x9d, 0x3f, 0x3f, 0x32, 0x21, 0xc6, 0xbf, 0x05, 0xaa, 0x14, 0x55, 0x6a, 0xe4, 0x0b,
+	0xb4, 0xa2, 0x89, 0x44, 0xb9, 0xf6, 0x60, 0xec, 0x2d, 0x5d, 0x01, 0xeb, 0x68, 0x6d, 0x07, 0xd1,
+	0x43, 0x23, 0x13, 0x2f, 0xc1, 0x12, 0xf1, 0x5a, 0xf6, 0x06, 0x89, 0x73, 0x3f, 0x64, 0xbf, 0x4e,
+	0xb5, 0xeb, 0xf0, 0xaf, 0xe2, 0x62, 0xfb, 0xcd, 0x7b, 0x3b, 0x33, 0x6f, 0xc6, 0x0b, 0x7b, 0xf7,
+	0xe2, 0x4e, 0xde, 0x26, 0xb3, 0xa2, 0x14, 0x52, 0x54, 0xe3, 0xb9, 0x58, 0x2e, 0x45, 0x3e, 0xd2,
+	0x08, 0x75, 0x6a, 0xe4, 0xec, 0x80, 0x49, 0x7c, 0x64, 0x81, 0x99, 0xa5, 0x03, 0x63, 0x68, 0x1c,
+	0x74, 0x99, 0x99, 0xa5, 0xce, 0x3e, 0x34, 0x89, 0x5f, 0xa1, 0x21, 0xb4, 0x33, 0xc9, 0x97, 0xd5,
+	0xc0, 0x18, 0x36, 0x0f, 0x7a, 0x47, 0x30, 0x5a, 0xa7, 0x20, 0x3e, 0xab, 0x09, 0xe7, 0xb7, 0x01,
+	0xe0, 0xa6, 0xcb, 0x2c, 0x0f, 0x65, 0x22, 0xb9, 0xb3, 0x82, 0x76, 0xf4, 0x50, 0xf0, 0x0a, 0xf5,
+	0xe0, 0xbf, 0x98, 0x9e, 0xd1, 0xe0, 0x92, 0xda, 0x0d, 0x84, 0xc0, 0x9a, 0x30, 0x3c, 0x61, 0xc1,
+	0x94, 0x84, 0x24, 0xa0, 0xd8, 0xb7, 0x0d, 0x25, 0xc0, 0xd4, 0x3d, 0x39, 0xc7, 0xbe, 0x6d, 0xa2,
+	0x4d, 0xd8, 0xf0, 0x49, 0x58, 0xa3, 0x26, 0xda, 0x85, 0xff, 0xfd, 0xe0, 0x92, 0x9e, 0x07, 0xae,
+	0x4f, 0xe8, 0xe9, 0x8c, 0x5c, 0xb8, 0xa7, 0xd8, 0x6e, 0xa9, 0x13, 0x3e, 0x3e, 0xc7, 0x11, 0xf6,
+	0xed, 0xb6, 0x3e, 0xa1, 0x00, 0xa1, 0xa7, 0x76, 0xc7, 0x59, 0x00, 0x04, 0x05, 0x2f, 0x55, 0x0f,
+	0xab, 0xca, 0xb9, 0x7a, 0xb3, 0x09, 0x0b, 0xc0, 0x27, 0xa1, 0x17, 0x4c, 0x31, 0xd3, 0x0d, 0x58,
+	0x00, 0xae, 0x17, 0x91, 0xa9, 0xab, 0x73, 0x98, 0x4a, 0x1c, 0xe1, 0x50, 0x83, 0x26, 0x02, 0xe8,
+	0x68, 0x52, 0xd5, 0x05, 0xe8, 0x7c, 0x77, 0x89, 0x6a, 0xad, 0xed, 0x60, 0xe8, 0x7b, 0x22, 0xcf,
+	0xf9, 0x5c, 0xae, 0x6b, 0x1d, 0xbf, 0x59, 0x6b, 0x0b, 0x7a, 0x31, 0x65, 0xd8, 0xf5, 0x7e, 0x28,
+	0x4f, 0xb6, 0x81, 0xfa, 0xd0, 0x7d, 0x86, 0xa6, 0xf3, 0xc7, 0x80, 0xbe, 0x6a, 0x38, 0x91, 0x99,
+	0xc8, 0x19, 0xaf, 0x0a, 0xf4, 0x0d, 0x5a, 0x73, 0x91, 0x72, 0xbd, 0x02, 0xeb, 0xe8, 0xd3, 0xe3,
+	0xa0, 0x5f, 0x89, 0x5e, 0x22, 0xb9, 0x2a, 0x73, 0x4f, 0xa4, 0x9c, 0xe9, 0x63, 0x68, 0x1f, 0xb6,
+	0x92, 0x34, 0xcd, 0x14, 0x97, 0xdc, 0xcd, 0xb2, 0xfc, 0x46, 0x0c, 0x4c, 0xbd, 0x4c, 0xeb, 0x39,
+	0x4c, 0xf2, 0x1b, 0xe1, 0xfc, 0x82, 0xed, 0x37, 0xb2, 0xa8, 0x91, 0x07, 0x13, 0xcc, 0xdc, 0x88,
+	0x04, 0x74, 0x16, 0xc6, 0x9e, 0x87, 0xc3, 0xd0, 0x6e, 0xbc, 0x0e, 0xab, 0x21, 0xc4, 0x4c, 0xb9,
+	0x79, 0x0f, 0xbb, 0xcf, 0xe1, 0x98, 0x86, 0xf1, 0x64, 0x12, 0x30, 0xb5, 0x17, 0xd3, 0x39, 0x84,
+	0xee, 0x34, 0xb9, 0x5b, 0x71, 0x35, 0x14, 0xe7, 0x23, 0xb4, 0xd4, 0x1b, 0x75, 0xa1, 0x8d, 0x2f,
+	0x26, 0xd1, 0x95, 0xdd, 0x58, 0x6f, 0x3a, 0x72, 0xa9, 0x87, 0x6d, 0xc3, 0xa1, 0x60, 0x69, 0x75,
+	0x58, 0xf0, 0x79, 0x76, 0x93, 0xf1, 0xf2, 0xdf, 0x1f, 0x11, 0x1d, 0x42, 0xfb, 0x5e, 0x29, 0xb4,
+	0x1d, 0xeb, 0xe8, 0xdd, 0xe3, 0x60, 0x9e, 0x8a, 0x8c, 0xd4, 0x83, 0xd5, 0x22, 0x47, 0xc2, 0x66,
+	0x6d, 0x4a, 0xd3, 0x15, 0xb2, 0xa1, 0x19, 0x72, 0xa9, 0xd3, 0xf5, 0x99, 0xfa, 0x44, 0x43, 0xe8,
+	0xc5, 0x79, 0xb5, 0x2a, 0x0a, 0x51, 0x4a, 0x9e, 0xea, 0xac, 0x7d, 0xf6, 0x32, 0x84, 0x76, 0xa0,
+	0x8d, 0xcb, 0x52, 0x94, 0x83, 0xa6, 0xe6, 0x6a, 0x80, 0xf6, 0x60, 0xc3, 0xcf, 0x2a, 0x99, 0xe4,
+	0x73, 0x3e, 0x68, 0x69, 0xe2, 0x09, 0x7f, 0xfe, 0x00, 0x9b, 0x11, 0xaf, 0xe4, 0x85, 0x48, 0xf9,
+	0x19, 0x7f, 0xa8, 0x94, 0xc7, 0xa4, 0xc8, 0x66, 0x92, 0x57, 0xd2, 0x6e, 0x9c, 0x60, 0xd8, 0x16,
+	0xe5, 0x62, 0x24, 0x0a, 0x9e, 0xcf, 0x45, 0x99, 0x8e, 0xea, 0x3b, 0xf9, 0x73, 0xb4, 0xc8, 0xe4,
+	0xed, 0xea, 0x5a, 0xf9, 0x19, 0x3f, 0x72, 0xe3, 0x9a, 0xfb, 0xb2, 0xbe, 0xaf, 0xf7, 0xc7, 0xe3,
+	0x85, 0x58, 0xdf, 0xda, 0xeb, 0x8e, 0x0e, 0x7e, 0xfd, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x36, 0xc3,
+	0x8c, 0xb0, 0xd4, 0x03, 0x00, 0x00,
+}
diff --git a/vendor/github.com/opencord/voltha-protos/v4/go/common/meta.pb.go b/vendor/github.com/opencord/voltha-protos/v4/go/common/meta.pb.go
new file mode 100644
index 0000000..0af225d
--- /dev/null
+++ b/vendor/github.com/opencord/voltha-protos/v4/go/common/meta.pb.go
@@ -0,0 +1,142 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: voltha_protos/meta.proto
+
+package common
+
+import (
+	fmt "fmt"
+	proto "github.com/golang/protobuf/proto"
+	descriptor "github.com/golang/protobuf/protoc-gen-go/descriptor"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type Access int32
+
+const (
+	// read-write, stored attribute
+	Access_CONFIG Access = 0
+	// read-only field, stored with the model, covered by its hash
+	Access_READ_ONLY Access = 1
+	// A read-only attribute that is not stored in the model, not covered
+	// by its hash, its value is filled real-time upon each request.
+	Access_REAL_TIME Access = 2
+)
+
+var Access_name = map[int32]string{
+	0: "CONFIG",
+	1: "READ_ONLY",
+	2: "REAL_TIME",
+}
+
+var Access_value = map[string]int32{
+	"CONFIG":    0,
+	"READ_ONLY": 1,
+	"REAL_TIME": 2,
+}
+
+func (x Access) String() string {
+	return proto.EnumName(Access_name, int32(x))
+}
+
+func (Access) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_96b320e8a67781f3, []int{0}
+}
+
+type ChildNode struct {
+	Key                  string   `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ChildNode) Reset()         { *m = ChildNode{} }
+func (m *ChildNode) String() string { return proto.CompactTextString(m) }
+func (*ChildNode) ProtoMessage()    {}
+func (*ChildNode) Descriptor() ([]byte, []int) {
+	return fileDescriptor_96b320e8a67781f3, []int{0}
+}
+
+func (m *ChildNode) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ChildNode.Unmarshal(m, b)
+}
+func (m *ChildNode) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ChildNode.Marshal(b, m, deterministic)
+}
+func (m *ChildNode) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ChildNode.Merge(m, src)
+}
+func (m *ChildNode) XXX_Size() int {
+	return xxx_messageInfo_ChildNode.Size(m)
+}
+func (m *ChildNode) XXX_DiscardUnknown() {
+	xxx_messageInfo_ChildNode.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ChildNode proto.InternalMessageInfo
+
+func (m *ChildNode) GetKey() string {
+	if m != nil {
+		return m.Key
+	}
+	return ""
+}
+
+var E_ChildNode = &proto.ExtensionDesc{
+	ExtendedType:  (*descriptor.FieldOptions)(nil),
+	ExtensionType: (*ChildNode)(nil),
+	Field:         7761772,
+	Name:          "voltha.child_node",
+	Tag:           "bytes,7761772,opt,name=child_node",
+	Filename:      "voltha_protos/meta.proto",
+}
+
+var E_Access = &proto.ExtensionDesc{
+	ExtendedType:  (*descriptor.FieldOptions)(nil),
+	ExtensionType: (*Access)(nil),
+	Field:         7761773,
+	Name:          "voltha.access",
+	Tag:           "varint,7761773,opt,name=access,enum=voltha.Access",
+	Filename:      "voltha_protos/meta.proto",
+}
+
+func init() {
+	proto.RegisterEnum("voltha.Access", Access_name, Access_value)
+	proto.RegisterType((*ChildNode)(nil), "voltha.ChildNode")
+	proto.RegisterExtension(E_ChildNode)
+	proto.RegisterExtension(E_Access)
+}
+
+func init() { proto.RegisterFile("voltha_protos/meta.proto", fileDescriptor_96b320e8a67781f3) }
+
+var fileDescriptor_96b320e8a67781f3 = []byte{
+	// 281 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x90, 0x41, 0x4b, 0x84, 0x40,
+	0x14, 0xc7, 0xb3, 0x05, 0xc1, 0x17, 0x2d, 0xe6, 0x69, 0x59, 0x58, 0x90, 0x4e, 0x4b, 0xd0, 0x0c,
+	0x58, 0xa7, 0xbd, 0x6d, 0xdb, 0x6e, 0x2d, 0x98, 0x82, 0x74, 0xa9, 0x8b, 0xe8, 0x38, 0xa9, 0xa4,
+	0x3e, 0x71, 0x66, 0x17, 0xfa, 0xa8, 0x5d, 0xfa, 0x04, 0xf5, 0x1d, 0x42, 0xc7, 0xe9, 0xda, 0xed,
+	0xff, 0xde, 0xfc, 0xe7, 0xc7, 0x8f, 0x07, 0xb3, 0x23, 0x56, 0xb2, 0x48, 0xe2, 0xb6, 0x43, 0x89,
+	0x82, 0xd6, 0x5c, 0x26, 0x64, 0xc8, 0x8e, 0xa9, 0x5e, 0xe6, 0x6e, 0x8e, 0x98, 0x57, 0x9c, 0x0e,
+	0xdb, 0xf4, 0xf0, 0x46, 0x33, 0x2e, 0x58, 0x57, 0xb6, 0x12, 0x3b, 0xd5, 0xbc, 0x5c, 0x80, 0xb5,
+	0x29, 0xca, 0x2a, 0x0b, 0x30, 0xe3, 0x8e, 0x0d, 0x93, 0x77, 0xfe, 0x31, 0x33, 0x5c, 0x63, 0x69,
+	0x45, 0x7d, 0xbc, 0xf2, 0xc0, 0x5c, 0x33, 0xc6, 0x85, 0x70, 0x00, 0xcc, 0x4d, 0x18, 0xec, 0xf6,
+	0x0f, 0xf6, 0x89, 0x73, 0x0e, 0x56, 0xb4, 0x5d, 0xdf, 0xc7, 0x61, 0xe0, 0xbf, 0xd8, 0xc6, 0x38,
+	0xfa, 0xf1, 0xf3, 0xfe, 0x69, 0x6b, 0x9f, 0xae, 0x22, 0x00, 0xd6, 0x23, 0xe3, 0xa6, 0x67, 0x2e,
+	0x88, 0x72, 0x20, 0xda, 0x81, 0xec, 0x4a, 0x5e, 0x65, 0x61, 0x2b, 0x4b, 0x6c, 0xc4, 0xec, 0xfb,
+	0xeb, 0x73, 0xe2, 0x1a, 0xcb, 0x33, 0xef, 0x82, 0x28, 0x67, 0xf2, 0xa7, 0x13, 0x59, 0x4c, 0xc7,
+	0xd5, 0x23, 0x98, 0x89, 0xf2, 0xf8, 0x87, 0xf7, 0xa3, 0x78, 0x53, 0x6f, 0xaa, 0x79, 0xca, 0x3f,
+	0x1a, 0xff, 0xdf, 0xf9, 0x30, 0xc7, 0x2e, 0x27, 0xd8, 0xf2, 0x86, 0x61, 0x97, 0xe9, 0x16, 0xc3,
+	0xba, 0xc6, 0xe6, 0x95, 0xe4, 0xa5, 0x2c, 0x0e, 0x69, 0x3f, 0x52, 0x5d, 0xa1, 0xaa, 0x72, 0x3d,
+	0x9e, 0xf9, 0x78, 0x4b, 0x73, 0xa4, 0xaa, 0x9f, 0x9a, 0xc3, 0xf2, 0xe6, 0x37, 0x00, 0x00, 0xff,
+	0xff, 0x0e, 0xea, 0x69, 0xf5, 0x8b, 0x01, 0x00, 0x00,
+}
diff --git a/vendor/github.com/opencord/voltha-protos/v4/go/ext/config/ext_config.pb.go b/vendor/github.com/opencord/voltha-protos/v4/go/ext/config/ext_config.pb.go
new file mode 100644
index 0000000..b68a7e4
--- /dev/null
+++ b/vendor/github.com/opencord/voltha-protos/v4/go/ext/config/ext_config.pb.go
@@ -0,0 +1,523 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: voltha_protos/ext_config.proto
+
+package config
+
+import (
+	fmt "fmt"
+	proto "github.com/golang/protobuf/proto"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type OnuItuPonAlarm_AlarmID int32
+
+const (
+	OnuItuPonAlarm_RDI_ERRORS OnuItuPonAlarm_AlarmID = 0
+)
+
+var OnuItuPonAlarm_AlarmID_name = map[int32]string{
+	0: "RDI_ERRORS",
+}
+
+var OnuItuPonAlarm_AlarmID_value = map[string]int32{
+	"RDI_ERRORS": 0,
+}
+
+func (x OnuItuPonAlarm_AlarmID) String() string {
+	return proto.EnumName(OnuItuPonAlarm_AlarmID_name, int32(x))
+}
+
+func (OnuItuPonAlarm_AlarmID) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_fb43b44b7fa3aba9, []int{1, 0}
+}
+
+type OnuItuPonAlarm_AlarmReportingCondition int32
+
+const (
+	OnuItuPonAlarm_RATE_THRESHOLD  OnuItuPonAlarm_AlarmReportingCondition = 0
+	OnuItuPonAlarm_RATE_RANGE      OnuItuPonAlarm_AlarmReportingCondition = 1
+	OnuItuPonAlarm_VALUE_THRESHOLD OnuItuPonAlarm_AlarmReportingCondition = 2
+)
+
+var OnuItuPonAlarm_AlarmReportingCondition_name = map[int32]string{
+	0: "RATE_THRESHOLD",
+	1: "RATE_RANGE",
+	2: "VALUE_THRESHOLD",
+}
+
+var OnuItuPonAlarm_AlarmReportingCondition_value = map[string]int32{
+	"RATE_THRESHOLD":  0,
+	"RATE_RANGE":      1,
+	"VALUE_THRESHOLD": 2,
+}
+
+func (x OnuItuPonAlarm_AlarmReportingCondition) String() string {
+	return proto.EnumName(OnuItuPonAlarm_AlarmReportingCondition_name, int32(x))
+}
+
+func (OnuItuPonAlarm_AlarmReportingCondition) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_fb43b44b7fa3aba9, []int{1, 1}
+}
+
+type AlarmConfig struct {
+	// Types that are valid to be assigned to Config:
+	//	*AlarmConfig_OnuItuPonAlarmConfig
+	Config               isAlarmConfig_Config `protobuf_oneof:"config"`
+	XXX_NoUnkeyedLiteral struct{}             `json:"-"`
+	XXX_unrecognized     []byte               `json:"-"`
+	XXX_sizecache        int32                `json:"-"`
+}
+
+func (m *AlarmConfig) Reset()         { *m = AlarmConfig{} }
+func (m *AlarmConfig) String() string { return proto.CompactTextString(m) }
+func (*AlarmConfig) ProtoMessage()    {}
+func (*AlarmConfig) Descriptor() ([]byte, []int) {
+	return fileDescriptor_fb43b44b7fa3aba9, []int{0}
+}
+
+func (m *AlarmConfig) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_AlarmConfig.Unmarshal(m, b)
+}
+func (m *AlarmConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_AlarmConfig.Marshal(b, m, deterministic)
+}
+func (m *AlarmConfig) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_AlarmConfig.Merge(m, src)
+}
+func (m *AlarmConfig) XXX_Size() int {
+	return xxx_messageInfo_AlarmConfig.Size(m)
+}
+func (m *AlarmConfig) XXX_DiscardUnknown() {
+	xxx_messageInfo_AlarmConfig.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_AlarmConfig proto.InternalMessageInfo
+
+type isAlarmConfig_Config interface {
+	isAlarmConfig_Config()
+}
+
+type AlarmConfig_OnuItuPonAlarmConfig struct {
+	OnuItuPonAlarmConfig *OnuItuPonAlarm `protobuf:"bytes,1,opt,name=onu_itu_pon_alarm_config,json=onuItuPonAlarmConfig,proto3,oneof"`
+}
+
+func (*AlarmConfig_OnuItuPonAlarmConfig) isAlarmConfig_Config() {}
+
+func (m *AlarmConfig) GetConfig() isAlarmConfig_Config {
+	if m != nil {
+		return m.Config
+	}
+	return nil
+}
+
+func (m *AlarmConfig) GetOnuItuPonAlarmConfig() *OnuItuPonAlarm {
+	if x, ok := m.GetConfig().(*AlarmConfig_OnuItuPonAlarmConfig); ok {
+		return x.OnuItuPonAlarmConfig
+	}
+	return nil
+}
+
+// XXX_OneofWrappers is for the internal use of the proto package.
+func (*AlarmConfig) XXX_OneofWrappers() []interface{} {
+	return []interface{}{
+		(*AlarmConfig_OnuItuPonAlarmConfig)(nil),
+	}
+}
+
+type OnuItuPonAlarm struct {
+	PonNi                   uint32                                 `protobuf:"fixed32,1,opt,name=pon_ni,json=ponNi,proto3" json:"pon_ni,omitempty"`
+	OnuId                   uint32                                 `protobuf:"fixed32,2,opt,name=onu_id,json=onuId,proto3" json:"onu_id,omitempty"`
+	AlarmId                 OnuItuPonAlarm_AlarmID                 `protobuf:"varint,3,opt,name=alarm_id,json=alarmId,proto3,enum=config.OnuItuPonAlarm_AlarmID" json:"alarm_id,omitempty"`
+	AlarmReportingCondition OnuItuPonAlarm_AlarmReportingCondition `protobuf:"varint,4,opt,name=alarm_reporting_condition,json=alarmReportingCondition,proto3,enum=config.OnuItuPonAlarm_AlarmReportingCondition" json:"alarm_reporting_condition,omitempty"`
+	// Types that are valid to be assigned to Config:
+	//	*OnuItuPonAlarm_RateThresholdConfig_
+	//	*OnuItuPonAlarm_RateRangeConfig_
+	//	*OnuItuPonAlarm_ValueThresholdConfig_
+	Config               isOnuItuPonAlarm_Config `protobuf_oneof:"config"`
+	XXX_NoUnkeyedLiteral struct{}                `json:"-"`
+	XXX_unrecognized     []byte                  `json:"-"`
+	XXX_sizecache        int32                   `json:"-"`
+}
+
+func (m *OnuItuPonAlarm) Reset()         { *m = OnuItuPonAlarm{} }
+func (m *OnuItuPonAlarm) String() string { return proto.CompactTextString(m) }
+func (*OnuItuPonAlarm) ProtoMessage()    {}
+func (*OnuItuPonAlarm) Descriptor() ([]byte, []int) {
+	return fileDescriptor_fb43b44b7fa3aba9, []int{1}
+}
+
+func (m *OnuItuPonAlarm) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_OnuItuPonAlarm.Unmarshal(m, b)
+}
+func (m *OnuItuPonAlarm) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_OnuItuPonAlarm.Marshal(b, m, deterministic)
+}
+func (m *OnuItuPonAlarm) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_OnuItuPonAlarm.Merge(m, src)
+}
+func (m *OnuItuPonAlarm) XXX_Size() int {
+	return xxx_messageInfo_OnuItuPonAlarm.Size(m)
+}
+func (m *OnuItuPonAlarm) XXX_DiscardUnknown() {
+	xxx_messageInfo_OnuItuPonAlarm.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OnuItuPonAlarm proto.InternalMessageInfo
+
+func (m *OnuItuPonAlarm) GetPonNi() uint32 {
+	if m != nil {
+		return m.PonNi
+	}
+	return 0
+}
+
+func (m *OnuItuPonAlarm) GetOnuId() uint32 {
+	if m != nil {
+		return m.OnuId
+	}
+	return 0
+}
+
+func (m *OnuItuPonAlarm) GetAlarmId() OnuItuPonAlarm_AlarmID {
+	if m != nil {
+		return m.AlarmId
+	}
+	return OnuItuPonAlarm_RDI_ERRORS
+}
+
+func (m *OnuItuPonAlarm) GetAlarmReportingCondition() OnuItuPonAlarm_AlarmReportingCondition {
+	if m != nil {
+		return m.AlarmReportingCondition
+	}
+	return OnuItuPonAlarm_RATE_THRESHOLD
+}
+
+type isOnuItuPonAlarm_Config interface {
+	isOnuItuPonAlarm_Config()
+}
+
+type OnuItuPonAlarm_RateThresholdConfig_ struct {
+	RateThresholdConfig *OnuItuPonAlarm_RateThresholdConfig `protobuf:"bytes,5,opt,name=rate_threshold_config,json=rateThresholdConfig,proto3,oneof"`
+}
+
+type OnuItuPonAlarm_RateRangeConfig_ struct {
+	RateRangeConfig *OnuItuPonAlarm_RateRangeConfig `protobuf:"bytes,6,opt,name=rate_range_config,json=rateRangeConfig,proto3,oneof"`
+}
+
+type OnuItuPonAlarm_ValueThresholdConfig_ struct {
+	ValueThresholdConfig *OnuItuPonAlarm_ValueThresholdConfig `protobuf:"bytes,7,opt,name=value_threshold_config,json=valueThresholdConfig,proto3,oneof"`
+}
+
+func (*OnuItuPonAlarm_RateThresholdConfig_) isOnuItuPonAlarm_Config() {}
+
+func (*OnuItuPonAlarm_RateRangeConfig_) isOnuItuPonAlarm_Config() {}
+
+func (*OnuItuPonAlarm_ValueThresholdConfig_) isOnuItuPonAlarm_Config() {}
+
+func (m *OnuItuPonAlarm) GetConfig() isOnuItuPonAlarm_Config {
+	if m != nil {
+		return m.Config
+	}
+	return nil
+}
+
+func (m *OnuItuPonAlarm) GetRateThresholdConfig() *OnuItuPonAlarm_RateThresholdConfig {
+	if x, ok := m.GetConfig().(*OnuItuPonAlarm_RateThresholdConfig_); ok {
+		return x.RateThresholdConfig
+	}
+	return nil
+}
+
+func (m *OnuItuPonAlarm) GetRateRangeConfig() *OnuItuPonAlarm_RateRangeConfig {
+	if x, ok := m.GetConfig().(*OnuItuPonAlarm_RateRangeConfig_); ok {
+		return x.RateRangeConfig
+	}
+	return nil
+}
+
+func (m *OnuItuPonAlarm) GetValueThresholdConfig() *OnuItuPonAlarm_ValueThresholdConfig {
+	if x, ok := m.GetConfig().(*OnuItuPonAlarm_ValueThresholdConfig_); ok {
+		return x.ValueThresholdConfig
+	}
+	return nil
+}
+
+// XXX_OneofWrappers is for the internal use of the proto package.
+func (*OnuItuPonAlarm) XXX_OneofWrappers() []interface{} {
+	return []interface{}{
+		(*OnuItuPonAlarm_RateThresholdConfig_)(nil),
+		(*OnuItuPonAlarm_RateRangeConfig_)(nil),
+		(*OnuItuPonAlarm_ValueThresholdConfig_)(nil),
+	}
+}
+
+type OnuItuPonAlarm_SoakTime struct {
+	ActiveSoakTime       uint32   `protobuf:"fixed32,1,opt,name=active_soak_time,json=activeSoakTime,proto3" json:"active_soak_time,omitempty"`
+	ClearSoakTime        uint32   `protobuf:"fixed32,2,opt,name=clear_soak_time,json=clearSoakTime,proto3" json:"clear_soak_time,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *OnuItuPonAlarm_SoakTime) Reset()         { *m = OnuItuPonAlarm_SoakTime{} }
+func (m *OnuItuPonAlarm_SoakTime) String() string { return proto.CompactTextString(m) }
+func (*OnuItuPonAlarm_SoakTime) ProtoMessage()    {}
+func (*OnuItuPonAlarm_SoakTime) Descriptor() ([]byte, []int) {
+	return fileDescriptor_fb43b44b7fa3aba9, []int{1, 0}
+}
+
+func (m *OnuItuPonAlarm_SoakTime) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_OnuItuPonAlarm_SoakTime.Unmarshal(m, b)
+}
+func (m *OnuItuPonAlarm_SoakTime) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_OnuItuPonAlarm_SoakTime.Marshal(b, m, deterministic)
+}
+func (m *OnuItuPonAlarm_SoakTime) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_OnuItuPonAlarm_SoakTime.Merge(m, src)
+}
+func (m *OnuItuPonAlarm_SoakTime) XXX_Size() int {
+	return xxx_messageInfo_OnuItuPonAlarm_SoakTime.Size(m)
+}
+func (m *OnuItuPonAlarm_SoakTime) XXX_DiscardUnknown() {
+	xxx_messageInfo_OnuItuPonAlarm_SoakTime.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OnuItuPonAlarm_SoakTime proto.InternalMessageInfo
+
+func (m *OnuItuPonAlarm_SoakTime) GetActiveSoakTime() uint32 {
+	if m != nil {
+		return m.ActiveSoakTime
+	}
+	return 0
+}
+
+func (m *OnuItuPonAlarm_SoakTime) GetClearSoakTime() uint32 {
+	if m != nil {
+		return m.ClearSoakTime
+	}
+	return 0
+}
+
+type OnuItuPonAlarm_RateThresholdConfig struct {
+	RateThresholdRising  uint64                   `protobuf:"fixed64,1,opt,name=rate_threshold_rising,json=rateThresholdRising,proto3" json:"rate_threshold_rising,omitempty"`
+	RateThresholdFalling uint64                   `protobuf:"fixed64,2,opt,name=rate_threshold_falling,json=rateThresholdFalling,proto3" json:"rate_threshold_falling,omitempty"`
+	SoakTime             *OnuItuPonAlarm_SoakTime `protobuf:"bytes,3,opt,name=soak_time,json=soakTime,proto3" json:"soak_time,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}                 `json:"-"`
+	XXX_unrecognized     []byte                   `json:"-"`
+	XXX_sizecache        int32                    `json:"-"`
+}
+
+func (m *OnuItuPonAlarm_RateThresholdConfig) Reset()         { *m = OnuItuPonAlarm_RateThresholdConfig{} }
+func (m *OnuItuPonAlarm_RateThresholdConfig) String() string { return proto.CompactTextString(m) }
+func (*OnuItuPonAlarm_RateThresholdConfig) ProtoMessage()    {}
+func (*OnuItuPonAlarm_RateThresholdConfig) Descriptor() ([]byte, []int) {
+	return fileDescriptor_fb43b44b7fa3aba9, []int{1, 1}
+}
+
+func (m *OnuItuPonAlarm_RateThresholdConfig) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_OnuItuPonAlarm_RateThresholdConfig.Unmarshal(m, b)
+}
+func (m *OnuItuPonAlarm_RateThresholdConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_OnuItuPonAlarm_RateThresholdConfig.Marshal(b, m, deterministic)
+}
+func (m *OnuItuPonAlarm_RateThresholdConfig) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_OnuItuPonAlarm_RateThresholdConfig.Merge(m, src)
+}
+func (m *OnuItuPonAlarm_RateThresholdConfig) XXX_Size() int {
+	return xxx_messageInfo_OnuItuPonAlarm_RateThresholdConfig.Size(m)
+}
+func (m *OnuItuPonAlarm_RateThresholdConfig) XXX_DiscardUnknown() {
+	xxx_messageInfo_OnuItuPonAlarm_RateThresholdConfig.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OnuItuPonAlarm_RateThresholdConfig proto.InternalMessageInfo
+
+func (m *OnuItuPonAlarm_RateThresholdConfig) GetRateThresholdRising() uint64 {
+	if m != nil {
+		return m.RateThresholdRising
+	}
+	return 0
+}
+
+func (m *OnuItuPonAlarm_RateThresholdConfig) GetRateThresholdFalling() uint64 {
+	if m != nil {
+		return m.RateThresholdFalling
+	}
+	return 0
+}
+
+func (m *OnuItuPonAlarm_RateThresholdConfig) GetSoakTime() *OnuItuPonAlarm_SoakTime {
+	if m != nil {
+		return m.SoakTime
+	}
+	return nil
+}
+
+type OnuItuPonAlarm_RateRangeConfig struct {
+	RateRangeLower       uint64                   `protobuf:"fixed64,1,opt,name=rate_range_lower,json=rateRangeLower,proto3" json:"rate_range_lower,omitempty"`
+	RateRangeUpper       uint64                   `protobuf:"fixed64,2,opt,name=rate_range_upper,json=rateRangeUpper,proto3" json:"rate_range_upper,omitempty"`
+	SoakTime             *OnuItuPonAlarm_SoakTime `protobuf:"bytes,3,opt,name=soak_time,json=soakTime,proto3" json:"soak_time,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}                 `json:"-"`
+	XXX_unrecognized     []byte                   `json:"-"`
+	XXX_sizecache        int32                    `json:"-"`
+}
+
+func (m *OnuItuPonAlarm_RateRangeConfig) Reset()         { *m = OnuItuPonAlarm_RateRangeConfig{} }
+func (m *OnuItuPonAlarm_RateRangeConfig) String() string { return proto.CompactTextString(m) }
+func (*OnuItuPonAlarm_RateRangeConfig) ProtoMessage()    {}
+func (*OnuItuPonAlarm_RateRangeConfig) Descriptor() ([]byte, []int) {
+	return fileDescriptor_fb43b44b7fa3aba9, []int{1, 2}
+}
+
+func (m *OnuItuPonAlarm_RateRangeConfig) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_OnuItuPonAlarm_RateRangeConfig.Unmarshal(m, b)
+}
+func (m *OnuItuPonAlarm_RateRangeConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_OnuItuPonAlarm_RateRangeConfig.Marshal(b, m, deterministic)
+}
+func (m *OnuItuPonAlarm_RateRangeConfig) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_OnuItuPonAlarm_RateRangeConfig.Merge(m, src)
+}
+func (m *OnuItuPonAlarm_RateRangeConfig) XXX_Size() int {
+	return xxx_messageInfo_OnuItuPonAlarm_RateRangeConfig.Size(m)
+}
+func (m *OnuItuPonAlarm_RateRangeConfig) XXX_DiscardUnknown() {
+	xxx_messageInfo_OnuItuPonAlarm_RateRangeConfig.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OnuItuPonAlarm_RateRangeConfig proto.InternalMessageInfo
+
+func (m *OnuItuPonAlarm_RateRangeConfig) GetRateRangeLower() uint64 {
+	if m != nil {
+		return m.RateRangeLower
+	}
+	return 0
+}
+
+func (m *OnuItuPonAlarm_RateRangeConfig) GetRateRangeUpper() uint64 {
+	if m != nil {
+		return m.RateRangeUpper
+	}
+	return 0
+}
+
+func (m *OnuItuPonAlarm_RateRangeConfig) GetSoakTime() *OnuItuPonAlarm_SoakTime {
+	if m != nil {
+		return m.SoakTime
+	}
+	return nil
+}
+
+type OnuItuPonAlarm_ValueThresholdConfig struct {
+	ThresholdLimit       uint64                   `protobuf:"fixed64,1,opt,name=threshold_limit,json=thresholdLimit,proto3" json:"threshold_limit,omitempty"`
+	SoakTime             *OnuItuPonAlarm_SoakTime `protobuf:"bytes,2,opt,name=soak_time,json=soakTime,proto3" json:"soak_time,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}                 `json:"-"`
+	XXX_unrecognized     []byte                   `json:"-"`
+	XXX_sizecache        int32                    `json:"-"`
+}
+
+func (m *OnuItuPonAlarm_ValueThresholdConfig) Reset()         { *m = OnuItuPonAlarm_ValueThresholdConfig{} }
+func (m *OnuItuPonAlarm_ValueThresholdConfig) String() string { return proto.CompactTextString(m) }
+func (*OnuItuPonAlarm_ValueThresholdConfig) ProtoMessage()    {}
+func (*OnuItuPonAlarm_ValueThresholdConfig) Descriptor() ([]byte, []int) {
+	return fileDescriptor_fb43b44b7fa3aba9, []int{1, 3}
+}
+
+func (m *OnuItuPonAlarm_ValueThresholdConfig) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_OnuItuPonAlarm_ValueThresholdConfig.Unmarshal(m, b)
+}
+func (m *OnuItuPonAlarm_ValueThresholdConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_OnuItuPonAlarm_ValueThresholdConfig.Marshal(b, m, deterministic)
+}
+func (m *OnuItuPonAlarm_ValueThresholdConfig) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_OnuItuPonAlarm_ValueThresholdConfig.Merge(m, src)
+}
+func (m *OnuItuPonAlarm_ValueThresholdConfig) XXX_Size() int {
+	return xxx_messageInfo_OnuItuPonAlarm_ValueThresholdConfig.Size(m)
+}
+func (m *OnuItuPonAlarm_ValueThresholdConfig) XXX_DiscardUnknown() {
+	xxx_messageInfo_OnuItuPonAlarm_ValueThresholdConfig.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OnuItuPonAlarm_ValueThresholdConfig proto.InternalMessageInfo
+
+func (m *OnuItuPonAlarm_ValueThresholdConfig) GetThresholdLimit() uint64 {
+	if m != nil {
+		return m.ThresholdLimit
+	}
+	return 0
+}
+
+func (m *OnuItuPonAlarm_ValueThresholdConfig) GetSoakTime() *OnuItuPonAlarm_SoakTime {
+	if m != nil {
+		return m.SoakTime
+	}
+	return nil
+}
+
+func init() {
+	proto.RegisterEnum("config.OnuItuPonAlarm_AlarmID", OnuItuPonAlarm_AlarmID_name, OnuItuPonAlarm_AlarmID_value)
+	proto.RegisterEnum("config.OnuItuPonAlarm_AlarmReportingCondition", OnuItuPonAlarm_AlarmReportingCondition_name, OnuItuPonAlarm_AlarmReportingCondition_value)
+	proto.RegisterType((*AlarmConfig)(nil), "config.AlarmConfig")
+	proto.RegisterType((*OnuItuPonAlarm)(nil), "config.OnuItuPonAlarm")
+	proto.RegisterType((*OnuItuPonAlarm_SoakTime)(nil), "config.OnuItuPonAlarm.SoakTime")
+	proto.RegisterType((*OnuItuPonAlarm_RateThresholdConfig)(nil), "config.OnuItuPonAlarm.RateThresholdConfig")
+	proto.RegisterType((*OnuItuPonAlarm_RateRangeConfig)(nil), "config.OnuItuPonAlarm.RateRangeConfig")
+	proto.RegisterType((*OnuItuPonAlarm_ValueThresholdConfig)(nil), "config.OnuItuPonAlarm.ValueThresholdConfig")
+}
+
+func init() { proto.RegisterFile("voltha_protos/ext_config.proto", fileDescriptor_fb43b44b7fa3aba9) }
+
+var fileDescriptor_fb43b44b7fa3aba9 = []byte{
+	// 609 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xd1, 0x4e, 0x1a, 0x41,
+	0x14, 0x05, 0xac, 0x80, 0xd7, 0x14, 0xe8, 0x80, 0x8a, 0x3e, 0x58, 0xe3, 0x83, 0x35, 0x6d, 0xba,
+	0x24, 0xd4, 0x97, 0x26, 0x7d, 0x41, 0xa5, 0x85, 0x84, 0xa8, 0x19, 0xd1, 0x87, 0xa6, 0xc9, 0x76,
+	0x64, 0xc7, 0x65, 0xea, 0x32, 0xb3, 0x19, 0x66, 0x69, 0x5f, 0xfa, 0x35, 0xfd, 0x8e, 0xf6, 0xdb,
+	0x9a, 0x99, 0xd9, 0x05, 0x81, 0xc5, 0xa4, 0xe9, 0x0b, 0xc9, 0x9e, 0x7b, 0xcf, 0xb9, 0x87, 0x73,
+	0x67, 0x06, 0xf6, 0x27, 0x22, 0x50, 0x43, 0xe2, 0x86, 0x52, 0x28, 0x31, 0x6e, 0xd0, 0x1f, 0xca,
+	0x1d, 0x08, 0x7e, 0xcf, 0x7c, 0xc7, 0x20, 0x28, 0x6f, 0xbf, 0x0e, 0x19, 0x6c, 0xb6, 0x02, 0x22,
+	0x47, 0x67, 0xe6, 0x13, 0x5d, 0x41, 0x5d, 0xf0, 0xc8, 0x65, 0x2a, 0x72, 0x43, 0xc1, 0x5d, 0xa2,
+	0x4b, 0x31, 0xb1, 0x9e, 0x3d, 0xc8, 0x1e, 0x6f, 0x36, 0xb7, 0x9d, 0x58, 0xe7, 0x92, 0x47, 0x5d,
+	0x15, 0x5d, 0x09, 0x6e, 0xf8, 0x9d, 0x0c, 0xae, 0x89, 0x39, 0xc4, 0x2a, 0x9e, 0x16, 0x21, 0x19,
+	0xf5, 0x67, 0x03, 0x4a, 0xf3, 0x24, 0xb4, 0x05, 0x79, 0x3d, 0x86, 0x33, 0x23, 0x5e, 0xc0, 0xeb,
+	0xa1, 0xe0, 0x17, 0x4c, 0xc3, 0xc6, 0x85, 0x57, 0xcf, 0x59, 0x58, 0x2b, 0x7b, 0xe8, 0x3d, 0x14,
+	0xad, 0x21, 0xe6, 0xd5, 0xd7, 0x0e, 0xb2, 0xc7, 0xa5, 0xe6, 0x7e, 0xba, 0x19, 0xc7, 0xfc, 0x76,
+	0xcf, 0x71, 0xc1, 0xf4, 0x77, 0x3d, 0xf4, 0x0d, 0x76, 0x2d, 0x55, 0xd2, 0x50, 0x48, 0xc5, 0xb8,
+	0xaf, 0xff, 0x95, 0xc7, 0x14, 0x13, 0xbc, 0xfe, 0xcc, 0x68, 0x39, 0x4f, 0x69, 0xe1, 0x84, 0x76,
+	0x96, 0xb0, 0xf0, 0x0e, 0x49, 0x2f, 0xa0, 0xaf, 0xb0, 0x25, 0x89, 0xa2, 0xae, 0x1a, 0x4a, 0x3a,
+	0x1e, 0x8a, 0xc0, 0x4b, 0x02, 0x5c, 0x37, 0x01, 0xbe, 0x5e, 0x31, 0x07, 0x13, 0x45, 0xfb, 0x09,
+	0xc5, 0x86, 0xd7, 0xc9, 0xe0, 0xaa, 0x5c, 0x86, 0x51, 0x1f, 0x5e, 0x98, 0x09, 0x92, 0x70, 0x9f,
+	0x26, 0xea, 0x79, 0xa3, 0x7e, 0xf4, 0x84, 0x3a, 0xd6, 0xed, 0x53, 0xe5, 0xb2, 0x9c, 0x87, 0xd0,
+	0x00, 0xb6, 0x27, 0x24, 0x88, 0x52, 0x8c, 0x17, 0x8c, 0xf4, 0x9b, 0x15, 0xd2, 0xb7, 0x9a, 0xb4,
+	0xec, 0xbc, 0x36, 0x49, 0xc1, 0xf7, 0xbe, 0x40, 0xf1, 0x5a, 0x90, 0x87, 0x3e, 0x1b, 0x51, 0x74,
+	0x0c, 0x15, 0x32, 0x50, 0x6c, 0x42, 0xdd, 0xb1, 0x20, 0x0f, 0xae, 0x62, 0x23, 0x1a, 0x9f, 0x83,
+	0x92, 0xc5, 0xa7, 0x9d, 0x47, 0x50, 0x1e, 0x04, 0x94, 0xc8, 0x47, 0x8d, 0xf6, 0x64, 0x3c, 0x37,
+	0x70, 0xd2, 0xb7, 0xf7, 0x3b, 0x0b, 0xd5, 0x94, 0x1c, 0x51, 0x73, 0x69, 0x25, 0x92, 0x8d, 0x19,
+	0xb7, 0x67, 0x3a, 0xbf, 0x10, 0x32, 0x36, 0x25, 0x74, 0x02, 0xdb, 0x0b, 0x9c, 0x7b, 0x12, 0x04,
+	0x9a, 0x94, 0x33, 0xa4, 0xda, 0x1c, 0xe9, 0xa3, 0xad, 0xa1, 0x0f, 0xb0, 0x31, 0xf3, 0xb8, 0x66,
+	0x72, 0x7b, 0xb9, 0x22, 0xb7, 0xc4, 0x35, 0x2e, 0x8e, 0x13, 0xff, 0xbf, 0xb2, 0x50, 0x5e, 0xd8,
+	0x94, 0x4e, 0xe9, 0xd1, 0xb2, 0x03, 0xf1, 0x9d, 0xca, 0xd8, 0x76, 0x69, 0xba, 0xc1, 0x9e, 0x46,
+	0x17, 0x3a, 0xa3, 0x30, 0xa4, 0x32, 0xf6, 0x3a, 0xeb, 0xbc, 0xd1, 0xe8, 0x7f, 0xba, 0xfc, 0x09,
+	0xb5, 0xb4, 0x9d, 0xa3, 0x57, 0x50, 0x9e, 0x85, 0x15, 0xb0, 0x11, 0x53, 0x89, 0xd1, 0x29, 0xdc,
+	0xd3, 0xe8, 0xfc, 0xf8, 0xdc, 0x3f, 0x8e, 0x3f, 0xdc, 0x85, 0x42, 0x7c, 0xbf, 0x51, 0x09, 0x00,
+	0x9f, 0x77, 0xdd, 0x36, 0xc6, 0x97, 0xf8, 0xba, 0x92, 0x39, 0xc4, 0xb0, 0xb3, 0xe2, 0xba, 0x22,
+	0x04, 0x25, 0xdc, 0xea, 0xb7, 0xdd, 0x7e, 0x07, 0xb7, 0xaf, 0x3b, 0x97, 0xbd, 0xf3, 0x4a, 0xc6,
+	0xd0, 0x35, 0x86, 0x5b, 0x17, 0x9f, 0xda, 0x95, 0x2c, 0xaa, 0x42, 0xf9, 0xb6, 0xd5, 0xbb, 0x79,
+	0xdc, 0x94, 0x9b, 0x3d, 0x60, 0xa7, 0x5d, 0xa8, 0x0a, 0xe9, 0x3b, 0x22, 0xa4, 0x7c, 0x20, 0xa4,
+	0xe7, 0xd8, 0x27, 0xf6, 0x73, 0xd3, 0x67, 0x6a, 0x18, 0xdd, 0x39, 0x03, 0x31, 0x6a, 0x24, 0xb5,
+	0x86, 0xad, 0xbd, 0x8d, 0x9f, 0xdf, 0xc9, 0x49, 0xc3, 0x17, 0xfa, 0x11, 0x6e, 0x58, 0xa9, 0xbb,
+	0xbc, 0x29, 0xbc, 0xfb, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xe2, 0x77, 0x17, 0x08, 0xa7, 0x05, 0x00,
+	0x00,
+}
diff --git a/vendor/github.com/opencord/voltha-protos/v3/go/openolt/openolt.pb.go b/vendor/github.com/opencord/voltha-protos/v4/go/openolt/openolt.pb.go
similarity index 69%
rename from vendor/github.com/opencord/voltha-protos/v3/go/openolt/openolt.pb.go
rename to vendor/github.com/opencord/voltha-protos/v4/go/openolt/openolt.pb.go
index c22549c..606da10 100644
--- a/vendor/github.com/opencord/voltha-protos/v3/go/openolt/openolt.pb.go
+++ b/vendor/github.com/opencord/voltha-protos/v4/go/openolt/openolt.pb.go
@@ -7,7 +7,9 @@
 	context "context"
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
-	tech_profile "github.com/opencord/voltha-protos/v3/go/tech_profile"
+	common "github.com/opencord/voltha-protos/v4/go/common"
+	config "github.com/opencord/voltha-protos/v4/go/ext/config"
+	tech_profile "github.com/opencord/voltha-protos/v4/go/tech_profile"
 	_ "google.golang.org/genproto/googleapis/api/annotations"
 	grpc "google.golang.org/grpc"
 	math "math"
@@ -109,6 +111,135 @@
 const InferredAdditionBWIndication_InferredAdditionBWIndication_Assured = InferredAdditionBWIndication(tech_profile.InferredAdditionBWIndication_InferredAdditionBWIndication_Assured)
 const InferredAdditionBWIndication_InferredAdditionBWIndication_BestEffort = InferredAdditionBWIndication(tech_profile.InferredAdditionBWIndication_InferredAdditionBWIndication_BestEffort)
 
+// ID from public import voltha_protos/common.proto
+type ID = common.ID
+
+// IDs from public import voltha_protos/common.proto
+type IDs = common.IDs
+
+// AdminState from public import voltha_protos/common.proto
+type AdminState = common.AdminState
+
+// OperStatus from public import voltha_protos/common.proto
+type OperStatus = common.OperStatus
+
+// ConnectStatus from public import voltha_protos/common.proto
+type ConnectStatus = common.ConnectStatus
+
+// OperationResp from public import voltha_protos/common.proto
+type OperationResp = common.OperationResp
+
+// ValueType from public import voltha_protos/common.proto
+type ValueType = common.ValueType
+
+// ValueSpecifier from public import voltha_protos/common.proto
+type ValueSpecifier = common.ValueSpecifier
+
+// ReturnValues from public import voltha_protos/common.proto
+type ReturnValues = common.ReturnValues
+
+// TestModeKeys from public import voltha_protos/common.proto
+type TestModeKeys = common.TestModeKeys
+
+var TestModeKeys_name = common.TestModeKeys_name
+var TestModeKeys_value = common.TestModeKeys_value
+
+const TestModeKeys_api_test = TestModeKeys(common.TestModeKeys_api_test)
+
+// AdminState_Types from public import voltha_protos/common.proto
+type AdminState_Types = common.AdminState_Types
+
+var AdminState_Types_name = common.AdminState_Types_name
+var AdminState_Types_value = common.AdminState_Types_value
+
+const AdminState_UNKNOWN = AdminState_Types(common.AdminState_UNKNOWN)
+const AdminState_PREPROVISIONED = AdminState_Types(common.AdminState_PREPROVISIONED)
+const AdminState_ENABLED = AdminState_Types(common.AdminState_ENABLED)
+const AdminState_DISABLED = AdminState_Types(common.AdminState_DISABLED)
+const AdminState_DOWNLOADING_IMAGE = AdminState_Types(common.AdminState_DOWNLOADING_IMAGE)
+const AdminState_DELETED = AdminState_Types(common.AdminState_DELETED)
+const AdminState_DELETING = AdminState_Types(common.AdminState_DELETING)
+
+// OperStatus_Types from public import voltha_protos/common.proto
+type OperStatus_Types = common.OperStatus_Types
+
+var OperStatus_Types_name = common.OperStatus_Types_name
+var OperStatus_Types_value = common.OperStatus_Types_value
+
+const OperStatus_UNKNOWN = OperStatus_Types(common.OperStatus_UNKNOWN)
+const OperStatus_DISCOVERED = OperStatus_Types(common.OperStatus_DISCOVERED)
+const OperStatus_ACTIVATING = OperStatus_Types(common.OperStatus_ACTIVATING)
+const OperStatus_TESTING = OperStatus_Types(common.OperStatus_TESTING)
+const OperStatus_ACTIVE = OperStatus_Types(common.OperStatus_ACTIVE)
+const OperStatus_FAILED = OperStatus_Types(common.OperStatus_FAILED)
+
+// ConnectStatus_Types from public import voltha_protos/common.proto
+type ConnectStatus_Types = common.ConnectStatus_Types
+
+var ConnectStatus_Types_name = common.ConnectStatus_Types_name
+var ConnectStatus_Types_value = common.ConnectStatus_Types_value
+
+const ConnectStatus_UNKNOWN = ConnectStatus_Types(common.ConnectStatus_UNKNOWN)
+const ConnectStatus_UNREACHABLE = ConnectStatus_Types(common.ConnectStatus_UNREACHABLE)
+const ConnectStatus_REACHABLE = ConnectStatus_Types(common.ConnectStatus_REACHABLE)
+
+// OperationResp_OperationReturnCode from public import voltha_protos/common.proto
+type OperationResp_OperationReturnCode = common.OperationResp_OperationReturnCode
+
+var OperationResp_OperationReturnCode_name = common.OperationResp_OperationReturnCode_name
+var OperationResp_OperationReturnCode_value = common.OperationResp_OperationReturnCode_value
+
+const OperationResp_OPERATION_SUCCESS = OperationResp_OperationReturnCode(common.OperationResp_OPERATION_SUCCESS)
+const OperationResp_OPERATION_FAILURE = OperationResp_OperationReturnCode(common.OperationResp_OPERATION_FAILURE)
+const OperationResp_OPERATION_UNSUPPORTED = OperationResp_OperationReturnCode(common.OperationResp_OPERATION_UNSUPPORTED)
+
+// ValueType_Type from public import voltha_protos/common.proto
+type ValueType_Type = common.ValueType_Type
+
+var ValueType_Type_name = common.ValueType_Type_name
+var ValueType_Type_value = common.ValueType_Type_value
+
+const ValueType_EMPTY = ValueType_Type(common.ValueType_EMPTY)
+const ValueType_DISTANCE = ValueType_Type(common.ValueType_DISTANCE)
+
+//* activation fail reason.
+type OnuIndication_ActivationFailReason int32
+
+const (
+	OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE                    OnuIndication_ActivationFailReason = 0
+	OnuIndication_ONU_ACTIVATION_FAIL_REASON_RANGING                 OnuIndication_ActivationFailReason = 1
+	OnuIndication_ONU_ACTIVATION_FAIL_REASON_PASSWORD_AUTHENTICATION OnuIndication_ActivationFailReason = 2
+	OnuIndication_ONU_ACTIVATION_FAIL_REASON_LOS                     OnuIndication_ActivationFailReason = 3
+	OnuIndication_ONU_ACTIVATION_FAIL_ONU_ALARM                      OnuIndication_ActivationFailReason = 4
+	OnuIndication_ONU_ACTIVATION_FAIL_SWITCH_OVER                    OnuIndication_ActivationFailReason = 5
+)
+
+var OnuIndication_ActivationFailReason_name = map[int32]string{
+	0: "ONU_ACTIVATION_FAIL_REASON_NONE",
+	1: "ONU_ACTIVATION_FAIL_REASON_RANGING",
+	2: "ONU_ACTIVATION_FAIL_REASON_PASSWORD_AUTHENTICATION",
+	3: "ONU_ACTIVATION_FAIL_REASON_LOS",
+	4: "ONU_ACTIVATION_FAIL_ONU_ALARM",
+	5: "ONU_ACTIVATION_FAIL_SWITCH_OVER",
+}
+
+var OnuIndication_ActivationFailReason_value = map[string]int32{
+	"ONU_ACTIVATION_FAIL_REASON_NONE":                    0,
+	"ONU_ACTIVATION_FAIL_REASON_RANGING":                 1,
+	"ONU_ACTIVATION_FAIL_REASON_PASSWORD_AUTHENTICATION": 2,
+	"ONU_ACTIVATION_FAIL_REASON_LOS":                     3,
+	"ONU_ACTIVATION_FAIL_ONU_ALARM":                      4,
+	"ONU_ACTIVATION_FAIL_SWITCH_OVER":                    5,
+}
+
+func (x OnuIndication_ActivationFailReason) String() string {
+	return proto.EnumName(OnuIndication_ActivationFailReason_name, int32(x))
+}
+
+func (OnuIndication_ActivationFailReason) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_c072e7aa0dfd74d5, []int{5, 0}
+}
+
 type DeviceInfo_DeviceResourceRanges_Pool_PoolType int32
 
 const (
@@ -137,7 +268,7 @@
 }
 
 func (DeviceInfo_DeviceResourceRanges_Pool_PoolType) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{15, 0, 0, 0}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{16, 0, 0, 0}
 }
 
 type DeviceInfo_DeviceResourceRanges_Pool_SharingType int32
@@ -165,7 +296,7 @@
 }
 
 func (DeviceInfo_DeviceResourceRanges_Pool_SharingType) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{15, 0, 0, 1}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{16, 0, 0, 1}
 }
 
 type GroupMember_InterfaceType int32
@@ -193,7 +324,7 @@
 }
 
 func (GroupMember_InterfaceType) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{38, 0}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{44, 0}
 }
 
 type Group_GroupMembersCommand int32
@@ -221,7 +352,7 @@
 }
 
 func (Group_GroupMembersCommand) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{39, 0}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{45, 0}
 }
 
 type Indication struct {
@@ -441,6 +572,10 @@
 	//	*AlarmIndication_OnuItuPonStatsInd
 	//	*AlarmIndication_OnuDeactivationFailureInd
 	//	*AlarmIndication_OnuRemoteDefectInd
+	//	*AlarmIndication_OnuLossGemDelineationInd
+	//	*AlarmIndication_OnuPhysicalEquipmentErrorInd
+	//	*AlarmIndication_OnuLossOfAckInd
+	//	*AlarmIndication_OnuDiffReachExceededInd
 	Data                 isAlarmIndication_Data `protobuf_oneof:"data"`
 	XXX_NoUnkeyedLiteral struct{}               `json:"-"`
 	XXX_unrecognized     []byte                 `json:"-"`
@@ -536,6 +671,22 @@
 	OnuRemoteDefectInd *OnuRemoteDefectIndication `protobuf:"bytes,15,opt,name=onu_remote_defect_ind,json=onuRemoteDefectInd,proto3,oneof"`
 }
 
+type AlarmIndication_OnuLossGemDelineationInd struct {
+	OnuLossGemDelineationInd *OnuLossOfGEMChannelDelineationIndication `protobuf:"bytes,16,opt,name=onu_loss_gem_delineation_ind,json=onuLossGemDelineationInd,proto3,oneof"`
+}
+
+type AlarmIndication_OnuPhysicalEquipmentErrorInd struct {
+	OnuPhysicalEquipmentErrorInd *OnuPhysicalEquipmentErrorIndication `protobuf:"bytes,17,opt,name=onu_physical_equipment_error_ind,json=onuPhysicalEquipmentErrorInd,proto3,oneof"`
+}
+
+type AlarmIndication_OnuLossOfAckInd struct {
+	OnuLossOfAckInd *OnuLossOfAcknowledgementIndication `protobuf:"bytes,18,opt,name=onu_loss_of_ack_ind,json=onuLossOfAckInd,proto3,oneof"`
+}
+
+type AlarmIndication_OnuDiffReachExceededInd struct {
+	OnuDiffReachExceededInd *OnuDifferentialReachExceededIndication `protobuf:"bytes,19,opt,name=onu_diff_reach_exceeded_ind,json=onuDiffReachExceededInd,proto3,oneof"`
+}
+
 func (*AlarmIndication_LosInd) isAlarmIndication_Data() {}
 
 func (*AlarmIndication_DyingGaspInd) isAlarmIndication_Data() {}
@@ -566,6 +717,14 @@
 
 func (*AlarmIndication_OnuRemoteDefectInd) isAlarmIndication_Data() {}
 
+func (*AlarmIndication_OnuLossGemDelineationInd) isAlarmIndication_Data() {}
+
+func (*AlarmIndication_OnuPhysicalEquipmentErrorInd) isAlarmIndication_Data() {}
+
+func (*AlarmIndication_OnuLossOfAckInd) isAlarmIndication_Data() {}
+
+func (*AlarmIndication_OnuDiffReachExceededInd) isAlarmIndication_Data() {}
+
 func (m *AlarmIndication) GetData() isAlarmIndication_Data {
 	if m != nil {
 		return m.Data
@@ -678,6 +837,34 @@
 	return nil
 }
 
+func (m *AlarmIndication) GetOnuLossGemDelineationInd() *OnuLossOfGEMChannelDelineationIndication {
+	if x, ok := m.GetData().(*AlarmIndication_OnuLossGemDelineationInd); ok {
+		return x.OnuLossGemDelineationInd
+	}
+	return nil
+}
+
+func (m *AlarmIndication) GetOnuPhysicalEquipmentErrorInd() *OnuPhysicalEquipmentErrorIndication {
+	if x, ok := m.GetData().(*AlarmIndication_OnuPhysicalEquipmentErrorInd); ok {
+		return x.OnuPhysicalEquipmentErrorInd
+	}
+	return nil
+}
+
+func (m *AlarmIndication) GetOnuLossOfAckInd() *OnuLossOfAcknowledgementIndication {
+	if x, ok := m.GetData().(*AlarmIndication_OnuLossOfAckInd); ok {
+		return x.OnuLossOfAckInd
+	}
+	return nil
+}
+
+func (m *AlarmIndication) GetOnuDiffReachExceededInd() *OnuDifferentialReachExceededIndication {
+	if x, ok := m.GetData().(*AlarmIndication_OnuDiffReachExceededInd); ok {
+		return x.OnuDiffReachExceededInd
+	}
+	return nil
+}
+
 // XXX_OneofWrappers is for the internal use of the proto package.
 func (*AlarmIndication) XXX_OneofWrappers() []interface{} {
 	return []interface{}{
@@ -696,6 +883,10 @@
 		(*AlarmIndication_OnuItuPonStatsInd)(nil),
 		(*AlarmIndication_OnuDeactivationFailureInd)(nil),
 		(*AlarmIndication_OnuRemoteDefectInd)(nil),
+		(*AlarmIndication_OnuLossGemDelineationInd)(nil),
+		(*AlarmIndication_OnuPhysicalEquipmentErrorInd)(nil),
+		(*AlarmIndication_OnuLossOfAckInd)(nil),
+		(*AlarmIndication_OnuDiffReachExceededInd)(nil),
 	}
 }
 
@@ -833,14 +1024,15 @@
 }
 
 type OnuIndication struct {
-	IntfId               uint32        `protobuf:"fixed32,1,opt,name=intf_id,json=intfId,proto3" json:"intf_id,omitempty"`
-	OnuId                uint32        `protobuf:"fixed32,2,opt,name=onu_id,json=onuId,proto3" json:"onu_id,omitempty"`
-	OperState            string        `protobuf:"bytes,3,opt,name=oper_state,json=operState,proto3" json:"oper_state,omitempty"`
-	AdminState           string        `protobuf:"bytes,5,opt,name=admin_state,json=adminState,proto3" json:"admin_state,omitempty"`
-	SerialNumber         *SerialNumber `protobuf:"bytes,4,opt,name=serial_number,json=serialNumber,proto3" json:"serial_number,omitempty"`
-	XXX_NoUnkeyedLiteral struct{}      `json:"-"`
-	XXX_unrecognized     []byte        `json:"-"`
-	XXX_sizecache        int32         `json:"-"`
+	IntfId               uint32                             `protobuf:"fixed32,1,opt,name=intf_id,json=intfId,proto3" json:"intf_id,omitempty"`
+	OnuId                uint32                             `protobuf:"fixed32,2,opt,name=onu_id,json=onuId,proto3" json:"onu_id,omitempty"`
+	OperState            string                             `protobuf:"bytes,3,opt,name=oper_state,json=operState,proto3" json:"oper_state,omitempty"`
+	AdminState           string                             `protobuf:"bytes,5,opt,name=admin_state,json=adminState,proto3" json:"admin_state,omitempty"`
+	SerialNumber         *SerialNumber                      `protobuf:"bytes,4,opt,name=serial_number,json=serialNumber,proto3" json:"serial_number,omitempty"`
+	FailReason           OnuIndication_ActivationFailReason `protobuf:"varint,6,opt,name=fail_reason,json=failReason,proto3,enum=openolt.OnuIndication_ActivationFailReason" json:"fail_reason,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}                           `json:"-"`
+	XXX_unrecognized     []byte                             `json:"-"`
+	XXX_sizecache        int32                              `json:"-"`
 }
 
 func (m *OnuIndication) Reset()         { *m = OnuIndication{} }
@@ -903,6 +1095,13 @@
 	return nil
 }
 
+func (m *OnuIndication) GetFailReason() OnuIndication_ActivationFailReason {
+	if m != nil {
+		return m.FailReason
+	}
+	return OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE
+}
+
 type IntfOperIndication struct {
 	Type                 string   `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"`
 	IntfId               uint32   `protobuf:"fixed32,2,opt,name=intf_id,json=intfId,proto3" json:"intf_id,omitempty"`
@@ -1183,6 +1382,7 @@
 	OnuId                uint32        `protobuf:"fixed32,2,opt,name=onu_id,json=onuId,proto3" json:"onu_id,omitempty"`
 	SerialNumber         *SerialNumber `protobuf:"bytes,3,opt,name=serial_number,json=serialNumber,proto3" json:"serial_number,omitempty"`
 	Pir                  uint32        `protobuf:"fixed32,4,opt,name=pir,proto3" json:"pir,omitempty"`
+	OmccEncryption       bool          `protobuf:"varint,5,opt,name=omcc_encryption,json=omccEncryption,proto3" json:"omcc_encryption,omitempty"`
 	XXX_NoUnkeyedLiteral struct{}      `json:"-"`
 	XXX_unrecognized     []byte        `json:"-"`
 	XXX_sizecache        int32         `json:"-"`
@@ -1241,6 +1441,76 @@
 	return 0
 }
 
+func (m *Onu) GetOmccEncryption() bool {
+	if m != nil {
+		return m.OmccEncryption
+	}
+	return false
+}
+
+type OnuLogicalDistance struct {
+	IntfId                 uint32   `protobuf:"fixed32,1,opt,name=intf_id,json=intfId,proto3" json:"intf_id,omitempty"`
+	OnuId                  uint32   `protobuf:"fixed32,2,opt,name=onu_id,json=onuId,proto3" json:"onu_id,omitempty"`
+	LogicalOnuDistanceZero uint32   `protobuf:"fixed32,3,opt,name=logical_onu_distance_zero,json=logicalOnuDistanceZero,proto3" json:"logical_onu_distance_zero,omitempty"`
+	LogicalOnuDistance     uint32   `protobuf:"fixed32,4,opt,name=logical_onu_distance,json=logicalOnuDistance,proto3" json:"logical_onu_distance,omitempty"`
+	XXX_NoUnkeyedLiteral   struct{} `json:"-"`
+	XXX_unrecognized       []byte   `json:"-"`
+	XXX_sizecache          int32    `json:"-"`
+}
+
+func (m *OnuLogicalDistance) Reset()         { *m = OnuLogicalDistance{} }
+func (m *OnuLogicalDistance) String() string { return proto.CompactTextString(m) }
+func (*OnuLogicalDistance) ProtoMessage()    {}
+func (*OnuLogicalDistance) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c072e7aa0dfd74d5, []int{12}
+}
+
+func (m *OnuLogicalDistance) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_OnuLogicalDistance.Unmarshal(m, b)
+}
+func (m *OnuLogicalDistance) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_OnuLogicalDistance.Marshal(b, m, deterministic)
+}
+func (m *OnuLogicalDistance) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_OnuLogicalDistance.Merge(m, src)
+}
+func (m *OnuLogicalDistance) XXX_Size() int {
+	return xxx_messageInfo_OnuLogicalDistance.Size(m)
+}
+func (m *OnuLogicalDistance) XXX_DiscardUnknown() {
+	xxx_messageInfo_OnuLogicalDistance.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OnuLogicalDistance proto.InternalMessageInfo
+
+func (m *OnuLogicalDistance) GetIntfId() uint32 {
+	if m != nil {
+		return m.IntfId
+	}
+	return 0
+}
+
+func (m *OnuLogicalDistance) GetOnuId() uint32 {
+	if m != nil {
+		return m.OnuId
+	}
+	return 0
+}
+
+func (m *OnuLogicalDistance) GetLogicalOnuDistanceZero() uint32 {
+	if m != nil {
+		return m.LogicalOnuDistanceZero
+	}
+	return 0
+}
+
+func (m *OnuLogicalDistance) GetLogicalOnuDistance() uint32 {
+	if m != nil {
+		return m.LogicalOnuDistance
+	}
+	return 0
+}
+
 type OmciMsg struct {
 	IntfId               uint32   `protobuf:"fixed32,1,opt,name=intf_id,json=intfId,proto3" json:"intf_id,omitempty"`
 	OnuId                uint32   `protobuf:"fixed32,2,opt,name=onu_id,json=onuId,proto3" json:"onu_id,omitempty"`
@@ -1254,7 +1524,7 @@
 func (m *OmciMsg) String() string { return proto.CompactTextString(m) }
 func (*OmciMsg) ProtoMessage()    {}
 func (*OmciMsg) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{12}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{13}
 }
 
 func (m *OmciMsg) XXX_Unmarshal(b []byte) error {
@@ -1311,7 +1581,7 @@
 func (m *OnuPacket) String() string { return proto.CompactTextString(m) }
 func (*OnuPacket) ProtoMessage()    {}
 func (*OnuPacket) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{13}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{14}
 }
 
 func (m *OnuPacket) XXX_Unmarshal(b []byte) error {
@@ -1379,7 +1649,7 @@
 func (m *UplinkPacket) String() string { return proto.CompactTextString(m) }
 func (*UplinkPacket) ProtoMessage()    {}
 func (*UplinkPacket) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{14}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{15}
 }
 
 func (m *UplinkPacket) XXX_Unmarshal(b []byte) error {
@@ -1443,7 +1713,7 @@
 func (m *DeviceInfo) String() string { return proto.CompactTextString(m) }
 func (*DeviceInfo) ProtoMessage()    {}
 func (*DeviceInfo) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{15}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{16}
 }
 
 func (m *DeviceInfo) XXX_Unmarshal(b []byte) error {
@@ -1599,7 +1869,7 @@
 func (m *DeviceInfo_DeviceResourceRanges) String() string { return proto.CompactTextString(m) }
 func (*DeviceInfo_DeviceResourceRanges) ProtoMessage()    {}
 func (*DeviceInfo_DeviceResourceRanges) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{15, 0}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{16, 0}
 }
 
 func (m *DeviceInfo_DeviceResourceRanges) XXX_Unmarshal(b []byte) error {
@@ -1655,7 +1925,7 @@
 func (m *DeviceInfo_DeviceResourceRanges_Pool) String() string { return proto.CompactTextString(m) }
 func (*DeviceInfo_DeviceResourceRanges_Pool) ProtoMessage()    {}
 func (*DeviceInfo_DeviceResourceRanges_Pool) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{15, 0, 0}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{16, 0, 0}
 }
 
 func (m *DeviceInfo_DeviceResourceRanges_Pool) XXX_Unmarshal(b []byte) error {
@@ -1729,7 +1999,7 @@
 func (m *Classifier) String() string { return proto.CompactTextString(m) }
 func (*Classifier) ProtoMessage()    {}
 func (*Classifier) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{16}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{17}
 }
 
 func (m *Classifier) XXX_Unmarshal(b []byte) error {
@@ -1874,7 +2144,7 @@
 func (m *ActionCmd) String() string { return proto.CompactTextString(m) }
 func (*ActionCmd) ProtoMessage()    {}
 func (*ActionCmd) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{17}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{18}
 }
 
 func (m *ActionCmd) XXX_Unmarshal(b []byte) error {
@@ -1975,7 +2245,7 @@
 func (m *Action) String() string { return proto.CompactTextString(m) }
 func (*Action) ProtoMessage()    {}
 func (*Action) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{18}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{19}
 }
 
 func (m *Action) XXX_Unmarshal(b []byte) error {
@@ -2046,30 +2316,34 @@
 }
 
 type Flow struct {
-	AccessIntfId         int32       `protobuf:"fixed32,1,opt,name=access_intf_id,json=accessIntfId,proto3" json:"access_intf_id,omitempty"`
-	OnuId                int32       `protobuf:"fixed32,2,opt,name=onu_id,json=onuId,proto3" json:"onu_id,omitempty"`
-	UniId                int32       `protobuf:"fixed32,11,opt,name=uni_id,json=uniId,proto3" json:"uni_id,omitempty"`
-	FlowId               uint32      `protobuf:"fixed32,3,opt,name=flow_id,json=flowId,proto3" json:"flow_id,omitempty"`
-	FlowType             string      `protobuf:"bytes,4,opt,name=flow_type,json=flowType,proto3" json:"flow_type,omitempty"`
-	AllocId              int32       `protobuf:"fixed32,10,opt,name=alloc_id,json=allocId,proto3" json:"alloc_id,omitempty"`
-	NetworkIntfId        int32       `protobuf:"fixed32,5,opt,name=network_intf_id,json=networkIntfId,proto3" json:"network_intf_id,omitempty"`
-	GemportId            int32       `protobuf:"fixed32,6,opt,name=gemport_id,json=gemportId,proto3" json:"gemport_id,omitempty"`
-	Classifier           *Classifier `protobuf:"bytes,7,opt,name=classifier,proto3" json:"classifier,omitempty"`
-	Action               *Action     `protobuf:"bytes,8,opt,name=action,proto3" json:"action,omitempty"`
-	Priority             int32       `protobuf:"fixed32,9,opt,name=priority,proto3" json:"priority,omitempty"`
-	Cookie               uint64      `protobuf:"fixed64,12,opt,name=cookie,proto3" json:"cookie,omitempty"`
-	PortNo               uint32      `protobuf:"fixed32,13,opt,name=port_no,json=portNo,proto3" json:"port_no,omitempty"`
-	GroupId              uint32      `protobuf:"fixed32,14,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"`
-	XXX_NoUnkeyedLiteral struct{}    `json:"-"`
-	XXX_unrecognized     []byte      `json:"-"`
-	XXX_sizecache        int32       `json:"-"`
+	AccessIntfId         int32             `protobuf:"fixed32,1,opt,name=access_intf_id,json=accessIntfId,proto3" json:"access_intf_id,omitempty"`
+	OnuId                int32             `protobuf:"fixed32,2,opt,name=onu_id,json=onuId,proto3" json:"onu_id,omitempty"`
+	UniId                int32             `protobuf:"fixed32,11,opt,name=uni_id,json=uniId,proto3" json:"uni_id,omitempty"`
+	FlowId               uint64            `protobuf:"fixed64,3,opt,name=flow_id,json=flowId,proto3" json:"flow_id,omitempty"`
+	SymmetricFlowId      uint64            `protobuf:"fixed64,18,opt,name=symmetric_flow_id,json=symmetricFlowId,proto3" json:"symmetric_flow_id,omitempty"`
+	FlowType             string            `protobuf:"bytes,4,opt,name=flow_type,json=flowType,proto3" json:"flow_type,omitempty"`
+	AllocId              int32             `protobuf:"fixed32,10,opt,name=alloc_id,json=allocId,proto3" json:"alloc_id,omitempty"`
+	NetworkIntfId        int32             `protobuf:"fixed32,5,opt,name=network_intf_id,json=networkIntfId,proto3" json:"network_intf_id,omitempty"`
+	GemportId            int32             `protobuf:"fixed32,6,opt,name=gemport_id,json=gemportId,proto3" json:"gemport_id,omitempty"`
+	Classifier           *Classifier       `protobuf:"bytes,7,opt,name=classifier,proto3" json:"classifier,omitempty"`
+	Action               *Action           `protobuf:"bytes,8,opt,name=action,proto3" json:"action,omitempty"`
+	Priority             int32             `protobuf:"fixed32,9,opt,name=priority,proto3" json:"priority,omitempty"`
+	Cookie               uint64            `protobuf:"fixed64,12,opt,name=cookie,proto3" json:"cookie,omitempty"`
+	PortNo               uint32            `protobuf:"fixed32,13,opt,name=port_no,json=portNo,proto3" json:"port_no,omitempty"`
+	GroupId              uint32            `protobuf:"fixed32,14,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"`
+	TechProfileId        uint32            `protobuf:"fixed32,15,opt,name=tech_profile_id,json=techProfileId,proto3" json:"tech_profile_id,omitempty"`
+	ReplicateFlow        bool              `protobuf:"varint,16,opt,name=replicate_flow,json=replicateFlow,proto3" json:"replicate_flow,omitempty"`
+	PbitToGemport        map[uint32]uint32 `protobuf:"bytes,17,rep,name=pbit_to_gemport,json=pbitToGemport,proto3" json:"pbit_to_gemport,omitempty" protobuf_key:"fixed32,1,opt,name=key,proto3" protobuf_val:"fixed32,2,opt,name=value,proto3"`
+	XXX_NoUnkeyedLiteral struct{}          `json:"-"`
+	XXX_unrecognized     []byte            `json:"-"`
+	XXX_sizecache        int32             `json:"-"`
 }
 
 func (m *Flow) Reset()         { *m = Flow{} }
 func (m *Flow) String() string { return proto.CompactTextString(m) }
 func (*Flow) ProtoMessage()    {}
 func (*Flow) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{19}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{20}
 }
 
 func (m *Flow) XXX_Unmarshal(b []byte) error {
@@ -2111,13 +2385,20 @@
 	return 0
 }
 
-func (m *Flow) GetFlowId() uint32 {
+func (m *Flow) GetFlowId() uint64 {
 	if m != nil {
 		return m.FlowId
 	}
 	return 0
 }
 
+func (m *Flow) GetSymmetricFlowId() uint64 {
+	if m != nil {
+		return m.SymmetricFlowId
+	}
+	return 0
+}
+
 func (m *Flow) GetFlowType() string {
 	if m != nil {
 		return m.FlowType
@@ -2188,6 +2469,27 @@
 	return 0
 }
 
+func (m *Flow) GetTechProfileId() uint32 {
+	if m != nil {
+		return m.TechProfileId
+	}
+	return 0
+}
+
+func (m *Flow) GetReplicateFlow() bool {
+	if m != nil {
+		return m.ReplicateFlow
+	}
+	return false
+}
+
+func (m *Flow) GetPbitToGemport() map[uint32]uint32 {
+	if m != nil {
+		return m.PbitToGemport
+	}
+	return nil
+}
+
 type SerialNumber struct {
 	VendorId             []byte   `protobuf:"bytes,1,opt,name=vendor_id,json=vendorId,proto3" json:"vendor_id,omitempty"`
 	VendorSpecific       []byte   `protobuf:"bytes,2,opt,name=vendor_specific,json=vendorSpecific,proto3" json:"vendor_specific,omitempty"`
@@ -2200,7 +2502,7 @@
 func (m *SerialNumber) String() string { return proto.CompactTextString(m) }
 func (*SerialNumber) ProtoMessage()    {}
 func (*SerialNumber) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{20}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{21}
 }
 
 func (m *SerialNumber) XXX_Unmarshal(b []byte) error {
@@ -2261,7 +2563,7 @@
 func (m *PortStatistics) String() string { return proto.CompactTextString(m) }
 func (*PortStatistics) ProtoMessage()    {}
 func (*PortStatistics) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{21}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{22}
 }
 
 func (m *PortStatistics) XXX_Unmarshal(b []byte) error {
@@ -2410,7 +2712,7 @@
 func (m *FlowStatistics) String() string { return proto.CompactTextString(m) }
 func (*FlowStatistics) ProtoMessage()    {}
 func (*FlowStatistics) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{22}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{23}
 }
 
 func (m *FlowStatistics) XXX_Unmarshal(b []byte) error {
@@ -2485,7 +2787,7 @@
 func (m *LosIndication) String() string { return proto.CompactTextString(m) }
 func (*LosIndication) ProtoMessage()    {}
 func (*LosIndication) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{23}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{24}
 }
 
 func (m *LosIndication) XXX_Unmarshal(b []byte) error {
@@ -2533,7 +2835,7 @@
 func (m *DyingGaspIndication) String() string { return proto.CompactTextString(m) }
 func (*DyingGaspIndication) ProtoMessage()    {}
 func (*DyingGaspIndication) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{24}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{25}
 }
 
 func (m *DyingGaspIndication) XXX_Unmarshal(b []byte) error {
@@ -2593,7 +2895,7 @@
 func (m *OnuAlarmIndication) String() string { return proto.CompactTextString(m) }
 func (*OnuAlarmIndication) ProtoMessage()    {}
 func (*OnuAlarmIndication) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{25}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{26}
 }
 
 func (m *OnuAlarmIndication) XXX_Unmarshal(b []byte) error {
@@ -2683,7 +2985,7 @@
 func (m *OnuStartupFailureIndication) String() string { return proto.CompactTextString(m) }
 func (*OnuStartupFailureIndication) ProtoMessage()    {}
 func (*OnuStartupFailureIndication) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{26}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{27}
 }
 
 func (m *OnuStartupFailureIndication) XXX_Unmarshal(b []byte) error {
@@ -2739,7 +3041,7 @@
 func (m *OnuSignalDegradeIndication) String() string { return proto.CompactTextString(m) }
 func (*OnuSignalDegradeIndication) ProtoMessage()    {}
 func (*OnuSignalDegradeIndication) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{27}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{28}
 }
 
 func (m *OnuSignalDegradeIndication) XXX_Unmarshal(b []byte) error {
@@ -2803,7 +3105,7 @@
 func (m *OnuDriftOfWindowIndication) String() string { return proto.CompactTextString(m) }
 func (*OnuDriftOfWindowIndication) ProtoMessage()    {}
 func (*OnuDriftOfWindowIndication) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{28}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{29}
 }
 
 func (m *OnuDriftOfWindowIndication) XXX_Unmarshal(b []byte) error {
@@ -2872,7 +3174,7 @@
 func (m *OnuLossOfOmciChannelIndication) String() string { return proto.CompactTextString(m) }
 func (*OnuLossOfOmciChannelIndication) ProtoMessage()    {}
 func (*OnuLossOfOmciChannelIndication) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{29}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{30}
 }
 
 func (m *OnuLossOfOmciChannelIndication) XXX_Unmarshal(b []byte) error {
@@ -2928,7 +3230,7 @@
 func (m *OnuSignalsFailureIndication) String() string { return proto.CompactTextString(m) }
 func (*OnuSignalsFailureIndication) ProtoMessage()    {}
 func (*OnuSignalsFailureIndication) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{30}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{31}
 }
 
 func (m *OnuSignalsFailureIndication) XXX_Unmarshal(b []byte) error {
@@ -2991,7 +3293,7 @@
 func (m *OnuTransmissionInterferenceWarning) String() string { return proto.CompactTextString(m) }
 func (*OnuTransmissionInterferenceWarning) ProtoMessage()    {}
 func (*OnuTransmissionInterferenceWarning) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{31}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{32}
 }
 
 func (m *OnuTransmissionInterferenceWarning) XXX_Unmarshal(b []byte) error {
@@ -3053,7 +3355,7 @@
 func (m *OnuActivationFailureIndication) String() string { return proto.CompactTextString(m) }
 func (*OnuActivationFailureIndication) ProtoMessage()    {}
 func (*OnuActivationFailureIndication) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{32}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{33}
 }
 
 func (m *OnuActivationFailureIndication) XXX_Unmarshal(b []byte) error {
@@ -3108,7 +3410,7 @@
 func (m *OnuLossOfKeySyncFailureIndication) String() string { return proto.CompactTextString(m) }
 func (*OnuLossOfKeySyncFailureIndication) ProtoMessage()    {}
 func (*OnuLossOfKeySyncFailureIndication) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{33}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{34}
 }
 
 func (m *OnuLossOfKeySyncFailureIndication) XXX_Unmarshal(b []byte) error {
@@ -3150,20 +3452,69 @@
 	return ""
 }
 
-type OnuItuPonStatsIndication struct {
-	IntfId               uint32   `protobuf:"fixed32,1,opt,name=intf_id,json=intfId,proto3" json:"intf_id,omitempty"`
-	OnuId                uint32   `protobuf:"fixed32,2,opt,name=onu_id,json=onuId,proto3" json:"onu_id,omitempty"`
-	RdiErrors            uint32   `protobuf:"fixed32,3,opt,name=rdi_errors,json=rdiErrors,proto3" json:"rdi_errors,omitempty"`
+type RdiErrorIndication struct {
+	RdiErrorCount        uint64   `protobuf:"fixed64,1,opt,name=rdi_error_count,json=rdiErrorCount,proto3" json:"rdi_error_count,omitempty"`
+	Status               string   `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
 	XXX_sizecache        int32    `json:"-"`
 }
 
+func (m *RdiErrorIndication) Reset()         { *m = RdiErrorIndication{} }
+func (m *RdiErrorIndication) String() string { return proto.CompactTextString(m) }
+func (*RdiErrorIndication) ProtoMessage()    {}
+func (*RdiErrorIndication) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c072e7aa0dfd74d5, []int{35}
+}
+
+func (m *RdiErrorIndication) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_RdiErrorIndication.Unmarshal(m, b)
+}
+func (m *RdiErrorIndication) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_RdiErrorIndication.Marshal(b, m, deterministic)
+}
+func (m *RdiErrorIndication) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_RdiErrorIndication.Merge(m, src)
+}
+func (m *RdiErrorIndication) XXX_Size() int {
+	return xxx_messageInfo_RdiErrorIndication.Size(m)
+}
+func (m *RdiErrorIndication) XXX_DiscardUnknown() {
+	xxx_messageInfo_RdiErrorIndication.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_RdiErrorIndication proto.InternalMessageInfo
+
+func (m *RdiErrorIndication) GetRdiErrorCount() uint64 {
+	if m != nil {
+		return m.RdiErrorCount
+	}
+	return 0
+}
+
+func (m *RdiErrorIndication) GetStatus() string {
+	if m != nil {
+		return m.Status
+	}
+	return ""
+}
+
+type OnuItuPonStatsIndication struct {
+	IntfId uint32 `protobuf:"fixed32,1,opt,name=intf_id,json=intfId,proto3" json:"intf_id,omitempty"`
+	OnuId  uint32 `protobuf:"fixed32,2,opt,name=onu_id,json=onuId,proto3" json:"onu_id,omitempty"`
+	// Types that are valid to be assigned to Stats:
+	//	*OnuItuPonStatsIndication_RdiErrorInd
+	Stats                isOnuItuPonStatsIndication_Stats `protobuf_oneof:"stats"`
+	XXX_NoUnkeyedLiteral struct{}                         `json:"-"`
+	XXX_unrecognized     []byte                           `json:"-"`
+	XXX_sizecache        int32                            `json:"-"`
+}
+
 func (m *OnuItuPonStatsIndication) Reset()         { *m = OnuItuPonStatsIndication{} }
 func (m *OnuItuPonStatsIndication) String() string { return proto.CompactTextString(m) }
 func (*OnuItuPonStatsIndication) ProtoMessage()    {}
 func (*OnuItuPonStatsIndication) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{34}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{36}
 }
 
 func (m *OnuItuPonStatsIndication) XXX_Unmarshal(b []byte) error {
@@ -3198,11 +3549,35 @@
 	return 0
 }
 
-func (m *OnuItuPonStatsIndication) GetRdiErrors() uint32 {
+type isOnuItuPonStatsIndication_Stats interface {
+	isOnuItuPonStatsIndication_Stats()
+}
+
+type OnuItuPonStatsIndication_RdiErrorInd struct {
+	RdiErrorInd *RdiErrorIndication `protobuf:"bytes,3,opt,name=rdi_error_ind,json=rdiErrorInd,proto3,oneof"`
+}
+
+func (*OnuItuPonStatsIndication_RdiErrorInd) isOnuItuPonStatsIndication_Stats() {}
+
+func (m *OnuItuPonStatsIndication) GetStats() isOnuItuPonStatsIndication_Stats {
 	if m != nil {
-		return m.RdiErrors
+		return m.Stats
 	}
-	return 0
+	return nil
+}
+
+func (m *OnuItuPonStatsIndication) GetRdiErrorInd() *RdiErrorIndication {
+	if x, ok := m.GetStats().(*OnuItuPonStatsIndication_RdiErrorInd); ok {
+		return x.RdiErrorInd
+	}
+	return nil
+}
+
+// XXX_OneofWrappers is for the internal use of the proto package.
+func (*OnuItuPonStatsIndication) XXX_OneofWrappers() []interface{} {
+	return []interface{}{
+		(*OnuItuPonStatsIndication_RdiErrorInd)(nil),
+	}
 }
 
 type OnuProcessingErrorIndication struct {
@@ -3217,7 +3592,7 @@
 func (m *OnuProcessingErrorIndication) String() string { return proto.CompactTextString(m) }
 func (*OnuProcessingErrorIndication) ProtoMessage()    {}
 func (*OnuProcessingErrorIndication) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{35}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{37}
 }
 
 func (m *OnuProcessingErrorIndication) XXX_Unmarshal(b []byte) error {
@@ -3255,7 +3630,7 @@
 type OnuDeactivationFailureIndication struct {
 	IntfId               uint32   `protobuf:"fixed32,1,opt,name=intf_id,json=intfId,proto3" json:"intf_id,omitempty"`
 	OnuId                uint32   `protobuf:"fixed32,2,opt,name=onu_id,json=onuId,proto3" json:"onu_id,omitempty"`
-	FailReason           uint32   `protobuf:"fixed32,3,opt,name=fail_reason,json=failReason,proto3" json:"fail_reason,omitempty"`
+	Status               string   `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
 	XXX_sizecache        int32    `json:"-"`
@@ -3265,7 +3640,7 @@
 func (m *OnuDeactivationFailureIndication) String() string { return proto.CompactTextString(m) }
 func (*OnuDeactivationFailureIndication) ProtoMessage()    {}
 func (*OnuDeactivationFailureIndication) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{36}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{38}
 }
 
 func (m *OnuDeactivationFailureIndication) XXX_Unmarshal(b []byte) error {
@@ -3300,17 +3675,17 @@
 	return 0
 }
 
-func (m *OnuDeactivationFailureIndication) GetFailReason() uint32 {
+func (m *OnuDeactivationFailureIndication) GetStatus() string {
 	if m != nil {
-		return m.FailReason
+		return m.Status
 	}
-	return 0
+	return ""
 }
 
 type OnuRemoteDefectIndication struct {
 	IntfId               uint32   `protobuf:"fixed32,1,opt,name=intf_id,json=intfId,proto3" json:"intf_id,omitempty"`
 	OnuId                uint32   `protobuf:"fixed32,2,opt,name=onu_id,json=onuId,proto3" json:"onu_id,omitempty"`
-	RdiErrors            uint32   `protobuf:"fixed32,3,opt,name=rdi_errors,json=rdiErrors,proto3" json:"rdi_errors,omitempty"`
+	RdiErrors            uint64   `protobuf:"fixed64,3,opt,name=rdi_errors,json=rdiErrors,proto3" json:"rdi_errors,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
 	XXX_sizecache        int32    `json:"-"`
@@ -3320,7 +3695,7 @@
 func (m *OnuRemoteDefectIndication) String() string { return proto.CompactTextString(m) }
 func (*OnuRemoteDefectIndication) ProtoMessage()    {}
 func (*OnuRemoteDefectIndication) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{37}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{39}
 }
 
 func (m *OnuRemoteDefectIndication) XXX_Unmarshal(b []byte) error {
@@ -3355,13 +3730,253 @@
 	return 0
 }
 
-func (m *OnuRemoteDefectIndication) GetRdiErrors() uint32 {
+func (m *OnuRemoteDefectIndication) GetRdiErrors() uint64 {
 	if m != nil {
 		return m.RdiErrors
 	}
 	return 0
 }
 
+type OnuLossOfGEMChannelDelineationIndication struct {
+	IntfId               uint32   `protobuf:"fixed32,1,opt,name=intf_id,json=intfId,proto3" json:"intf_id,omitempty"`
+	OnuId                uint32   `protobuf:"fixed32,2,opt,name=onu_id,json=onuId,proto3" json:"onu_id,omitempty"`
+	Status               string   `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"`
+	DelineationErrors    uint32   `protobuf:"fixed32,4,opt,name=delineation_errors,json=delineationErrors,proto3" json:"delineation_errors,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *OnuLossOfGEMChannelDelineationIndication) Reset() {
+	*m = OnuLossOfGEMChannelDelineationIndication{}
+}
+func (m *OnuLossOfGEMChannelDelineationIndication) String() string { return proto.CompactTextString(m) }
+func (*OnuLossOfGEMChannelDelineationIndication) ProtoMessage()    {}
+func (*OnuLossOfGEMChannelDelineationIndication) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c072e7aa0dfd74d5, []int{40}
+}
+
+func (m *OnuLossOfGEMChannelDelineationIndication) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_OnuLossOfGEMChannelDelineationIndication.Unmarshal(m, b)
+}
+func (m *OnuLossOfGEMChannelDelineationIndication) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_OnuLossOfGEMChannelDelineationIndication.Marshal(b, m, deterministic)
+}
+func (m *OnuLossOfGEMChannelDelineationIndication) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_OnuLossOfGEMChannelDelineationIndication.Merge(m, src)
+}
+func (m *OnuLossOfGEMChannelDelineationIndication) XXX_Size() int {
+	return xxx_messageInfo_OnuLossOfGEMChannelDelineationIndication.Size(m)
+}
+func (m *OnuLossOfGEMChannelDelineationIndication) XXX_DiscardUnknown() {
+	xxx_messageInfo_OnuLossOfGEMChannelDelineationIndication.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OnuLossOfGEMChannelDelineationIndication proto.InternalMessageInfo
+
+func (m *OnuLossOfGEMChannelDelineationIndication) GetIntfId() uint32 {
+	if m != nil {
+		return m.IntfId
+	}
+	return 0
+}
+
+func (m *OnuLossOfGEMChannelDelineationIndication) GetOnuId() uint32 {
+	if m != nil {
+		return m.OnuId
+	}
+	return 0
+}
+
+func (m *OnuLossOfGEMChannelDelineationIndication) GetStatus() string {
+	if m != nil {
+		return m.Status
+	}
+	return ""
+}
+
+func (m *OnuLossOfGEMChannelDelineationIndication) GetDelineationErrors() uint32 {
+	if m != nil {
+		return m.DelineationErrors
+	}
+	return 0
+}
+
+type OnuPhysicalEquipmentErrorIndication struct {
+	IntfId               uint32   `protobuf:"fixed32,1,opt,name=intf_id,json=intfId,proto3" json:"intf_id,omitempty"`
+	OnuId                uint32   `protobuf:"fixed32,2,opt,name=onu_id,json=onuId,proto3" json:"onu_id,omitempty"`
+	Status               string   `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *OnuPhysicalEquipmentErrorIndication) Reset()         { *m = OnuPhysicalEquipmentErrorIndication{} }
+func (m *OnuPhysicalEquipmentErrorIndication) String() string { return proto.CompactTextString(m) }
+func (*OnuPhysicalEquipmentErrorIndication) ProtoMessage()    {}
+func (*OnuPhysicalEquipmentErrorIndication) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c072e7aa0dfd74d5, []int{41}
+}
+
+func (m *OnuPhysicalEquipmentErrorIndication) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_OnuPhysicalEquipmentErrorIndication.Unmarshal(m, b)
+}
+func (m *OnuPhysicalEquipmentErrorIndication) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_OnuPhysicalEquipmentErrorIndication.Marshal(b, m, deterministic)
+}
+func (m *OnuPhysicalEquipmentErrorIndication) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_OnuPhysicalEquipmentErrorIndication.Merge(m, src)
+}
+func (m *OnuPhysicalEquipmentErrorIndication) XXX_Size() int {
+	return xxx_messageInfo_OnuPhysicalEquipmentErrorIndication.Size(m)
+}
+func (m *OnuPhysicalEquipmentErrorIndication) XXX_DiscardUnknown() {
+	xxx_messageInfo_OnuPhysicalEquipmentErrorIndication.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OnuPhysicalEquipmentErrorIndication proto.InternalMessageInfo
+
+func (m *OnuPhysicalEquipmentErrorIndication) GetIntfId() uint32 {
+	if m != nil {
+		return m.IntfId
+	}
+	return 0
+}
+
+func (m *OnuPhysicalEquipmentErrorIndication) GetOnuId() uint32 {
+	if m != nil {
+		return m.OnuId
+	}
+	return 0
+}
+
+func (m *OnuPhysicalEquipmentErrorIndication) GetStatus() string {
+	if m != nil {
+		return m.Status
+	}
+	return ""
+}
+
+type OnuLossOfAcknowledgementIndication struct {
+	IntfId               uint32   `protobuf:"fixed32,1,opt,name=intf_id,json=intfId,proto3" json:"intf_id,omitempty"`
+	OnuId                uint32   `protobuf:"fixed32,2,opt,name=onu_id,json=onuId,proto3" json:"onu_id,omitempty"`
+	Status               string   `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *OnuLossOfAcknowledgementIndication) Reset()         { *m = OnuLossOfAcknowledgementIndication{} }
+func (m *OnuLossOfAcknowledgementIndication) String() string { return proto.CompactTextString(m) }
+func (*OnuLossOfAcknowledgementIndication) ProtoMessage()    {}
+func (*OnuLossOfAcknowledgementIndication) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c072e7aa0dfd74d5, []int{42}
+}
+
+func (m *OnuLossOfAcknowledgementIndication) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_OnuLossOfAcknowledgementIndication.Unmarshal(m, b)
+}
+func (m *OnuLossOfAcknowledgementIndication) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_OnuLossOfAcknowledgementIndication.Marshal(b, m, deterministic)
+}
+func (m *OnuLossOfAcknowledgementIndication) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_OnuLossOfAcknowledgementIndication.Merge(m, src)
+}
+func (m *OnuLossOfAcknowledgementIndication) XXX_Size() int {
+	return xxx_messageInfo_OnuLossOfAcknowledgementIndication.Size(m)
+}
+func (m *OnuLossOfAcknowledgementIndication) XXX_DiscardUnknown() {
+	xxx_messageInfo_OnuLossOfAcknowledgementIndication.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OnuLossOfAcknowledgementIndication proto.InternalMessageInfo
+
+func (m *OnuLossOfAcknowledgementIndication) GetIntfId() uint32 {
+	if m != nil {
+		return m.IntfId
+	}
+	return 0
+}
+
+func (m *OnuLossOfAcknowledgementIndication) GetOnuId() uint32 {
+	if m != nil {
+		return m.OnuId
+	}
+	return 0
+}
+
+func (m *OnuLossOfAcknowledgementIndication) GetStatus() string {
+	if m != nil {
+		return m.Status
+	}
+	return ""
+}
+
+type OnuDifferentialReachExceededIndication struct {
+	IntfId               uint32   `protobuf:"fixed32,1,opt,name=intf_id,json=intfId,proto3" json:"intf_id,omitempty"`
+	OnuId                uint32   `protobuf:"fixed32,2,opt,name=onu_id,json=onuId,proto3" json:"onu_id,omitempty"`
+	Status               string   `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"`
+	Distance             uint32   `protobuf:"fixed32,4,opt,name=distance,proto3" json:"distance,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *OnuDifferentialReachExceededIndication) Reset() {
+	*m = OnuDifferentialReachExceededIndication{}
+}
+func (m *OnuDifferentialReachExceededIndication) String() string { return proto.CompactTextString(m) }
+func (*OnuDifferentialReachExceededIndication) ProtoMessage()    {}
+func (*OnuDifferentialReachExceededIndication) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c072e7aa0dfd74d5, []int{43}
+}
+
+func (m *OnuDifferentialReachExceededIndication) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_OnuDifferentialReachExceededIndication.Unmarshal(m, b)
+}
+func (m *OnuDifferentialReachExceededIndication) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_OnuDifferentialReachExceededIndication.Marshal(b, m, deterministic)
+}
+func (m *OnuDifferentialReachExceededIndication) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_OnuDifferentialReachExceededIndication.Merge(m, src)
+}
+func (m *OnuDifferentialReachExceededIndication) XXX_Size() int {
+	return xxx_messageInfo_OnuDifferentialReachExceededIndication.Size(m)
+}
+func (m *OnuDifferentialReachExceededIndication) XXX_DiscardUnknown() {
+	xxx_messageInfo_OnuDifferentialReachExceededIndication.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OnuDifferentialReachExceededIndication proto.InternalMessageInfo
+
+func (m *OnuDifferentialReachExceededIndication) GetIntfId() uint32 {
+	if m != nil {
+		return m.IntfId
+	}
+	return 0
+}
+
+func (m *OnuDifferentialReachExceededIndication) GetOnuId() uint32 {
+	if m != nil {
+		return m.OnuId
+	}
+	return 0
+}
+
+func (m *OnuDifferentialReachExceededIndication) GetStatus() string {
+	if m != nil {
+		return m.Status
+	}
+	return ""
+}
+
+func (m *OnuDifferentialReachExceededIndication) GetDistance() uint32 {
+	if m != nil {
+		return m.Distance
+	}
+	return 0
+}
+
 type GroupMember struct {
 	InterfaceId          uint32                    `protobuf:"varint,1,opt,name=interface_id,json=interfaceId,proto3" json:"interface_id,omitempty"`
 	InterfaceType        GroupMember_InterfaceType `protobuf:"varint,2,opt,name=interface_type,json=interfaceType,proto3,enum=openolt.GroupMember_InterfaceType" json:"interface_type,omitempty"`
@@ -3376,7 +3991,7 @@
 func (m *GroupMember) String() string { return proto.CompactTextString(m) }
 func (*GroupMember) ProtoMessage()    {}
 func (*GroupMember) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{38}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{44}
 }
 
 func (m *GroupMember) XXX_Unmarshal(b []byte) error {
@@ -3439,7 +4054,7 @@
 func (m *Group) String() string { return proto.CompactTextString(m) }
 func (*Group) ProtoMessage()    {}
 func (*Group) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{39}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{45}
 }
 
 func (m *Group) XXX_Unmarshal(b []byte) error {
@@ -3488,6 +4103,53 @@
 	return nil
 }
 
+type ValueParam struct {
+	Onu                  *Onu                  `protobuf:"bytes,1,opt,name=onu,proto3" json:"onu,omitempty"`
+	Value                common.ValueType_Type `protobuf:"varint,2,opt,name=value,proto3,enum=common.ValueType_Type" json:"value,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}              `json:"-"`
+	XXX_unrecognized     []byte                `json:"-"`
+	XXX_sizecache        int32                 `json:"-"`
+}
+
+func (m *ValueParam) Reset()         { *m = ValueParam{} }
+func (m *ValueParam) String() string { return proto.CompactTextString(m) }
+func (*ValueParam) ProtoMessage()    {}
+func (*ValueParam) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c072e7aa0dfd74d5, []int{46}
+}
+
+func (m *ValueParam) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ValueParam.Unmarshal(m, b)
+}
+func (m *ValueParam) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ValueParam.Marshal(b, m, deterministic)
+}
+func (m *ValueParam) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ValueParam.Merge(m, src)
+}
+func (m *ValueParam) XXX_Size() int {
+	return xxx_messageInfo_ValueParam.Size(m)
+}
+func (m *ValueParam) XXX_DiscardUnknown() {
+	xxx_messageInfo_ValueParam.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ValueParam proto.InternalMessageInfo
+
+func (m *ValueParam) GetOnu() *Onu {
+	if m != nil {
+		return m.Onu
+	}
+	return nil
+}
+
+func (m *ValueParam) GetValue() common.ValueType_Type {
+	if m != nil {
+		return m.Value
+	}
+	return common.ValueType_EMPTY
+}
+
 type Empty struct {
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -3498,7 +4160,7 @@
 func (m *Empty) String() string { return proto.CompactTextString(m) }
 func (*Empty) ProtoMessage()    {}
 func (*Empty) Descriptor() ([]byte, []int) {
-	return fileDescriptor_c072e7aa0dfd74d5, []int{40}
+	return fileDescriptor_c072e7aa0dfd74d5, []int{47}
 }
 
 func (m *Empty) XXX_Unmarshal(b []byte) error {
@@ -3520,6 +4182,7 @@
 var xxx_messageInfo_Empty proto.InternalMessageInfo
 
 func init() {
+	proto.RegisterEnum("openolt.OnuIndication_ActivationFailReason", OnuIndication_ActivationFailReason_name, OnuIndication_ActivationFailReason_value)
 	proto.RegisterEnum("openolt.DeviceInfo_DeviceResourceRanges_Pool_PoolType", DeviceInfo_DeviceResourceRanges_Pool_PoolType_name, DeviceInfo_DeviceResourceRanges_Pool_PoolType_value)
 	proto.RegisterEnum("openolt.DeviceInfo_DeviceResourceRanges_Pool_SharingType", DeviceInfo_DeviceResourceRanges_Pool_SharingType_name, DeviceInfo_DeviceResourceRanges_Pool_SharingType_value)
 	proto.RegisterEnum("openolt.GroupMember_InterfaceType", GroupMember_InterfaceType_name, GroupMember_InterfaceType_value)
@@ -3536,6 +4199,7 @@
 	proto.RegisterType((*Interface)(nil), "openolt.Interface")
 	proto.RegisterType((*Heartbeat)(nil), "openolt.Heartbeat")
 	proto.RegisterType((*Onu)(nil), "openolt.Onu")
+	proto.RegisterType((*OnuLogicalDistance)(nil), "openolt.OnuLogicalDistance")
 	proto.RegisterType((*OmciMsg)(nil), "openolt.OmciMsg")
 	proto.RegisterType((*OnuPacket)(nil), "openolt.OnuPacket")
 	proto.RegisterType((*UplinkPacket)(nil), "openolt.UplinkPacket")
@@ -3546,6 +4210,7 @@
 	proto.RegisterType((*ActionCmd)(nil), "openolt.ActionCmd")
 	proto.RegisterType((*Action)(nil), "openolt.Action")
 	proto.RegisterType((*Flow)(nil), "openolt.Flow")
+	proto.RegisterMapType((map[uint32]uint32)(nil), "openolt.Flow.PbitToGemportEntry")
 	proto.RegisterType((*SerialNumber)(nil), "openolt.SerialNumber")
 	proto.RegisterType((*PortStatistics)(nil), "openolt.PortStatistics")
 	proto.RegisterType((*FlowStatistics)(nil), "openolt.FlowStatistics")
@@ -3560,242 +4225,297 @@
 	proto.RegisterType((*OnuTransmissionInterferenceWarning)(nil), "openolt.OnuTransmissionInterferenceWarning")
 	proto.RegisterType((*OnuActivationFailureIndication)(nil), "openolt.OnuActivationFailureIndication")
 	proto.RegisterType((*OnuLossOfKeySyncFailureIndication)(nil), "openolt.OnuLossOfKeySyncFailureIndication")
+	proto.RegisterType((*RdiErrorIndication)(nil), "openolt.RdiErrorIndication")
 	proto.RegisterType((*OnuItuPonStatsIndication)(nil), "openolt.OnuItuPonStatsIndication")
 	proto.RegisterType((*OnuProcessingErrorIndication)(nil), "openolt.OnuProcessingErrorIndication")
 	proto.RegisterType((*OnuDeactivationFailureIndication)(nil), "openolt.OnuDeactivationFailureIndication")
 	proto.RegisterType((*OnuRemoteDefectIndication)(nil), "openolt.OnuRemoteDefectIndication")
+	proto.RegisterType((*OnuLossOfGEMChannelDelineationIndication)(nil), "openolt.OnuLossOfGEMChannelDelineationIndication")
+	proto.RegisterType((*OnuPhysicalEquipmentErrorIndication)(nil), "openolt.OnuPhysicalEquipmentErrorIndication")
+	proto.RegisterType((*OnuLossOfAcknowledgementIndication)(nil), "openolt.OnuLossOfAcknowledgementIndication")
+	proto.RegisterType((*OnuDifferentialReachExceededIndication)(nil), "openolt.OnuDifferentialReachExceededIndication")
 	proto.RegisterType((*GroupMember)(nil), "openolt.GroupMember")
 	proto.RegisterType((*Group)(nil), "openolt.Group")
+	proto.RegisterType((*ValueParam)(nil), "openolt.ValueParam")
 	proto.RegisterType((*Empty)(nil), "openolt.Empty")
 }
 
 func init() { proto.RegisterFile("voltha_protos/openolt.proto", fileDescriptor_c072e7aa0dfd74d5) }
 
 var fileDescriptor_c072e7aa0dfd74d5 = []byte{
-	// 3558 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x5a, 0x4f, 0x73, 0x23, 0x49,
-	0x56, 0x6f, 0xd9, 0xb2, 0x4a, 0x7a, 0xfa, 0x63, 0x75, 0xba, 0xdd, 0xed, 0x7f, 0xdb, 0xed, 0x29,
-	0x9a, 0x9d, 0xde, 0x81, 0xb5, 0x67, 0x7a, 0x36, 0x80, 0x1d, 0x16, 0x18, 0xdb, 0x52, 0xb7, 0xc5,
-	0xb4, 0x5b, 0xa6, 0xac, 0x9e, 0x86, 0x25, 0x26, 0x6a, 0xcb, 0x55, 0x29, 0x39, 0x71, 0xa9, 0xb2,
-	0xa6, 0x2a, 0x65, 0xb7, 0xaf, 0x0b, 0xcb, 0x07, 0x60, 0x83, 0x03, 0x1c, 0xe1, 0x0b, 0x70, 0xdc,
-	0x88, 0x39, 0x72, 0x25, 0xb8, 0xf0, 0x15, 0xf8, 0x0c, 0x9c, 0x38, 0x10, 0xf9, 0x32, 0xeb, 0x9f,
-	0x24, 0xbb, 0xdb, 0x83, 0x09, 0x2e, 0x0e, 0xe7, 0x7b, 0xbf, 0xf7, 0xcb, 0x7c, 0x99, 0x2f, 0x5f,
-	0xbe, 0xca, 0x14, 0x6c, 0x5e, 0x70, 0x5f, 0x9c, 0x39, 0x76, 0x18, 0x71, 0xc1, 0xe3, 0x5d, 0x1e,
-	0xd2, 0x80, 0xfb, 0x62, 0x07, 0x9b, 0xc4, 0xd0, 0xcd, 0x8d, 0xad, 0x11, 0xe7, 0x23, 0x9f, 0xee,
-	0x3a, 0x21, 0xdb, 0x75, 0x82, 0x80, 0x0b, 0x47, 0x30, 0x1e, 0xc4, 0x0a, 0xb6, 0xb1, 0x5d, 0xe4,
-	0x10, 0xd4, 0x3d, 0x93, 0xff, 0x0f, 0x99, 0x4f, 0x15, 0xc2, 0xfc, 0xb7, 0x32, 0x40, 0x2f, 0xf0,
-	0x98, 0x8b, 0x76, 0xe4, 0x33, 0x30, 0xb8, 0x2f, 0x6c, 0x16, 0x78, 0x6b, 0xa5, 0xed, 0xd2, 0xb3,
-	0xfa, 0xf3, 0x87, 0x3b, 0x49, 0xc7, 0x7d, 0x5f, 0x64, 0xc0, 0xc3, 0x7b, 0x56, 0x85, 0xa3, 0x80,
-	0xfc, 0x04, 0xaa, 0x2c, 0x10, 0x43, 0xb4, 0x59, 0x40, 0x9b, 0x47, 0xa9, 0x4d, 0x2f, 0x10, 0xc3,
-	0x82, 0x91, 0xc1, 0x94, 0x84, 0xec, 0x41, 0x13, 0xad, 0x78, 0x48, 0x23, 0x34, 0x5d, 0x44, 0xd3,
-	0xcd, 0x82, 0x69, 0x3f, 0xa4, 0x51, 0xc1, 0xbc, 0xce, 0x32, 0x29, 0xf9, 0x63, 0x68, 0xf0, 0x60,
-	0x62, 0x7b, 0x2c, 0x76, 0x91, 0xa1, 0x8c, 0x0c, 0x1b, 0xd9, 0x80, 0x83, 0x49, 0x87, 0xc5, 0x6e,
-	0x81, 0x00, 0x78, 0x2a, 0x44, 0x5f, 0x83, 0x09, 0x9a, 0x2e, 0x4d, 0xfb, 0x1a, 0x4c, 0xa6, 0x7c,
-	0x45, 0x81, 0xf4, 0x95, 0x8f, 0x5d, 0x86, 0x36, 0x95, 0x29, 0x5f, 0xfb, 0x63, 0x97, 0x15, 0x7d,
-	0xe5, 0x4a, 0x42, 0x7e, 0x02, 0x46, 0x78, 0xae, 0x26, 0xd5, 0x40, 0xa3, 0xf5, 0xd4, 0xe8, 0xd8,
-	0x71, 0xcf, 0xe9, 0xd4, 0xbc, 0x86, 0xe7, 0x38, 0xaf, 0x7f, 0x00, 0x10, 0xf2, 0x48, 0xd8, 0xb1,
-	0x70, 0x44, 0xbc, 0x56, 0x9d, 0xea, 0xed, 0x98, 0x47, 0xe2, 0x44, 0x2e, 0x76, 0x2c, 0x98, 0x1b,
-	0x1f, 0xde, 0xb3, 0x6a, 0xa1, 0x96, 0xc4, 0xd2, 0x72, 0xe8, 0xf3, 0x4b, 0x6d, 0x59, 0x9b, 0xb2,
-	0x7c, 0xe1, 0xf3, 0xcb, 0xa2, 0xe5, 0x50, 0x4b, 0x62, 0xf2, 0xfb, 0x50, 0x73, 0x7c, 0x27, 0x1a,
-	0xe3, 0x58, 0x01, 0x0d, 0xd7, 0x52, 0xc3, 0x3d, 0xa9, 0x29, 0x0c, 0xb5, 0xea, 0x68, 0xd1, 0x7e,
-	0x05, 0xca, 0x9e, 0x23, 0x1c, 0xf3, 0x5f, 0x00, 0x96, 0xa7, 0x70, 0x72, 0x9e, 0x7d, 0x1e, 0xcf,
-	0x8d, 0xa9, 0x57, 0x3c, 0x2e, 0xfa, 0xee, 0xa3, 0x80, 0x74, 0xa0, 0xe5, 0x5d, 0xb1, 0x60, 0x64,
-	0x8f, 0x9c, 0x38, 0xcc, 0x45, 0xd6, 0x56, 0x6a, 0xd9, 0x91, 0xea, 0x97, 0x4e, 0x1c, 0x16, 0xec,
-	0x1b, 0x5e, 0x4e, 0x2c, 0x63, 0x4c, 0x2e, 0x70, 0xe6, 0xd1, 0x74, 0x8c, 0xf5, 0x83, 0xc9, 0xac,
-	0x53, 0x75, 0x9e, 0x49, 0xc9, 0x5b, 0x78, 0x20, 0x29, 0x62, 0xe1, 0x44, 0x62, 0x12, 0xda, 0x43,
-	0x87, 0xf9, 0xb9, 0x58, 0x7b, 0x9a, 0x67, 0x3a, 0x51, 0x98, 0x17, 0x0e, 0xf3, 0x27, 0x11, 0x2d,
-	0x50, 0xde, 0xe7, 0x05, 0xb5, 0x24, 0xfe, 0x39, 0x3c, 0x44, 0x62, 0x36, 0x0a, 0x1c, 0xdf, 0xf6,
-	0xe8, 0x28, 0x72, 0x3c, 0x9a, 0x8b, 0xc5, 0xdf, 0x2a, 0x50, 0x23, 0xaa, 0xa3, 0x40, 0x05, 0xe6,
-	0x15, 0x3e, 0xab, 0x25, 0x7f, 0x09, 0x8f, 0x70, 0x63, 0x44, 0x6c, 0x28, 0x6c, 0x3e, 0xb4, 0x2f,
-	0x59, 0xe0, 0xf1, 0xcb, 0x5c, 0xd0, 0x16, 0xc8, 0x3b, 0x12, 0xd6, 0x1f, 0xbe, 0x45, 0xd0, 0x0c,
-	0xf9, 0xb4, 0x96, 0x0c, 0x40, 0x7a, 0x63, 0xfb, 0x3c, 0x8e, 0xed, 0x74, 0x2f, 0xa8, 0xb0, 0xfe,
-	0x38, 0x4f, 0xfb, 0x8a, 0xc7, 0x71, 0x7f, 0x28, 0x37, 0xc5, 0xc1, 0x99, 0x13, 0x04, 0xd4, 0x2f,
-	0x50, 0xb7, 0xb8, 0x46, 0xe8, 0x2d, 0x92, 0xcc, 0x33, 0xba, 0x12, 0x67, 0xf3, 0x5c, 0x9d, 0x33,
-	0xcf, 0x0a, 0x73, 0xed, 0x3c, 0x67, 0x6a, 0x49, 0xdc, 0x57, 0x49, 0x42, 0xb0, 0x4b, 0x35, 0x52,
-	0xb5, 0x1b, 0x7e, 0x27, 0x4f, 0x38, 0x88, 0x9c, 0x20, 0x1e, 0xb3, 0x38, 0x66, 0x3c, 0xe8, 0x05,
-	0x82, 0x46, 0x43, 0x1a, 0xd1, 0xc0, 0xa5, 0x6f, 0x9d, 0x28, 0x60, 0xc1, 0x48, 0x67, 0x8d, 0x01,
-	0xbb, 0xc4, 0x91, 0xfe, 0x42, 0x4d, 0xae, 0xe3, 0x0a, 0x76, 0x81, 0xfd, 0x66, 0x83, 0x85, 0xd9,
-	0x59, 0xd8, 0x4b, 0x61, 0xf3, 0xc6, 0x2b, 0x7d, 0x2e, 0x22, 0x54, 0x0f, 0x6b, 0xb2, 0x87, 0x30,
-	0xe2, 0x2e, 0x8d, 0x63, 0xb9, 0x0b, 0x68, 0x14, 0x71, 0x95, 0x25, 0xeb, 0xd8, 0xc5, 0x6f, 0xe7,
-	0xbb, 0x38, 0x4e, 0x71, 0x5d, 0x09, 0x2b, 0x74, 0xb0, 0xca, 0xe7, 0xe9, 0x09, 0x85, 0xf5, 0x6c,
-	0x0d, 0x87, 0x76, 0x7c, 0x15, 0xb8, 0x99, 0x17, 0x0d, 0xec, 0xe2, 0x93, 0xd9, 0xb5, 0xfc, 0x8a,
-	0x5e, 0x9d, 0x5c, 0x05, 0xee, 0x75, 0x8e, 0x28, 0x50, 0x82, 0x90, 0xdd, 0xbc, 0x81, 0x55, 0x4c,
-	0xb0, 0x62, 0x62, 0x87, 0x3c, 0x50, 0xe9, 0x08, 0xbb, 0x68, 0x62, 0x17, 0x1f, 0x15, 0xd2, 0xad,
-	0x98, 0x1c, 0xf3, 0x00, 0xb3, 0xd0, 0xcc, 0x92, 0x16, 0x75, 0xc4, 0x87, 0x2d, 0x0c, 0x6f, 0x3a,
-	0xb5, 0x06, 0x93, 0x48, 0x6d, 0xa0, 0x16, 0xb2, 0xff, 0xa8, 0x10, 0xe3, 0x39, 0xec, 0xbc, 0xf1,
-	0xcb, 0xe9, 0x98, 0x8f, 0x21, 0x6f, 0x95, 0x13, 0x11, 0x1d, 0x73, 0x41, 0x6d, 0x8f, 0x0e, 0xa9,
-	0xab, 0x52, 0xf9, 0x32, 0x76, 0x63, 0xe6, 0xbb, 0xb1, 0x10, 0xd4, 0x41, 0x4c, 0x81, 0x9f, 0xf0,
-	0x19, 0x65, 0x9a, 0x32, 0x77, 0xa0, 0x59, 0x38, 0x5a, 0xc9, 0x0f, 0x00, 0xf0, 0x54, 0x94, 0xf3,
-	0x45, 0x31, 0x65, 0xd6, 0xac, 0x9a, 0x94, 0xc8, 0x19, 0xa0, 0xe6, 0x21, 0xb4, 0x8a, 0xc7, 0x2a,
-	0x79, 0x04, 0x86, 0x3a, 0x81, 0x55, 0x82, 0x35, 0xac, 0x0a, 0x9e, 0xb2, 0xde, 0x14, 0xd3, 0xc2,
-	0x34, 0xd3, 0x19, 0xdc, 0x9f, 0x39, 0x23, 0xaf, 0x27, 0xfb, 0x02, 0x9a, 0x31, 0x8d, 0x98, 0xe3,
-	0xdb, 0xc1, 0x64, 0x7c, 0x4a, 0x23, 0x9d, 0x92, 0x57, 0xd3, 0x09, 0x38, 0x41, 0xed, 0x6b, 0x54,
-	0x5a, 0x8d, 0x38, 0xd7, 0x32, 0xbf, 0x2b, 0x41, 0xb3, 0x70, 0xa6, 0x5e, 0xdf, 0xcd, 0x2a, 0x54,
-	0x30, 0x68, 0x54, 0xca, 0x37, 0xac, 0x25, 0x19, 0x00, 0xd3, 0xae, 0x2c, 0x4e, 0xb9, 0x42, 0x9e,
-	0x40, 0xdd, 0xf1, 0xc6, 0x2c, 0xd0, 0xfa, 0x25, 0xd4, 0x03, 0x8a, 0x14, 0x60, 0x66, 0xf4, 0xe5,
-	0x0f, 0x1f, 0xfd, 0x2f, 0x80, 0xcc, 0x56, 0x23, 0x84, 0x40, 0x59, 0x5c, 0x85, 0xc9, 0x02, 0xe1,
-	0xff, 0x79, 0xaf, 0x16, 0x6e, 0x58, 0x89, 0xe9, 0xe1, 0x9b, 0x16, 0xb4, 0x8a, 0xe5, 0xc3, 0xad,
-	0xe7, 0xa7, 0x0d, 0x8b, 0xe1, 0xb9, 0x40, 0xe6, 0x86, 0x25, 0xff, 0x35, 0xff, 0xb5, 0x04, 0xed,
-	0xe9, 0xf2, 0x82, 0x6c, 0x42, 0x0d, 0x69, 0x71, 0xe4, 0x6a, 0x96, 0xb0, 0x7a, 0x1b, 0x4c, 0x8d,
-	0x7e, 0x26, 0x8e, 0x46, 0x74, 0x8c, 0xd5, 0x48, 0xda, 0x6f, 0x4d, 0x4b, 0x7a, 0x9e, 0xb4, 0xc3,
-	0x7a, 0x83, 0xa9, 0x13, 0xd6, 0xb0, 0x2a, 0xb2, 0xa9, 0x14, 0x68, 0x14, 0x70, 0x3c, 0x78, 0x0c,
-	0xab, 0x22, 0x9b, 0xaf, 0x39, 0x79, 0x08, 0x15, 0x97, 0xf3, 0x73, 0x46, 0xf1, 0xe4, 0xa8, 0x58,
-	0xba, 0x95, 0x78, 0x51, 0xce, 0xbc, 0x78, 0x0a, 0x35, 0x95, 0x93, 0x1d, 0xf7, 0xfa, 0x01, 0x9a,
-	0x3f, 0x83, 0xda, 0x21, 0x75, 0x22, 0x71, 0x4a, 0x1d, 0x41, 0x76, 0x61, 0xe5, 0x2c, 0x69, 0xa8,
-	0x13, 0x45, 0x4c, 0x22, 0xaa, 0x2d, 0x48, 0xaa, 0x3a, 0x49, 0x34, 0xe6, 0x5f, 0x97, 0x60, 0xb1,
-	0x1f, 0x4c, 0x6e, 0x3d, 0xe7, 0x33, 0x31, 0xb5, 0xf8, 0xc1, 0x31, 0x85, 0x9e, 0x32, 0x15, 0x85,
-	0x86, 0x25, 0xff, 0x35, 0xbf, 0x02, 0x43, 0xc6, 0xc0, 0x51, 0x3c, 0xba, 0x83, 0xc5, 0xff, 0x55,
-	0x09, 0x6a, 0xf2, 0x6c, 0xc0, 0xf5, 0xbf, 0x35, 0x5f, 0x6e, 0xdd, 0xca, 0x85, 0x75, 0x2b, 0x06,
-	0xc2, 0xd2, 0x74, 0x20, 0xcc, 0x8e, 0xe3, 0xa7, 0xd0, 0x78, 0x13, 0xfa, 0x2c, 0x38, 0x7f, 0xdf,
-	0x48, 0xb4, 0xe9, 0x42, 0x66, 0xfa, 0x77, 0x35, 0x80, 0x0e, 0xbd, 0x60, 0x2e, 0xed, 0x05, 0x43,
-	0x0c, 0x99, 0x0b, 0x1a, 0x78, 0x3c, 0xd2, 0x1b, 0x4e, 0xb7, 0xc8, 0x03, 0x58, 0x1a, 0x73, 0x8f,
-	0xfa, 0x3a, 0xbd, 0xa9, 0x06, 0xf9, 0x11, 0xb4, 0xcf, 0x9c, 0xc8, 0xbb, 0x74, 0x22, 0x6a, 0x5f,
-	0xd0, 0x48, 0x1e, 0xed, 0x7a, 0xd7, 0x2d, 0x27, 0xf2, 0xaf, 0x95, 0x58, 0x42, 0x87, 0x2c, 0x1a,
-	0x17, 0xa0, 0x65, 0x05, 0x4d, 0xe4, 0x09, 0x74, 0x13, 0x6a, 0x1e, 0x8e, 0x48, 0x8e, 0xbf, 0xad,
-	0x76, 0x8f, 0x12, 0xf4, 0x3c, 0xf2, 0x29, 0x3c, 0xd0, 0xca, 0x62, 0x50, 0xdc, 0x47, 0x1c, 0x51,
-	0xba, 0x7c, 0x44, 0x48, 0x3a, 0x79, 0x2e, 0xca, 0xc9, 0x8b, 0xf1, 0xd8, 0x35, 0xac, 0x6a, 0xc8,
-	0x03, 0x59, 0xda, 0xc7, 0xe4, 0x31, 0x80, 0xfc, 0x5c, 0x0b, 0xb8, 0xcf, 0x47, 0x57, 0x49, 0x42,
-	0xcb, 0x24, 0x64, 0x5b, 0x15, 0x36, 0xcc, 0x53, 0xc5, 0xa9, 0xde, 0x60, 0x80, 0x0b, 0x88, 0xb5,
-	0x26, 0xd9, 0x02, 0xd0, 0x08, 0xaa, 0x4b, 0x34, 0xc3, 0xaa, 0xa2, 0xbe, 0x1b, 0x78, 0xe4, 0x29,
-	0xb4, 0x1c, 0xdf, 0xe7, 0x6e, 0xc6, 0x50, 0x45, 0x44, 0x03, 0xa5, 0x09, 0xc7, 0x36, 0x34, 0x52,
-	0x14, 0xd5, 0xe5, 0x93, 0x61, 0x81, 0xc6, 0x48, 0x9e, 0x67, 0xd0, 0xce, 0x42, 0x42, 0x33, 0x01,
-	0xa2, 0x5a, 0x69, 0x60, 0x28, 0xae, 0xa7, 0xd0, 0xca, 0x21, 0xa9, 0xae, 0x66, 0x0c, 0xab, 0x91,
-	0xe2, 0x24, 0x9f, 0x09, 0x4d, 0x9d, 0x4c, 0x34, 0x59, 0x13, 0x41, 0x75, 0x95, 0x52, 0x14, 0xd3,
-	0x63, 0xa8, 0x27, 0x18, 0xaa, 0x0f, 0x7c, 0x43, 0x7d, 0xc6, 0x28, 0x8e, 0x2f, 0xa1, 0x12, 0x39,
-	0xc1, 0x88, 0xc6, 0x6b, 0xcb, 0xdb, 0x8b, 0xcf, 0xea, 0xcf, 0x9f, 0x65, 0x9f, 0x0d, 0x69, 0x40,
-	0xe9, 0x7f, 0x2d, 0x1a, 0xf3, 0x49, 0xe4, 0x52, 0x0b, 0xf1, 0x96, 0xb6, 0xdb, 0xf8, 0xfb, 0x32,
-	0x3c, 0x98, 0x07, 0x20, 0xeb, 0xc9, 0xd7, 0xae, 0x17, 0xaf, 0x95, 0xb6, 0x17, 0x9f, 0x19, 0xfa,
-	0x93, 0xd6, 0x9b, 0x5e, 0xb1, 0x85, 0x99, 0x15, 0x3b, 0x80, 0xa5, 0x90, 0x73, 0x3f, 0x5e, 0x5b,
-	0xc4, 0x41, 0xfd, 0xf8, 0x43, 0x07, 0xb5, 0x73, 0xcc, 0xb9, 0x6f, 0x29, 0xdb, 0x8d, 0xff, 0x5e,
-	0x80, 0xb2, 0x6c, 0x93, 0x3f, 0xcd, 0x1d, 0x3f, 0xad, 0xe7, 0xbf, 0x77, 0x2b, 0x32, 0xfc, 0x23,
-	0x53, 0xbe, 0x3e, 0xb6, 0x4e, 0xc0, 0x88, 0xcf, 0x9c, 0x88, 0x05, 0x23, 0x1c, 0x76, 0xeb, 0xf9,
-	0x4f, 0x6f, 0x47, 0x77, 0xa2, 0x8c, 0x91, 0x31, 0x61, 0x92, 0x1b, 0x53, 0x2d, 0xa0, 0x3a, 0x13,
-	0x54, 0x43, 0xee, 0x73, 0xaa, 0xbf, 0x9f, 0x0c, 0x4b, 0xfe, 0x6b, 0xee, 0x41, 0x35, 0x19, 0x0e,
-	0x01, 0xa8, 0xf4, 0x5f, 0xbf, 0xb1, 0x7b, 0x9d, 0xf6, 0x3d, 0xd2, 0x80, 0xea, 0xde, 0xab, 0x57,
-	0xfd, 0x03, 0xd9, 0x2a, 0x91, 0x16, 0xc0, 0xcb, 0xee, 0xd1, 0x71, 0xdf, 0x1a, 0xc8, 0xf6, 0x02,
-	0xa9, 0x83, 0xf1, 0xe2, 0x55, 0xff, 0xad, 0x6c, 0x2c, 0x9a, 0x67, 0x50, 0xcf, 0x0d, 0x81, 0x3c,
-	0x04, 0xd2, 0xe9, 0x76, 0x7a, 0x07, 0x7b, 0x83, 0x6e, 0xc7, 0x3e, 0xee, 0x5a, 0x76, 0xef, 0xf5,
-	0xe0, 0x45, 0xfb, 0x1e, 0x79, 0x02, 0x9b, 0x27, 0x87, 0x7b, 0x56, 0xb7, 0x63, 0xef, 0xff, 0x85,
-	0xbd, 0xf7, 0xea, 0x15, 0xca, 0xf1, 0x9f, 0x41, 0xf7, 0xe0, 0xb0, 0x5d, 0x22, 0xdb, 0xb0, 0x35,
-	0x07, 0x70, 0xb2, 0x77, 0xd4, 0x55, 0x88, 0x05, 0xf3, 0x6f, 0x16, 0x01, 0x0e, 0x7c, 0x27, 0x8e,
-	0xd9, 0x90, 0xd1, 0x08, 0xf3, 0xa7, 0x2d, 0xc2, 0x34, 0x9b, 0x2d, 0xf1, 0x41, 0xc8, 0x3c, 0xb2,
-	0x02, 0x4b, 0xdc, 0xbe, 0x48, 0xb3, 0x6a, 0x99, 0x7f, 0xcd, 0x30, 0xd7, 0x32, 0x85, 0xd5, 0x13,
-	0xc2, 0x12, 0x2c, 0x43, 0xac, 0x9a, 0x92, 0x32, 0x93, 0xd8, 0x47, 0x60, 0x70, 0x3b, 0x3c, 0x65,
-	0x22, 0xd6, 0x49, 0xb6, 0xc2, 0x8f, 0x65, 0x0b, 0xf3, 0xa7, 0x56, 0xe8, 0x13, 0x95, 0x29, 0xc5,
-	0x3a, 0x54, 0xa9, 0x38, 0x53, 0xe7, 0xba, 0xda, 0xea, 0x06, 0x15, 0x67, 0xc9, 0xb1, 0xee, 0xc5,
-	0xc2, 0x1e, 0x3b, 0x2e, 0x6e, 0xf1, 0x86, 0x55, 0xf1, 0x62, 0x71, 0xe4, 0xb8, 0x52, 0x11, 0x47,
-	0x2e, 0x2a, 0x6a, 0x4a, 0x11, 0x47, 0xae, 0x54, 0xc8, 0x20, 0x0f, 0xd5, 0xa5, 0x91, 0xde, 0xcb,
-	0x06, 0x0b, 0x8f, 0xf1, 0xe2, 0x69, 0x15, 0xa4, 0xb5, 0xcd, 0x42, 0xbd, 0x79, 0x97, 0xbc, 0x58,
-	0xf4, 0x42, 0x29, 0x96, 0x54, 0x2c, 0xd4, 0x79, 0x6c, 0x29, 0x8e, 0xdc, 0x5e, 0x28, 0x89, 0xa4,
-	0x58, 0xee, 0x6e, 0xbd, 0x8f, 0x65, 0x8f, 0x32, 0xc1, 0x49, 0x95, 0x24, 0x42, 0x95, 0xda, 0xc0,
-	0x72, 0x94, 0xa8, 0xda, 0x86, 0x46, 0x78, 0x2e, 0x6c, 0xe1, 0x8c, 0x94, 0x3f, 0xcb, 0x6a, 0x2b,
-	0x85, 0xe7, 0x62, 0xe0, 0xe0, 0x0a, 0x9b, 0xbf, 0x5a, 0x84, 0x9a, 0xfc, 0x70, 0xe2, 0xc1, 0xc1,
-	0x18, 0x53, 0x86, 0xe3, 0x79, 0x36, 0x9f, 0x08, 0x1a, 0x49, 0x2b, 0x5c, 0x8c, 0xaa, 0x55, 0x77,
-	0x3c, 0xaf, 0x2f, 0x65, 0x03, 0x67, 0x24, 0xd3, 0x94, 0x2c, 0xe1, 0x2f, 0x68, 0x0e, 0xb6, 0x80,
-	0xb0, 0x96, 0x92, 0xa7, 0xc8, 0x6d, 0x68, 0x88, 0xc8, 0x09, 0x6d, 0xc1, 0xed, 0x33, 0x1e, 0xab,
-	0xf0, 0xad, 0x5a, 0x20, 0x65, 0x03, 0x7e, 0xc8, 0x63, 0x41, 0x7e, 0x17, 0x48, 0x44, 0xc7, 0x4e,
-	0x74, 0xae, 0xb9, 0xd4, 0x7a, 0x94, 0x11, 0xd7, 0x56, 0x1a, 0x64, 0x53, 0x2b, 0x93, 0xa1, 0x59,
-	0x10, 0xa4, 0xe8, 0xa5, 0x3c, 0xba, 0x27, 0x15, 0x0a, 0xad, 0x7d, 0x51, 0x50, 0x39, 0xc8, 0x4a,
-	0xea, 0x0b, 0xa2, 0x8a, 0xbe, 0x64, 0x30, 0x23, 0xef, 0x4b, 0x8a, 0xdc, 0x81, 0x15, 0x21, 0xbf,
-	0x6e, 0x7d, 0x47, 0xe4, 0xc1, 0x55, 0x04, 0xdf, 0x4f, 0x55, 0xf3, 0xf1, 0xd9, 0x44, 0xd5, 0xa6,
-	0xf0, 0xc9, 0x5c, 0x99, 0xbf, 0x29, 0x41, 0x45, 0xad, 0x03, 0x79, 0x0a, 0x8b, 0xee, 0x38, 0xb9,
-	0xe1, 0x21, 0xd9, 0xa5, 0x51, 0xb2, 0x4a, 0x96, 0x54, 0xcf, 0xdf, 0x19, 0xb9, 0x68, 0x5f, 0x2c,
-	0x44, 0x7b, 0xb6, 0xbd, 0xca, 0x53, 0xdb, 0x4b, 0x6d, 0x99, 0xa5, 0xe2, 0x96, 0x99, 0xbf, 0x33,
-	0xb2, 0x7d, 0x67, 0xe4, 0xf6, 0x9d, 0xf9, 0x9b, 0x45, 0x28, 0xbf, 0xf0, 0xf9, 0x25, 0x1e, 0x84,
-	0xae, 0xfc, 0x42, 0xb6, 0xf3, 0x95, 0xc9, 0xb2, 0xd5, 0x50, 0xd2, 0xde, 0xbc, 0x4a, 0x69, 0x39,
-	0xa9, 0x94, 0x56, 0xa1, 0x32, 0x09, 0x98, 0x14, 0xd7, 0x95, 0x78, 0x12, 0xb0, 0x9b, 0x2a, 0xe2,
-	0x4d, 0xc0, 0x63, 0x4a, 0xc5, 0xb5, 0xaa, 0x32, 0xaa, 0x52, 0x80, 0x1b, 0x75, 0x1d, 0xaa, 0xc9,
-	0x61, 0x8b, 0xdb, 0x6e, 0xd9, 0x32, 0xf4, 0x41, 0x4b, 0x7e, 0x08, 0xcb, 0x01, 0x15, 0x97, 0x1c,
-	0xa3, 0x48, 0x8d, 0x72, 0x09, 0x11, 0x4d, 0x2d, 0xee, 0xcd, 0xab, 0xd4, 0x2b, 0x08, 0xc9, 0x15,
-	0x68, 0x9f, 0x03, 0xb8, 0x69, 0xf6, 0xd2, 0xb7, 0x36, 0x2b, 0xe9, 0x5a, 0x65, 0x89, 0xcd, 0xca,
-	0xc1, 0xc8, 0xc7, 0x50, 0x71, 0x70, 0x15, 0xf5, 0x6d, 0xcc, 0xf2, 0xd4, 0xe2, 0x5a, 0x5a, 0x4d,
-	0x36, 0xa0, 0x1a, 0x46, 0x8c, 0x47, 0x4c, 0x5c, 0x61, 0xc8, 0x2c, 0x5b, 0x69, 0x3b, 0x57, 0xf1,
-	0x37, 0x0a, 0x15, 0x7f, 0xae, 0xd4, 0x6c, 0x16, 0x4a, 0xcd, 0x75, 0xa8, 0x8e, 0x22, 0x3e, 0x09,
-	0xa5, 0x1f, 0x3a, 0x3f, 0x60, 0xbb, 0xe7, 0x99, 0x03, 0x68, 0x4c, 0xd7, 0x51, 0xaa, 0x18, 0x4c,
-	0x16, 0xaf, 0x61, 0x55, 0x95, 0xa0, 0xe7, 0x91, 0x8f, 0x61, 0x59, 0x2b, 0xe3, 0x90, 0xba, 0x6c,
-	0xc8, 0x5c, 0x5d, 0x64, 0xb6, 0x94, 0xf8, 0x44, 0x4b, 0xcd, 0x7f, 0x2f, 0x43, 0xab, 0x78, 0xab,
-	0x7a, 0x7d, 0xb5, 0xba, 0x0e, 0xd5, 0xe8, 0x9d, 0x7d, 0x7a, 0x25, 0x68, 0x8c, 0x6c, 0x15, 0xcb,
-	0x88, 0xde, 0xed, 0xcb, 0xa6, 0x5c, 0x81, 0xe8, 0x9d, 0x1d, 0x62, 0xb9, 0xab, 0xe2, 0xb9, 0x62,
-	0xd5, 0xa2, 0x77, 0xaa, 0xfe, 0x8d, 0x71, 0xef, 0xbe, 0xb3, 0x27, 0xae, 0x23, 0x73, 0x9f, 0x06,
-	0x95, 0x11, 0xd4, 0x8a, 0xde, 0xbd, 0x91, 0xe2, 0x22, 0x72, 0x5c, 0x40, 0x2e, 0x25, 0xc8, 0xa3,
-	0x59, 0xe4, 0x69, 0x01, 0x59, 0x49, 0x90, 0xfb, 0xb3, 0x48, 0x75, 0x9d, 0x94, 0x20, 0x8d, 0x04,
-	0x89, 0xd7, 0x43, 0x09, 0x72, 0x1d, 0xaa, 0x22, 0xf1, 0xb0, 0xaa, 0x3c, 0x14, 0x99, 0x87, 0x22,
-	0xf3, 0xb0, 0xa6, 0x3c, 0x14, 0x79, 0x0f, 0xc5, 0xb4, 0x87, 0xa0, 0xfa, 0x10, 0x33, 0x1e, 0x8a,
-	0x69, 0x0f, 0xeb, 0x09, 0xf2, 0x68, 0x16, 0x59, 0xf4, 0xb0, 0x91, 0x20, 0xf7, 0x67, 0x91, 0x45,
-	0x0f, 0x9b, 0x09, 0xb2, 0xe0, 0xa1, 0x09, 0xcd, 0xe8, 0x9d, 0xed, 0x46, 0xae, 0x42, 0xc7, 0x18,
-	0x65, 0x15, 0xab, 0x1e, 0xbd, 0x3b, 0x88, 0x5c, 0x44, 0xa2, 0xab, 0xa7, 0x2c, 0x4c, 0x00, 0xcb,
-	0xca, 0xd5, 0x53, 0x16, 0x6a, 0xf5, 0x16, 0xd4, 0x04, 0x1b, 0xd3, 0x58, 0x38, 0xe3, 0x10, 0xbf,
-	0x07, 0x0c, 0x2b, 0x13, 0x98, 0xdf, 0x95, 0xa0, 0x55, 0xbc, 0x6c, 0xcf, 0xe7, 0x85, 0x52, 0x21,
-	0x2f, 0x7c, 0xff, 0x80, 0xfa, 0xfe, 0x0b, 0x75, 0xf3, 0xe8, 0xbf, 0x84, 0x66, 0xe1, 0x76, 0xfe,
-	0xfa, 0xcd, 0xf0, 0x10, 0x2a, 0xb1, 0x70, 0xc4, 0x24, 0xd6, 0x35, 0xaf, 0x6e, 0x99, 0xdf, 0xc0,
-	0xca, 0x9c, 0x5b, 0xfa, 0x5b, 0x7f, 0x8c, 0x66, 0xf4, 0x8b, 0x05, 0xfa, 0x7f, 0x5e, 0x00, 0x32,
-	0x7b, 0x81, 0xff, 0x7d, 0x2e, 0x96, 0x7c, 0x1e, 0xdb, 0x85, 0x2e, 0x6a, 0x3e, 0x8f, 0x4f, 0x50,
-	0xa0, 0xd4, 0xa7, 0x89, 0xba, 0x9c, 0xa8, 0x4f, 0xb5, 0xfa, 0x19, 0xb4, 0x7d, 0x1e, 0xba, 0xf6,
-	0x98, 0xc5, 0x29, 0x87, 0xfa, 0x56, 0x6b, 0x49, 0xf9, 0x11, 0x8b, 0x13, 0xa2, 0xcf, 0x60, 0x55,
-	0x23, 0x75, 0xc0, 0x25, 0xf0, 0x8a, 0xfa, 0x3e, 0x54, 0x70, 0x15, 0x78, 0xda, 0xe4, 0x09, 0xd4,
-	0x7d, 0x3e, 0x64, 0x09, 0xd0, 0x50, 0x65, 0x90, 0x14, 0x69, 0xc0, 0x47, 0xd0, 0xf0, 0xb9, 0x33,
-	0x4e, 0x11, 0x55, 0x44, 0xd4, 0x51, 0xa6, 0x20, 0x26, 0x85, 0xcd, 0x1b, 0xde, 0x26, 0xee, 0x6c,
-	0x31, 0xfe, 0xa1, 0x04, 0x1b, 0xd7, 0x3f, 0x54, 0xdc, 0x55, 0x37, 0xe4, 0x73, 0x78, 0xc8, 0x02,
-	0xf9, 0x91, 0x4e, 0xed, 0x53, 0x26, 0xf4, 0x3c, 0x46, 0x8e, 0xa0, 0xba, 0x40, 0x58, 0xd1, 0xda,
-	0x7d, 0x26, 0x70, 0x22, 0x2d, 0x47, 0x50, 0xf3, 0xd7, 0x6a, 0x6c, 0xd7, 0xbc, 0x73, 0xdc, 0xd9,
-	0xd8, 0x1e, 0xc0, 0x12, 0xbe, 0xb8, 0x24, 0xb5, 0x0a, 0x36, 0x24, 0x7b, 0x40, 0x2f, 0x6d, 0xfa,
-	0x6d, 0x52, 0xad, 0x54, 0x02, 0x7a, 0xd9, 0xfd, 0xd6, 0x33, 0xcf, 0xe0, 0xf1, 0xcd, 0xaf, 0x24,
-	0x77, 0xb6, 0x36, 0xff, 0x58, 0x52, 0x31, 0x70, 0xcd, 0xbb, 0xc9, 0xff, 0xef, 0xe2, 0xfc, 0xb2,
-	0x04, 0xe6, 0xfb, 0xdf, 0x60, 0xfe, 0x6f, 0x17, 0xc9, 0xfc, 0x16, 0xd7, 0xe2, 0x86, 0xb7, 0x9a,
-	0x5b, 0xf7, 0xff, 0x04, 0xea, 0xf8, 0xa0, 0x12, 0x51, 0x27, 0xd6, 0x57, 0x4f, 0x86, 0x05, 0x52,
-	0x64, 0xa1, 0xc4, 0x3c, 0x87, 0x8f, 0xde, 0xfb, 0xb0, 0x72, 0x67, 0x11, 0xc0, 0x60, 0xed, 0xba,
-	0x27, 0x96, 0xef, 0x93, 0x2f, 0x23, 0x8f, 0x25, 0x47, 0xa2, 0x72, 0xac, 0x16, 0x79, 0x4c, 0x1d,
-	0x89, 0xe6, 0x6b, 0xd8, 0xba, 0xe9, 0x4d, 0xea, 0xb6, 0xdd, 0x99, 0x31, 0x6c, 0xbf, 0xef, 0xfd,
-	0xe6, 0xee, 0x17, 0xe7, 0xaf, 0x60, 0xfd, 0xda, 0xd7, 0x9c, 0xbb, 0x9e, 0xb0, 0xff, 0x2a, 0x41,
-	0xfd, 0xa5, 0x2c, 0x6c, 0x8f, 0x28, 0x16, 0xb3, 0x1f, 0x41, 0x83, 0x25, 0x17, 0xde, 0x49, 0x1f,
-	0x4d, 0xfc, 0xe1, 0x83, 0x92, 0xf5, 0x3c, 0xd2, 0x83, 0x56, 0x06, 0xc1, 0x2f, 0x09, 0x75, 0x6b,
-	0x93, 0xbd, 0x45, 0xe5, 0x08, 0x77, 0xd2, 0xeb, 0x73, 0xbc, 0x9e, 0x69, 0xb2, 0x7c, 0x93, 0x3c,
-	0x86, 0xfa, 0x88, 0x8e, 0xed, 0xe4, 0x83, 0x61, 0x11, 0x3b, 0x93, 0x1f, 0x0c, 0xc7, 0xea, 0x83,
-	0x21, 0x5f, 0xd2, 0x97, 0x51, 0x99, 0xb6, 0xcd, 0x3f, 0x82, 0x66, 0x81, 0x9b, 0x18, 0xb0, 0x78,
-	0xdc, 0x7f, 0xdd, 0xbe, 0x47, 0xda, 0xd0, 0xe8, 0x1e, 0xf7, 0x5f, 0xdb, 0x9f, 0xbd, 0xb4, 0x8f,
-	0xf7, 0x06, 0x87, 0xed, 0x12, 0xb9, 0x0f, 0x4d, 0x25, 0xf9, 0x54, 0x8b, 0x16, 0xcc, 0xbf, 0x5d,
-	0x80, 0x25, 0x1c, 0x67, 0xa1, 0xd4, 0x57, 0xee, 0x26, 0xa5, 0x3e, 0xf9, 0x19, 0x18, 0x2e, 0x1f,
-	0x8f, 0x1d, 0xfd, 0x0b, 0x80, 0x19, 0x1f, 0xf3, 0x9e, 0xc6, 0x07, 0x0a, 0x69, 0x25, 0x26, 0x64,
-	0x07, 0x8c, 0xb1, 0x52, 0xe9, 0x3b, 0xb7, 0x07, 0xf3, 0x66, 0xc8, 0x4a, 0x40, 0xb9, 0x2f, 0x9d,
-	0xf2, 0x8d, 0x5f, 0x3a, 0xe6, 0x57, 0xb0, 0x32, 0xa7, 0x63, 0xb2, 0x0c, 0xf5, 0xbd, 0x4e, 0xc7,
-	0x3e, 0xea, 0x1e, 0xed, 0x77, 0xad, 0x93, 0xf6, 0x3d, 0x42, 0xa0, 0x65, 0x75, 0x8f, 0xfa, 0x5f,
-	0x77, 0x53, 0x59, 0x49, 0x82, 0x4e, 0xba, 0x83, 0x54, 0xb0, 0x60, 0x1a, 0xb0, 0xd4, 0x1d, 0x87,
-	0xe2, 0xea, 0xf9, 0x3f, 0xb5, 0xc0, 0xe8, 0xab, 0x0e, 0x49, 0x07, 0xa0, 0xc3, 0x62, 0xe7, 0xd4,
-	0xa7, 0x7d, 0x5f, 0x90, 0x56, 0x3a, 0x10, 0x44, 0x6e, 0x4c, 0xb5, 0xcd, 0x87, 0xbf, 0xfc, 0x8f,
-	0xff, 0xfc, 0xf5, 0x42, 0xdb, 0xac, 0xef, 0x5e, 0x7c, 0xb6, 0xab, 0xed, 0xbe, 0x28, 0x7d, 0x42,
-	0x5e, 0x40, 0xdd, 0xa2, 0x34, 0xf8, 0x50, 0x9a, 0x47, 0x48, 0x73, 0xdf, 0x6c, 0x48, 0x9a, 0xc4,
-	0x50, 0xf2, 0x74, 0xa1, 0xae, 0xb3, 0x23, 0xed, 0x07, 0x13, 0xd2, 0xc8, 0x3f, 0x7a, 0xce, 0xb0,
-	0xac, 0x21, 0x0b, 0x31, 0x9b, 0x92, 0xa5, 0xab, 0x3a, 0x0f, 0x26, 0x92, 0xe6, 0x10, 0x9a, 0xe9,
-	0x4e, 0xfe, 0x00, 0xa2, 0x75, 0x24, 0x5a, 0x31, 0x5b, 0x39, 0xaf, 0x34, 0xd3, 0x01, 0xd4, 0x3a,
-	0xd4, 0xa7, 0xb7, 0x1e, 0x4e, 0x6a, 0x24, 0x49, 0x7a, 0x00, 0xfa, 0xc5, 0xa5, 0x3f, 0x11, 0xa4,
-	0x5d, 0xf8, 0x25, 0xcf, 0x51, 0x3c, 0xba, 0x79, 0x3c, 0x99, 0xa5, 0xa4, 0xea, 0x43, 0x23, 0x7d,
-	0x6e, 0x91, 0x64, 0xa4, 0xf0, 0x42, 0x8f, 0xe2, 0x19, 0xba, 0x4d, 0xa4, 0x5b, 0x35, 0xdb, 0x48,
-	0x97, 0xb3, 0x96, 0x84, 0x7f, 0x0e, 0xcb, 0xf9, 0x87, 0x13, 0xc9, 0x99, 0xbd, 0x2b, 0xe5, 0x35,
-	0x33, 0xb4, 0x8f, 0x91, 0x76, 0xcd, 0x5c, 0x91, 0xb4, 0x53, 0x1c, 0x92, 0xf9, 0x4b, 0x30, 0xe4,
-	0x57, 0xc9, 0x9e, 0xe7, 0x91, 0x66, 0xe1, 0x47, 0x41, 0x37, 0x47, 0x95, 0xb6, 0x51, 0x51, 0x05,
-	0xb2, 0x65, 0xe1, 0x5d, 0xd3, 0xfb, 0x48, 0x0a, 0x93, 0x96, 0x99, 0x49, 0x9e, 0x13, 0x68, 0xa5,
-	0xaf, 0x76, 0x07, 0x67, 0xd4, 0x3d, 0x9f, 0x09, 0xd0, 0x6c, 0x1a, 0x53, 0xa0, 0xf9, 0x03, 0x24,
-	0x7c, 0x64, 0x12, 0x49, 0x58, 0xb4, 0x97, 0xa4, 0x47, 0x50, 0x57, 0x31, 0x77, 0xcc, 0x83, 0xde,
-	0x30, 0xb7, 0x10, 0x69, 0xae, 0x9a, 0x19, 0xe2, 0x06, 0x32, 0x3e, 0x30, 0x97, 0xb3, 0x80, 0x45,
-	0x63, 0xbd, 0xb0, 0x3a, 0xf2, 0x3e, 0x9c, 0xaf, 0xb0, 0xb0, 0x79, 0x6b, 0x49, 0x68, 0x41, 0xf3,
-	0x25, 0x15, 0xb9, 0x87, 0xad, 0x69, 0x9f, 0x57, 0xe6, 0xdc, 0xbd, 0x9b, 0x5b, 0x48, 0xf9, 0xd0,
-	0xbc, 0x2f, 0x29, 0x0b, 0xf6, 0x92, 0xf3, 0x4f, 0xa0, 0x62, 0xd1, 0x53, 0xce, 0xdf, 0xbf, 0xc3,
-	0x57, 0x91, 0x67, 0xd9, 0x04, 0xb5, 0xc3, 0xa5, 0x8d, 0x24, 0x78, 0x03, 0xf7, 0x0f, 0xb8, 0xef,
-	0x53, 0x37, 0x7f, 0xfb, 0xf1, 0x3e, 0xae, 0x6d, 0xe4, 0xda, 0x30, 0x57, 0x25, 0xd7, 0x8c, 0xb9,
-	0xa4, 0x8d, 0xe0, 0xd1, 0x41, 0x44, 0x1d, 0x41, 0x07, 0x91, 0x33, 0x1c, 0x32, 0xf7, 0xc4, 0x3d,
-	0xa3, 0xde, 0xc4, 0x97, 0xa9, 0xf6, 0xc9, 0x4e, 0xe1, 0xc7, 0x88, 0x33, 0x80, 0x99, 0xde, 0x7e,
-	0x88, 0xbd, 0x6d, 0x9b, 0x9b, 0xd8, 0xdb, 0x7c, 0x56, 0xdd, 0xa7, 0x8a, 0xb0, 0xbb, 0xee, 0xf3,
-	0x1a, 0x56, 0xd9, 0xe7, 0x10, 0x56, 0x0a, 0x23, 0xfa, 0xb3, 0x09, 0x9d, 0xd0, 0x98, 0x6c, 0xce,
-	0xed, 0x4f, 0x29, 0x67, 0xfa, 0x32, 0xb1, 0xaf, 0x2d, 0xf3, 0xd1, 0x8c, 0x7f, 0xca, 0x40, 0xf7,
-	0x53, 0x18, 0xc5, 0xff, 0xba, 0x9f, 0x39, 0x6c, 0xb2, 0x9f, 0x3f, 0x84, 0xb6, 0xda, 0x06, 0xb9,
-	0xb2, 0xe7, 0xfa, 0x30, 0xcd, 0x40, 0xe6, 0xbd, 0x4f, 0x4b, 0xe4, 0x1b, 0x58, 0x3d, 0xa6, 0xd1,
-	0x90, 0x47, 0x63, 0x3c, 0x22, 0xfb, 0x21, 0x8d, 0xa6, 0x19, 0x50, 0x31, 0x33, 0xb2, 0xa7, 0x38,
-	0xb2, 0xc7, 0xe6, 0xba, 0x1c, 0xd9, 0x5c, 0x8a, 0x2f, 0x4a, 0x9f, 0xec, 0x7f, 0x03, 0x9b, 0x3c,
-	0x1a, 0xa1, 0xa9, 0xcb, 0x23, 0x6f, 0x47, 0xfd, 0xc2, 0x35, 0xa1, 0xda, 0x6f, 0x7e, 0x8d, 0x6d,
-	0x79, 0x8c, 0xf6, 0x5f, 0x0d, 0x7e, 0xbe, 0x3b, 0x62, 0xe2, 0x6c, 0x72, 0xba, 0xe3, 0xf2, 0xf1,
-	0x6e, 0x62, 0xb2, 0xab, 0x4c, 0x7e, 0xac, 0x7f, 0x14, 0x7b, 0xf1, 0xf9, 0xee, 0x88, 0x27, 0x3f,
-	0xaf, 0x3d, 0x2e, 0x9d, 0x56, 0x50, 0xfe, 0xf9, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0xcc, 0x5a,
-	0x82, 0xc1, 0x80, 0x2b, 0x00, 0x00,
+	// 4347 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x5b, 0xcd, 0x73, 0x24, 0x47,
+	0x56, 0x9f, 0x96, 0x5a, 0xdd, 0xad, 0xd7, 0x9f, 0x4a, 0x8d, 0x66, 0xf4, 0x31, 0x9e, 0x91, 0xcb,
+	0xb3, 0xf6, 0xac, 0xb1, 0x25, 0x7b, 0xec, 0x58, 0xd6, 0x66, 0x01, 0xb7, 0xa4, 0x1e, 0xa9, 0xb1,
+	0xa4, 0x6e, 0xaa, 0x7b, 0x66, 0xc0, 0x1b, 0x8e, 0xda, 0x52, 0x55, 0x76, 0xab, 0x56, 0xd5, 0x95,
+	0xe5, 0xaa, 0x6c, 0x7d, 0x70, 0xdc, 0x60, 0xe1, 0xc2, 0x09, 0x07, 0x44, 0xc0, 0x8d, 0xe0, 0xca,
+	0x85, 0x1b, 0x11, 0x1c, 0x38, 0x70, 0x25, 0xb8, 0xf0, 0x2f, 0x70, 0xe3, 0xce, 0x89, 0x20, 0x88,
+	0x7c, 0x99, 0xf5, 0xd5, 0xdd, 0xd2, 0x8c, 0x8c, 0x08, 0x2e, 0x8a, 0xce, 0xf7, 0x7e, 0xef, 0x97,
+	0xf9, 0x32, 0x5f, 0x66, 0xbe, 0xcc, 0x2c, 0xc1, 0xc6, 0x39, 0x73, 0xf9, 0xa9, 0x69, 0xf8, 0x01,
+	0xe3, 0x2c, 0xdc, 0x66, 0x3e, 0xf5, 0x98, 0xcb, 0xb7, 0xb0, 0x48, 0x8a, 0xaa, 0xb8, 0xfe, 0x68,
+	0xc8, 0xd8, 0xd0, 0xa5, 0xdb, 0xa6, 0xef, 0x6c, 0x9b, 0x9e, 0xc7, 0xb8, 0xc9, 0x1d, 0xe6, 0x85,
+	0x12, 0xb6, 0xbe, 0x99, 0xe5, 0xe0, 0xd4, 0x3a, 0x15, 0xbf, 0x07, 0x8e, 0x4b, 0x15, 0x62, 0x3d,
+	0x8b, 0xb0, 0xd8, 0x68, 0xc4, 0x3c, 0xa5, 0x7b, 0x9c, 0xd5, 0xd1, 0x4b, 0x6e, 0x58, 0xcc, 0x1b,
+	0x38, 0x43, 0xa9, 0xd7, 0xfe, 0x25, 0x0f, 0xd0, 0xf6, 0x6c, 0xc7, 0xc2, 0x3a, 0xc9, 0xa7, 0x50,
+	0x64, 0x2e, 0x37, 0x1c, 0xcf, 0x5e, 0xcd, 0x6d, 0xe6, 0x9e, 0x95, 0x9f, 0x3f, 0xd8, 0x8a, 0x1a,
+	0xdd, 0x71, 0x79, 0x02, 0x3c, 0xb8, 0xa7, 0x17, 0x18, 0x0a, 0xc8, 0xe7, 0x50, 0x72, 0x3c, 0x3e,
+	0x40, 0x9b, 0x39, 0xb4, 0x79, 0x18, 0xdb, 0xb4, 0x3d, 0x3e, 0xc8, 0x18, 0x15, 0x1d, 0x29, 0x21,
+	0x4d, 0xa8, 0xa2, 0x15, 0xf3, 0x69, 0x80, 0xa6, 0xf3, 0x68, 0xba, 0x91, 0x31, 0xed, 0xf8, 0x34,
+	0xc8, 0x98, 0x97, 0x9d, 0x44, 0x4a, 0x7e, 0x07, 0x2a, 0xcc, 0x1b, 0x1b, 0xb6, 0x13, 0x5a, 0xc8,
+	0x90, 0x47, 0x86, 0xf5, 0xa4, 0xc1, 0xde, 0x78, 0xcf, 0x09, 0xad, 0x0c, 0x01, 0xb0, 0x58, 0x88,
+	0xbe, 0x7a, 0x63, 0x34, 0x5d, 0x98, 0xf4, 0xd5, 0x1b, 0x4f, 0xf8, 0x8a, 0x02, 0xe1, 0x2b, 0x1b,
+	0x59, 0x0e, 0xda, 0x14, 0x26, 0x7c, 0xed, 0x8c, 0x2c, 0x27, 0xeb, 0x2b, 0x93, 0x12, 0xf2, 0x39,
+	0x14, 0xfd, 0x33, 0xd9, 0xa9, 0x45, 0x34, 0x5a, 0x8b, 0x8d, 0xba, 0xa6, 0x75, 0x46, 0x27, 0xfa,
+	0xd5, 0x3f, 0xc3, 0x7e, 0xfd, 0x29, 0x80, 0xcf, 0x02, 0x6e, 0x84, 0xdc, 0xe4, 0xe1, 0x6a, 0x69,
+	0xa2, 0xb6, 0x2e, 0x0b, 0x78, 0x4f, 0x04, 0x4a, 0xc8, 0x1d, 0x2b, 0x3c, 0xb8, 0xa7, 0x2f, 0xfa,
+	0x4a, 0x12, 0x0a, 0xcb, 0x81, 0xcb, 0x2e, 0x94, 0xe5, 0xe2, 0x84, 0xe5, 0x0b, 0x97, 0x5d, 0x64,
+	0x2d, 0x07, 0x4a, 0x12, 0x92, 0xdf, 0x84, 0x45, 0xd3, 0x35, 0x83, 0x11, 0xb6, 0x15, 0xd0, 0x70,
+	0x35, 0x36, 0x6c, 0x0a, 0x4d, 0xa6, 0xa9, 0x25, 0x53, 0x89, 0x76, 0x0a, 0x90, 0xb7, 0x4d, 0x6e,
+	0x6a, 0xff, 0x51, 0x85, 0xfa, 0x04, 0x4e, 0xf4, 0xb3, 0xcb, 0xc2, 0x99, 0x31, 0x75, 0xc8, 0xc2,
+	0xac, 0xef, 0x2e, 0x0a, 0xc8, 0x1e, 0xd4, 0xec, 0x2b, 0xc7, 0x1b, 0x1a, 0x43, 0x33, 0xf4, 0x53,
+	0x91, 0xf5, 0x28, 0xb6, 0xdc, 0x13, 0xea, 0x7d, 0x33, 0xf4, 0x33, 0xf6, 0x15, 0x3b, 0x25, 0x16,
+	0x31, 0x26, 0x06, 0x38, 0xf1, 0x68, 0x32, 0xc6, 0x3a, 0xde, 0x78, 0xda, 0xa9, 0x32, 0x4b, 0xa4,
+	0xe4, 0x35, 0xdc, 0x17, 0x14, 0x21, 0x37, 0x03, 0x3e, 0xf6, 0x8d, 0x81, 0xe9, 0xb8, 0xa9, 0x58,
+	0x7b, 0x9a, 0x66, 0xea, 0x49, 0xcc, 0x0b, 0xd3, 0x71, 0xc7, 0x01, 0xcd, 0x50, 0x2e, 0xb1, 0x8c,
+	0x5a, 0x10, 0x7f, 0x03, 0x0f, 0x90, 0xd8, 0x19, 0x7a, 0xa6, 0x6b, 0xd8, 0x74, 0x18, 0x98, 0x36,
+	0x4d, 0xc5, 0xe2, 0x7b, 0x19, 0x6a, 0x44, 0xed, 0x49, 0x50, 0x86, 0x79, 0x99, 0x4d, 0x6b, 0xc9,
+	0xcf, 0xe1, 0x21, 0x4e, 0x8c, 0xc0, 0x19, 0x70, 0x83, 0x0d, 0x8c, 0x0b, 0xc7, 0xb3, 0xd9, 0x45,
+	0x2a, 0x68, 0x33, 0xe4, 0x7b, 0x02, 0xd6, 0x19, 0xbc, 0x46, 0xd0, 0x14, 0xf9, 0xa4, 0x96, 0xf4,
+	0x41, 0x78, 0x63, 0xb8, 0x2c, 0x0c, 0x8d, 0x78, 0x2e, 0xc8, 0xb0, 0xfe, 0x20, 0x4d, 0x7b, 0xc8,
+	0xc2, 0xb0, 0x33, 0x10, 0x93, 0x62, 0xf7, 0xd4, 0xf4, 0x3c, 0xea, 0x66, 0xa8, 0x6b, 0x4c, 0x21,
+	0xd4, 0x14, 0x89, 0xfa, 0x19, 0x5d, 0x09, 0x93, 0x7e, 0x2e, 0xcd, 0xe8, 0x67, 0x89, 0xb9, 0xb6,
+	0x9f, 0x13, 0xb5, 0x20, 0xee, 0xc8, 0x45, 0x82, 0x3b, 0x17, 0xb2, 0xa5, 0x72, 0x36, 0xfc, 0x46,
+	0x9a, 0xb0, 0x1f, 0x98, 0x5e, 0x38, 0x72, 0xc2, 0xd0, 0x61, 0x5e, 0xdb, 0xe3, 0x34, 0x18, 0xd0,
+	0x80, 0x7a, 0x16, 0x7d, 0x6d, 0x06, 0x9e, 0xe3, 0x0d, 0xd5, 0xaa, 0xd1, 0x77, 0x2e, 0xb0, 0xa5,
+	0xbf, 0x90, 0x9d, 0x6b, 0x5a, 0xdc, 0x39, 0xc7, 0x7a, 0x93, 0xc6, 0xc2, 0x74, 0x2f, 0x34, 0x63,
+	0xd8, 0xac, 0xf6, 0x0a, 0x9f, 0xb3, 0x08, 0x59, 0xc3, 0xaa, 0xa8, 0xc1, 0x0f, 0x98, 0x45, 0xc3,
+	0x50, 0xcc, 0x02, 0x1a, 0x04, 0x4c, 0xae, 0x92, 0x65, 0xac, 0xe2, 0x47, 0xe9, 0x2a, 0xba, 0x31,
+	0xae, 0x25, 0x60, 0x99, 0x0a, 0x56, 0xd8, 0x2c, 0x3d, 0xa1, 0xb0, 0x96, 0x8c, 0xe1, 0xc0, 0x08,
+	0xaf, 0x3c, 0x2b, 0xf1, 0xa2, 0x82, 0x55, 0x7c, 0x38, 0x3d, 0x96, 0x5f, 0xd3, 0xab, 0xde, 0x95,
+	0x67, 0x5d, 0xe7, 0x88, 0x04, 0x45, 0x08, 0x51, 0xcd, 0x4b, 0x58, 0xc1, 0x05, 0x96, 0x8f, 0x0d,
+	0x9f, 0x79, 0x72, 0x39, 0xc2, 0x2a, 0xaa, 0x58, 0xc5, 0xbb, 0x99, 0xe5, 0x96, 0x8f, 0xbb, 0xcc,
+	0xc3, 0x55, 0x68, 0x6a, 0x48, 0xb3, 0x3a, 0xe2, 0xc2, 0x23, 0x0c, 0x6f, 0x3a, 0x31, 0x06, 0xe3,
+	0x40, 0x4e, 0xa0, 0x1a, 0xb2, 0xff, 0x38, 0x13, 0xe3, 0x29, 0xec, 0xac, 0xf6, 0x8b, 0xee, 0x98,
+	0x8d, 0x21, 0xaf, 0xa5, 0x13, 0x01, 0x1d, 0x31, 0x4e, 0x0d, 0x9b, 0x0e, 0xa8, 0x25, 0x97, 0xf2,
+	0x3a, 0x56, 0xa3, 0xa5, 0xab, 0xd1, 0x11, 0xb4, 0x87, 0x98, 0x0c, 0x3f, 0x61, 0x53, 0x4a, 0x12,
+	0x4a, 0x37, 0x70, 0x10, 0x86, 0x74, 0x64, 0xd8, 0xd4, 0x75, 0x3c, 0x2a, 0xdd, 0x11, 0xfc, 0x0d,
+	0xe4, 0xff, 0x74, 0x7a, 0x1c, 0xf6, 0x5b, 0x47, 0x6a, 0x4a, 0xed, 0x25, 0x26, 0x99, 0xea, 0x56,
+	0xd5, 0x70, 0xec, 0xd3, 0x51, 0x16, 0x42, 0xce, 0x61, 0x13, 0x63, 0xeb, 0xf4, 0x2a, 0x74, 0x2c,
+	0xd3, 0x35, 0xe8, 0x77, 0x63, 0xc7, 0x1f, 0x51, 0x8f, 0xa7, 0x62, 0x6c, 0x09, 0x2b, 0xfe, 0x28,
+	0x13, 0x63, 0x0a, 0xdf, 0x8a, 0xe0, 0xd3, 0xa1, 0x26, 0x9c, 0xb9, 0x16, 0x46, 0x7e, 0x0e, 0xcb,
+	0xe9, 0x88, 0x33, 0xad, 0x33, 0xac, 0x8a, 0x4c, 0xcf, 0x46, 0xe9, 0x63, 0xd3, 0x3a, 0xf3, 0xd8,
+	0x85, 0x4b, 0xed, 0x21, 0x15, 0x3c, 0x99, 0x9a, 0xea, 0x2c, 0x85, 0x12, 0xe4, 0x0c, 0x36, 0x64,
+	0x22, 0x30, 0x18, 0x18, 0x01, 0x35, 0xad, 0x53, 0x83, 0x5e, 0x5a, 0x94, 0xda, 0xd4, 0xc6, 0x4a,
+	0x96, 0xb1, 0x92, 0xed, 0x6c, 0x5e, 0x30, 0xc0, 0x49, 0xce, 0x1d, 0xd3, 0xd5, 0x85, 0x45, 0x4b,
+	0x19, 0x64, 0x2a, 0x7a, 0xc8, 0x24, 0x72, 0x12, 0x11, 0xef, 0x76, 0x5b, 0x50, 0xcd, 0x64, 0x45,
+	0xe4, 0x1d, 0x00, 0x4c, 0x68, 0x44, 0xa8, 0x53, 0xdc, 0xed, 0x16, 0xf5, 0x45, 0x21, 0x11, 0xc1,
+	0x4b, 0xb5, 0x03, 0xa8, 0x65, 0x33, 0x22, 0xf2, 0x10, 0x8a, 0x32, 0x79, 0x92, 0x7b, 0x63, 0x51,
+	0x2f, 0x60, 0x82, 0x64, 0x4f, 0x30, 0xcd, 0x4d, 0x32, 0x9d, 0xc2, 0xd2, 0x54, 0x7a, 0x73, 0x3d,
+	0xd9, 0x97, 0x50, 0x0d, 0x69, 0xe0, 0x98, 0xae, 0xe1, 0x8d, 0x47, 0x27, 0x34, 0x50, 0xbb, 0xe9,
+	0x4a, 0xdc, 0x25, 0x3d, 0xd4, 0x1e, 0xa3, 0x52, 0xaf, 0x84, 0xa9, 0x92, 0xf6, 0x7d, 0x1e, 0xaa,
+	0x99, 0x74, 0xe8, 0xfa, 0x6a, 0x56, 0xa0, 0x80, 0xf3, 0x5d, 0xee, 0xd6, 0x45, 0x7d, 0x41, 0xcc,
+	0xdd, 0x49, 0x57, 0xe6, 0x27, 0x5c, 0x21, 0x4f, 0xa0, 0x6c, 0xda, 0x23, 0xc7, 0x53, 0xfa, 0x05,
+	0xd4, 0x03, 0x8a, 0x24, 0x60, 0xaa, 0xf5, 0xf9, 0xb7, 0x6e, 0x3d, 0x39, 0x84, 0x32, 0x2e, 0x6c,
+	0x01, 0x35, 0x43, 0xe6, 0xe1, 0xf6, 0x57, 0xcb, 0xc6, 0x5b, 0xe2, 0xd8, 0x56, 0x76, 0x29, 0xd6,
+	0xd1, 0x44, 0x87, 0x41, 0xfc, 0x5b, 0xfb, 0xd3, 0x39, 0xb8, 0x3f, 0x0b, 0x44, 0xde, 0x83, 0x27,
+	0x9d, 0xe3, 0x97, 0x46, 0x73, 0xb7, 0xdf, 0x7e, 0xd5, 0xec, 0xb7, 0x3b, 0xc7, 0xc6, 0x8b, 0x66,
+	0xfb, 0xd0, 0xd0, 0x5b, 0xcd, 0x5e, 0xe7, 0xd8, 0x38, 0xee, 0x1c, 0xb7, 0x1a, 0xf7, 0xc8, 0xfb,
+	0xa0, 0xdd, 0x00, 0xd2, 0x9b, 0xc7, 0xfb, 0xed, 0xe3, 0xfd, 0x46, 0x8e, 0xfc, 0x04, 0x9e, 0xdf,
+	0x80, 0xeb, 0x36, 0x7b, 0xbd, 0xd7, 0x1d, 0x7d, 0xcf, 0x68, 0xbe, 0xec, 0x1f, 0xb4, 0x8e, 0xfb,
+	0xed, 0x5d, 0xc4, 0x34, 0xe6, 0x88, 0x06, 0x8f, 0x6f, 0xb0, 0x3b, 0xec, 0xf4, 0x1a, 0xf3, 0xe4,
+	0x5d, 0x78, 0x67, 0x16, 0x06, 0x65, 0x87, 0x4d, 0xfd, 0xa8, 0x91, 0xbf, 0xce, 0x97, 0xde, 0xeb,
+	0x76, 0x7f, 0xf7, 0xc0, 0xe8, 0xbc, 0x6a, 0xe9, 0x8d, 0x05, 0xed, 0x17, 0x40, 0xa6, 0x13, 0x74,
+	0x42, 0x20, 0xcf, 0xaf, 0xfc, 0x28, 0xf0, 0xf1, 0x77, 0x3a, 0x5a, 0xe6, 0x6e, 0x88, 0xf0, 0xc9,
+	0xb0, 0xd0, 0x74, 0xa8, 0x65, 0x33, 0xea, 0x5b, 0xc7, 0x5d, 0x03, 0xe6, 0xfd, 0x33, 0x8e, 0xcc,
+	0x15, 0x5d, 0xfc, 0xd4, 0xfe, 0x39, 0x07, 0x8d, 0xc9, 0x8c, 0x9b, 0x6c, 0xc0, 0x22, 0xd2, 0x62,
+	0xcb, 0x65, 0xf4, 0xe1, 0x81, 0xa6, 0x3f, 0xd1, 0xfa, 0xa9, 0xf9, 0x39, 0xa4, 0x23, 0x4c, 0xd0,
+	0xe3, 0x7a, 0x17, 0x95, 0xa4, 0x6d, 0x0b, 0x3b, 0x4c, 0xc1, 0x1d, 0x99, 0x74, 0x16, 0xf5, 0x82,
+	0x28, 0x4a, 0x05, 0x1a, 0x79, 0x0c, 0x83, 0xb1, 0xa8, 0x17, 0x44, 0xf1, 0x98, 0x91, 0x07, 0x50,
+	0xb0, 0x18, 0x3b, 0x73, 0x28, 0x26, 0x53, 0x05, 0x5d, 0x95, 0x22, 0x2f, 0xf2, 0x89, 0x17, 0x4f,
+	0x61, 0x51, 0xa6, 0x29, 0xa6, 0x75, 0x7d, 0x03, 0xb5, 0x9f, 0xc1, 0xe2, 0x01, 0x35, 0x03, 0x7e,
+	0x42, 0x4d, 0x4e, 0xb6, 0x61, 0xf9, 0x34, 0x2a, 0xc8, 0x24, 0x8b, 0x8f, 0x03, 0xaa, 0x2c, 0x48,
+	0xac, 0xea, 0x45, 0x1a, 0xed, 0xef, 0x72, 0x30, 0xdf, 0xf1, 0xc6, 0xb7, 0xee, 0xf3, 0xa9, 0xb9,
+	0x3a, 0xff, 0xf6, 0x73, 0x55, 0x78, 0xea, 0xc8, 0xd9, 0x5d, 0xd4, 0xc5, 0x4f, 0xf2, 0x01, 0xd4,
+	0xd9, 0xc8, 0xb2, 0x0c, 0xea, 0x59, 0xc1, 0x95, 0x2f, 0x46, 0x0b, 0x07, 0xa8, 0xa4, 0xd7, 0x84,
+	0xb8, 0x15, 0x4b, 0xb5, 0xbf, 0xcf, 0x01, 0xc1, 0xbd, 0x63, 0x28, 0xb6, 0x9f, 0x3d, 0x27, 0xe4,
+	0xa6, 0x77, 0x43, 0xe7, 0x5c, 0xd7, 0xfa, 0x2f, 0x60, 0xcd, 0x95, 0x14, 0x86, 0x3a, 0x59, 0x22,
+	0x8f, 0xf1, 0x47, 0x34, 0x60, 0x6a, 0x1c, 0x1f, 0x28, 0x80, 0x5c, 0x7d, 0x51, 0xfd, 0x0d, 0x0d,
+	0x18, 0xf9, 0x04, 0xee, 0xcf, 0x32, 0x55, 0xde, 0x90, 0x69, 0x2b, 0xed, 0x6b, 0x28, 0x8a, 0x00,
+	0x3f, 0x0a, 0x87, 0x77, 0x10, 0xd9, 0xbf, 0xce, 0xc1, 0xa2, 0xd8, 0xa7, 0x31, 0xb8, 0x6f, 0xcd,
+	0x97, 0x0a, 0xca, 0x7c, 0x26, 0x28, 0xb3, 0x51, 0xbe, 0x30, 0x19, 0xe5, 0xd3, 0xed, 0xf8, 0x02,
+	0x2a, 0x2f, 0x7d, 0xd7, 0xf1, 0xce, 0xde, 0xd4, 0x12, 0x65, 0x3a, 0x97, 0x98, 0xfe, 0xf9, 0x22,
+	0xc0, 0x1e, 0x3d, 0x77, 0x2c, 0xda, 0xf6, 0x06, 0x38, 0x1f, 0xce, 0xa9, 0x67, 0xb3, 0x40, 0xad,
+	0x26, 0xaa, 0x44, 0xee, 0xc3, 0xc2, 0x88, 0xd9, 0xd4, 0x55, 0x7b, 0xa2, 0x2c, 0x90, 0x1f, 0x43,
+	0xe3, 0xd4, 0x0c, 0xec, 0x0b, 0x33, 0xa0, 0xc6, 0x39, 0x0d, 0x44, 0x2a, 0xaf, 0x96, 0x94, 0x7a,
+	0x24, 0x7f, 0x25, 0xc5, 0x02, 0x3a, 0x70, 0x82, 0x51, 0x06, 0x9a, 0x97, 0xd0, 0x48, 0x1e, 0x41,
+	0x37, 0x60, 0xd1, 0xc6, 0x16, 0x89, 0xf6, 0x37, 0xe4, 0xd2, 0x20, 0x05, 0x6d, 0x5b, 0x8c, 0xb8,
+	0x52, 0x66, 0x23, 0x7e, 0x09, 0x71, 0x44, 0xea, 0xd2, 0xe1, 0x2e, 0xe8, 0x44, 0x1e, 0x2c, 0x3a,
+	0x2f, 0xc4, 0x34, 0xbb, 0xa8, 0x97, 0x7c, 0xe6, 0x89, 0xa3, 0x7c, 0x48, 0x1e, 0x03, 0x70, 0x6a,
+	0x9d, 0x7a, 0xcc, 0x65, 0xc3, 0xab, 0x68, 0x17, 0x4c, 0x24, 0x64, 0x53, 0x1e, 0x64, 0x1c, 0x5b,
+	0x1e, 0x46, 0xd5, 0xea, 0x01, 0x38, 0x80, 0x78, 0xb6, 0x24, 0x8f, 0x00, 0x14, 0x82, 0xaa, 0x23,
+	0x59, 0x51, 0x2f, 0xa1, 0xbe, 0xe5, 0xd9, 0xe4, 0x29, 0xd4, 0x4c, 0xd7, 0x65, 0x56, 0xc2, 0x50,
+	0x42, 0x44, 0x05, 0xa5, 0x11, 0xc7, 0x26, 0x54, 0x62, 0x14, 0x55, 0xc7, 0xa5, 0xa2, 0x0e, 0x0a,
+	0x23, 0x78, 0x9e, 0x41, 0x23, 0x09, 0x09, 0xc5, 0x04, 0x88, 0xaa, 0xc5, 0x81, 0x21, 0xb9, 0x9e,
+	0x42, 0x2d, 0x85, 0xa4, 0xea, 0xf4, 0x52, 0xd4, 0x2b, 0x31, 0x4e, 0xf0, 0x69, 0x50, 0x55, 0x2b,
+	0xa5, 0x22, 0xab, 0x22, 0xa8, 0x2c, 0xd7, 0x4b, 0xc9, 0xf4, 0x18, 0xca, 0x11, 0x86, 0xaa, 0x04,
+	0xbf, 0x28, 0xaf, 0x2d, 0x24, 0xc7, 0x57, 0x50, 0x08, 0x4c, 0x6f, 0x48, 0xc3, 0xd5, 0xfa, 0xe6,
+	0xfc, 0xb3, 0xf2, 0xf3, 0x67, 0xc9, 0x35, 0x41, 0x1c, 0x50, 0xea, 0xa7, 0x4e, 0x43, 0x36, 0x0e,
+	0x2c, 0xaa, 0x23, 0x5e, 0x57, 0x76, 0xeb, 0x7f, 0x91, 0x87, 0xfb, 0xb3, 0x00, 0x64, 0x2d, 0xba,
+	0xdd, 0xb2, 0xc3, 0xd5, 0xdc, 0xe6, 0xfc, 0xb3, 0xa2, 0xba, 0xc2, 0xb2, 0x27, 0x47, 0x6c, 0x6e,
+	0x6a, 0xc4, 0x76, 0x61, 0xc1, 0x67, 0xcc, 0x0d, 0x57, 0xe7, 0xb1, 0x51, 0x1f, 0xbf, 0x6d, 0xa3,
+	0xb6, 0xba, 0x8c, 0xb9, 0xba, 0xb4, 0x5d, 0xff, 0xaf, 0x39, 0xc8, 0x8b, 0x32, 0xf9, 0xbd, 0xd4,
+	0xde, 0x5a, 0x7b, 0xfe, 0x93, 0x5b, 0x91, 0xe1, 0x1f, 0xb1, 0x9f, 0xa9, 0x3d, 0xb9, 0x07, 0xc5,
+	0xf0, 0xd4, 0x0c, 0x1c, 0x6f, 0x88, 0xcd, 0xae, 0x3d, 0xff, 0xe2, 0x76, 0x74, 0x3d, 0x69, 0x8c,
+	0x8c, 0x11, 0x93, 0x98, 0x98, 0x72, 0x00, 0xe5, 0x42, 0x29, 0x0b, 0x62, 0x9e, 0x53, 0x75, 0x5f,
+	0x52, 0xd4, 0xc5, 0x4f, 0xad, 0x09, 0xa5, 0xa8, 0x39, 0x04, 0xa0, 0x20, 0x72, 0x8d, 0xf6, 0x5e,
+	0xe3, 0x1e, 0xa9, 0x40, 0xa9, 0x79, 0x78, 0xd8, 0xd9, 0x15, 0xa5, 0x1c, 0xa9, 0x01, 0xec, 0xb7,
+	0x8e, 0xba, 0x1d, 0xbd, 0x2f, 0xca, 0x73, 0xa4, 0x0c, 0xc5, 0x17, 0x87, 0x9d, 0xd7, 0xa2, 0x30,
+	0xaf, 0x9d, 0x42, 0x39, 0xd5, 0x04, 0xf2, 0x00, 0xc8, 0x5e, 0x6b, 0x4f, 0x24, 0x42, 0xad, 0x3d,
+	0xa3, 0xdb, 0xd2, 0x8d, 0xf6, 0x71, 0xff, 0x45, 0xe3, 0x1e, 0x79, 0x02, 0x1b, 0xbd, 0x83, 0xa6,
+	0xde, 0xda, 0x33, 0x76, 0xfe, 0xd0, 0x68, 0x1e, 0x1e, 0xa2, 0x1c, 0x7f, 0xf4, 0x5b, 0xbb, 0x07,
+	0x8d, 0x1c, 0xd9, 0x84, 0x47, 0x33, 0x00, 0xbd, 0xe6, 0x51, 0x4b, 0x22, 0xe6, 0xb4, 0x3f, 0x9e,
+	0x07, 0xd8, 0x75, 0xcd, 0x30, 0x74, 0x06, 0x0e, 0x0d, 0x70, 0xfd, 0x34, 0xb8, 0x1f, 0xaf, 0x66,
+	0x0b, 0xac, 0xef, 0x3b, 0x36, 0x59, 0x86, 0x05, 0x66, 0x9c, 0xc7, 0xab, 0x6a, 0x9e, 0xbd, 0x72,
+	0x70, 0xad, 0x75, 0x24, 0x56, 0x75, 0x88, 0x13, 0x61, 0x1d, 0xc4, 0xca, 0x2e, 0xc9, 0x3b, 0x02,
+	0xfb, 0x10, 0x8a, 0xcc, 0xf0, 0x4f, 0x1c, 0x1e, 0xaa, 0x45, 0xb6, 0xc0, 0xba, 0xa2, 0x84, 0xeb,
+	0xa7, 0x52, 0xa8, 0x74, 0xc1, 0x91, 0x8a, 0x35, 0x28, 0x51, 0x7e, 0x2a, 0x93, 0x16, 0x39, 0xd5,
+	0x8b, 0x94, 0x9f, 0x46, 0x39, 0x8b, 0x1d, 0x72, 0x63, 0x64, 0x5a, 0x38, 0xc5, 0x2b, 0x7a, 0xc1,
+	0x0e, 0xf9, 0x91, 0x69, 0x09, 0x45, 0x18, 0x58, 0xa8, 0x58, 0x94, 0x8a, 0x30, 0xb0, 0x84, 0x42,
+	0x04, 0xb9, 0x2f, 0xaf, 0x88, 0xd5, 0x5c, 0x2e, 0x3a, 0x7e, 0x17, 0x2f, 0xa9, 0x57, 0x40, 0x58,
+	0x1b, 0x8e, 0xaf, 0x26, 0xef, 0x82, 0x1d, 0xf2, 0xb6, 0x2f, 0xc4, 0x82, 0xca, 0xf1, 0xd5, 0x3a,
+	0xb6, 0x10, 0x06, 0x56, 0xdb, 0x17, 0x44, 0x42, 0x2c, 0x66, 0xb7, 0x9a, 0xc7, 0xa2, 0x46, 0xb1,
+	0xc0, 0x09, 0x95, 0x20, 0x42, 0x95, 0x9c, 0xc0, 0xa2, 0x95, 0xa8, 0xda, 0x84, 0x8a, 0x7f, 0xc6,
+	0x0d, 0x6e, 0x0e, 0xa5, 0x3f, 0x75, 0x39, 0x95, 0xfc, 0x33, 0xde, 0x37, 0x71, 0x84, 0xb5, 0x5f,
+	0xcf, 0xc3, 0xa2, 0x48, 0xbc, 0x99, 0xb7, 0x3b, 0xc2, 0x25, 0xc3, 0xb4, 0x6d, 0x83, 0x8d, 0x39,
+	0x0d, 0x84, 0x15, 0x0e, 0x46, 0x49, 0x2f, 0x9b, 0xb6, 0xdd, 0x11, 0xb2, 0xbe, 0x39, 0x14, 0xcb,
+	0x94, 0x38, 0xb2, 0x9f, 0xd3, 0x14, 0x6c, 0x4e, 0xe6, 0x0e, 0x52, 0x1e, 0x23, 0x37, 0xa1, 0xc2,
+	0x03, 0xd3, 0x37, 0x38, 0x33, 0x4e, 0x59, 0x28, 0xc3, 0xb7, 0xa4, 0x83, 0x90, 0xf5, 0xd9, 0x01,
+	0x0b, 0x39, 0xf9, 0x08, 0x48, 0x40, 0x47, 0x66, 0x70, 0xa6, 0xb8, 0xe4, 0x78, 0xe4, 0x11, 0xd7,
+	0x90, 0x1a, 0x64, 0x93, 0x23, 0x93, 0xa0, 0x1d, 0xcf, 0x8b, 0xd1, 0x0b, 0x69, 0x74, 0x5b, 0x28,
+	0x24, 0x5a, 0xf9, 0x22, 0xa1, 0xa2, 0x91, 0x85, 0xd8, 0x17, 0x44, 0x65, 0x7d, 0x49, 0x60, 0xc5,
+	0xb4, 0x2f, 0x31, 0x72, 0x0b, 0x96, 0x79, 0x60, 0x7a, 0xa1, 0x6b, 0xf2, 0x34, 0xb8, 0x84, 0xe0,
+	0xa5, 0x58, 0x35, 0x1b, 0x9f, 0x74, 0xd4, 0xe2, 0x04, 0x3e, 0xea, 0x2b, 0xed, 0x1f, 0x72, 0x50,
+	0x90, 0xe3, 0x40, 0x9e, 0xc2, 0xbc, 0x35, 0x8a, 0x6e, 0x74, 0x49, 0x72, 0x49, 0x1c, 0x8d, 0x92,
+	0x2e, 0xd4, 0xb3, 0x67, 0x46, 0x2a, 0xda, 0xe7, 0x33, 0xd1, 0x9e, 0x4c, 0xaf, 0xfc, 0xc4, 0xf4,
+	0x92, 0x53, 0x66, 0x21, 0x3b, 0x65, 0x66, 0xcf, 0x8c, 0x64, 0xde, 0x15, 0x53, 0xf3, 0x4e, 0xfb,
+	0xa7, 0x05, 0xc8, 0xbf, 0x70, 0xd9, 0x05, 0x6e, 0x84, 0x96, 0x45, 0xc3, 0xd0, 0x48, 0x67, 0x26,
+	0x75, 0xbd, 0x22, 0xa5, 0xed, 0x59, 0x99, 0x52, 0x3d, 0xca, 0x94, 0x56, 0xa0, 0x30, 0xf6, 0x1c,
+	0x21, 0x2e, 0x4b, 0xf1, 0xd8, 0x73, 0xa6, 0xd3, 0xfd, 0x42, 0x9c, 0xee, 0x7f, 0x08, 0x4b, 0xe1,
+	0xd5, 0x68, 0x44, 0x79, 0xe0, 0x58, 0x46, 0x04, 0x21, 0x08, 0xa9, 0xc7, 0x8a, 0x17, 0x12, 0xbb,
+	0x01, 0xb8, 0xa5, 0xc9, 0x39, 0x20, 0x33, 0x92, 0x92, 0x10, 0xe0, 0xa4, 0x5e, 0x83, 0x52, 0xb4,
+	0x31, 0xe3, 0x14, 0xad, 0xeb, 0x45, 0xb5, 0x29, 0x93, 0xf7, 0xa1, 0xee, 0x51, 0x7e, 0xc1, 0x30,
+	0xe2, 0xa4, 0x47, 0x0b, 0x88, 0xa8, 0x2a, 0x71, 0x7b, 0xd6, 0x91, 0xa5, 0x80, 0x90, 0x54, 0x32,
+	0xf7, 0x19, 0x80, 0x15, 0xaf, 0x74, 0xea, 0x46, 0x77, 0x39, 0x1e, 0xd7, 0x64, 0x11, 0xd4, 0x53,
+	0x30, 0xf2, 0x01, 0x14, 0x4c, 0x1c, 0x71, 0x75, 0x53, 0x5b, 0x9f, 0x08, 0x04, 0x5d, 0xa9, 0xc9,
+	0x3a, 0x94, 0xfc, 0xc0, 0x61, 0x81, 0xc3, 0xaf, 0x30, 0xbc, 0xea, 0x7a, 0x5c, 0x4e, 0x1d, 0x7d,
+	0x2a, 0x99, 0xa3, 0x4f, 0x2a, 0x2d, 0xad, 0x66, 0xd2, 0xd2, 0x35, 0x28, 0x0d, 0x03, 0x36, 0xf6,
+	0x85, 0x1f, 0x6a, 0x2d, 0xc1, 0xb2, 0xec, 0x8c, 0xf4, 0x0b, 0x99, 0x40, 0xd4, 0x11, 0x51, 0x15,
+	0xe2, 0xae, 0x94, 0xb6, 0x6d, 0xf2, 0x23, 0xa8, 0x05, 0xd4, 0x77, 0xc5, 0x21, 0x90, 0xe2, 0xc0,
+	0x60, 0x7e, 0x57, 0xd2, 0xab, 0xb1, 0x14, 0x83, 0xe5, 0x00, 0xea, 0x22, 0xc6, 0xc4, 0xe2, 0xa0,
+	0x7a, 0x6a, 0x75, 0x09, 0x77, 0xf3, 0xcd, 0xcc, 0x7b, 0xca, 0x96, 0x08, 0xbd, 0x3e, 0xdb, 0x97,
+	0x90, 0x96, 0xc7, 0x83, 0x2b, 0xbd, 0xea, 0xa7, 0x65, 0xeb, 0x5f, 0x01, 0x99, 0x06, 0x89, 0xed,
+	0xf1, 0x8c, 0x5e, 0xa9, 0xdd, 0x44, 0xfc, 0x14, 0xdb, 0xe8, 0xb9, 0xe9, 0x8e, 0x69, 0x94, 0xa1,
+	0x63, 0xe1, 0xcb, 0xb9, 0x9f, 0xe6, 0xb4, 0x3e, 0x54, 0x26, 0xd3, 0x49, 0x99, 0x13, 0x47, 0x31,
+	0x5c, 0xd1, 0x4b, 0x52, 0xd0, 0xb6, 0xc5, 0xd1, 0x49, 0x29, 0x43, 0x9f, 0x5a, 0xce, 0xc0, 0xb1,
+	0x54, 0xae, 0x5d, 0x93, 0xe2, 0x9e, 0x92, 0x6a, 0xff, 0x9a, 0x87, 0x5a, 0xf6, 0x31, 0xe9, 0xfa,
+	0xa4, 0x7d, 0x0d, 0x4a, 0xc1, 0xa5, 0x71, 0x72, 0xc5, 0x69, 0x88, 0x6c, 0x05, 0xbd, 0x18, 0x5c,
+	0xee, 0x88, 0xa2, 0x08, 0xae, 0xe0, 0xd2, 0xf0, 0x31, 0xeb, 0x0f, 0xd5, 0x24, 0x58, 0x0c, 0x2e,
+	0xe5, 0x31, 0x20, 0xc4, 0x25, 0xec, 0xd2, 0x18, 0x5b, 0xa6, 0xd8, 0x02, 0x14, 0x28, 0x8f, 0xa0,
+	0x5a, 0x70, 0xf9, 0x52, 0x88, 0xb3, 0xc8, 0x51, 0x06, 0xb9, 0x10, 0x21, 0x8f, 0xa6, 0x91, 0x27,
+	0x19, 0x64, 0x21, 0x42, 0xee, 0x4c, 0x23, 0xe5, 0x0d, 0x67, 0x84, 0x2c, 0x46, 0x48, 0xbc, 0xa3,
+	0x8c, 0x90, 0x6b, 0x50, 0xe2, 0x91, 0x87, 0x25, 0xe9, 0x21, 0x4f, 0x3c, 0xe4, 0x89, 0x87, 0x8b,
+	0xd2, 0x43, 0x9e, 0xf6, 0x90, 0x4f, 0x7a, 0x08, 0xb2, 0x0e, 0x3e, 0xe5, 0x21, 0x9f, 0xf4, 0xb0,
+	0x1c, 0x21, 0x8f, 0xa6, 0x91, 0x59, 0x0f, 0x2b, 0x11, 0x72, 0x67, 0x1a, 0x99, 0xf5, 0xb0, 0x1a,
+	0x21, 0x33, 0x1e, 0x6a, 0x50, 0x0d, 0x2e, 0x0d, 0x2b, 0xb0, 0x24, 0x3a, 0xc4, 0x09, 0x54, 0xd0,
+	0xcb, 0xc1, 0xe5, 0x6e, 0x60, 0x21, 0x12, 0x5d, 0x3d, 0x71, 0xfc, 0x08, 0x50, 0x97, 0xae, 0x9e,
+	0x38, 0xbe, 0x52, 0x3f, 0x82, 0x45, 0xee, 0x8c, 0x68, 0xc8, 0xcd, 0x91, 0x8f, 0xd3, 0xa6, 0xa8,
+	0x27, 0x02, 0xed, 0x1f, 0x73, 0x50, 0xcb, 0xbe, 0x31, 0xa6, 0x97, 0xc7, 0x5c, 0xe6, 0x36, 0xe4,
+	0x87, 0x07, 0xd4, 0x0f, 0x1f, 0xa8, 0x9b, 0x5b, 0xff, 0x15, 0x54, 0x33, 0x8f, 0x92, 0xd7, 0x4f,
+	0x86, 0x07, 0x50, 0x08, 0xb9, 0xc9, 0xc7, 0xa1, 0x4a, 0xfd, 0x55, 0x49, 0xfb, 0x16, 0x96, 0x67,
+	0x3c, 0x4e, 0xde, 0xfa, 0x4c, 0x9e, 0xd0, 0xcf, 0x67, 0xe8, 0xff, 0x76, 0x0e, 0xaf, 0x3a, 0x26,
+	0x1f, 0x59, 0x7f, 0xc0, 0xa5, 0xac, 0xcb, 0x42, 0x23, 0x53, 0xc5, 0xa2, 0xcb, 0xc2, 0x1e, 0x0a,
+	0xa4, 0xfa, 0x24, 0x52, 0xe7, 0x23, 0xf5, 0x89, 0x52, 0x3f, 0x83, 0x86, 0xcb, 0x7c, 0xcb, 0x18,
+	0x39, 0x61, 0xcc, 0x21, 0x8f, 0xac, 0x35, 0x21, 0x3f, 0x72, 0xc2, 0x88, 0xe8, 0x53, 0x58, 0x51,
+	0x48, 0x15, 0x70, 0x11, 0xbc, 0x20, 0x8f, 0xc9, 0x12, 0x2e, 0x03, 0x4f, 0x99, 0x3c, 0x81, 0xb2,
+	0xcb, 0x06, 0x4e, 0x04, 0x2c, 0xca, 0x6c, 0x50, 0x88, 0x14, 0xe0, 0x5d, 0xa8, 0xb8, 0xcc, 0x1c,
+	0xc5, 0x88, 0x12, 0x22, 0xca, 0x28, 0x93, 0x10, 0x8d, 0xc2, 0xc6, 0x0d, 0x4f, 0xb2, 0x77, 0x36,
+	0x18, 0x7f, 0x95, 0x83, 0xf5, 0xeb, 0xdf, 0x67, 0xef, 0xaa, 0x1a, 0xf2, 0x19, 0x3c, 0x70, 0xbc,
+	0x73, 0x1a, 0x84, 0xd4, 0x10, 0x9b, 0x91, 0xec, 0xc7, 0xc0, 0xe4, 0xd1, 0xf5, 0xd2, 0xb2, 0xd2,
+	0xee, 0x38, 0xf2, 0xc5, 0x45, 0x37, 0x39, 0xd5, 0xbe, 0x97, 0x6d, 0xbb, 0xe6, 0x79, 0xf7, 0xce,
+	0xda, 0x76, 0x1f, 0x16, 0xf0, 0xa1, 0x39, 0x4a, 0xd9, 0xb0, 0x20, 0xd8, 0x3d, 0x7a, 0x61, 0xd0,
+	0xef, 0xa2, 0xa4, 0xad, 0xe0, 0xd1, 0x8b, 0xd6, 0x77, 0xb6, 0x76, 0x0a, 0x8f, 0x6f, 0x7e, 0x1c,
+	0xbe, 0xb3, 0xb1, 0xf9, 0xeb, 0x9c, 0x8c, 0x81, 0x6b, 0x9e, 0x8b, 0xff, 0x7f, 0x07, 0xe7, 0x57,
+	0x39, 0xd0, 0xde, 0xfc, 0xf4, 0xfc, 0x7f, 0x3b, 0x48, 0xda, 0x77, 0x38, 0x16, 0x37, 0x3c, 0x51,
+	0xdf, 0xba, 0xfe, 0x27, 0xd9, 0xe7, 0x16, 0x99, 0xdd, 0xa7, 0x5f, 0x50, 0xce, 0xe0, 0xdd, 0x37,
+	0xbe, 0x27, 0xdf, 0x59, 0x04, 0xf4, 0x81, 0xe8, 0xb6, 0x33, 0xf1, 0x54, 0x29, 0x32, 0xc4, 0xc0,
+	0x76, 0xd4, 0x38, 0x59, 0x6c, 0xec, 0x71, 0xac, 0xa5, 0xa0, 0x57, 0x03, 0x05, 0xde, 0x15, 0xc2,
+	0x6b, 0xd7, 0xf7, 0xbf, 0xcc, 0xc1, 0xea, 0x75, 0x0f, 0xd6, 0xb7, 0x6e, 0x7a, 0x13, 0xaa, 0x49,
+	0x63, 0x66, 0x7d, 0xa2, 0x32, 0xed, 0xc0, 0xc1, 0x3d, 0xbd, 0x1c, 0x24, 0xd2, 0x9d, 0x22, 0xde,
+	0xbb, 0xf0, 0x50, 0x3b, 0x86, 0x47, 0x37, 0x7d, 0x0e, 0x70, 0xdb, 0xb6, 0x69, 0xbf, 0x84, 0xcd,
+	0x37, 0x3d, 0x9d, 0xdf, 0xd9, 0x50, 0xfd, 0x12, 0xd6, 0xae, 0x7d, 0x3f, 0xff, 0x21, 0x7b, 0x5b,
+	0xdc, 0xa9, 0x49, 0xea, 0xa0, 0xba, 0x2c, 0xd4, 0xfe, 0x26, 0x07, 0xcf, 0xde, 0xf6, 0x31, 0xfd,
+	0xce, 0x66, 0xe0, 0xc7, 0x40, 0xd2, 0x0f, 0xfc, 0xaa, 0x6d, 0x72, 0x3a, 0x2e, 0xa5, 0x34, 0xaa,
+	0x8d, 0x23, 0x78, 0xef, 0x2d, 0x9e, 0xdd, 0xef, 0xac, 0xfb, 0x5d, 0x5c, 0x8d, 0xde, 0xf0, 0xf4,
+	0x7e, 0x67, 0xb5, 0xfd, 0x59, 0x0e, 0xde, 0x7f, 0xbb, 0x47, 0xf8, 0x3b, 0xeb, 0xfe, 0x75, 0x28,
+	0x4d, 0x3c, 0xc9, 0xc4, 0x65, 0xed, 0x3f, 0x73, 0x50, 0xde, 0x17, 0xc7, 0xc7, 0x23, 0x8a, 0xe7,
+	0xaa, 0x77, 0xa1, 0xe2, 0x44, 0xef, 0x6b, 0x51, 0xc5, 0x55, 0xfc, 0xf4, 0x50, 0xca, 0xda, 0x36,
+	0x69, 0x43, 0x2d, 0x81, 0xe0, 0x79, 0x5d, 0xde, 0xa3, 0x26, 0x5f, 0x83, 0xa4, 0x08, 0xb7, 0xe2,
+	0xd7, 0x3a, 0xbc, 0x30, 0xad, 0x3a, 0xe9, 0x22, 0x79, 0x0c, 0xe5, 0x21, 0x1d, 0x19, 0xd1, 0xb1,
+	0x7c, 0x1e, 0x2b, 0x13, 0xc7, 0xf2, 0xae, 0x3c, 0x96, 0xa7, 0x0f, 0xce, 0x79, 0x54, 0xc6, 0x65,
+	0xed, 0xb7, 0xa1, 0x9a, 0xe1, 0x26, 0x45, 0x98, 0xef, 0x76, 0x8e, 0x1b, 0xf7, 0x48, 0x03, 0x2a,
+	0xad, 0x6e, 0xe7, 0xd8, 0xf8, 0x74, 0xdf, 0xe8, 0x36, 0xfb, 0x07, 0x8d, 0x1c, 0x59, 0x82, 0xaa,
+	0x94, 0x7c, 0xa2, 0x44, 0x73, 0xda, 0x9f, 0xcc, 0xc1, 0x02, 0xb6, 0x33, 0x73, 0xa0, 0x96, 0xee,
+	0xc6, 0x07, 0xea, 0x9f, 0x41, 0xd1, 0x62, 0xa3, 0x91, 0xa9, 0xbe, 0xc1, 0x9b, 0xf2, 0x31, 0xed,
+	0x69, 0xb8, 0x2b, 0x91, 0x7a, 0x64, 0x42, 0xb6, 0xa0, 0x38, 0x92, 0x2a, 0x75, 0x0b, 0x7e, 0x7f,
+	0x56, 0x0f, 0xe9, 0x11, 0x28, 0x75, 0x9f, 0x90, 0xbf, 0xf1, 0x3e, 0x41, 0xfb, 0x1a, 0x96, 0x67,
+	0x54, 0x4c, 0xea, 0x50, 0x6e, 0xee, 0xed, 0x19, 0x47, 0xad, 0xa3, 0x9d, 0x96, 0xde, 0x6b, 0xdc,
+	0x23, 0x04, 0x6a, 0x7a, 0xeb, 0xa8, 0xf3, 0xaa, 0x15, 0xcb, 0x72, 0x02, 0xd4, 0x6b, 0xf5, 0x63,
+	0xc1, 0x9c, 0xf6, 0x0d, 0xc0, 0x2b, 0x71, 0xcc, 0xee, 0x9a, 0x81, 0x39, 0x22, 0x8f, 0x61, 0x9e,
+	0x79, 0x63, 0x75, 0xb3, 0x55, 0xc9, 0x7c, 0xdf, 0x23, 0x14, 0xe4, 0xa3, 0xf4, 0x09, 0xbd, 0xf6,
+	0xfc, 0xc1, 0x96, 0xfa, 0xe0, 0x16, 0x29, 0xc4, 0x30, 0x6c, 0xe1, 0x38, 0x4b, 0x90, 0x56, 0x84,
+	0x85, 0xd6, 0xc8, 0xe7, 0x57, 0xcf, 0xff, 0x7b, 0x09, 0x8a, 0x1d, 0xc9, 0x45, 0xf6, 0x00, 0xf6,
+	0x9c, 0xd0, 0x3c, 0x71, 0x69, 0xc7, 0xe5, 0xa4, 0x16, 0xd7, 0x81, 0xc8, 0xf5, 0x89, 0xb2, 0xf6,
+	0xe0, 0x57, 0xff, 0xf6, 0xef, 0xdf, 0xcf, 0x35, 0xb4, 0xf2, 0xf6, 0xf9, 0xa7, 0xdb, 0xca, 0xee,
+	0xcb, 0xdc, 0x87, 0xe4, 0x05, 0x94, 0x75, 0x4a, 0xbd, 0xb7, 0xa5, 0x79, 0x88, 0x34, 0x4b, 0x5a,
+	0x45, 0xd0, 0x44, 0x86, 0x82, 0xa7, 0x05, 0x65, 0x95, 0x04, 0xd0, 0x8e, 0x37, 0x26, 0x19, 0x97,
+	0xa7, 0x58, 0x56, 0x91, 0x85, 0x68, 0x55, 0xc1, 0xd2, 0x92, 0x95, 0x7b, 0x63, 0x41, 0x73, 0x00,
+	0xd5, 0x78, 0xb3, 0x78, 0x0b, 0xa2, 0x35, 0x24, 0x5a, 0xd6, 0x6a, 0x29, 0xaf, 0x14, 0xd3, 0x2e,
+	0x2c, 0xee, 0x51, 0x97, 0xde, 0xba, 0x39, 0xb1, 0x91, 0x20, 0x69, 0x03, 0xa8, 0xf7, 0xd5, 0xce,
+	0x98, 0x93, 0x46, 0xe6, 0x3b, 0xdd, 0xa3, 0x70, 0x78, 0x73, 0x7b, 0x12, 0x4b, 0x41, 0xd5, 0x81,
+	0x4a, 0xfc, 0xb8, 0x2a, 0xc8, 0x48, 0xe6, 0xdb, 0x28, 0x14, 0x4f, 0xd1, 0x6d, 0x20, 0xdd, 0x8a,
+	0xd6, 0x40, 0xba, 0x94, 0xb5, 0x20, 0xfc, 0x03, 0xa8, 0xa7, 0x9f, 0x49, 0x05, 0x67, 0xf2, 0x44,
+	0x9e, 0xd6, 0x4c, 0xd1, 0x3e, 0x46, 0xda, 0x55, 0x6d, 0x59, 0xd0, 0x4e, 0x70, 0x08, 0xe6, 0xaf,
+	0xa0, 0x28, 0x0e, 0xdf, 0x4d, 0xdb, 0x26, 0xd5, 0xcc, 0x15, 0xd5, 0xcd, 0x51, 0xa5, 0x6c, 0x64,
+	0x54, 0x81, 0x28, 0xe9, 0x78, 0xb3, 0xfc, 0x26, 0x92, 0x4c, 0xa7, 0x25, 0x66, 0x82, 0xa7, 0x07,
+	0xb5, 0xf8, 0x03, 0x84, 0xdd, 0x53, 0x6a, 0x9d, 0x4d, 0x05, 0x68, 0xd2, 0x8d, 0x31, 0x50, 0x7b,
+	0x07, 0x09, 0x1f, 0x6a, 0x44, 0x10, 0x66, 0xed, 0x05, 0xe9, 0x11, 0x94, 0x65, 0xcc, 0x75, 0x99,
+	0xd7, 0x1e, 0xa4, 0x06, 0x22, 0x5e, 0x07, 0xa7, 0x9a, 0xb8, 0x8e, 0x8c, 0xf7, 0xb5, 0x7a, 0x12,
+	0xb0, 0x68, 0xac, 0x06, 0x56, 0x45, 0xde, 0xdb, 0xf3, 0x65, 0x06, 0x36, 0x6d, 0x2d, 0x08, 0x75,
+	0xa8, 0xee, 0x53, 0x9e, 0x7a, 0xc6, 0x9e, 0xf4, 0x79, 0x79, 0xc6, 0x4b, 0x9b, 0xf6, 0x08, 0x29,
+	0x1f, 0x68, 0x4b, 0x82, 0x32, 0x63, 0x2f, 0x38, 0x7f, 0x17, 0x0a, 0x3a, 0x3d, 0x61, 0xec, 0xcd,
+	0x33, 0x7c, 0x05, 0x79, 0xea, 0x1a, 0xc8, 0x19, 0x2e, 0x6c, 0x04, 0xc1, 0x4b, 0x58, 0xda, 0x65,
+	0xae, 0x4b, 0xad, 0xf4, 0x25, 0xdf, 0x9b, 0xb8, 0x36, 0x91, 0x6b, 0x5d, 0x5b, 0x11, 0x5c, 0x53,
+	0xe6, 0x82, 0x36, 0x80, 0x87, 0xbb, 0x01, 0x35, 0x39, 0xed, 0x07, 0xe6, 0x60, 0xe0, 0x58, 0x3d,
+	0xeb, 0x94, 0xda, 0x63, 0x57, 0x2c, 0xe3, 0x4f, 0xb6, 0x32, 0xff, 0xa6, 0x30, 0x05, 0x98, 0xaa,
+	0xed, 0x7d, 0xac, 0x6d, 0x53, 0xdb, 0xc0, 0xda, 0x66, 0xb3, 0xaa, 0x3a, 0x65, 0x84, 0xdd, 0x75,
+	0x9d, 0xd7, 0xb0, 0x8a, 0x3a, 0x07, 0xb0, 0x9c, 0x69, 0xd1, 0xef, 0x8f, 0xe9, 0x98, 0x86, 0x64,
+	0x63, 0x66, 0x7d, 0x52, 0x39, 0x55, 0x97, 0x86, 0x75, 0x3d, 0xd2, 0x1e, 0x4e, 0xf9, 0x27, 0x0d,
+	0x54, 0x3d, 0x99, 0x56, 0xfc, 0xaf, 0xeb, 0x99, 0xc1, 0x26, 0xea, 0xf9, 0x2d, 0x68, 0xc8, 0x69,
+	0x90, 0xca, 0xb3, 0xae, 0x0f, 0xd3, 0x04, 0xa4, 0xdd, 0xfb, 0x24, 0x47, 0xbe, 0x85, 0x95, 0x2e,
+	0x0d, 0x06, 0x2c, 0x18, 0xe1, 0xf6, 0xdb, 0xf1, 0x69, 0x30, 0xc9, 0x80, 0x8a, 0xa9, 0x96, 0x3d,
+	0xc5, 0x96, 0x3d, 0xd6, 0xd6, 0x44, 0xcb, 0x66, 0x52, 0xc8, 0x45, 0xbb, 0x2c, 0x17, 0x71, 0x99,
+	0x97, 0xbc, 0x89, 0x34, 0x33, 0xb7, 0x53, 0x86, 0x82, 0xaa, 0x0f, 0xe5, 0x7d, 0xca, 0x5b, 0x97,
+	0x1c, 0xf7, 0x65, 0x92, 0x78, 0x94, 0x6c, 0xf5, 0xeb, 0xf7, 0xa3, 0xbd, 0x5b, 0xa7, 0x7c, 0x1c,
+	0x78, 0xa8, 0x09, 0xb3, 0xac, 0x29, 0x0e, 0xc1, 0xfa, 0x2d, 0x7e, 0x78, 0x29, 0x0f, 0x7f, 0x78,
+	0x07, 0xd7, 0xa3, 0x9c, 0x88, 0x14, 0x00, 0xff, 0xa7, 0x26, 0xab, 0xba, 0x79, 0x4e, 0x4d, 0xd1,
+	0x08, 0x7a, 0x1f, 0xd6, 0xf6, 0x29, 0x3f, 0x9c, 0xfd, 0x8d, 0x51, 0x76, 0x27, 0xdc, 0xc8, 0x7e,
+	0x35, 0x9b, 0xf9, 0xf2, 0x49, 0x7b, 0x86, 0x35, 0x69, 0xda, 0x3b, 0xca, 0x85, 0xd9, 0x8c, 0xa2,
+	0xc6, 0x53, 0x58, 0x99, 0xa9, 0xbf, 0x4d, 0x6d, 0x99, 0xb1, 0x9d, 0xc9, 0xf6, 0x65, 0xee, 0xc3,
+	0x9d, 0x6f, 0x61, 0x83, 0x05, 0x43, 0xe4, 0xb1, 0x58, 0x60, 0x6f, 0xc9, 0xff, 0x4c, 0x8a, 0x78,
+	0x77, 0xaa, 0xaf, 0xb0, 0x2c, 0x52, 0xa4, 0xce, 0x61, 0xff, 0x9b, 0xed, 0xa1, 0xc3, 0x4f, 0xc7,
+	0x27, 0x62, 0x80, 0xb6, 0x23, 0x93, 0x6d, 0x69, 0xf2, 0xb1, 0xfa, 0x67, 0xa6, 0xf3, 0xcf, 0xb7,
+	0x87, 0x2c, 0xfa, 0xa7, 0xaa, 0x6e, 0xae, 0x3b, 0x77, 0x52, 0x40, 0xcd, 0x67, 0xff, 0x13, 0x00,
+	0x00, 0xff, 0xff, 0x6c, 0xe5, 0xc7, 0x34, 0x78, 0x35, 0x00, 0x00,
 }
 
 // Reference imports to suppress errors if they are not otherwise used.
@@ -3832,6 +4552,11 @@
 	RemoveTrafficQueues(ctx context.Context, in *tech_profile.TrafficQueues, opts ...grpc.CallOption) (*Empty, error)
 	EnableIndication(ctx context.Context, in *Empty, opts ...grpc.CallOption) (Openolt_EnableIndicationClient, error)
 	PerformGroupOperation(ctx context.Context, in *Group, opts ...grpc.CallOption) (*Empty, error)
+	DeleteGroup(ctx context.Context, in *Group, opts ...grpc.CallOption) (*Empty, error)
+	GetExtValue(ctx context.Context, in *ValueParam, opts ...grpc.CallOption) (*common.ReturnValues, error)
+	OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm, opts ...grpc.CallOption) (*Empty, error)
+	GetLogicalOnuDistanceZero(ctx context.Context, in *Onu, opts ...grpc.CallOption) (*OnuLogicalDistance, error)
+	GetLogicalOnuDistance(ctx context.Context, in *Onu, opts ...grpc.CallOption) (*OnuLogicalDistance, error)
 }
 
 type openoltClient struct {
@@ -4063,6 +4788,51 @@
 	return out, nil
 }
 
+func (c *openoltClient) DeleteGroup(ctx context.Context, in *Group, opts ...grpc.CallOption) (*Empty, error) {
+	out := new(Empty)
+	err := c.cc.Invoke(ctx, "/openolt.Openolt/DeleteGroup", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *openoltClient) GetExtValue(ctx context.Context, in *ValueParam, opts ...grpc.CallOption) (*common.ReturnValues, error) {
+	out := new(common.ReturnValues)
+	err := c.cc.Invoke(ctx, "/openolt.Openolt/GetExtValue", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *openoltClient) OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm, opts ...grpc.CallOption) (*Empty, error) {
+	out := new(Empty)
+	err := c.cc.Invoke(ctx, "/openolt.Openolt/OnuItuPonAlarmSet", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *openoltClient) GetLogicalOnuDistanceZero(ctx context.Context, in *Onu, opts ...grpc.CallOption) (*OnuLogicalDistance, error) {
+	out := new(OnuLogicalDistance)
+	err := c.cc.Invoke(ctx, "/openolt.Openolt/GetLogicalOnuDistanceZero", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *openoltClient) GetLogicalOnuDistance(ctx context.Context, in *Onu, opts ...grpc.CallOption) (*OnuLogicalDistance, error) {
+	out := new(OnuLogicalDistance)
+	err := c.cc.Invoke(ctx, "/openolt.Openolt/GetLogicalOnuDistance", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
 // OpenoltServer is the server API for Openolt service.
 type OpenoltServer interface {
 	DisableOlt(context.Context, *Empty) (*Empty, error)
@@ -4087,6 +4857,11 @@
 	RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*Empty, error)
 	EnableIndication(*Empty, Openolt_EnableIndicationServer) error
 	PerformGroupOperation(context.Context, *Group) (*Empty, error)
+	DeleteGroup(context.Context, *Group) (*Empty, error)
+	GetExtValue(context.Context, *ValueParam) (*common.ReturnValues, error)
+	OnuItuPonAlarmSet(context.Context, *config.OnuItuPonAlarm) (*Empty, error)
+	GetLogicalOnuDistanceZero(context.Context, *Onu) (*OnuLogicalDistance, error)
+	GetLogicalOnuDistance(context.Context, *Onu) (*OnuLogicalDistance, error)
 }
 
 func RegisterOpenoltServer(s *grpc.Server, srv OpenoltServer) {
@@ -4492,6 +5267,96 @@
 	return interceptor(ctx, in, info, handler)
 }
 
+func _Openolt_DeleteGroup_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(Group)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(OpenoltServer).DeleteGroup(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/openolt.Openolt/DeleteGroup",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(OpenoltServer).DeleteGroup(ctx, req.(*Group))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Openolt_GetExtValue_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ValueParam)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(OpenoltServer).GetExtValue(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/openolt.Openolt/GetExtValue",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(OpenoltServer).GetExtValue(ctx, req.(*ValueParam))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Openolt_OnuItuPonAlarmSet_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(config.OnuItuPonAlarm)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(OpenoltServer).OnuItuPonAlarmSet(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/openolt.Openolt/OnuItuPonAlarmSet",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(OpenoltServer).OnuItuPonAlarmSet(ctx, req.(*config.OnuItuPonAlarm))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Openolt_GetLogicalOnuDistanceZero_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(Onu)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(OpenoltServer).GetLogicalOnuDistanceZero(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/openolt.Openolt/GetLogicalOnuDistanceZero",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(OpenoltServer).GetLogicalOnuDistanceZero(ctx, req.(*Onu))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Openolt_GetLogicalOnuDistance_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(Onu)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(OpenoltServer).GetLogicalOnuDistance(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/openolt.Openolt/GetLogicalOnuDistance",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(OpenoltServer).GetLogicalOnuDistance(ctx, req.(*Onu))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
 var _Openolt_serviceDesc = grpc.ServiceDesc{
 	ServiceName: "openolt.Openolt",
 	HandlerType: (*OpenoltServer)(nil),
@@ -4580,6 +5445,26 @@
 			MethodName: "PerformGroupOperation",
 			Handler:    _Openolt_PerformGroupOperation_Handler,
 		},
+		{
+			MethodName: "DeleteGroup",
+			Handler:    _Openolt_DeleteGroup_Handler,
+		},
+		{
+			MethodName: "GetExtValue",
+			Handler:    _Openolt_GetExtValue_Handler,
+		},
+		{
+			MethodName: "OnuItuPonAlarmSet",
+			Handler:    _Openolt_OnuItuPonAlarmSet_Handler,
+		},
+		{
+			MethodName: "GetLogicalOnuDistanceZero",
+			Handler:    _Openolt_GetLogicalOnuDistanceZero_Handler,
+		},
+		{
+			MethodName: "GetLogicalOnuDistance",
+			Handler:    _Openolt_GetLogicalOnuDistance_Handler,
+		},
 	},
 	Streams: []grpc.StreamDesc{
 		{
diff --git a/vendor/github.com/opencord/voltha-protos/v3/go/tech_profile/tech_profile.pb.go b/vendor/github.com/opencord/voltha-protos/v4/go/tech_profile/tech_profile.pb.go
similarity index 79%
rename from vendor/github.com/opencord/voltha-protos/v3/go/tech_profile/tech_profile.pb.go
rename to vendor/github.com/opencord/voltha-protos/v4/go/tech_profile/tech_profile.pb.go
index f74a616..d60ed83 100644
--- a/vendor/github.com/opencord/voltha-protos/v3/go/tech_profile/tech_profile.pb.go
+++ b/vendor/github.com/opencord/voltha-protos/v4/go/tech_profile/tech_profile.pb.go
@@ -322,6 +322,7 @@
 	AllocId              uint32              `protobuf:"fixed32,2,opt,name=alloc_id,json=allocId,proto3" json:"alloc_id,omitempty"`
 	Scheduler            *SchedulerConfig    `protobuf:"bytes,3,opt,name=scheduler,proto3" json:"scheduler,omitempty"`
 	TrafficShapingInfo   *TrafficShapingInfo `protobuf:"bytes,4,opt,name=traffic_shaping_info,json=trafficShapingInfo,proto3" json:"traffic_shaping_info,omitempty"`
+	TechProfileId        uint32              `protobuf:"fixed32,5,opt,name=tech_profile_id,json=techProfileId,proto3" json:"tech_profile_id,omitempty"`
 	XXX_NoUnkeyedLiteral struct{}            `json:"-"`
 	XXX_unrecognized     []byte              `json:"-"`
 	XXX_sizecache        int32               `json:"-"`
@@ -380,6 +381,13 @@
 	return nil
 }
 
+func (m *TrafficScheduler) GetTechProfileId() uint32 {
+	if m != nil {
+		return m.TechProfileId
+	}
+	return 0
+}
+
 type TrafficSchedulers struct {
 	IntfId               uint32              `protobuf:"fixed32,1,opt,name=intf_id,json=intfId,proto3" json:"intf_id,omitempty"`
 	OnuId                uint32              `protobuf:"fixed32,2,opt,name=onu_id,json=onuId,proto3" json:"onu_id,omitempty"`
@@ -812,6 +820,7 @@
 	UniId                uint32          `protobuf:"fixed32,4,opt,name=uni_id,json=uniId,proto3" json:"uni_id,omitempty"`
 	PortNo               uint32          `protobuf:"fixed32,5,opt,name=port_no,json=portNo,proto3" json:"port_no,omitempty"`
 	TrafficQueues        []*TrafficQueue `protobuf:"bytes,6,rep,name=traffic_queues,json=trafficQueues,proto3" json:"traffic_queues,omitempty"`
+	TechProfileId        uint32          `protobuf:"fixed32,7,opt,name=tech_profile_id,json=techProfileId,proto3" json:"tech_profile_id,omitempty"`
 	XXX_NoUnkeyedLiteral struct{}        `json:"-"`
 	XXX_unrecognized     []byte          `json:"-"`
 	XXX_sizecache        int32           `json:"-"`
@@ -877,6 +886,13 @@
 	return nil
 }
 
+func (m *TrafficQueues) GetTechProfileId() uint32 {
+	if m != nil {
+		return m.TechProfileId
+	}
+	return 0
+}
+
 func init() {
 	proto.RegisterEnum("tech_profile.Direction", Direction_name, Direction_value)
 	proto.RegisterEnum("tech_profile.SchedulingPolicy", SchedulingPolicy_name, SchedulingPolicy_value)
@@ -898,75 +914,77 @@
 func init() { proto.RegisterFile("voltha_protos/tech_profile.proto", fileDescriptor_d019a68bffe14cae) }
 
 var fileDescriptor_d019a68bffe14cae = []byte{
-	// 1118 bytes of a gzipped FileDescriptorProto
+	// 1139 bytes of a gzipped FileDescriptorProto
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0xdd, 0x6e, 0x1b, 0x45,
-	0x14, 0xf6, 0xda, 0x8d, 0x7f, 0x4e, 0x6c, 0x77, 0x33, 0x25, 0xd4, 0xa4, 0x2d, 0x18, 0x97, 0xaa,
-	0x91, 0x11, 0x31, 0x4a, 0x4b, 0x6f, 0x8a, 0x54, 0xd9, 0x4d, 0xa4, 0x58, 0xa2, 0x69, 0xba, 0x09,
-	0x32, 0xe2, 0x82, 0xd5, 0x78, 0x67, 0xbc, 0x1e, 0x69, 0x3d, 0xb3, 0xcc, 0x8e, 0xeb, 0xa4, 0x57,
-	0xdc, 0xf0, 0x16, 0xdc, 0xf2, 0x02, 0x70, 0x83, 0x78, 0x22, 0x5e, 0x80, 0x7b, 0x34, 0xb3, 0xbb,
-	0xb6, 0xd7, 0x36, 0x29, 0x54, 0x70, 0x37, 0xe7, 0xdb, 0x6f, 0xce, 0x9c, 0x6f, 0xce, 0xcf, 0x0e,
-	0x34, 0x5f, 0x8b, 0x40, 0x8d, 0xb1, 0x1b, 0x4a, 0xa1, 0x44, 0xd4, 0x51, 0xd4, 0x1b, 0xeb, 0xf5,
-	0x88, 0x05, 0xf4, 0xc0, 0x60, 0xa8, 0xba, 0x8c, 0xed, 0xdd, 0xf5, 0x85, 0xf0, 0x03, 0xda, 0xc1,
-	0x21, 0xeb, 0x60, 0xce, 0x85, 0xc2, 0x8a, 0x09, 0x1e, 0xc5, 0xdc, 0xd6, 0x0f, 0x79, 0xb8, 0x79,
-	0xee, 0x8d, 0x29, 0x99, 0x06, 0x54, 0x3e, 0x17, 0x7c, 0xc4, 0x7c, 0xf4, 0x05, 0x54, 0x08, 0x93,
-	0xd4, 0xd3, 0xbc, 0x86, 0xd5, 0xb4, 0xf6, 0xeb, 0x87, 0xb7, 0x0f, 0x32, 0xe7, 0x1c, 0xa5, 0x9f,
-	0x9d, 0x05, 0x13, 0x3d, 0x83, 0x1a, 0x26, 0x84, 0xe9, 0x35, 0x0e, 0xdc, 0xe1, 0xac, 0x91, 0x37,
-	0x5b, 0xf7, 0xb2, 0x5b, 0xbb, 0x73, 0x4a, 0x6f, 0xe0, 0x54, 0x17, 0x1b, 0x7a, 0x33, 0xb4, 0x07,
-	0xe5, 0x50, 0x32, 0x21, 0x99, 0xba, 0x6a, 0x14, 0x9a, 0xd6, 0x7e, 0xc9, 0x99, 0xdb, 0xe8, 0x7d,
-	0x28, 0xce, 0x28, 0xf3, 0xc7, 0xaa, 0x71, 0xc3, 0x7c, 0x49, 0x2c, 0xd4, 0x85, 0x6a, 0xa4, 0xc3,
-	0x77, 0x43, 0x11, 0x30, 0xef, 0xaa, 0xb1, 0x65, 0xce, 0xfc, 0x30, 0x7b, 0x66, 0x22, 0x90, 0x71,
-	0xff, 0xcc, 0xb0, 0x9c, 0x6d, 0xb3, 0x27, 0x36, 0x5a, 0xbf, 0x59, 0x80, 0x2e, 0x24, 0x1e, 0x8d,
-	0x98, 0x77, 0x3e, 0xc6, 0x21, 0xe3, 0x7e, 0x9f, 0x8f, 0x04, 0xb2, 0xa1, 0xe0, 0x31, 0x69, 0xf4,
-	0x97, 0x1c, 0xbd, 0x34, 0xc8, 0x30, 0x32, 0xb2, 0x34, 0x32, 0x8c, 0x34, 0x12, 0x32, 0x99, 0x04,
-	0xab, 0x97, 0x06, 0x19, 0x46, 0x49, 0x90, 0x7a, 0xa9, 0x11, 0x9f, 0x49, 0x13, 0x58, 0xc9, 0xd1,
-	0x4b, 0x74, 0x02, 0x80, 0x09, 0x71, 0x87, 0x33, 0x97, 0x71, 0xd2, 0x28, 0x9a, 0x88, 0xdb, 0xd9,
-	0x88, 0xfb, 0x7c, 0x44, 0xa5, 0xa4, 0x24, 0xbd, 0xad, 0xde, 0xa0, 0xcf, 0x09, 0xf3, 0x4c, 0xea,
-	0x9c, 0x32, 0x26, 0xa4, 0x37, 0xeb, 0x73, 0xd2, 0xfa, 0xd3, 0x02, 0x3b, 0x0d, 0x3d, 0x4d, 0xe2,
-	0xbb, 0xa6, 0xef, 0x03, 0x28, 0xe3, 0x20, 0x10, 0x9e, 0xcb, 0x48, 0x22, 0xb1, 0x64, 0xec, 0x3e,
-	0x41, 0x4f, 0xa1, 0x12, 0xa5, 0xee, 0x8d, 0xd8, 0xed, 0xc3, 0x7b, 0x1b, 0x6f, 0x38, 0x2d, 0x21,
-	0x67, 0xc1, 0x47, 0x0e, 0xbc, 0xa7, 0xe2, 0x10, 0xdd, 0x28, 0xbe, 0x5e, 0x97, 0xf1, 0x91, 0x30,
-	0x57, 0xb4, 0x7d, 0xd8, 0xcc, 0xfa, 0x59, 0xcf, 0x83, 0x83, 0xd4, 0x1a, 0xd6, 0xfa, 0xdd, 0x82,
-	0x9d, 0x55, 0xdd, 0x11, 0xba, 0x0d, 0x25, 0xc6, 0xd5, 0x48, 0x0b, 0x88, 0xb3, 0x56, 0xd4, 0x66,
-	0x9f, 0xa0, 0x5d, 0x28, 0x0a, 0x3e, 0x5d, 0x08, 0xdb, 0x12, 0x7c, 0x1a, 0xc3, 0x53, 0xce, 0x34,
-	0x1c, 0xa7, 0x6b, 0x6b, 0xca, 0x59, 0x9f, 0x68, 0x37, 0xa1, 0x90, 0xca, 0xe5, 0x22, 0x49, 0x5a,
-	0x51, 0x9b, 0xa7, 0x02, 0x1d, 0x43, 0x7d, 0xae, 0x44, 0x9f, 0x1a, 0x35, 0x0a, 0xcd, 0xc2, 0xfe,
-	0xf6, 0x6a, 0xb5, 0xad, 0x06, 0xe6, 0xd4, 0xd4, 0x12, 0x12, 0xb5, 0x9e, 0xc0, 0xee, 0x05, 0x66,
-	0xc1, 0x91, 0x14, 0xe1, 0x11, 0x8b, 0x3c, 0x2c, 0x49, 0xd2, 0x77, 0xf7, 0x00, 0xbe, 0x9f, 0xd2,
-	0x29, 0x75, 0x23, 0xf6, 0x86, 0x26, 0x12, 0x2a, 0x06, 0x39, 0x67, 0x6f, 0x68, 0xeb, 0x47, 0x0b,
-	0x6c, 0x87, 0x92, 0xec, 0x9e, 0xfb, 0x50, 0x9b, 0x30, 0xee, 0xaa, 0xb1, 0xa4, 0xd1, 0x58, 0x04,
-	0xa9, 0xf2, 0xea, 0x84, 0xf1, 0x8b, 0x14, 0x33, 0x24, 0x7c, 0xb9, 0x44, 0xca, 0x27, 0x24, 0x7c,
-	0xb9, 0x20, 0x3d, 0x84, 0x9b, 0x9a, 0x14, 0x4a, 0x31, 0xc4, 0x43, 0x16, 0x2c, 0x9a, 0xb0, 0x3e,
-	0xc1, 0x97, 0x67, 0x0b, 0xb4, 0xf5, 0xab, 0x05, 0x3b, 0x83, 0xb5, 0x40, 0x1e, 0xc3, 0x96, 0x2f,
-	0x29, 0x8d, 0x2b, 0x6e, 0xed, 0x4e, 0x56, 0xe9, 0x4e, 0x4c, 0x46, 0x4f, 0xa0, 0x78, 0x45, 0x83,
-	0x40, 0xc4, 0xc3, 0xe2, 0xed, 0xdb, 0x12, 0x36, 0xfa, 0x1c, 0x0a, 0x92, 0x92, 0xa4, 0x16, 0xdf,
-	0xb6, 0x49, 0x53, 0x5b, 0x7f, 0xe4, 0xa1, 0x96, 0x8d, 0xb8, 0x07, 0x75, 0x12, 0x03, 0xe9, 0xf0,
-	0x88, 0x9b, 0xe5, 0xce, 0x6a, 0xb3, 0x18, 0x4e, 0x32, 0x39, 0x6a, 0x64, 0xd9, 0x44, 0xdf, 0x41,
-	0x43, 0x61, 0x16, 0xb8, 0x44, 0x8a, 0xd0, 0x4d, 0xbd, 0x79, 0xc6, 0x7f, 0xa2, 0xe8, 0xfe, 0x4a,
-	0x71, 0x6c, 0xca, 0xfc, 0x49, 0xce, 0xd9, 0x55, 0x1b, 0x4b, 0xe2, 0x14, 0x90, 0xa4, 0x64, 0xd5,
-	0xf3, 0x3f, 0x92, 0x7d, 0x92, 0x73, 0x6c, 0xb9, 0x9a, 0xa5, 0x57, 0x70, 0x6b, 0xb6, 0xc1, 0x61,
-	0xdc, 0x8b, 0x1f, 0x65, 0x1d, 0x0e, 0x36, 0x78, 0xdc, 0x99, 0xad, 0xba, 0xec, 0xd9, 0x8b, 0x6b,
-	0x8c, 0xbd, 0xb5, 0x7e, 0x2e, 0x40, 0x35, 0x69, 0x82, 0x57, 0xba, 0x7a, 0xdf, 0x75, 0x22, 0xdd,
-	0x03, 0xf0, 0xe9, 0xc4, 0xf4, 0xe2, 0xbc, 0x75, 0x2b, 0x09, 0xd2, 0x27, 0x7a, 0x60, 0x85, 0x43,
-	0xa6, 0xdc, 0x09, 0x0e, 0xcd, 0x8d, 0x54, 0x9c, 0x92, 0xb6, 0x5f, 0xe0, 0x10, 0x3d, 0x80, 0x3a,
-	0xa6, 0x91, 0x4b, 0xb9, 0x27, 0xaf, 0x42, 0x73, 0xaa, 0x56, 0x58, 0x76, 0x6a, 0x98, 0x46, 0xc7,
-	0x73, 0xf0, 0x3f, 0xf8, 0x79, 0x64, 0xfe, 0x59, 0xc5, 0xbf, 0xfd, 0x67, 0x95, 0x32, 0xff, 0xac,
-	0xf5, 0xc2, 0x2b, 0xff, 0xeb, 0xc2, 0xeb, 0xad, 0xde, 0x7a, 0xa3, 0x62, 0x72, 0xb8, 0xd9, 0x47,
-	0xd2, 0x08, 0xa9, 0x8f, 0xd8, 0x6c, 0xfd, 0x62, 0x41, 0x6d, 0x39, 0x4f, 0xff, 0xff, 0x04, 0xed,
-	0x2e, 0x26, 0xa8, 0x99, 0x6b, 0x51, 0xa3, 0x68, 0x26, 0xe8, 0xde, 0xc6, 0x09, 0x6a, 0x82, 0x9a,
-	0x4f, 0xcf, 0x38, 0xc4, 0xf6, 0x97, 0x50, 0x99, 0x17, 0x0b, 0xaa, 0x42, 0xf9, 0xeb, 0xb3, 0xf3,
-	0x0b, 0xe7, 0xb8, 0xfb, 0xc2, 0xce, 0xa1, 0x3a, 0xc0, 0xd1, 0xcb, 0xc1, 0x69, 0x62, 0x5b, 0x68,
-	0x07, 0x6a, 0xbd, 0xfe, 0x51, 0xdf, 0x39, 0x7e, 0x7e, 0xd1, 0x7f, 0x79, 0xda, 0xfd, 0xca, 0xce,
-	0xb7, 0x9f, 0x82, 0xbd, 0x9a, 0x4f, 0x54, 0x82, 0xc2, 0xc0, 0x71, 0xec, 0x1c, 0x42, 0x50, 0x3f,
-	0x57, 0x92, 0x79, 0xea, 0x2c, 0xc9, 0xa0, 0x6d, 0x21, 0x80, 0xe2, 0xc9, 0xd5, 0x50, 0x32, 0x62,
-	0xe7, 0xdb, 0x1c, 0xaa, 0xcb, 0xaf, 0x17, 0xb4, 0x0b, 0x3b, 0xcb, 0xb6, 0x7b, 0x2a, 0x38, 0xb5,
-	0x73, 0xe8, 0x16, 0xdc, 0xcc, 0xc2, 0x5d, 0xdb, 0x42, 0x77, 0xe0, 0x76, 0x06, 0xec, 0xd1, 0x48,
-	0x1d, 0x8f, 0x46, 0x42, 0x2a, 0x3b, 0xbf, 0xe6, 0xa8, 0x3b, 0x55, 0xc2, 0x2e, 0xb4, 0x9f, 0xcd,
-	0x27, 0x56, 0x12, 0x69, 0x15, 0xca, 0xe9, 0xfc, 0xb0, 0x73, 0xa8, 0x06, 0x95, 0xc1, 0xdc, 0xb4,
-	0xb4, 0x0c, 0x87, 0x12, 0x3b, 0x8f, 0xca, 0x70, 0x43, 0xb7, 0xae, 0x5d, 0x68, 0xff, 0x64, 0xc1,
-	0xdd, 0xeb, 0x5e, 0x12, 0xe8, 0x01, 0x7c, 0x7c, 0xdd, 0xf7, 0x54, 0xd1, 0x3e, 0x7c, 0x72, 0x2d,
-	0xad, 0x1b, 0x45, 0x53, 0x49, 0x89, 0x6d, 0xa1, 0x4f, 0xe1, 0xe1, 0xb5, 0xcc, 0x65, 0xd9, 0xbd,
-	0x6f, 0xa0, 0x29, 0xa4, 0x7f, 0x20, 0x42, 0xca, 0x3d, 0x21, 0xc9, 0x41, 0xfc, 0xb0, 0xcd, 0x94,
-	0xc2, 0xb7, 0x8f, 0x7d, 0xa6, 0xc6, 0xd3, 0xe1, 0x81, 0x27, 0x26, 0x9d, 0x94, 0xd8, 0x89, 0x89,
-	0x9f, 0x25, 0x2f, 0xe0, 0xd7, 0x8f, 0x3a, 0xbe, 0xc8, 0xbc, 0x83, 0x87, 0x45, 0xf3, 0xe9, 0xd1,
-	0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x31, 0x2e, 0x0c, 0xef, 0x2c, 0x0b, 0x00, 0x00,
+	0x14, 0xf6, 0xda, 0x8d, 0x7f, 0x4e, 0x6c, 0x67, 0x33, 0x25, 0xc4, 0xa4, 0x0d, 0x18, 0x97, 0xd2,
+	0xc8, 0x88, 0x18, 0x85, 0xd0, 0x9b, 0x22, 0x55, 0x76, 0x13, 0x29, 0x2b, 0xd1, 0x34, 0xdd, 0x04,
+	0x19, 0x71, 0xc1, 0x6a, 0xbd, 0x33, 0x5e, 0x8f, 0xb4, 0x9e, 0x59, 0x66, 0xc7, 0x75, 0xd2, 0x2b,
+	0x6e, 0x78, 0x0b, 0xb8, 0xe4, 0x09, 0xb8, 0x41, 0x3c, 0x0a, 0x4f, 0xc0, 0x63, 0xa0, 0x99, 0xdd,
+	0xb5, 0xbd, 0xb6, 0x49, 0xa1, 0x82, 0xbb, 0x39, 0xdf, 0x7e, 0xe7, 0xcc, 0xf9, 0x9f, 0x85, 0xe6,
+	0x2b, 0x1e, 0xc8, 0x91, 0xeb, 0x84, 0x82, 0x4b, 0x1e, 0x75, 0x24, 0xf1, 0x46, 0xea, 0x3c, 0xa4,
+	0x01, 0x39, 0xd4, 0x18, 0xaa, 0x2e, 0x62, 0x7b, 0xf7, 0x7d, 0xce, 0xfd, 0x80, 0x74, 0xdc, 0x90,
+	0x76, 0x5c, 0xc6, 0xb8, 0x74, 0x25, 0xe5, 0x2c, 0x8a, 0xb9, 0xad, 0x1f, 0xf2, 0xb0, 0x75, 0xe9,
+	0x8d, 0x08, 0x9e, 0x04, 0x44, 0x3c, 0xe3, 0x6c, 0x48, 0x7d, 0xf4, 0x05, 0x54, 0x30, 0x15, 0xc4,
+	0x53, 0xbc, 0x86, 0xd1, 0x34, 0x0e, 0xea, 0x47, 0xbb, 0x87, 0x99, 0x7b, 0x4e, 0xd2, 0xcf, 0xf6,
+	0x9c, 0x89, 0x9e, 0x42, 0xcd, 0xc5, 0x98, 0xaa, 0xb3, 0x1b, 0x38, 0x83, 0x69, 0x23, 0xaf, 0x55,
+	0xf7, 0xb2, 0xaa, 0xdd, 0x19, 0xa5, 0xd7, 0xb7, 0xab, 0x73, 0x85, 0xde, 0x14, 0xed, 0x41, 0x39,
+	0x14, 0x94, 0x0b, 0x2a, 0x6f, 0x1a, 0x85, 0xa6, 0x71, 0x50, 0xb2, 0x67, 0x32, 0x7a, 0x17, 0x8a,
+	0x53, 0x42, 0xfd, 0x91, 0x6c, 0xdc, 0xd1, 0x5f, 0x12, 0x09, 0x75, 0xa1, 0x1a, 0x29, 0xf7, 0x9d,
+	0x90, 0x07, 0xd4, 0xbb, 0x69, 0x6c, 0xe8, 0x3b, 0xdf, 0xcf, 0xde, 0x99, 0x04, 0x48, 0x99, 0x7f,
+	0xa1, 0x59, 0xf6, 0xa6, 0xd6, 0x89, 0x85, 0xd6, 0x6f, 0x06, 0xa0, 0x2b, 0xe1, 0x0e, 0x87, 0xd4,
+	0xbb, 0x1c, 0xb9, 0x21, 0x65, 0xbe, 0xc5, 0x86, 0x1c, 0x99, 0x50, 0xf0, 0xa8, 0xd0, 0xf1, 0x97,
+	0x6c, 0x75, 0xd4, 0xc8, 0x20, 0xd2, 0x61, 0x29, 0x64, 0x10, 0x29, 0x24, 0xa4, 0x22, 0x71, 0x56,
+	0x1d, 0x35, 0x32, 0x88, 0x12, 0x27, 0xd5, 0x51, 0x21, 0x3e, 0x15, 0xda, 0xb1, 0x92, 0xad, 0x8e,
+	0xe8, 0x0c, 0xc0, 0xc5, 0xd8, 0x19, 0x4c, 0x1d, 0xca, 0x70, 0xa3, 0xa8, 0x3d, 0x6e, 0x67, 0x3d,
+	0xb6, 0xd8, 0x90, 0x08, 0x41, 0x70, 0x9a, 0xad, 0x5e, 0xdf, 0x62, 0x98, 0x7a, 0xba, 0x74, 0x76,
+	0xd9, 0xc5, 0xb8, 0x37, 0xb5, 0x18, 0x6e, 0xfd, 0x9c, 0x07, 0x33, 0x75, 0x3d, 0x2d, 0xe2, 0xdb,
+	0x96, 0xef, 0x3d, 0x28, 0xbb, 0x41, 0xc0, 0x3d, 0x87, 0xe2, 0x24, 0xc4, 0x92, 0x96, 0x2d, 0x8c,
+	0x9e, 0x40, 0x25, 0x4a, 0xcd, 0xeb, 0x60, 0x37, 0x8f, 0xf6, 0xd7, 0x66, 0x38, 0x6d, 0x21, 0x7b,
+	0xce, 0x47, 0x36, 0xbc, 0x23, 0x63, 0x17, 0x9d, 0x28, 0x4e, 0xaf, 0x43, 0xd9, 0x90, 0xeb, 0x14,
+	0x6d, 0x1e, 0x35, 0xb3, 0x76, 0x56, 0xeb, 0x60, 0x23, 0xb9, 0x5a, 0x9b, 0x8f, 0x61, 0x6b, 0x51,
+	0x4d, 0xb9, 0x1c, 0xe7, 0xb7, 0xa6, 0xe0, 0x8b, 0x18, 0xb5, 0x70, 0xeb, 0x77, 0x03, 0xb6, 0x97,
+	0xf3, 0x13, 0xa1, 0x5d, 0x28, 0x51, 0x26, 0x87, 0x4a, 0x2b, 0xae, 0x6e, 0x51, 0x89, 0x16, 0x46,
+	0x3b, 0x50, 0xe4, 0x6c, 0x32, 0x4f, 0xc0, 0x06, 0x67, 0x93, 0x18, 0x9e, 0x30, 0xaa, 0xe0, 0xb8,
+	0xac, 0x1b, 0x13, 0x46, 0x2d, 0xac, 0xcc, 0x84, 0x5c, 0x48, 0x87, 0xf1, 0xe4, 0xf2, 0xa2, 0x12,
+	0xcf, 0x39, 0x3a, 0x85, 0xfa, 0x2c, 0x62, 0x75, 0x6b, 0xd4, 0x28, 0x34, 0x0b, 0x07, 0x9b, 0xcb,
+	0x5d, 0xb9, 0xec, 0x98, 0x5d, 0x93, 0x0b, 0x48, 0xd4, 0x7a, 0x0c, 0x3b, 0x57, 0x2e, 0x0d, 0x4e,
+	0x04, 0x0f, 0x4f, 0x68, 0xe4, 0xb9, 0x02, 0x27, 0xf3, 0xb9, 0x0f, 0xf0, 0xfd, 0x84, 0x4c, 0x88,
+	0x13, 0xd1, 0xd7, 0x24, 0x09, 0xa1, 0xa2, 0x91, 0x4b, 0xfa, 0x9a, 0xb4, 0x7e, 0x34, 0xc0, 0xb4,
+	0x09, 0xce, 0xea, 0x3c, 0x80, 0xda, 0x98, 0x32, 0x47, 0x8e, 0x04, 0x89, 0x46, 0x3c, 0x48, 0x23,
+	0xaf, 0x8e, 0x29, 0xbb, 0x4a, 0x31, 0x4d, 0x72, 0xaf, 0x17, 0x48, 0xf9, 0x84, 0xe4, 0x5e, 0xcf,
+	0x49, 0x8f, 0x60, 0x4b, 0x91, 0x42, 0xc1, 0x07, 0xee, 0x80, 0x06, 0xf3, 0x61, 0xad, 0x8f, 0xdd,
+	0xeb, 0x8b, 0x39, 0xda, 0xfa, 0xd5, 0x80, 0xed, 0xfe, 0x8a, 0x23, 0xc7, 0xb0, 0xe1, 0x0b, 0x42,
+	0xe2, 0xce, 0x5c, 0xc9, 0xc9, 0x32, 0xdd, 0x8e, 0xc9, 0xe8, 0x31, 0x14, 0x6f, 0x48, 0x10, 0xf0,
+	0x78, 0xa9, 0xbc, 0x59, 0x2d, 0x61, 0xa3, 0xcf, 0xa0, 0x20, 0x08, 0x4e, 0x7a, 0xf6, 0x4d, 0x4a,
+	0x8a, 0xda, 0xfa, 0x33, 0x0f, 0xb5, 0xac, 0xc7, 0x3d, 0xa8, 0xe3, 0x18, 0x48, 0x97, 0x4c, 0x3c,
+	0x54, 0xf7, 0x96, 0x87, 0x4a, 0x73, 0x92, 0x0d, 0x53, 0xc3, 0x8b, 0x22, 0xfa, 0x0e, 0x1a, 0xd2,
+	0xa5, 0x81, 0x83, 0x05, 0x0f, 0x9d, 0xd4, 0x9a, 0xa7, 0xed, 0x27, 0x11, 0x3d, 0x58, 0x6a, 0x8e,
+	0x75, 0x95, 0x3f, 0xcb, 0xd9, 0x3b, 0x72, 0x6d, 0x4b, 0x9c, 0x03, 0x12, 0x04, 0x2f, 0x5b, 0xfe,
+	0x47, 0x61, 0x9f, 0xe5, 0x6c, 0x53, 0x2c, 0x57, 0xe9, 0x25, 0xdc, 0x9d, 0xae, 0x31, 0x18, 0xcf,
+	0xec, 0x07, 0x59, 0x83, 0xfd, 0x35, 0x16, 0xb7, 0xa7, 0xcb, 0x26, 0x7b, 0xe6, 0x3c, 0x8d, 0xb1,
+	0xb5, 0xd6, 0x2f, 0x05, 0xa8, 0x26, 0x43, 0xf0, 0x52, 0x75, 0xef, 0xdb, 0x6e, 0xae, 0x7d, 0x00,
+	0x9f, 0x8c, 0xf5, 0x2c, 0xce, 0x46, 0xb7, 0x92, 0x20, 0x16, 0x56, 0x8b, 0x2d, 0x1c, 0x50, 0xe9,
+	0x8c, 0xdd, 0x50, 0x67, 0xa4, 0x62, 0x97, 0x94, 0xfc, 0xdc, 0x0d, 0xd1, 0x43, 0xa8, 0xbb, 0x24,
+	0x72, 0x08, 0xf3, 0xc4, 0x4d, 0xa8, 0x6f, 0x55, 0x11, 0x96, 0xed, 0x9a, 0x4b, 0xa2, 0xd3, 0x19,
+	0xf8, 0x1f, 0x3c, 0x32, 0x99, 0xb7, 0xad, 0xf8, 0xb7, 0x6f, 0x5b, 0x29, 0xf3, 0xb6, 0xad, 0x36,
+	0x5e, 0xf9, 0x5f, 0x37, 0x5e, 0x6f, 0x39, 0xeb, 0x8d, 0x8a, 0xae, 0xe1, 0x7a, 0x1b, 0xc9, 0x20,
+	0xa4, 0x36, 0x62, 0xb1, 0xf5, 0x87, 0x01, 0xb5, 0xc5, 0x3a, 0xfd, 0xff, 0x1b, 0xb4, 0x3b, 0xdf,
+	0xa0, 0x7a, 0xaf, 0x45, 0x8d, 0xa2, 0xde, 0xa0, 0x7b, 0x6b, 0x37, 0xa8, 0x76, 0x6a, 0xb6, 0x3d,
+	0x13, 0x17, 0xd7, 0x3c, 0x11, 0xa5, 0x35, 0x4f, 0x44, 0xfb, 0x4b, 0xa8, 0xcc, 0x9a, 0x0a, 0x55,
+	0xa1, 0xfc, 0xf5, 0xc5, 0xe5, 0x95, 0x7d, 0xda, 0x7d, 0x6e, 0xe6, 0x50, 0x1d, 0xe0, 0xe4, 0x45,
+	0xff, 0x3c, 0x91, 0x0d, 0xb4, 0x0d, 0xb5, 0x9e, 0x75, 0x62, 0xd9, 0xa7, 0xcf, 0xae, 0xac, 0x17,
+	0xe7, 0xdd, 0xaf, 0xcc, 0x7c, 0xfb, 0x09, 0x98, 0xcb, 0x75, 0x47, 0x25, 0x28, 0xf4, 0x6d, 0xdb,
+	0xcc, 0x21, 0x04, 0xf5, 0x4b, 0x29, 0xa8, 0x27, 0x2f, 0x92, 0x4a, 0x9b, 0x06, 0x02, 0x28, 0x9e,
+	0xdd, 0x0c, 0x04, 0xc5, 0x66, 0xbe, 0xcd, 0xa0, 0xba, 0xf8, 0x37, 0x84, 0x76, 0x60, 0x7b, 0x51,
+	0x76, 0xce, 0x39, 0x23, 0x66, 0x0e, 0xdd, 0x85, 0xad, 0x2c, 0xdc, 0x35, 0x0d, 0x74, 0x0f, 0x76,
+	0x33, 0x60, 0x8f, 0x44, 0xf2, 0x74, 0x38, 0xe4, 0x42, 0x9a, 0xf9, 0x15, 0x43, 0xdd, 0x89, 0xe4,
+	0x66, 0xa1, 0xfd, 0x74, 0xb6, 0xd9, 0x12, 0x4f, 0xab, 0x50, 0x4e, 0xf7, 0x8c, 0x99, 0x43, 0x35,
+	0xa8, 0xf4, 0x67, 0xa2, 0xa1, 0xc2, 0xb0, 0x09, 0x36, 0xf3, 0xa8, 0x0c, 0x77, 0xd4, 0x88, 0x9b,
+	0x85, 0xf6, 0x4f, 0x06, 0xdc, 0xbf, 0xed, 0xcf, 0x04, 0x3d, 0x84, 0x0f, 0x6f, 0xfb, 0x9e, 0x46,
+	0x74, 0x00, 0x1f, 0xdd, 0x4a, 0xeb, 0x46, 0xd1, 0x44, 0x10, 0x6c, 0x1a, 0xe8, 0x13, 0x78, 0x74,
+	0x2b, 0x73, 0x31, 0xec, 0xde, 0x37, 0xd0, 0xe4, 0xc2, 0x3f, 0xe4, 0x21, 0x61, 0x1e, 0x17, 0xf8,
+	0x30, 0xfe, 0x51, 0xce, 0xb4, 0xcc, 0xb7, 0xc7, 0x3e, 0x95, 0xa3, 0xc9, 0xe0, 0xd0, 0xe3, 0xe3,
+	0x4e, 0x4a, 0xec, 0xc4, 0xc4, 0x4f, 0x93, 0x3f, 0xea, 0x57, 0xc7, 0x1d, 0x9f, 0x67, 0xfe, 0xab,
+	0x07, 0x45, 0xfd, 0xe9, 0xf3, 0xbf, 0x02, 0x00, 0x00, 0xff, 0xff, 0x1e, 0x89, 0x67, 0x3b, 0x7c,
+	0x0b, 0x00, 0x00,
 }
diff --git a/vendor/github.com/opentracing/opentracing-go/.gitignore b/vendor/github.com/opentracing/opentracing-go/.gitignore
new file mode 100644
index 0000000..c57100a
--- /dev/null
+++ b/vendor/github.com/opentracing/opentracing-go/.gitignore
@@ -0,0 +1 @@
+coverage.txt
diff --git a/vendor/github.com/opentracing/opentracing-go/.travis.yml b/vendor/github.com/opentracing/opentracing-go/.travis.yml
new file mode 100644
index 0000000..8d5b75e
--- /dev/null
+++ b/vendor/github.com/opentracing/opentracing-go/.travis.yml
@@ -0,0 +1,20 @@
+language: go
+
+matrix:
+  include:
+  - go: "1.11.x"
+  - go: "1.12.x"
+  - go: "tip"
+    env:
+    - LINT=true
+    - COVERAGE=true
+
+install:
+  - if [ "$LINT" == true ]; then go get -u golang.org/x/lint/golint/... ; else echo 'skipping lint'; fi
+  - go get -u github.com/stretchr/testify/...
+
+script:
+  - make test
+  - go build ./...
+  - if [ "$LINT" == true ]; then make lint ; else echo 'skipping lint'; fi
+  - if [ "$COVERAGE" == true ]; then make cover && bash <(curl -s https://codecov.io/bash) ; else echo 'skipping coverage'; fi
diff --git a/vendor/github.com/opentracing/opentracing-go/CHANGELOG.md b/vendor/github.com/opentracing/opentracing-go/CHANGELOG.md
new file mode 100644
index 0000000..7c14feb
--- /dev/null
+++ b/vendor/github.com/opentracing/opentracing-go/CHANGELOG.md
@@ -0,0 +1,46 @@
+Changes by Version
+==================
+
+1.1.0 (2019-03-23)
+-------------------
+
+Notable changes:
+- The library is now released under Apache 2.0 license
+- Use Set() instead of Add() in HTTPHeadersCarrier is functionally a breaking change (fixes issue [#159](https://github.com/opentracing/opentracing-go/issues/159))
+- 'golang.org/x/net/context' is replaced with 'context' from the standard library
+
+List of all changes:
+
+- Export StartSpanFromContextWithTracer (#214) <Aaron Delaney>
+- Add IsGlobalTracerRegistered() to indicate if a tracer has been registered (#201) <Mike Goldsmith>
+- Use Set() instead of Add() in HTTPHeadersCarrier (#191) <jeremyxu2010>
+- Update license to Apache 2.0 (#181) <Andrea Kao>
+- Replace 'golang.org/x/net/context' with 'context' (#176) <Tony Ghita>
+- Port of Python opentracing/harness/api_check.py to Go (#146) <chris erway>
+- Fix race condition in MockSpan.Context() (#170) <Brad>
+- Add PeerHostIPv4.SetString() (#155)  <NeoCN>
+- Add a Noop log field type to log to allow for optional fields (#150)  <Matt Ho>
+
+
+1.0.2 (2017-04-26)
+-------------------
+
+- Add more semantic tags (#139) <Rustam Zagirov>
+
+
+1.0.1 (2017-02-06)
+-------------------
+
+- Correct spelling in comments <Ben Sigelman>
+- Address race in nextMockID() (#123) <bill fumerola>
+- log: avoid panic marshaling nil error (#131) <Anthony Voutas>
+- Deprecate InitGlobalTracer in favor of SetGlobalTracer (#128) <Yuri Shkuro>
+- Drop Go 1.5 that fails in Travis (#129) <Yuri Shkuro>
+- Add convenience methods Key() and Value() to log.Field <Ben Sigelman>
+- Add convenience methods to log.Field (2 years, 6 months ago) <Radu Berinde>
+
+1.0.0 (2016-09-26)
+-------------------
+
+- This release implements OpenTracing Specification 1.0 (https://opentracing.io/spec)
+
diff --git a/vendor/github.com/opentracing/opentracing-go/LICENSE b/vendor/github.com/opentracing/opentracing-go/LICENSE
new file mode 100644
index 0000000..f002734
--- /dev/null
+++ b/vendor/github.com/opentracing/opentracing-go/LICENSE
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright 2016 The OpenTracing Authors
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/vendor/github.com/opentracing/opentracing-go/Makefile b/vendor/github.com/opentracing/opentracing-go/Makefile
new file mode 100644
index 0000000..62abb63
--- /dev/null
+++ b/vendor/github.com/opentracing/opentracing-go/Makefile
@@ -0,0 +1,20 @@
+.DEFAULT_GOAL := test-and-lint
+
+.PHONY: test-and-lint
+test-and-lint: test lint
+
+.PHONY: test
+test:
+	go test -v -cover -race ./...
+
+.PHONY: cover
+cover:
+	go test -v -coverprofile=coverage.txt -covermode=atomic -race ./...
+
+.PHONY: lint
+lint:
+	go fmt ./...
+	golint ./...
+	@# Run again with magic to exit non-zero if golint outputs anything.
+	@! (golint ./... | read dummy)
+	go vet ./...
diff --git a/vendor/github.com/opentracing/opentracing-go/README.md b/vendor/github.com/opentracing/opentracing-go/README.md
new file mode 100644
index 0000000..6ef1d7c
--- /dev/null
+++ b/vendor/github.com/opentracing/opentracing-go/README.md
@@ -0,0 +1,171 @@
+[![Gitter chat](http://img.shields.io/badge/gitter-join%20chat%20%E2%86%92-brightgreen.svg)](https://gitter.im/opentracing/public) [![Build Status](https://travis-ci.org/opentracing/opentracing-go.svg?branch=master)](https://travis-ci.org/opentracing/opentracing-go) [![GoDoc](https://godoc.org/github.com/opentracing/opentracing-go?status.svg)](http://godoc.org/github.com/opentracing/opentracing-go)
+[![Sourcegraph Badge](https://sourcegraph.com/github.com/opentracing/opentracing-go/-/badge.svg)](https://sourcegraph.com/github.com/opentracing/opentracing-go?badge)
+
+# OpenTracing API for Go
+
+This package is a Go platform API for OpenTracing.
+
+## Required Reading
+
+In order to understand the Go platform API, one must first be familiar with the
+[OpenTracing project](https://opentracing.io) and
+[terminology](https://opentracing.io/specification/) more specifically.
+
+## API overview for those adding instrumentation
+
+Everyday consumers of this `opentracing` package really only need to worry
+about a couple of key abstractions: the `StartSpan` function, the `Span`
+interface, and binding a `Tracer` at `main()`-time. Here are code snippets
+demonstrating some important use cases.
+
+#### Singleton initialization
+
+The simplest starting point is `./default_tracer.go`. As early as possible, call
+
+```go
+    import "github.com/opentracing/opentracing-go"
+    import ".../some_tracing_impl"
+
+    func main() {
+        opentracing.SetGlobalTracer(
+            // tracing impl specific:
+            some_tracing_impl.New(...),
+        )
+        ...
+    }
+```
+
+#### Non-Singleton initialization
+
+If you prefer direct control to singletons, manage ownership of the
+`opentracing.Tracer` implementation explicitly.
+
+#### Creating a Span given an existing Go `context.Context`
+
+If you use `context.Context` in your application, OpenTracing's Go library will
+happily rely on it for `Span` propagation. To start a new (blocking child)
+`Span`, you can use `StartSpanFromContext`.
+
+```go
+    func xyz(ctx context.Context, ...) {
+        ...
+        span, ctx := opentracing.StartSpanFromContext(ctx, "operation_name")
+        defer span.Finish()
+        span.LogFields(
+            log.String("event", "soft error"),
+            log.String("type", "cache timeout"),
+            log.Int("waited.millis", 1500))
+        ...
+    }
+```
+
+#### Starting an empty trace by creating a "root span"
+
+It's always possible to create a "root" `Span` with no parent or other causal
+reference.
+
+```go
+    func xyz() {
+        ...
+        sp := opentracing.StartSpan("operation_name")
+        defer sp.Finish()
+        ...
+    }
+```
+
+#### Creating a (child) Span given an existing (parent) Span
+
+```go
+    func xyz(parentSpan opentracing.Span, ...) {
+        ...
+        sp := opentracing.StartSpan(
+            "operation_name",
+            opentracing.ChildOf(parentSpan.Context()))
+        defer sp.Finish()
+        ...
+    }
+```
+
+#### Serializing to the wire
+
+```go
+    func makeSomeRequest(ctx context.Context) ... {
+        if span := opentracing.SpanFromContext(ctx); span != nil {
+            httpClient := &http.Client{}
+            httpReq, _ := http.NewRequest("GET", "http://myservice/", nil)
+
+            // Transmit the span's TraceContext as HTTP headers on our
+            // outbound request.
+            opentracing.GlobalTracer().Inject(
+                span.Context(),
+                opentracing.HTTPHeaders,
+                opentracing.HTTPHeadersCarrier(httpReq.Header))
+
+            resp, err := httpClient.Do(httpReq)
+            ...
+        }
+        ...
+    }
+```
+
+#### Deserializing from the wire
+
+```go
+    http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
+        var serverSpan opentracing.Span
+        appSpecificOperationName := ...
+        wireContext, err := opentracing.GlobalTracer().Extract(
+            opentracing.HTTPHeaders,
+            opentracing.HTTPHeadersCarrier(req.Header))
+        if err != nil {
+            // Optionally record something about err here
+        }
+
+        // Create the span referring to the RPC client if available.
+        // If wireContext == nil, a root span will be created.
+        serverSpan = opentracing.StartSpan(
+            appSpecificOperationName,
+            ext.RPCServerOption(wireContext))
+
+        defer serverSpan.Finish()
+
+        ctx := opentracing.ContextWithSpan(context.Background(), serverSpan)
+        ...
+    }
+```
+
+#### Conditionally capture a field using `log.Noop`
+
+In some situations, you may want to dynamically decide whether or not
+to log a field.  For example, you may want to capture additional data,
+such as a customer ID, in non-production environments:
+
+```go
+    func Customer(order *Order) log.Field {
+        if os.Getenv("ENVIRONMENT") == "dev" {
+            return log.String("customer", order.Customer.ID)
+        }
+        return log.Noop()
+    }
+```
+
+#### Goroutine-safety
+
+The entire public API is goroutine-safe and does not require external
+synchronization.
+
+## API pointers for those implementing a tracing system
+
+Tracing system implementors may be able to reuse or copy-paste-modify the `basictracer` package, found [here](https://github.com/opentracing/basictracer-go). In particular, see `basictracer.New(...)`.
+
+## API compatibility
+
+For the time being, "mild" backwards-incompatible changes may be made without changing the major version number. As OpenTracing and `opentracing-go` mature, backwards compatibility will become more of a priority.
+
+## Tracer test suite
+
+A test suite is available in the [harness](https://godoc.org/github.com/opentracing/opentracing-go/harness) package that can assist Tracer implementors to assert that their Tracer is working correctly.
+
+## Licensing
+
+[Apache 2.0 License](./LICENSE).
diff --git a/vendor/github.com/opentracing/opentracing-go/ext/tags.go b/vendor/github.com/opentracing/opentracing-go/ext/tags.go
new file mode 100644
index 0000000..52e8895
--- /dev/null
+++ b/vendor/github.com/opentracing/opentracing-go/ext/tags.go
@@ -0,0 +1,210 @@
+package ext
+
+import "github.com/opentracing/opentracing-go"
+
+// These constants define common tag names recommended for better portability across
+// tracing systems and languages/platforms.
+//
+// The tag names are defined as typed strings, so that in addition to the usual use
+//
+//     span.setTag(TagName, value)
+//
+// they also support value type validation via this additional syntax:
+//
+//    TagName.Set(span, value)
+//
+var (
+	//////////////////////////////////////////////////////////////////////
+	// SpanKind (client/server or producer/consumer)
+	//////////////////////////////////////////////////////////////////////
+
+	// SpanKind hints at relationship between spans, e.g. client/server
+	SpanKind = spanKindTagName("span.kind")
+
+	// SpanKindRPCClient marks a span representing the client-side of an RPC
+	// or other remote call
+	SpanKindRPCClientEnum = SpanKindEnum("client")
+	SpanKindRPCClient     = opentracing.Tag{Key: string(SpanKind), Value: SpanKindRPCClientEnum}
+
+	// SpanKindRPCServer marks a span representing the server-side of an RPC
+	// or other remote call
+	SpanKindRPCServerEnum = SpanKindEnum("server")
+	SpanKindRPCServer     = opentracing.Tag{Key: string(SpanKind), Value: SpanKindRPCServerEnum}
+
+	// SpanKindProducer marks a span representing the producer-side of a
+	// message bus
+	SpanKindProducerEnum = SpanKindEnum("producer")
+	SpanKindProducer     = opentracing.Tag{Key: string(SpanKind), Value: SpanKindProducerEnum}
+
+	// SpanKindConsumer marks a span representing the consumer-side of a
+	// message bus
+	SpanKindConsumerEnum = SpanKindEnum("consumer")
+	SpanKindConsumer     = opentracing.Tag{Key: string(SpanKind), Value: SpanKindConsumerEnum}
+
+	//////////////////////////////////////////////////////////////////////
+	// Component name
+	//////////////////////////////////////////////////////////////////////
+
+	// Component is a low-cardinality identifier of the module, library,
+	// or package that is generating a span.
+	Component = stringTagName("component")
+
+	//////////////////////////////////////////////////////////////////////
+	// Sampling hint
+	//////////////////////////////////////////////////////////////////////
+
+	// SamplingPriority determines the priority of sampling this Span.
+	SamplingPriority = uint16TagName("sampling.priority")
+
+	//////////////////////////////////////////////////////////////////////
+	// Peer tags. These tags can be emitted by either client-side of
+	// server-side to describe the other side/service in a peer-to-peer
+	// communications, like an RPC call.
+	//////////////////////////////////////////////////////////////////////
+
+	// PeerService records the service name of the peer.
+	PeerService = stringTagName("peer.service")
+
+	// PeerAddress records the address name of the peer. This may be a "ip:port",
+	// a bare "hostname", a FQDN or even a database DSN substring
+	// like "mysql://username@127.0.0.1:3306/dbname"
+	PeerAddress = stringTagName("peer.address")
+
+	// PeerHostname records the host name of the peer
+	PeerHostname = stringTagName("peer.hostname")
+
+	// PeerHostIPv4 records IP v4 host address of the peer
+	PeerHostIPv4 = ipv4Tag("peer.ipv4")
+
+	// PeerHostIPv6 records IP v6 host address of the peer
+	PeerHostIPv6 = stringTagName("peer.ipv6")
+
+	// PeerPort records port number of the peer
+	PeerPort = uint16TagName("peer.port")
+
+	//////////////////////////////////////////////////////////////////////
+	// HTTP Tags
+	//////////////////////////////////////////////////////////////////////
+
+	// HTTPUrl should be the URL of the request being handled in this segment
+	// of the trace, in standard URI format. The protocol is optional.
+	HTTPUrl = stringTagName("http.url")
+
+	// HTTPMethod is the HTTP method of the request, and is case-insensitive.
+	HTTPMethod = stringTagName("http.method")
+
+	// HTTPStatusCode is the numeric HTTP status code (200, 404, etc) of the
+	// HTTP response.
+	HTTPStatusCode = uint16TagName("http.status_code")
+
+	//////////////////////////////////////////////////////////////////////
+	// DB Tags
+	//////////////////////////////////////////////////////////////////////
+
+	// DBInstance is database instance name.
+	DBInstance = stringTagName("db.instance")
+
+	// DBStatement is a database statement for the given database type.
+	// It can be a query or a prepared statement (i.e., before substitution).
+	DBStatement = stringTagName("db.statement")
+
+	// DBType is a database type. For any SQL database, "sql".
+	// For others, the lower-case database category, e.g. "redis"
+	DBType = stringTagName("db.type")
+
+	// DBUser is a username for accessing database.
+	DBUser = stringTagName("db.user")
+
+	//////////////////////////////////////////////////////////////////////
+	// Message Bus Tag
+	//////////////////////////////////////////////////////////////////////
+
+	// MessageBusDestination is an address at which messages can be exchanged
+	MessageBusDestination = stringTagName("message_bus.destination")
+
+	//////////////////////////////////////////////////////////////////////
+	// Error Tag
+	//////////////////////////////////////////////////////////////////////
+
+	// Error indicates that operation represented by the span resulted in an error.
+	Error = boolTagName("error")
+)
+
+// ---
+
+// SpanKindEnum represents common span types
+type SpanKindEnum string
+
+type spanKindTagName string
+
+// Set adds a string tag to the `span`
+func (tag spanKindTagName) Set(span opentracing.Span, value SpanKindEnum) {
+	span.SetTag(string(tag), value)
+}
+
+type rpcServerOption struct {
+	clientContext opentracing.SpanContext
+}
+
+func (r rpcServerOption) Apply(o *opentracing.StartSpanOptions) {
+	if r.clientContext != nil {
+		opentracing.ChildOf(r.clientContext).Apply(o)
+	}
+	SpanKindRPCServer.Apply(o)
+}
+
+// RPCServerOption returns a StartSpanOption appropriate for an RPC server span
+// with `client` representing the metadata for the remote peer Span if available.
+// In case client == nil, due to the client not being instrumented, this RPC
+// server span will be a root span.
+func RPCServerOption(client opentracing.SpanContext) opentracing.StartSpanOption {
+	return rpcServerOption{client}
+}
+
+// ---
+
+type stringTagName string
+
+// Set adds a string tag to the `span`
+func (tag stringTagName) Set(span opentracing.Span, value string) {
+	span.SetTag(string(tag), value)
+}
+
+// ---
+
+type uint32TagName string
+
+// Set adds a uint32 tag to the `span`
+func (tag uint32TagName) Set(span opentracing.Span, value uint32) {
+	span.SetTag(string(tag), value)
+}
+
+// ---
+
+type uint16TagName string
+
+// Set adds a uint16 tag to the `span`
+func (tag uint16TagName) Set(span opentracing.Span, value uint16) {
+	span.SetTag(string(tag), value)
+}
+
+// ---
+
+type boolTagName string
+
+// Add adds a bool tag to the `span`
+func (tag boolTagName) Set(span opentracing.Span, value bool) {
+	span.SetTag(string(tag), value)
+}
+
+type ipv4Tag string
+
+// Set adds IP v4 host address of the peer as an uint32 value to the `span`, keep this for backward and zipkin compatibility
+func (tag ipv4Tag) Set(span opentracing.Span, value uint32) {
+	span.SetTag(string(tag), value)
+}
+
+// SetString records IP v4 host address of the peer as a .-separated tuple to the `span`. E.g., "127.0.0.1"
+func (tag ipv4Tag) SetString(span opentracing.Span, value string) {
+	span.SetTag(string(tag), value)
+}
diff --git a/vendor/github.com/opentracing/opentracing-go/globaltracer.go b/vendor/github.com/opentracing/opentracing-go/globaltracer.go
new file mode 100644
index 0000000..4f7066a
--- /dev/null
+++ b/vendor/github.com/opentracing/opentracing-go/globaltracer.go
@@ -0,0 +1,42 @@
+package opentracing
+
+type registeredTracer struct {
+	tracer       Tracer
+	isRegistered bool
+}
+
+var (
+	globalTracer = registeredTracer{NoopTracer{}, false}
+)
+
+// SetGlobalTracer sets the [singleton] opentracing.Tracer returned by
+// GlobalTracer(). Those who use GlobalTracer (rather than directly manage an
+// opentracing.Tracer instance) should call SetGlobalTracer as early as
+// possible in main(), prior to calling the `StartSpan` global func below.
+// Prior to calling `SetGlobalTracer`, any Spans started via the `StartSpan`
+// (etc) globals are noops.
+func SetGlobalTracer(tracer Tracer) {
+	globalTracer = registeredTracer{tracer, true}
+}
+
+// GlobalTracer returns the global singleton `Tracer` implementation.
+// Before `SetGlobalTracer()` is called, the `GlobalTracer()` is a noop
+// implementation that drops all data handed to it.
+func GlobalTracer() Tracer {
+	return globalTracer.tracer
+}
+
+// StartSpan defers to `Tracer.StartSpan`. See `GlobalTracer()`.
+func StartSpan(operationName string, opts ...StartSpanOption) Span {
+	return globalTracer.tracer.StartSpan(operationName, opts...)
+}
+
+// InitGlobalTracer is deprecated. Please use SetGlobalTracer.
+func InitGlobalTracer(tracer Tracer) {
+	SetGlobalTracer(tracer)
+}
+
+// IsGlobalTracerRegistered returns a `bool` to indicate if a tracer has been globally registered
+func IsGlobalTracerRegistered() bool {
+	return globalTracer.isRegistered
+}
diff --git a/vendor/github.com/opentracing/opentracing-go/gocontext.go b/vendor/github.com/opentracing/opentracing-go/gocontext.go
new file mode 100644
index 0000000..08c00c0
--- /dev/null
+++ b/vendor/github.com/opentracing/opentracing-go/gocontext.go
@@ -0,0 +1,60 @@
+package opentracing
+
+import "context"
+
+type contextKey struct{}
+
+var activeSpanKey = contextKey{}
+
+// ContextWithSpan returns a new `context.Context` that holds a reference to
+// `span`'s SpanContext.
+func ContextWithSpan(ctx context.Context, span Span) context.Context {
+	return context.WithValue(ctx, activeSpanKey, span)
+}
+
+// SpanFromContext returns the `Span` previously associated with `ctx`, or
+// `nil` if no such `Span` could be found.
+//
+// NOTE: context.Context != SpanContext: the former is Go's intra-process
+// context propagation mechanism, and the latter houses OpenTracing's per-Span
+// identity and baggage information.
+func SpanFromContext(ctx context.Context) Span {
+	val := ctx.Value(activeSpanKey)
+	if sp, ok := val.(Span); ok {
+		return sp
+	}
+	return nil
+}
+
+// StartSpanFromContext starts and returns a Span with `operationName`, using
+// any Span found within `ctx` as a ChildOfRef. If no such parent could be
+// found, StartSpanFromContext creates a root (parentless) Span.
+//
+// The second return value is a context.Context object built around the
+// returned Span.
+//
+// Example usage:
+//
+//    SomeFunction(ctx context.Context, ...) {
+//        sp, ctx := opentracing.StartSpanFromContext(ctx, "SomeFunction")
+//        defer sp.Finish()
+//        ...
+//    }
+func StartSpanFromContext(ctx context.Context, operationName string, opts ...StartSpanOption) (Span, context.Context) {
+	return StartSpanFromContextWithTracer(ctx, GlobalTracer(), operationName, opts...)
+}
+
+// StartSpanFromContextWithTracer starts and returns a span with `operationName`
+// using  a span found within the context as a ChildOfRef. If that doesn't exist
+// it creates a root span. It also returns a context.Context object built
+// around the returned span.
+//
+// It's behavior is identical to StartSpanFromContext except that it takes an explicit
+// tracer as opposed to using the global tracer.
+func StartSpanFromContextWithTracer(ctx context.Context, tracer Tracer, operationName string, opts ...StartSpanOption) (Span, context.Context) {
+	if parentSpan := SpanFromContext(ctx); parentSpan != nil {
+		opts = append(opts, ChildOf(parentSpan.Context()))
+	}
+	span := tracer.StartSpan(operationName, opts...)
+	return span, ContextWithSpan(ctx, span)
+}
diff --git a/vendor/github.com/opentracing/opentracing-go/log/field.go b/vendor/github.com/opentracing/opentracing-go/log/field.go
new file mode 100644
index 0000000..50feea3
--- /dev/null
+++ b/vendor/github.com/opentracing/opentracing-go/log/field.go
@@ -0,0 +1,269 @@
+package log
+
+import (
+	"fmt"
+	"math"
+)
+
+type fieldType int
+
+const (
+	stringType fieldType = iota
+	boolType
+	intType
+	int32Type
+	uint32Type
+	int64Type
+	uint64Type
+	float32Type
+	float64Type
+	errorType
+	objectType
+	lazyLoggerType
+	noopType
+)
+
+// Field instances are constructed via LogBool, LogString, and so on.
+// Tracing implementations may then handle them via the Field.Marshal
+// method.
+//
+// "heavily influenced by" (i.e., partially stolen from)
+// https://github.com/uber-go/zap
+type Field struct {
+	key          string
+	fieldType    fieldType
+	numericVal   int64
+	stringVal    string
+	interfaceVal interface{}
+}
+
+// String adds a string-valued key:value pair to a Span.LogFields() record
+func String(key, val string) Field {
+	return Field{
+		key:       key,
+		fieldType: stringType,
+		stringVal: val,
+	}
+}
+
+// Bool adds a bool-valued key:value pair to a Span.LogFields() record
+func Bool(key string, val bool) Field {
+	var numericVal int64
+	if val {
+		numericVal = 1
+	}
+	return Field{
+		key:        key,
+		fieldType:  boolType,
+		numericVal: numericVal,
+	}
+}
+
+// Int adds an int-valued key:value pair to a Span.LogFields() record
+func Int(key string, val int) Field {
+	return Field{
+		key:        key,
+		fieldType:  intType,
+		numericVal: int64(val),
+	}
+}
+
+// Int32 adds an int32-valued key:value pair to a Span.LogFields() record
+func Int32(key string, val int32) Field {
+	return Field{
+		key:        key,
+		fieldType:  int32Type,
+		numericVal: int64(val),
+	}
+}
+
+// Int64 adds an int64-valued key:value pair to a Span.LogFields() record
+func Int64(key string, val int64) Field {
+	return Field{
+		key:        key,
+		fieldType:  int64Type,
+		numericVal: val,
+	}
+}
+
+// Uint32 adds a uint32-valued key:value pair to a Span.LogFields() record
+func Uint32(key string, val uint32) Field {
+	return Field{
+		key:        key,
+		fieldType:  uint32Type,
+		numericVal: int64(val),
+	}
+}
+
+// Uint64 adds a uint64-valued key:value pair to a Span.LogFields() record
+func Uint64(key string, val uint64) Field {
+	return Field{
+		key:        key,
+		fieldType:  uint64Type,
+		numericVal: int64(val),
+	}
+}
+
+// Float32 adds a float32-valued key:value pair to a Span.LogFields() record
+func Float32(key string, val float32) Field {
+	return Field{
+		key:        key,
+		fieldType:  float32Type,
+		numericVal: int64(math.Float32bits(val)),
+	}
+}
+
+// Float64 adds a float64-valued key:value pair to a Span.LogFields() record
+func Float64(key string, val float64) Field {
+	return Field{
+		key:        key,
+		fieldType:  float64Type,
+		numericVal: int64(math.Float64bits(val)),
+	}
+}
+
+// Error adds an error with the key "error" to a Span.LogFields() record
+func Error(err error) Field {
+	return Field{
+		key:          "error",
+		fieldType:    errorType,
+		interfaceVal: err,
+	}
+}
+
+// Object adds an object-valued key:value pair to a Span.LogFields() record
+func Object(key string, obj interface{}) Field {
+	return Field{
+		key:          key,
+		fieldType:    objectType,
+		interfaceVal: obj,
+	}
+}
+
+// LazyLogger allows for user-defined, late-bound logging of arbitrary data
+type LazyLogger func(fv Encoder)
+
+// Lazy adds a LazyLogger to a Span.LogFields() record; the tracing
+// implementation will call the LazyLogger function at an indefinite time in
+// the future (after Lazy() returns).
+func Lazy(ll LazyLogger) Field {
+	return Field{
+		fieldType:    lazyLoggerType,
+		interfaceVal: ll,
+	}
+}
+
+// Noop creates a no-op log field that should be ignored by the tracer.
+// It can be used to capture optional fields, for example those that should
+// only be logged in non-production environment:
+//
+//     func customerField(order *Order) log.Field {
+//          if os.Getenv("ENVIRONMENT") == "dev" {
+//              return log.String("customer", order.Customer.ID)
+//          }
+//          return log.Noop()
+//     }
+//
+//     span.LogFields(log.String("event", "purchase"), customerField(order))
+//
+func Noop() Field {
+	return Field{
+		fieldType: noopType,
+	}
+}
+
+// Encoder allows access to the contents of a Field (via a call to
+// Field.Marshal).
+//
+// Tracer implementations typically provide an implementation of Encoder;
+// OpenTracing callers typically do not need to concern themselves with it.
+type Encoder interface {
+	EmitString(key, value string)
+	EmitBool(key string, value bool)
+	EmitInt(key string, value int)
+	EmitInt32(key string, value int32)
+	EmitInt64(key string, value int64)
+	EmitUint32(key string, value uint32)
+	EmitUint64(key string, value uint64)
+	EmitFloat32(key string, value float32)
+	EmitFloat64(key string, value float64)
+	EmitObject(key string, value interface{})
+	EmitLazyLogger(value LazyLogger)
+}
+
+// Marshal passes a Field instance through to the appropriate
+// field-type-specific method of an Encoder.
+func (lf Field) Marshal(visitor Encoder) {
+	switch lf.fieldType {
+	case stringType:
+		visitor.EmitString(lf.key, lf.stringVal)
+	case boolType:
+		visitor.EmitBool(lf.key, lf.numericVal != 0)
+	case intType:
+		visitor.EmitInt(lf.key, int(lf.numericVal))
+	case int32Type:
+		visitor.EmitInt32(lf.key, int32(lf.numericVal))
+	case int64Type:
+		visitor.EmitInt64(lf.key, int64(lf.numericVal))
+	case uint32Type:
+		visitor.EmitUint32(lf.key, uint32(lf.numericVal))
+	case uint64Type:
+		visitor.EmitUint64(lf.key, uint64(lf.numericVal))
+	case float32Type:
+		visitor.EmitFloat32(lf.key, math.Float32frombits(uint32(lf.numericVal)))
+	case float64Type:
+		visitor.EmitFloat64(lf.key, math.Float64frombits(uint64(lf.numericVal)))
+	case errorType:
+		if err, ok := lf.interfaceVal.(error); ok {
+			visitor.EmitString(lf.key, err.Error())
+		} else {
+			visitor.EmitString(lf.key, "<nil>")
+		}
+	case objectType:
+		visitor.EmitObject(lf.key, lf.interfaceVal)
+	case lazyLoggerType:
+		visitor.EmitLazyLogger(lf.interfaceVal.(LazyLogger))
+	case noopType:
+		// intentionally left blank
+	}
+}
+
+// Key returns the field's key.
+func (lf Field) Key() string {
+	return lf.key
+}
+
+// Value returns the field's value as interface{}.
+func (lf Field) Value() interface{} {
+	switch lf.fieldType {
+	case stringType:
+		return lf.stringVal
+	case boolType:
+		return lf.numericVal != 0
+	case intType:
+		return int(lf.numericVal)
+	case int32Type:
+		return int32(lf.numericVal)
+	case int64Type:
+		return int64(lf.numericVal)
+	case uint32Type:
+		return uint32(lf.numericVal)
+	case uint64Type:
+		return uint64(lf.numericVal)
+	case float32Type:
+		return math.Float32frombits(uint32(lf.numericVal))
+	case float64Type:
+		return math.Float64frombits(uint64(lf.numericVal))
+	case errorType, objectType, lazyLoggerType:
+		return lf.interfaceVal
+	case noopType:
+		return nil
+	default:
+		return nil
+	}
+}
+
+// String returns a string representation of the key and value.
+func (lf Field) String() string {
+	return fmt.Sprint(lf.key, ":", lf.Value())
+}
diff --git a/vendor/github.com/opentracing/opentracing-go/log/util.go b/vendor/github.com/opentracing/opentracing-go/log/util.go
new file mode 100644
index 0000000..3832feb
--- /dev/null
+++ b/vendor/github.com/opentracing/opentracing-go/log/util.go
@@ -0,0 +1,54 @@
+package log
+
+import "fmt"
+
+// InterleavedKVToFields converts keyValues a la Span.LogKV() to a Field slice
+// a la Span.LogFields().
+func InterleavedKVToFields(keyValues ...interface{}) ([]Field, error) {
+	if len(keyValues)%2 != 0 {
+		return nil, fmt.Errorf("non-even keyValues len: %d", len(keyValues))
+	}
+	fields := make([]Field, len(keyValues)/2)
+	for i := 0; i*2 < len(keyValues); i++ {
+		key, ok := keyValues[i*2].(string)
+		if !ok {
+			return nil, fmt.Errorf(
+				"non-string key (pair #%d): %T",
+				i, keyValues[i*2])
+		}
+		switch typedVal := keyValues[i*2+1].(type) {
+		case bool:
+			fields[i] = Bool(key, typedVal)
+		case string:
+			fields[i] = String(key, typedVal)
+		case int:
+			fields[i] = Int(key, typedVal)
+		case int8:
+			fields[i] = Int32(key, int32(typedVal))
+		case int16:
+			fields[i] = Int32(key, int32(typedVal))
+		case int32:
+			fields[i] = Int32(key, typedVal)
+		case int64:
+			fields[i] = Int64(key, typedVal)
+		case uint:
+			fields[i] = Uint64(key, uint64(typedVal))
+		case uint64:
+			fields[i] = Uint64(key, typedVal)
+		case uint8:
+			fields[i] = Uint32(key, uint32(typedVal))
+		case uint16:
+			fields[i] = Uint32(key, uint32(typedVal))
+		case uint32:
+			fields[i] = Uint32(key, typedVal)
+		case float32:
+			fields[i] = Float32(key, typedVal)
+		case float64:
+			fields[i] = Float64(key, typedVal)
+		default:
+			// When in doubt, coerce to a string
+			fields[i] = String(key, fmt.Sprint(typedVal))
+		}
+	}
+	return fields, nil
+}
diff --git a/vendor/github.com/opentracing/opentracing-go/noop.go b/vendor/github.com/opentracing/opentracing-go/noop.go
new file mode 100644
index 0000000..0d32f69
--- /dev/null
+++ b/vendor/github.com/opentracing/opentracing-go/noop.go
@@ -0,0 +1,64 @@
+package opentracing
+
+import "github.com/opentracing/opentracing-go/log"
+
+// A NoopTracer is a trivial, minimum overhead implementation of Tracer
+// for which all operations are no-ops.
+//
+// The primary use of this implementation is in libraries, such as RPC
+// frameworks, that make tracing an optional feature controlled by the
+// end user. A no-op implementation allows said libraries to use it
+// as the default Tracer and to write instrumentation that does
+// not need to keep checking if the tracer instance is nil.
+//
+// For the same reason, the NoopTracer is the default "global" tracer
+// (see GlobalTracer and SetGlobalTracer functions).
+//
+// WARNING: NoopTracer does not support baggage propagation.
+type NoopTracer struct{}
+
+type noopSpan struct{}
+type noopSpanContext struct{}
+
+var (
+	defaultNoopSpanContext = noopSpanContext{}
+	defaultNoopSpan        = noopSpan{}
+	defaultNoopTracer      = NoopTracer{}
+)
+
+const (
+	emptyString = ""
+)
+
+// noopSpanContext:
+func (n noopSpanContext) ForeachBaggageItem(handler func(k, v string) bool) {}
+
+// noopSpan:
+func (n noopSpan) Context() SpanContext                                  { return defaultNoopSpanContext }
+func (n noopSpan) SetBaggageItem(key, val string) Span                   { return defaultNoopSpan }
+func (n noopSpan) BaggageItem(key string) string                         { return emptyString }
+func (n noopSpan) SetTag(key string, value interface{}) Span             { return n }
+func (n noopSpan) LogFields(fields ...log.Field)                         {}
+func (n noopSpan) LogKV(keyVals ...interface{})                          {}
+func (n noopSpan) Finish()                                               {}
+func (n noopSpan) FinishWithOptions(opts FinishOptions)                  {}
+func (n noopSpan) SetOperationName(operationName string) Span            { return n }
+func (n noopSpan) Tracer() Tracer                                        { return defaultNoopTracer }
+func (n noopSpan) LogEvent(event string)                                 {}
+func (n noopSpan) LogEventWithPayload(event string, payload interface{}) {}
+func (n noopSpan) Log(data LogData)                                      {}
+
+// StartSpan belongs to the Tracer interface.
+func (n NoopTracer) StartSpan(operationName string, opts ...StartSpanOption) Span {
+	return defaultNoopSpan
+}
+
+// Inject belongs to the Tracer interface.
+func (n NoopTracer) Inject(sp SpanContext, format interface{}, carrier interface{}) error {
+	return nil
+}
+
+// Extract belongs to the Tracer interface.
+func (n NoopTracer) Extract(format interface{}, carrier interface{}) (SpanContext, error) {
+	return nil, ErrSpanContextNotFound
+}
diff --git a/vendor/github.com/opentracing/opentracing-go/propagation.go b/vendor/github.com/opentracing/opentracing-go/propagation.go
new file mode 100644
index 0000000..b0c275e
--- /dev/null
+++ b/vendor/github.com/opentracing/opentracing-go/propagation.go
@@ -0,0 +1,176 @@
+package opentracing
+
+import (
+	"errors"
+	"net/http"
+)
+
+///////////////////////////////////////////////////////////////////////////////
+// CORE PROPAGATION INTERFACES:
+///////////////////////////////////////////////////////////////////////////////
+
+var (
+	// ErrUnsupportedFormat occurs when the `format` passed to Tracer.Inject() or
+	// Tracer.Extract() is not recognized by the Tracer implementation.
+	ErrUnsupportedFormat = errors.New("opentracing: Unknown or unsupported Inject/Extract format")
+
+	// ErrSpanContextNotFound occurs when the `carrier` passed to
+	// Tracer.Extract() is valid and uncorrupted but has insufficient
+	// information to extract a SpanContext.
+	ErrSpanContextNotFound = errors.New("opentracing: SpanContext not found in Extract carrier")
+
+	// ErrInvalidSpanContext errors occur when Tracer.Inject() is asked to
+	// operate on a SpanContext which it is not prepared to handle (for
+	// example, since it was created by a different tracer implementation).
+	ErrInvalidSpanContext = errors.New("opentracing: SpanContext type incompatible with tracer")
+
+	// ErrInvalidCarrier errors occur when Tracer.Inject() or Tracer.Extract()
+	// implementations expect a different type of `carrier` than they are
+	// given.
+	ErrInvalidCarrier = errors.New("opentracing: Invalid Inject/Extract carrier")
+
+	// ErrSpanContextCorrupted occurs when the `carrier` passed to
+	// Tracer.Extract() is of the expected type but is corrupted.
+	ErrSpanContextCorrupted = errors.New("opentracing: SpanContext data corrupted in Extract carrier")
+)
+
+///////////////////////////////////////////////////////////////////////////////
+// BUILTIN PROPAGATION FORMATS:
+///////////////////////////////////////////////////////////////////////////////
+
+// BuiltinFormat is used to demarcate the values within package `opentracing`
+// that are intended for use with the Tracer.Inject() and Tracer.Extract()
+// methods.
+type BuiltinFormat byte
+
+const (
+	// Binary represents SpanContexts as opaque binary data.
+	//
+	// For Tracer.Inject(): the carrier must be an `io.Writer`.
+	//
+	// For Tracer.Extract(): the carrier must be an `io.Reader`.
+	Binary BuiltinFormat = iota
+
+	// TextMap represents SpanContexts as key:value string pairs.
+	//
+	// Unlike HTTPHeaders, the TextMap format does not restrict the key or
+	// value character sets in any way.
+	//
+	// For Tracer.Inject(): the carrier must be a `TextMapWriter`.
+	//
+	// For Tracer.Extract(): the carrier must be a `TextMapReader`.
+	TextMap
+
+	// HTTPHeaders represents SpanContexts as HTTP header string pairs.
+	//
+	// Unlike TextMap, the HTTPHeaders format requires that the keys and values
+	// be valid as HTTP headers as-is (i.e., character casing may be unstable
+	// and special characters are disallowed in keys, values should be
+	// URL-escaped, etc).
+	//
+	// For Tracer.Inject(): the carrier must be a `TextMapWriter`.
+	//
+	// For Tracer.Extract(): the carrier must be a `TextMapReader`.
+	//
+	// See HTTPHeadersCarrier for an implementation of both TextMapWriter
+	// and TextMapReader that defers to an http.Header instance for storage.
+	// For example, Inject():
+	//
+	//    carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
+	//    err := span.Tracer().Inject(
+	//        span.Context(), opentracing.HTTPHeaders, carrier)
+	//
+	// Or Extract():
+	//
+	//    carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
+	//    clientContext, err := tracer.Extract(
+	//        opentracing.HTTPHeaders, carrier)
+	//
+	HTTPHeaders
+)
+
+// TextMapWriter is the Inject() carrier for the TextMap builtin format. With
+// it, the caller can encode a SpanContext for propagation as entries in a map
+// of unicode strings.
+type TextMapWriter interface {
+	// Set a key:value pair to the carrier. Multiple calls to Set() for the
+	// same key leads to undefined behavior.
+	//
+	// NOTE: The backing store for the TextMapWriter may contain data unrelated
+	// to SpanContext. As such, Inject() and Extract() implementations that
+	// call the TextMapWriter and TextMapReader interfaces must agree on a
+	// prefix or other convention to distinguish their own key:value pairs.
+	Set(key, val string)
+}
+
+// TextMapReader is the Extract() carrier for the TextMap builtin format. With it,
+// the caller can decode a propagated SpanContext as entries in a map of
+// unicode strings.
+type TextMapReader interface {
+	// ForeachKey returns TextMap contents via repeated calls to the `handler`
+	// function. If any call to `handler` returns a non-nil error, ForeachKey
+	// terminates and returns that error.
+	//
+	// NOTE: The backing store for the TextMapReader may contain data unrelated
+	// to SpanContext. As such, Inject() and Extract() implementations that
+	// call the TextMapWriter and TextMapReader interfaces must agree on a
+	// prefix or other convention to distinguish their own key:value pairs.
+	//
+	// The "foreach" callback pattern reduces unnecessary copying in some cases
+	// and also allows implementations to hold locks while the map is read.
+	ForeachKey(handler func(key, val string) error) error
+}
+
+// TextMapCarrier allows the use of regular map[string]string
+// as both TextMapWriter and TextMapReader.
+type TextMapCarrier map[string]string
+
+// ForeachKey conforms to the TextMapReader interface.
+func (c TextMapCarrier) ForeachKey(handler func(key, val string) error) error {
+	for k, v := range c {
+		if err := handler(k, v); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// Set implements Set() of opentracing.TextMapWriter
+func (c TextMapCarrier) Set(key, val string) {
+	c[key] = val
+}
+
+// HTTPHeadersCarrier satisfies both TextMapWriter and TextMapReader.
+//
+// Example usage for server side:
+//
+//     carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
+//     clientContext, err := tracer.Extract(opentracing.HTTPHeaders, carrier)
+//
+// Example usage for client side:
+//
+//     carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
+//     err := tracer.Inject(
+//         span.Context(),
+//         opentracing.HTTPHeaders,
+//         carrier)
+//
+type HTTPHeadersCarrier http.Header
+
+// Set conforms to the TextMapWriter interface.
+func (c HTTPHeadersCarrier) Set(key, val string) {
+	h := http.Header(c)
+	h.Set(key, val)
+}
+
+// ForeachKey conforms to the TextMapReader interface.
+func (c HTTPHeadersCarrier) ForeachKey(handler func(key, val string) error) error {
+	for k, vals := range c {
+		for _, v := range vals {
+			if err := handler(k, v); err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
diff --git a/vendor/github.com/opentracing/opentracing-go/span.go b/vendor/github.com/opentracing/opentracing-go/span.go
new file mode 100644
index 0000000..0d3fb53
--- /dev/null
+++ b/vendor/github.com/opentracing/opentracing-go/span.go
@@ -0,0 +1,189 @@
+package opentracing
+
+import (
+	"time"
+
+	"github.com/opentracing/opentracing-go/log"
+)
+
+// SpanContext represents Span state that must propagate to descendant Spans and across process
+// boundaries (e.g., a <trace_id, span_id, sampled> tuple).
+type SpanContext interface {
+	// ForeachBaggageItem grants access to all baggage items stored in the
+	// SpanContext.
+	// The handler function will be called for each baggage key/value pair.
+	// The ordering of items is not guaranteed.
+	//
+	// The bool return value indicates if the handler wants to continue iterating
+	// through the rest of the baggage items; for example if the handler is trying to
+	// find some baggage item by pattern matching the name, it can return false
+	// as soon as the item is found to stop further iterations.
+	ForeachBaggageItem(handler func(k, v string) bool)
+}
+
+// Span represents an active, un-finished span in the OpenTracing system.
+//
+// Spans are created by the Tracer interface.
+type Span interface {
+	// Sets the end timestamp and finalizes Span state.
+	//
+	// With the exception of calls to Context() (which are always allowed),
+	// Finish() must be the last call made to any span instance, and to do
+	// otherwise leads to undefined behavior.
+	Finish()
+	// FinishWithOptions is like Finish() but with explicit control over
+	// timestamps and log data.
+	FinishWithOptions(opts FinishOptions)
+
+	// Context() yields the SpanContext for this Span. Note that the return
+	// value of Context() is still valid after a call to Span.Finish(), as is
+	// a call to Span.Context() after a call to Span.Finish().
+	Context() SpanContext
+
+	// Sets or changes the operation name.
+	//
+	// Returns a reference to this Span for chaining.
+	SetOperationName(operationName string) Span
+
+	// Adds a tag to the span.
+	//
+	// If there is a pre-existing tag set for `key`, it is overwritten.
+	//
+	// Tag values can be numeric types, strings, or bools. The behavior of
+	// other tag value types is undefined at the OpenTracing level. If a
+	// tracing system does not know how to handle a particular value type, it
+	// may ignore the tag, but shall not panic.
+	//
+	// Returns a reference to this Span for chaining.
+	SetTag(key string, value interface{}) Span
+
+	// LogFields is an efficient and type-checked way to record key:value
+	// logging data about a Span, though the programming interface is a little
+	// more verbose than LogKV(). Here's an example:
+	//
+	//    span.LogFields(
+	//        log.String("event", "soft error"),
+	//        log.String("type", "cache timeout"),
+	//        log.Int("waited.millis", 1500))
+	//
+	// Also see Span.FinishWithOptions() and FinishOptions.BulkLogData.
+	LogFields(fields ...log.Field)
+
+	// LogKV is a concise, readable way to record key:value logging data about
+	// a Span, though unfortunately this also makes it less efficient and less
+	// type-safe than LogFields(). Here's an example:
+	//
+	//    span.LogKV(
+	//        "event", "soft error",
+	//        "type", "cache timeout",
+	//        "waited.millis", 1500)
+	//
+	// For LogKV (as opposed to LogFields()), the parameters must appear as
+	// key-value pairs, like
+	//
+	//    span.LogKV(key1, val1, key2, val2, key3, val3, ...)
+	//
+	// The keys must all be strings. The values may be strings, numeric types,
+	// bools, Go error instances, or arbitrary structs.
+	//
+	// (Note to implementors: consider the log.InterleavedKVToFields() helper)
+	LogKV(alternatingKeyValues ...interface{})
+
+	// SetBaggageItem sets a key:value pair on this Span and its SpanContext
+	// that also propagates to descendants of this Span.
+	//
+	// SetBaggageItem() enables powerful functionality given a full-stack
+	// opentracing integration (e.g., arbitrary application data from a mobile
+	// app can make it, transparently, all the way into the depths of a storage
+	// system), and with it some powerful costs: use this feature with care.
+	//
+	// IMPORTANT NOTE #1: SetBaggageItem() will only propagate baggage items to
+	// *future* causal descendants of the associated Span.
+	//
+	// IMPORTANT NOTE #2: Use this thoughtfully and with care. Every key and
+	// value is copied into every local *and remote* child of the associated
+	// Span, and that can add up to a lot of network and cpu overhead.
+	//
+	// Returns a reference to this Span for chaining.
+	SetBaggageItem(restrictedKey, value string) Span
+
+	// Gets the value for a baggage item given its key. Returns the empty string
+	// if the value isn't found in this Span.
+	BaggageItem(restrictedKey string) string
+
+	// Provides access to the Tracer that created this Span.
+	Tracer() Tracer
+
+	// Deprecated: use LogFields or LogKV
+	LogEvent(event string)
+	// Deprecated: use LogFields or LogKV
+	LogEventWithPayload(event string, payload interface{})
+	// Deprecated: use LogFields or LogKV
+	Log(data LogData)
+}
+
+// LogRecord is data associated with a single Span log. Every LogRecord
+// instance must specify at least one Field.
+type LogRecord struct {
+	Timestamp time.Time
+	Fields    []log.Field
+}
+
+// FinishOptions allows Span.FinishWithOptions callers to override the finish
+// timestamp and provide log data via a bulk interface.
+type FinishOptions struct {
+	// FinishTime overrides the Span's finish time, or implicitly becomes
+	// time.Now() if FinishTime.IsZero().
+	//
+	// FinishTime must resolve to a timestamp that's >= the Span's StartTime
+	// (per StartSpanOptions).
+	FinishTime time.Time
+
+	// LogRecords allows the caller to specify the contents of many LogFields()
+	// calls with a single slice. May be nil.
+	//
+	// None of the LogRecord.Timestamp values may be .IsZero() (i.e., they must
+	// be set explicitly). Also, they must be >= the Span's start timestamp and
+	// <= the FinishTime (or time.Now() if FinishTime.IsZero()). Otherwise the
+	// behavior of FinishWithOptions() is undefined.
+	//
+	// If specified, the caller hands off ownership of LogRecords at
+	// FinishWithOptions() invocation time.
+	//
+	// If specified, the (deprecated) BulkLogData must be nil or empty.
+	LogRecords []LogRecord
+
+	// BulkLogData is DEPRECATED.
+	BulkLogData []LogData
+}
+
+// LogData is DEPRECATED
+type LogData struct {
+	Timestamp time.Time
+	Event     string
+	Payload   interface{}
+}
+
+// ToLogRecord converts a deprecated LogData to a non-deprecated LogRecord
+func (ld *LogData) ToLogRecord() LogRecord {
+	var literalTimestamp time.Time
+	if ld.Timestamp.IsZero() {
+		literalTimestamp = time.Now()
+	} else {
+		literalTimestamp = ld.Timestamp
+	}
+	rval := LogRecord{
+		Timestamp: literalTimestamp,
+	}
+	if ld.Payload == nil {
+		rval.Fields = []log.Field{
+			log.String("event", ld.Event),
+		}
+	} else {
+		rval.Fields = []log.Field{
+			log.String("event", ld.Event),
+			log.Object("payload", ld.Payload),
+		}
+	}
+	return rval
+}
diff --git a/vendor/github.com/opentracing/opentracing-go/tracer.go b/vendor/github.com/opentracing/opentracing-go/tracer.go
new file mode 100644
index 0000000..715f0ce
--- /dev/null
+++ b/vendor/github.com/opentracing/opentracing-go/tracer.go
@@ -0,0 +1,304 @@
+package opentracing
+
+import "time"
+
+// Tracer is a simple, thin interface for Span creation and SpanContext
+// propagation.
+type Tracer interface {
+
+	// Create, start, and return a new Span with the given `operationName` and
+	// incorporate the given StartSpanOption `opts`. (Note that `opts` borrows
+	// from the "functional options" pattern, per
+	// http://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis)
+	//
+	// A Span with no SpanReference options (e.g., opentracing.ChildOf() or
+	// opentracing.FollowsFrom()) becomes the root of its own trace.
+	//
+	// Examples:
+	//
+	//     var tracer opentracing.Tracer = ...
+	//
+	//     // The root-span case:
+	//     sp := tracer.StartSpan("GetFeed")
+	//
+	//     // The vanilla child span case:
+	//     sp := tracer.StartSpan(
+	//         "GetFeed",
+	//         opentracing.ChildOf(parentSpan.Context()))
+	//
+	//     // All the bells and whistles:
+	//     sp := tracer.StartSpan(
+	//         "GetFeed",
+	//         opentracing.ChildOf(parentSpan.Context()),
+	//         opentracing.Tag{"user_agent", loggedReq.UserAgent},
+	//         opentracing.StartTime(loggedReq.Timestamp),
+	//     )
+	//
+	StartSpan(operationName string, opts ...StartSpanOption) Span
+
+	// Inject() takes the `sm` SpanContext instance and injects it for
+	// propagation within `carrier`. The actual type of `carrier` depends on
+	// the value of `format`.
+	//
+	// OpenTracing defines a common set of `format` values (see BuiltinFormat),
+	// and each has an expected carrier type.
+	//
+	// Other packages may declare their own `format` values, much like the keys
+	// used by `context.Context` (see https://godoc.org/context#WithValue).
+	//
+	// Example usage (sans error handling):
+	//
+	//     carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
+	//     err := tracer.Inject(
+	//         span.Context(),
+	//         opentracing.HTTPHeaders,
+	//         carrier)
+	//
+	// NOTE: All opentracing.Tracer implementations MUST support all
+	// BuiltinFormats.
+	//
+	// Implementations may return opentracing.ErrUnsupportedFormat if `format`
+	// is not supported by (or not known by) the implementation.
+	//
+	// Implementations may return opentracing.ErrInvalidCarrier or any other
+	// implementation-specific error if the format is supported but injection
+	// fails anyway.
+	//
+	// See Tracer.Extract().
+	Inject(sm SpanContext, format interface{}, carrier interface{}) error
+
+	// Extract() returns a SpanContext instance given `format` and `carrier`.
+	//
+	// OpenTracing defines a common set of `format` values (see BuiltinFormat),
+	// and each has an expected carrier type.
+	//
+	// Other packages may declare their own `format` values, much like the keys
+	// used by `context.Context` (see
+	// https://godoc.org/golang.org/x/net/context#WithValue).
+	//
+	// Example usage (with StartSpan):
+	//
+	//
+	//     carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
+	//     clientContext, err := tracer.Extract(opentracing.HTTPHeaders, carrier)
+	//
+	//     // ... assuming the ultimate goal here is to resume the trace with a
+	//     // server-side Span:
+	//     var serverSpan opentracing.Span
+	//     if err == nil {
+	//         span = tracer.StartSpan(
+	//             rpcMethodName, ext.RPCServerOption(clientContext))
+	//     } else {
+	//         span = tracer.StartSpan(rpcMethodName)
+	//     }
+	//
+	//
+	// NOTE: All opentracing.Tracer implementations MUST support all
+	// BuiltinFormats.
+	//
+	// Return values:
+	//  - A successful Extract returns a SpanContext instance and a nil error
+	//  - If there was simply no SpanContext to extract in `carrier`, Extract()
+	//    returns (nil, opentracing.ErrSpanContextNotFound)
+	//  - If `format` is unsupported or unrecognized, Extract() returns (nil,
+	//    opentracing.ErrUnsupportedFormat)
+	//  - If there are more fundamental problems with the `carrier` object,
+	//    Extract() may return opentracing.ErrInvalidCarrier,
+	//    opentracing.ErrSpanContextCorrupted, or implementation-specific
+	//    errors.
+	//
+	// See Tracer.Inject().
+	Extract(format interface{}, carrier interface{}) (SpanContext, error)
+}
+
+// StartSpanOptions allows Tracer.StartSpan() callers and implementors a
+// mechanism to override the start timestamp, specify Span References, and make
+// a single Tag or multiple Tags available at Span start time.
+//
+// StartSpan() callers should look at the StartSpanOption interface and
+// implementations available in this package.
+//
+// Tracer implementations can convert a slice of `StartSpanOption` instances
+// into a `StartSpanOptions` struct like so:
+//
+//     func StartSpan(opName string, opts ...opentracing.StartSpanOption) {
+//         sso := opentracing.StartSpanOptions{}
+//         for _, o := range opts {
+//             o.Apply(&sso)
+//         }
+//         ...
+//     }
+//
+type StartSpanOptions struct {
+	// Zero or more causal references to other Spans (via their SpanContext).
+	// If empty, start a "root" Span (i.e., start a new trace).
+	References []SpanReference
+
+	// StartTime overrides the Span's start time, or implicitly becomes
+	// time.Now() if StartTime.IsZero().
+	StartTime time.Time
+
+	// Tags may have zero or more entries; the restrictions on map values are
+	// identical to those for Span.SetTag(). May be nil.
+	//
+	// If specified, the caller hands off ownership of Tags at
+	// StartSpan() invocation time.
+	Tags map[string]interface{}
+}
+
+// StartSpanOption instances (zero or more) may be passed to Tracer.StartSpan.
+//
+// StartSpanOption borrows from the "functional options" pattern, per
+// http://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis
+type StartSpanOption interface {
+	Apply(*StartSpanOptions)
+}
+
+// SpanReferenceType is an enum type describing different categories of
+// relationships between two Spans. If Span-2 refers to Span-1, the
+// SpanReferenceType describes Span-1 from Span-2's perspective. For example,
+// ChildOfRef means that Span-1 created Span-2.
+//
+// NOTE: Span-1 and Span-2 do *not* necessarily depend on each other for
+// completion; e.g., Span-2 may be part of a background job enqueued by Span-1,
+// or Span-2 may be sitting in a distributed queue behind Span-1.
+type SpanReferenceType int
+
+const (
+	// ChildOfRef refers to a parent Span that caused *and* somehow depends
+	// upon the new child Span. Often (but not always), the parent Span cannot
+	// finish until the child Span does.
+	//
+	// An timing diagram for a ChildOfRef that's blocked on the new Span:
+	//
+	//     [-Parent Span---------]
+	//          [-Child Span----]
+	//
+	// See http://opentracing.io/spec/
+	//
+	// See opentracing.ChildOf()
+	ChildOfRef SpanReferenceType = iota
+
+	// FollowsFromRef refers to a parent Span that does not depend in any way
+	// on the result of the new child Span. For instance, one might use
+	// FollowsFromRefs to describe pipeline stages separated by queues,
+	// or a fire-and-forget cache insert at the tail end of a web request.
+	//
+	// A FollowsFromRef Span is part of the same logical trace as the new Span:
+	// i.e., the new Span is somehow caused by the work of its FollowsFromRef.
+	//
+	// All of the following could be valid timing diagrams for children that
+	// "FollowFrom" a parent.
+	//
+	//     [-Parent Span-]  [-Child Span-]
+	//
+	//
+	//     [-Parent Span--]
+	//      [-Child Span-]
+	//
+	//
+	//     [-Parent Span-]
+	//                 [-Child Span-]
+	//
+	// See http://opentracing.io/spec/
+	//
+	// See opentracing.FollowsFrom()
+	FollowsFromRef
+)
+
+// SpanReference is a StartSpanOption that pairs a SpanReferenceType and a
+// referenced SpanContext. See the SpanReferenceType documentation for
+// supported relationships.  If SpanReference is created with
+// ReferencedContext==nil, it has no effect. Thus it allows for a more concise
+// syntax for starting spans:
+//
+//     sc, _ := tracer.Extract(someFormat, someCarrier)
+//     span := tracer.StartSpan("operation", opentracing.ChildOf(sc))
+//
+// The `ChildOf(sc)` option above will not panic if sc == nil, it will just
+// not add the parent span reference to the options.
+type SpanReference struct {
+	Type              SpanReferenceType
+	ReferencedContext SpanContext
+}
+
+// Apply satisfies the StartSpanOption interface.
+func (r SpanReference) Apply(o *StartSpanOptions) {
+	if r.ReferencedContext != nil {
+		o.References = append(o.References, r)
+	}
+}
+
+// ChildOf returns a StartSpanOption pointing to a dependent parent span.
+// If sc == nil, the option has no effect.
+//
+// See ChildOfRef, SpanReference
+func ChildOf(sc SpanContext) SpanReference {
+	return SpanReference{
+		Type:              ChildOfRef,
+		ReferencedContext: sc,
+	}
+}
+
+// FollowsFrom returns a StartSpanOption pointing to a parent Span that caused
+// the child Span but does not directly depend on its result in any way.
+// If sc == nil, the option has no effect.
+//
+// See FollowsFromRef, SpanReference
+func FollowsFrom(sc SpanContext) SpanReference {
+	return SpanReference{
+		Type:              FollowsFromRef,
+		ReferencedContext: sc,
+	}
+}
+
+// StartTime is a StartSpanOption that sets an explicit start timestamp for the
+// new Span.
+type StartTime time.Time
+
+// Apply satisfies the StartSpanOption interface.
+func (t StartTime) Apply(o *StartSpanOptions) {
+	o.StartTime = time.Time(t)
+}
+
+// Tags are a generic map from an arbitrary string key to an opaque value type.
+// The underlying tracing system is responsible for interpreting and
+// serializing the values.
+type Tags map[string]interface{}
+
+// Apply satisfies the StartSpanOption interface.
+func (t Tags) Apply(o *StartSpanOptions) {
+	if o.Tags == nil {
+		o.Tags = make(map[string]interface{})
+	}
+	for k, v := range t {
+		o.Tags[k] = v
+	}
+}
+
+// Tag may be passed as a StartSpanOption to add a tag to new spans,
+// or its Set method may be used to apply the tag to an existing Span,
+// for example:
+//
+// tracer.StartSpan("opName", Tag{"Key", value})
+//
+//   or
+//
+// Tag{"key", value}.Set(span)
+type Tag struct {
+	Key   string
+	Value interface{}
+}
+
+// Apply satisfies the StartSpanOption interface.
+func (t Tag) Apply(o *StartSpanOptions) {
+	if o.Tags == nil {
+		o.Tags = make(map[string]interface{})
+	}
+	o.Tags[t.Key] = t.Value
+}
+
+// Set applies the tag to an existing Span.
+func (t Tag) Set(s Span) {
+	s.SetTag(t.Key, t.Value)
+}
diff --git a/vendor/github.com/pkg/errors/.gitignore b/vendor/github.com/pkg/errors/.gitignore
new file mode 100644
index 0000000..daf913b
--- /dev/null
+++ b/vendor/github.com/pkg/errors/.gitignore
@@ -0,0 +1,24 @@
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+*.test
+*.prof
diff --git a/vendor/github.com/pkg/errors/.travis.yml b/vendor/github.com/pkg/errors/.travis.yml
new file mode 100644
index 0000000..d4b9266
--- /dev/null
+++ b/vendor/github.com/pkg/errors/.travis.yml
@@ -0,0 +1,15 @@
+language: go
+go_import_path: github.com/pkg/errors
+go:
+  - 1.4.x
+  - 1.5.x
+  - 1.6.x
+  - 1.7.x
+  - 1.8.x
+  - 1.9.x
+  - 1.10.x
+  - 1.11.x
+  - tip
+
+script:
+  - go test -v ./...
diff --git a/vendor/github.com/pkg/errors/LICENSE b/vendor/github.com/pkg/errors/LICENSE
new file mode 100644
index 0000000..835ba3e
--- /dev/null
+++ b/vendor/github.com/pkg/errors/LICENSE
@@ -0,0 +1,23 @@
+Copyright (c) 2015, Dave Cheney <dave@cheney.net>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/pkg/errors/README.md b/vendor/github.com/pkg/errors/README.md
new file mode 100644
index 0000000..6483ba2
--- /dev/null
+++ b/vendor/github.com/pkg/errors/README.md
@@ -0,0 +1,52 @@
+# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge)
+
+Package errors provides simple error handling primitives.
+
+`go get github.com/pkg/errors`
+
+The traditional error handling idiom in Go is roughly akin to
+```go
+if err != nil {
+        return err
+}
+```
+which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error.
+
+## Adding context to an error
+
+The errors.Wrap function returns a new error that adds context to the original error. For example
+```go
+_, err := ioutil.ReadAll(r)
+if err != nil {
+        return errors.Wrap(err, "read failed")
+}
+```
+## Retrieving the cause of an error
+
+Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`.
+```go
+type causer interface {
+        Cause() error
+}
+```
+`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example:
+```go
+switch err := errors.Cause(err).(type) {
+case *MyError:
+        // handle specifically
+default:
+        // unknown error
+}
+```
+
+[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors).
+
+## Contributing
+
+We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high.
+
+Before proposing a change, please discuss your change by raising an issue.
+
+## License
+
+BSD-2-Clause
diff --git a/vendor/github.com/pkg/errors/appveyor.yml b/vendor/github.com/pkg/errors/appveyor.yml
new file mode 100644
index 0000000..a932ead
--- /dev/null
+++ b/vendor/github.com/pkg/errors/appveyor.yml
@@ -0,0 +1,32 @@
+version: build-{build}.{branch}
+
+clone_folder: C:\gopath\src\github.com\pkg\errors
+shallow_clone: true # for startup speed
+
+environment:
+  GOPATH: C:\gopath
+
+platform:
+  - x64
+
+# http://www.appveyor.com/docs/installed-software
+install:
+  # some helpful output for debugging builds
+  - go version
+  - go env
+  # pre-installed MinGW at C:\MinGW is 32bit only
+  # but MSYS2 at C:\msys64 has mingw64
+  - set PATH=C:\msys64\mingw64\bin;%PATH%
+  - gcc --version
+  - g++ --version
+
+build_script:
+  - go install -v ./...
+
+test_script:
+  - set PATH=C:\gopath\bin;%PATH%
+  - go test -v ./...
+
+#artifacts:
+#  - path: '%GOPATH%\bin\*.exe'
+deploy: off
diff --git a/vendor/github.com/pkg/errors/errors.go b/vendor/github.com/pkg/errors/errors.go
new file mode 100644
index 0000000..7421f32
--- /dev/null
+++ b/vendor/github.com/pkg/errors/errors.go
@@ -0,0 +1,282 @@
+// Package errors provides simple error handling primitives.
+//
+// The traditional error handling idiom in Go is roughly akin to
+//
+//     if err != nil {
+//             return err
+//     }
+//
+// which when applied recursively up the call stack results in error reports
+// without context or debugging information. The errors package allows
+// programmers to add context to the failure path in their code in a way
+// that does not destroy the original value of the error.
+//
+// Adding context to an error
+//
+// The errors.Wrap function returns a new error that adds context to the
+// original error by recording a stack trace at the point Wrap is called,
+// together with the supplied message. For example
+//
+//     _, err := ioutil.ReadAll(r)
+//     if err != nil {
+//             return errors.Wrap(err, "read failed")
+//     }
+//
+// If additional control is required, the errors.WithStack and
+// errors.WithMessage functions destructure errors.Wrap into its component
+// operations: annotating an error with a stack trace and with a message,
+// respectively.
+//
+// Retrieving the cause of an error
+//
+// Using errors.Wrap constructs a stack of errors, adding context to the
+// preceding error. Depending on the nature of the error it may be necessary
+// to reverse the operation of errors.Wrap to retrieve the original error
+// for inspection. Any error value which implements this interface
+//
+//     type causer interface {
+//             Cause() error
+//     }
+//
+// can be inspected by errors.Cause. errors.Cause will recursively retrieve
+// the topmost error that does not implement causer, which is assumed to be
+// the original cause. For example:
+//
+//     switch err := errors.Cause(err).(type) {
+//     case *MyError:
+//             // handle specifically
+//     default:
+//             // unknown error
+//     }
+//
+// Although the causer interface is not exported by this package, it is
+// considered a part of its stable public interface.
+//
+// Formatted printing of errors
+//
+// All error values returned from this package implement fmt.Formatter and can
+// be formatted by the fmt package. The following verbs are supported:
+//
+//     %s    print the error. If the error has a Cause it will be
+//           printed recursively.
+//     %v    see %s
+//     %+v   extended format. Each Frame of the error's StackTrace will
+//           be printed in detail.
+//
+// Retrieving the stack trace of an error or wrapper
+//
+// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are
+// invoked. This information can be retrieved with the following interface:
+//
+//     type stackTracer interface {
+//             StackTrace() errors.StackTrace
+//     }
+//
+// The returned errors.StackTrace type is defined as
+//
+//     type StackTrace []Frame
+//
+// The Frame type represents a call site in the stack trace. Frame supports
+// the fmt.Formatter interface that can be used for printing information about
+// the stack trace of this error. For example:
+//
+//     if err, ok := err.(stackTracer); ok {
+//             for _, f := range err.StackTrace() {
+//                     fmt.Printf("%+s:%d", f)
+//             }
+//     }
+//
+// Although the stackTracer interface is not exported by this package, it is
+// considered a part of its stable public interface.
+//
+// See the documentation for Frame.Format for more details.
+package errors
+
+import (
+	"fmt"
+	"io"
+)
+
+// New returns an error with the supplied message.
+// New also records the stack trace at the point it was called.
+func New(message string) error {
+	return &fundamental{
+		msg:   message,
+		stack: callers(),
+	}
+}
+
+// Errorf formats according to a format specifier and returns the string
+// as a value that satisfies error.
+// Errorf also records the stack trace at the point it was called.
+func Errorf(format string, args ...interface{}) error {
+	return &fundamental{
+		msg:   fmt.Sprintf(format, args...),
+		stack: callers(),
+	}
+}
+
+// fundamental is an error that has a message and a stack, but no caller.
+type fundamental struct {
+	msg string
+	*stack
+}
+
+func (f *fundamental) Error() string { return f.msg }
+
+func (f *fundamental) Format(s fmt.State, verb rune) {
+	switch verb {
+	case 'v':
+		if s.Flag('+') {
+			io.WriteString(s, f.msg)
+			f.stack.Format(s, verb)
+			return
+		}
+		fallthrough
+	case 's':
+		io.WriteString(s, f.msg)
+	case 'q':
+		fmt.Fprintf(s, "%q", f.msg)
+	}
+}
+
+// WithStack annotates err with a stack trace at the point WithStack was called.
+// If err is nil, WithStack returns nil.
+func WithStack(err error) error {
+	if err == nil {
+		return nil
+	}
+	return &withStack{
+		err,
+		callers(),
+	}
+}
+
+type withStack struct {
+	error
+	*stack
+}
+
+func (w *withStack) Cause() error { return w.error }
+
+func (w *withStack) Format(s fmt.State, verb rune) {
+	switch verb {
+	case 'v':
+		if s.Flag('+') {
+			fmt.Fprintf(s, "%+v", w.Cause())
+			w.stack.Format(s, verb)
+			return
+		}
+		fallthrough
+	case 's':
+		io.WriteString(s, w.Error())
+	case 'q':
+		fmt.Fprintf(s, "%q", w.Error())
+	}
+}
+
+// Wrap returns an error annotating err with a stack trace
+// at the point Wrap is called, and the supplied message.
+// If err is nil, Wrap returns nil.
+func Wrap(err error, message string) error {
+	if err == nil {
+		return nil
+	}
+	err = &withMessage{
+		cause: err,
+		msg:   message,
+	}
+	return &withStack{
+		err,
+		callers(),
+	}
+}
+
+// Wrapf returns an error annotating err with a stack trace
+// at the point Wrapf is called, and the format specifier.
+// If err is nil, Wrapf returns nil.
+func Wrapf(err error, format string, args ...interface{}) error {
+	if err == nil {
+		return nil
+	}
+	err = &withMessage{
+		cause: err,
+		msg:   fmt.Sprintf(format, args...),
+	}
+	return &withStack{
+		err,
+		callers(),
+	}
+}
+
+// WithMessage annotates err with a new message.
+// If err is nil, WithMessage returns nil.
+func WithMessage(err error, message string) error {
+	if err == nil {
+		return nil
+	}
+	return &withMessage{
+		cause: err,
+		msg:   message,
+	}
+}
+
+// WithMessagef annotates err with the format specifier.
+// If err is nil, WithMessagef returns nil.
+func WithMessagef(err error, format string, args ...interface{}) error {
+	if err == nil {
+		return nil
+	}
+	return &withMessage{
+		cause: err,
+		msg:   fmt.Sprintf(format, args...),
+	}
+}
+
+type withMessage struct {
+	cause error
+	msg   string
+}
+
+func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() }
+func (w *withMessage) Cause() error  { return w.cause }
+
+func (w *withMessage) Format(s fmt.State, verb rune) {
+	switch verb {
+	case 'v':
+		if s.Flag('+') {
+			fmt.Fprintf(s, "%+v\n", w.Cause())
+			io.WriteString(s, w.msg)
+			return
+		}
+		fallthrough
+	case 's', 'q':
+		io.WriteString(s, w.Error())
+	}
+}
+
+// Cause returns the underlying cause of the error, if possible.
+// An error value has a cause if it implements the following
+// interface:
+//
+//     type causer interface {
+//            Cause() error
+//     }
+//
+// If the error does not implement Cause, the original error will
+// be returned. If the error is nil, nil will be returned without further
+// investigation.
+func Cause(err error) error {
+	type causer interface {
+		Cause() error
+	}
+
+	for err != nil {
+		cause, ok := err.(causer)
+		if !ok {
+			break
+		}
+		err = cause.Cause()
+	}
+	return err
+}
diff --git a/vendor/github.com/pkg/errors/stack.go b/vendor/github.com/pkg/errors/stack.go
new file mode 100644
index 0000000..2874a04
--- /dev/null
+++ b/vendor/github.com/pkg/errors/stack.go
@@ -0,0 +1,147 @@
+package errors
+
+import (
+	"fmt"
+	"io"
+	"path"
+	"runtime"
+	"strings"
+)
+
+// Frame represents a program counter inside a stack frame.
+type Frame uintptr
+
+// pc returns the program counter for this frame;
+// multiple frames may have the same PC value.
+func (f Frame) pc() uintptr { return uintptr(f) - 1 }
+
+// file returns the full path to the file that contains the
+// function for this Frame's pc.
+func (f Frame) file() string {
+	fn := runtime.FuncForPC(f.pc())
+	if fn == nil {
+		return "unknown"
+	}
+	file, _ := fn.FileLine(f.pc())
+	return file
+}
+
+// line returns the line number of source code of the
+// function for this Frame's pc.
+func (f Frame) line() int {
+	fn := runtime.FuncForPC(f.pc())
+	if fn == nil {
+		return 0
+	}
+	_, line := fn.FileLine(f.pc())
+	return line
+}
+
+// Format formats the frame according to the fmt.Formatter interface.
+//
+//    %s    source file
+//    %d    source line
+//    %n    function name
+//    %v    equivalent to %s:%d
+//
+// Format accepts flags that alter the printing of some verbs, as follows:
+//
+//    %+s   function name and path of source file relative to the compile time
+//          GOPATH separated by \n\t (<funcname>\n\t<path>)
+//    %+v   equivalent to %+s:%d
+func (f Frame) Format(s fmt.State, verb rune) {
+	switch verb {
+	case 's':
+		switch {
+		case s.Flag('+'):
+			pc := f.pc()
+			fn := runtime.FuncForPC(pc)
+			if fn == nil {
+				io.WriteString(s, "unknown")
+			} else {
+				file, _ := fn.FileLine(pc)
+				fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file)
+			}
+		default:
+			io.WriteString(s, path.Base(f.file()))
+		}
+	case 'd':
+		fmt.Fprintf(s, "%d", f.line())
+	case 'n':
+		name := runtime.FuncForPC(f.pc()).Name()
+		io.WriteString(s, funcname(name))
+	case 'v':
+		f.Format(s, 's')
+		io.WriteString(s, ":")
+		f.Format(s, 'd')
+	}
+}
+
+// StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
+type StackTrace []Frame
+
+// Format formats the stack of Frames according to the fmt.Formatter interface.
+//
+//    %s	lists source files for each Frame in the stack
+//    %v	lists the source file and line number for each Frame in the stack
+//
+// Format accepts flags that alter the printing of some verbs, as follows:
+//
+//    %+v   Prints filename, function, and line number for each Frame in the stack.
+func (st StackTrace) Format(s fmt.State, verb rune) {
+	switch verb {
+	case 'v':
+		switch {
+		case s.Flag('+'):
+			for _, f := range st {
+				fmt.Fprintf(s, "\n%+v", f)
+			}
+		case s.Flag('#'):
+			fmt.Fprintf(s, "%#v", []Frame(st))
+		default:
+			fmt.Fprintf(s, "%v", []Frame(st))
+		}
+	case 's':
+		fmt.Fprintf(s, "%s", []Frame(st))
+	}
+}
+
+// stack represents a stack of program counters.
+type stack []uintptr
+
+func (s *stack) Format(st fmt.State, verb rune) {
+	switch verb {
+	case 'v':
+		switch {
+		case st.Flag('+'):
+			for _, pc := range *s {
+				f := Frame(pc)
+				fmt.Fprintf(st, "\n%+v", f)
+			}
+		}
+	}
+}
+
+func (s *stack) StackTrace() StackTrace {
+	f := make([]Frame, len(*s))
+	for i := 0; i < len(f); i++ {
+		f[i] = Frame((*s)[i])
+	}
+	return f
+}
+
+func callers() *stack {
+	const depth = 32
+	var pcs [depth]uintptr
+	n := runtime.Callers(3, pcs[:])
+	var st stack = pcs[0:n]
+	return &st
+}
+
+// funcname removes the path prefix component of a function's name reported by func.Name().
+func funcname(name string) string {
+	i := strings.LastIndex(name, "/")
+	name = name[i+1:]
+	i = strings.Index(name, ".")
+	return name[i+1:]
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/.gitignore b/vendor/github.com/uber/jaeger-client-go/.gitignore
new file mode 100644
index 0000000..2734907
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/.gitignore
@@ -0,0 +1,15 @@
+*.out
+*.test
+*.xml
+*.swp
+.idea/
+.tmp/
+*.iml
+*.cov
+*.html
+*.log
+gen/thrift/js
+gen/thrift/py
+vendor/
+crossdock-main
+crossdock/jaeger-docker-compose.yml
diff --git a/vendor/github.com/uber/jaeger-client-go/.gitmodules b/vendor/github.com/uber/jaeger-client-go/.gitmodules
new file mode 100644
index 0000000..295ebcf
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "idl"]
+	path = idl
+	url = https://github.com/uber/jaeger-idl.git
diff --git a/vendor/github.com/uber/jaeger-client-go/.travis.yml b/vendor/github.com/uber/jaeger-client-go/.travis.yml
new file mode 100644
index 0000000..e81cc88
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/.travis.yml
@@ -0,0 +1,56 @@
+sudo: required
+
+language: go
+go_import_path: github.com/uber/jaeger-client-go
+
+dist: trusty
+
+matrix:
+  include:
+  - go: 1.13.x
+    env:
+    - TESTS=true
+    - USE_DEP=true
+    - COVERAGE=true
+  - go: 1.13.x
+    env:
+    - USE_DEP=true
+    - CROSSDOCK=true
+  - go: 1.13.x
+    env:
+    - TESTS=true
+    - USE_DEP=false
+    - USE_GLIDE=true
+  # test with previous version of Go
+  - go: 1.12.x
+    env:
+    - TESTS=true
+    - USE_DEP=true
+    - CI_SKIP_LINT=true
+
+services:
+  - docker
+
+env:
+  global:
+    - DOCKER_COMPOSE_VERSION=1.8.0
+    - COMMIT=${TRAVIS_COMMIT::8}
+    # DOCKER_PASS
+    - secure: "CnjVyxNvMC/dhr/eR7C+FiWucZ4/O5LfAuz9YU0qlnV6XLR7XXRtzZlfFKIImJT6xHp+OptTqAIXqUbvwK2OXDP1ZsLiWRm+2elb9/isGusWXjs3g817lX8njSUcIFILbfi+vAE7UD2BKjHxpmvWmCZidisU1rcaZ9OQNPqMnNIDxVx0FOTwYx+2hfkdjnN5dikzafBDQ6ZZV/mGbcaTG45GGFU6DHyVLzf9qCPXyXnz2+VDhcoPQsYkzE56XHCmHxvEfXxgfqYefJNUlFPhniAQySVsCNVDJ8QcCV6uHaXoIzxJKx9FdUnWKI1/AtpQsTZPgEm4Ujnt+kGJsXopXy2Xx4MZxmcTCBwAMjZxPMF7KoojbtDeOZgEMtf1tGPN6DTNc3NpVmr0BKZ44lhqk+vnd8HAiC1tHDEoSb1Esl7dMUUf1qZAh3MtT+NYi3mTwyx/ilXUS7KPyy7x0ezB3kGuMoLhvR2hrprqRr5NOV2hrd1au+IXmb+4IanFOsBlceBfs8P0JFMO/aw15r+HimSZpQsJx//IT0LReCZYXLe0/WVsF/8+HDwHKlO99gGpk4iXlNKKvdPWabihMp3I3peMrvL+jnlwh47RqHs/0Q71xsKjVWTn+Svq3FpVP0Pgyxhg+oG4WEByBiLnBQcZwSBhWexkJrNI73GzaZiIldk="
+    # DOCKER_USER
+    - secure: "bpBSmypHzI4PnteM4cwLiMC2163Sj/4mEl+1dj+6NWl2tr1hREeVXKhsWBpah25n6BDyr2A4yhBZcWLaNKrsCKT3U37csAQTOFVeQ9x5xhPq+ohANd/OsspFsxNZaKwx161LizH/uTDotMxxevZacsyYWGNv/cRFkwcQ8upLkReRR6puJ+jNQC0BFpKWBJY/zpm5J7xFb7FO20LvQVyRgsgzqWmg9oRNVw9uwOfSY3btacftYctDLUbAr8YRNHd2C6dZnMAi8KdDTLXKTqjKmp6WidOmi92Ml7tOjB+bV6TOaVAhrcI5Rdje4rRWG4MucAjPMP0ZBW36KTfcGqFUcDhX7UqISe2WxoI+8ZD6fJ+nNtD3bk4YAUJB4BSs2sQdiYyjpHyGJR6RW50+3uRz2YbXpzVr9wqv2lZSl/xy3wC5Hag55uqzVlSiDw2pK8lctT3dnQveE7PqAI577PjF2NrHlgrBbykOwwUCNbRTmykzqoDnkxclmiZ+rflEeWsSYglePK/d6Gj9+N7wJZM5heprdJJMFTrzMWZ21Ll9ZGY9updCBKmJA8pBYiLHbu0lWOp+9QUGC+621Zq0d1PHhN6L4eXk/f3RNoZTr//cX6WdNmmO7tBbaGpmp/UYiYTY1WO9vP7tCDsT75k285HCfnIrlGRdbCZZbfuYNGPKIQ0="
+
+install:
+  - make install-ci USE_DEP=$USE_DEP
+  - if [ "$CROSSDOCK" == true ]; then bash ./travis/install-crossdock-deps.sh ; fi
+
+script:
+  - if [ "$TESTS" == true ]; then make test-ci ; else echo 'skipping tests'; fi
+  - if [ "$CROSSDOCK" == true ]; then bash ./travis/build-crossdock.sh ; else echo 'skipping crossdock'; fi
+
+after_success:
+  - if [ "$COVERAGE" == true ]; then mv cover.out coverage.txt ; else echo 'skipping coverage'; fi
+  - if [ "$COVERAGE" == true ]; then bash <(curl -s https://codecov.io/bash) ; else echo 'skipping coverage'; fi
+
+after_failure:
+  - if [ "$CROSSDOCK" == true ]; then timeout 5 docker-compose -f crossdock/docker-compose.yml logs; fi
diff --git a/vendor/github.com/uber/jaeger-client-go/CHANGELOG.md b/vendor/github.com/uber/jaeger-client-go/CHANGELOG.md
new file mode 100644
index 0000000..944feb2
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/CHANGELOG.md
@@ -0,0 +1,330 @@
+Changes by Version
+==================
+
+2.23.1 (2020-04-28)
+-------------------
+- Fix regression by handling nil logger correctly ([#507](https://github.com/jaegertracing/jaeger-client-go/pull/507)) -- Prithvi Raj
+
+
+2.23.0 (2020-04-22)
+-------------------
+
+- Add the ability to log all span interactions at a new debug log level([#502](https://github.com/jaegertracing/jaeger-client-go/pull/502), [#503](https://github.com/jaegertracing/jaeger-client-go/pull/503), [#504](https://github.com/jaegertracing/jaeger-client-go/pull/504)) -- Prithvi Raj
+- Chore (docs): fix typos ([#496](https://github.com/jaegertracing/jaeger-client-go/pull/496), [#498](https://github.com/jaegertracing/jaeger-client-go/pull/498)) -- Febrian Setianto and Ivan Babrou
+- Unset highest bit of traceID in probabilistic sampler ([#490](https://github.com/jaegertracing/jaeger-client-go/pull/490)) -- Sokolov Yura
+
+2.22.1 (2020-01-16)
+-------------------
+
+- Increase UDP batch overhead to account for data loss metrics ([#488](https://github.com/jaegertracing/jaeger-client-go/pull/488)) -- Yuri Shkuro
+
+
+2.22.0 (2020-01-15)
+-------------------
+
+- Report data loss stats to Jaeger backend ([#482](https://github.com/jaegertracing/jaeger-client-go/pull/482)) -- Yuri Shkuro
+- Add limit on log records per span ([#483](https://github.com/jaegertracing/jaeger-client-go/pull/483)) -- Sokolov Yura
+
+
+2.21.1 (2019-12-20)
+-------------------
+
+- Update version correctly.
+
+
+2.21.0 (2019-12-20)
+-------------------
+
+- Clarify reporting error logs ([#469](https://github.com/jaegertracing/jaeger-client-go/pull/469)) -- Yuri Shkuro
+- Do not strip leading zeros from trace IDs ([#472](https://github.com/jaegertracing/jaeger-client-go/pull/472)) -- Yuri Shkuro
+- Chore (docs): fixed a couple of typos ([#475](https://github.com/jaegertracing/jaeger-client-go/pull/475)) -- Marc Bramaud
+- Support custom HTTP headers when reporting spans over HTTP ([#479](https://github.com/jaegertracing/jaeger-client-go/pull/479)) -- Albert Teoh
+
+
+2.20.1 (2019-11-08)
+-------------------
+
+Minor patch via https://github.com/jaegertracing/jaeger-client-go/pull/468
+
+- Make `AdaptiveSamplerUpdater` usable with default values; Resolves #467
+- Create `OperationNameLateBinding` sampler option and config option
+- Make `SamplerOptions` var of public type, so that its functions are discoverable via godoc
+
+
+2.20.0 (2019-11-06)
+-------------------
+
+## New Features
+
+- Allow all in-process spans of a trace to share sampling state (#443) -- Prithvi Raj
+
+  Sampling state is shared between all spans of the trace that are still in memory.
+  This allows implementation of delayed sampling decisions (see below).
+
+- Support delayed sampling decisions (#449) -- Yuri Shkuro
+
+  This is a large structural change to how the samplers work.
+  It allows some samplers to be executed multiple times on different
+  span events (like setting a tag) and make a positive sampling decision
+  later in the span life cycle, or even based on children spans.
+  See [README](./README.md#delayed-sampling) for more details.
+
+  There is a related minor change in behavior of the adaptive (per-operation) sampler,
+  which will no longer re-sample the trace when `span.SetOperation()` is called, i.e. the
+  operation used to make the sampling decision is always the one provided at span creation.
+
+- Add experimental tag matching sampler (#452) -- Yuri Shkuro
+
+  A sampler that can sample a trace based on a certain tag added to the root
+  span or one of its local (in-process) children. The sampler can be used with
+  another experimental `PrioritySampler` that allows multiple samplers to try
+  to make a sampling decision, in a certain priority order.
+
+- [log/zap] Report whether a trace was sampled (#445) -- Abhinav Gupta
+- Allow config.FromEnv() to enrich an existing config object (#436) -- Vineeth Reddy
+
+## Minor patches
+
+- Expose Sampler on Tracer and accept sampler options via Configuration (#460) -- Yuri Shkuro
+- Fix github.com/uber-go/atomic import (#464) -- Yuri Shkuro
+- Add nodejs to crossdock tests (#441) -- Bhavin Gandhi
+- Bump Go compiler version to 1.13 (#453) -- Yuri Shkuro
+
+2.19.0 (2019-09-23)
+-------------------
+
+- Upgrade jaeger-lib to 2.2 and unpin Prom client (#434) -- Yuri Shkuro
+
+
+2.18.1 (2019-09-16)
+-------------------
+
+- Remove go.mod / go.sum that interfere with `go get` (#432)
+
+
+2.18.0 (2019-09-09)
+-------------------
+
+- Add option "noDebugFlagOnForcedSampling" for tracer initialization [resolves #422] (#423) <Jun Guo>
+
+
+2.17.0 (2019-08-30)
+-------------------
+
+- Add a flag for firehose mode (#419) <Prithvi Raj>
+- Default sampling server URL to agent (#414) <Bryan Boreham>
+- Update default sampling rate when sampling strategy is refreshed (#413) <Bryan Boreham>
+- Support "Self" Span Reference (#411) <dm03514>
+- Don't complain about blank service name if tracing is Disabled (#410) Yuri <Shkuro>
+- Use IP address from tag if exist (#402) <NikoKVCS>
+- Expose span data to custom reporters [fixes #394] (#399) <Curtis Allen>
+- Fix the span allocation in the pool (#381) <Dmitry Ponomarev>
+
+
+2.16.0 (2019-03-24)
+-------------------
+
+- Add baggage to B3 codec (#319) <Pavol Loffay>
+- Add support for 128bit trace ids to zipkin thrift spans. (#378) <Douglas Reid>
+- Update zipkin propagation logic to support 128bit traceIDs (#373) <Douglas Reid>
+- Accept "true" for the x-b3-sampled header (#356) <Adrian Bogatu>
+
+- Allow setting of PoolSpans from Config object (#322) <Matthew Pound>
+- Make propagators public to allow wrapping (#379) <Ivan Babrou>
+- Change default metric namespace to use relevant separator for the metric backend (#364) <Gary Brown>
+- Change metrics prefix to jaeger_tracer and add descriptions (#346) <Gary Brown>
+- Bump OpenTracing to ^1.1.x (#383) <Yuri Shkuro>
+- Upgrade jaeger-lib to v2.0.0 (#359) <Gary Brown>
+- Avoid defer when generating random number (#358) <Gary Brown>
+- Use a pool of rand.Source to reduce lock contention when creating span ids (#357) <Gary Brown>
+- Make JAEGER_ENDPOINT take priority over JAEGER_AGENT_XXX (#342) <Eundoo Song>
+
+
+2.15.0 (2018-10-10)
+-------------------
+
+- Fix FollowsFrom spans ignoring baggage/debug header from dummy parent context (#313) <Zvi Cahana>
+- Make maximum annotation length configurable in tracer options (#318) <Eric Chang>
+- Support more environment variables in configuration (#323) <Daneyon Hansen>
+- Print error on Sampler Query failure (#328) <Goutham Veeramachaneni>
+- Add an HTTPOption to support custom http.RoundTripper (#333) <Michael Puncel>
+- Return an error when an HTTP error code is seen in zipkin HTTP transport (#331) <Michael Puncel>
+
+
+2.14.0 (2018-04-30)
+-------------------
+
+- Support throttling for debug traces (#274) <Isaac Hier>
+- Remove dependency on Apache Thrift (#303) <Yuri Shkuro>
+- Remove dependency on tchannel  (#295) (#294) <Yuri Shkuro>
+- Test with Go 1.9 (#298) <Yuri Shkuro>
+
+
+2.13.0 (2018-04-15)
+-------------------
+
+- Use value receiver for config.NewTracer() (#283) <Yuri Shkuro>
+- Lock span during jaeger thrift conversion (#273) <Won Jun Jang>
+- Fix the RemotelyControlledSampler so that it terminates go-routine on Close() (#260) <Scott Kidder> <Yuri Shkuro>
+- Added support for client configuration via env vars (#275) <Juraci Paixão Kröhling>
+- Allow overriding sampler in the Config (#270) <Mike Kabischev>
+
+
+2.12.0 (2018-03-14)
+-------------------
+
+- Use lock when retrieving span.Context() (#268)
+- Add Configuration support for custom Injector and Extractor (#263) <Martin Liu>
+
+
+2.11.2 (2018-01-12)
+-------------------
+
+- Add Gopkg.toml to allow using the lib with `dep`
+
+
+2.11.1 (2018-01-03)
+-------------------
+
+- Do not enqueue spans after Reporter is closed (#235, #245)
+- Change default flush interval to 1sec (#243)
+
+
+2.11.0 (2017-11-27)
+-------------------
+
+- Normalize metric names and tags to be compatible with Prometheus (#222)
+
+
+2.10.0 (2017-11-14)
+-------------------
+
+- Support custom tracing headers (#176)
+- Add BaggageRestrictionManager (#178) and RemoteBaggageRestrictionManager (#182)
+- Do not coerce baggage keys to lower case (#196)
+- Log span name when span cannot be reported (#198)
+- Add option to enable gen128Bit for tracer (#193) and allow custom generator for high bits of trace ID (#219)
+
+
+2.9.0 (2017-07-29)
+------------------
+
+- Pin thrift <= 0.10 (#179)
+- Introduce a parallel interface ContribObserver (#159)
+
+
+2.8.0 (2017-07-05)
+------------------
+
+- Drop `jaeger.` prefix from `jaeger.hostname` process-level tag
+- Add options to set tracer tags
+
+
+2.7.0 (2017-06-21)
+------------------
+
+- Fix rate limiter balance [#135](https://github.com/uber/jaeger-client-go/pull/135) [#140](https://github.com/uber/jaeger-client-go/pull/140)
+- Default client to send Jaeger.thrift [#147](https://github.com/uber/jaeger-client-go/pull/147)
+- Save baggage in span [#153](https://github.com/uber/jaeger-client-go/pull/153)
+- Move reporter.queueLength to the top of the struct to guarantee 64bit alignment [#158](https://github.com/uber/jaeger-client-go/pull/158)
+- Support HTTP transport with jaeger.thrift [#161](https://github.com/uber/jaeger-client-go/pull/161)
+
+
+2.6.0 (2017-03-28)
+------------------
+
+- Add config option to initialize RPC Metrics feature
+
+
+2.5.0 (2017-03-23)
+------------------
+
+- Split request latency metric by success/failure [#123](https://github.com/uber/jaeger-client-go/pull/123)
+- Add mutex to adaptive sampler and fix race condition [#124](https://github.com/uber/jaeger-client-go/pull/124)
+- Fix rate limiter panic [#125](https://github.com/uber/jaeger-client-go/pull/125)
+
+
+2.4.0 (2017-03-21)
+------------------
+
+- Remove `_ms` suffix from request latency metric name [#121](https://github.com/uber/jaeger-client-go/pull/121)
+- Rename all metrics to "request" and "http_request" and use tags for other dimensions [#121](https://github.com/uber/jaeger-client-go/pull/121)
+
+
+2.3.0 (2017-03-20)
+------------------
+
+- Make Span type public to allow access to non-std methods for testing [#117](https://github.com/uber/jaeger-client-go/pull/117)
+- Add a structured way to extract traces for logging with zap [#118](https://github.com/uber/jaeger-client-go/pull/118)
+
+
+2.2.1 (2017-03-14)
+------------------
+
+- Fix panic caused by updating the remote sampler from adaptive sampler to any other sampler type (https://github.com/uber/jaeger-client-go/pull/111)
+
+
+2.2.0 (2017-03-10)
+------------------
+
+- Introduce Observer and SpanObserver (https://github.com/uber/jaeger-client-go/pull/94)
+- Add RPC metrics emitter as Observer/SpanObserver (https://github.com/uber/jaeger-client-go/pull/103)
+
+
+2.1.2 (2017-02-27)
+-------------------
+
+- Fix leaky bucket bug (https://github.com/uber/jaeger-client-go/pull/99)
+- Fix zap logger Infof (https://github.com/uber/jaeger-client-go/pull/100)
+- Add tracer initialization godoc examples
+
+
+2.1.1 (2017-02-21)
+-------------------
+
+- Fix inefficient usage of zap.Logger
+
+
+2.1.0 (2017-02-17)
+-------------------
+
+- Add adapter for zap.Logger (https://github.com/uber-go/zap)
+- Move logging API to ./log/ package
+
+
+2.0.0 (2017-02-08)
+-------------------
+
+- Support Adaptive Sampling
+- Support 128bit Trace IDs
+- Change trace/span IDs from uint64 to strong types TraceID and SpanID
+- Add Zipkin HTTP B3 Propagation format support #72
+- Rip out existing metrics and use github.com/uber/jaeger-lib/metrics
+- Change API for tracer, reporter, sampler initialization
+
+
+1.6.0 (2016-10-14)
+-------------------
+
+- Add Zipkin HTTP transport
+- Support external baggage via jaeger-baggage header
+- Unpin Thrift version, keep to master
+
+
+1.5.1 (2016-09-27)
+-------------------
+
+- Relax dependency on opentracing to ^1
+
+
+1.5.0 (2016-09-27)
+-------------------
+
+- Upgrade to opentracing-go 1.0
+- Support KV logging for Spans
+
+
+1.4.0 (2016-09-14)
+-------------------
+
+- Support debug traces via HTTP header "jaeger-debug-id"
diff --git a/vendor/github.com/uber/jaeger-client-go/CONTRIBUTING.md b/vendor/github.com/uber/jaeger-client-go/CONTRIBUTING.md
new file mode 100644
index 0000000..41e2154
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/CONTRIBUTING.md
@@ -0,0 +1,170 @@
+# How to Contribute to Jaeger
+
+We'd love your help!
+
+Jaeger is [Apache 2.0 licensed](LICENSE) and accepts contributions via GitHub
+pull requests. This document outlines some of the conventions on development
+workflow, commit message formatting, contact points and other resources to make
+it easier to get your contribution accepted.
+
+We gratefully welcome improvements to documentation as well as to code.
+
+# Certificate of Origin
+
+By contributing to this project you agree to the [Developer Certificate of
+Origin](https://developercertificate.org/) (DCO). This document was created
+by the Linux Kernel community and is a simple statement that you, as a
+contributor, have the legal right to make the contribution. See the [DCO](DCO)
+file for details.
+
+## Getting Started
+
+This library uses [dep](https://golang.github.io/dep/) to manage dependencies.
+
+To get started, make sure you clone the Git repository into the correct location
+`github.com/uber/jaeger-client-go` relative to `$GOPATH`:
+
+```
+mkdir -p $GOPATH/src/github.com/uber
+cd $GOPATH/src/github.com/uber
+git clone git@github.com:jaegertracing/jaeger-client-go.git jaeger-client-go
+cd jaeger-client-go
+git submodule update --init --recursive
+```
+
+Then install dependencies and run the tests:
+
+```
+make install
+make test
+```
+
+## Imports grouping
+
+This projects follows the following pattern for grouping imports in Go files:
+  * imports from standard library
+  * imports from other projects
+  * imports from `jaeger-client-go` project
+
+For example:
+
+```go
+import (
+	"fmt"
+
+	"github.com/uber/jaeger-lib/metrics"
+	"go.uber.org/zap"
+
+	"github.com/uber/jaeger-client-go/config"
+)
+```
+
+## Making A Change
+
+*Before making any significant changes, please [open an
+issue](https://github.com/jaegertracing/jaeger-client-go/issues).* Discussing your proposed
+changes ahead of time will make the contribution process smooth for everyone.
+
+Once we've discussed your changes and you've got your code ready, make sure
+that tests are passing (`make test` or `make cover`) and open your PR. Your
+pull request is most likely to be accepted if it:
+
+* Includes tests for new functionality.
+* Follows the guidelines in [Effective
+  Go](https://golang.org/doc/effective_go.html) and the [Go team's common code
+  review comments](https://github.com/golang/go/wiki/CodeReviewComments).
+* Has a [good commit message](https://chris.beams.io/posts/git-commit/):
+   * Separate subject from body with a blank line
+   * Limit the subject line to 50 characters
+   * Capitalize the subject line
+   * Do not end the subject line with a period
+   * Use the imperative mood in the subject line
+   * Wrap the body at 72 characters
+   * Use the body to explain _what_ and _why_ instead of _how_
+* Each commit must be signed by the author ([see below](#sign-your-work)).
+
+## License
+
+By contributing your code, you agree to license your contribution under the terms
+of the [Apache License](LICENSE).
+
+If you are adding a new file it should have a header like below.  The easiest
+way to add such header is to run `make fmt`.
+
+```
+// Copyright (c) 2017 The Jaeger Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+```
+
+## Sign your work
+
+The sign-off is a simple line at the end of the explanation for the
+patch, which certifies that you wrote it or otherwise have the right to
+pass it on as an open-source patch.  The rules are pretty simple: if you
+can certify the below (from
+[developercertificate.org](http://developercertificate.org/)):
+
+```
+Developer Certificate of Origin
+Version 1.1
+
+Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
+660 York Street, Suite 102,
+San Francisco, CA 94110 USA
+
+Everyone is permitted to copy and distribute verbatim copies of this
+license document, but changing it is not allowed.
+
+
+Developer's Certificate of Origin 1.1
+
+By making a contribution to this project, I certify that:
+
+(a) The contribution was created in whole or in part by me and I
+    have the right to submit it under the open source license
+    indicated in the file; or
+
+(b) The contribution is based upon previous work that, to the best
+    of my knowledge, is covered under an appropriate open source
+    license and I have the right under that license to submit that
+    work with modifications, whether created in whole or in part
+    by me, under the same open source license (unless I am
+    permitted to submit under a different license), as indicated
+    in the file; or
+
+(c) The contribution was provided directly to me by some other
+    person who certified (a), (b) or (c) and I have not modified
+    it.
+
+(d) I understand and agree that this project and the contribution
+    are public and that a record of the contribution (including all
+    personal information I submit with it, including my sign-off) is
+    maintained indefinitely and may be redistributed consistent with
+    this project or the open source license(s) involved.
+```
+
+then you just add a line to every git commit message:
+
+    Signed-off-by: Joe Smith <joe@gmail.com>
+
+using your real name (sorry, no pseudonyms or anonymous contributions.)
+
+You can add the sign off when creating the git commit via `git commit -s`.
+
+If you want this to be automatic you can set up some aliases:
+
+```
+git config --add alias.amend "commit -s --amend"
+git config --add alias.c "commit -s"
+```
diff --git a/vendor/github.com/uber/jaeger-client-go/DCO b/vendor/github.com/uber/jaeger-client-go/DCO
new file mode 100644
index 0000000..068953d
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/DCO
@@ -0,0 +1,37 @@
+Developer Certificate of Origin
+Version 1.1
+
+Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
+660 York Street, Suite 102,
+San Francisco, CA 94110 USA
+
+Everyone is permitted to copy and distribute verbatim copies of this
+license document, but changing it is not allowed.
+
+
+Developer's Certificate of Origin 1.1
+
+By making a contribution to this project, I certify that:
+
+(a) The contribution was created in whole or in part by me and I
+    have the right to submit it under the open source license
+    indicated in the file; or
+
+(b) The contribution is based upon previous work that, to the best
+    of my knowledge, is covered under an appropriate open source
+    license and I have the right under that license to submit that
+    work with modifications, whether created in whole or in part
+    by me, under the same open source license (unless I am
+    permitted to submit under a different license), as indicated
+    in the file; or
+
+(c) The contribution was provided directly to me by some other
+    person who certified (a), (b) or (c) and I have not modified
+    it.
+
+(d) I understand and agree that this project and the contribution
+    are public and that a record of the contribution (including all
+    personal information I submit with it, including my sign-off) is
+    maintained indefinitely and may be redistributed consistent with
+    this project or the open source license(s) involved.
+
diff --git a/vendor/github.com/uber/jaeger-client-go/Gopkg.lock b/vendor/github.com/uber/jaeger-client-go/Gopkg.lock
new file mode 100644
index 0000000..2a5215a
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/Gopkg.lock
@@ -0,0 +1,328 @@
+# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
+
+
+[[projects]]
+  digest = "1:9f3b30d9f8e0d7040f729b82dcbc8f0dead820a133b3147ce355fc451f32d761"
+  name = "github.com/BurntSushi/toml"
+  packages = ["."]
+  pruneopts = "UT"
+  revision = "3012a1dbe2e4bd1391d42b32f0577cb7bbc7f005"
+  version = "v0.3.1"
+
+[[projects]]
+  digest = "1:d6afaeed1502aa28e80a4ed0981d570ad91b2579193404256ce672ed0a609e0d"
+  name = "github.com/beorn7/perks"
+  packages = ["quantile"]
+  pruneopts = "UT"
+  revision = "37c8de3658fcb183f997c4e13e8337516ab753e6"
+  version = "v1.0.1"
+
+[[projects]]
+  branch = "master"
+  digest = "1:4c4c33075b704791d6a7f09dfb55c66769e8a1dc6adf87026292d274fe8ad113"
+  name = "github.com/codahale/hdrhistogram"
+  packages = ["."]
+  pruneopts = "UT"
+  revision = "3a0bb77429bd3a61596f5e8a3172445844342120"
+
+[[projects]]
+  branch = "master"
+  digest = "1:a382acd6150713655ded76ab5fbcbc7924a7808dab4312dda5d1f23dd8ce5277"
+  name = "github.com/crossdock/crossdock-go"
+  packages = [
+    ".",
+    "assert",
+    "require",
+  ]
+  pruneopts = "UT"
+  revision = "049aabb0122b03bc9bd30cab8f3f91fb60166361"
+
+[[projects]]
+  digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec"
+  name = "github.com/davecgh/go-spew"
+  packages = ["spew"]
+  pruneopts = "UT"
+  revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73"
+  version = "v1.1.1"
+
+[[projects]]
+  digest = "1:7ae311278f7ccaa724de8f2cdec0a507ba3ee6dea8c77237e8157bcf64b0f28b"
+  name = "github.com/golang/mock"
+  packages = ["gomock"]
+  pruneopts = "UT"
+  revision = "3a35fb6e3e18b9dbfee291262260dee7372d2a92"
+  version = "v1.4.3"
+
+[[projects]]
+  digest = "1:573ca21d3669500ff845bdebee890eb7fc7f0f50c59f2132f2a0c6b03d85086a"
+  name = "github.com/golang/protobuf"
+  packages = ["proto"]
+  pruneopts = "UT"
+  revision = "6c65a5562fc06764971b7c5d05c76c75e84bdbf7"
+  version = "v1.3.2"
+
+[[projects]]
+  digest = "1:ff5ebae34cfbf047d505ee150de27e60570e8c394b3b8fdbb720ff6ac71985fc"
+  name = "github.com/matttproud/golang_protobuf_extensions"
+  packages = ["pbutil"]
+  pruneopts = "UT"
+  revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c"
+  version = "v1.0.1"
+
+[[projects]]
+  digest = "1:727b8f567a30d0739d6c26b9472b3422b351c93cf62095164c845a54b16fc18e"
+  name = "github.com/opentracing/opentracing-go"
+  packages = [
+    ".",
+    "ext",
+    "harness",
+    "log",
+  ]
+  pruneopts = "UT"
+  revision = "659c90643e714681897ec2521c60567dd21da733"
+  version = "v1.1.0"
+
+[[projects]]
+  digest = "1:cf31692c14422fa27c83a05292eb5cbe0fb2775972e8f1f8446a71549bd8980b"
+  name = "github.com/pkg/errors"
+  packages = ["."]
+  pruneopts = "UT"
+  revision = "ba968bfe8b2f7e042a574c888954fccecfa385b4"
+  version = "v0.8.1"
+
+[[projects]]
+  digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe"
+  name = "github.com/pmezard/go-difflib"
+  packages = ["difflib"]
+  pruneopts = "UT"
+  revision = "792786c7400a136282c1664665ae0a8db921c6c2"
+  version = "v1.0.0"
+
+[[projects]]
+  digest = "1:7097829edd12fd7211fca0d29496b44f94ef9e6d72f88fb64f3d7b06315818ad"
+  name = "github.com/prometheus/client_golang"
+  packages = [
+    "prometheus",
+    "prometheus/internal",
+  ]
+  pruneopts = "UT"
+  revision = "170205fb58decfd011f1550d4cfb737230d7ae4f"
+  version = "v1.1.0"
+
+[[projects]]
+  branch = "master"
+  digest = "1:2d5cd61daa5565187e1d96bae64dbbc6080dacf741448e9629c64fd93203b0d4"
+  name = "github.com/prometheus/client_model"
+  packages = ["go"]
+  pruneopts = "UT"
+  revision = "14fe0d1b01d4d5fc031dd4bec1823bd3ebbe8016"
+
+[[projects]]
+  digest = "1:f119e3205d3a1f0f19dbd7038eb37528e2c6f0933269dc344e305951fb87d632"
+  name = "github.com/prometheus/common"
+  packages = [
+    "expfmt",
+    "internal/bitbucket.org/ww/goautoneg",
+    "model",
+  ]
+  pruneopts = "UT"
+  revision = "287d3e634a1e550c9e463dd7e5a75a422c614505"
+  version = "v0.7.0"
+
+[[projects]]
+  digest = "1:a210815b437763623ecca8eb91e6a0bf4f2d6773c5a6c9aec0e28f19e5fd6deb"
+  name = "github.com/prometheus/procfs"
+  packages = [
+    ".",
+    "internal/fs",
+    "internal/util",
+  ]
+  pruneopts = "UT"
+  revision = "499c85531f756d1129edd26485a5f73871eeb308"
+  version = "v0.0.5"
+
+[[projects]]
+  digest = "1:0496f0e99014b7fd0a560c539f51d0882731137b85494142f47e550e4657176a"
+  name = "github.com/stretchr/testify"
+  packages = [
+    "assert",
+    "require",
+    "suite",
+  ]
+  pruneopts = "UT"
+  revision = "221dbe5ed46703ee255b1da0dec05086f5035f62"
+  version = "v1.4.0"
+
+[[projects]]
+  digest = "1:0ec60ffd594af00ba1660bc746aa0e443d27dd4003dee55f9d08a0b4ff5431a3"
+  name = "github.com/uber/jaeger-lib"
+  packages = [
+    "metrics",
+    "metrics/metricstest",
+    "metrics/prometheus",
+  ]
+  pruneopts = "UT"
+  revision = "a87ae9d84fb038a8d79266298970720be7c80fcd"
+  version = "v2.2.0"
+
+[[projects]]
+  digest = "1:0bdcb0c740d79d400bd3f7946ac22a715c94db62b20bfd2e01cd50693aba0600"
+  name = "go.uber.org/atomic"
+  packages = ["."]
+  pruneopts = "UT"
+  revision = "9dc4df04d0d1c39369750a9f6c32c39560672089"
+  version = "v1.5.0"
+
+[[projects]]
+  digest = "1:002ebc50f3ef475ac325e1904be931d9dcba6dc6d73b5682afce0c63436e3902"
+  name = "go.uber.org/multierr"
+  packages = ["."]
+  pruneopts = "UT"
+  revision = "c3fc3d02ec864719d8e25be2d7dde1e35a36aa27"
+  version = "v1.3.0"
+
+[[projects]]
+  branch = "master"
+  digest = "1:3032e90a153750ea149f68bf081f97ca738f041fba45c41c80737f572ffdf2f4"
+  name = "go.uber.org/tools"
+  packages = ["update-license"]
+  pruneopts = "UT"
+  revision = "2cfd321de3ee5d5f8a5fda2521d1703478334d98"
+
+[[projects]]
+  digest = "1:98a70115729234dc73ee7bb83973cb39cb8fedf278d17df77264382bad0183ec"
+  name = "go.uber.org/zap"
+  packages = [
+    ".",
+    "buffer",
+    "internal/bufferpool",
+    "internal/color",
+    "internal/exit",
+    "zapcore",
+    "zaptest/observer",
+  ]
+  pruneopts = "UT"
+  revision = "a6015e13fab9b744d96085308ce4e8f11bad1996"
+  version = "v1.12.0"
+
+[[projects]]
+  branch = "master"
+  digest = "1:21d7bad9b7da270fd2d50aba8971a041bd691165c95096a2a4c68db823cbc86a"
+  name = "golang.org/x/lint"
+  packages = [
+    ".",
+    "golint",
+  ]
+  pruneopts = "UT"
+  revision = "16217165b5de779cb6a5e4fc81fa9c1166fda457"
+
+[[projects]]
+  branch = "master"
+  digest = "1:f8b491a7c25030a895a0e579742d07136e6958e77ef2d46e769db8eec4e58fcd"
+  name = "golang.org/x/net"
+  packages = [
+    "context",
+    "context/ctxhttp",
+  ]
+  pruneopts = "UT"
+  revision = "0deb6923b6d97481cb43bc1043fe5b72a0143032"
+
+[[projects]]
+  branch = "master"
+  digest = "1:5dfb17d45415b7b8927382f53955a66f55f9d9d11557aa82f7f481d642ab247a"
+  name = "golang.org/x/sys"
+  packages = ["windows"]
+  pruneopts = "UT"
+  revision = "f43be2a4598cf3a47be9f94f0c28197ed9eae611"
+
+[[projects]]
+  branch = "master"
+  digest = "1:bae8b3bf837d9d7f601776f37f44e031d46943677beff8fb2eb9c7317d44de2f"
+  name = "golang.org/x/tools"
+  packages = [
+    "go/analysis",
+    "go/analysis/passes/inspect",
+    "go/ast/astutil",
+    "go/ast/inspector",
+    "go/buildutil",
+    "go/gcexportdata",
+    "go/internal/gcimporter",
+    "go/internal/packagesdriver",
+    "go/packages",
+    "go/types/objectpath",
+    "go/types/typeutil",
+    "internal/fastwalk",
+    "internal/gopathwalk",
+    "internal/semver",
+    "internal/span",
+  ]
+  pruneopts = "UT"
+  revision = "8dbcdeb83d3faec5315146800b375c4962a42fc6"
+
+[[projects]]
+  digest = "1:59f10c1537d2199d9115d946927fe31165959a95190849c82ff11e05803528b0"
+  name = "gopkg.in/yaml.v2"
+  packages = ["."]
+  pruneopts = "UT"
+  revision = "f221b8435cfb71e54062f6c6e99e9ade30b124d5"
+  version = "v2.2.4"
+
+[[projects]]
+  digest = "1:131158a88aad1f94854d0aa21a64af2802d0a470fb0f01cb33c04fafd2047111"
+  name = "honnef.co/go/tools"
+  packages = [
+    "arg",
+    "cmd/staticcheck",
+    "config",
+    "deprecated",
+    "facts",
+    "functions",
+    "go/types/typeutil",
+    "internal/cache",
+    "internal/passes/buildssa",
+    "internal/renameio",
+    "internal/sharedcheck",
+    "lint",
+    "lint/lintdsl",
+    "lint/lintutil",
+    "lint/lintutil/format",
+    "loader",
+    "printf",
+    "simple",
+    "ssa",
+    "ssautil",
+    "staticcheck",
+    "staticcheck/vrp",
+    "stylecheck",
+    "unused",
+    "version",
+  ]
+  pruneopts = "UT"
+  revision = "afd67930eec2a9ed3e9b19f684d17a062285f16a"
+  version = "2019.2.3"
+
+[solve-meta]
+  analyzer-name = "dep"
+  analyzer-version = 1
+  input-imports = [
+    "github.com/crossdock/crossdock-go",
+    "github.com/golang/mock/gomock",
+    "github.com/opentracing/opentracing-go",
+    "github.com/opentracing/opentracing-go/ext",
+    "github.com/opentracing/opentracing-go/harness",
+    "github.com/opentracing/opentracing-go/log",
+    "github.com/pkg/errors",
+    "github.com/prometheus/client_golang/prometheus",
+    "github.com/stretchr/testify/assert",
+    "github.com/stretchr/testify/require",
+    "github.com/stretchr/testify/suite",
+    "github.com/uber/jaeger-lib/metrics",
+    "github.com/uber/jaeger-lib/metrics/metricstest",
+    "github.com/uber/jaeger-lib/metrics/prometheus",
+    "go.uber.org/atomic",
+    "go.uber.org/zap",
+    "go.uber.org/zap/zapcore",
+    "go.uber.org/zap/zaptest/observer",
+  ]
+  solver-name = "gps-cdcl"
+  solver-version = 1
diff --git a/vendor/github.com/uber/jaeger-client-go/Gopkg.toml b/vendor/github.com/uber/jaeger-client-go/Gopkg.toml
new file mode 100644
index 0000000..1fed7f8
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/Gopkg.toml
@@ -0,0 +1,31 @@
+[[constraint]]
+  name = "github.com/crossdock/crossdock-go"
+  branch = "master"
+
+[[constraint]]
+  name = "github.com/opentracing/opentracing-go"
+  version = "^1.1"
+
+[[constraint]]
+  name = "github.com/prometheus/client_golang"
+  version = "^1"
+
+[[constraint]]
+  name = "github.com/stretchr/testify"
+  version = "^1.1.3"
+
+[[constraint]]
+  name = "go.uber.org/atomic"
+  version = "^1"
+
+[[constraint]]
+  name = "github.com/uber/jaeger-lib"
+  version = "^2.2"
+
+[[constraint]]
+  name = "go.uber.org/zap"
+  version = "^1"
+
+[prune]
+  go-tests = true
+  unused-packages = true
diff --git a/vendor/github.com/uber/jaeger-client-go/LICENSE b/vendor/github.com/uber/jaeger-client-go/LICENSE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/LICENSE
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/vendor/github.com/uber/jaeger-client-go/Makefile b/vendor/github.com/uber/jaeger-client-go/Makefile
new file mode 100644
index 0000000..d5e962c
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/Makefile
@@ -0,0 +1,134 @@
+PROJECT_ROOT=github.com/uber/jaeger-client-go
+PACKAGES := . $(shell go list ./... | awk -F/ 'NR>1 {print "./"$$4"/..."}' | grep -v -e ./thrift-gen/... -e ./thrift/... | sort -u)
+# all .go files that don't exist in hidden directories
+ALL_SRC := $(shell find . -name "*.go" | grep -v -e vendor -e thrift-gen -e ./thrift/ \
+        -e ".*/\..*" \
+        -e ".*/_.*" \
+        -e ".*/mocks.*")
+
+USE_DEP := true
+
+-include crossdock/rules.mk
+
+RACE=-race
+GOTEST=go test -v $(RACE)
+GOLINT=golint
+GOVET=go vet
+GOFMT=gofmt
+FMT_LOG=fmt.log
+LINT_LOG=lint.log
+
+THRIFT_VER=0.9.3
+THRIFT_IMG=thrift:$(THRIFT_VER)
+THRIFT=docker run -v "${PWD}:/data" $(THRIFT_IMG) thrift
+THRIFT_GO_ARGS=thrift_import="github.com/apache/thrift/lib/go/thrift"
+THRIFT_GEN_DIR=thrift-gen
+
+PASS=$(shell printf "\033[32mPASS\033[0m")
+FAIL=$(shell printf "\033[31mFAIL\033[0m")
+COLORIZE=sed ''/PASS/s//$(PASS)/'' | sed ''/FAIL/s//$(FAIL)/''
+
+.DEFAULT_GOAL := test-and-lint
+
+.PHONY: test-and-lint
+test-and-lint: test fmt lint
+
+.PHONY: test
+test:
+ifeq ($(USE_DEP),true)
+	dep check
+endif
+	bash -c "set -e; set -o pipefail; $(GOTEST) $(PACKAGES) | $(COLORIZE)"
+
+.PHONY: fmt
+fmt:
+	$(GOFMT) -e -s -l -w $(ALL_SRC)
+	./scripts/updateLicenses.sh
+
+.PHONY: lint
+lint:
+	$(GOVET) $(PACKAGES)
+	@cat /dev/null > $(LINT_LOG)
+	@$(foreach pkg, $(PACKAGES), $(GOLINT) $(pkg) | grep -v crossdock/thrift >> $(LINT_LOG) || true;)
+	@[ ! -s "$(LINT_LOG)" ] || (echo "Lint Failures" | cat - $(LINT_LOG) && false)
+	@$(GOFMT) -e -s -l $(ALL_SRC) > $(FMT_LOG)
+	./scripts/updateLicenses.sh >> $(FMT_LOG)
+	@[ ! -s "$(FMT_LOG)" ] || (echo "go fmt or license check failures, run 'make fmt'" | cat - $(FMT_LOG) && false)
+
+
+.PHONY: install
+install:
+	@echo install: USE_DEP=$(USE_DEP) USE_GLIDE=$(USE_GLIDE)
+ifeq ($(USE_DEP),true)
+	dep version || make install-dep
+	dep ensure
+endif
+ifeq ($(USE_GLIDE),true)
+	glide --version || go get github.com/Masterminds/glide
+	glide install
+endif
+
+
+.PHONY: cover
+cover:
+	$(GOTEST) -cover -coverprofile cover.out $(PACKAGES)
+
+.PHONY: cover-html
+cover-html: cover
+	go tool cover -html=cover.out -o cover.html
+
+# This is not part of the regular test target because we don't want to slow it
+# down.
+.PHONY: test-examples
+test-examples:
+	make -C examples
+
+.PHONY: thrift
+thrift: idl-submodule thrift-compile
+
+# TODO at the moment we're not generating tchan_*.go files
+.PHONY: thrift-compile
+thrift-compile: thrift-image
+	$(THRIFT) -o /data --gen go:$(THRIFT_GO_ARGS) --out /data/$(THRIFT_GEN_DIR) /data/idl/thrift/agent.thrift
+	$(THRIFT) -o /data --gen go:$(THRIFT_GO_ARGS) --out /data/$(THRIFT_GEN_DIR) /data/idl/thrift/sampling.thrift
+	$(THRIFT) -o /data --gen go:$(THRIFT_GO_ARGS) --out /data/$(THRIFT_GEN_DIR) /data/idl/thrift/jaeger.thrift
+	$(THRIFT) -o /data --gen go:$(THRIFT_GO_ARGS) --out /data/$(THRIFT_GEN_DIR) /data/idl/thrift/zipkincore.thrift
+	$(THRIFT) -o /data --gen go:$(THRIFT_GO_ARGS) --out /data/$(THRIFT_GEN_DIR) /data/idl/thrift/baggage.thrift
+	$(THRIFT) -o /data --gen go:$(THRIFT_GO_ARGS) --out /data/crossdock/thrift/ /data/idl/thrift/crossdock/tracetest.thrift
+	sed -i '' 's|"zipkincore"|"$(PROJECT_ROOT)/thrift-gen/zipkincore"|g' $(THRIFT_GEN_DIR)/agent/*.go
+	sed -i '' 's|"jaeger"|"$(PROJECT_ROOT)/thrift-gen/jaeger"|g' $(THRIFT_GEN_DIR)/agent/*.go
+	sed -i '' 's|"github.com/apache/thrift/lib/go/thrift"|"github.com/uber/jaeger-client-go/thrift"|g' \
+		$(THRIFT_GEN_DIR)/*/*.go crossdock/thrift/tracetest/*.go
+	rm -rf thrift-gen/*/*-remote
+	rm -rf crossdock/thrift/*/*-remote
+	rm -rf thrift-gen/jaeger/collector.go
+
+.PHONY: idl-submodule
+idl-submodule:
+	git submodule init
+	git submodule update
+
+.PHONY: thrift-image
+thrift-image:
+	$(THRIFT) -version
+
+.PHONY: install-dep
+install-dep:
+	- curl -L -s https://github.com/golang/dep/releases/download/v0.5.0/dep-linux-amd64 -o $$GOPATH/bin/dep
+	- chmod +x $$GOPATH/bin/dep
+
+.PHONY: install-ci
+install-ci: install
+	go get github.com/wadey/gocovmerge
+	go get github.com/mattn/goveralls
+	go get golang.org/x/tools/cmd/cover
+	go get golang.org/x/lint/golint
+
+.PHONY: test-ci
+test-ci: cover
+ifeq ($(CI_SKIP_LINT),true)
+	echo 'skipping lint'
+else
+	make lint
+endif
+
diff --git a/vendor/github.com/uber/jaeger-client-go/README.md b/vendor/github.com/uber/jaeger-client-go/README.md
new file mode 100644
index 0000000..7c348e7
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/README.md
@@ -0,0 +1,318 @@
+[![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] [![OpenTracing 1.0 Enabled][ot-img]][ot-url]
+
+# Jaeger Bindings for Go OpenTracing API
+
+Instrumentation library that implements an
+[OpenTracing Go](https://github.com/opentracing/opentracing-go) Tracer for Jaeger (https://jaegertracing.io).
+
+**IMPORTANT**: The library's import path is based on its original location under `github.com/uber`. Do not try to import it as `github.com/jaegertracing`, it will not compile. We might revisit this in the next major release.
+  * :white_check_mark: `import "github.com/uber/jaeger-client-go"`
+  * :x: `import "github.com/jaegertracing/jaeger-client-go"`
+
+## How to Contribute
+
+Please see [CONTRIBUTING.md](CONTRIBUTING.md).
+
+## Installation
+
+We recommended using a dependency manager like [dep](https://golang.github.io/dep/)
+and [semantic versioning](http://semver.org/) when including this library into an application.
+For example, Jaeger backend imports this library like this:
+
+```toml
+[[constraint]]
+  name = "github.com/uber/jaeger-client-go"
+  version = "2.17"
+```
+
+If you instead want to use the latest version in `master`, you can pull it via `go get`.
+Note that during `go get` you may see build errors due to incompatible dependencies, which is why
+we recommend using semantic versions for dependencies.  The error  may be fixed by running
+`make install` (it will install `dep` if you don't have it):
+
+```shell
+go get -u github.com/uber/jaeger-client-go/
+cd $GOPATH/src/github.com/uber/jaeger-client-go/
+git submodule update --init --recursive
+make install
+```
+
+## Initialization
+
+See tracer initialization examples in [godoc](https://godoc.org/github.com/uber/jaeger-client-go/config#pkg-examples)
+and [config/example_test.go](./config/example_test.go).
+
+### Environment variables
+
+The tracer can be initialized with values coming from environment variables. None of the env vars are required
+and all of them can be overridden via direct setting of the property on the configuration object.
+
+Property| Description
+--- | ---
+JAEGER_SERVICE_NAME | The service name
+JAEGER_AGENT_HOST | The hostname for communicating with agent via UDP
+JAEGER_AGENT_PORT | The port for communicating with agent via UDP
+JAEGER_ENDPOINT | The HTTP endpoint for sending spans directly to a collector, i.e. http://jaeger-collector:14268/api/traces
+JAEGER_USER | Username to send as part of "Basic" authentication to the collector endpoint
+JAEGER_PASSWORD | Password to send as part of "Basic" authentication to the collector endpoint
+JAEGER_REPORTER_LOG_SPANS | Whether the reporter should also log the spans
+JAEGER_REPORTER_MAX_QUEUE_SIZE | The reporter's maximum queue size
+JAEGER_REPORTER_FLUSH_INTERVAL | The reporter's flush interval, with units, e.g. "500ms" or "2s" ([valid units][timeunits])
+JAEGER_SAMPLER_TYPE | The sampler type
+JAEGER_SAMPLER_PARAM | The sampler parameter (number)
+JAEGER_SAMPLER_MANAGER_HOST_PORT | The HTTP endpoint when using the remote sampler, i.e. http://jaeger-agent:5778/sampling
+JAEGER_SAMPLER_MAX_OPERATIONS | The maximum number of operations that the sampler will keep track of
+JAEGER_SAMPLER_REFRESH_INTERVAL | How often the remotely controlled sampler will poll jaeger-agent for the appropriate sampling strategy, with units, e.g. "1m" or "30s" ([valid units][timeunits])
+JAEGER_TAGS | A comma separated list of `name = value` tracer level tags, which get added to all reported spans. The value can also refer to an environment variable using the format `${envVarName:default}`, where the `:default` is optional, and identifies a value to be used if the environment variable cannot be found
+JAEGER_DISABLED | Whether the tracer is disabled or not. If true, the default `opentracing.NoopTracer` is used.
+JAEGER_RPC_METRICS | Whether to store RPC metrics
+
+By default, the client sends traces via UDP to the agent at `localhost:6831`. Use `JAEGER_AGENT_HOST` and
+`JAEGER_AGENT_PORT` to send UDP traces to a different `host:port`. If `JAEGER_ENDPOINT` is set, the client sends traces
+to the endpoint via `HTTP`, making the `JAEGER_AGENT_HOST` and `JAEGER_AGENT_PORT` unused. If `JAEGER_ENDPOINT` is
+secured, HTTP basic authentication can be performed by setting the `JAEGER_USER` and `JAEGER_PASSWORD` environment
+variables.
+
+### Closing the tracer via `io.Closer`
+
+The constructor function for Jaeger Tracer returns the tracer itself and an `io.Closer` instance.
+It is recommended to structure your `main()` so that it calls the `Close()` function on the closer
+before exiting, e.g.
+
+```go
+tracer, closer, err := cfg.NewTracer(...)
+defer closer.Close()
+```
+
+This is especially useful for command-line tools that enable tracing, as well as
+for the long-running apps that support graceful shutdown. For example, if your deployment
+system sends SIGTERM instead of killing the process and you trap that signal to do a graceful
+exit, then having `defer closer.Close()` ensures that all buffered spans are flushed.
+
+### Metrics & Monitoring
+
+The tracer emits a number of different metrics, defined in
+[metrics.go](metrics.go). The monitoring backend is expected to support
+tag-based metric names, e.g. instead of `statsd`-style string names
+like `counters.my-service.jaeger.spans.started.sampled`, the metrics
+are defined by a short name and a collection of key/value tags, for
+example: `name:jaeger.traces, state:started, sampled:y`. See [metrics.go](./metrics.go)
+file for the full list and descriptions of emitted metrics.
+
+The monitoring backend is represented by the `metrics.Factory` interface from package
+[`"github.com/uber/jaeger-lib/metrics"`](https://github.com/jaegertracing/jaeger-lib/tree/master/metrics).  An implementation
+of that interface can be passed as an option to either the Configuration object or the Tracer
+constructor, for example:
+
+```go
+import (
+    "github.com/uber/jaeger-client-go/config"
+    "github.com/uber/jaeger-lib/metrics/prometheus"
+)
+
+    metricsFactory := prometheus.New()
+    tracer, closer, err := config.Configuration{
+        ServiceName: "your-service-name",
+    }.NewTracer(
+        config.Metrics(metricsFactory),
+    )
+```
+
+By default, a no-op `metrics.NullFactory` is used.
+
+### Logging
+
+The tracer can be configured with an optional logger, which will be
+used to log communication errors, or log spans if a logging reporter
+option is specified in the configuration. The logging API is abstracted
+by the [Logger](logger.go) interface. A logger instance implementing
+this interface can be set on the `Config` object before calling the
+`New` method.
+
+Besides the [zap](https://github.com/uber-go/zap) implementation
+bundled with this package there is also a [go-kit](https://github.com/go-kit/kit)
+one in the [jaeger-lib](https://github.com/jaegertracing/jaeger-lib) repository.
+
+## Instrumentation for Tracing
+
+Since this tracer is fully compliant with OpenTracing API 1.0,
+all code instrumentation should only use the API itself, as described
+in the [opentracing-go](https://github.com/opentracing/opentracing-go) documentation.
+
+## Features
+
+### Reporters
+
+A "reporter" is a component that receives the finished spans and reports
+them to somewhere. Under normal circumstances, the Tracer
+should use the default `RemoteReporter`, which sends the spans out of
+process via configurable "transport". For testing purposes, one can
+use an `InMemoryReporter` that accumulates spans in a buffer and
+allows to retrieve them for later verification. Also available are
+`NullReporter`, a no-op reporter that does nothing, a `LoggingReporter`
+which logs all finished spans using their `String()` method, and a
+`CompositeReporter` that can be used to combine more than one reporter
+into one, e.g. to attach a logging reporter to the main remote reporter.
+
+### Span Reporting Transports
+
+The remote reporter uses "transports" to actually send the spans out
+of process. Currently the supported transports include:
+  * [Jaeger Thrift](https://github.com/jaegertracing/jaeger-idl/blob/master/thrift/agent.thrift) over UDP or HTTP,
+  * [Zipkin Thrift](https://github.com/jaegertracing/jaeger-idl/blob/master/thrift/zipkincore.thrift) over HTTP.
+
+### Sampling
+
+The tracer does not record all spans, but only those that have the
+sampling bit set in the `flags`. When a new trace is started and a new
+unique ID is generated, a sampling decision is made whether this trace
+should be sampled. The sampling decision is propagated to all downstream
+calls via the `flags` field of the trace context. The following samplers
+are available:
+  1. `RemotelyControlledSampler` uses one of the other simpler samplers
+     and periodically updates it by polling an external server. This
+     allows dynamic control of the sampling strategies.
+  1. `ConstSampler` always makes the same sampling decision for all
+     trace IDs. it can be configured to either sample all traces, or
+     to sample none.
+  1. `ProbabilisticSampler` uses a fixed sampling rate as a probability
+     for a given trace to be sampled. The actual decision is made by
+     comparing the trace ID with a random number multiplied by the
+     sampling rate.
+  1. `RateLimitingSampler` can be used to allow only a certain fixed
+     number of traces to be sampled per second.
+
+#### Delayed sampling
+
+Version 2.20 introduced the ability to delay sampling decisions in the life cycle
+of the root span. It involves several features and architectural changes:
+  * **Shared sampling state**: the sampling state is shared across all local
+    (i.e. in-process) spans for a given trace.
+  * **New `SamplerV2` API** allows the sampler to be called at multiple points 
+    in the life cycle of a span:
+    * on span creation
+    * on overwriting span operation name
+    * on setting span tags
+    * on finishing the span
+  * **Final/non-final sampling state**: the new `SamplerV2` API allows the sampler
+    to indicate if the negative sampling decision is final or not (positive sampling
+    decisions are always final). If the decision is not final, the sampler will be
+    called again on further span life cycle events, like setting tags.
+
+These new features are used in the experimental `x.TagMatchingSampler`, which
+can sample a trace based on a certain tag added to the root
+span or one of its local (in-process) children. The sampler can be used with
+another experimental `x.PrioritySampler` that allows multiple samplers to try
+to make a sampling decision, in a certain priority order.
+
+### Baggage Injection
+
+The OpenTracing spec allows for [baggage][baggage], which are key value pairs that are added
+to the span context and propagated throughout the trace. An external process can inject baggage
+by setting the special HTTP Header `jaeger-baggage` on a request:
+
+```sh
+curl -H "jaeger-baggage: key1=value1, key2=value2" http://myhost.com
+```
+
+Baggage can also be programatically set inside your service:
+
+```go
+if span := opentracing.SpanFromContext(ctx); span != nil {
+    span.SetBaggageItem("key", "value")
+}
+```
+
+Another service downstream of that can retrieve the baggage in a similar way:
+
+```go
+if span := opentracing.SpanFromContext(ctx); span != nil {
+    val := span.BaggageItem("key")
+    println(val)
+}
+```
+
+### Debug Traces (Forced Sampling)
+
+#### Programmatically
+
+The OpenTracing API defines a `sampling.priority` standard tag that
+can be used to affect the sampling of a span and its children:
+
+```go
+import (
+    "github.com/opentracing/opentracing-go"
+    "github.com/opentracing/opentracing-go/ext"
+)
+
+span := opentracing.SpanFromContext(ctx)
+ext.SamplingPriority.Set(span, 1)
+```
+
+#### Via HTTP Headers
+
+Jaeger Tracer also understands a special HTTP Header `jaeger-debug-id`,
+which can be set in the incoming request, e.g.
+
+```sh
+curl -H "jaeger-debug-id: some-correlation-id" http://myhost.com
+```
+
+When Jaeger sees this header in the request that otherwise has no
+tracing context, it ensures that the new trace started for this
+request will be sampled in the "debug" mode (meaning it should survive
+all downsampling that might happen in the collection pipeline), and the
+root span will have a tag as if this statement was executed:
+
+```go
+span.SetTag("jaeger-debug-id", "some-correlation-id")
+```
+
+This allows using Jaeger UI to find the trace by this tag.
+
+### Zipkin HTTP B3 compatible header propagation
+
+Jaeger Tracer supports Zipkin B3 Propagation HTTP headers, which are used
+by a lot of Zipkin tracers. This means that you can use Jaeger in conjunction with e.g. [these OpenZipkin tracers](https://github.com/openzipkin).
+
+However it is not the default propagation format, see [here](zipkin/README.md#NewZipkinB3HTTPHeaderPropagator) how to set it up.
+
+## SelfRef
+
+Jaeger Tracer supports an additional [span reference][] type call `Self`, which was proposed
+to the OpenTracing Specification (https://github.com/opentracing/specification/issues/81)
+but not yet accepted. This allows the caller to provide an already created `SpanContext`
+when starting a new span. The `Self` reference bypasses trace and span id generation,
+as well as sampling decisions (i.e. the sampling bit in the `SpanContext.flags` must be
+set appropriately by the caller).
+
+The `Self` reference supports the following use cases:
+  * the ability to provide externally generated trace and span IDs
+  * appending data to the same span from different processes, such as loading and continuing spans/traces from offline (ie log-based) storage
+
+Usage requires passing in a `SpanContext` and the `jaeger.Self` reference type:
+```
+span := tracer.StartSpan(
+    "continued_span",
+    jaeger.SelfRef(yourSpanContext),
+)
+...
+defer span.Finish()
+```
+
+## License
+
+[Apache 2.0 License](LICENSE).
+
+
+[doc-img]: https://godoc.org/github.com/uber/jaeger-client-go?status.svg
+[doc]: https://godoc.org/github.com/uber/jaeger-client-go
+[ci-img]: https://travis-ci.org/jaegertracing/jaeger-client-go.svg?branch=master
+[ci]: https://travis-ci.org/jaegertracing/jaeger-client-go
+[cov-img]: https://codecov.io/gh/jaegertracing/jaeger-client-go/branch/master/graph/badge.svg
+[cov]: https://codecov.io/gh/jaegertracing/jaeger-client-go
+[ot-img]: https://img.shields.io/badge/OpenTracing--1.0-enabled-blue.svg
+[ot-url]: http://opentracing.io
+[baggage]: https://github.com/opentracing/specification/blob/master/specification.md#set-a-baggage-item
+[timeunits]: https://golang.org/pkg/time/#ParseDuration
+[span reference]: https://github.com/opentracing/specification/blob/1.1/specification.md#references-between-spans
diff --git a/vendor/github.com/uber/jaeger-client-go/RELEASE.md b/vendor/github.com/uber/jaeger-client-go/RELEASE.md
new file mode 100644
index 0000000..115e49a
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/RELEASE.md
@@ -0,0 +1,11 @@
+# Release Process
+
+1. Create a PR "Preparing for release X.Y.Z" against master branch
+    * Alter CHANGELOG.md from `<placeholder_version> (unreleased)` to `<X.Y.Z> (YYYY-MM-DD)`
+    * Update `JaegerClientVersion` in constants.go to `Go-X.Y.Z`
+2. Create a release "Release X.Y.Z" on Github
+    * Create Tag `vX.Y.Z`
+    * Copy CHANGELOG.md into the release notes
+3. Create a PR "Back to development" against master branch
+    * Add `<next_version> (unreleased)` to CHANGELOG.md
+    * Update `JaegerClientVersion` in constants.go to `Go-<next_version>dev`
diff --git a/vendor/github.com/uber/jaeger-client-go/baggage_setter.go b/vendor/github.com/uber/jaeger-client-go/baggage_setter.go
new file mode 100644
index 0000000..1037ca0
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/baggage_setter.go
@@ -0,0 +1,77 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import (
+	"github.com/opentracing/opentracing-go/log"
+
+	"github.com/uber/jaeger-client-go/internal/baggage"
+)
+
+// baggageSetter is an actor that can set a baggage value on a Span given certain
+// restrictions (eg. maxValueLength).
+type baggageSetter struct {
+	restrictionManager baggage.RestrictionManager
+	metrics            *Metrics
+}
+
+func newBaggageSetter(restrictionManager baggage.RestrictionManager, metrics *Metrics) *baggageSetter {
+	return &baggageSetter{
+		restrictionManager: restrictionManager,
+		metrics:            metrics,
+	}
+}
+
+// (NB) span should hold the lock before making this call
+func (s *baggageSetter) setBaggage(span *Span, key, value string) {
+	var truncated bool
+	var prevItem string
+	restriction := s.restrictionManager.GetRestriction(span.serviceName(), key)
+	if !restriction.KeyAllowed() {
+		s.logFields(span, key, value, prevItem, truncated, restriction.KeyAllowed())
+		s.metrics.BaggageUpdateFailure.Inc(1)
+		return
+	}
+	if len(value) > restriction.MaxValueLength() {
+		truncated = true
+		value = value[:restriction.MaxValueLength()]
+		s.metrics.BaggageTruncate.Inc(1)
+	}
+	prevItem = span.context.baggage[key]
+	s.logFields(span, key, value, prevItem, truncated, restriction.KeyAllowed())
+	span.context = span.context.WithBaggageItem(key, value)
+	s.metrics.BaggageUpdateSuccess.Inc(1)
+}
+
+func (s *baggageSetter) logFields(span *Span, key, value, prevItem string, truncated, valid bool) {
+	if !span.context.IsSampled() {
+		return
+	}
+	fields := []log.Field{
+		log.String("event", "baggage"),
+		log.String("key", key),
+		log.String("value", value),
+	}
+	if prevItem != "" {
+		fields = append(fields, log.String("override", "true"))
+	}
+	if truncated {
+		fields = append(fields, log.String("truncated", "true"))
+	}
+	if !valid {
+		fields = append(fields, log.String("invalid", "true"))
+	}
+	span.logFieldsNoLocking(fields...)
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/config/config.go b/vendor/github.com/uber/jaeger-client-go/config/config.go
new file mode 100644
index 0000000..44e9353
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/config/config.go
@@ -0,0 +1,413 @@
+// Copyright (c) 2017-2018 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"strings"
+	"time"
+
+	"github.com/opentracing/opentracing-go"
+
+	"github.com/uber/jaeger-client-go"
+	"github.com/uber/jaeger-client-go/internal/baggage/remote"
+	throttler "github.com/uber/jaeger-client-go/internal/throttler/remote"
+	"github.com/uber/jaeger-client-go/rpcmetrics"
+	"github.com/uber/jaeger-client-go/transport"
+	"github.com/uber/jaeger-lib/metrics"
+)
+
+const defaultSamplingProbability = 0.001
+
+// Configuration configures and creates Jaeger Tracer
+type Configuration struct {
+	// ServiceName specifies the service name to use on the tracer.
+	// Can be provided via environment variable named JAEGER_SERVICE_NAME
+	ServiceName string `yaml:"serviceName"`
+
+	// Disabled can be provided via environment variable named JAEGER_DISABLED
+	Disabled bool `yaml:"disabled"`
+
+	// RPCMetrics can be provided via environment variable named JAEGER_RPC_METRICS
+	RPCMetrics bool `yaml:"rpc_metrics"`
+
+	// Tags can be provided via environment variable named JAEGER_TAGS
+	Tags []opentracing.Tag `yaml:"tags"`
+
+	Sampler             *SamplerConfig             `yaml:"sampler"`
+	Reporter            *ReporterConfig            `yaml:"reporter"`
+	Headers             *jaeger.HeadersConfig      `yaml:"headers"`
+	BaggageRestrictions *BaggageRestrictionsConfig `yaml:"baggage_restrictions"`
+	Throttler           *ThrottlerConfig           `yaml:"throttler"`
+}
+
+// SamplerConfig allows initializing a non-default sampler.  All fields are optional.
+type SamplerConfig struct {
+	// Type specifies the type of the sampler: const, probabilistic, rateLimiting, or remote
+	// Can be set by exporting an environment variable named JAEGER_SAMPLER_TYPE
+	Type string `yaml:"type"`
+
+	// Param is a value passed to the sampler.
+	// Valid values for Param field are:
+	// - for "const" sampler, 0 or 1 for always false/true respectively
+	// - for "probabilistic" sampler, a probability between 0 and 1
+	// - for "rateLimiting" sampler, the number of spans per second
+	// - for "remote" sampler, param is the same as for "probabilistic"
+	//   and indicates the initial sampling rate before the actual one
+	//   is received from the mothership.
+	// Can be set by exporting an environment variable named JAEGER_SAMPLER_PARAM
+	Param float64 `yaml:"param"`
+
+	// SamplingServerURL is the address of jaeger-agent's HTTP sampling server
+	// Can be set by exporting an environment variable named JAEGER_SAMPLER_MANAGER_HOST_PORT
+	SamplingServerURL string `yaml:"samplingServerURL"`
+
+	// SamplingRefreshInterval controls how often the remotely controlled sampler will poll
+	// jaeger-agent for the appropriate sampling strategy.
+	// Can be set by exporting an environment variable named JAEGER_SAMPLER_REFRESH_INTERVAL
+	SamplingRefreshInterval time.Duration `yaml:"samplingRefreshInterval"`
+
+	// MaxOperations is the maximum number of operations that the PerOperationSampler
+	// will keep track of. If an operation is not tracked, a default probabilistic
+	// sampler will be used rather than the per operation specific sampler.
+	// Can be set by exporting an environment variable named JAEGER_SAMPLER_MAX_OPERATIONS.
+	MaxOperations int `yaml:"maxOperations"`
+
+	// Opt-in feature for applications that require late binding of span name via explicit
+	// call to SetOperationName when using PerOperationSampler. When this feature is enabled,
+	// the sampler will return retryable=true from OnCreateSpan(), thus leaving the sampling
+	// decision as non-final (and the span as writeable). This may lead to degraded performance
+	// in applications that always provide the correct span name on trace creation.
+	//
+	// For backwards compatibility this option is off by default.
+	OperationNameLateBinding bool `yaml:"operationNameLateBinding"`
+
+	// Options can be used to programmatically pass additional options to the Remote sampler.
+	Options []jaeger.SamplerOption
+}
+
+// ReporterConfig configures the reporter. All fields are optional.
+type ReporterConfig struct {
+	// QueueSize controls how many spans the reporter can keep in memory before it starts dropping
+	// new spans. The queue is continuously drained by a background go-routine, as fast as spans
+	// can be sent out of process.
+	// Can be set by exporting an environment variable named JAEGER_REPORTER_MAX_QUEUE_SIZE
+	QueueSize int `yaml:"queueSize"`
+
+	// BufferFlushInterval controls how often the buffer is force-flushed, even if it's not full.
+	// It is generally not useful, as it only matters for very low traffic services.
+	// Can be set by exporting an environment variable named JAEGER_REPORTER_FLUSH_INTERVAL
+	BufferFlushInterval time.Duration
+
+	// LogSpans, when true, enables LoggingReporter that runs in parallel with the main reporter
+	// and logs all submitted spans. Main Configuration.Logger must be initialized in the code
+	// for this option to have any effect.
+	// Can be set by exporting an environment variable named JAEGER_REPORTER_LOG_SPANS
+	LogSpans bool `yaml:"logSpans"`
+
+	// LocalAgentHostPort instructs reporter to send spans to jaeger-agent at this address
+	// Can be set by exporting an environment variable named JAEGER_AGENT_HOST / JAEGER_AGENT_PORT
+	LocalAgentHostPort string `yaml:"localAgentHostPort"`
+
+	// CollectorEndpoint instructs reporter to send spans to jaeger-collector at this URL
+	// Can be set by exporting an environment variable named JAEGER_ENDPOINT
+	CollectorEndpoint string `yaml:"collectorEndpoint"`
+
+	// User instructs reporter to include a user for basic http authentication when sending spans to jaeger-collector.
+	// Can be set by exporting an environment variable named JAEGER_USER
+	User string `yaml:"user"`
+
+	// Password instructs reporter to include a password for basic http authentication when sending spans to
+	// jaeger-collector. Can be set by exporting an environment variable named JAEGER_PASSWORD
+	Password string `yaml:"password"`
+
+	// HTTPHeaders instructs the reporter to add these headers to the http request when reporting spans.
+	// This field takes effect only when using HTTPTransport by setting the CollectorEndpoint.
+	HTTPHeaders map[string]string `yaml:"http_headers"`
+}
+
+// BaggageRestrictionsConfig configures the baggage restrictions manager which can be used to whitelist
+// certain baggage keys. All fields are optional.
+type BaggageRestrictionsConfig struct {
+	// DenyBaggageOnInitializationFailure controls the startup failure mode of the baggage restriction
+	// manager. If true, the manager will not allow any baggage to be written until baggage restrictions have
+	// been retrieved from jaeger-agent. If false, the manager wil allow any baggage to be written until baggage
+	// restrictions have been retrieved from jaeger-agent.
+	DenyBaggageOnInitializationFailure bool `yaml:"denyBaggageOnInitializationFailure"`
+
+	// HostPort is the hostPort of jaeger-agent's baggage restrictions server
+	HostPort string `yaml:"hostPort"`
+
+	// RefreshInterval controls how often the baggage restriction manager will poll
+	// jaeger-agent for the most recent baggage restrictions.
+	RefreshInterval time.Duration `yaml:"refreshInterval"`
+}
+
+// ThrottlerConfig configures the throttler which can be used to throttle the
+// rate at which the client may send debug requests.
+type ThrottlerConfig struct {
+	// HostPort of jaeger-agent's credit server.
+	HostPort string `yaml:"hostPort"`
+
+	// RefreshInterval controls how often the throttler will poll jaeger-agent
+	// for more throttling credits.
+	RefreshInterval time.Duration `yaml:"refreshInterval"`
+
+	// SynchronousInitialization determines whether or not the throttler should
+	// synchronously fetch credits from the agent when an operation is seen for
+	// the first time. This should be set to true if the client will be used by
+	// a short lived service that needs to ensure that credits are fetched
+	// upfront such that sampling or throttling occurs.
+	SynchronousInitialization bool `yaml:"synchronousInitialization"`
+}
+
+type nullCloser struct{}
+
+func (*nullCloser) Close() error { return nil }
+
+// New creates a new Jaeger Tracer, and a closer func that can be used to flush buffers
+// before shutdown.
+//
+// Deprecated: use NewTracer() function
+func (c Configuration) New(
+	serviceName string,
+	options ...Option,
+) (opentracing.Tracer, io.Closer, error) {
+	if serviceName != "" {
+		c.ServiceName = serviceName
+	}
+
+	return c.NewTracer(options...)
+}
+
+// NewTracer returns a new tracer based on the current configuration, using the given options,
+// and a closer func that can be used to flush buffers before shutdown.
+func (c Configuration) NewTracer(options ...Option) (opentracing.Tracer, io.Closer, error) {
+	if c.Disabled {
+		return &opentracing.NoopTracer{}, &nullCloser{}, nil
+	}
+
+	if c.ServiceName == "" {
+		return nil, nil, errors.New("no service name provided")
+	}
+
+	opts := applyOptions(options...)
+	tracerMetrics := jaeger.NewMetrics(opts.metrics, nil)
+	if c.RPCMetrics {
+		Observer(
+			rpcmetrics.NewObserver(
+				opts.metrics.Namespace(metrics.NSOptions{Name: "jaeger-rpc", Tags: map[string]string{"component": "jaeger"}}),
+				rpcmetrics.DefaultNameNormalizer,
+			),
+		)(&opts) // adds to c.observers
+	}
+	if c.Sampler == nil {
+		c.Sampler = &SamplerConfig{
+			Type:  jaeger.SamplerTypeRemote,
+			Param: defaultSamplingProbability,
+		}
+	}
+	if c.Reporter == nil {
+		c.Reporter = &ReporterConfig{}
+	}
+
+	sampler := opts.sampler
+	if sampler == nil {
+		s, err := c.Sampler.NewSampler(c.ServiceName, tracerMetrics)
+		if err != nil {
+			return nil, nil, err
+		}
+		sampler = s
+	}
+
+	reporter := opts.reporter
+	if reporter == nil {
+		r, err := c.Reporter.NewReporter(c.ServiceName, tracerMetrics, opts.logger)
+		if err != nil {
+			return nil, nil, err
+		}
+		reporter = r
+	}
+
+	tracerOptions := []jaeger.TracerOption{
+		jaeger.TracerOptions.Metrics(tracerMetrics),
+		jaeger.TracerOptions.Logger(opts.logger),
+		jaeger.TracerOptions.CustomHeaderKeys(c.Headers),
+		jaeger.TracerOptions.Gen128Bit(opts.gen128Bit),
+		jaeger.TracerOptions.PoolSpans(opts.poolSpans),
+		jaeger.TracerOptions.ZipkinSharedRPCSpan(opts.zipkinSharedRPCSpan),
+		jaeger.TracerOptions.MaxTagValueLength(opts.maxTagValueLength),
+		jaeger.TracerOptions.NoDebugFlagOnForcedSampling(opts.noDebugFlagOnForcedSampling),
+	}
+
+	for _, tag := range opts.tags {
+		tracerOptions = append(tracerOptions, jaeger.TracerOptions.Tag(tag.Key, tag.Value))
+	}
+
+	for _, tag := range c.Tags {
+		tracerOptions = append(tracerOptions, jaeger.TracerOptions.Tag(tag.Key, tag.Value))
+	}
+
+	for _, obs := range opts.observers {
+		tracerOptions = append(tracerOptions, jaeger.TracerOptions.Observer(obs))
+	}
+
+	for _, cobs := range opts.contribObservers {
+		tracerOptions = append(tracerOptions, jaeger.TracerOptions.ContribObserver(cobs))
+	}
+
+	for format, injector := range opts.injectors {
+		tracerOptions = append(tracerOptions, jaeger.TracerOptions.Injector(format, injector))
+	}
+
+	for format, extractor := range opts.extractors {
+		tracerOptions = append(tracerOptions, jaeger.TracerOptions.Extractor(format, extractor))
+	}
+
+	if c.BaggageRestrictions != nil {
+		mgr := remote.NewRestrictionManager(
+			c.ServiceName,
+			remote.Options.Metrics(tracerMetrics),
+			remote.Options.Logger(opts.logger),
+			remote.Options.HostPort(c.BaggageRestrictions.HostPort),
+			remote.Options.RefreshInterval(c.BaggageRestrictions.RefreshInterval),
+			remote.Options.DenyBaggageOnInitializationFailure(
+				c.BaggageRestrictions.DenyBaggageOnInitializationFailure,
+			),
+		)
+		tracerOptions = append(tracerOptions, jaeger.TracerOptions.BaggageRestrictionManager(mgr))
+	}
+
+	if c.Throttler != nil {
+		debugThrottler := throttler.NewThrottler(
+			c.ServiceName,
+			throttler.Options.Metrics(tracerMetrics),
+			throttler.Options.Logger(opts.logger),
+			throttler.Options.HostPort(c.Throttler.HostPort),
+			throttler.Options.RefreshInterval(c.Throttler.RefreshInterval),
+			throttler.Options.SynchronousInitialization(
+				c.Throttler.SynchronousInitialization,
+			),
+		)
+
+		tracerOptions = append(tracerOptions, jaeger.TracerOptions.DebugThrottler(debugThrottler))
+	}
+
+	tracer, closer := jaeger.NewTracer(
+		c.ServiceName,
+		sampler,
+		reporter,
+		tracerOptions...,
+	)
+
+	return tracer, closer, nil
+}
+
+// InitGlobalTracer creates a new Jaeger Tracer, and sets it as global OpenTracing Tracer.
+// It returns a closer func that can be used to flush buffers before shutdown.
+func (c Configuration) InitGlobalTracer(
+	serviceName string,
+	options ...Option,
+) (io.Closer, error) {
+	if c.Disabled {
+		return &nullCloser{}, nil
+	}
+	tracer, closer, err := c.New(serviceName, options...)
+	if err != nil {
+		return nil, err
+	}
+	opentracing.SetGlobalTracer(tracer)
+	return closer, nil
+}
+
+// NewSampler creates a new sampler based on the configuration
+func (sc *SamplerConfig) NewSampler(
+	serviceName string,
+	metrics *jaeger.Metrics,
+) (jaeger.Sampler, error) {
+	samplerType := strings.ToLower(sc.Type)
+	if samplerType == jaeger.SamplerTypeConst {
+		return jaeger.NewConstSampler(sc.Param != 0), nil
+	}
+	if samplerType == jaeger.SamplerTypeProbabilistic {
+		if sc.Param >= 0 && sc.Param <= 1.0 {
+			return jaeger.NewProbabilisticSampler(sc.Param)
+		}
+		return nil, fmt.Errorf(
+			"invalid Param for probabilistic sampler; expecting value between 0 and 1, received %v",
+			sc.Param,
+		)
+	}
+	if samplerType == jaeger.SamplerTypeRateLimiting {
+		return jaeger.NewRateLimitingSampler(sc.Param), nil
+	}
+	if samplerType == jaeger.SamplerTypeRemote || sc.Type == "" {
+		sc2 := *sc
+		sc2.Type = jaeger.SamplerTypeProbabilistic
+		initSampler, err := sc2.NewSampler(serviceName, nil)
+		if err != nil {
+			return nil, err
+		}
+		options := []jaeger.SamplerOption{
+			jaeger.SamplerOptions.Metrics(metrics),
+			jaeger.SamplerOptions.InitialSampler(initSampler),
+			jaeger.SamplerOptions.SamplingServerURL(sc.SamplingServerURL),
+			jaeger.SamplerOptions.MaxOperations(sc.MaxOperations),
+			jaeger.SamplerOptions.OperationNameLateBinding(sc.OperationNameLateBinding),
+			jaeger.SamplerOptions.SamplingRefreshInterval(sc.SamplingRefreshInterval),
+		}
+		options = append(options, sc.Options...)
+		return jaeger.NewRemotelyControlledSampler(serviceName, options...), nil
+	}
+	return nil, fmt.Errorf("unknown sampler type (%s)", sc.Type)
+}
+
+// NewReporter instantiates a new reporter that submits spans to the collector
+func (rc *ReporterConfig) NewReporter(
+	serviceName string,
+	metrics *jaeger.Metrics,
+	logger jaeger.Logger,
+) (jaeger.Reporter, error) {
+	sender, err := rc.newTransport()
+	if err != nil {
+		return nil, err
+	}
+	reporter := jaeger.NewRemoteReporter(
+		sender,
+		jaeger.ReporterOptions.QueueSize(rc.QueueSize),
+		jaeger.ReporterOptions.BufferFlushInterval(rc.BufferFlushInterval),
+		jaeger.ReporterOptions.Logger(logger),
+		jaeger.ReporterOptions.Metrics(metrics))
+	if rc.LogSpans && logger != nil {
+		logger.Infof("Initializing logging reporter\n")
+		reporter = jaeger.NewCompositeReporter(jaeger.NewLoggingReporter(logger), reporter)
+	}
+	return reporter, err
+}
+
+func (rc *ReporterConfig) newTransport() (jaeger.Transport, error) {
+	switch {
+	case rc.CollectorEndpoint != "":
+		httpOptions := []transport.HTTPOption{transport.HTTPBatchSize(1), transport.HTTPHeaders(rc.HTTPHeaders)}
+		if rc.User != "" && rc.Password != "" {
+			httpOptions = append(httpOptions, transport.HTTPBasicAuth(rc.User, rc.Password))
+		}
+		return transport.NewHTTPTransport(rc.CollectorEndpoint, httpOptions...), nil
+	default:
+		return jaeger.NewUDPTransport(rc.LocalAgentHostPort, 0)
+	}
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/config/config_env.go b/vendor/github.com/uber/jaeger-client-go/config/config_env.go
new file mode 100644
index 0000000..a729bd8
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/config/config_env.go
@@ -0,0 +1,232 @@
+// Copyright (c) 2018 The Jaeger Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+	"fmt"
+	"net/url"
+	"os"
+	"strconv"
+	"strings"
+	"time"
+
+	"github.com/opentracing/opentracing-go"
+	"github.com/pkg/errors"
+
+	"github.com/uber/jaeger-client-go"
+)
+
+const (
+	// environment variable names
+	envServiceName            = "JAEGER_SERVICE_NAME"
+	envDisabled               = "JAEGER_DISABLED"
+	envRPCMetrics             = "JAEGER_RPC_METRICS"
+	envTags                   = "JAEGER_TAGS"
+	envSamplerType            = "JAEGER_SAMPLER_TYPE"
+	envSamplerParam           = "JAEGER_SAMPLER_PARAM"
+	envSamplerManagerHostPort = "JAEGER_SAMPLER_MANAGER_HOST_PORT"
+	envSamplerMaxOperations   = "JAEGER_SAMPLER_MAX_OPERATIONS"
+	envSamplerRefreshInterval = "JAEGER_SAMPLER_REFRESH_INTERVAL"
+	envReporterMaxQueueSize   = "JAEGER_REPORTER_MAX_QUEUE_SIZE"
+	envReporterFlushInterval  = "JAEGER_REPORTER_FLUSH_INTERVAL"
+	envReporterLogSpans       = "JAEGER_REPORTER_LOG_SPANS"
+	envEndpoint               = "JAEGER_ENDPOINT"
+	envUser                   = "JAEGER_USER"
+	envPassword               = "JAEGER_PASSWORD"
+	envAgentHost              = "JAEGER_AGENT_HOST"
+	envAgentPort              = "JAEGER_AGENT_PORT"
+)
+
+// FromEnv uses environment variables to set the tracer's Configuration
+func FromEnv() (*Configuration, error) {
+	c := &Configuration{}
+	return c.FromEnv()
+}
+
+// FromEnv uses environment variables and overrides existing tracer's Configuration
+func (c *Configuration) FromEnv() (*Configuration, error) {
+	if e := os.Getenv(envServiceName); e != "" {
+		c.ServiceName = e
+	}
+
+	if e := os.Getenv(envRPCMetrics); e != "" {
+		if value, err := strconv.ParseBool(e); err == nil {
+			c.RPCMetrics = value
+		} else {
+			return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envRPCMetrics, e)
+		}
+	}
+
+	if e := os.Getenv(envDisabled); e != "" {
+		if value, err := strconv.ParseBool(e); err == nil {
+			c.Disabled = value
+		} else {
+			return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envDisabled, e)
+		}
+	}
+
+	if e := os.Getenv(envTags); e != "" {
+		c.Tags = parseTags(e)
+	}
+
+	if c.Sampler == nil {
+		c.Sampler = &SamplerConfig{}
+	}
+
+	if s, err := c.Sampler.samplerConfigFromEnv(); err == nil {
+		c.Sampler = s
+	} else {
+		return nil, errors.Wrap(err, "cannot obtain sampler config from env")
+	}
+
+	if c.Reporter == nil {
+		c.Reporter = &ReporterConfig{}
+	}
+
+	if r, err := c.Reporter.reporterConfigFromEnv(); err == nil {
+		c.Reporter = r
+	} else {
+		return nil, errors.Wrap(err, "cannot obtain reporter config from env")
+	}
+
+	return c, nil
+}
+
+// samplerConfigFromEnv creates a new SamplerConfig based on the environment variables
+func (sc *SamplerConfig) samplerConfigFromEnv() (*SamplerConfig, error) {
+	if e := os.Getenv(envSamplerType); e != "" {
+		sc.Type = e
+	}
+
+	if e := os.Getenv(envSamplerParam); e != "" {
+		if value, err := strconv.ParseFloat(e, 64); err == nil {
+			sc.Param = value
+		} else {
+			return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envSamplerParam, e)
+		}
+	}
+
+	if e := os.Getenv(envSamplerManagerHostPort); e != "" {
+		sc.SamplingServerURL = e
+	} else if e := os.Getenv(envAgentHost); e != "" {
+		// Fallback if we know the agent host - try the sampling endpoint there
+		sc.SamplingServerURL = fmt.Sprintf("http://%s:%d/sampling", e, jaeger.DefaultSamplingServerPort)
+	}
+
+	if e := os.Getenv(envSamplerMaxOperations); e != "" {
+		if value, err := strconv.ParseInt(e, 10, 0); err == nil {
+			sc.MaxOperations = int(value)
+		} else {
+			return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envSamplerMaxOperations, e)
+		}
+	}
+
+	if e := os.Getenv(envSamplerRefreshInterval); e != "" {
+		if value, err := time.ParseDuration(e); err == nil {
+			sc.SamplingRefreshInterval = value
+		} else {
+			return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envSamplerRefreshInterval, e)
+		}
+	}
+
+	return sc, nil
+}
+
+// reporterConfigFromEnv creates a new ReporterConfig based on the environment variables
+func (rc *ReporterConfig) reporterConfigFromEnv() (*ReporterConfig, error) {
+	if e := os.Getenv(envReporterMaxQueueSize); e != "" {
+		if value, err := strconv.ParseInt(e, 10, 0); err == nil {
+			rc.QueueSize = int(value)
+		} else {
+			return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envReporterMaxQueueSize, e)
+		}
+	}
+
+	if e := os.Getenv(envReporterFlushInterval); e != "" {
+		if value, err := time.ParseDuration(e); err == nil {
+			rc.BufferFlushInterval = value
+		} else {
+			return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envReporterFlushInterval, e)
+		}
+	}
+
+	if e := os.Getenv(envReporterLogSpans); e != "" {
+		if value, err := strconv.ParseBool(e); err == nil {
+			rc.LogSpans = value
+		} else {
+			return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envReporterLogSpans, e)
+		}
+	}
+
+	if e := os.Getenv(envEndpoint); e != "" {
+		u, err := url.ParseRequestURI(e)
+		if err != nil {
+			return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envEndpoint, e)
+		}
+		rc.CollectorEndpoint = u.String()
+		user := os.Getenv(envUser)
+		pswd := os.Getenv(envPassword)
+		if user != "" && pswd == "" || user == "" && pswd != "" {
+			return nil, errors.Errorf("you must set %s and %s env vars together", envUser, envPassword)
+		}
+		rc.User = user
+		rc.Password = pswd
+	} else {
+		host := jaeger.DefaultUDPSpanServerHost
+		if e := os.Getenv(envAgentHost); e != "" {
+			host = e
+		}
+
+		port := jaeger.DefaultUDPSpanServerPort
+		if e := os.Getenv(envAgentPort); e != "" {
+			if value, err := strconv.ParseInt(e, 10, 0); err == nil {
+				port = int(value)
+			} else {
+				return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envAgentPort, e)
+			}
+		}
+		rc.LocalAgentHostPort = fmt.Sprintf("%s:%d", host, port)
+	}
+
+	return rc, nil
+}
+
+// parseTags parses the given string into a collection of Tags.
+// Spec for this value:
+// - comma separated list of key=value
+// - value can be specified using the notation ${envVar:defaultValue}, where `envVar`
+// is an environment variable and `defaultValue` is the value to use in case the env var is not set
+func parseTags(sTags string) []opentracing.Tag {
+	pairs := strings.Split(sTags, ",")
+	tags := make([]opentracing.Tag, 0)
+	for _, p := range pairs {
+		kv := strings.SplitN(p, "=", 2)
+		k, v := strings.TrimSpace(kv[0]), strings.TrimSpace(kv[1])
+
+		if strings.HasPrefix(v, "${") && strings.HasSuffix(v, "}") {
+			ed := strings.SplitN(v[2:len(v)-1], ":", 2)
+			e, d := ed[0], ed[1]
+			v = os.Getenv(e)
+			if v == "" && d != "" {
+				v = d
+			}
+		}
+
+		tag := opentracing.Tag{Key: k, Value: v}
+		tags = append(tags, tag)
+	}
+
+	return tags
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/config/options.go b/vendor/github.com/uber/jaeger-client-go/config/options.go
new file mode 100644
index 0000000..e0e50e8
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/config/options.go
@@ -0,0 +1,165 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+	opentracing "github.com/opentracing/opentracing-go"
+	"github.com/uber/jaeger-lib/metrics"
+
+	"github.com/uber/jaeger-client-go"
+)
+
+// Option is a function that sets some option on the client.
+type Option func(c *Options)
+
+// Options control behavior of the client.
+type Options struct {
+	metrics                     metrics.Factory
+	logger                      jaeger.Logger
+	reporter                    jaeger.Reporter
+	sampler                     jaeger.Sampler
+	contribObservers            []jaeger.ContribObserver
+	observers                   []jaeger.Observer
+	gen128Bit                   bool
+	poolSpans                   bool
+	zipkinSharedRPCSpan         bool
+	maxTagValueLength           int
+	noDebugFlagOnForcedSampling bool
+	tags                        []opentracing.Tag
+	injectors                   map[interface{}]jaeger.Injector
+	extractors                  map[interface{}]jaeger.Extractor
+}
+
+// Metrics creates an Option that initializes Metrics in the tracer,
+// which is used to emit statistics about spans.
+func Metrics(factory metrics.Factory) Option {
+	return func(c *Options) {
+		c.metrics = factory
+	}
+}
+
+// Logger can be provided to log Reporter errors, as well as to log spans
+// if Reporter.LogSpans is set to true.
+func Logger(logger jaeger.Logger) Option {
+	return func(c *Options) {
+		c.logger = logger
+	}
+}
+
+// Reporter can be provided explicitly to override the configuration.
+// Useful for testing, e.g. by passing InMemoryReporter.
+func Reporter(reporter jaeger.Reporter) Option {
+	return func(c *Options) {
+		c.reporter = reporter
+	}
+}
+
+// Sampler can be provided explicitly to override the configuration.
+func Sampler(sampler jaeger.Sampler) Option {
+	return func(c *Options) {
+		c.sampler = sampler
+	}
+}
+
+// Observer can be registered with the Tracer to receive notifications about new Spans.
+func Observer(observer jaeger.Observer) Option {
+	return func(c *Options) {
+		c.observers = append(c.observers, observer)
+	}
+}
+
+// ContribObserver can be registered with the Tracer to receive notifications
+// about new spans.
+func ContribObserver(observer jaeger.ContribObserver) Option {
+	return func(c *Options) {
+		c.contribObservers = append(c.contribObservers, observer)
+	}
+}
+
+// Gen128Bit specifies whether to generate 128bit trace IDs.
+func Gen128Bit(gen128Bit bool) Option {
+	return func(c *Options) {
+		c.gen128Bit = gen128Bit
+	}
+}
+
+// PoolSpans specifies whether to pool spans
+func PoolSpans(poolSpans bool) Option {
+	return func(c *Options) {
+		c.poolSpans = poolSpans
+	}
+}
+
+// ZipkinSharedRPCSpan creates an option that enables sharing span ID between client
+// and server spans a la zipkin. If false, client and server spans will be assigned
+// different IDs.
+func ZipkinSharedRPCSpan(zipkinSharedRPCSpan bool) Option {
+	return func(c *Options) {
+		c.zipkinSharedRPCSpan = zipkinSharedRPCSpan
+	}
+}
+
+// MaxTagValueLength can be provided to override the default max tag value length.
+func MaxTagValueLength(maxTagValueLength int) Option {
+	return func(c *Options) {
+		c.maxTagValueLength = maxTagValueLength
+	}
+}
+
+// NoDebugFlagOnForcedSampling can be used to decide whether debug flag will be set or not
+// when calling span.setSamplingPriority to force sample a span.
+func NoDebugFlagOnForcedSampling(noDebugFlagOnForcedSampling bool) Option {
+	return func(c *Options) {
+		c.noDebugFlagOnForcedSampling = noDebugFlagOnForcedSampling
+	}
+}
+
+// Tag creates an option that adds a tracer-level tag.
+func Tag(key string, value interface{}) Option {
+	return func(c *Options) {
+		c.tags = append(c.tags, opentracing.Tag{Key: key, Value: value})
+	}
+}
+
+// Injector registers an Injector with the given format.
+func Injector(format interface{}, injector jaeger.Injector) Option {
+	return func(c *Options) {
+		c.injectors[format] = injector
+	}
+}
+
+// Extractor registers an Extractor with the given format.
+func Extractor(format interface{}, extractor jaeger.Extractor) Option {
+	return func(c *Options) {
+		c.extractors[format] = extractor
+	}
+}
+
+func applyOptions(options ...Option) Options {
+	opts := Options{
+		injectors:  make(map[interface{}]jaeger.Injector),
+		extractors: make(map[interface{}]jaeger.Extractor),
+	}
+	for _, option := range options {
+		option(&opts)
+	}
+	if opts.metrics == nil {
+		opts.metrics = metrics.NullFactory
+	}
+	if opts.logger == nil {
+		opts.logger = jaeger.NullLogger
+	}
+	return opts
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/constants.go b/vendor/github.com/uber/jaeger-client-go/constants.go
new file mode 100644
index 0000000..1f8578f
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/constants.go
@@ -0,0 +1,106 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import (
+	"fmt"
+
+	"github.com/opentracing/opentracing-go"
+)
+
+const (
+	// JaegerClientVersion is the version of the client library reported as Span tag.
+	JaegerClientVersion = "Go-2.23.1"
+
+	// JaegerClientVersionTagKey is the name of the tag used to report client version.
+	JaegerClientVersionTagKey = "jaeger.version"
+
+	// JaegerDebugHeader is the name of HTTP header or a TextMap carrier key which,
+	// if found in the carrier, forces the trace to be sampled as "debug" trace.
+	// The value of the header is recorded as the tag on the root span, so that the
+	// trace can be found in the UI using this value as a correlation ID.
+	JaegerDebugHeader = "jaeger-debug-id"
+
+	// JaegerBaggageHeader is the name of the HTTP header that is used to submit baggage.
+	// It differs from TraceBaggageHeaderPrefix in that it can be used only in cases where
+	// a root span does not exist.
+	JaegerBaggageHeader = "jaeger-baggage"
+
+	// TracerHostnameTagKey used to report host name of the process.
+	TracerHostnameTagKey = "hostname"
+
+	// TracerIPTagKey used to report ip of the process.
+	TracerIPTagKey = "ip"
+
+	// TracerUUIDTagKey used to report UUID of the client process.
+	TracerUUIDTagKey = "client-uuid"
+
+	// SamplerTypeTagKey reports which sampler was used on the root span.
+	SamplerTypeTagKey = "sampler.type"
+
+	// SamplerParamTagKey reports the parameter of the sampler, like sampling probability.
+	SamplerParamTagKey = "sampler.param"
+
+	// TraceContextHeaderName is the http header name used to propagate tracing context.
+	// This must be in lower-case to avoid mismatches when decoding incoming headers.
+	TraceContextHeaderName = "uber-trace-id"
+
+	// TracerStateHeaderName is deprecated.
+	// Deprecated: use TraceContextHeaderName
+	TracerStateHeaderName = TraceContextHeaderName
+
+	// TraceBaggageHeaderPrefix is the prefix for http headers used to propagate baggage.
+	// This must be in lower-case to avoid mismatches when decoding incoming headers.
+	TraceBaggageHeaderPrefix = "uberctx-"
+
+	// SamplerTypeConst is the type of sampler that always makes the same decision.
+	SamplerTypeConst = "const"
+
+	// SamplerTypeRemote is the type of sampler that polls Jaeger agent for sampling strategy.
+	SamplerTypeRemote = "remote"
+
+	// SamplerTypeProbabilistic is the type of sampler that samples traces
+	// with a certain fixed probability.
+	SamplerTypeProbabilistic = "probabilistic"
+
+	// SamplerTypeRateLimiting is the type of sampler that samples
+	// only up to a fixed number of traces per second.
+	SamplerTypeRateLimiting = "ratelimiting"
+
+	// SamplerTypeLowerBound is the type of sampler that samples
+	// at least a fixed number of traces per second.
+	SamplerTypeLowerBound = "lowerbound"
+
+	// DefaultUDPSpanServerHost is the default host to send the spans to, via UDP
+	DefaultUDPSpanServerHost = "localhost"
+
+	// DefaultUDPSpanServerPort is the default port to send the spans to, via UDP
+	DefaultUDPSpanServerPort = 6831
+
+	// DefaultSamplingServerPort is the default port to fetch sampling config from, via http
+	DefaultSamplingServerPort = 5778
+
+	// DefaultMaxTagValueLength is the default max length of byte array or string allowed in the tag value.
+	DefaultMaxTagValueLength = 256
+
+	// SelfRefType is a jaeger specific reference type that supports creating a span
+	// with an already defined context.
+	selfRefType opentracing.SpanReferenceType = 99
+)
+
+var (
+	// DefaultSamplingServerURL is the default url to fetch sampling config from, via http
+	DefaultSamplingServerURL = fmt.Sprintf("http://localhost:%d/sampling", DefaultSamplingServerPort)
+)
diff --git a/vendor/github.com/uber/jaeger-client-go/contrib_observer.go b/vendor/github.com/uber/jaeger-client-go/contrib_observer.go
new file mode 100644
index 0000000..4ce1881
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/contrib_observer.go
@@ -0,0 +1,56 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import (
+	opentracing "github.com/opentracing/opentracing-go"
+)
+
+// ContribObserver can be registered with the Tracer to receive notifications
+// about new Spans. Modelled after github.com/opentracing-contrib/go-observer.
+type ContribObserver interface {
+	// Create and return a span observer. Called when a span starts.
+	// If the Observer is not interested in the given span, it must return (nil, false).
+	// E.g :
+	//     func StartSpan(opName string, opts ...opentracing.StartSpanOption) {
+	//         var sp opentracing.Span
+	//         sso := opentracing.StartSpanOptions{}
+	//         if spanObserver, ok := Observer.OnStartSpan(span, opName, sso); ok {
+	//             // we have a valid SpanObserver
+	//         }
+	//         ...
+	//     }
+	OnStartSpan(sp opentracing.Span, operationName string, options opentracing.StartSpanOptions) (ContribSpanObserver, bool)
+}
+
+// ContribSpanObserver is created by the Observer and receives notifications
+// about other Span events. This interface is meant to match
+// github.com/opentracing-contrib/go-observer, via duck typing, without
+// directly importing the go-observer package.
+type ContribSpanObserver interface {
+	OnSetOperationName(operationName string)
+	OnSetTag(key string, value interface{})
+	OnFinish(options opentracing.FinishOptions)
+}
+
+// wrapper observer for the old observers (see observer.go)
+type oldObserver struct {
+	obs Observer
+}
+
+func (o *oldObserver) OnStartSpan(sp opentracing.Span, operationName string, options opentracing.StartSpanOptions) (ContribSpanObserver, bool) {
+	spanObserver := o.obs.OnStartSpan(operationName, options)
+	return spanObserver, spanObserver != nil
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/doc.go b/vendor/github.com/uber/jaeger-client-go/doc.go
new file mode 100644
index 0000000..4f55490
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/doc.go
@@ -0,0 +1,24 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/*
+Package jaeger implements an OpenTracing (http://opentracing.io) Tracer.
+It is currently using Zipkin-compatible data model and can be directly
+itegrated with Zipkin backend (http://zipkin.io).
+
+For integration instructions please refer to the README:
+
+https://github.com/uber/jaeger-client-go/blob/master/README.md
+*/
+package jaeger
diff --git a/vendor/github.com/uber/jaeger-client-go/glide.lock b/vendor/github.com/uber/jaeger-client-go/glide.lock
new file mode 100644
index 0000000..f4c05b2
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/glide.lock
@@ -0,0 +1,98 @@
+hash: a4a449cfc060c2d7be850a69b171e4382a3bd00d1a0a72cfc944facc3fe263bf
+updated: 2019-09-23T17:10:15.213856-04:00
+imports:
+- name: github.com/beorn7/perks
+  version: 37c8de3658fcb183f997c4e13e8337516ab753e6
+  subpackages:
+  - quantile
+- name: github.com/codahale/hdrhistogram
+  version: 3a0bb77429bd3a61596f5e8a3172445844342120
+- name: github.com/crossdock/crossdock-go
+  version: 049aabb0122b03bc9bd30cab8f3f91fb60166361
+  subpackages:
+  - assert
+  - require
+- name: github.com/davecgh/go-spew
+  version: d8f796af33cc11cb798c1aaeb27a4ebc5099927d
+  subpackages:
+  - spew
+- name: github.com/golang/protobuf
+  version: 1680a479a2cfb3fa22b972af7e36d0a0fde47bf8
+  subpackages:
+  - proto
+- name: github.com/matttproud/golang_protobuf_extensions
+  version: c182affec369e30f25d3eb8cd8a478dee585ae7d
+  subpackages:
+  - pbutil
+- name: github.com/opentracing/opentracing-go
+  version: 659c90643e714681897ec2521c60567dd21da733
+  subpackages:
+  - ext
+  - harness
+  - log
+- name: github.com/pkg/errors
+  version: ba968bfe8b2f7e042a574c888954fccecfa385b4
+- name: github.com/pmezard/go-difflib
+  version: 5d4384ee4fb2527b0a1256a821ebfc92f91efefc
+  subpackages:
+  - difflib
+- name: github.com/prometheus/client_golang
+  version: 170205fb58decfd011f1550d4cfb737230d7ae4f
+  subpackages:
+  - prometheus
+  - prometheus/internal
+- name: github.com/prometheus/client_model
+  version: 14fe0d1b01d4d5fc031dd4bec1823bd3ebbe8016
+  subpackages:
+  - go
+- name: github.com/prometheus/common
+  version: 287d3e634a1e550c9e463dd7e5a75a422c614505
+  subpackages:
+  - expfmt
+  - internal/bitbucket.org/ww/goautoneg
+  - model
+- name: github.com/prometheus/procfs
+  version: de25ac347ef9305868b04dc42425c973b863b18c
+  subpackages:
+  - internal/fs
+  - internal/util
+- name: github.com/stretchr/testify
+  version: 85f2b59c4459e5bf57488796be8c3667cb8246d6
+  subpackages:
+  - assert
+  - require
+  - suite
+- name: github.com/uber-go/atomic
+  version: df976f2515e274675050de7b3f42545de80594fd
+- name: github.com/uber/jaeger-lib
+  version: a87ae9d84fb038a8d79266298970720be7c80fcd
+  subpackages:
+  - metrics
+  - metrics/metricstest
+  - metrics/prometheus
+- name: go.uber.org/atomic
+  version: df976f2515e274675050de7b3f42545de80594fd
+- name: go.uber.org/multierr
+  version: 3c4937480c32f4c13a875a1829af76c98ca3d40a
+- name: go.uber.org/zap
+  version: 27376062155ad36be76b0f12cf1572a221d3a48c
+  subpackages:
+  - buffer
+  - internal/bufferpool
+  - internal/color
+  - internal/exit
+  - zapcore
+- name: golang.org/x/net
+  version: aa69164e4478b84860dc6769c710c699c67058a3
+  subpackages:
+  - context
+  - context/ctxhttp
+- name: golang.org/x/sys
+  version: 0a153f010e6963173baba2306531d173aa843137
+  subpackages:
+  - windows
+- name: gopkg.in/yaml.v2
+  version: 51d6538a90f86fe93ac480b35f37b2be17fef232
+- name: github.com/golang/mock 
+  version: 3a35fb6e3e18b9dbfee291262260dee7372d2a92
+testImports: []
diff --git a/vendor/github.com/uber/jaeger-client-go/glide.yaml b/vendor/github.com/uber/jaeger-client-go/glide.yaml
new file mode 100644
index 0000000..eb58c67
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/glide.yaml
@@ -0,0 +1,28 @@
+package: github.com/uber/jaeger-client-go
+import:
+- package: github.com/opentracing/opentracing-go
+  version: ^1.1
+  subpackages:
+  - ext
+  - log
+- package: github.com/crossdock/crossdock-go
+- package: github.com/uber/jaeger-lib
+  version: ^2.0.0
+  subpackages:
+  - metrics
+- package: github.com/pkg/errors
+  version: ~0.8.0
+- package: go.uber.org/zap
+  source: https://github.com/uber-go/zap.git
+  version: ^1
+- package: github.com/uber-go/atomic
+  version: ^1
+- package: github.com/prometheus/client_golang
+  version: ^1
+testImport:
+- package: github.com/stretchr/testify
+  subpackages:
+  - assert
+  - require
+  - suite
+- package: github.com/golang/mock
diff --git a/vendor/github.com/uber/jaeger-client-go/header.go b/vendor/github.com/uber/jaeger-client-go/header.go
new file mode 100644
index 0000000..5da7035
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/header.go
@@ -0,0 +1,65 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+// HeadersConfig contains the values for the header keys that Jaeger will use.
+// These values may be either custom or default depending on whether custom
+// values were provided via a configuration.
+type HeadersConfig struct {
+	// JaegerDebugHeader is the name of HTTP header or a TextMap carrier key which,
+	// if found in the carrier, forces the trace to be sampled as "debug" trace.
+	// The value of the header is recorded as the tag on the root span, so that the
+	// trace can be found in the UI using this value as a correlation ID.
+	JaegerDebugHeader string `yaml:"jaegerDebugHeader"`
+
+	// JaegerBaggageHeader is the name of the HTTP header that is used to submit baggage.
+	// It differs from TraceBaggageHeaderPrefix in that it can be used only in cases where
+	// a root span does not exist.
+	JaegerBaggageHeader string `yaml:"jaegerBaggageHeader"`
+
+	// TraceContextHeaderName is the http header name used to propagate tracing context.
+	// This must be in lower-case to avoid mismatches when decoding incoming headers.
+	TraceContextHeaderName string `yaml:"TraceContextHeaderName"`
+
+	// TraceBaggageHeaderPrefix is the prefix for http headers used to propagate baggage.
+	// This must be in lower-case to avoid mismatches when decoding incoming headers.
+	TraceBaggageHeaderPrefix string `yaml:"traceBaggageHeaderPrefix"`
+}
+
+// ApplyDefaults sets missing configuration keys to default values
+func (c *HeadersConfig) ApplyDefaults() *HeadersConfig {
+	if c.JaegerBaggageHeader == "" {
+		c.JaegerBaggageHeader = JaegerBaggageHeader
+	}
+	if c.JaegerDebugHeader == "" {
+		c.JaegerDebugHeader = JaegerDebugHeader
+	}
+	if c.TraceBaggageHeaderPrefix == "" {
+		c.TraceBaggageHeaderPrefix = TraceBaggageHeaderPrefix
+	}
+	if c.TraceContextHeaderName == "" {
+		c.TraceContextHeaderName = TraceContextHeaderName
+	}
+	return c
+}
+
+func getDefaultHeadersConfig() *HeadersConfig {
+	return &HeadersConfig{
+		JaegerDebugHeader:        JaegerDebugHeader,
+		JaegerBaggageHeader:      JaegerBaggageHeader,
+		TraceContextHeaderName:   TraceContextHeaderName,
+		TraceBaggageHeaderPrefix: TraceBaggageHeaderPrefix,
+	}
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/internal/baggage/remote/options.go b/vendor/github.com/uber/jaeger-client-go/internal/baggage/remote/options.go
new file mode 100644
index 0000000..7457293
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/internal/baggage/remote/options.go
@@ -0,0 +1,101 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package remote
+
+import (
+	"time"
+
+	"github.com/uber/jaeger-client-go"
+)
+
+const (
+	defaultMaxValueLength  = 2048
+	defaultRefreshInterval = time.Minute
+	defaultHostPort        = "localhost:5778"
+)
+
+// Option is a function that sets some option on the RestrictionManager
+type Option func(options *options)
+
+// Options is a factory for all available options
+var Options options
+
+type options struct {
+	denyBaggageOnInitializationFailure bool
+	metrics                            *jaeger.Metrics
+	logger                             jaeger.Logger
+	hostPort                           string
+	refreshInterval                    time.Duration
+}
+
+// DenyBaggageOnInitializationFailure creates an Option that determines the startup failure mode of RestrictionManager.
+// If DenyBaggageOnInitializationFailure is true, RestrictionManager will not allow any baggage to be written until baggage
+// restrictions have been retrieved from agent.
+// If DenyBaggageOnInitializationFailure is false, RestrictionManager will allow any baggage to be written until baggage
+// restrictions have been retrieved from agent.
+func (options) DenyBaggageOnInitializationFailure(b bool) Option {
+	return func(o *options) {
+		o.denyBaggageOnInitializationFailure = b
+	}
+}
+
+// Metrics creates an Option that initializes Metrics on the RestrictionManager, which is used to emit statistics.
+func (options) Metrics(m *jaeger.Metrics) Option {
+	return func(o *options) {
+		o.metrics = m
+	}
+}
+
+// Logger creates an Option that sets the logger used by the RestrictionManager.
+func (options) Logger(logger jaeger.Logger) Option {
+	return func(o *options) {
+		o.logger = logger
+	}
+}
+
+// HostPort creates an Option that sets the hostPort of the local agent that contains the baggage restrictions.
+func (options) HostPort(hostPort string) Option {
+	return func(o *options) {
+		o.hostPort = hostPort
+	}
+}
+
+// RefreshInterval creates an Option that sets how often the RestrictionManager will poll local agent for
+// the baggage restrictions.
+func (options) RefreshInterval(refreshInterval time.Duration) Option {
+	return func(o *options) {
+		o.refreshInterval = refreshInterval
+	}
+}
+
+func applyOptions(o ...Option) options {
+	opts := options{}
+	for _, option := range o {
+		option(&opts)
+	}
+	if opts.metrics == nil {
+		opts.metrics = jaeger.NewNullMetrics()
+	}
+	if opts.logger == nil {
+		opts.logger = jaeger.NullLogger
+	}
+	if opts.hostPort == "" {
+		opts.hostPort = defaultHostPort
+	}
+	if opts.refreshInterval == 0 {
+		opts.refreshInterval = defaultRefreshInterval
+	}
+	return opts
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/internal/baggage/remote/restriction_manager.go b/vendor/github.com/uber/jaeger-client-go/internal/baggage/remote/restriction_manager.go
new file mode 100644
index 0000000..a56515a
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/internal/baggage/remote/restriction_manager.go
@@ -0,0 +1,157 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package remote
+
+import (
+	"fmt"
+	"net/url"
+	"sync"
+	"time"
+
+	"github.com/uber/jaeger-client-go/internal/baggage"
+	thrift "github.com/uber/jaeger-client-go/thrift-gen/baggage"
+	"github.com/uber/jaeger-client-go/utils"
+)
+
+type httpBaggageRestrictionManagerProxy struct {
+	url string
+}
+
+func newHTTPBaggageRestrictionManagerProxy(hostPort, serviceName string) *httpBaggageRestrictionManagerProxy {
+	v := url.Values{}
+	v.Set("service", serviceName)
+	return &httpBaggageRestrictionManagerProxy{
+		url: fmt.Sprintf("http://%s/baggageRestrictions?%s", hostPort, v.Encode()),
+	}
+}
+
+func (s *httpBaggageRestrictionManagerProxy) GetBaggageRestrictions(serviceName string) ([]*thrift.BaggageRestriction, error) {
+	var out []*thrift.BaggageRestriction
+	if err := utils.GetJSON(s.url, &out); err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// RestrictionManager manages baggage restrictions by retrieving baggage restrictions from agent
+type RestrictionManager struct {
+	options
+
+	mux                sync.RWMutex
+	serviceName        string
+	restrictions       map[string]*baggage.Restriction
+	thriftProxy        thrift.BaggageRestrictionManager
+	pollStopped        sync.WaitGroup
+	stopPoll           chan struct{}
+	invalidRestriction *baggage.Restriction
+	validRestriction   *baggage.Restriction
+
+	// Determines if the manager has successfully retrieved baggage restrictions from agent
+	initialized bool
+}
+
+// NewRestrictionManager returns a BaggageRestrictionManager that polls the agent for the latest
+// baggage restrictions.
+func NewRestrictionManager(serviceName string, options ...Option) *RestrictionManager {
+	// TODO there is a developing use case where a single tracer can generate traces on behalf of many services.
+	// restrictionsMap will need to exist per service
+	opts := applyOptions(options...)
+	m := &RestrictionManager{
+		serviceName:        serviceName,
+		options:            opts,
+		restrictions:       make(map[string]*baggage.Restriction),
+		thriftProxy:        newHTTPBaggageRestrictionManagerProxy(opts.hostPort, serviceName),
+		stopPoll:           make(chan struct{}),
+		invalidRestriction: baggage.NewRestriction(false, 0),
+		validRestriction:   baggage.NewRestriction(true, defaultMaxValueLength),
+	}
+	m.pollStopped.Add(1)
+	go m.pollManager()
+	return m
+}
+
+// isReady returns true if the manager has retrieved baggage restrictions from the remote source.
+func (m *RestrictionManager) isReady() bool {
+	m.mux.RLock()
+	defer m.mux.RUnlock()
+	return m.initialized
+}
+
+// GetRestriction implements RestrictionManager#GetRestriction.
+func (m *RestrictionManager) GetRestriction(service, key string) *baggage.Restriction {
+	m.mux.RLock()
+	defer m.mux.RUnlock()
+	if !m.initialized {
+		if m.denyBaggageOnInitializationFailure {
+			return m.invalidRestriction
+		}
+		return m.validRestriction
+	}
+	if restriction, ok := m.restrictions[key]; ok {
+		return restriction
+	}
+	return m.invalidRestriction
+}
+
+// Close stops remote polling and closes the RemoteRestrictionManager.
+func (m *RestrictionManager) Close() error {
+	close(m.stopPoll)
+	m.pollStopped.Wait()
+	return nil
+}
+
+func (m *RestrictionManager) pollManager() {
+	defer m.pollStopped.Done()
+	// attempt to initialize baggage restrictions
+	if err := m.updateRestrictions(); err != nil {
+		m.logger.Error(fmt.Sprintf("Failed to initialize baggage restrictions: %s", err.Error()))
+	}
+	ticker := time.NewTicker(m.refreshInterval)
+	defer ticker.Stop()
+
+	for {
+		select {
+		case <-ticker.C:
+			if err := m.updateRestrictions(); err != nil {
+				m.logger.Error(fmt.Sprintf("Failed to update baggage restrictions: %s", err.Error()))
+			}
+		case <-m.stopPoll:
+			return
+		}
+	}
+}
+
+func (m *RestrictionManager) updateRestrictions() error {
+	restrictions, err := m.thriftProxy.GetBaggageRestrictions(m.serviceName)
+	if err != nil {
+		m.metrics.BaggageRestrictionsUpdateFailure.Inc(1)
+		return err
+	}
+	newRestrictions := m.parseRestrictions(restrictions)
+	m.metrics.BaggageRestrictionsUpdateSuccess.Inc(1)
+	m.mux.Lock()
+	defer m.mux.Unlock()
+	m.initialized = true
+	m.restrictions = newRestrictions
+	return nil
+}
+
+func (m *RestrictionManager) parseRestrictions(restrictions []*thrift.BaggageRestriction) map[string]*baggage.Restriction {
+	setters := make(map[string]*baggage.Restriction, len(restrictions))
+	for _, restriction := range restrictions {
+		setters[restriction.BaggageKey] = baggage.NewRestriction(true, int(restriction.MaxValueLength))
+	}
+	return setters
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/internal/baggage/restriction_manager.go b/vendor/github.com/uber/jaeger-client-go/internal/baggage/restriction_manager.go
new file mode 100644
index 0000000..c16a5c5
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/internal/baggage/restriction_manager.go
@@ -0,0 +1,71 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package baggage
+
+const (
+	defaultMaxValueLength = 2048
+)
+
+// Restriction determines whether a baggage key is allowed and contains any restrictions on the baggage value.
+type Restriction struct {
+	keyAllowed     bool
+	maxValueLength int
+}
+
+// NewRestriction returns a new Restriction.
+func NewRestriction(keyAllowed bool, maxValueLength int) *Restriction {
+	return &Restriction{
+		keyAllowed:     keyAllowed,
+		maxValueLength: maxValueLength,
+	}
+}
+
+// KeyAllowed returns whether the baggage key for this restriction is allowed.
+func (r *Restriction) KeyAllowed() bool {
+	return r.keyAllowed
+}
+
+// MaxValueLength returns the max length for the baggage value.
+func (r *Restriction) MaxValueLength() int {
+	return r.maxValueLength
+}
+
+// RestrictionManager keeps track of valid baggage keys and their restrictions. The manager
+// will return a Restriction for a specific baggage key which will determine whether the baggage
+// key is allowed for the current service and any other applicable restrictions on the baggage
+// value.
+type RestrictionManager interface {
+	GetRestriction(service, key string) *Restriction
+}
+
+// DefaultRestrictionManager allows any baggage key.
+type DefaultRestrictionManager struct {
+	defaultRestriction *Restriction
+}
+
+// NewDefaultRestrictionManager returns a DefaultRestrictionManager.
+func NewDefaultRestrictionManager(maxValueLength int) *DefaultRestrictionManager {
+	if maxValueLength == 0 {
+		maxValueLength = defaultMaxValueLength
+	}
+	return &DefaultRestrictionManager{
+		defaultRestriction: &Restriction{keyAllowed: true, maxValueLength: maxValueLength},
+	}
+}
+
+// GetRestriction implements RestrictionManager#GetRestriction.
+func (m *DefaultRestrictionManager) GetRestriction(service, key string) *Restriction {
+	return m.defaultRestriction
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/internal/reporterstats/stats.go b/vendor/github.com/uber/jaeger-client-go/internal/reporterstats/stats.go
new file mode 100644
index 0000000..fe0bef2
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/internal/reporterstats/stats.go
@@ -0,0 +1,25 @@
+// Copyright (c) 2020 The Jaeger Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package reporterstats
+
+// ReporterStats exposes some metrics from the RemoteReporter.
+type ReporterStats interface {
+	SpansDroppedFromQueue() int64
+}
+
+// Receiver can be implemented by a Transport to be given ReporterStats.
+type Receiver interface {
+	SetReporterStats(ReporterStats)
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/internal/spanlog/json.go b/vendor/github.com/uber/jaeger-client-go/internal/spanlog/json.go
new file mode 100644
index 0000000..0e10b8a
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/internal/spanlog/json.go
@@ -0,0 +1,81 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package spanlog
+
+import (
+	"encoding/json"
+	"fmt"
+
+	"github.com/opentracing/opentracing-go/log"
+)
+
+type fieldsAsMap map[string]string
+
+// MaterializeWithJSON converts log Fields into JSON string
+// TODO refactor into pluggable materializer
+func MaterializeWithJSON(logFields []log.Field) ([]byte, error) {
+	fields := fieldsAsMap(make(map[string]string, len(logFields)))
+	for _, field := range logFields {
+		field.Marshal(fields)
+	}
+	if event, ok := fields["event"]; ok && len(fields) == 1 {
+		return []byte(event), nil
+	}
+	return json.Marshal(fields)
+}
+
+func (ml fieldsAsMap) EmitString(key, value string) {
+	ml[key] = value
+}
+
+func (ml fieldsAsMap) EmitBool(key string, value bool) {
+	ml[key] = fmt.Sprintf("%t", value)
+}
+
+func (ml fieldsAsMap) EmitInt(key string, value int) {
+	ml[key] = fmt.Sprintf("%d", value)
+}
+
+func (ml fieldsAsMap) EmitInt32(key string, value int32) {
+	ml[key] = fmt.Sprintf("%d", value)
+}
+
+func (ml fieldsAsMap) EmitInt64(key string, value int64) {
+	ml[key] = fmt.Sprintf("%d", value)
+}
+
+func (ml fieldsAsMap) EmitUint32(key string, value uint32) {
+	ml[key] = fmt.Sprintf("%d", value)
+}
+
+func (ml fieldsAsMap) EmitUint64(key string, value uint64) {
+	ml[key] = fmt.Sprintf("%d", value)
+}
+
+func (ml fieldsAsMap) EmitFloat32(key string, value float32) {
+	ml[key] = fmt.Sprintf("%f", value)
+}
+
+func (ml fieldsAsMap) EmitFloat64(key string, value float64) {
+	ml[key] = fmt.Sprintf("%f", value)
+}
+
+func (ml fieldsAsMap) EmitObject(key string, value interface{}) {
+	ml[key] = fmt.Sprintf("%+v", value)
+}
+
+func (ml fieldsAsMap) EmitLazyLogger(value log.LazyLogger) {
+	value(ml)
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/internal/throttler/remote/options.go b/vendor/github.com/uber/jaeger-client-go/internal/throttler/remote/options.go
new file mode 100644
index 0000000..f52c322
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/internal/throttler/remote/options.go
@@ -0,0 +1,99 @@
+// Copyright (c) 2018 The Jaeger Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package remote
+
+import (
+	"time"
+
+	"github.com/uber/jaeger-client-go"
+)
+
+const (
+	defaultHostPort        = "localhost:5778"
+	defaultRefreshInterval = time.Second * 5
+)
+
+// Option is a function that sets some option on the Throttler
+type Option func(options *options)
+
+// Options is a factory for all available options
+var Options options
+
+type options struct {
+	metrics                   *jaeger.Metrics
+	logger                    jaeger.Logger
+	hostPort                  string
+	refreshInterval           time.Duration
+	synchronousInitialization bool
+}
+
+// Metrics creates an Option that initializes Metrics on the Throttler, which is used to emit statistics.
+func (options) Metrics(m *jaeger.Metrics) Option {
+	return func(o *options) {
+		o.metrics = m
+	}
+}
+
+// Logger creates an Option that sets the logger used by the Throttler.
+func (options) Logger(logger jaeger.Logger) Option {
+	return func(o *options) {
+		o.logger = logger
+	}
+}
+
+// HostPort creates an Option that sets the hostPort of the local agent that keeps track of credits.
+func (options) HostPort(hostPort string) Option {
+	return func(o *options) {
+		o.hostPort = hostPort
+	}
+}
+
+// RefreshInterval creates an Option that sets how often the Throttler will poll local agent for
+// credits.
+func (options) RefreshInterval(refreshInterval time.Duration) Option {
+	return func(o *options) {
+		o.refreshInterval = refreshInterval
+	}
+}
+
+// SynchronousInitialization creates an Option that determines whether the throttler should synchronously
+// fetch credits from the agent when an operation is seen for the first time. This should be set to true
+// if the client will be used by a short lived service that needs to ensure that credits are fetched upfront
+// such that sampling or throttling occurs.
+func (options) SynchronousInitialization(b bool) Option {
+	return func(o *options) {
+		o.synchronousInitialization = b
+	}
+}
+
+func applyOptions(o ...Option) options {
+	opts := options{}
+	for _, option := range o {
+		option(&opts)
+	}
+	if opts.metrics == nil {
+		opts.metrics = jaeger.NewNullMetrics()
+	}
+	if opts.logger == nil {
+		opts.logger = jaeger.NullLogger
+	}
+	if opts.hostPort == "" {
+		opts.hostPort = defaultHostPort
+	}
+	if opts.refreshInterval == 0 {
+		opts.refreshInterval = defaultRefreshInterval
+	}
+	return opts
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/internal/throttler/remote/throttler.go b/vendor/github.com/uber/jaeger-client-go/internal/throttler/remote/throttler.go
new file mode 100644
index 0000000..20f434f
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/internal/throttler/remote/throttler.go
@@ -0,0 +1,216 @@
+// Copyright (c) 2018 The Jaeger Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package remote
+
+import (
+	"fmt"
+	"net/url"
+	"sync"
+	"sync/atomic"
+	"time"
+
+	"github.com/pkg/errors"
+
+	"github.com/uber/jaeger-client-go"
+	"github.com/uber/jaeger-client-go/utils"
+)
+
+const (
+	// minimumCredits is the minimum amount of credits necessary to not be throttled.
+	// i.e. if currentCredits > minimumCredits, then the operation will not be throttled.
+	minimumCredits = 1.0
+)
+
+var (
+	errorUUIDNotSet = errors.New("Throttler UUID must be set")
+)
+
+type operationBalance struct {
+	Operation string  `json:"operation"`
+	Balance   float64 `json:"balance"`
+}
+
+type creditResponse struct {
+	Balances []operationBalance `json:"balances"`
+}
+
+type httpCreditManagerProxy struct {
+	hostPort string
+}
+
+func newHTTPCreditManagerProxy(hostPort string) *httpCreditManagerProxy {
+	return &httpCreditManagerProxy{
+		hostPort: hostPort,
+	}
+}
+
+// N.B. Operations list must not be empty.
+func (m *httpCreditManagerProxy) FetchCredits(uuid, serviceName string, operations []string) (*creditResponse, error) {
+	params := url.Values{}
+	params.Set("service", serviceName)
+	params.Set("uuid", uuid)
+	for _, op := range operations {
+		params.Add("operations", op)
+	}
+	var resp creditResponse
+	if err := utils.GetJSON(fmt.Sprintf("http://%s/credits?%s", m.hostPort, params.Encode()), &resp); err != nil {
+		return nil, errors.Wrap(err, "Failed to receive credits from agent")
+	}
+	return &resp, nil
+}
+
+// Throttler retrieves credits from agent and uses it to throttle operations.
+type Throttler struct {
+	options
+
+	mux           sync.RWMutex
+	service       string
+	uuid          atomic.Value
+	creditManager *httpCreditManagerProxy
+	credits       map[string]float64 // map of operation->credits
+	close         chan struct{}
+	stopped       sync.WaitGroup
+}
+
+// NewThrottler returns a Throttler that polls agent for credits and uses them to throttle
+// the service.
+func NewThrottler(service string, options ...Option) *Throttler {
+	opts := applyOptions(options...)
+	creditManager := newHTTPCreditManagerProxy(opts.hostPort)
+	t := &Throttler{
+		options:       opts,
+		creditManager: creditManager,
+		service:       service,
+		credits:       make(map[string]float64),
+		close:         make(chan struct{}),
+	}
+	t.stopped.Add(1)
+	go t.pollManager()
+	return t
+}
+
+// IsAllowed implements Throttler#IsAllowed.
+func (t *Throttler) IsAllowed(operation string) bool {
+	t.mux.Lock()
+	defer t.mux.Unlock()
+	value, ok := t.credits[operation]
+	if !ok || value == 0 {
+		if !ok {
+			// NOTE: This appears to be a no-op at first glance, but it stores
+			// the operation key in the map. Necessary for functionality of
+			// Throttler#operations method.
+			t.credits[operation] = 0
+		}
+		if !t.synchronousInitialization {
+			t.metrics.ThrottledDebugSpans.Inc(1)
+			return false
+		}
+		// If it is the first time this operation is being checked, synchronously fetch
+		// the credits.
+		credits, err := t.fetchCredits([]string{operation})
+		if err != nil {
+			// Failed to receive credits from agent, try again next time
+			t.logger.Error("Failed to fetch credits: " + err.Error())
+			return false
+		}
+		if len(credits.Balances) == 0 {
+			// This shouldn't happen but just in case
+			return false
+		}
+		for _, opBalance := range credits.Balances {
+			t.credits[opBalance.Operation] += opBalance.Balance
+		}
+	}
+	return t.isAllowed(operation)
+}
+
+// Close stops the throttler from fetching credits from remote.
+func (t *Throttler) Close() error {
+	close(t.close)
+	t.stopped.Wait()
+	return nil
+}
+
+// SetProcess implements ProcessSetter#SetProcess. It's imperative that the UUID is set before any remote
+// requests are made.
+func (t *Throttler) SetProcess(process jaeger.Process) {
+	if process.UUID != "" {
+		t.uuid.Store(process.UUID)
+	}
+}
+
+// N.B. This function must be called with the Write Lock
+func (t *Throttler) isAllowed(operation string) bool {
+	credits := t.credits[operation]
+	if credits < minimumCredits {
+		t.metrics.ThrottledDebugSpans.Inc(1)
+		return false
+	}
+	t.credits[operation] = credits - minimumCredits
+	return true
+}
+
+func (t *Throttler) pollManager() {
+	defer t.stopped.Done()
+	ticker := time.NewTicker(t.refreshInterval)
+	defer ticker.Stop()
+	for {
+		select {
+		case <-ticker.C:
+			t.refreshCredits()
+		case <-t.close:
+			return
+		}
+	}
+}
+
+func (t *Throttler) operations() []string {
+	t.mux.RLock()
+	defer t.mux.RUnlock()
+	operations := make([]string, 0, len(t.credits))
+	for op := range t.credits {
+		operations = append(operations, op)
+	}
+	return operations
+}
+
+func (t *Throttler) refreshCredits() {
+	operations := t.operations()
+	if len(operations) == 0 {
+		return
+	}
+	newCredits, err := t.fetchCredits(operations)
+	if err != nil {
+		t.metrics.ThrottlerUpdateFailure.Inc(1)
+		t.logger.Error("Failed to fetch credits: " + err.Error())
+		return
+	}
+	t.metrics.ThrottlerUpdateSuccess.Inc(1)
+
+	t.mux.Lock()
+	defer t.mux.Unlock()
+	for _, opBalance := range newCredits.Balances {
+		t.credits[opBalance.Operation] += opBalance.Balance
+	}
+}
+
+func (t *Throttler) fetchCredits(operations []string) (*creditResponse, error) {
+	uuid := t.uuid.Load()
+	uuidStr, _ := uuid.(string)
+	if uuid == nil || uuidStr == "" {
+		return nil, errorUUIDNotSet
+	}
+	return t.creditManager.FetchCredits(uuidStr, t.service, operations)
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/internal/throttler/throttler.go b/vendor/github.com/uber/jaeger-client-go/internal/throttler/throttler.go
new file mode 100644
index 0000000..196ed69
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/internal/throttler/throttler.go
@@ -0,0 +1,32 @@
+// Copyright (c) 2018 The Jaeger Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package throttler
+
+// Throttler is used to rate limits operations. For example, given how debug spans
+// are always sampled, a throttler can be enabled per client to rate limit the amount
+// of debug spans a client can start.
+type Throttler interface {
+	// IsAllowed determines whether the operation should be allowed and not be
+	// throttled.
+	IsAllowed(operation string) bool
+}
+
+// DefaultThrottler doesn't throttle at all.
+type DefaultThrottler struct{}
+
+// IsAllowed implements Throttler#IsAllowed.
+func (t DefaultThrottler) IsAllowed(operation string) bool {
+	return true
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/interop.go b/vendor/github.com/uber/jaeger-client-go/interop.go
new file mode 100644
index 0000000..8402d08
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/interop.go
@@ -0,0 +1,55 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import (
+	"github.com/opentracing/opentracing-go"
+)
+
+// TODO this file should not be needed after TChannel PR.
+
+type formatKey int
+
+// SpanContextFormat is a constant used as OpenTracing Format.
+// Requires *SpanContext as carrier.
+// This format is intended for interop with TChannel or other Zipkin-like tracers.
+const SpanContextFormat formatKey = iota
+
+type jaegerTraceContextPropagator struct {
+	tracer *Tracer
+}
+
+func (p *jaegerTraceContextPropagator) Inject(
+	ctx SpanContext,
+	abstractCarrier interface{},
+) error {
+	carrier, ok := abstractCarrier.(*SpanContext)
+	if !ok {
+		return opentracing.ErrInvalidCarrier
+	}
+
+	carrier.CopyFrom(&ctx)
+	return nil
+}
+
+func (p *jaegerTraceContextPropagator) Extract(abstractCarrier interface{}) (SpanContext, error) {
+	carrier, ok := abstractCarrier.(*SpanContext)
+	if !ok {
+		return emptyContext, opentracing.ErrInvalidCarrier
+	}
+	ctx := new(SpanContext)
+	ctx.CopyFrom(carrier)
+	return *ctx, nil
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/jaeger_tag.go b/vendor/github.com/uber/jaeger-client-go/jaeger_tag.go
new file mode 100644
index 0000000..868b2a5
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/jaeger_tag.go
@@ -0,0 +1,84 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import (
+	"fmt"
+
+	"github.com/opentracing/opentracing-go/log"
+
+	j "github.com/uber/jaeger-client-go/thrift-gen/jaeger"
+)
+
+type tags []*j.Tag
+
+// ConvertLogsToJaegerTags converts log Fields into jaeger tags.
+func ConvertLogsToJaegerTags(logFields []log.Field) []*j.Tag {
+	fields := tags(make([]*j.Tag, 0, len(logFields)))
+	for _, field := range logFields {
+		field.Marshal(&fields)
+	}
+	return fields
+}
+
+func (t *tags) EmitString(key, value string) {
+	*t = append(*t, &j.Tag{Key: key, VType: j.TagType_STRING, VStr: &value})
+}
+
+func (t *tags) EmitBool(key string, value bool) {
+	*t = append(*t, &j.Tag{Key: key, VType: j.TagType_BOOL, VBool: &value})
+}
+
+func (t *tags) EmitInt(key string, value int) {
+	vLong := int64(value)
+	*t = append(*t, &j.Tag{Key: key, VType: j.TagType_LONG, VLong: &vLong})
+}
+
+func (t *tags) EmitInt32(key string, value int32) {
+	vLong := int64(value)
+	*t = append(*t, &j.Tag{Key: key, VType: j.TagType_LONG, VLong: &vLong})
+}
+
+func (t *tags) EmitInt64(key string, value int64) {
+	*t = append(*t, &j.Tag{Key: key, VType: j.TagType_LONG, VLong: &value})
+}
+
+func (t *tags) EmitUint32(key string, value uint32) {
+	vLong := int64(value)
+	*t = append(*t, &j.Tag{Key: key, VType: j.TagType_LONG, VLong: &vLong})
+}
+
+func (t *tags) EmitUint64(key string, value uint64) {
+	vLong := int64(value)
+	*t = append(*t, &j.Tag{Key: key, VType: j.TagType_LONG, VLong: &vLong})
+}
+
+func (t *tags) EmitFloat32(key string, value float32) {
+	vDouble := float64(value)
+	*t = append(*t, &j.Tag{Key: key, VType: j.TagType_DOUBLE, VDouble: &vDouble})
+}
+
+func (t *tags) EmitFloat64(key string, value float64) {
+	*t = append(*t, &j.Tag{Key: key, VType: j.TagType_DOUBLE, VDouble: &value})
+}
+
+func (t *tags) EmitObject(key string, value interface{}) {
+	vStr := fmt.Sprintf("%+v", value)
+	*t = append(*t, &j.Tag{Key: key, VType: j.TagType_STRING, VStr: &vStr})
+}
+
+func (t *tags) EmitLazyLogger(value log.LazyLogger) {
+	value(t)
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/jaeger_thrift_span.go b/vendor/github.com/uber/jaeger-client-go/jaeger_thrift_span.go
new file mode 100644
index 0000000..3ac2f8f
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/jaeger_thrift_span.go
@@ -0,0 +1,181 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import (
+	"time"
+
+	"github.com/opentracing/opentracing-go"
+
+	j "github.com/uber/jaeger-client-go/thrift-gen/jaeger"
+	"github.com/uber/jaeger-client-go/utils"
+)
+
+// BuildJaegerThrift builds jaeger span based on internal span.
+// TODO: (breaking change) move to internal package.
+func BuildJaegerThrift(span *Span) *j.Span {
+	span.Lock()
+	defer span.Unlock()
+	startTime := utils.TimeToMicrosecondsSinceEpochInt64(span.startTime)
+	duration := span.duration.Nanoseconds() / int64(time.Microsecond)
+	jaegerSpan := &j.Span{
+		TraceIdLow:    int64(span.context.traceID.Low),
+		TraceIdHigh:   int64(span.context.traceID.High),
+		SpanId:        int64(span.context.spanID),
+		ParentSpanId:  int64(span.context.parentID),
+		OperationName: span.operationName,
+		Flags:         int32(span.context.samplingState.flags()),
+		StartTime:     startTime,
+		Duration:      duration,
+		Tags:          buildTags(span.tags, span.tracer.options.maxTagValueLength),
+		Logs:          buildLogs(span.logs),
+		References:    buildReferences(span.references),
+	}
+	return jaegerSpan
+}
+
+// BuildJaegerProcessThrift creates a thrift Process type.
+// TODO: (breaking change) move to internal package.
+func BuildJaegerProcessThrift(span *Span) *j.Process {
+	span.Lock()
+	defer span.Unlock()
+	return buildJaegerProcessThrift(span.tracer)
+}
+
+func buildJaegerProcessThrift(tracer *Tracer) *j.Process {
+	process := &j.Process{
+		ServiceName: tracer.serviceName,
+		Tags:        buildTags(tracer.tags, tracer.options.maxTagValueLength),
+	}
+	if tracer.process.UUID != "" {
+		process.Tags = append(process.Tags, &j.Tag{Key: TracerUUIDTagKey, VStr: &tracer.process.UUID, VType: j.TagType_STRING})
+	}
+	return process
+}
+
+func buildTags(tags []Tag, maxTagValueLength int) []*j.Tag {
+	jTags := make([]*j.Tag, 0, len(tags))
+	for _, tag := range tags {
+		jTag := buildTag(&tag, maxTagValueLength)
+		jTags = append(jTags, jTag)
+	}
+	return jTags
+}
+
+func buildLogs(logs []opentracing.LogRecord) []*j.Log {
+	jLogs := make([]*j.Log, 0, len(logs))
+	for _, log := range logs {
+		jLog := &j.Log{
+			Timestamp: utils.TimeToMicrosecondsSinceEpochInt64(log.Timestamp),
+			Fields:    ConvertLogsToJaegerTags(log.Fields),
+		}
+		jLogs = append(jLogs, jLog)
+	}
+	return jLogs
+}
+
+func buildTag(tag *Tag, maxTagValueLength int) *j.Tag {
+	jTag := &j.Tag{Key: tag.key}
+	switch value := tag.value.(type) {
+	case string:
+		vStr := truncateString(value, maxTagValueLength)
+		jTag.VStr = &vStr
+		jTag.VType = j.TagType_STRING
+	case []byte:
+		if len(value) > maxTagValueLength {
+			value = value[:maxTagValueLength]
+		}
+		jTag.VBinary = value
+		jTag.VType = j.TagType_BINARY
+	case int:
+		vLong := int64(value)
+		jTag.VLong = &vLong
+		jTag.VType = j.TagType_LONG
+	case uint:
+		vLong := int64(value)
+		jTag.VLong = &vLong
+		jTag.VType = j.TagType_LONG
+	case int8:
+		vLong := int64(value)
+		jTag.VLong = &vLong
+		jTag.VType = j.TagType_LONG
+	case uint8:
+		vLong := int64(value)
+		jTag.VLong = &vLong
+		jTag.VType = j.TagType_LONG
+	case int16:
+		vLong := int64(value)
+		jTag.VLong = &vLong
+		jTag.VType = j.TagType_LONG
+	case uint16:
+		vLong := int64(value)
+		jTag.VLong = &vLong
+		jTag.VType = j.TagType_LONG
+	case int32:
+		vLong := int64(value)
+		jTag.VLong = &vLong
+		jTag.VType = j.TagType_LONG
+	case uint32:
+		vLong := int64(value)
+		jTag.VLong = &vLong
+		jTag.VType = j.TagType_LONG
+	case int64:
+		vLong := int64(value)
+		jTag.VLong = &vLong
+		jTag.VType = j.TagType_LONG
+	case uint64:
+		vLong := int64(value)
+		jTag.VLong = &vLong
+		jTag.VType = j.TagType_LONG
+	case float32:
+		vDouble := float64(value)
+		jTag.VDouble = &vDouble
+		jTag.VType = j.TagType_DOUBLE
+	case float64:
+		vDouble := float64(value)
+		jTag.VDouble = &vDouble
+		jTag.VType = j.TagType_DOUBLE
+	case bool:
+		vBool := value
+		jTag.VBool = &vBool
+		jTag.VType = j.TagType_BOOL
+	default:
+		vStr := truncateString(stringify(value), maxTagValueLength)
+		jTag.VStr = &vStr
+		jTag.VType = j.TagType_STRING
+	}
+	return jTag
+}
+
+func buildReferences(references []Reference) []*j.SpanRef {
+	retMe := make([]*j.SpanRef, 0, len(references))
+	for _, ref := range references {
+		if ref.Type == opentracing.ChildOfRef {
+			retMe = append(retMe, spanRef(ref.Context, j.SpanRefType_CHILD_OF))
+		} else if ref.Type == opentracing.FollowsFromRef {
+			retMe = append(retMe, spanRef(ref.Context, j.SpanRefType_FOLLOWS_FROM))
+		}
+	}
+	return retMe
+}
+
+func spanRef(ctx SpanContext, refType j.SpanRefType) *j.SpanRef {
+	return &j.SpanRef{
+		RefType:     refType,
+		TraceIdLow:  int64(ctx.traceID.Low),
+		TraceIdHigh: int64(ctx.traceID.High),
+		SpanId:      int64(ctx.spanID),
+	}
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/log/logger.go b/vendor/github.com/uber/jaeger-client-go/log/logger.go
new file mode 100644
index 0000000..ced6e0c
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/log/logger.go
@@ -0,0 +1,141 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package log
+
+import (
+	"bytes"
+	"fmt"
+	"log"
+	"sync"
+)
+
+// Logger provides an abstract interface for logging from Reporters.
+// Applications can provide their own implementation of this interface to adapt
+// reporters logging to whatever logging library they prefer (stdlib log,
+// logrus, go-logging, etc).
+type Logger interface {
+	// Error logs a message at error priority
+	Error(msg string)
+
+	// Infof logs a message at info priority
+	Infof(msg string, args ...interface{})
+}
+
+// StdLogger is implementation of the Logger interface that delegates to default `log` package
+var StdLogger = &stdLogger{}
+
+type stdLogger struct{}
+
+func (l *stdLogger) Error(msg string) {
+	log.Printf("ERROR: %s", msg)
+}
+
+// Infof logs a message at info priority
+func (l *stdLogger) Infof(msg string, args ...interface{}) {
+	log.Printf(msg, args...)
+}
+
+// Debugf logs a message at debug priority
+func (l *stdLogger) Debugf(msg string, args ...interface{}) {
+	log.Printf(fmt.Sprintf("DEBUG: %s", msg), args...)
+}
+
+// NullLogger is implementation of the Logger interface that is no-op
+var NullLogger = &nullLogger{}
+
+type nullLogger struct{}
+
+func (l *nullLogger) Error(msg string)                       {}
+func (l *nullLogger) Infof(msg string, args ...interface{})  {}
+func (l *nullLogger) Debugf(msg string, args ...interface{}) {}
+
+// BytesBufferLogger implements Logger backed by a bytes.Buffer.
+type BytesBufferLogger struct {
+	mux sync.Mutex
+	buf bytes.Buffer
+}
+
+// Error implements Logger.
+func (l *BytesBufferLogger) Error(msg string) {
+	l.mux.Lock()
+	l.buf.WriteString(fmt.Sprintf("ERROR: %s\n", msg))
+	l.mux.Unlock()
+}
+
+// Infof implements Logger.
+func (l *BytesBufferLogger) Infof(msg string, args ...interface{}) {
+	l.mux.Lock()
+	l.buf.WriteString("INFO: " + fmt.Sprintf(msg, args...) + "\n")
+	l.mux.Unlock()
+}
+
+// Debugf implements Logger.
+func (l *BytesBufferLogger) Debugf(msg string, args ...interface{}) {
+	l.mux.Lock()
+	l.buf.WriteString("DEBUG: " + fmt.Sprintf(msg, args...) + "\n")
+	l.mux.Unlock()
+}
+
+// String returns string representation of the underlying buffer.
+func (l *BytesBufferLogger) String() string {
+	l.mux.Lock()
+	defer l.mux.Unlock()
+	return l.buf.String()
+}
+
+// Flush empties the underlying buffer.
+func (l *BytesBufferLogger) Flush() {
+	l.mux.Lock()
+	defer l.mux.Unlock()
+	l.buf.Reset()
+}
+
+// DebugLogger is an interface which adds a debug logging level
+type DebugLogger interface {
+	Logger
+
+	// Debugf logs a message at debug priority
+	Debugf(msg string, args ...interface{})
+}
+
+// DebugLogAdapter is a log adapter that converts a Logger into a DebugLogger
+// If the provided Logger doesn't satisfy the interface, a logger with debug
+// disabled is returned
+func DebugLogAdapter(logger Logger) DebugLogger {
+	if logger == nil {
+		return nil
+	}
+	if debugLogger, ok := logger.(DebugLogger); ok {
+		return debugLogger
+	}
+	logger.Infof("debug logging disabled")
+	return debugDisabledLogAdapter{logger: logger}
+}
+
+type debugDisabledLogAdapter struct {
+	logger Logger
+}
+
+func (d debugDisabledLogAdapter) Error(msg string) {
+	d.logger.Error(msg)
+}
+
+func (d debugDisabledLogAdapter) Infof(msg string, args ...interface{}) {
+	d.logger.Infof(msg, args...)
+}
+
+// Debugf is a nop
+func (d debugDisabledLogAdapter) Debugf(msg string, args ...interface{}) {
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/logger.go b/vendor/github.com/uber/jaeger-client-go/logger.go
new file mode 100644
index 0000000..d4f0b50
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/logger.go
@@ -0,0 +1,53 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import "log"
+
+// NB This will be deprecated in 3.0.0, please use jaeger-client-go/log/logger instead.
+
+// Logger provides an abstract interface for logging from Reporters.
+// Applications can provide their own implementation of this interface to adapt
+// reporters logging to whatever logging library they prefer (stdlib log,
+// logrus, go-logging, etc).
+type Logger interface {
+	// Error logs a message at error priority
+	Error(msg string)
+
+	// Infof logs a message at info priority
+	Infof(msg string, args ...interface{})
+}
+
+// StdLogger is implementation of the Logger interface that delegates to default `log` package
+var StdLogger = &stdLogger{}
+
+type stdLogger struct{}
+
+func (l *stdLogger) Error(msg string) {
+	log.Printf("ERROR: %s", msg)
+}
+
+// Infof logs a message at info priority
+func (l *stdLogger) Infof(msg string, args ...interface{}) {
+	log.Printf(msg, args...)
+}
+
+// NullLogger is implementation of the Logger interface that delegates to default `log` package
+var NullLogger = &nullLogger{}
+
+type nullLogger struct{}
+
+func (l *nullLogger) Error(msg string)                      {}
+func (l *nullLogger) Infof(msg string, args ...interface{}) {}
diff --git a/vendor/github.com/uber/jaeger-client-go/metrics.go b/vendor/github.com/uber/jaeger-client-go/metrics.go
new file mode 100644
index 0000000..50e4e22
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/metrics.go
@@ -0,0 +1,119 @@
+// Copyright (c) 2017-2018 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import (
+	"github.com/uber/jaeger-lib/metrics"
+)
+
+// Metrics is a container of all stats emitted by Jaeger tracer.
+type Metrics struct {
+	// Number of traces started by this tracer as sampled
+	TracesStartedSampled metrics.Counter `metric:"traces" tags:"state=started,sampled=y" help:"Number of traces started by this tracer as sampled"`
+
+	// Number of traces started by this tracer as not sampled
+	TracesStartedNotSampled metrics.Counter `metric:"traces" tags:"state=started,sampled=n" help:"Number of traces started by this tracer as not sampled"`
+
+	// Number of traces started by this tracer with delayed sampling
+	TracesStartedDelayedSampling metrics.Counter `metric:"traces" tags:"state=started,sampled=n" help:"Number of traces started by this tracer with delayed sampling"`
+
+	// Number of externally started sampled traces this tracer joined
+	TracesJoinedSampled metrics.Counter `metric:"traces" tags:"state=joined,sampled=y" help:"Number of externally started sampled traces this tracer joined"`
+
+	// Number of externally started not-sampled traces this tracer joined
+	TracesJoinedNotSampled metrics.Counter `metric:"traces" tags:"state=joined,sampled=n" help:"Number of externally started not-sampled traces this tracer joined"`
+
+	// Number of sampled spans started by this tracer
+	SpansStartedSampled metrics.Counter `metric:"started_spans" tags:"sampled=y" help:"Number of spans started by this tracer as sampled"`
+
+	// Number of not sampled spans started by this tracer
+	SpansStartedNotSampled metrics.Counter `metric:"started_spans" tags:"sampled=n" help:"Number of spans started by this tracer as not sampled"`
+
+	// Number of spans with delayed sampling started by this tracer
+	SpansStartedDelayedSampling metrics.Counter `metric:"started_spans" tags:"sampled=delayed" help:"Number of spans started by this tracer with delayed sampling"`
+
+	// Number of spans finished by this tracer
+	SpansFinishedSampled metrics.Counter `metric:"finished_spans" tags:"sampled=y" help:"Number of sampled spans finished by this tracer"`
+
+	// Number of spans finished by this tracer
+	SpansFinishedNotSampled metrics.Counter `metric:"finished_spans" tags:"sampled=n" help:"Number of not-sampled spans finished by this tracer"`
+
+	// Number of spans finished by this tracer
+	SpansFinishedDelayedSampling metrics.Counter `metric:"finished_spans" tags:"sampled=delayed" help:"Number of spans with delayed sampling finished by this tracer"`
+
+	// Number of errors decoding tracing context
+	DecodingErrors metrics.Counter `metric:"span_context_decoding_errors" help:"Number of errors decoding tracing context"`
+
+	// Number of spans successfully reported
+	ReporterSuccess metrics.Counter `metric:"reporter_spans" tags:"result=ok" help:"Number of spans successfully reported"`
+
+	// Number of spans not reported due to a Sender failure
+	ReporterFailure metrics.Counter `metric:"reporter_spans" tags:"result=err" help:"Number of spans not reported due to a Sender failure"`
+
+	// Number of spans dropped due to internal queue overflow
+	ReporterDropped metrics.Counter `metric:"reporter_spans" tags:"result=dropped" help:"Number of spans dropped due to internal queue overflow"`
+
+	// Current number of spans in the reporter queue
+	ReporterQueueLength metrics.Gauge `metric:"reporter_queue_length" help:"Current number of spans in the reporter queue"`
+
+	// Number of times the Sampler succeeded to retrieve sampling strategy
+	SamplerRetrieved metrics.Counter `metric:"sampler_queries" tags:"result=ok" help:"Number of times the Sampler succeeded to retrieve sampling strategy"`
+
+	// Number of times the Sampler failed to retrieve sampling strategy
+	SamplerQueryFailure metrics.Counter `metric:"sampler_queries" tags:"result=err" help:"Number of times the Sampler failed to retrieve sampling strategy"`
+
+	// Number of times the Sampler succeeded to retrieve and update sampling strategy
+	SamplerUpdated metrics.Counter `metric:"sampler_updates" tags:"result=ok" help:"Number of times the Sampler succeeded to retrieve and update sampling strategy"`
+
+	// Number of times the Sampler failed to update sampling strategy
+	SamplerUpdateFailure metrics.Counter `metric:"sampler_updates" tags:"result=err" help:"Number of times the Sampler failed to update sampling strategy"`
+
+	// Number of times baggage was successfully written or updated on spans.
+	BaggageUpdateSuccess metrics.Counter `metric:"baggage_updates" tags:"result=ok" help:"Number of times baggage was successfully written or updated on spans"`
+
+	// Number of times baggage failed to write or update on spans.
+	BaggageUpdateFailure metrics.Counter `metric:"baggage_updates" tags:"result=err" help:"Number of times baggage failed to write or update on spans"`
+
+	// Number of times baggage was truncated as per baggage restrictions.
+	BaggageTruncate metrics.Counter `metric:"baggage_truncations" help:"Number of times baggage was truncated as per baggage restrictions"`
+
+	// Number of times baggage restrictions were successfully updated.
+	BaggageRestrictionsUpdateSuccess metrics.Counter `metric:"baggage_restrictions_updates" tags:"result=ok" help:"Number of times baggage restrictions were successfully updated"`
+
+	// Number of times baggage restrictions failed to update.
+	BaggageRestrictionsUpdateFailure metrics.Counter `metric:"baggage_restrictions_updates" tags:"result=err" help:"Number of times baggage restrictions failed to update"`
+
+	// Number of times debug spans were throttled.
+	ThrottledDebugSpans metrics.Counter `metric:"throttled_debug_spans" help:"Number of times debug spans were throttled"`
+
+	// Number of times throttler successfully updated.
+	ThrottlerUpdateSuccess metrics.Counter `metric:"throttler_updates" tags:"result=ok" help:"Number of times throttler successfully updated"`
+
+	// Number of times throttler failed to update.
+	ThrottlerUpdateFailure metrics.Counter `metric:"throttler_updates" tags:"result=err" help:"Number of times throttler failed to update"`
+}
+
+// NewMetrics creates a new Metrics struct and initializes it.
+func NewMetrics(factory metrics.Factory, globalTags map[string]string) *Metrics {
+	m := &Metrics{}
+	// TODO the namespace "jaeger" should be configurable
+	metrics.MustInit(m, factory.Namespace(metrics.NSOptions{Name: "jaeger"}).Namespace(metrics.NSOptions{Name: "tracer"}), globalTags)
+	return m
+}
+
+// NewNullMetrics creates a new Metrics struct that won't report any metrics.
+func NewNullMetrics() *Metrics {
+	return NewMetrics(metrics.NullFactory, nil)
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/observer.go b/vendor/github.com/uber/jaeger-client-go/observer.go
new file mode 100644
index 0000000..7bbd028
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/observer.go
@@ -0,0 +1,88 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import opentracing "github.com/opentracing/opentracing-go"
+
+// Observer can be registered with the Tracer to receive notifications about
+// new Spans.
+//
+// Deprecated: use jaeger.ContribObserver instead.
+type Observer interface {
+	OnStartSpan(operationName string, options opentracing.StartSpanOptions) SpanObserver
+}
+
+// SpanObserver is created by the Observer and receives notifications about
+// other Span events.
+//
+// Deprecated: use jaeger.ContribSpanObserver instead.
+type SpanObserver interface {
+	OnSetOperationName(operationName string)
+	OnSetTag(key string, value interface{})
+	OnFinish(options opentracing.FinishOptions)
+}
+
+// compositeObserver is a dispatcher to other observers
+type compositeObserver struct {
+	observers []ContribObserver
+}
+
+// compositeSpanObserver is a dispatcher to other span observers
+type compositeSpanObserver struct {
+	observers []ContribSpanObserver
+}
+
+// noopSpanObserver is used when there are no observers registered
+// on the Tracer or none of them returns span observers from OnStartSpan.
+var noopSpanObserver = &compositeSpanObserver{}
+
+func (o *compositeObserver) append(contribObserver ContribObserver) {
+	o.observers = append(o.observers, contribObserver)
+}
+
+func (o *compositeObserver) OnStartSpan(sp opentracing.Span, operationName string, options opentracing.StartSpanOptions) ContribSpanObserver {
+	var spanObservers []ContribSpanObserver
+	for _, obs := range o.observers {
+		spanObs, ok := obs.OnStartSpan(sp, operationName, options)
+		if ok {
+			if spanObservers == nil {
+				spanObservers = make([]ContribSpanObserver, 0, len(o.observers))
+			}
+			spanObservers = append(spanObservers, spanObs)
+		}
+	}
+	if len(spanObservers) == 0 {
+		return noopSpanObserver
+	}
+	return &compositeSpanObserver{observers: spanObservers}
+}
+
+func (o *compositeSpanObserver) OnSetOperationName(operationName string) {
+	for _, obs := range o.observers {
+		obs.OnSetOperationName(operationName)
+	}
+}
+
+func (o *compositeSpanObserver) OnSetTag(key string, value interface{}) {
+	for _, obs := range o.observers {
+		obs.OnSetTag(key, value)
+	}
+}
+
+func (o *compositeSpanObserver) OnFinish(options opentracing.FinishOptions) {
+	for _, obs := range o.observers {
+		obs.OnFinish(options)
+	}
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/process.go b/vendor/github.com/uber/jaeger-client-go/process.go
new file mode 100644
index 0000000..30cbf99
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/process.go
@@ -0,0 +1,29 @@
+// Copyright (c) 2018 The Jaeger Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+// Process holds process specific metadata that's relevant to this client.
+type Process struct {
+	Service string
+	UUID    string
+	Tags    []Tag
+}
+
+// ProcessSetter sets a process. This can be used by any class that requires
+// the process to be set as part of initialization.
+// See internal/throttler/remote/throttler.go for an example.
+type ProcessSetter interface {
+	SetProcess(process Process)
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/propagation.go b/vendor/github.com/uber/jaeger-client-go/propagation.go
new file mode 100644
index 0000000..42fd64b
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/propagation.go
@@ -0,0 +1,313 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import (
+	"bytes"
+	"encoding/binary"
+	"fmt"
+	"io"
+	"log"
+	"net/url"
+	"strings"
+	"sync"
+
+	opentracing "github.com/opentracing/opentracing-go"
+)
+
+// Injector is responsible for injecting SpanContext instances in a manner suitable
+// for propagation via a format-specific "carrier" object. Typically the
+// injection will take place across an RPC boundary, but message queues and
+// other IPC mechanisms are also reasonable places to use an Injector.
+type Injector interface {
+	// Inject takes `SpanContext` and injects it into `carrier`. The actual type
+	// of `carrier` depends on the `format` passed to `Tracer.Inject()`.
+	//
+	// Implementations may return opentracing.ErrInvalidCarrier or any other
+	// implementation-specific error if injection fails.
+	Inject(ctx SpanContext, carrier interface{}) error
+}
+
+// Extractor is responsible for extracting SpanContext instances from a
+// format-specific "carrier" object. Typically the extraction will take place
+// on the server side of an RPC boundary, but message queues and other IPC
+// mechanisms are also reasonable places to use an Extractor.
+type Extractor interface {
+	// Extract decodes a SpanContext instance from the given `carrier`,
+	// or (nil, opentracing.ErrSpanContextNotFound) if no context could
+	// be found in the `carrier`.
+	Extract(carrier interface{}) (SpanContext, error)
+}
+
+// TextMapPropagator is a combined Injector and Extractor for TextMap format
+type TextMapPropagator struct {
+	headerKeys  *HeadersConfig
+	metrics     Metrics
+	encodeValue func(string) string
+	decodeValue func(string) string
+}
+
+// NewTextMapPropagator creates a combined Injector and Extractor for TextMap format
+func NewTextMapPropagator(headerKeys *HeadersConfig, metrics Metrics) *TextMapPropagator {
+	return &TextMapPropagator{
+		headerKeys: headerKeys,
+		metrics:    metrics,
+		encodeValue: func(val string) string {
+			return val
+		},
+		decodeValue: func(val string) string {
+			return val
+		},
+	}
+}
+
+// NewHTTPHeaderPropagator creates a combined Injector and Extractor for HTTPHeaders format
+func NewHTTPHeaderPropagator(headerKeys *HeadersConfig, metrics Metrics) *TextMapPropagator {
+	return &TextMapPropagator{
+		headerKeys: headerKeys,
+		metrics:    metrics,
+		encodeValue: func(val string) string {
+			return url.QueryEscape(val)
+		},
+		decodeValue: func(val string) string {
+			// ignore decoding errors, cannot do anything about them
+			if v, err := url.QueryUnescape(val); err == nil {
+				return v
+			}
+			return val
+		},
+	}
+}
+
+// BinaryPropagator is a combined Injector and Extractor for Binary format
+type BinaryPropagator struct {
+	tracer  *Tracer
+	buffers sync.Pool
+}
+
+// NewBinaryPropagator creates a combined Injector and Extractor for Binary format
+func NewBinaryPropagator(tracer *Tracer) *BinaryPropagator {
+	return &BinaryPropagator{
+		tracer:  tracer,
+		buffers: sync.Pool{New: func() interface{} { return &bytes.Buffer{} }},
+	}
+}
+
+// Inject implements Injector of TextMapPropagator
+func (p *TextMapPropagator) Inject(
+	sc SpanContext,
+	abstractCarrier interface{},
+) error {
+	textMapWriter, ok := abstractCarrier.(opentracing.TextMapWriter)
+	if !ok {
+		return opentracing.ErrInvalidCarrier
+	}
+
+	// Do not encode the string with trace context to avoid accidental double-encoding
+	// if people are using opentracing < 0.10.0. Our colon-separated representation
+	// of the trace context is already safe for HTTP headers.
+	textMapWriter.Set(p.headerKeys.TraceContextHeaderName, sc.String())
+	for k, v := range sc.baggage {
+		safeKey := p.addBaggageKeyPrefix(k)
+		safeVal := p.encodeValue(v)
+		textMapWriter.Set(safeKey, safeVal)
+	}
+	return nil
+}
+
+// Extract implements Extractor of TextMapPropagator
+func (p *TextMapPropagator) Extract(abstractCarrier interface{}) (SpanContext, error) {
+	textMapReader, ok := abstractCarrier.(opentracing.TextMapReader)
+	if !ok {
+		return emptyContext, opentracing.ErrInvalidCarrier
+	}
+	var ctx SpanContext
+	var baggage map[string]string
+	err := textMapReader.ForeachKey(func(rawKey, value string) error {
+		key := strings.ToLower(rawKey) // TODO not necessary for plain TextMap
+		if key == p.headerKeys.TraceContextHeaderName {
+			var err error
+			safeVal := p.decodeValue(value)
+			if ctx, err = ContextFromString(safeVal); err != nil {
+				return err
+			}
+		} else if key == p.headerKeys.JaegerDebugHeader {
+			ctx.debugID = p.decodeValue(value)
+		} else if key == p.headerKeys.JaegerBaggageHeader {
+			if baggage == nil {
+				baggage = make(map[string]string)
+			}
+			for k, v := range p.parseCommaSeparatedMap(value) {
+				baggage[k] = v
+			}
+		} else if strings.HasPrefix(key, p.headerKeys.TraceBaggageHeaderPrefix) {
+			if baggage == nil {
+				baggage = make(map[string]string)
+			}
+			safeKey := p.removeBaggageKeyPrefix(key)
+			safeVal := p.decodeValue(value)
+			baggage[safeKey] = safeVal
+		}
+		return nil
+	})
+	if err != nil {
+		p.metrics.DecodingErrors.Inc(1)
+		return emptyContext, err
+	}
+	if !ctx.traceID.IsValid() && ctx.debugID == "" && len(baggage) == 0 {
+		return emptyContext, opentracing.ErrSpanContextNotFound
+	}
+	ctx.baggage = baggage
+	return ctx, nil
+}
+
+// Inject implements Injector of BinaryPropagator
+func (p *BinaryPropagator) Inject(
+	sc SpanContext,
+	abstractCarrier interface{},
+) error {
+	carrier, ok := abstractCarrier.(io.Writer)
+	if !ok {
+		return opentracing.ErrInvalidCarrier
+	}
+
+	// Handle the tracer context
+	if err := binary.Write(carrier, binary.BigEndian, sc.traceID); err != nil {
+		return err
+	}
+	if err := binary.Write(carrier, binary.BigEndian, sc.spanID); err != nil {
+		return err
+	}
+	if err := binary.Write(carrier, binary.BigEndian, sc.parentID); err != nil {
+		return err
+	}
+	if err := binary.Write(carrier, binary.BigEndian, sc.samplingState.flags()); err != nil {
+		return err
+	}
+
+	// Handle the baggage items
+	if err := binary.Write(carrier, binary.BigEndian, int32(len(sc.baggage))); err != nil {
+		return err
+	}
+	for k, v := range sc.baggage {
+		if err := binary.Write(carrier, binary.BigEndian, int32(len(k))); err != nil {
+			return err
+		}
+		io.WriteString(carrier, k)
+		if err := binary.Write(carrier, binary.BigEndian, int32(len(v))); err != nil {
+			return err
+		}
+		io.WriteString(carrier, v)
+	}
+
+	return nil
+}
+
+// Extract implements Extractor of BinaryPropagator
+func (p *BinaryPropagator) Extract(abstractCarrier interface{}) (SpanContext, error) {
+	carrier, ok := abstractCarrier.(io.Reader)
+	if !ok {
+		return emptyContext, opentracing.ErrInvalidCarrier
+	}
+	var ctx SpanContext
+	ctx.samplingState = &samplingState{}
+
+	if err := binary.Read(carrier, binary.BigEndian, &ctx.traceID); err != nil {
+		return emptyContext, opentracing.ErrSpanContextCorrupted
+	}
+	if err := binary.Read(carrier, binary.BigEndian, &ctx.spanID); err != nil {
+		return emptyContext, opentracing.ErrSpanContextCorrupted
+	}
+	if err := binary.Read(carrier, binary.BigEndian, &ctx.parentID); err != nil {
+		return emptyContext, opentracing.ErrSpanContextCorrupted
+	}
+
+	var flags byte
+	if err := binary.Read(carrier, binary.BigEndian, &flags); err != nil {
+		return emptyContext, opentracing.ErrSpanContextCorrupted
+	}
+	ctx.samplingState.setFlags(flags)
+
+	// Handle the baggage items
+	var numBaggage int32
+	if err := binary.Read(carrier, binary.BigEndian, &numBaggage); err != nil {
+		return emptyContext, opentracing.ErrSpanContextCorrupted
+	}
+	if iNumBaggage := int(numBaggage); iNumBaggage > 0 {
+		ctx.baggage = make(map[string]string, iNumBaggage)
+		buf := p.buffers.Get().(*bytes.Buffer)
+		defer p.buffers.Put(buf)
+
+		var keyLen, valLen int32
+		for i := 0; i < iNumBaggage; i++ {
+			if err := binary.Read(carrier, binary.BigEndian, &keyLen); err != nil {
+				return emptyContext, opentracing.ErrSpanContextCorrupted
+			}
+			buf.Reset()
+			buf.Grow(int(keyLen))
+			if n, err := io.CopyN(buf, carrier, int64(keyLen)); err != nil || int32(n) != keyLen {
+				return emptyContext, opentracing.ErrSpanContextCorrupted
+			}
+			key := buf.String()
+
+			if err := binary.Read(carrier, binary.BigEndian, &valLen); err != nil {
+				return emptyContext, opentracing.ErrSpanContextCorrupted
+			}
+			buf.Reset()
+			buf.Grow(int(valLen))
+			if n, err := io.CopyN(buf, carrier, int64(valLen)); err != nil || int32(n) != valLen {
+				return emptyContext, opentracing.ErrSpanContextCorrupted
+			}
+			ctx.baggage[key] = buf.String()
+		}
+	}
+
+	return ctx, nil
+}
+
+// Converts a comma separated key value pair list into a map
+// e.g. key1=value1, key2=value2, key3 = value3
+// is converted to map[string]string { "key1" : "value1",
+//                                     "key2" : "value2",
+//                                     "key3" : "value3" }
+func (p *TextMapPropagator) parseCommaSeparatedMap(value string) map[string]string {
+	baggage := make(map[string]string)
+	value, err := url.QueryUnescape(value)
+	if err != nil {
+		log.Printf("Unable to unescape %s, %v", value, err)
+		return baggage
+	}
+	for _, kvpair := range strings.Split(value, ",") {
+		kv := strings.Split(strings.TrimSpace(kvpair), "=")
+		if len(kv) == 2 {
+			baggage[kv[0]] = kv[1]
+		} else {
+			log.Printf("Malformed value passed in for %s", p.headerKeys.JaegerBaggageHeader)
+		}
+	}
+	return baggage
+}
+
+// Converts a baggage item key into an http header format,
+// by prepending TraceBaggageHeaderPrefix and encoding the key string
+func (p *TextMapPropagator) addBaggageKeyPrefix(key string) string {
+	// TODO encodeBaggageKeyAsHeader add caching and escaping
+	return fmt.Sprintf("%v%v", p.headerKeys.TraceBaggageHeaderPrefix, key)
+}
+
+func (p *TextMapPropagator) removeBaggageKeyPrefix(key string) string {
+	// TODO decodeBaggageHeaderKey add caching and escaping
+	return key[len(p.headerKeys.TraceBaggageHeaderPrefix):]
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/reference.go b/vendor/github.com/uber/jaeger-client-go/reference.go
new file mode 100644
index 0000000..5646e78
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/reference.go
@@ -0,0 +1,23 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import "github.com/opentracing/opentracing-go"
+
+// Reference represents a causal reference to other Spans (via their SpanContext).
+type Reference struct {
+	Type    opentracing.SpanReferenceType
+	Context SpanContext
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/reporter.go b/vendor/github.com/uber/jaeger-client-go/reporter.go
new file mode 100644
index 0000000..a71a92c
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/reporter.go
@@ -0,0 +1,322 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import (
+	"fmt"
+	"sync"
+	"sync/atomic"
+	"time"
+
+	"github.com/opentracing/opentracing-go"
+
+	"github.com/uber/jaeger-client-go/internal/reporterstats"
+	"github.com/uber/jaeger-client-go/log"
+)
+
+// Reporter is called by the tracer when a span is completed to report the span to the tracing collector.
+type Reporter interface {
+	// Report submits a new span to collectors, possibly asynchronously and/or with buffering.
+	// If the reporter is processing Span asynchronously then it needs to Retain() the span,
+	// and then Release() it when no longer needed, to avoid span data corruption.
+	Report(span *Span)
+
+	// Close does a clean shutdown of the reporter, flushing any traces that may be buffered in memory.
+	Close()
+}
+
+// ------------------------------
+
+type nullReporter struct{}
+
+// NewNullReporter creates a no-op reporter that ignores all reported spans.
+func NewNullReporter() Reporter {
+	return &nullReporter{}
+}
+
+// Report implements Report() method of Reporter by doing nothing.
+func (r *nullReporter) Report(span *Span) {
+	// no-op
+}
+
+// Close implements Close() method of Reporter by doing nothing.
+func (r *nullReporter) Close() {
+	// no-op
+}
+
+// ------------------------------
+
+type loggingReporter struct {
+	logger Logger
+}
+
+// NewLoggingReporter creates a reporter that logs all reported spans to provided logger.
+func NewLoggingReporter(logger Logger) Reporter {
+	return &loggingReporter{logger}
+}
+
+// Report implements Report() method of Reporter by logging the span to the logger.
+func (r *loggingReporter) Report(span *Span) {
+	r.logger.Infof("Reporting span %+v", span)
+}
+
+// Close implements Close() method of Reporter by doing nothing.
+func (r *loggingReporter) Close() {
+	// no-op
+}
+
+// ------------------------------
+
+// InMemoryReporter is used for testing, and simply collects spans in memory.
+type InMemoryReporter struct {
+	spans []opentracing.Span
+	lock  sync.Mutex
+}
+
+// NewInMemoryReporter creates a reporter that stores spans in memory.
+// NOTE: the Tracer should be created with options.PoolSpans = false.
+func NewInMemoryReporter() *InMemoryReporter {
+	return &InMemoryReporter{
+		spans: make([]opentracing.Span, 0, 10),
+	}
+}
+
+// Report implements Report() method of Reporter by storing the span in the buffer.
+func (r *InMemoryReporter) Report(span *Span) {
+	r.lock.Lock()
+	// Need to retain the span otherwise it will be released
+	r.spans = append(r.spans, span.Retain())
+	r.lock.Unlock()
+}
+
+// Close implements Close() method of Reporter
+func (r *InMemoryReporter) Close() {
+	r.Reset()
+}
+
+// SpansSubmitted returns the number of spans accumulated in the buffer.
+func (r *InMemoryReporter) SpansSubmitted() int {
+	r.lock.Lock()
+	defer r.lock.Unlock()
+	return len(r.spans)
+}
+
+// GetSpans returns accumulated spans as a copy of the buffer.
+func (r *InMemoryReporter) GetSpans() []opentracing.Span {
+	r.lock.Lock()
+	defer r.lock.Unlock()
+	copied := make([]opentracing.Span, len(r.spans))
+	copy(copied, r.spans)
+	return copied
+}
+
+// Reset clears all accumulated spans.
+func (r *InMemoryReporter) Reset() {
+	r.lock.Lock()
+	defer r.lock.Unlock()
+
+	// Before reset the collection need to release Span memory
+	for _, span := range r.spans {
+		span.(*Span).Release()
+	}
+	r.spans = r.spans[:0]
+}
+
+// ------------------------------
+
+type compositeReporter struct {
+	reporters []Reporter
+}
+
+// NewCompositeReporter creates a reporter that ignores all reported spans.
+func NewCompositeReporter(reporters ...Reporter) Reporter {
+	return &compositeReporter{reporters: reporters}
+}
+
+// Report implements Report() method of Reporter by delegating to each underlying reporter.
+func (r *compositeReporter) Report(span *Span) {
+	for _, reporter := range r.reporters {
+		reporter.Report(span)
+	}
+}
+
+// Close implements Close() method of Reporter by closing each underlying reporter.
+func (r *compositeReporter) Close() {
+	for _, reporter := range r.reporters {
+		reporter.Close()
+	}
+}
+
+// ------------- REMOTE REPORTER -----------------
+
+type reporterQueueItemType int
+
+const (
+	defaultQueueSize           = 100
+	defaultBufferFlushInterval = 1 * time.Second
+
+	reporterQueueItemSpan reporterQueueItemType = iota
+	reporterQueueItemClose
+)
+
+type reporterQueueItem struct {
+	itemType reporterQueueItemType
+	span     *Span
+	close    *sync.WaitGroup
+}
+
+// reporterStats implements reporterstats.ReporterStats.
+type reporterStats struct {
+	droppedCount int64 // provided to Transports to report data loss to the backend
+}
+
+// SpansDroppedFromQueue implements reporterstats.ReporterStats.
+func (r *reporterStats) SpansDroppedFromQueue() int64 {
+	return atomic.LoadInt64(&r.droppedCount)
+}
+
+func (r *reporterStats) incDroppedCount() {
+	atomic.AddInt64(&r.droppedCount, 1)
+}
+
+type remoteReporter struct {
+	// These fields must be first in the struct because `sync/atomic` expects 64-bit alignment.
+	// Cf. https://github.com/uber/jaeger-client-go/issues/155, https://goo.gl/zW7dgq
+	queueLength int64 // used to update metrics.Gauge
+	closed      int64 // 0 - not closed, 1 - closed
+
+	reporterOptions
+
+	sender        Transport
+	queue         chan reporterQueueItem
+	reporterStats *reporterStats
+}
+
+// NewRemoteReporter creates a new reporter that sends spans out of process by means of Sender.
+// Calls to Report(Span) return immediately (side effect: if internal buffer is full the span is dropped).
+// Periodically the transport buffer is flushed even if it hasn't reached max packet size.
+// Calls to Close() block until all spans reported prior to the call to Close are flushed.
+func NewRemoteReporter(sender Transport, opts ...ReporterOption) Reporter {
+	options := reporterOptions{}
+	for _, option := range opts {
+		option(&options)
+	}
+	if options.bufferFlushInterval <= 0 {
+		options.bufferFlushInterval = defaultBufferFlushInterval
+	}
+	if options.logger == nil {
+		options.logger = log.NullLogger
+	}
+	if options.metrics == nil {
+		options.metrics = NewNullMetrics()
+	}
+	if options.queueSize <= 0 {
+		options.queueSize = defaultQueueSize
+	}
+	reporter := &remoteReporter{
+		reporterOptions: options,
+		sender:          sender,
+		queue:           make(chan reporterQueueItem, options.queueSize),
+		reporterStats:   new(reporterStats),
+	}
+	if receiver, ok := sender.(reporterstats.Receiver); ok {
+		receiver.SetReporterStats(reporter.reporterStats)
+	}
+	go reporter.processQueue()
+	return reporter
+}
+
+// Report implements Report() method of Reporter.
+// It passes the span to a background go-routine for submission to Jaeger backend.
+// If the internal queue is full, the span is dropped and metrics.ReporterDropped counter is incremented.
+// If Report() is called after the reporter has been Close()-ed, the additional spans will not be
+// sent to the backend, but the metrics.ReporterDropped counter may not reflect them correctly,
+// because some of them may still be successfully added to the queue.
+func (r *remoteReporter) Report(span *Span) {
+	select {
+	// Need to retain the span otherwise it will be released
+	case r.queue <- reporterQueueItem{itemType: reporterQueueItemSpan, span: span.Retain()}:
+		atomic.AddInt64(&r.queueLength, 1)
+	default:
+		r.metrics.ReporterDropped.Inc(1)
+		r.reporterStats.incDroppedCount()
+	}
+}
+
+// Close implements Close() method of Reporter by waiting for the queue to be drained.
+func (r *remoteReporter) Close() {
+	r.logger.Debugf("closing reporter")
+	if swapped := atomic.CompareAndSwapInt64(&r.closed, 0, 1); !swapped {
+		r.logger.Error("Repeated attempt to close the reporter is ignored")
+		return
+	}
+	r.sendCloseEvent()
+	_ = r.sender.Close()
+}
+
+func (r *remoteReporter) sendCloseEvent() {
+	wg := &sync.WaitGroup{}
+	wg.Add(1)
+	item := reporterQueueItem{itemType: reporterQueueItemClose, close: wg}
+
+	r.queue <- item // if the queue is full we will block until there is space
+	atomic.AddInt64(&r.queueLength, 1)
+	wg.Wait()
+}
+
+// processQueue reads spans from the queue, converts them to Thrift, and stores them in an internal buffer.
+// When the buffer length reaches batchSize, it is flushed by submitting the accumulated spans to Jaeger.
+// Buffer also gets flushed automatically every batchFlushInterval seconds, just in case the tracer stopped
+// reporting new spans.
+func (r *remoteReporter) processQueue() {
+	// flush causes the Sender to flush its accumulated spans and clear the buffer
+	flush := func() {
+		if flushed, err := r.sender.Flush(); err != nil {
+			r.metrics.ReporterFailure.Inc(int64(flushed))
+			r.logger.Error(fmt.Sprintf("failed to flush Jaeger spans to server: %s", err.Error()))
+		} else if flushed > 0 {
+			r.metrics.ReporterSuccess.Inc(int64(flushed))
+		}
+	}
+
+	timer := time.NewTicker(r.bufferFlushInterval)
+	for {
+		select {
+		case <-timer.C:
+			flush()
+		case item := <-r.queue:
+			atomic.AddInt64(&r.queueLength, -1)
+			switch item.itemType {
+			case reporterQueueItemSpan:
+				span := item.span
+				if flushed, err := r.sender.Append(span); err != nil {
+					r.metrics.ReporterFailure.Inc(int64(flushed))
+					r.logger.Error(fmt.Sprintf("error reporting Jaeger span %q: %s", span.OperationName(), err.Error()))
+				} else if flushed > 0 {
+					r.metrics.ReporterSuccess.Inc(int64(flushed))
+					// to reduce the number of gauge stats, we only emit queue length on flush
+					r.metrics.ReporterQueueLength.Update(atomic.LoadInt64(&r.queueLength))
+					r.logger.Debugf("flushed %d spans", flushed)
+				}
+				span.Release()
+			case reporterQueueItemClose:
+				timer.Stop()
+				flush()
+				item.close.Done()
+				return
+			}
+		}
+	}
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/reporter_options.go b/vendor/github.com/uber/jaeger-client-go/reporter_options.go
new file mode 100644
index 0000000..2fc0305
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/reporter_options.go
@@ -0,0 +1,71 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import (
+	"time"
+
+	"github.com/uber/jaeger-client-go/log"
+)
+
+// ReporterOption is a function that sets some option on the reporter.
+type ReporterOption func(c *reporterOptions)
+
+// ReporterOptions is a factory for all available ReporterOption's
+var ReporterOptions reporterOptions
+
+// reporterOptions control behavior of the reporter.
+type reporterOptions struct {
+	// queueSize is the size of internal queue where reported spans are stored before they are processed in the background
+	queueSize int
+	// bufferFlushInterval is how often the buffer is force-flushed, even if it's not full
+	bufferFlushInterval time.Duration
+	// logger is used to log errors of span submissions
+	logger log.DebugLogger
+	// metrics is used to record runtime stats
+	metrics *Metrics
+}
+
+// QueueSize creates a ReporterOption that sets the size of the internal queue where
+// spans are stored before they are processed.
+func (reporterOptions) QueueSize(queueSize int) ReporterOption {
+	return func(r *reporterOptions) {
+		r.queueSize = queueSize
+	}
+}
+
+// Metrics creates a ReporterOption that initializes Metrics in the reporter,
+// which is used to record runtime statistics.
+func (reporterOptions) Metrics(metrics *Metrics) ReporterOption {
+	return func(r *reporterOptions) {
+		r.metrics = metrics
+	}
+}
+
+// BufferFlushInterval creates a ReporterOption that sets how often the queue
+// is force-flushed.
+func (reporterOptions) BufferFlushInterval(bufferFlushInterval time.Duration) ReporterOption {
+	return func(r *reporterOptions) {
+		r.bufferFlushInterval = bufferFlushInterval
+	}
+}
+
+// Logger creates a ReporterOption that initializes the logger used to log
+// errors of span submissions.
+func (reporterOptions) Logger(logger Logger) ReporterOption {
+	return func(r *reporterOptions) {
+		r.logger = log.DebugLogAdapter(logger)
+	}
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/rpcmetrics/README.md b/vendor/github.com/uber/jaeger-client-go/rpcmetrics/README.md
new file mode 100644
index 0000000..879948e
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/rpcmetrics/README.md
@@ -0,0 +1,5 @@
+An Observer that can be used to emit RPC metrics
+================================================
+
+It can be attached to the tracer during tracer construction.
+See `ExampleObserver` function in [observer_test.go](./observer_test.go).
diff --git a/vendor/github.com/uber/jaeger-client-go/rpcmetrics/doc.go b/vendor/github.com/uber/jaeger-client-go/rpcmetrics/doc.go
new file mode 100644
index 0000000..51aa11b
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/rpcmetrics/doc.go
@@ -0,0 +1,16 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package rpcmetrics implements an Observer that can be used to emit RPC metrics.
+package rpcmetrics
diff --git a/vendor/github.com/uber/jaeger-client-go/rpcmetrics/endpoints.go b/vendor/github.com/uber/jaeger-client-go/rpcmetrics/endpoints.go
new file mode 100644
index 0000000..3055524
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/rpcmetrics/endpoints.go
@@ -0,0 +1,63 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rpcmetrics
+
+import "sync"
+
+// normalizedEndpoints is a cache for endpointName -> safeName mappings.
+type normalizedEndpoints struct {
+	names       map[string]string
+	maxSize     int
+	defaultName string
+	normalizer  NameNormalizer
+	mux         sync.RWMutex
+}
+
+func newNormalizedEndpoints(maxSize int, normalizer NameNormalizer) *normalizedEndpoints {
+	return &normalizedEndpoints{
+		maxSize:    maxSize,
+		normalizer: normalizer,
+		names:      make(map[string]string, maxSize),
+	}
+}
+
+// normalize looks up the name in the cache, if not found it uses normalizer
+// to convert the name to a safe name. If called with more than maxSize unique
+// names it returns "" for all other names beyond those already cached.
+func (n *normalizedEndpoints) normalize(name string) string {
+	n.mux.RLock()
+	norm, ok := n.names[name]
+	l := len(n.names)
+	n.mux.RUnlock()
+	if ok {
+		return norm
+	}
+	if l >= n.maxSize {
+		return ""
+	}
+	return n.normalizeWithLock(name)
+}
+
+func (n *normalizedEndpoints) normalizeWithLock(name string) string {
+	norm := n.normalizer.Normalize(name)
+	n.mux.Lock()
+	defer n.mux.Unlock()
+	// cache may have grown while we were not holding the lock
+	if len(n.names) >= n.maxSize {
+		return ""
+	}
+	n.names[name] = norm
+	return norm
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/rpcmetrics/metrics.go b/vendor/github.com/uber/jaeger-client-go/rpcmetrics/metrics.go
new file mode 100644
index 0000000..a8cec2f
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/rpcmetrics/metrics.go
@@ -0,0 +1,124 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rpcmetrics
+
+import (
+	"sync"
+
+	"github.com/uber/jaeger-lib/metrics"
+)
+
+const (
+	otherEndpointsPlaceholder = "other"
+	endpointNameMetricTag     = "endpoint"
+)
+
+// Metrics is a collection of metrics for an endpoint describing
+// throughput, success, errors, and performance.
+type Metrics struct {
+	// RequestCountSuccess is a counter of the total number of successes.
+	RequestCountSuccess metrics.Counter `metric:"requests" tags:"error=false"`
+
+	// RequestCountFailures is a counter of the number of times any failure has been observed.
+	RequestCountFailures metrics.Counter `metric:"requests" tags:"error=true"`
+
+	// RequestLatencySuccess is a latency histogram of successful requests.
+	RequestLatencySuccess metrics.Timer `metric:"request_latency" tags:"error=false"`
+
+	// RequestLatencyFailures is a latency histogram of failed requests.
+	RequestLatencyFailures metrics.Timer `metric:"request_latency" tags:"error=true"`
+
+	// HTTPStatusCode2xx is a counter of the total number of requests with HTTP status code 200-299
+	HTTPStatusCode2xx metrics.Counter `metric:"http_requests" tags:"status_code=2xx"`
+
+	// HTTPStatusCode3xx is a counter of the total number of requests with HTTP status code 300-399
+	HTTPStatusCode3xx metrics.Counter `metric:"http_requests" tags:"status_code=3xx"`
+
+	// HTTPStatusCode4xx is a counter of the total number of requests with HTTP status code 400-499
+	HTTPStatusCode4xx metrics.Counter `metric:"http_requests" tags:"status_code=4xx"`
+
+	// HTTPStatusCode5xx is a counter of the total number of requests with HTTP status code 500-599
+	HTTPStatusCode5xx metrics.Counter `metric:"http_requests" tags:"status_code=5xx"`
+}
+
+func (m *Metrics) recordHTTPStatusCode(statusCode uint16) {
+	if statusCode >= 200 && statusCode < 300 {
+		m.HTTPStatusCode2xx.Inc(1)
+	} else if statusCode >= 300 && statusCode < 400 {
+		m.HTTPStatusCode3xx.Inc(1)
+	} else if statusCode >= 400 && statusCode < 500 {
+		m.HTTPStatusCode4xx.Inc(1)
+	} else if statusCode >= 500 && statusCode < 600 {
+		m.HTTPStatusCode5xx.Inc(1)
+	}
+}
+
+// MetricsByEndpoint is a registry/cache of metrics for each unique endpoint name.
+// Only maxNumberOfEndpoints Metrics are stored, all other endpoint names are mapped
+// to a generic endpoint name "other".
+type MetricsByEndpoint struct {
+	metricsFactory    metrics.Factory
+	endpoints         *normalizedEndpoints
+	metricsByEndpoint map[string]*Metrics
+	mux               sync.RWMutex
+}
+
+func newMetricsByEndpoint(
+	metricsFactory metrics.Factory,
+	normalizer NameNormalizer,
+	maxNumberOfEndpoints int,
+) *MetricsByEndpoint {
+	return &MetricsByEndpoint{
+		metricsFactory:    metricsFactory,
+		endpoints:         newNormalizedEndpoints(maxNumberOfEndpoints, normalizer),
+		metricsByEndpoint: make(map[string]*Metrics, maxNumberOfEndpoints+1), // +1 for "other"
+	}
+}
+
+func (m *MetricsByEndpoint) get(endpoint string) *Metrics {
+	safeName := m.endpoints.normalize(endpoint)
+	if safeName == "" {
+		safeName = otherEndpointsPlaceholder
+	}
+	m.mux.RLock()
+	met := m.metricsByEndpoint[safeName]
+	m.mux.RUnlock()
+	if met != nil {
+		return met
+	}
+
+	return m.getWithWriteLock(safeName)
+}
+
+// split to make easier to test
+func (m *MetricsByEndpoint) getWithWriteLock(safeName string) *Metrics {
+	m.mux.Lock()
+	defer m.mux.Unlock()
+
+	// it is possible that the name has been already registered after we released
+	// the read lock and before we grabbed the write lock, so check for that.
+	if met, ok := m.metricsByEndpoint[safeName]; ok {
+		return met
+	}
+
+	// it would be nice to create the struct before locking, since Init() is somewhat
+	// expensive, however some metrics backends (e.g. expvar) may not like duplicate metrics.
+	met := &Metrics{}
+	tags := map[string]string{endpointNameMetricTag: safeName}
+	metrics.Init(met, m.metricsFactory, tags)
+
+	m.metricsByEndpoint[safeName] = met
+	return met
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/rpcmetrics/normalizer.go b/vendor/github.com/uber/jaeger-client-go/rpcmetrics/normalizer.go
new file mode 100644
index 0000000..148d84b
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/rpcmetrics/normalizer.go
@@ -0,0 +1,101 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rpcmetrics
+
+// NameNormalizer is used to convert the endpoint names to strings
+// that can be safely used as tags in the metrics.
+type NameNormalizer interface {
+	Normalize(name string) string
+}
+
+// DefaultNameNormalizer converts endpoint names so that they contain only characters
+// from the safe charset [a-zA-Z0-9-./_]. All other characters are replaced with '-'.
+var DefaultNameNormalizer = &SimpleNameNormalizer{
+	SafeSets: []SafeCharacterSet{
+		&Range{From: 'a', To: 'z'},
+		&Range{From: 'A', To: 'Z'},
+		&Range{From: '0', To: '9'},
+		&Char{'-'},
+		&Char{'_'},
+		&Char{'/'},
+		&Char{'.'},
+	},
+	Replacement: '-',
+}
+
+// SimpleNameNormalizer uses a set of safe character sets.
+type SimpleNameNormalizer struct {
+	SafeSets    []SafeCharacterSet
+	Replacement byte
+}
+
+// SafeCharacterSet determines if the given character is "safe"
+type SafeCharacterSet interface {
+	IsSafe(c byte) bool
+}
+
+// Range implements SafeCharacterSet
+type Range struct {
+	From, To byte
+}
+
+// IsSafe implements SafeCharacterSet
+func (r *Range) IsSafe(c byte) bool {
+	return c >= r.From && c <= r.To
+}
+
+// Char implements SafeCharacterSet
+type Char struct {
+	Val byte
+}
+
+// IsSafe implements SafeCharacterSet
+func (ch *Char) IsSafe(c byte) bool {
+	return c == ch.Val
+}
+
+// Normalize checks each character in the string against SafeSets,
+// and if it's not safe substitutes it with Replacement.
+func (n *SimpleNameNormalizer) Normalize(name string) string {
+	var retMe []byte
+	nameBytes := []byte(name)
+	for i, b := range nameBytes {
+		if n.safeByte(b) {
+			if retMe != nil {
+				retMe[i] = b
+			}
+		} else {
+			if retMe == nil {
+				retMe = make([]byte, len(nameBytes))
+				copy(retMe[0:i], nameBytes[0:i])
+			}
+			retMe[i] = n.Replacement
+		}
+	}
+	if retMe == nil {
+		return name
+	}
+	return string(retMe)
+}
+
+// safeByte checks if b against all safe charsets.
+func (n *SimpleNameNormalizer) safeByte(b byte) bool {
+	for i := range n.SafeSets {
+		if n.SafeSets[i].IsSafe(b) {
+			return true
+		}
+	}
+	return false
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/rpcmetrics/observer.go b/vendor/github.com/uber/jaeger-client-go/rpcmetrics/observer.go
new file mode 100644
index 0000000..eca5ff6
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/rpcmetrics/observer.go
@@ -0,0 +1,171 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rpcmetrics
+
+import (
+	"strconv"
+	"sync"
+	"time"
+
+	"github.com/opentracing/opentracing-go"
+	"github.com/opentracing/opentracing-go/ext"
+	"github.com/uber/jaeger-lib/metrics"
+
+	jaeger "github.com/uber/jaeger-client-go"
+)
+
+const defaultMaxNumberOfEndpoints = 200
+
+// Observer is an observer that can emit RPC metrics.
+type Observer struct {
+	metricsByEndpoint *MetricsByEndpoint
+}
+
+// NewObserver creates a new observer that can emit RPC metrics.
+func NewObserver(metricsFactory metrics.Factory, normalizer NameNormalizer) *Observer {
+	return &Observer{
+		metricsByEndpoint: newMetricsByEndpoint(
+			metricsFactory,
+			normalizer,
+			defaultMaxNumberOfEndpoints,
+		),
+	}
+}
+
+// OnStartSpan creates a new Observer for the span.
+func (o *Observer) OnStartSpan(
+	operationName string,
+	options opentracing.StartSpanOptions,
+) jaeger.SpanObserver {
+	return NewSpanObserver(o.metricsByEndpoint, operationName, options)
+}
+
+// SpanKind identifies the span as inboud, outbound, or internal
+type SpanKind int
+
+const (
+	// Local span kind
+	Local SpanKind = iota
+	// Inbound span kind
+	Inbound
+	// Outbound span kind
+	Outbound
+)
+
+// SpanObserver collects RPC metrics
+type SpanObserver struct {
+	metricsByEndpoint *MetricsByEndpoint
+	operationName     string
+	startTime         time.Time
+	mux               sync.Mutex
+	kind              SpanKind
+	httpStatusCode    uint16
+	err               bool
+}
+
+// NewSpanObserver creates a new SpanObserver that can emit RPC metrics.
+func NewSpanObserver(
+	metricsByEndpoint *MetricsByEndpoint,
+	operationName string,
+	options opentracing.StartSpanOptions,
+) *SpanObserver {
+	so := &SpanObserver{
+		metricsByEndpoint: metricsByEndpoint,
+		operationName:     operationName,
+		startTime:         options.StartTime,
+	}
+	for k, v := range options.Tags {
+		so.handleTagInLock(k, v)
+	}
+	return so
+}
+
+// handleTags watches for special tags
+// - SpanKind
+// - HttpStatusCode
+// - Error
+func (so *SpanObserver) handleTagInLock(key string, value interface{}) {
+	if key == string(ext.SpanKind) {
+		if v, ok := value.(ext.SpanKindEnum); ok {
+			value = string(v)
+		}
+		if v, ok := value.(string); ok {
+			if v == string(ext.SpanKindRPCClientEnum) {
+				so.kind = Outbound
+			} else if v == string(ext.SpanKindRPCServerEnum) {
+				so.kind = Inbound
+			}
+		}
+		return
+	}
+	if key == string(ext.HTTPStatusCode) {
+		if v, ok := value.(uint16); ok {
+			so.httpStatusCode = v
+		} else if v, ok := value.(int); ok {
+			so.httpStatusCode = uint16(v)
+		} else if v, ok := value.(string); ok {
+			if vv, err := strconv.Atoi(v); err == nil {
+				so.httpStatusCode = uint16(vv)
+			}
+		}
+		return
+	}
+	if key == string(ext.Error) {
+		if v, ok := value.(bool); ok {
+			so.err = v
+		} else if v, ok := value.(string); ok {
+			if vv, err := strconv.ParseBool(v); err == nil {
+				so.err = vv
+			}
+		}
+		return
+	}
+}
+
+// OnFinish emits the RPC metrics. It only has an effect when operation name
+// is not blank, and the span kind is an RPC server.
+func (so *SpanObserver) OnFinish(options opentracing.FinishOptions) {
+	so.mux.Lock()
+	defer so.mux.Unlock()
+
+	if so.operationName == "" || so.kind != Inbound {
+		return
+	}
+
+	mets := so.metricsByEndpoint.get(so.operationName)
+	latency := options.FinishTime.Sub(so.startTime)
+	if so.err {
+		mets.RequestCountFailures.Inc(1)
+		mets.RequestLatencyFailures.Record(latency)
+	} else {
+		mets.RequestCountSuccess.Inc(1)
+		mets.RequestLatencySuccess.Record(latency)
+	}
+	mets.recordHTTPStatusCode(so.httpStatusCode)
+}
+
+// OnSetOperationName records new operation name.
+func (so *SpanObserver) OnSetOperationName(operationName string) {
+	so.mux.Lock()
+	so.operationName = operationName
+	so.mux.Unlock()
+}
+
+// OnSetTag implements SpanObserver
+func (so *SpanObserver) OnSetTag(key string, value interface{}) {
+	so.mux.Lock()
+	so.handleTagInLock(key, value)
+	so.mux.Unlock()
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/sampler.go b/vendor/github.com/uber/jaeger-client-go/sampler.go
new file mode 100644
index 0000000..d0be8ad
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/sampler.go
@@ -0,0 +1,516 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import (
+	"fmt"
+	"math"
+	"strings"
+	"sync"
+
+	"github.com/uber/jaeger-client-go/thrift-gen/sampling"
+	"github.com/uber/jaeger-client-go/utils"
+)
+
+const (
+	defaultMaxOperations = 2000
+)
+
+// Sampler decides whether a new trace should be sampled or not.
+type Sampler interface {
+	// IsSampled decides whether a trace with given `id` and `operation`
+	// should be sampled. This function will also return the tags that
+	// can be used to identify the type of sampling that was applied to
+	// the root span. Most simple samplers would return two tags,
+	// sampler.type and sampler.param, similar to those used in the Configuration
+	IsSampled(id TraceID, operation string) (sampled bool, tags []Tag)
+
+	// Close does a clean shutdown of the sampler, stopping any background
+	// go-routines it may have started.
+	Close()
+
+	// Equal checks if the `other` sampler is functionally equivalent
+	// to this sampler.
+	// TODO (breaking change) remove this function. See PerOperationSampler.Equals for explanation.
+	Equal(other Sampler) bool
+}
+
+// -----------------------
+
+// ConstSampler is a sampler that always makes the same decision.
+type ConstSampler struct {
+	legacySamplerV1Base
+	Decision bool
+	tags     []Tag
+}
+
+// NewConstSampler creates a ConstSampler.
+func NewConstSampler(sample bool) *ConstSampler {
+	tags := []Tag{
+		{key: SamplerTypeTagKey, value: SamplerTypeConst},
+		{key: SamplerParamTagKey, value: sample},
+	}
+	s := &ConstSampler{
+		Decision: sample,
+		tags:     tags,
+	}
+	s.delegate = s.IsSampled
+	return s
+}
+
+// IsSampled implements IsSampled() of Sampler.
+func (s *ConstSampler) IsSampled(id TraceID, operation string) (bool, []Tag) {
+	return s.Decision, s.tags
+}
+
+// Close implements Close() of Sampler.
+func (s *ConstSampler) Close() {
+	// nothing to do
+}
+
+// Equal implements Equal() of Sampler.
+func (s *ConstSampler) Equal(other Sampler) bool {
+	if o, ok := other.(*ConstSampler); ok {
+		return s.Decision == o.Decision
+	}
+	return false
+}
+
+// String is used to log sampler details.
+func (s *ConstSampler) String() string {
+	return fmt.Sprintf("ConstSampler(decision=%t)", s.Decision)
+}
+
+// -----------------------
+
+// ProbabilisticSampler is a sampler that randomly samples a certain percentage
+// of traces.
+type ProbabilisticSampler struct {
+	legacySamplerV1Base
+	samplingRate     float64
+	samplingBoundary uint64
+	tags             []Tag
+}
+
+const maxRandomNumber = ^(uint64(1) << 63) // i.e. 0x7fffffffffffffff
+
+// NewProbabilisticSampler creates a sampler that randomly samples a certain percentage of traces specified by the
+// samplingRate, in the range between 0.0 and 1.0.
+//
+// It relies on the fact that new trace IDs are 63bit random numbers themselves, thus making the sampling decision
+// without generating a new random number, but simply calculating if traceID < (samplingRate * 2^63).
+// TODO remove the error from this function for next major release
+func NewProbabilisticSampler(samplingRate float64) (*ProbabilisticSampler, error) {
+	if samplingRate < 0.0 || samplingRate > 1.0 {
+		return nil, fmt.Errorf("Sampling Rate must be between 0.0 and 1.0, received %f", samplingRate)
+	}
+	return newProbabilisticSampler(samplingRate), nil
+}
+
+func newProbabilisticSampler(samplingRate float64) *ProbabilisticSampler {
+	s := new(ProbabilisticSampler)
+	s.delegate = s.IsSampled
+	return s.init(samplingRate)
+}
+
+func (s *ProbabilisticSampler) init(samplingRate float64) *ProbabilisticSampler {
+	s.samplingRate = math.Max(0.0, math.Min(samplingRate, 1.0))
+	s.samplingBoundary = uint64(float64(maxRandomNumber) * s.samplingRate)
+	s.tags = []Tag{
+		{key: SamplerTypeTagKey, value: SamplerTypeProbabilistic},
+		{key: SamplerParamTagKey, value: s.samplingRate},
+	}
+	return s
+}
+
+// SamplingRate returns the sampling probability this sampled was constructed with.
+func (s *ProbabilisticSampler) SamplingRate() float64 {
+	return s.samplingRate
+}
+
+// IsSampled implements IsSampled() of Sampler.
+func (s *ProbabilisticSampler) IsSampled(id TraceID, operation string) (bool, []Tag) {
+	return s.samplingBoundary >= id.Low&maxRandomNumber, s.tags
+}
+
+// Close implements Close() of Sampler.
+func (s *ProbabilisticSampler) Close() {
+	// nothing to do
+}
+
+// Equal implements Equal() of Sampler.
+func (s *ProbabilisticSampler) Equal(other Sampler) bool {
+	if o, ok := other.(*ProbabilisticSampler); ok {
+		return s.samplingBoundary == o.samplingBoundary
+	}
+	return false
+}
+
+// Update modifies in-place the sampling rate. Locking must be done externally.
+func (s *ProbabilisticSampler) Update(samplingRate float64) error {
+	if samplingRate < 0.0 || samplingRate > 1.0 {
+		return fmt.Errorf("Sampling Rate must be between 0.0 and 1.0, received %f", samplingRate)
+	}
+	s.init(samplingRate)
+	return nil
+}
+
+// String is used to log sampler details.
+func (s *ProbabilisticSampler) String() string {
+	return fmt.Sprintf("ProbabilisticSampler(samplingRate=%v)", s.samplingRate)
+}
+
+// -----------------------
+
+// RateLimitingSampler samples at most maxTracesPerSecond. The distribution of sampled traces follows
+// burstiness of the service, i.e. a service with uniformly distributed requests will have those
+// requests sampled uniformly as well, but if requests are bursty, especially sub-second, then a
+// number of sequential requests can be sampled each second.
+type RateLimitingSampler struct {
+	legacySamplerV1Base
+	maxTracesPerSecond float64
+	rateLimiter        *utils.ReconfigurableRateLimiter
+	tags               []Tag
+}
+
+// NewRateLimitingSampler creates new RateLimitingSampler.
+func NewRateLimitingSampler(maxTracesPerSecond float64) *RateLimitingSampler {
+	s := new(RateLimitingSampler)
+	s.delegate = s.IsSampled
+	return s.init(maxTracesPerSecond)
+}
+
+func (s *RateLimitingSampler) init(maxTracesPerSecond float64) *RateLimitingSampler {
+	if s.rateLimiter == nil {
+		s.rateLimiter = utils.NewRateLimiter(maxTracesPerSecond, math.Max(maxTracesPerSecond, 1.0))
+	} else {
+		s.rateLimiter.Update(maxTracesPerSecond, math.Max(maxTracesPerSecond, 1.0))
+	}
+	s.maxTracesPerSecond = maxTracesPerSecond
+	s.tags = []Tag{
+		{key: SamplerTypeTagKey, value: SamplerTypeRateLimiting},
+		{key: SamplerParamTagKey, value: maxTracesPerSecond},
+	}
+	return s
+}
+
+// IsSampled implements IsSampled() of Sampler.
+func (s *RateLimitingSampler) IsSampled(id TraceID, operation string) (bool, []Tag) {
+	return s.rateLimiter.CheckCredit(1.0), s.tags
+}
+
+// Update reconfigures the rate limiter, while preserving its accumulated balance.
+// Locking must be done externally.
+func (s *RateLimitingSampler) Update(maxTracesPerSecond float64) {
+	if s.maxTracesPerSecond != maxTracesPerSecond {
+		s.init(maxTracesPerSecond)
+	}
+}
+
+// Close does nothing.
+func (s *RateLimitingSampler) Close() {
+	// nothing to do
+}
+
+// Equal compares with another sampler.
+func (s *RateLimitingSampler) Equal(other Sampler) bool {
+	if o, ok := other.(*RateLimitingSampler); ok {
+		return s.maxTracesPerSecond == o.maxTracesPerSecond
+	}
+	return false
+}
+
+// String is used to log sampler details.
+func (s *RateLimitingSampler) String() string {
+	return fmt.Sprintf("RateLimitingSampler(maxTracesPerSecond=%v)", s.maxTracesPerSecond)
+}
+
+// -----------------------
+
+// GuaranteedThroughputProbabilisticSampler is a sampler that leverages both ProbabilisticSampler and
+// RateLimitingSampler. The RateLimitingSampler is used as a guaranteed lower bound sampler such that
+// every operation is sampled at least once in a time interval defined by the lowerBound. ie a lowerBound
+// of 1.0 / (60 * 10) will sample an operation at least once every 10 minutes.
+//
+// The ProbabilisticSampler is given higher priority when tags are emitted, ie. if IsSampled() for both
+// samplers return true, the tags for ProbabilisticSampler will be used.
+type GuaranteedThroughputProbabilisticSampler struct {
+	probabilisticSampler *ProbabilisticSampler
+	lowerBoundSampler    *RateLimitingSampler
+	tags                 []Tag
+	samplingRate         float64
+	lowerBound           float64
+}
+
+// NewGuaranteedThroughputProbabilisticSampler returns a delegating sampler that applies both
+// ProbabilisticSampler and RateLimitingSampler.
+func NewGuaranteedThroughputProbabilisticSampler(
+	lowerBound, samplingRate float64,
+) (*GuaranteedThroughputProbabilisticSampler, error) {
+	return newGuaranteedThroughputProbabilisticSampler(lowerBound, samplingRate), nil
+}
+
+func newGuaranteedThroughputProbabilisticSampler(lowerBound, samplingRate float64) *GuaranteedThroughputProbabilisticSampler {
+	s := &GuaranteedThroughputProbabilisticSampler{
+		lowerBoundSampler: NewRateLimitingSampler(lowerBound),
+		lowerBound:        lowerBound,
+	}
+	s.setProbabilisticSampler(samplingRate)
+	return s
+}
+
+func (s *GuaranteedThroughputProbabilisticSampler) setProbabilisticSampler(samplingRate float64) {
+	if s.probabilisticSampler == nil {
+		s.probabilisticSampler = newProbabilisticSampler(samplingRate)
+	} else if s.samplingRate != samplingRate {
+		s.probabilisticSampler.init(samplingRate)
+	}
+	// since we don't validate samplingRate, sampler may have clamped it to [0, 1] interval
+	samplingRate = s.probabilisticSampler.SamplingRate()
+	if s.samplingRate != samplingRate || s.tags == nil {
+		s.samplingRate = s.probabilisticSampler.SamplingRate()
+		s.tags = []Tag{
+			{key: SamplerTypeTagKey, value: SamplerTypeLowerBound},
+			{key: SamplerParamTagKey, value: s.samplingRate},
+		}
+	}
+}
+
+// IsSampled implements IsSampled() of Sampler.
+func (s *GuaranteedThroughputProbabilisticSampler) IsSampled(id TraceID, operation string) (bool, []Tag) {
+	if sampled, tags := s.probabilisticSampler.IsSampled(id, operation); sampled {
+		s.lowerBoundSampler.IsSampled(id, operation)
+		return true, tags
+	}
+	sampled, _ := s.lowerBoundSampler.IsSampled(id, operation)
+	return sampled, s.tags
+}
+
+// Close implements Close() of Sampler.
+func (s *GuaranteedThroughputProbabilisticSampler) Close() {
+	s.probabilisticSampler.Close()
+	s.lowerBoundSampler.Close()
+}
+
+// Equal implements Equal() of Sampler.
+func (s *GuaranteedThroughputProbabilisticSampler) Equal(other Sampler) bool {
+	// NB The Equal() function is expensive and will be removed. See PerOperationSampler.Equal() for
+	// more information.
+	return false
+}
+
+// this function should only be called while holding a Write lock
+func (s *GuaranteedThroughputProbabilisticSampler) update(lowerBound, samplingRate float64) {
+	s.setProbabilisticSampler(samplingRate)
+	if s.lowerBound != lowerBound {
+		s.lowerBoundSampler.Update(lowerBound)
+		s.lowerBound = lowerBound
+	}
+}
+
+func (s GuaranteedThroughputProbabilisticSampler) String() string {
+	return fmt.Sprintf("GuaranteedThroughputProbabilisticSampler(lowerBound=%f, samplingRate=%f)", s.lowerBound, s.samplingRate)
+}
+
+// -----------------------
+
+// PerOperationSampler is a delegating sampler that applies GuaranteedThroughputProbabilisticSampler
+// on a per-operation basis.
+type PerOperationSampler struct {
+	sync.RWMutex
+
+	samplers       map[string]*GuaranteedThroughputProbabilisticSampler
+	defaultSampler *ProbabilisticSampler
+	lowerBound     float64
+	maxOperations  int
+
+	// see description in PerOperationSamplerParams
+	operationNameLateBinding bool
+}
+
+// NewAdaptiveSampler returns a new PerOperationSampler.
+// Deprecated: please use NewPerOperationSampler.
+func NewAdaptiveSampler(strategies *sampling.PerOperationSamplingStrategies, maxOperations int) (*PerOperationSampler, error) {
+	return NewPerOperationSampler(PerOperationSamplerParams{
+		MaxOperations: maxOperations,
+		Strategies:    strategies,
+	}), nil
+}
+
+// PerOperationSamplerParams defines parameters when creating PerOperationSampler.
+type PerOperationSamplerParams struct {
+	// Max number of operations that will be tracked. Other operations will be given default strategy.
+	MaxOperations int
+
+	// Opt-in feature for applications that require late binding of span name via explicit call to SetOperationName.
+	// When this feature is enabled, the sampler will return retryable=true from OnCreateSpan(), thus leaving
+	// the sampling decision as non-final (and the span as writeable). This may lead to degraded performance
+	// in applications that always provide the correct span name on trace creation.
+	//
+	// For backwards compatibility this option is off by default.
+	OperationNameLateBinding bool
+
+	// Initial configuration of the sampling strategies (usually retrieved from the backend by Remote Sampler).
+	Strategies *sampling.PerOperationSamplingStrategies
+}
+
+// NewPerOperationSampler returns a new PerOperationSampler.
+func NewPerOperationSampler(params PerOperationSamplerParams) *PerOperationSampler {
+	if params.MaxOperations <= 0 {
+		params.MaxOperations = defaultMaxOperations
+	}
+	samplers := make(map[string]*GuaranteedThroughputProbabilisticSampler)
+	for _, strategy := range params.Strategies.PerOperationStrategies {
+		sampler := newGuaranteedThroughputProbabilisticSampler(
+			params.Strategies.DefaultLowerBoundTracesPerSecond,
+			strategy.ProbabilisticSampling.SamplingRate,
+		)
+		samplers[strategy.Operation] = sampler
+	}
+	return &PerOperationSampler{
+		samplers:                 samplers,
+		defaultSampler:           newProbabilisticSampler(params.Strategies.DefaultSamplingProbability),
+		lowerBound:               params.Strategies.DefaultLowerBoundTracesPerSecond,
+		maxOperations:            params.MaxOperations,
+		operationNameLateBinding: params.OperationNameLateBinding,
+	}
+}
+
+// IsSampled is not used and only exists to match Sampler V1 API.
+// TODO (breaking change) remove when upgrading everything to SamplerV2
+func (s *PerOperationSampler) IsSampled(id TraceID, operation string) (bool, []Tag) {
+	return false, nil
+}
+
+func (s *PerOperationSampler) trySampling(span *Span, operationName string) (bool, []Tag) {
+	samplerV1 := s.getSamplerForOperation(operationName)
+	var sampled bool
+	var tags []Tag
+	if span.context.samplingState.isLocalRootSpan(span.context.spanID) {
+		sampled, tags = samplerV1.IsSampled(span.context.TraceID(), operationName)
+	}
+	return sampled, tags
+}
+
+// OnCreateSpan implements OnCreateSpan of SamplerV2.
+func (s *PerOperationSampler) OnCreateSpan(span *Span) SamplingDecision {
+	sampled, tags := s.trySampling(span, span.OperationName())
+	return SamplingDecision{Sample: sampled, Retryable: s.operationNameLateBinding, Tags: tags}
+}
+
+// OnSetOperationName implements OnSetOperationName of SamplerV2.
+func (s *PerOperationSampler) OnSetOperationName(span *Span, operationName string) SamplingDecision {
+	sampled, tags := s.trySampling(span, operationName)
+	return SamplingDecision{Sample: sampled, Retryable: false, Tags: tags}
+}
+
+// OnSetTag implements OnSetTag of SamplerV2.
+func (s *PerOperationSampler) OnSetTag(span *Span, key string, value interface{}) SamplingDecision {
+	return SamplingDecision{Sample: false, Retryable: true}
+}
+
+// OnFinishSpan implements OnFinishSpan of SamplerV2.
+func (s *PerOperationSampler) OnFinishSpan(span *Span) SamplingDecision {
+	return SamplingDecision{Sample: false, Retryable: true}
+}
+
+func (s *PerOperationSampler) getSamplerForOperation(operation string) Sampler {
+	s.RLock()
+	sampler, ok := s.samplers[operation]
+	if ok {
+		defer s.RUnlock()
+		return sampler
+	}
+	s.RUnlock()
+	s.Lock()
+	defer s.Unlock()
+
+	// Check if sampler has already been created
+	sampler, ok = s.samplers[operation]
+	if ok {
+		return sampler
+	}
+	// Store only up to maxOperations of unique ops.
+	if len(s.samplers) >= s.maxOperations {
+		return s.defaultSampler
+	}
+	newSampler := newGuaranteedThroughputProbabilisticSampler(s.lowerBound, s.defaultSampler.SamplingRate())
+	s.samplers[operation] = newSampler
+	return newSampler
+}
+
+// Close invokes Close on all underlying samplers.
+func (s *PerOperationSampler) Close() {
+	s.Lock()
+	defer s.Unlock()
+	for _, sampler := range s.samplers {
+		sampler.Close()
+	}
+	s.defaultSampler.Close()
+}
+
+func (s *PerOperationSampler) String() string {
+	var sb strings.Builder
+
+	fmt.Fprintf(&sb, "PerOperationSampler(defaultSampler=%v, ", s.defaultSampler)
+	fmt.Fprintf(&sb, "lowerBound=%f, ", s.lowerBound)
+	fmt.Fprintf(&sb, "maxOperations=%d, ", s.maxOperations)
+	fmt.Fprintf(&sb, "operationNameLateBinding=%t, ", s.operationNameLateBinding)
+	fmt.Fprintf(&sb, "numOperations=%d,\n", len(s.samplers))
+	fmt.Fprintf(&sb, "samplers=[")
+	for operationName, sampler := range s.samplers {
+		fmt.Fprintf(&sb, "\n(operationName=%s, sampler=%v)", operationName, sampler)
+	}
+	fmt.Fprintf(&sb, "])")
+
+	return sb.String()
+}
+
+// Equal is not used.
+// TODO (breaking change) remove this in the future
+func (s *PerOperationSampler) Equal(other Sampler) bool {
+	// NB The Equal() function is overly expensive for PerOperationSampler since it's composed of multiple
+	// samplers which all need to be initialized before this function can be called for a comparison.
+	// Therefore, PerOperationSampler uses the update() function to only alter the samplers that need
+	// changing. Hence this function always returns false so that the update function can be called.
+	// Once the Equal() function is removed from the Sampler API, this will no longer be needed.
+	return false
+}
+
+func (s *PerOperationSampler) update(strategies *sampling.PerOperationSamplingStrategies) {
+	s.Lock()
+	defer s.Unlock()
+	newSamplers := map[string]*GuaranteedThroughputProbabilisticSampler{}
+	for _, strategy := range strategies.PerOperationStrategies {
+		operation := strategy.Operation
+		samplingRate := strategy.ProbabilisticSampling.SamplingRate
+		lowerBound := strategies.DefaultLowerBoundTracesPerSecond
+		if sampler, ok := s.samplers[operation]; ok {
+			sampler.update(lowerBound, samplingRate)
+			newSamplers[operation] = sampler
+		} else {
+			sampler := newGuaranteedThroughputProbabilisticSampler(
+				lowerBound,
+				samplingRate,
+			)
+			newSamplers[operation] = sampler
+		}
+	}
+	s.lowerBound = strategies.DefaultLowerBoundTracesPerSecond
+	if s.defaultSampler.SamplingRate() != strategies.DefaultSamplingProbability {
+		s.defaultSampler = newProbabilisticSampler(strategies.DefaultSamplingProbability)
+	}
+	s.samplers = newSamplers
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/sampler_remote.go b/vendor/github.com/uber/jaeger-client-go/sampler_remote.go
new file mode 100644
index 0000000..112e3e1
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/sampler_remote.go
@@ -0,0 +1,337 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import (
+	"encoding/json"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"sync"
+	"sync/atomic"
+	"time"
+
+	"github.com/uber/jaeger-client-go/log"
+	"github.com/uber/jaeger-client-go/thrift-gen/sampling"
+)
+
+const (
+	defaultSamplingRefreshInterval = time.Minute
+)
+
+// SamplingStrategyFetcher is used to fetch sampling strategy updates from remote server.
+type SamplingStrategyFetcher interface {
+	Fetch(service string) ([]byte, error)
+}
+
+// SamplingStrategyParser is used to parse sampling strategy updates. The output object
+// should be of the type that is recognized by the SamplerUpdaters.
+type SamplingStrategyParser interface {
+	Parse(response []byte) (interface{}, error)
+}
+
+// SamplerUpdater is used by RemotelyControlledSampler to apply sampling strategies,
+// retrieved from remote config server, to the current sampler. The updater can modify
+// the sampler in-place if sampler supports it, or create a new one.
+//
+// If the strategy does not contain configuration for the sampler in question,
+// updater must return modifiedSampler=nil to give other updaters a chance to inspect
+// the sampling strategy response.
+//
+// RemotelyControlledSampler invokes the updaters while holding a lock on the main sampler.
+type SamplerUpdater interface {
+	Update(sampler SamplerV2, strategy interface{}) (modified SamplerV2, err error)
+}
+
+// RemotelyControlledSampler is a delegating sampler that polls a remote server
+// for the appropriate sampling strategy, constructs a corresponding sampler and
+// delegates to it for sampling decisions.
+type RemotelyControlledSampler struct {
+	// These fields must be first in the struct because `sync/atomic` expects 64-bit alignment.
+	// Cf. https://github.com/uber/jaeger-client-go/issues/155, https://goo.gl/zW7dgq
+	closed int64 // 0 - not closed, 1 - closed
+
+	sync.RWMutex
+	samplerOptions
+
+	serviceName string
+	doneChan    chan *sync.WaitGroup
+}
+
+// NewRemotelyControlledSampler creates a sampler that periodically pulls
+// the sampling strategy from an HTTP sampling server (e.g. jaeger-agent).
+func NewRemotelyControlledSampler(
+	serviceName string,
+	opts ...SamplerOption,
+) *RemotelyControlledSampler {
+	options := new(samplerOptions).applyOptionsAndDefaults(opts...)
+	sampler := &RemotelyControlledSampler{
+		samplerOptions: *options,
+		serviceName:    serviceName,
+		doneChan:       make(chan *sync.WaitGroup),
+	}
+	go sampler.pollController()
+	return sampler
+}
+
+// IsSampled implements IsSampled() of Sampler.
+// TODO (breaking change) remove when Sampler V1 is removed
+func (s *RemotelyControlledSampler) IsSampled(id TraceID, operation string) (bool, []Tag) {
+	return false, nil
+}
+
+// OnCreateSpan implements OnCreateSpan of SamplerV2.
+func (s *RemotelyControlledSampler) OnCreateSpan(span *Span) SamplingDecision {
+	return s.sampler.OnCreateSpan(span)
+}
+
+// OnSetOperationName implements OnSetOperationName of SamplerV2.
+func (s *RemotelyControlledSampler) OnSetOperationName(span *Span, operationName string) SamplingDecision {
+	return s.sampler.OnSetOperationName(span, operationName)
+}
+
+// OnSetTag implements OnSetTag of SamplerV2.
+func (s *RemotelyControlledSampler) OnSetTag(span *Span, key string, value interface{}) SamplingDecision {
+	return s.sampler.OnSetTag(span, key, value)
+}
+
+// OnFinishSpan implements OnFinishSpan of SamplerV2.
+func (s *RemotelyControlledSampler) OnFinishSpan(span *Span) SamplingDecision {
+	return s.sampler.OnFinishSpan(span)
+}
+
+// Close implements Close() of Sampler.
+func (s *RemotelyControlledSampler) Close() {
+	if swapped := atomic.CompareAndSwapInt64(&s.closed, 0, 1); !swapped {
+		s.logger.Error("Repeated attempt to close the sampler is ignored")
+		return
+	}
+
+	var wg sync.WaitGroup
+	wg.Add(1)
+	s.doneChan <- &wg
+	wg.Wait()
+}
+
+// Equal implements Equal() of Sampler.
+func (s *RemotelyControlledSampler) Equal(other Sampler) bool {
+	// NB The Equal() function is expensive and will be removed. See PerOperationSampler.Equal() for
+	// more information.
+	return false
+}
+
+func (s *RemotelyControlledSampler) pollController() {
+	ticker := time.NewTicker(s.samplingRefreshInterval)
+	defer ticker.Stop()
+	s.pollControllerWithTicker(ticker)
+}
+
+func (s *RemotelyControlledSampler) pollControllerWithTicker(ticker *time.Ticker) {
+	for {
+		select {
+		case <-ticker.C:
+			s.UpdateSampler()
+		case wg := <-s.doneChan:
+			wg.Done()
+			return
+		}
+	}
+}
+
+// Sampler returns the currently active sampler.
+func (s *RemotelyControlledSampler) Sampler() SamplerV2 {
+	s.Lock()
+	defer s.Unlock()
+	return s.sampler
+}
+
+func (s *RemotelyControlledSampler) setSampler(sampler SamplerV2) {
+	s.Lock()
+	defer s.Unlock()
+	s.sampler = sampler
+}
+
+// UpdateSampler forces the sampler to fetch sampling strategy from backend server.
+// This function is called automatically on a timer, but can also be safely called manually, e.g. from tests.
+func (s *RemotelyControlledSampler) UpdateSampler() {
+	res, err := s.samplingFetcher.Fetch(s.serviceName)
+	if err != nil {
+		s.metrics.SamplerQueryFailure.Inc(1)
+		s.logger.Infof("failed to fetch sampling strategy: %v", err)
+		return
+	}
+	strategy, err := s.samplingParser.Parse(res)
+	if err != nil {
+		s.metrics.SamplerUpdateFailure.Inc(1)
+		s.logger.Infof("failed to parse sampling strategy response: %v", err)
+		return
+	}
+
+	s.Lock()
+	defer s.Unlock()
+
+	s.metrics.SamplerRetrieved.Inc(1)
+	if err := s.updateSamplerViaUpdaters(strategy); err != nil {
+		s.metrics.SamplerUpdateFailure.Inc(1)
+		s.logger.Infof("failed to handle sampling strategy response %+v. Got error: %v", res, err)
+		return
+	}
+	s.metrics.SamplerUpdated.Inc(1)
+}
+
+// NB: this function should only be called while holding a Write lock
+func (s *RemotelyControlledSampler) updateSamplerViaUpdaters(strategy interface{}) error {
+	for _, updater := range s.updaters {
+		sampler, err := updater.Update(s.sampler, strategy)
+		if err != nil {
+			return err
+		}
+		if sampler != nil {
+			s.logger.Debugf("sampler updated: %+v", sampler)
+			s.sampler = sampler
+			return nil
+		}
+	}
+	return fmt.Errorf("unsupported sampling strategy %+v", strategy)
+}
+
+// -----------------------
+
+// ProbabilisticSamplerUpdater is used by RemotelyControlledSampler to parse sampling configuration.
+type ProbabilisticSamplerUpdater struct{}
+
+// Update implements Update of SamplerUpdater.
+func (u *ProbabilisticSamplerUpdater) Update(sampler SamplerV2, strategy interface{}) (SamplerV2, error) {
+	type response interface {
+		GetProbabilisticSampling() *sampling.ProbabilisticSamplingStrategy
+	}
+	var _ response = new(sampling.SamplingStrategyResponse) // sanity signature check
+	if resp, ok := strategy.(response); ok {
+		if probabilistic := resp.GetProbabilisticSampling(); probabilistic != nil {
+			if ps, ok := sampler.(*ProbabilisticSampler); ok {
+				if err := ps.Update(probabilistic.SamplingRate); err != nil {
+					return nil, err
+				}
+				return sampler, nil
+			}
+			return newProbabilisticSampler(probabilistic.SamplingRate), nil
+		}
+	}
+	return nil, nil
+}
+
+// -----------------------
+
+// RateLimitingSamplerUpdater is used by RemotelyControlledSampler to parse sampling configuration.
+type RateLimitingSamplerUpdater struct{}
+
+// Update implements Update of SamplerUpdater.
+func (u *RateLimitingSamplerUpdater) Update(sampler SamplerV2, strategy interface{}) (SamplerV2, error) {
+	type response interface {
+		GetRateLimitingSampling() *sampling.RateLimitingSamplingStrategy
+	}
+	var _ response = new(sampling.SamplingStrategyResponse) // sanity signature check
+	if resp, ok := strategy.(response); ok {
+		if rateLimiting := resp.GetRateLimitingSampling(); rateLimiting != nil {
+			rateLimit := float64(rateLimiting.MaxTracesPerSecond)
+			if rl, ok := sampler.(*RateLimitingSampler); ok {
+				rl.Update(rateLimit)
+				return rl, nil
+			}
+			return NewRateLimitingSampler(rateLimit), nil
+		}
+	}
+	return nil, nil
+}
+
+// -----------------------
+
+// AdaptiveSamplerUpdater is used by RemotelyControlledSampler to parse sampling configuration.
+// Fields have the same meaning as in PerOperationSamplerParams.
+type AdaptiveSamplerUpdater struct {
+	MaxOperations            int
+	OperationNameLateBinding bool
+}
+
+// Update implements Update of SamplerUpdater.
+func (u *AdaptiveSamplerUpdater) Update(sampler SamplerV2, strategy interface{}) (SamplerV2, error) {
+	type response interface {
+		GetOperationSampling() *sampling.PerOperationSamplingStrategies
+	}
+	var _ response = new(sampling.SamplingStrategyResponse) // sanity signature check
+	if p, ok := strategy.(response); ok {
+		if operations := p.GetOperationSampling(); operations != nil {
+			if as, ok := sampler.(*PerOperationSampler); ok {
+				as.update(operations)
+				return as, nil
+			}
+			return NewPerOperationSampler(PerOperationSamplerParams{
+				MaxOperations:            u.MaxOperations,
+				OperationNameLateBinding: u.OperationNameLateBinding,
+				Strategies:               operations,
+			}), nil
+		}
+	}
+	return nil, nil
+}
+
+// -----------------------
+
+type httpSamplingStrategyFetcher struct {
+	serverURL string
+	logger    log.DebugLogger
+}
+
+func (f *httpSamplingStrategyFetcher) Fetch(serviceName string) ([]byte, error) {
+	v := url.Values{}
+	v.Set("service", serviceName)
+	uri := f.serverURL + "?" + v.Encode()
+
+	// TODO create and reuse http.Client with proper timeout settings, etc.
+	resp, err := http.Get(uri)
+	if err != nil {
+		return nil, err
+	}
+
+	defer func() {
+		if err := resp.Body.Close(); err != nil {
+			f.logger.Error(fmt.Sprintf("failed to close HTTP response body: %+v", err))
+		}
+	}()
+
+	body, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return nil, err
+	}
+
+	if resp.StatusCode >= 400 {
+		return nil, fmt.Errorf("StatusCode: %d, Body: %s", resp.StatusCode, body)
+	}
+
+	return body, nil
+}
+
+// -----------------------
+
+type samplingStrategyParser struct{}
+
+func (p *samplingStrategyParser) Parse(response []byte) (interface{}, error) {
+	strategy := new(sampling.SamplingStrategyResponse)
+	if err := json.Unmarshal(response, strategy); err != nil {
+		return nil, err
+	}
+	return strategy, nil
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/sampler_remote_options.go b/vendor/github.com/uber/jaeger-client-go/sampler_remote_options.go
new file mode 100644
index 0000000..e4a6108
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/sampler_remote_options.go
@@ -0,0 +1,162 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import (
+	"time"
+
+	"github.com/uber/jaeger-client-go/log"
+)
+
+// SamplerOption is a function that sets some option on the sampler
+type SamplerOption func(options *samplerOptions)
+
+// SamplerOptions is a factory for all available SamplerOption's.
+var SamplerOptions SamplerOptionsFactory
+
+// SamplerOptionsFactory is a factory for all available SamplerOption's.
+// The type acts as a namespace for factory functions. It is public to
+// make the functions discoverable via godoc. Recommended to be used
+// via global SamplerOptions variable.
+type SamplerOptionsFactory struct{}
+
+type samplerOptions struct {
+	metrics                 *Metrics
+	sampler                 SamplerV2
+	logger                  log.DebugLogger
+	samplingServerURL       string
+	samplingRefreshInterval time.Duration
+	samplingFetcher         SamplingStrategyFetcher
+	samplingParser          SamplingStrategyParser
+	updaters                []SamplerUpdater
+	posParams               PerOperationSamplerParams
+}
+
+// Metrics creates a SamplerOption that initializes Metrics on the sampler,
+// which is used to emit statistics.
+func (SamplerOptionsFactory) Metrics(m *Metrics) SamplerOption {
+	return func(o *samplerOptions) {
+		o.metrics = m
+	}
+}
+
+// MaxOperations creates a SamplerOption that sets the maximum number of
+// operations the sampler will keep track of.
+func (SamplerOptionsFactory) MaxOperations(maxOperations int) SamplerOption {
+	return func(o *samplerOptions) {
+		o.posParams.MaxOperations = maxOperations
+	}
+}
+
+// OperationNameLateBinding creates a SamplerOption that sets the respective
+// field in the PerOperationSamplerParams.
+func (SamplerOptionsFactory) OperationNameLateBinding(enable bool) SamplerOption {
+	return func(o *samplerOptions) {
+		o.posParams.OperationNameLateBinding = enable
+	}
+}
+
+// InitialSampler creates a SamplerOption that sets the initial sampler
+// to use before a remote sampler is created and used.
+func (SamplerOptionsFactory) InitialSampler(sampler Sampler) SamplerOption {
+	return func(o *samplerOptions) {
+		o.sampler = samplerV1toV2(sampler)
+	}
+}
+
+// Logger creates a SamplerOption that sets the logger used by the sampler.
+func (SamplerOptionsFactory) Logger(logger Logger) SamplerOption {
+	return func(o *samplerOptions) {
+		o.logger = log.DebugLogAdapter(logger)
+	}
+}
+
+// SamplingServerURL creates a SamplerOption that sets the sampling server url
+// of the local agent that contains the sampling strategies.
+func (SamplerOptionsFactory) SamplingServerURL(samplingServerURL string) SamplerOption {
+	return func(o *samplerOptions) {
+		o.samplingServerURL = samplingServerURL
+	}
+}
+
+// SamplingRefreshInterval creates a SamplerOption that sets how often the
+// sampler will poll local agent for the appropriate sampling strategy.
+func (SamplerOptionsFactory) SamplingRefreshInterval(samplingRefreshInterval time.Duration) SamplerOption {
+	return func(o *samplerOptions) {
+		o.samplingRefreshInterval = samplingRefreshInterval
+	}
+}
+
+// SamplingStrategyFetcher creates a SamplerOption that initializes sampling strategy fetcher.
+func (SamplerOptionsFactory) SamplingStrategyFetcher(fetcher SamplingStrategyFetcher) SamplerOption {
+	return func(o *samplerOptions) {
+		o.samplingFetcher = fetcher
+	}
+}
+
+// SamplingStrategyParser creates a SamplerOption that initializes sampling strategy parser.
+func (SamplerOptionsFactory) SamplingStrategyParser(parser SamplingStrategyParser) SamplerOption {
+	return func(o *samplerOptions) {
+		o.samplingParser = parser
+	}
+}
+
+// Updaters creates a SamplerOption that initializes sampler updaters.
+func (SamplerOptionsFactory) Updaters(updaters ...SamplerUpdater) SamplerOption {
+	return func(o *samplerOptions) {
+		o.updaters = updaters
+	}
+}
+
+func (o *samplerOptions) applyOptionsAndDefaults(opts ...SamplerOption) *samplerOptions {
+	for _, option := range opts {
+		option(o)
+	}
+	if o.sampler == nil {
+		o.sampler = newProbabilisticSampler(0.001)
+	}
+	if o.logger == nil {
+		o.logger = log.NullLogger
+	}
+	if o.samplingServerURL == "" {
+		o.samplingServerURL = DefaultSamplingServerURL
+	}
+	if o.metrics == nil {
+		o.metrics = NewNullMetrics()
+	}
+	if o.samplingRefreshInterval <= 0 {
+		o.samplingRefreshInterval = defaultSamplingRefreshInterval
+	}
+	if o.samplingFetcher == nil {
+		o.samplingFetcher = &httpSamplingStrategyFetcher{
+			serverURL: o.samplingServerURL,
+			logger:    o.logger,
+		}
+	}
+	if o.samplingParser == nil {
+		o.samplingParser = new(samplingStrategyParser)
+	}
+	if o.updaters == nil {
+		o.updaters = []SamplerUpdater{
+			&AdaptiveSamplerUpdater{
+				MaxOperations:            o.posParams.MaxOperations,
+				OperationNameLateBinding: o.posParams.OperationNameLateBinding,
+			},
+			new(ProbabilisticSamplerUpdater),
+			new(RateLimitingSamplerUpdater),
+		}
+	}
+	return o
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/sampler_v2.go b/vendor/github.com/uber/jaeger-client-go/sampler_v2.go
new file mode 100644
index 0000000..a50671a
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/sampler_v2.go
@@ -0,0 +1,93 @@
+// Copyright (c) 2019 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+// SamplingDecision is returned by the V2 samplers.
+type SamplingDecision struct {
+	Sample    bool
+	Retryable bool
+	Tags      []Tag
+}
+
+// SamplerV2 is an extension of the V1 samplers that allows sampling decisions
+// be made at different points of the span lifecycle.
+type SamplerV2 interface {
+	OnCreateSpan(span *Span) SamplingDecision
+	OnSetOperationName(span *Span, operationName string) SamplingDecision
+	OnSetTag(span *Span, key string, value interface{}) SamplingDecision
+	OnFinishSpan(span *Span) SamplingDecision
+
+	// Close does a clean shutdown of the sampler, stopping any background
+	// go-routines it may have started.
+	Close()
+}
+
+// samplerV1toV2 wraps legacy V1 sampler into an adapter that make it look like V2.
+func samplerV1toV2(s Sampler) SamplerV2 {
+	if s2, ok := s.(SamplerV2); ok {
+		return s2
+	}
+	type legacySamplerV1toV2Adapter struct {
+		legacySamplerV1Base
+	}
+	return &legacySamplerV1toV2Adapter{
+		legacySamplerV1Base: legacySamplerV1Base{
+			delegate: s.IsSampled,
+		},
+	}
+}
+
+// SamplerV2Base can be used by V2 samplers to implement dummy V1 methods.
+// Supporting V1 API is required because Tracer configuration only accepts V1 Sampler
+// for backwards compatibility reasons.
+// TODO (breaking change) remove this in the next major release
+type SamplerV2Base struct{}
+
+// IsSampled implements IsSampled of Sampler.
+func (SamplerV2Base) IsSampled(id TraceID, operation string) (sampled bool, tags []Tag) {
+	return false, nil
+}
+
+// Close implements Close of Sampler.
+func (SamplerV2Base) Close() {}
+
+// Equal implements Equal of Sampler.
+func (SamplerV2Base) Equal(other Sampler) bool { return false }
+
+// legacySamplerV1Base is used as a base for simple samplers that only implement
+// the legacy isSampled() function that is not sensitive to its arguments.
+type legacySamplerV1Base struct {
+	delegate func(id TraceID, operation string) (sampled bool, tags []Tag)
+}
+
+func (s *legacySamplerV1Base) OnCreateSpan(span *Span) SamplingDecision {
+	isSampled, tags := s.delegate(span.context.traceID, span.operationName)
+	return SamplingDecision{Sample: isSampled, Retryable: false, Tags: tags}
+}
+
+func (s *legacySamplerV1Base) OnSetOperationName(span *Span, operationName string) SamplingDecision {
+	isSampled, tags := s.delegate(span.context.traceID, span.operationName)
+	return SamplingDecision{Sample: isSampled, Retryable: false, Tags: tags}
+}
+
+func (s *legacySamplerV1Base) OnSetTag(span *Span, key string, value interface{}) SamplingDecision {
+	return SamplingDecision{Sample: false, Retryable: true}
+}
+
+func (s *legacySamplerV1Base) OnFinishSpan(span *Span) SamplingDecision {
+	return SamplingDecision{Sample: false, Retryable: true}
+}
+
+func (s *legacySamplerV1Base) Close() {}
diff --git a/vendor/github.com/uber/jaeger-client-go/span.go b/vendor/github.com/uber/jaeger-client-go/span.go
new file mode 100644
index 0000000..42c9112
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/span.go
@@ -0,0 +1,487 @@
+// Copyright (c) 2017-2018 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import (
+	"sync"
+	"sync/atomic"
+	"time"
+
+	"github.com/opentracing/opentracing-go"
+	"github.com/opentracing/opentracing-go/ext"
+	"github.com/opentracing/opentracing-go/log"
+)
+
+// Span implements opentracing.Span
+type Span struct {
+	// referenceCounter used to increase the lifetime of
+	// the object before return it into the pool.
+	referenceCounter int32
+
+	sync.RWMutex
+
+	tracer *Tracer
+
+	// TODO: (breaking change) change to use a pointer
+	context SpanContext
+
+	// The name of the "operation" this span is an instance of.
+	// Known as a "span name" in some implementations.
+	operationName string
+
+	// firstInProcess, if true, indicates that this span is the root of the (sub)tree
+	// of spans in the current process. In other words it's true for the root spans,
+	// and the ingress spans when the process joins another trace.
+	firstInProcess bool
+
+	// startTime is the timestamp indicating when the span began, with microseconds precision.
+	startTime time.Time
+
+	// duration returns duration of the span with microseconds precision.
+	// Zero value means duration is unknown.
+	duration time.Duration
+
+	// tags attached to this span
+	tags []Tag
+
+	// The span's "micro-log"
+	logs []opentracing.LogRecord
+
+	// The number of logs dropped because of MaxLogsPerSpan.
+	numDroppedLogs int
+
+	// references for this span
+	references []Reference
+
+	observer ContribSpanObserver
+}
+
+// Tag is a simple key value wrapper.
+// TODO (breaking change) deprecate in the next major release, use opentracing.Tag instead.
+type Tag struct {
+	key   string
+	value interface{}
+}
+
+// NewTag creates a new Tag.
+// TODO (breaking change) deprecate in the next major release, use opentracing.Tag instead.
+func NewTag(key string, value interface{}) Tag {
+	return Tag{key: key, value: value}
+}
+
+// SetOperationName sets or changes the operation name.
+func (s *Span) SetOperationName(operationName string) opentracing.Span {
+	s.Lock()
+	s.operationName = operationName
+	s.Unlock()
+	if !s.isSamplingFinalized() {
+		decision := s.tracer.sampler.OnSetOperationName(s, operationName)
+		s.applySamplingDecision(decision, true)
+	}
+	s.observer.OnSetOperationName(operationName)
+	return s
+}
+
+// SetTag implements SetTag() of opentracing.Span
+func (s *Span) SetTag(key string, value interface{}) opentracing.Span {
+	return s.setTagInternal(key, value, true)
+}
+
+func (s *Span) setTagInternal(key string, value interface{}, lock bool) opentracing.Span {
+	s.observer.OnSetTag(key, value)
+	if key == string(ext.SamplingPriority) && !setSamplingPriority(s, value) {
+		return s
+	}
+	if !s.isSamplingFinalized() {
+		decision := s.tracer.sampler.OnSetTag(s, key, value)
+		s.applySamplingDecision(decision, lock)
+	}
+	if s.isWriteable() {
+		if lock {
+			s.Lock()
+			defer s.Unlock()
+		}
+		s.appendTagNoLocking(key, value)
+	}
+	return s
+}
+
+// SpanContext returns span context
+func (s *Span) SpanContext() SpanContext {
+	s.Lock()
+	defer s.Unlock()
+	return s.context
+}
+
+// StartTime returns span start time
+func (s *Span) StartTime() time.Time {
+	s.Lock()
+	defer s.Unlock()
+	return s.startTime
+}
+
+// Duration returns span duration
+func (s *Span) Duration() time.Duration {
+	s.Lock()
+	defer s.Unlock()
+	return s.duration
+}
+
+// Tags returns tags for span
+func (s *Span) Tags() opentracing.Tags {
+	s.Lock()
+	defer s.Unlock()
+	var result = make(opentracing.Tags, len(s.tags))
+	for _, tag := range s.tags {
+		result[tag.key] = tag.value
+	}
+	return result
+}
+
+// Logs returns micro logs for span
+func (s *Span) Logs() []opentracing.LogRecord {
+	s.Lock()
+	defer s.Unlock()
+
+	logs := append([]opentracing.LogRecord(nil), s.logs...)
+	if s.numDroppedLogs != 0 {
+		fixLogs(logs, s.numDroppedLogs)
+	}
+
+	return logs
+}
+
+// References returns references for this span
+func (s *Span) References() []opentracing.SpanReference {
+	s.Lock()
+	defer s.Unlock()
+
+	if s.references == nil || len(s.references) == 0 {
+		return nil
+	}
+
+	result := make([]opentracing.SpanReference, len(s.references))
+	for i, r := range s.references {
+		result[i] = opentracing.SpanReference{Type: r.Type, ReferencedContext: r.Context}
+	}
+	return result
+}
+
+func (s *Span) appendTagNoLocking(key string, value interface{}) {
+	s.tags = append(s.tags, Tag{key: key, value: value})
+}
+
+// LogFields implements opentracing.Span API
+func (s *Span) LogFields(fields ...log.Field) {
+	s.Lock()
+	defer s.Unlock()
+	if !s.context.IsSampled() {
+		return
+	}
+	s.logFieldsNoLocking(fields...)
+}
+
+// this function should only be called while holding a Write lock
+func (s *Span) logFieldsNoLocking(fields ...log.Field) {
+	lr := opentracing.LogRecord{
+		Fields:    fields,
+		Timestamp: time.Now(),
+	}
+	s.appendLogNoLocking(lr)
+}
+
+// LogKV implements opentracing.Span API
+func (s *Span) LogKV(alternatingKeyValues ...interface{}) {
+	s.RLock()
+	sampled := s.context.IsSampled()
+	s.RUnlock()
+	if !sampled {
+		return
+	}
+	fields, err := log.InterleavedKVToFields(alternatingKeyValues...)
+	if err != nil {
+		s.LogFields(log.Error(err), log.String("function", "LogKV"))
+		return
+	}
+	s.LogFields(fields...)
+}
+
+// LogEvent implements opentracing.Span API
+func (s *Span) LogEvent(event string) {
+	s.Log(opentracing.LogData{Event: event})
+}
+
+// LogEventWithPayload implements opentracing.Span API
+func (s *Span) LogEventWithPayload(event string, payload interface{}) {
+	s.Log(opentracing.LogData{Event: event, Payload: payload})
+}
+
+// Log implements opentracing.Span API
+func (s *Span) Log(ld opentracing.LogData) {
+	s.Lock()
+	defer s.Unlock()
+	if s.context.IsSampled() {
+		if ld.Timestamp.IsZero() {
+			ld.Timestamp = s.tracer.timeNow()
+		}
+		s.appendLogNoLocking(ld.ToLogRecord())
+	}
+}
+
+// this function should only be called while holding a Write lock
+func (s *Span) appendLogNoLocking(lr opentracing.LogRecord) {
+	maxLogs := s.tracer.options.maxLogsPerSpan
+	if maxLogs == 0 || len(s.logs) < maxLogs {
+		s.logs = append(s.logs, lr)
+		return
+	}
+
+	// We have too many logs. We don't touch the first numOld logs; we treat the
+	// rest as a circular buffer and overwrite the oldest log among those.
+	numOld := (maxLogs - 1) / 2
+	numNew := maxLogs - numOld
+	s.logs[numOld+s.numDroppedLogs%numNew] = lr
+	s.numDroppedLogs++
+}
+
+// rotateLogBuffer rotates the records in the buffer: records 0 to pos-1 move at
+// the end (i.e. pos circular left shifts).
+func rotateLogBuffer(buf []opentracing.LogRecord, pos int) {
+	// This algorithm is described in:
+	//    http://www.cplusplus.com/reference/algorithm/rotate
+	for first, middle, next := 0, pos, pos; first != middle; {
+		buf[first], buf[next] = buf[next], buf[first]
+		first++
+		next++
+		if next == len(buf) {
+			next = middle
+		} else if first == middle {
+			middle = next
+		}
+	}
+}
+
+func fixLogs(logs []opentracing.LogRecord, numDroppedLogs int) {
+	// We dropped some log events, which means that we used part of Logs as a
+	// circular buffer (see appendLog). De-circularize it.
+	numOld := (len(logs) - 1) / 2
+	numNew := len(logs) - numOld
+	rotateLogBuffer(logs[numOld:], numDroppedLogs%numNew)
+
+	// Replace the log in the middle (the oldest "new" log) with information
+	// about the dropped logs. This means that we are effectively dropping one
+	// more "new" log.
+	numDropped := numDroppedLogs + 1
+	logs[numOld] = opentracing.LogRecord{
+		// Keep the timestamp of the last dropped event.
+		Timestamp: logs[numOld].Timestamp,
+		Fields: []log.Field{
+			log.String("event", "dropped Span logs"),
+			log.Int("dropped_log_count", numDropped),
+			log.String("component", "jaeger-client"),
+		},
+	}
+}
+
+func (s *Span) fixLogsIfDropped() {
+	if s.numDroppedLogs == 0 {
+		return
+	}
+	fixLogs(s.logs, s.numDroppedLogs)
+	s.numDroppedLogs = 0
+}
+
+// SetBaggageItem implements SetBaggageItem() of opentracing.SpanContext
+func (s *Span) SetBaggageItem(key, value string) opentracing.Span {
+	s.Lock()
+	defer s.Unlock()
+	s.tracer.setBaggage(s, key, value)
+	return s
+}
+
+// BaggageItem implements BaggageItem() of opentracing.SpanContext
+func (s *Span) BaggageItem(key string) string {
+	s.RLock()
+	defer s.RUnlock()
+	return s.context.baggage[key]
+}
+
+// Finish implements opentracing.Span API
+// After finishing the Span object it returns back to the allocator unless the reporter retains it again,
+// so after that, the Span object should no longer be used because it won't be valid anymore.
+func (s *Span) Finish() {
+	s.FinishWithOptions(opentracing.FinishOptions{})
+}
+
+// FinishWithOptions implements opentracing.Span API
+func (s *Span) FinishWithOptions(options opentracing.FinishOptions) {
+	if options.FinishTime.IsZero() {
+		options.FinishTime = s.tracer.timeNow()
+	}
+	s.observer.OnFinish(options)
+	s.Lock()
+	s.duration = options.FinishTime.Sub(s.startTime)
+	s.Unlock()
+	if !s.isSamplingFinalized() {
+		decision := s.tracer.sampler.OnFinishSpan(s)
+		s.applySamplingDecision(decision, true)
+	}
+	if s.context.IsSampled() {
+		s.Lock()
+		s.fixLogsIfDropped()
+		if len(options.LogRecords) > 0 || len(options.BulkLogData) > 0 {
+			// Note: bulk logs are not subject to maxLogsPerSpan limit
+			if options.LogRecords != nil {
+				s.logs = append(s.logs, options.LogRecords...)
+			}
+			for _, ld := range options.BulkLogData {
+				s.logs = append(s.logs, ld.ToLogRecord())
+			}
+		}
+		s.Unlock()
+	}
+	// call reportSpan even for non-sampled traces, to return span to the pool
+	// and update metrics counter
+	s.tracer.reportSpan(s)
+}
+
+// Context implements opentracing.Span API
+func (s *Span) Context() opentracing.SpanContext {
+	s.Lock()
+	defer s.Unlock()
+	return s.context
+}
+
+// Tracer implements opentracing.Span API
+func (s *Span) Tracer() opentracing.Tracer {
+	return s.tracer
+}
+
+func (s *Span) String() string {
+	s.RLock()
+	defer s.RUnlock()
+	return s.context.String()
+}
+
+// OperationName allows retrieving current operation name.
+func (s *Span) OperationName() string {
+	s.RLock()
+	defer s.RUnlock()
+	return s.operationName
+}
+
+// Retain increases object counter to increase the lifetime of the object
+func (s *Span) Retain() *Span {
+	atomic.AddInt32(&s.referenceCounter, 1)
+	return s
+}
+
+// Release decrements object counter and return to the
+// allocator manager  when counter will below zero
+func (s *Span) Release() {
+	if atomic.AddInt32(&s.referenceCounter, -1) == -1 {
+		s.tracer.spanAllocator.Put(s)
+	}
+}
+
+// reset span state and release unused data
+func (s *Span) reset() {
+	s.firstInProcess = false
+	s.context = emptyContext
+	s.operationName = ""
+	s.tracer = nil
+	s.startTime = time.Time{}
+	s.duration = 0
+	s.observer = nil
+	atomic.StoreInt32(&s.referenceCounter, 0)
+
+	// Note: To reuse memory we can save the pointers on the heap
+	s.tags = s.tags[:0]
+	s.logs = s.logs[:0]
+	s.numDroppedLogs = 0
+	s.references = s.references[:0]
+}
+
+func (s *Span) serviceName() string {
+	return s.tracer.serviceName
+}
+
+func (s *Span) applySamplingDecision(decision SamplingDecision, lock bool) {
+	if !decision.Retryable {
+		s.context.samplingState.setFinal()
+	}
+	if decision.Sample {
+		s.context.samplingState.setSampled()
+		if len(decision.Tags) > 0 {
+			if lock {
+				s.Lock()
+				defer s.Unlock()
+			}
+			for _, tag := range decision.Tags {
+				s.appendTagNoLocking(tag.key, tag.value)
+			}
+		}
+	}
+}
+
+// Span can be written to if it is sampled or the sampling decision has not been finalized.
+func (s *Span) isWriteable() bool {
+	state := s.context.samplingState
+	return !state.isFinal() || state.isSampled()
+}
+
+func (s *Span) isSamplingFinalized() bool {
+	return s.context.samplingState.isFinal()
+}
+
+// setSamplingPriority returns true if the flag was updated successfully, false otherwise.
+// The behavior of setSamplingPriority is surprising
+// If noDebugFlagOnForcedSampling is set
+//     setSamplingPriority(span, 1) always sets only flagSampled
+// If noDebugFlagOnForcedSampling is unset, and isDebugAllowed passes
+//     setSamplingPriority(span, 1) sets both flagSampled and flagDebug
+// However,
+//     setSamplingPriority(span, 0) always only resets flagSampled
+//
+// This means that doing a setSamplingPriority(span, 1) followed by setSamplingPriority(span, 0) can
+// leave flagDebug set
+func setSamplingPriority(s *Span, value interface{}) bool {
+	val, ok := value.(uint16)
+	if !ok {
+		return false
+	}
+	if val == 0 {
+		s.context.samplingState.unsetSampled()
+		s.context.samplingState.setFinal()
+		return true
+	}
+	if s.tracer.options.noDebugFlagOnForcedSampling {
+		s.context.samplingState.setSampled()
+		s.context.samplingState.setFinal()
+		return true
+	} else if s.tracer.isDebugAllowed(s.operationName) {
+		s.context.samplingState.setDebugAndSampled()
+		s.context.samplingState.setFinal()
+		return true
+	}
+	return false
+}
+
+// EnableFirehose enables firehose flag on the span context
+func EnableFirehose(s *Span) {
+	s.Lock()
+	defer s.Unlock()
+	s.context.samplingState.setFirehose()
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/span_allocator.go b/vendor/github.com/uber/jaeger-client-go/span_allocator.go
new file mode 100644
index 0000000..6fe0cd0
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/span_allocator.go
@@ -0,0 +1,56 @@
+// Copyright (c) 2019 The Jaeger Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import "sync"
+
+// SpanAllocator abstraction of managign span allocations
+type SpanAllocator interface {
+	Get() *Span
+	Put(*Span)
+}
+
+type syncPollSpanAllocator struct {
+	spanPool sync.Pool
+}
+
+func newSyncPollSpanAllocator() SpanAllocator {
+	return &syncPollSpanAllocator{
+		spanPool: sync.Pool{New: func() interface{} {
+			return &Span{}
+		}},
+	}
+}
+
+func (pool *syncPollSpanAllocator) Get() *Span {
+	return pool.spanPool.Get().(*Span)
+}
+
+func (pool *syncPollSpanAllocator) Put(span *Span) {
+	span.reset()
+	pool.spanPool.Put(span)
+}
+
+type simpleSpanAllocator struct{}
+
+func (pool simpleSpanAllocator) Get() *Span {
+	return &Span{}
+}
+
+func (pool simpleSpanAllocator) Put(span *Span) {
+	// @comment https://github.com/jaegertracing/jaeger-client-go/pull/381#issuecomment-475904351
+	// since finished spans are not reused, no need to reset them
+	// span.reset()
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/span_context.go b/vendor/github.com/uber/jaeger-client-go/span_context.go
new file mode 100644
index 0000000..1b44f3f
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/span_context.go
@@ -0,0 +1,383 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import (
+	"errors"
+	"fmt"
+	"strconv"
+	"strings"
+	"sync"
+
+	"go.uber.org/atomic"
+)
+
+const (
+	flagSampled  = 1
+	flagDebug    = 2
+	flagFirehose = 8
+)
+
+var (
+	errEmptyTracerStateString     = errors.New("Cannot convert empty string to tracer state")
+	errMalformedTracerStateString = errors.New("String does not match tracer state format")
+
+	emptyContext = SpanContext{}
+)
+
+// TraceID represents unique 128bit identifier of a trace
+type TraceID struct {
+	High, Low uint64
+}
+
+// SpanID represents unique 64bit identifier of a span
+type SpanID uint64
+
+// SpanContext represents propagated span identity and state
+type SpanContext struct {
+	// traceID represents globally unique ID of the trace.
+	// Usually generated as a random number.
+	traceID TraceID
+
+	// spanID represents span ID that must be unique within its trace,
+	// but does not have to be globally unique.
+	spanID SpanID
+
+	// parentID refers to the ID of the parent span.
+	// Should be 0 if the current span is a root span.
+	parentID SpanID
+
+	// Distributed Context baggage. The is a snapshot in time.
+	baggage map[string]string
+
+	// debugID can be set to some correlation ID when the context is being
+	// extracted from a TextMap carrier.
+	//
+	// See JaegerDebugHeader in constants.go
+	debugID string
+
+	// samplingState is shared across all spans
+	samplingState *samplingState
+
+	// remote indicates that span context represents a remote parent
+	remote bool
+}
+
+type samplingState struct {
+	// Span context's state flags that are propagated across processes. Only lower 8 bits are used.
+	// We use an int32 instead of byte to be able to use CAS operations.
+	stateFlags atomic.Int32
+
+	// When state is not final, sampling will be retried on other span write operations,
+	// like SetOperationName / SetTag, and the spans will remain writable.
+	final atomic.Bool
+
+	// localRootSpan stores the SpanID of the first span created in this process for a given trace.
+	localRootSpan SpanID
+
+	// extendedState allows samplers to keep intermediate state.
+	// The keys and values in this map are completely opaque: interface{} -> interface{}.
+	extendedState sync.Map
+}
+
+func (s *samplingState) isLocalRootSpan(id SpanID) bool {
+	return id == s.localRootSpan
+}
+
+func (s *samplingState) setFlag(newFlag int32) {
+	swapped := false
+	for !swapped {
+		old := s.stateFlags.Load()
+		swapped = s.stateFlags.CAS(old, old|newFlag)
+	}
+}
+
+func (s *samplingState) unsetFlag(newFlag int32) {
+	swapped := false
+	for !swapped {
+		old := s.stateFlags.Load()
+		swapped = s.stateFlags.CAS(old, old&^newFlag)
+	}
+}
+
+func (s *samplingState) setSampled() {
+	s.setFlag(flagSampled)
+}
+
+func (s *samplingState) unsetSampled() {
+	s.unsetFlag(flagSampled)
+}
+
+func (s *samplingState) setDebugAndSampled() {
+	s.setFlag(flagDebug | flagSampled)
+}
+
+func (s *samplingState) setFirehose() {
+	s.setFlag(flagFirehose)
+}
+
+func (s *samplingState) setFlags(flags byte) {
+	s.stateFlags.Store(int32(flags))
+}
+
+func (s *samplingState) setFinal() {
+	s.final.Store(true)
+}
+
+func (s *samplingState) flags() byte {
+	return byte(s.stateFlags.Load())
+}
+
+func (s *samplingState) isSampled() bool {
+	return s.stateFlags.Load()&flagSampled == flagSampled
+}
+
+func (s *samplingState) isDebug() bool {
+	return s.stateFlags.Load()&flagDebug == flagDebug
+}
+
+func (s *samplingState) isFirehose() bool {
+	return s.stateFlags.Load()&flagFirehose == flagFirehose
+}
+
+func (s *samplingState) isFinal() bool {
+	return s.final.Load()
+}
+
+func (s *samplingState) extendedStateForKey(key interface{}, initValue func() interface{}) interface{} {
+	if value, ok := s.extendedState.Load(key); ok {
+		return value
+	}
+	value := initValue()
+	value, _ = s.extendedState.LoadOrStore(key, value)
+	return value
+}
+
+// ForeachBaggageItem implements ForeachBaggageItem() of opentracing.SpanContext
+func (c SpanContext) ForeachBaggageItem(handler func(k, v string) bool) {
+	for k, v := range c.baggage {
+		if !handler(k, v) {
+			break
+		}
+	}
+}
+
+// IsSampled returns whether this trace was chosen for permanent storage
+// by the sampling mechanism of the tracer.
+func (c SpanContext) IsSampled() bool {
+	return c.samplingState.isSampled()
+}
+
+// IsDebug indicates whether sampling was explicitly requested by the service.
+func (c SpanContext) IsDebug() bool {
+	return c.samplingState.isDebug()
+}
+
+// IsSamplingFinalized indicates whether the sampling decision has been finalized.
+func (c SpanContext) IsSamplingFinalized() bool {
+	return c.samplingState.isFinal()
+}
+
+// IsFirehose indicates whether the firehose flag was set
+func (c SpanContext) IsFirehose() bool {
+	return c.samplingState.isFirehose()
+}
+
+// ExtendedSamplingState returns the custom state object for a given key. If the value for this key does not exist,
+// it is initialized via initValue function. This state can be used by samplers (e.g. x.PrioritySampler).
+func (c SpanContext) ExtendedSamplingState(key interface{}, initValue func() interface{}) interface{} {
+	return c.samplingState.extendedStateForKey(key, initValue)
+}
+
+// IsValid indicates whether this context actually represents a valid trace.
+func (c SpanContext) IsValid() bool {
+	return c.traceID.IsValid() && c.spanID != 0
+}
+
+// SetFirehose enables firehose mode for this trace.
+func (c SpanContext) SetFirehose() {
+	c.samplingState.setFirehose()
+}
+
+func (c SpanContext) String() string {
+	if c.traceID.High == 0 {
+		return fmt.Sprintf("%016x:%016x:%016x:%x", c.traceID.Low, uint64(c.spanID), uint64(c.parentID), c.samplingState.stateFlags.Load())
+	}
+	return fmt.Sprintf("%016x%016x:%016x:%016x:%x", c.traceID.High, c.traceID.Low, uint64(c.spanID), uint64(c.parentID), c.samplingState.stateFlags.Load())
+}
+
+// ContextFromString reconstructs the Context encoded in a string
+func ContextFromString(value string) (SpanContext, error) {
+	var context SpanContext
+	if value == "" {
+		return emptyContext, errEmptyTracerStateString
+	}
+	parts := strings.Split(value, ":")
+	if len(parts) != 4 {
+		return emptyContext, errMalformedTracerStateString
+	}
+	var err error
+	if context.traceID, err = TraceIDFromString(parts[0]); err != nil {
+		return emptyContext, err
+	}
+	if context.spanID, err = SpanIDFromString(parts[1]); err != nil {
+		return emptyContext, err
+	}
+	if context.parentID, err = SpanIDFromString(parts[2]); err != nil {
+		return emptyContext, err
+	}
+	flags, err := strconv.ParseUint(parts[3], 10, 8)
+	if err != nil {
+		return emptyContext, err
+	}
+	context.samplingState = &samplingState{}
+	context.samplingState.setFlags(byte(flags))
+	return context, nil
+}
+
+// TraceID returns the trace ID of this span context
+func (c SpanContext) TraceID() TraceID {
+	return c.traceID
+}
+
+// SpanID returns the span ID of this span context
+func (c SpanContext) SpanID() SpanID {
+	return c.spanID
+}
+
+// ParentID returns the parent span ID of this span context
+func (c SpanContext) ParentID() SpanID {
+	return c.parentID
+}
+
+// Flags returns the bitmap containing such bits as 'sampled' and 'debug'.
+func (c SpanContext) Flags() byte {
+	return c.samplingState.flags()
+}
+
+// NewSpanContext creates a new instance of SpanContext
+func NewSpanContext(traceID TraceID, spanID, parentID SpanID, sampled bool, baggage map[string]string) SpanContext {
+	samplingState := &samplingState{}
+	if sampled {
+		samplingState.setSampled()
+	}
+
+	return SpanContext{
+		traceID:       traceID,
+		spanID:        spanID,
+		parentID:      parentID,
+		samplingState: samplingState,
+		baggage:       baggage}
+}
+
+// CopyFrom copies data from ctx into this context, including span identity and baggage.
+// TODO This is only used by interop.go. Remove once TChannel Go supports OpenTracing.
+func (c *SpanContext) CopyFrom(ctx *SpanContext) {
+	c.traceID = ctx.traceID
+	c.spanID = ctx.spanID
+	c.parentID = ctx.parentID
+	c.samplingState = ctx.samplingState
+	if l := len(ctx.baggage); l > 0 {
+		c.baggage = make(map[string]string, l)
+		for k, v := range ctx.baggage {
+			c.baggage[k] = v
+		}
+	} else {
+		c.baggage = nil
+	}
+}
+
+// WithBaggageItem creates a new context with an extra baggage item.
+func (c SpanContext) WithBaggageItem(key, value string) SpanContext {
+	var newBaggage map[string]string
+	if c.baggage == nil {
+		newBaggage = map[string]string{key: value}
+	} else {
+		newBaggage = make(map[string]string, len(c.baggage)+1)
+		for k, v := range c.baggage {
+			newBaggage[k] = v
+		}
+		newBaggage[key] = value
+	}
+	// Use positional parameters so the compiler will help catch new fields.
+	return SpanContext{c.traceID, c.spanID, c.parentID, newBaggage, "", c.samplingState, c.remote}
+}
+
+// isDebugIDContainerOnly returns true when the instance of the context is only
+// used to return the debug/correlation ID from extract() method. This happens
+// in the situation when "jaeger-debug-id" header is passed in the carrier to
+// the extract() method, but the request otherwise has no span context in it.
+// Previously this would've returned opentracing.ErrSpanContextNotFound from the
+// extract method, but now it returns a dummy context with only debugID filled in.
+//
+// See JaegerDebugHeader in constants.go
+// See TextMapPropagator#Extract
+func (c *SpanContext) isDebugIDContainerOnly() bool {
+	return !c.traceID.IsValid() && c.debugID != ""
+}
+
+// ------- TraceID -------
+
+func (t TraceID) String() string {
+	if t.High == 0 {
+		return fmt.Sprintf("%x", t.Low)
+	}
+	return fmt.Sprintf("%x%016x", t.High, t.Low)
+}
+
+// TraceIDFromString creates a TraceID from a hexadecimal string
+func TraceIDFromString(s string) (TraceID, error) {
+	var hi, lo uint64
+	var err error
+	if len(s) > 32 {
+		return TraceID{}, fmt.Errorf("TraceID cannot be longer than 32 hex characters: %s", s)
+	} else if len(s) > 16 {
+		hiLen := len(s) - 16
+		if hi, err = strconv.ParseUint(s[0:hiLen], 16, 64); err != nil {
+			return TraceID{}, err
+		}
+		if lo, err = strconv.ParseUint(s[hiLen:], 16, 64); err != nil {
+			return TraceID{}, err
+		}
+	} else {
+		if lo, err = strconv.ParseUint(s, 16, 64); err != nil {
+			return TraceID{}, err
+		}
+	}
+	return TraceID{High: hi, Low: lo}, nil
+}
+
+// IsValid checks if the trace ID is valid, i.e. not zero.
+func (t TraceID) IsValid() bool {
+	return t.High != 0 || t.Low != 0
+}
+
+// ------- SpanID -------
+
+func (s SpanID) String() string {
+	return fmt.Sprintf("%x", uint64(s))
+}
+
+// SpanIDFromString creates a SpanID from a hexadecimal string
+func SpanIDFromString(s string) (SpanID, error) {
+	if len(s) > 16 {
+		return SpanID(0), fmt.Errorf("SpanID cannot be longer than 16 hex characters: %s", s)
+	}
+	id, err := strconv.ParseUint(s, 16, 64)
+	if err != nil {
+		return SpanID(0), err
+	}
+	return SpanID(id), nil
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/agent/agent.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/agent/agent.go
new file mode 100644
index 0000000..e48811c
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/agent/agent.go
@@ -0,0 +1,411 @@
+// Autogenerated by Thrift Compiler (0.9.3)
+// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+
+package agent
+
+import (
+	"bytes"
+	"fmt"
+	"github.com/uber/jaeger-client-go/thrift"
+	"github.com/uber/jaeger-client-go/thrift-gen/jaeger"
+	"github.com/uber/jaeger-client-go/thrift-gen/zipkincore"
+)
+
+// (needed to ensure safety because of naive import list construction.)
+var _ = thrift.ZERO
+var _ = fmt.Printf
+var _ = bytes.Equal
+
+var _ = jaeger.GoUnusedProtection__
+var _ = zipkincore.GoUnusedProtection__
+
+type Agent interface {
+	// Parameters:
+	//  - Spans
+	EmitZipkinBatch(spans []*zipkincore.Span) (err error)
+	// Parameters:
+	//  - Batch
+	EmitBatch(batch *jaeger.Batch) (err error)
+}
+
+type AgentClient struct {
+	Transport       thrift.TTransport
+	ProtocolFactory thrift.TProtocolFactory
+	InputProtocol   thrift.TProtocol
+	OutputProtocol  thrift.TProtocol
+	SeqId           int32
+}
+
+func NewAgentClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *AgentClient {
+	return &AgentClient{Transport: t,
+		ProtocolFactory: f,
+		InputProtocol:   f.GetProtocol(t),
+		OutputProtocol:  f.GetProtocol(t),
+		SeqId:           0,
+	}
+}
+
+func NewAgentClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *AgentClient {
+	return &AgentClient{Transport: t,
+		ProtocolFactory: nil,
+		InputProtocol:   iprot,
+		OutputProtocol:  oprot,
+		SeqId:           0,
+	}
+}
+
+// Parameters:
+//  - Spans
+func (p *AgentClient) EmitZipkinBatch(spans []*zipkincore.Span) (err error) {
+	if err = p.sendEmitZipkinBatch(spans); err != nil {
+		return
+	}
+	return
+}
+
+func (p *AgentClient) sendEmitZipkinBatch(spans []*zipkincore.Span) (err error) {
+	oprot := p.OutputProtocol
+	if oprot == nil {
+		oprot = p.ProtocolFactory.GetProtocol(p.Transport)
+		p.OutputProtocol = oprot
+	}
+	p.SeqId++
+	if err = oprot.WriteMessageBegin("emitZipkinBatch", thrift.ONEWAY, p.SeqId); err != nil {
+		return
+	}
+	args := AgentEmitZipkinBatchArgs{
+		Spans: spans,
+	}
+	if err = args.Write(oprot); err != nil {
+		return
+	}
+	if err = oprot.WriteMessageEnd(); err != nil {
+		return
+	}
+	return oprot.Flush()
+}
+
+// Parameters:
+//  - Batch
+func (p *AgentClient) EmitBatch(batch *jaeger.Batch) (err error) {
+	if err = p.sendEmitBatch(batch); err != nil {
+		return
+	}
+	return
+}
+
+func (p *AgentClient) sendEmitBatch(batch *jaeger.Batch) (err error) {
+	oprot := p.OutputProtocol
+	if oprot == nil {
+		oprot = p.ProtocolFactory.GetProtocol(p.Transport)
+		p.OutputProtocol = oprot
+	}
+	p.SeqId++
+	if err = oprot.WriteMessageBegin("emitBatch", thrift.ONEWAY, p.SeqId); err != nil {
+		return
+	}
+	args := AgentEmitBatchArgs{
+		Batch: batch,
+	}
+	if err = args.Write(oprot); err != nil {
+		return
+	}
+	if err = oprot.WriteMessageEnd(); err != nil {
+		return
+	}
+	return oprot.Flush()
+}
+
+type AgentProcessor struct {
+	processorMap map[string]thrift.TProcessorFunction
+	handler      Agent
+}
+
+func (p *AgentProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) {
+	p.processorMap[key] = processor
+}
+
+func (p *AgentProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) {
+	processor, ok = p.processorMap[key]
+	return processor, ok
+}
+
+func (p *AgentProcessor) ProcessorMap() map[string]thrift.TProcessorFunction {
+	return p.processorMap
+}
+
+func NewAgentProcessor(handler Agent) *AgentProcessor {
+
+	self0 := &AgentProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)}
+	self0.processorMap["emitZipkinBatch"] = &agentProcessorEmitZipkinBatch{handler: handler}
+	self0.processorMap["emitBatch"] = &agentProcessorEmitBatch{handler: handler}
+	return self0
+}
+
+func (p *AgentProcessor) Process(iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
+	name, _, seqId, err := iprot.ReadMessageBegin()
+	if err != nil {
+		return false, err
+	}
+	if processor, ok := p.GetProcessorFunction(name); ok {
+		return processor.Process(seqId, iprot, oprot)
+	}
+	iprot.Skip(thrift.STRUCT)
+	iprot.ReadMessageEnd()
+	x1 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function "+name)
+	oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId)
+	x1.Write(oprot)
+	oprot.WriteMessageEnd()
+	oprot.Flush()
+	return false, x1
+
+}
+
+type agentProcessorEmitZipkinBatch struct {
+	handler Agent
+}
+
+func (p *agentProcessorEmitZipkinBatch) Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
+	args := AgentEmitZipkinBatchArgs{}
+	if err = args.Read(iprot); err != nil {
+		iprot.ReadMessageEnd()
+		return false, err
+	}
+
+	iprot.ReadMessageEnd()
+	var err2 error
+	if err2 = p.handler.EmitZipkinBatch(args.Spans); err2 != nil {
+		return true, err2
+	}
+	return true, nil
+}
+
+type agentProcessorEmitBatch struct {
+	handler Agent
+}
+
+func (p *agentProcessorEmitBatch) Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
+	args := AgentEmitBatchArgs{}
+	if err = args.Read(iprot); err != nil {
+		iprot.ReadMessageEnd()
+		return false, err
+	}
+
+	iprot.ReadMessageEnd()
+	var err2 error
+	if err2 = p.handler.EmitBatch(args.Batch); err2 != nil {
+		return true, err2
+	}
+	return true, nil
+}
+
+// HELPER FUNCTIONS AND STRUCTURES
+
+// Attributes:
+//  - Spans
+type AgentEmitZipkinBatchArgs struct {
+	Spans []*zipkincore.Span `thrift:"spans,1" json:"spans"`
+}
+
+func NewAgentEmitZipkinBatchArgs() *AgentEmitZipkinBatchArgs {
+	return &AgentEmitZipkinBatchArgs{}
+}
+
+func (p *AgentEmitZipkinBatchArgs) GetSpans() []*zipkincore.Span {
+	return p.Spans
+}
+func (p *AgentEmitZipkinBatchArgs) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+		default:
+			if err := iprot.Skip(fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	return nil
+}
+
+func (p *AgentEmitZipkinBatchArgs) readField1(iprot thrift.TProtocol) error {
+	_, size, err := iprot.ReadListBegin()
+	if err != nil {
+		return thrift.PrependError("error reading list begin: ", err)
+	}
+	tSlice := make([]*zipkincore.Span, 0, size)
+	p.Spans = tSlice
+	for i := 0; i < size; i++ {
+		_elem2 := &zipkincore.Span{}
+		if err := _elem2.Read(iprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem2), err)
+		}
+		p.Spans = append(p.Spans, _elem2)
+	}
+	if err := iprot.ReadListEnd(); err != nil {
+		return thrift.PrependError("error reading list end: ", err)
+	}
+	return nil
+}
+
+func (p *AgentEmitZipkinBatchArgs) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("emitZipkinBatch_args"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := 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 *AgentEmitZipkinBatchArgs) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("spans", thrift.LIST, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:spans: ", p), err)
+	}
+	if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Spans)); err != nil {
+		return thrift.PrependError("error writing list begin: ", err)
+	}
+	for _, v := range p.Spans {
+		if err := v.Write(oprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
+		}
+	}
+	if err := oprot.WriteListEnd(); err != nil {
+		return thrift.PrependError("error writing list end: ", err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:spans: ", p), err)
+	}
+	return err
+}
+
+func (p *AgentEmitZipkinBatchArgs) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("AgentEmitZipkinBatchArgs(%+v)", *p)
+}
+
+// Attributes:
+//  - Batch
+type AgentEmitBatchArgs struct {
+	Batch *jaeger.Batch `thrift:"batch,1" json:"batch"`
+}
+
+func NewAgentEmitBatchArgs() *AgentEmitBatchArgs {
+	return &AgentEmitBatchArgs{}
+}
+
+var AgentEmitBatchArgs_Batch_DEFAULT *jaeger.Batch
+
+func (p *AgentEmitBatchArgs) GetBatch() *jaeger.Batch {
+	if !p.IsSetBatch() {
+		return AgentEmitBatchArgs_Batch_DEFAULT
+	}
+	return p.Batch
+}
+func (p *AgentEmitBatchArgs) IsSetBatch() bool {
+	return p.Batch != nil
+}
+
+func (p *AgentEmitBatchArgs) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+		default:
+			if err := iprot.Skip(fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	return nil
+}
+
+func (p *AgentEmitBatchArgs) readField1(iprot thrift.TProtocol) error {
+	p.Batch = &jaeger.Batch{}
+	if err := p.Batch.Read(iprot); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Batch), err)
+	}
+	return nil
+}
+
+func (p *AgentEmitBatchArgs) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("emitBatch_args"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := 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 *AgentEmitBatchArgs) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("batch", thrift.STRUCT, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:batch: ", p), err)
+	}
+	if err := p.Batch.Write(oprot); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Batch), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:batch: ", p), err)
+	}
+	return err
+}
+
+func (p *AgentEmitBatchArgs) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("AgentEmitBatchArgs(%+v)", *p)
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/agent/constants.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/agent/constants.go
new file mode 100644
index 0000000..aa9857b
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/agent/constants.go
@@ -0,0 +1,23 @@
+// Autogenerated by Thrift Compiler (0.9.3)
+// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+
+package agent
+
+import (
+	"bytes"
+	"fmt"
+	"github.com/uber/jaeger-client-go/thrift"
+	"github.com/uber/jaeger-client-go/thrift-gen/jaeger"
+	"github.com/uber/jaeger-client-go/thrift-gen/zipkincore"
+)
+
+// (needed to ensure safety because of naive import list construction.)
+var _ = thrift.ZERO
+var _ = fmt.Printf
+var _ = bytes.Equal
+
+var _ = jaeger.GoUnusedProtection__
+var _ = zipkincore.GoUnusedProtection__
+
+func init() {
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/agent/ttypes.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/agent/ttypes.go
new file mode 100644
index 0000000..9c28f11
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/agent/ttypes.go
@@ -0,0 +1,21 @@
+// Autogenerated by Thrift Compiler (0.9.3)
+// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+
+package agent
+
+import (
+	"bytes"
+	"fmt"
+	"github.com/uber/jaeger-client-go/thrift"
+	"github.com/uber/jaeger-client-go/thrift-gen/jaeger"
+	"github.com/uber/jaeger-client-go/thrift-gen/zipkincore"
+)
+
+// (needed to ensure safety because of naive import list construction.)
+var _ = thrift.ZERO
+var _ = fmt.Printf
+var _ = bytes.Equal
+
+var _ = jaeger.GoUnusedProtection__
+var _ = zipkincore.GoUnusedProtection__
+var GoUnusedProtection__ int
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/baggage/baggagerestrictionmanager.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/baggage/baggagerestrictionmanager.go
new file mode 100644
index 0000000..1f79c12
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/baggage/baggagerestrictionmanager.go
@@ -0,0 +1,435 @@
+// Autogenerated by Thrift Compiler (0.9.3)
+// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+
+package baggage
+
+import (
+	"bytes"
+	"fmt"
+	"github.com/uber/jaeger-client-go/thrift"
+)
+
+// (needed to ensure safety because of naive import list construction.)
+var _ = thrift.ZERO
+var _ = fmt.Printf
+var _ = bytes.Equal
+
+type BaggageRestrictionManager interface {
+	// getBaggageRestrictions retrieves the baggage restrictions for a specific service.
+	// Usually, baggageRestrictions apply to all services however there may be situations
+	// where a baggageKey might only be allowed to be set by a specific service.
+	//
+	// Parameters:
+	//  - ServiceName
+	GetBaggageRestrictions(serviceName string) (r []*BaggageRestriction, err error)
+}
+
+type BaggageRestrictionManagerClient struct {
+	Transport       thrift.TTransport
+	ProtocolFactory thrift.TProtocolFactory
+	InputProtocol   thrift.TProtocol
+	OutputProtocol  thrift.TProtocol
+	SeqId           int32
+}
+
+func NewBaggageRestrictionManagerClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *BaggageRestrictionManagerClient {
+	return &BaggageRestrictionManagerClient{Transport: t,
+		ProtocolFactory: f,
+		InputProtocol:   f.GetProtocol(t),
+		OutputProtocol:  f.GetProtocol(t),
+		SeqId:           0,
+	}
+}
+
+func NewBaggageRestrictionManagerClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *BaggageRestrictionManagerClient {
+	return &BaggageRestrictionManagerClient{Transport: t,
+		ProtocolFactory: nil,
+		InputProtocol:   iprot,
+		OutputProtocol:  oprot,
+		SeqId:           0,
+	}
+}
+
+// getBaggageRestrictions retrieves the baggage restrictions for a specific service.
+// Usually, baggageRestrictions apply to all services however there may be situations
+// where a baggageKey might only be allowed to be set by a specific service.
+//
+// Parameters:
+//  - ServiceName
+func (p *BaggageRestrictionManagerClient) GetBaggageRestrictions(serviceName string) (r []*BaggageRestriction, err error) {
+	if err = p.sendGetBaggageRestrictions(serviceName); err != nil {
+		return
+	}
+	return p.recvGetBaggageRestrictions()
+}
+
+func (p *BaggageRestrictionManagerClient) sendGetBaggageRestrictions(serviceName string) (err error) {
+	oprot := p.OutputProtocol
+	if oprot == nil {
+		oprot = p.ProtocolFactory.GetProtocol(p.Transport)
+		p.OutputProtocol = oprot
+	}
+	p.SeqId++
+	if err = oprot.WriteMessageBegin("getBaggageRestrictions", thrift.CALL, p.SeqId); err != nil {
+		return
+	}
+	args := BaggageRestrictionManagerGetBaggageRestrictionsArgs{
+		ServiceName: serviceName,
+	}
+	if err = args.Write(oprot); err != nil {
+		return
+	}
+	if err = oprot.WriteMessageEnd(); err != nil {
+		return
+	}
+	return oprot.Flush()
+}
+
+func (p *BaggageRestrictionManagerClient) recvGetBaggageRestrictions() (value []*BaggageRestriction, err error) {
+	iprot := p.InputProtocol
+	if iprot == nil {
+		iprot = p.ProtocolFactory.GetProtocol(p.Transport)
+		p.InputProtocol = iprot
+	}
+	method, mTypeId, seqId, err := iprot.ReadMessageBegin()
+	if err != nil {
+		return
+	}
+	if method != "getBaggageRestrictions" {
+		err = thrift.NewTApplicationException(thrift.WRONG_METHOD_NAME, "getBaggageRestrictions failed: wrong method name")
+		return
+	}
+	if p.SeqId != seqId {
+		err = thrift.NewTApplicationException(thrift.BAD_SEQUENCE_ID, "getBaggageRestrictions failed: out of sequence response")
+		return
+	}
+	if mTypeId == thrift.EXCEPTION {
+		error0 := thrift.NewTApplicationException(thrift.UNKNOWN_APPLICATION_EXCEPTION, "Unknown Exception")
+		var error1 error
+		error1, err = error0.Read(iprot)
+		if err != nil {
+			return
+		}
+		if err = iprot.ReadMessageEnd(); err != nil {
+			return
+		}
+		err = error1
+		return
+	}
+	if mTypeId != thrift.REPLY {
+		err = thrift.NewTApplicationException(thrift.INVALID_MESSAGE_TYPE_EXCEPTION, "getBaggageRestrictions failed: invalid message type")
+		return
+	}
+	result := BaggageRestrictionManagerGetBaggageRestrictionsResult{}
+	if err = result.Read(iprot); err != nil {
+		return
+	}
+	if err = iprot.ReadMessageEnd(); err != nil {
+		return
+	}
+	value = result.GetSuccess()
+	return
+}
+
+type BaggageRestrictionManagerProcessor struct {
+	processorMap map[string]thrift.TProcessorFunction
+	handler      BaggageRestrictionManager
+}
+
+func (p *BaggageRestrictionManagerProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) {
+	p.processorMap[key] = processor
+}
+
+func (p *BaggageRestrictionManagerProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) {
+	processor, ok = p.processorMap[key]
+	return processor, ok
+}
+
+func (p *BaggageRestrictionManagerProcessor) ProcessorMap() map[string]thrift.TProcessorFunction {
+	return p.processorMap
+}
+
+func NewBaggageRestrictionManagerProcessor(handler BaggageRestrictionManager) *BaggageRestrictionManagerProcessor {
+
+	self2 := &BaggageRestrictionManagerProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)}
+	self2.processorMap["getBaggageRestrictions"] = &baggageRestrictionManagerProcessorGetBaggageRestrictions{handler: handler}
+	return self2
+}
+
+func (p *BaggageRestrictionManagerProcessor) Process(iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
+	name, _, seqId, err := iprot.ReadMessageBegin()
+	if err != nil {
+		return false, err
+	}
+	if processor, ok := p.GetProcessorFunction(name); ok {
+		return processor.Process(seqId, iprot, oprot)
+	}
+	iprot.Skip(thrift.STRUCT)
+	iprot.ReadMessageEnd()
+	x3 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function "+name)
+	oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId)
+	x3.Write(oprot)
+	oprot.WriteMessageEnd()
+	oprot.Flush()
+	return false, x3
+
+}
+
+type baggageRestrictionManagerProcessorGetBaggageRestrictions struct {
+	handler BaggageRestrictionManager
+}
+
+func (p *baggageRestrictionManagerProcessorGetBaggageRestrictions) Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
+	args := BaggageRestrictionManagerGetBaggageRestrictionsArgs{}
+	if err = args.Read(iprot); err != nil {
+		iprot.ReadMessageEnd()
+		x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error())
+		oprot.WriteMessageBegin("getBaggageRestrictions", thrift.EXCEPTION, seqId)
+		x.Write(oprot)
+		oprot.WriteMessageEnd()
+		oprot.Flush()
+		return false, err
+	}
+
+	iprot.ReadMessageEnd()
+	result := BaggageRestrictionManagerGetBaggageRestrictionsResult{}
+	var retval []*BaggageRestriction
+	var err2 error
+	if retval, err2 = p.handler.GetBaggageRestrictions(args.ServiceName); err2 != nil {
+		x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing getBaggageRestrictions: "+err2.Error())
+		oprot.WriteMessageBegin("getBaggageRestrictions", thrift.EXCEPTION, seqId)
+		x.Write(oprot)
+		oprot.WriteMessageEnd()
+		oprot.Flush()
+		return true, err2
+	} else {
+		result.Success = retval
+	}
+	if err2 = oprot.WriteMessageBegin("getBaggageRestrictions", thrift.REPLY, seqId); err2 != nil {
+		err = err2
+	}
+	if err2 = result.Write(oprot); err == nil && err2 != nil {
+		err = err2
+	}
+	if err2 = oprot.WriteMessageEnd(); err == nil && err2 != nil {
+		err = err2
+	}
+	if err2 = oprot.Flush(); err == nil && err2 != nil {
+		err = err2
+	}
+	if err != nil {
+		return
+	}
+	return true, err
+}
+
+// HELPER FUNCTIONS AND STRUCTURES
+
+// Attributes:
+//  - ServiceName
+type BaggageRestrictionManagerGetBaggageRestrictionsArgs struct {
+	ServiceName string `thrift:"serviceName,1" json:"serviceName"`
+}
+
+func NewBaggageRestrictionManagerGetBaggageRestrictionsArgs() *BaggageRestrictionManagerGetBaggageRestrictionsArgs {
+	return &BaggageRestrictionManagerGetBaggageRestrictionsArgs{}
+}
+
+func (p *BaggageRestrictionManagerGetBaggageRestrictionsArgs) GetServiceName() string {
+	return p.ServiceName
+}
+func (p *BaggageRestrictionManagerGetBaggageRestrictionsArgs) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+		default:
+			if err := iprot.Skip(fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	return nil
+}
+
+func (p *BaggageRestrictionManagerGetBaggageRestrictionsArgs) readField1(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadString(); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		p.ServiceName = v
+	}
+	return nil
+}
+
+func (p *BaggageRestrictionManagerGetBaggageRestrictionsArgs) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("getBaggageRestrictions_args"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := 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 *BaggageRestrictionManagerGetBaggageRestrictionsArgs) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("serviceName", thrift.STRING, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:serviceName: ", p), err)
+	}
+	if err := oprot.WriteString(string(p.ServiceName)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.serviceName (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:serviceName: ", p), err)
+	}
+	return err
+}
+
+func (p *BaggageRestrictionManagerGetBaggageRestrictionsArgs) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("BaggageRestrictionManagerGetBaggageRestrictionsArgs(%+v)", *p)
+}
+
+// Attributes:
+//  - Success
+type BaggageRestrictionManagerGetBaggageRestrictionsResult struct {
+	Success []*BaggageRestriction `thrift:"success,0" json:"success,omitempty"`
+}
+
+func NewBaggageRestrictionManagerGetBaggageRestrictionsResult() *BaggageRestrictionManagerGetBaggageRestrictionsResult {
+	return &BaggageRestrictionManagerGetBaggageRestrictionsResult{}
+}
+
+var BaggageRestrictionManagerGetBaggageRestrictionsResult_Success_DEFAULT []*BaggageRestriction
+
+func (p *BaggageRestrictionManagerGetBaggageRestrictionsResult) GetSuccess() []*BaggageRestriction {
+	return p.Success
+}
+func (p *BaggageRestrictionManagerGetBaggageRestrictionsResult) IsSetSuccess() bool {
+	return p.Success != nil
+}
+
+func (p *BaggageRestrictionManagerGetBaggageRestrictionsResult) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 0:
+			if err := p.readField0(iprot); err != nil {
+				return err
+			}
+		default:
+			if err := iprot.Skip(fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	return nil
+}
+
+func (p *BaggageRestrictionManagerGetBaggageRestrictionsResult) readField0(iprot thrift.TProtocol) error {
+	_, size, err := iprot.ReadListBegin()
+	if err != nil {
+		return thrift.PrependError("error reading list begin: ", err)
+	}
+	tSlice := make([]*BaggageRestriction, 0, size)
+	p.Success = tSlice
+	for i := 0; i < size; i++ {
+		_elem4 := &BaggageRestriction{}
+		if err := _elem4.Read(iprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem4), err)
+		}
+		p.Success = append(p.Success, _elem4)
+	}
+	if err := iprot.ReadListEnd(); err != nil {
+		return thrift.PrependError("error reading list end: ", err)
+	}
+	return nil
+}
+
+func (p *BaggageRestrictionManagerGetBaggageRestrictionsResult) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("getBaggageRestrictions_result"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField0(oprot); err != nil {
+		return err
+	}
+	if err := oprot.WriteFieldStop(); err != nil {
+		return thrift.PrependError("write field stop error: ", err)
+	}
+	if err := oprot.WriteStructEnd(); err != nil {
+		return thrift.PrependError("write struct stop error: ", err)
+	}
+	return nil
+}
+
+func (p *BaggageRestrictionManagerGetBaggageRestrictionsResult) writeField0(oprot thrift.TProtocol) (err error) {
+	if p.IsSetSuccess() {
+		if err := oprot.WriteFieldBegin("success", thrift.LIST, 0); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 0:success: ", p), err)
+		}
+		if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Success)); err != nil {
+			return thrift.PrependError("error writing list begin: ", err)
+		}
+		for _, v := range p.Success {
+			if err := v.Write(oprot); err != nil {
+				return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
+			}
+		}
+		if err := oprot.WriteListEnd(); err != nil {
+			return thrift.PrependError("error writing list end: ", err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 0:success: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *BaggageRestrictionManagerGetBaggageRestrictionsResult) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("BaggageRestrictionManagerGetBaggageRestrictionsResult(%+v)", *p)
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/baggage/constants.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/baggage/constants.go
new file mode 100644
index 0000000..ed35ce9
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/baggage/constants.go
@@ -0,0 +1,18 @@
+// Autogenerated by Thrift Compiler (0.9.3)
+// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+
+package baggage
+
+import (
+	"bytes"
+	"fmt"
+	"github.com/uber/jaeger-client-go/thrift"
+)
+
+// (needed to ensure safety because of naive import list construction.)
+var _ = thrift.ZERO
+var _ = fmt.Printf
+var _ = bytes.Equal
+
+func init() {
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/baggage/ttypes.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/baggage/ttypes.go
new file mode 100644
index 0000000..7888892
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/baggage/ttypes.go
@@ -0,0 +1,154 @@
+// Autogenerated by Thrift Compiler (0.9.3)
+// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+
+package baggage
+
+import (
+	"bytes"
+	"fmt"
+	"github.com/uber/jaeger-client-go/thrift"
+)
+
+// (needed to ensure safety because of naive import list construction.)
+var _ = thrift.ZERO
+var _ = fmt.Printf
+var _ = bytes.Equal
+
+var GoUnusedProtection__ int
+
+// Attributes:
+//  - BaggageKey
+//  - MaxValueLength
+type BaggageRestriction struct {
+	BaggageKey     string `thrift:"baggageKey,1,required" json:"baggageKey"`
+	MaxValueLength int32  `thrift:"maxValueLength,2,required" json:"maxValueLength"`
+}
+
+func NewBaggageRestriction() *BaggageRestriction {
+	return &BaggageRestriction{}
+}
+
+func (p *BaggageRestriction) GetBaggageKey() string {
+	return p.BaggageKey
+}
+
+func (p *BaggageRestriction) GetMaxValueLength() int32 {
+	return p.MaxValueLength
+}
+func (p *BaggageRestriction) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	var issetBaggageKey bool = false
+	var issetMaxValueLength bool = false
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+			issetBaggageKey = true
+		case 2:
+			if err := p.readField2(iprot); err != nil {
+				return err
+			}
+			issetMaxValueLength = true
+		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)
+	}
+	if !issetBaggageKey {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field BaggageKey is not set"))
+	}
+	if !issetMaxValueLength {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field MaxValueLength is not set"))
+	}
+	return nil
+}
+
+func (p *BaggageRestriction) readField1(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadString(); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		p.BaggageKey = v
+	}
+	return nil
+}
+
+func (p *BaggageRestriction) readField2(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI32(); err != nil {
+		return thrift.PrependError("error reading field 2: ", err)
+	} else {
+		p.MaxValueLength = v
+	}
+	return nil
+}
+
+func (p *BaggageRestriction) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("BaggageRestriction"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField2(oprot); err != nil {
+		return err
+	}
+	if err := oprot.WriteFieldStop(); err != nil {
+		return thrift.PrependError("write field stop error: ", err)
+	}
+	if err := oprot.WriteStructEnd(); err != nil {
+		return thrift.PrependError("write struct stop error: ", err)
+	}
+	return nil
+}
+
+func (p *BaggageRestriction) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("baggageKey", thrift.STRING, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:baggageKey: ", p), err)
+	}
+	if err := oprot.WriteString(string(p.BaggageKey)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.baggageKey (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:baggageKey: ", p), err)
+	}
+	return err
+}
+
+func (p *BaggageRestriction) writeField2(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("maxValueLength", thrift.I32, 2); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:maxValueLength: ", p), err)
+	}
+	if err := oprot.WriteI32(int32(p.MaxValueLength)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.maxValueLength (2) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 2:maxValueLength: ", p), err)
+	}
+	return err
+}
+
+func (p *BaggageRestriction) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("BaggageRestriction(%+v)", *p)
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/jaeger/agent.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/jaeger/agent.go
new file mode 100644
index 0000000..b32c37d
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/jaeger/agent.go
@@ -0,0 +1,242 @@
+// Autogenerated by Thrift Compiler (0.9.3)
+// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+
+package jaeger
+
+import (
+	"bytes"
+	"fmt"
+	"github.com/uber/jaeger-client-go/thrift"
+)
+
+// (needed to ensure safety because of naive import list construction.)
+var _ = thrift.ZERO
+var _ = fmt.Printf
+var _ = bytes.Equal
+
+type Agent interface {
+	// Parameters:
+	//  - Batch
+	EmitBatch(batch *Batch) (err error)
+}
+
+type AgentClient struct {
+	Transport       thrift.TTransport
+	ProtocolFactory thrift.TProtocolFactory
+	InputProtocol   thrift.TProtocol
+	OutputProtocol  thrift.TProtocol
+	SeqId           int32
+}
+
+func NewAgentClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *AgentClient {
+	return &AgentClient{Transport: t,
+		ProtocolFactory: f,
+		InputProtocol:   f.GetProtocol(t),
+		OutputProtocol:  f.GetProtocol(t),
+		SeqId:           0,
+	}
+}
+
+func NewAgentClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *AgentClient {
+	return &AgentClient{Transport: t,
+		ProtocolFactory: nil,
+		InputProtocol:   iprot,
+		OutputProtocol:  oprot,
+		SeqId:           0,
+	}
+}
+
+// Parameters:
+//  - Batch
+func (p *AgentClient) EmitBatch(batch *Batch) (err error) {
+	if err = p.sendEmitBatch(batch); err != nil {
+		return
+	}
+	return
+}
+
+func (p *AgentClient) sendEmitBatch(batch *Batch) (err error) {
+	oprot := p.OutputProtocol
+	if oprot == nil {
+		oprot = p.ProtocolFactory.GetProtocol(p.Transport)
+		p.OutputProtocol = oprot
+	}
+	p.SeqId++
+	if err = oprot.WriteMessageBegin("emitBatch", thrift.ONEWAY, p.SeqId); err != nil {
+		return
+	}
+	args := AgentEmitBatchArgs{
+		Batch: batch,
+	}
+	if err = args.Write(oprot); err != nil {
+		return
+	}
+	if err = oprot.WriteMessageEnd(); err != nil {
+		return
+	}
+	return oprot.Flush()
+}
+
+type AgentProcessor struct {
+	processorMap map[string]thrift.TProcessorFunction
+	handler      Agent
+}
+
+func (p *AgentProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) {
+	p.processorMap[key] = processor
+}
+
+func (p *AgentProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) {
+	processor, ok = p.processorMap[key]
+	return processor, ok
+}
+
+func (p *AgentProcessor) ProcessorMap() map[string]thrift.TProcessorFunction {
+	return p.processorMap
+}
+
+func NewAgentProcessor(handler Agent) *AgentProcessor {
+
+	self6 := &AgentProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)}
+	self6.processorMap["emitBatch"] = &agentProcessorEmitBatch{handler: handler}
+	return self6
+}
+
+func (p *AgentProcessor) Process(iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
+	name, _, seqId, err := iprot.ReadMessageBegin()
+	if err != nil {
+		return false, err
+	}
+	if processor, ok := p.GetProcessorFunction(name); ok {
+		return processor.Process(seqId, iprot, oprot)
+	}
+	iprot.Skip(thrift.STRUCT)
+	iprot.ReadMessageEnd()
+	x7 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function "+name)
+	oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId)
+	x7.Write(oprot)
+	oprot.WriteMessageEnd()
+	oprot.Flush()
+	return false, x7
+
+}
+
+type agentProcessorEmitBatch struct {
+	handler Agent
+}
+
+func (p *agentProcessorEmitBatch) Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
+	args := AgentEmitBatchArgs{}
+	if err = args.Read(iprot); err != nil {
+		iprot.ReadMessageEnd()
+		return false, err
+	}
+
+	iprot.ReadMessageEnd()
+	var err2 error
+	if err2 = p.handler.EmitBatch(args.Batch); err2 != nil {
+		return true, err2
+	}
+	return true, nil
+}
+
+// HELPER FUNCTIONS AND STRUCTURES
+
+// Attributes:
+//  - Batch
+type AgentEmitBatchArgs struct {
+	Batch *Batch `thrift:"batch,1" json:"batch"`
+}
+
+func NewAgentEmitBatchArgs() *AgentEmitBatchArgs {
+	return &AgentEmitBatchArgs{}
+}
+
+var AgentEmitBatchArgs_Batch_DEFAULT *Batch
+
+func (p *AgentEmitBatchArgs) GetBatch() *Batch {
+	if !p.IsSetBatch() {
+		return AgentEmitBatchArgs_Batch_DEFAULT
+	}
+	return p.Batch
+}
+func (p *AgentEmitBatchArgs) IsSetBatch() bool {
+	return p.Batch != nil
+}
+
+func (p *AgentEmitBatchArgs) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+		default:
+			if err := iprot.Skip(fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	return nil
+}
+
+func (p *AgentEmitBatchArgs) readField1(iprot thrift.TProtocol) error {
+	p.Batch = &Batch{}
+	if err := p.Batch.Read(iprot); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Batch), err)
+	}
+	return nil
+}
+
+func (p *AgentEmitBatchArgs) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("emitBatch_args"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := 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 *AgentEmitBatchArgs) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("batch", thrift.STRUCT, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:batch: ", p), err)
+	}
+	if err := p.Batch.Write(oprot); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Batch), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:batch: ", p), err)
+	}
+	return err
+}
+
+func (p *AgentEmitBatchArgs) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("AgentEmitBatchArgs(%+v)", *p)
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/jaeger/constants.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/jaeger/constants.go
new file mode 100644
index 0000000..621b8b1
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/jaeger/constants.go
@@ -0,0 +1,18 @@
+// Autogenerated by Thrift Compiler (0.9.3)
+// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+
+package jaeger
+
+import (
+	"bytes"
+	"fmt"
+	"github.com/uber/jaeger-client-go/thrift"
+)
+
+// (needed to ensure safety because of naive import list construction.)
+var _ = thrift.ZERO
+var _ = fmt.Printf
+var _ = bytes.Equal
+
+func init() {
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/jaeger/ttypes.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/jaeger/ttypes.go
new file mode 100644
index 0000000..e69c6d6
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/jaeger/ttypes.go
@@ -0,0 +1,2106 @@
+// Autogenerated by Thrift Compiler (0.9.3)
+// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+
+package jaeger
+
+import (
+	"bytes"
+	"fmt"
+	"github.com/uber/jaeger-client-go/thrift"
+)
+
+// (needed to ensure safety because of naive import list construction.)
+var _ = thrift.ZERO
+var _ = fmt.Printf
+var _ = bytes.Equal
+
+var GoUnusedProtection__ int
+
+type TagType int64
+
+const (
+	TagType_STRING TagType = 0
+	TagType_DOUBLE TagType = 1
+	TagType_BOOL   TagType = 2
+	TagType_LONG   TagType = 3
+	TagType_BINARY TagType = 4
+)
+
+func (p TagType) String() string {
+	switch p {
+	case TagType_STRING:
+		return "STRING"
+	case TagType_DOUBLE:
+		return "DOUBLE"
+	case TagType_BOOL:
+		return "BOOL"
+	case TagType_LONG:
+		return "LONG"
+	case TagType_BINARY:
+		return "BINARY"
+	}
+	return "<UNSET>"
+}
+
+func TagTypeFromString(s string) (TagType, error) {
+	switch s {
+	case "STRING":
+		return TagType_STRING, nil
+	case "DOUBLE":
+		return TagType_DOUBLE, nil
+	case "BOOL":
+		return TagType_BOOL, nil
+	case "LONG":
+		return TagType_LONG, nil
+	case "BINARY":
+		return TagType_BINARY, nil
+	}
+	return TagType(0), fmt.Errorf("not a valid TagType string")
+}
+
+func TagTypePtr(v TagType) *TagType { return &v }
+
+func (p TagType) MarshalText() ([]byte, error) {
+	return []byte(p.String()), nil
+}
+
+func (p *TagType) UnmarshalText(text []byte) error {
+	q, err := TagTypeFromString(string(text))
+	if err != nil {
+		return err
+	}
+	*p = q
+	return nil
+}
+
+type SpanRefType int64
+
+const (
+	SpanRefType_CHILD_OF     SpanRefType = 0
+	SpanRefType_FOLLOWS_FROM SpanRefType = 1
+)
+
+func (p SpanRefType) String() string {
+	switch p {
+	case SpanRefType_CHILD_OF:
+		return "CHILD_OF"
+	case SpanRefType_FOLLOWS_FROM:
+		return "FOLLOWS_FROM"
+	}
+	return "<UNSET>"
+}
+
+func SpanRefTypeFromString(s string) (SpanRefType, error) {
+	switch s {
+	case "CHILD_OF":
+		return SpanRefType_CHILD_OF, nil
+	case "FOLLOWS_FROM":
+		return SpanRefType_FOLLOWS_FROM, nil
+	}
+	return SpanRefType(0), fmt.Errorf("not a valid SpanRefType string")
+}
+
+func SpanRefTypePtr(v SpanRefType) *SpanRefType { return &v }
+
+func (p SpanRefType) MarshalText() ([]byte, error) {
+	return []byte(p.String()), nil
+}
+
+func (p *SpanRefType) UnmarshalText(text []byte) error {
+	q, err := SpanRefTypeFromString(string(text))
+	if err != nil {
+		return err
+	}
+	*p = q
+	return nil
+}
+
+// Attributes:
+//  - Key
+//  - VType
+//  - VStr
+//  - VDouble
+//  - VBool
+//  - VLong
+//  - VBinary
+type Tag struct {
+	Key     string   `thrift:"key,1,required" json:"key"`
+	VType   TagType  `thrift:"vType,2,required" json:"vType"`
+	VStr    *string  `thrift:"vStr,3" json:"vStr,omitempty"`
+	VDouble *float64 `thrift:"vDouble,4" json:"vDouble,omitempty"`
+	VBool   *bool    `thrift:"vBool,5" json:"vBool,omitempty"`
+	VLong   *int64   `thrift:"vLong,6" json:"vLong,omitempty"`
+	VBinary []byte   `thrift:"vBinary,7" json:"vBinary,omitempty"`
+}
+
+func NewTag() *Tag {
+	return &Tag{}
+}
+
+func (p *Tag) GetKey() string {
+	return p.Key
+}
+
+func (p *Tag) GetVType() TagType {
+	return p.VType
+}
+
+var Tag_VStr_DEFAULT string
+
+func (p *Tag) GetVStr() string {
+	if !p.IsSetVStr() {
+		return Tag_VStr_DEFAULT
+	}
+	return *p.VStr
+}
+
+var Tag_VDouble_DEFAULT float64
+
+func (p *Tag) GetVDouble() float64 {
+	if !p.IsSetVDouble() {
+		return Tag_VDouble_DEFAULT
+	}
+	return *p.VDouble
+}
+
+var Tag_VBool_DEFAULT bool
+
+func (p *Tag) GetVBool() bool {
+	if !p.IsSetVBool() {
+		return Tag_VBool_DEFAULT
+	}
+	return *p.VBool
+}
+
+var Tag_VLong_DEFAULT int64
+
+func (p *Tag) GetVLong() int64 {
+	if !p.IsSetVLong() {
+		return Tag_VLong_DEFAULT
+	}
+	return *p.VLong
+}
+
+var Tag_VBinary_DEFAULT []byte
+
+func (p *Tag) GetVBinary() []byte {
+	return p.VBinary
+}
+func (p *Tag) IsSetVStr() bool {
+	return p.VStr != nil
+}
+
+func (p *Tag) IsSetVDouble() bool {
+	return p.VDouble != nil
+}
+
+func (p *Tag) IsSetVBool() bool {
+	return p.VBool != nil
+}
+
+func (p *Tag) IsSetVLong() bool {
+	return p.VLong != nil
+}
+
+func (p *Tag) IsSetVBinary() bool {
+	return p.VBinary != nil
+}
+
+func (p *Tag) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	var issetKey bool = false
+	var issetVType bool = false
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+			issetKey = true
+		case 2:
+			if err := p.readField2(iprot); err != nil {
+				return err
+			}
+			issetVType = true
+		case 3:
+			if err := p.readField3(iprot); err != nil {
+				return err
+			}
+		case 4:
+			if err := p.readField4(iprot); err != nil {
+				return err
+			}
+		case 5:
+			if err := p.readField5(iprot); err != nil {
+				return err
+			}
+		case 6:
+			if err := p.readField6(iprot); err != nil {
+				return err
+			}
+		case 7:
+			if err := p.readField7(iprot); err != nil {
+				return err
+			}
+		default:
+			if err := iprot.Skip(fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	if !issetKey {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Key is not set"))
+	}
+	if !issetVType {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field VType is not set"))
+	}
+	return nil
+}
+
+func (p *Tag) readField1(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadString(); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		p.Key = v
+	}
+	return nil
+}
+
+func (p *Tag) readField2(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI32(); err != nil {
+		return thrift.PrependError("error reading field 2: ", err)
+	} else {
+		temp := TagType(v)
+		p.VType = temp
+	}
+	return nil
+}
+
+func (p *Tag) readField3(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadString(); err != nil {
+		return thrift.PrependError("error reading field 3: ", err)
+	} else {
+		p.VStr = &v
+	}
+	return nil
+}
+
+func (p *Tag) readField4(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadDouble(); err != nil {
+		return thrift.PrependError("error reading field 4: ", err)
+	} else {
+		p.VDouble = &v
+	}
+	return nil
+}
+
+func (p *Tag) readField5(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadBool(); err != nil {
+		return thrift.PrependError("error reading field 5: ", err)
+	} else {
+		p.VBool = &v
+	}
+	return nil
+}
+
+func (p *Tag) readField6(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(); err != nil {
+		return thrift.PrependError("error reading field 6: ", err)
+	} else {
+		p.VLong = &v
+	}
+	return nil
+}
+
+func (p *Tag) readField7(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadBinary(); err != nil {
+		return thrift.PrependError("error reading field 7: ", err)
+	} else {
+		p.VBinary = v
+	}
+	return nil
+}
+
+func (p *Tag) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("Tag"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField2(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField3(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField4(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField5(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField6(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField7(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 *Tag) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("key", thrift.STRING, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:key: ", p), err)
+	}
+	if err := oprot.WriteString(string(p.Key)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.key (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:key: ", p), err)
+	}
+	return err
+}
+
+func (p *Tag) writeField2(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("vType", thrift.I32, 2); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:vType: ", p), err)
+	}
+	if err := oprot.WriteI32(int32(p.VType)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.vType (2) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 2:vType: ", p), err)
+	}
+	return err
+}
+
+func (p *Tag) writeField3(oprot thrift.TProtocol) (err error) {
+	if p.IsSetVStr() {
+		if err := oprot.WriteFieldBegin("vStr", thrift.STRING, 3); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 3:vStr: ", p), err)
+		}
+		if err := oprot.WriteString(string(*p.VStr)); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T.vStr (3) field write error: ", p), err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 3:vStr: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *Tag) writeField4(oprot thrift.TProtocol) (err error) {
+	if p.IsSetVDouble() {
+		if err := oprot.WriteFieldBegin("vDouble", thrift.DOUBLE, 4); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 4:vDouble: ", p), err)
+		}
+		if err := oprot.WriteDouble(float64(*p.VDouble)); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T.vDouble (4) field write error: ", p), err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 4:vDouble: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *Tag) writeField5(oprot thrift.TProtocol) (err error) {
+	if p.IsSetVBool() {
+		if err := oprot.WriteFieldBegin("vBool", thrift.BOOL, 5); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 5:vBool: ", p), err)
+		}
+		if err := oprot.WriteBool(bool(*p.VBool)); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T.vBool (5) field write error: ", p), err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 5:vBool: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *Tag) writeField6(oprot thrift.TProtocol) (err error) {
+	if p.IsSetVLong() {
+		if err := oprot.WriteFieldBegin("vLong", thrift.I64, 6); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 6:vLong: ", p), err)
+		}
+		if err := oprot.WriteI64(int64(*p.VLong)); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T.vLong (6) field write error: ", p), err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 6:vLong: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *Tag) writeField7(oprot thrift.TProtocol) (err error) {
+	if p.IsSetVBinary() {
+		if err := oprot.WriteFieldBegin("vBinary", thrift.STRING, 7); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 7:vBinary: ", p), err)
+		}
+		if err := oprot.WriteBinary(p.VBinary); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T.vBinary (7) field write error: ", p), err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 7:vBinary: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *Tag) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("Tag(%+v)", *p)
+}
+
+// Attributes:
+//  - Timestamp
+//  - Fields
+type Log struct {
+	Timestamp int64  `thrift:"timestamp,1,required" json:"timestamp"`
+	Fields    []*Tag `thrift:"fields,2,required" json:"fields"`
+}
+
+func NewLog() *Log {
+	return &Log{}
+}
+
+func (p *Log) GetTimestamp() int64 {
+	return p.Timestamp
+}
+
+func (p *Log) GetFields() []*Tag {
+	return p.Fields
+}
+func (p *Log) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	var issetTimestamp bool = false
+	var issetFields bool = false
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+			issetTimestamp = true
+		case 2:
+			if err := p.readField2(iprot); err != nil {
+				return err
+			}
+			issetFields = true
+		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)
+	}
+	if !issetTimestamp {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Timestamp is not set"))
+	}
+	if !issetFields {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Fields is not set"))
+	}
+	return nil
+}
+
+func (p *Log) readField1(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		p.Timestamp = v
+	}
+	return nil
+}
+
+func (p *Log) readField2(iprot thrift.TProtocol) error {
+	_, size, err := iprot.ReadListBegin()
+	if err != nil {
+		return thrift.PrependError("error reading list begin: ", err)
+	}
+	tSlice := make([]*Tag, 0, size)
+	p.Fields = tSlice
+	for i := 0; i < size; i++ {
+		_elem0 := &Tag{}
+		if err := _elem0.Read(iprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem0), err)
+		}
+		p.Fields = append(p.Fields, _elem0)
+	}
+	if err := iprot.ReadListEnd(); err != nil {
+		return thrift.PrependError("error reading list end: ", err)
+	}
+	return nil
+}
+
+func (p *Log) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("Log"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField2(oprot); err != nil {
+		return err
+	}
+	if err := oprot.WriteFieldStop(); err != nil {
+		return thrift.PrependError("write field stop error: ", err)
+	}
+	if err := oprot.WriteStructEnd(); err != nil {
+		return thrift.PrependError("write struct stop error: ", err)
+	}
+	return nil
+}
+
+func (p *Log) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("timestamp", thrift.I64, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:timestamp: ", p), err)
+	}
+	if err := oprot.WriteI64(int64(p.Timestamp)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.timestamp (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:timestamp: ", p), err)
+	}
+	return err
+}
+
+func (p *Log) writeField2(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("fields", thrift.LIST, 2); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:fields: ", p), err)
+	}
+	if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Fields)); err != nil {
+		return thrift.PrependError("error writing list begin: ", err)
+	}
+	for _, v := range p.Fields {
+		if err := v.Write(oprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
+		}
+	}
+	if err := oprot.WriteListEnd(); err != nil {
+		return thrift.PrependError("error writing list end: ", err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 2:fields: ", p), err)
+	}
+	return err
+}
+
+func (p *Log) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("Log(%+v)", *p)
+}
+
+// Attributes:
+//  - RefType
+//  - TraceIdLow
+//  - TraceIdHigh
+//  - SpanId
+type SpanRef struct {
+	RefType     SpanRefType `thrift:"refType,1,required" json:"refType"`
+	TraceIdLow  int64       `thrift:"traceIdLow,2,required" json:"traceIdLow"`
+	TraceIdHigh int64       `thrift:"traceIdHigh,3,required" json:"traceIdHigh"`
+	SpanId      int64       `thrift:"spanId,4,required" json:"spanId"`
+}
+
+func NewSpanRef() *SpanRef {
+	return &SpanRef{}
+}
+
+func (p *SpanRef) GetRefType() SpanRefType {
+	return p.RefType
+}
+
+func (p *SpanRef) GetTraceIdLow() int64 {
+	return p.TraceIdLow
+}
+
+func (p *SpanRef) GetTraceIdHigh() int64 {
+	return p.TraceIdHigh
+}
+
+func (p *SpanRef) GetSpanId() int64 {
+	return p.SpanId
+}
+func (p *SpanRef) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	var issetRefType bool = false
+	var issetTraceIdLow bool = false
+	var issetTraceIdHigh bool = false
+	var issetSpanId bool = false
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+			issetRefType = true
+		case 2:
+			if err := p.readField2(iprot); err != nil {
+				return err
+			}
+			issetTraceIdLow = true
+		case 3:
+			if err := p.readField3(iprot); err != nil {
+				return err
+			}
+			issetTraceIdHigh = true
+		case 4:
+			if err := p.readField4(iprot); err != nil {
+				return err
+			}
+			issetSpanId = true
+		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)
+	}
+	if !issetRefType {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field RefType is not set"))
+	}
+	if !issetTraceIdLow {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field TraceIdLow is not set"))
+	}
+	if !issetTraceIdHigh {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field TraceIdHigh is not set"))
+	}
+	if !issetSpanId {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field SpanId is not set"))
+	}
+	return nil
+}
+
+func (p *SpanRef) readField1(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI32(); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		temp := SpanRefType(v)
+		p.RefType = temp
+	}
+	return nil
+}
+
+func (p *SpanRef) readField2(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(); err != nil {
+		return thrift.PrependError("error reading field 2: ", err)
+	} else {
+		p.TraceIdLow = v
+	}
+	return nil
+}
+
+func (p *SpanRef) readField3(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(); err != nil {
+		return thrift.PrependError("error reading field 3: ", err)
+	} else {
+		p.TraceIdHigh = v
+	}
+	return nil
+}
+
+func (p *SpanRef) readField4(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(); err != nil {
+		return thrift.PrependError("error reading field 4: ", err)
+	} else {
+		p.SpanId = v
+	}
+	return nil
+}
+
+func (p *SpanRef) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("SpanRef"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField2(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField3(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField4(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 *SpanRef) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("refType", thrift.I32, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:refType: ", p), err)
+	}
+	if err := oprot.WriteI32(int32(p.RefType)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.refType (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:refType: ", p), err)
+	}
+	return err
+}
+
+func (p *SpanRef) writeField2(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("traceIdLow", thrift.I64, 2); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:traceIdLow: ", p), err)
+	}
+	if err := oprot.WriteI64(int64(p.TraceIdLow)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.traceIdLow (2) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 2:traceIdLow: ", p), err)
+	}
+	return err
+}
+
+func (p *SpanRef) writeField3(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("traceIdHigh", thrift.I64, 3); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 3:traceIdHigh: ", p), err)
+	}
+	if err := oprot.WriteI64(int64(p.TraceIdHigh)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.traceIdHigh (3) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 3:traceIdHigh: ", p), err)
+	}
+	return err
+}
+
+func (p *SpanRef) writeField4(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("spanId", thrift.I64, 4); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 4:spanId: ", p), err)
+	}
+	if err := oprot.WriteI64(int64(p.SpanId)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.spanId (4) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 4:spanId: ", p), err)
+	}
+	return err
+}
+
+func (p *SpanRef) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("SpanRef(%+v)", *p)
+}
+
+// Attributes:
+//  - TraceIdLow
+//  - TraceIdHigh
+//  - SpanId
+//  - ParentSpanId
+//  - OperationName
+//  - References
+//  - Flags
+//  - StartTime
+//  - Duration
+//  - Tags
+//  - Logs
+type Span struct {
+	TraceIdLow    int64      `thrift:"traceIdLow,1,required" json:"traceIdLow"`
+	TraceIdHigh   int64      `thrift:"traceIdHigh,2,required" json:"traceIdHigh"`
+	SpanId        int64      `thrift:"spanId,3,required" json:"spanId"`
+	ParentSpanId  int64      `thrift:"parentSpanId,4,required" json:"parentSpanId"`
+	OperationName string     `thrift:"operationName,5,required" json:"operationName"`
+	References    []*SpanRef `thrift:"references,6" json:"references,omitempty"`
+	Flags         int32      `thrift:"flags,7,required" json:"flags"`
+	StartTime     int64      `thrift:"startTime,8,required" json:"startTime"`
+	Duration      int64      `thrift:"duration,9,required" json:"duration"`
+	Tags          []*Tag     `thrift:"tags,10" json:"tags,omitempty"`
+	Logs          []*Log     `thrift:"logs,11" json:"logs,omitempty"`
+}
+
+func NewSpan() *Span {
+	return &Span{}
+}
+
+func (p *Span) GetTraceIdLow() int64 {
+	return p.TraceIdLow
+}
+
+func (p *Span) GetTraceIdHigh() int64 {
+	return p.TraceIdHigh
+}
+
+func (p *Span) GetSpanId() int64 {
+	return p.SpanId
+}
+
+func (p *Span) GetParentSpanId() int64 {
+	return p.ParentSpanId
+}
+
+func (p *Span) GetOperationName() string {
+	return p.OperationName
+}
+
+var Span_References_DEFAULT []*SpanRef
+
+func (p *Span) GetReferences() []*SpanRef {
+	return p.References
+}
+
+func (p *Span) GetFlags() int32 {
+	return p.Flags
+}
+
+func (p *Span) GetStartTime() int64 {
+	return p.StartTime
+}
+
+func (p *Span) GetDuration() int64 {
+	return p.Duration
+}
+
+var Span_Tags_DEFAULT []*Tag
+
+func (p *Span) GetTags() []*Tag {
+	return p.Tags
+}
+
+var Span_Logs_DEFAULT []*Log
+
+func (p *Span) GetLogs() []*Log {
+	return p.Logs
+}
+func (p *Span) IsSetReferences() bool {
+	return p.References != nil
+}
+
+func (p *Span) IsSetTags() bool {
+	return p.Tags != nil
+}
+
+func (p *Span) IsSetLogs() bool {
+	return p.Logs != nil
+}
+
+func (p *Span) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	var issetTraceIdLow bool = false
+	var issetTraceIdHigh bool = false
+	var issetSpanId bool = false
+	var issetParentSpanId bool = false
+	var issetOperationName bool = false
+	var issetFlags bool = false
+	var issetStartTime bool = false
+	var issetDuration bool = false
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+			issetTraceIdLow = true
+		case 2:
+			if err := p.readField2(iprot); err != nil {
+				return err
+			}
+			issetTraceIdHigh = true
+		case 3:
+			if err := p.readField3(iprot); err != nil {
+				return err
+			}
+			issetSpanId = true
+		case 4:
+			if err := p.readField4(iprot); err != nil {
+				return err
+			}
+			issetParentSpanId = true
+		case 5:
+			if err := p.readField5(iprot); err != nil {
+				return err
+			}
+			issetOperationName = true
+		case 6:
+			if err := p.readField6(iprot); err != nil {
+				return err
+			}
+		case 7:
+			if err := p.readField7(iprot); err != nil {
+				return err
+			}
+			issetFlags = true
+		case 8:
+			if err := p.readField8(iprot); err != nil {
+				return err
+			}
+			issetStartTime = true
+		case 9:
+			if err := p.readField9(iprot); err != nil {
+				return err
+			}
+			issetDuration = true
+		case 10:
+			if err := p.readField10(iprot); err != nil {
+				return err
+			}
+		case 11:
+			if err := p.readField11(iprot); err != nil {
+				return err
+			}
+		default:
+			if err := iprot.Skip(fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	if !issetTraceIdLow {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field TraceIdLow is not set"))
+	}
+	if !issetTraceIdHigh {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field TraceIdHigh is not set"))
+	}
+	if !issetSpanId {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field SpanId is not set"))
+	}
+	if !issetParentSpanId {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field ParentSpanId is not set"))
+	}
+	if !issetOperationName {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field OperationName is not set"))
+	}
+	if !issetFlags {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Flags is not set"))
+	}
+	if !issetStartTime {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field StartTime is not set"))
+	}
+	if !issetDuration {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Duration is not set"))
+	}
+	return nil
+}
+
+func (p *Span) readField1(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		p.TraceIdLow = v
+	}
+	return nil
+}
+
+func (p *Span) readField2(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(); err != nil {
+		return thrift.PrependError("error reading field 2: ", err)
+	} else {
+		p.TraceIdHigh = v
+	}
+	return nil
+}
+
+func (p *Span) readField3(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(); err != nil {
+		return thrift.PrependError("error reading field 3: ", err)
+	} else {
+		p.SpanId = v
+	}
+	return nil
+}
+
+func (p *Span) readField4(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(); err != nil {
+		return thrift.PrependError("error reading field 4: ", err)
+	} else {
+		p.ParentSpanId = v
+	}
+	return nil
+}
+
+func (p *Span) readField5(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadString(); err != nil {
+		return thrift.PrependError("error reading field 5: ", err)
+	} else {
+		p.OperationName = v
+	}
+	return nil
+}
+
+func (p *Span) readField6(iprot thrift.TProtocol) error {
+	_, size, err := iprot.ReadListBegin()
+	if err != nil {
+		return thrift.PrependError("error reading list begin: ", err)
+	}
+	tSlice := make([]*SpanRef, 0, size)
+	p.References = tSlice
+	for i := 0; i < size; i++ {
+		_elem1 := &SpanRef{}
+		if err := _elem1.Read(iprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem1), err)
+		}
+		p.References = append(p.References, _elem1)
+	}
+	if err := iprot.ReadListEnd(); err != nil {
+		return thrift.PrependError("error reading list end: ", err)
+	}
+	return nil
+}
+
+func (p *Span) readField7(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI32(); err != nil {
+		return thrift.PrependError("error reading field 7: ", err)
+	} else {
+		p.Flags = v
+	}
+	return nil
+}
+
+func (p *Span) readField8(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(); err != nil {
+		return thrift.PrependError("error reading field 8: ", err)
+	} else {
+		p.StartTime = v
+	}
+	return nil
+}
+
+func (p *Span) readField9(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(); err != nil {
+		return thrift.PrependError("error reading field 9: ", err)
+	} else {
+		p.Duration = v
+	}
+	return nil
+}
+
+func (p *Span) readField10(iprot thrift.TProtocol) error {
+	_, size, err := iprot.ReadListBegin()
+	if err != nil {
+		return thrift.PrependError("error reading list begin: ", err)
+	}
+	tSlice := make([]*Tag, 0, size)
+	p.Tags = tSlice
+	for i := 0; i < size; i++ {
+		_elem2 := &Tag{}
+		if err := _elem2.Read(iprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem2), err)
+		}
+		p.Tags = append(p.Tags, _elem2)
+	}
+	if err := iprot.ReadListEnd(); err != nil {
+		return thrift.PrependError("error reading list end: ", err)
+	}
+	return nil
+}
+
+func (p *Span) readField11(iprot thrift.TProtocol) error {
+	_, size, err := iprot.ReadListBegin()
+	if err != nil {
+		return thrift.PrependError("error reading list begin: ", err)
+	}
+	tSlice := make([]*Log, 0, size)
+	p.Logs = tSlice
+	for i := 0; i < size; i++ {
+		_elem3 := &Log{}
+		if err := _elem3.Read(iprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem3), err)
+		}
+		p.Logs = append(p.Logs, _elem3)
+	}
+	if err := iprot.ReadListEnd(); err != nil {
+		return thrift.PrependError("error reading list end: ", err)
+	}
+	return nil
+}
+
+func (p *Span) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("Span"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField2(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField3(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField4(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField5(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField6(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField7(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField8(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField9(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField10(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField11(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 *Span) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("traceIdLow", thrift.I64, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:traceIdLow: ", p), err)
+	}
+	if err := oprot.WriteI64(int64(p.TraceIdLow)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.traceIdLow (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:traceIdLow: ", p), err)
+	}
+	return err
+}
+
+func (p *Span) writeField2(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("traceIdHigh", thrift.I64, 2); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:traceIdHigh: ", p), err)
+	}
+	if err := oprot.WriteI64(int64(p.TraceIdHigh)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.traceIdHigh (2) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 2:traceIdHigh: ", p), err)
+	}
+	return err
+}
+
+func (p *Span) writeField3(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("spanId", thrift.I64, 3); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 3:spanId: ", p), err)
+	}
+	if err := oprot.WriteI64(int64(p.SpanId)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.spanId (3) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 3:spanId: ", p), err)
+	}
+	return err
+}
+
+func (p *Span) writeField4(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("parentSpanId", thrift.I64, 4); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 4:parentSpanId: ", p), err)
+	}
+	if err := oprot.WriteI64(int64(p.ParentSpanId)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.parentSpanId (4) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 4:parentSpanId: ", p), err)
+	}
+	return err
+}
+
+func (p *Span) writeField5(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("operationName", thrift.STRING, 5); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 5:operationName: ", p), err)
+	}
+	if err := oprot.WriteString(string(p.OperationName)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.operationName (5) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 5:operationName: ", p), err)
+	}
+	return err
+}
+
+func (p *Span) writeField6(oprot thrift.TProtocol) (err error) {
+	if p.IsSetReferences() {
+		if err := oprot.WriteFieldBegin("references", thrift.LIST, 6); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 6:references: ", p), err)
+		}
+		if err := oprot.WriteListBegin(thrift.STRUCT, len(p.References)); err != nil {
+			return thrift.PrependError("error writing list begin: ", err)
+		}
+		for _, v := range p.References {
+			if err := v.Write(oprot); err != nil {
+				return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
+			}
+		}
+		if err := oprot.WriteListEnd(); err != nil {
+			return thrift.PrependError("error writing list end: ", err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 6:references: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *Span) writeField7(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("flags", thrift.I32, 7); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 7:flags: ", p), err)
+	}
+	if err := oprot.WriteI32(int32(p.Flags)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.flags (7) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 7:flags: ", p), err)
+	}
+	return err
+}
+
+func (p *Span) writeField8(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("startTime", thrift.I64, 8); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 8:startTime: ", p), err)
+	}
+	if err := oprot.WriteI64(int64(p.StartTime)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.startTime (8) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 8:startTime: ", p), err)
+	}
+	return err
+}
+
+func (p *Span) writeField9(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("duration", thrift.I64, 9); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 9:duration: ", p), err)
+	}
+	if err := oprot.WriteI64(int64(p.Duration)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.duration (9) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 9:duration: ", p), err)
+	}
+	return err
+}
+
+func (p *Span) writeField10(oprot thrift.TProtocol) (err error) {
+	if p.IsSetTags() {
+		if err := oprot.WriteFieldBegin("tags", thrift.LIST, 10); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 10:tags: ", p), err)
+		}
+		if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Tags)); err != nil {
+			return thrift.PrependError("error writing list begin: ", err)
+		}
+		for _, v := range p.Tags {
+			if err := v.Write(oprot); err != nil {
+				return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
+			}
+		}
+		if err := oprot.WriteListEnd(); err != nil {
+			return thrift.PrependError("error writing list end: ", err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 10:tags: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *Span) writeField11(oprot thrift.TProtocol) (err error) {
+	if p.IsSetLogs() {
+		if err := oprot.WriteFieldBegin("logs", thrift.LIST, 11); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 11:logs: ", p), err)
+		}
+		if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Logs)); err != nil {
+			return thrift.PrependError("error writing list begin: ", err)
+		}
+		for _, v := range p.Logs {
+			if err := v.Write(oprot); err != nil {
+				return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
+			}
+		}
+		if err := oprot.WriteListEnd(); err != nil {
+			return thrift.PrependError("error writing list end: ", err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 11:logs: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *Span) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("Span(%+v)", *p)
+}
+
+// Attributes:
+//  - ServiceName
+//  - Tags
+type Process struct {
+	ServiceName string `thrift:"serviceName,1,required" json:"serviceName"`
+	Tags        []*Tag `thrift:"tags,2" json:"tags,omitempty"`
+}
+
+func NewProcess() *Process {
+	return &Process{}
+}
+
+func (p *Process) GetServiceName() string {
+	return p.ServiceName
+}
+
+var Process_Tags_DEFAULT []*Tag
+
+func (p *Process) GetTags() []*Tag {
+	return p.Tags
+}
+func (p *Process) IsSetTags() bool {
+	return p.Tags != nil
+}
+
+func (p *Process) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	var issetServiceName bool = false
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+			issetServiceName = true
+		case 2:
+			if err := p.readField2(iprot); err != nil {
+				return err
+			}
+		default:
+			if err := iprot.Skip(fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	if !issetServiceName {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field ServiceName is not set"))
+	}
+	return nil
+}
+
+func (p *Process) readField1(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadString(); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		p.ServiceName = v
+	}
+	return nil
+}
+
+func (p *Process) readField2(iprot thrift.TProtocol) error {
+	_, size, err := iprot.ReadListBegin()
+	if err != nil {
+		return thrift.PrependError("error reading list begin: ", err)
+	}
+	tSlice := make([]*Tag, 0, size)
+	p.Tags = tSlice
+	for i := 0; i < size; i++ {
+		_elem4 := &Tag{}
+		if err := _elem4.Read(iprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem4), err)
+		}
+		p.Tags = append(p.Tags, _elem4)
+	}
+	if err := iprot.ReadListEnd(); err != nil {
+		return thrift.PrependError("error reading list end: ", err)
+	}
+	return nil
+}
+
+func (p *Process) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("Process"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField2(oprot); err != nil {
+		return err
+	}
+	if err := oprot.WriteFieldStop(); err != nil {
+		return thrift.PrependError("write field stop error: ", err)
+	}
+	if err := oprot.WriteStructEnd(); err != nil {
+		return thrift.PrependError("write struct stop error: ", err)
+	}
+	return nil
+}
+
+func (p *Process) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("serviceName", thrift.STRING, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:serviceName: ", p), err)
+	}
+	if err := oprot.WriteString(string(p.ServiceName)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.serviceName (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:serviceName: ", p), err)
+	}
+	return err
+}
+
+func (p *Process) writeField2(oprot thrift.TProtocol) (err error) {
+	if p.IsSetTags() {
+		if err := oprot.WriteFieldBegin("tags", thrift.LIST, 2); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:tags: ", p), err)
+		}
+		if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Tags)); err != nil {
+			return thrift.PrependError("error writing list begin: ", err)
+		}
+		for _, v := range p.Tags {
+			if err := v.Write(oprot); err != nil {
+				return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
+			}
+		}
+		if err := oprot.WriteListEnd(); err != nil {
+			return thrift.PrependError("error writing list end: ", err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 2:tags: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *Process) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("Process(%+v)", *p)
+}
+
+// Attributes:
+//  - FullQueueDroppedSpans
+//  - TooLargeDroppedSpans
+//  - FailedToEmitSpans
+type ClientStats struct {
+	FullQueueDroppedSpans int64 `thrift:"fullQueueDroppedSpans,1,required" json:"fullQueueDroppedSpans"`
+	TooLargeDroppedSpans  int64 `thrift:"tooLargeDroppedSpans,2,required" json:"tooLargeDroppedSpans"`
+	FailedToEmitSpans     int64 `thrift:"failedToEmitSpans,3,required" json:"failedToEmitSpans"`
+}
+
+func NewClientStats() *ClientStats {
+	return &ClientStats{}
+}
+
+func (p *ClientStats) GetFullQueueDroppedSpans() int64 {
+	return p.FullQueueDroppedSpans
+}
+
+func (p *ClientStats) GetTooLargeDroppedSpans() int64 {
+	return p.TooLargeDroppedSpans
+}
+
+func (p *ClientStats) GetFailedToEmitSpans() int64 {
+	return p.FailedToEmitSpans
+}
+func (p *ClientStats) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	var issetFullQueueDroppedSpans bool = false
+	var issetTooLargeDroppedSpans bool = false
+	var issetFailedToEmitSpans bool = false
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+			issetFullQueueDroppedSpans = true
+		case 2:
+			if err := p.readField2(iprot); err != nil {
+				return err
+			}
+			issetTooLargeDroppedSpans = true
+		case 3:
+			if err := p.readField3(iprot); err != nil {
+				return err
+			}
+			issetFailedToEmitSpans = true
+		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)
+	}
+	if !issetFullQueueDroppedSpans {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field FullQueueDroppedSpans is not set"))
+	}
+	if !issetTooLargeDroppedSpans {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field TooLargeDroppedSpans is not set"))
+	}
+	if !issetFailedToEmitSpans {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field FailedToEmitSpans is not set"))
+	}
+	return nil
+}
+
+func (p *ClientStats) readField1(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		p.FullQueueDroppedSpans = v
+	}
+	return nil
+}
+
+func (p *ClientStats) readField2(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(); err != nil {
+		return thrift.PrependError("error reading field 2: ", err)
+	} else {
+		p.TooLargeDroppedSpans = v
+	}
+	return nil
+}
+
+func (p *ClientStats) readField3(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(); err != nil {
+		return thrift.PrependError("error reading field 3: ", err)
+	} else {
+		p.FailedToEmitSpans = v
+	}
+	return nil
+}
+
+func (p *ClientStats) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("ClientStats"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField2(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField3(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 *ClientStats) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("fullQueueDroppedSpans", thrift.I64, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:fullQueueDroppedSpans: ", p), err)
+	}
+	if err := oprot.WriteI64(int64(p.FullQueueDroppedSpans)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.fullQueueDroppedSpans (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:fullQueueDroppedSpans: ", p), err)
+	}
+	return err
+}
+
+func (p *ClientStats) writeField2(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("tooLargeDroppedSpans", thrift.I64, 2); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:tooLargeDroppedSpans: ", p), err)
+	}
+	if err := oprot.WriteI64(int64(p.TooLargeDroppedSpans)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.tooLargeDroppedSpans (2) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 2:tooLargeDroppedSpans: ", p), err)
+	}
+	return err
+}
+
+func (p *ClientStats) writeField3(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("failedToEmitSpans", thrift.I64, 3); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 3:failedToEmitSpans: ", p), err)
+	}
+	if err := oprot.WriteI64(int64(p.FailedToEmitSpans)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.failedToEmitSpans (3) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 3:failedToEmitSpans: ", p), err)
+	}
+	return err
+}
+
+func (p *ClientStats) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("ClientStats(%+v)", *p)
+}
+
+// Attributes:
+//  - Process
+//  - Spans
+//  - SeqNo
+//  - Stats
+type Batch struct {
+	Process *Process     `thrift:"process,1,required" json:"process"`
+	Spans   []*Span      `thrift:"spans,2,required" json:"spans"`
+	SeqNo   *int64       `thrift:"seqNo,3" json:"seqNo,omitempty"`
+	Stats   *ClientStats `thrift:"stats,4" json:"stats,omitempty"`
+}
+
+func NewBatch() *Batch {
+	return &Batch{}
+}
+
+var Batch_Process_DEFAULT *Process
+
+func (p *Batch) GetProcess() *Process {
+	if !p.IsSetProcess() {
+		return Batch_Process_DEFAULT
+	}
+	return p.Process
+}
+
+func (p *Batch) GetSpans() []*Span {
+	return p.Spans
+}
+
+var Batch_SeqNo_DEFAULT int64
+
+func (p *Batch) GetSeqNo() int64 {
+	if !p.IsSetSeqNo() {
+		return Batch_SeqNo_DEFAULT
+	}
+	return *p.SeqNo
+}
+
+var Batch_Stats_DEFAULT *ClientStats
+
+func (p *Batch) GetStats() *ClientStats {
+	if !p.IsSetStats() {
+		return Batch_Stats_DEFAULT
+	}
+	return p.Stats
+}
+func (p *Batch) IsSetProcess() bool {
+	return p.Process != nil
+}
+
+func (p *Batch) IsSetSeqNo() bool {
+	return p.SeqNo != nil
+}
+
+func (p *Batch) IsSetStats() bool {
+	return p.Stats != nil
+}
+
+func (p *Batch) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	var issetProcess bool = false
+	var issetSpans bool = false
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+			issetProcess = true
+		case 2:
+			if err := p.readField2(iprot); err != nil {
+				return err
+			}
+			issetSpans = true
+		case 3:
+			if err := p.readField3(iprot); err != nil {
+				return err
+			}
+		case 4:
+			if err := p.readField4(iprot); err != nil {
+				return err
+			}
+		default:
+			if err := iprot.Skip(fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	if !issetProcess {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Process is not set"))
+	}
+	if !issetSpans {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Spans is not set"))
+	}
+	return nil
+}
+
+func (p *Batch) readField1(iprot thrift.TProtocol) error {
+	p.Process = &Process{}
+	if err := p.Process.Read(iprot); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Process), err)
+	}
+	return nil
+}
+
+func (p *Batch) readField2(iprot thrift.TProtocol) error {
+	_, size, err := iprot.ReadListBegin()
+	if err != nil {
+		return thrift.PrependError("error reading list begin: ", err)
+	}
+	tSlice := make([]*Span, 0, size)
+	p.Spans = tSlice
+	for i := 0; i < size; i++ {
+		_elem5 := &Span{}
+		if err := _elem5.Read(iprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem5), err)
+		}
+		p.Spans = append(p.Spans, _elem5)
+	}
+	if err := iprot.ReadListEnd(); err != nil {
+		return thrift.PrependError("error reading list end: ", err)
+	}
+	return nil
+}
+
+func (p *Batch) readField3(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(); err != nil {
+		return thrift.PrependError("error reading field 3: ", err)
+	} else {
+		p.SeqNo = &v
+	}
+	return nil
+}
+
+func (p *Batch) readField4(iprot thrift.TProtocol) error {
+	p.Stats = &ClientStats{}
+	if err := p.Stats.Read(iprot); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Stats), err)
+	}
+	return nil
+}
+
+func (p *Batch) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("Batch"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField2(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField3(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField4(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 *Batch) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("process", thrift.STRUCT, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:process: ", p), err)
+	}
+	if err := p.Process.Write(oprot); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Process), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:process: ", p), err)
+	}
+	return err
+}
+
+func (p *Batch) writeField2(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("spans", thrift.LIST, 2); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:spans: ", p), err)
+	}
+	if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Spans)); err != nil {
+		return thrift.PrependError("error writing list begin: ", err)
+	}
+	for _, v := range p.Spans {
+		if err := v.Write(oprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
+		}
+	}
+	if err := oprot.WriteListEnd(); err != nil {
+		return thrift.PrependError("error writing list end: ", err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 2:spans: ", p), err)
+	}
+	return err
+}
+
+func (p *Batch) writeField3(oprot thrift.TProtocol) (err error) {
+	if p.IsSetSeqNo() {
+		if err := oprot.WriteFieldBegin("seqNo", thrift.I64, 3); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 3:seqNo: ", p), err)
+		}
+		if err := oprot.WriteI64(int64(*p.SeqNo)); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T.seqNo (3) field write error: ", p), err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 3:seqNo: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *Batch) writeField4(oprot thrift.TProtocol) (err error) {
+	if p.IsSetStats() {
+		if err := oprot.WriteFieldBegin("stats", thrift.STRUCT, 4); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 4:stats: ", p), err)
+		}
+		if err := p.Stats.Write(oprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Stats), err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 4:stats: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *Batch) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("Batch(%+v)", *p)
+}
+
+// Attributes:
+//  - Ok
+type BatchSubmitResponse struct {
+	Ok bool `thrift:"ok,1,required" json:"ok"`
+}
+
+func NewBatchSubmitResponse() *BatchSubmitResponse {
+	return &BatchSubmitResponse{}
+}
+
+func (p *BatchSubmitResponse) GetOk() bool {
+	return p.Ok
+}
+func (p *BatchSubmitResponse) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	var issetOk bool = false
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+			issetOk = true
+		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)
+	}
+	if !issetOk {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Ok is not set"))
+	}
+	return nil
+}
+
+func (p *BatchSubmitResponse) readField1(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadBool(); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		p.Ok = v
+	}
+	return nil
+}
+
+func (p *BatchSubmitResponse) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("BatchSubmitResponse"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := oprot.WriteFieldStop(); err != nil {
+		return thrift.PrependError("write field stop error: ", err)
+	}
+	if err := oprot.WriteStructEnd(); err != nil {
+		return thrift.PrependError("write struct stop error: ", err)
+	}
+	return nil
+}
+
+func (p *BatchSubmitResponse) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("ok", thrift.BOOL, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:ok: ", p), err)
+	}
+	if err := oprot.WriteBool(bool(p.Ok)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.ok (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:ok: ", p), err)
+	}
+	return err
+}
+
+func (p *BatchSubmitResponse) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("BatchSubmitResponse(%+v)", *p)
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/sampling/constants.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/sampling/constants.go
new file mode 100644
index 0000000..0f6e3a8
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/sampling/constants.go
@@ -0,0 +1,18 @@
+// Autogenerated by Thrift Compiler (0.9.3)
+// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+
+package sampling
+
+import (
+	"bytes"
+	"fmt"
+	"github.com/uber/jaeger-client-go/thrift"
+)
+
+// (needed to ensure safety because of naive import list construction.)
+var _ = thrift.ZERO
+var _ = fmt.Printf
+var _ = bytes.Equal
+
+func init() {
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/sampling/samplingmanager.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/sampling/samplingmanager.go
new file mode 100644
index 0000000..33179cf
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/sampling/samplingmanager.go
@@ -0,0 +1,410 @@
+// Autogenerated by Thrift Compiler (0.9.3)
+// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+
+package sampling
+
+import (
+	"bytes"
+	"fmt"
+	"github.com/uber/jaeger-client-go/thrift"
+)
+
+// (needed to ensure safety because of naive import list construction.)
+var _ = thrift.ZERO
+var _ = fmt.Printf
+var _ = bytes.Equal
+
+type SamplingManager interface {
+	// Parameters:
+	//  - ServiceName
+	GetSamplingStrategy(serviceName string) (r *SamplingStrategyResponse, err error)
+}
+
+type SamplingManagerClient struct {
+	Transport       thrift.TTransport
+	ProtocolFactory thrift.TProtocolFactory
+	InputProtocol   thrift.TProtocol
+	OutputProtocol  thrift.TProtocol
+	SeqId           int32
+}
+
+func NewSamplingManagerClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *SamplingManagerClient {
+	return &SamplingManagerClient{Transport: t,
+		ProtocolFactory: f,
+		InputProtocol:   f.GetProtocol(t),
+		OutputProtocol:  f.GetProtocol(t),
+		SeqId:           0,
+	}
+}
+
+func NewSamplingManagerClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *SamplingManagerClient {
+	return &SamplingManagerClient{Transport: t,
+		ProtocolFactory: nil,
+		InputProtocol:   iprot,
+		OutputProtocol:  oprot,
+		SeqId:           0,
+	}
+}
+
+// Parameters:
+//  - ServiceName
+func (p *SamplingManagerClient) GetSamplingStrategy(serviceName string) (r *SamplingStrategyResponse, err error) {
+	if err = p.sendGetSamplingStrategy(serviceName); err != nil {
+		return
+	}
+	return p.recvGetSamplingStrategy()
+}
+
+func (p *SamplingManagerClient) sendGetSamplingStrategy(serviceName string) (err error) {
+	oprot := p.OutputProtocol
+	if oprot == nil {
+		oprot = p.ProtocolFactory.GetProtocol(p.Transport)
+		p.OutputProtocol = oprot
+	}
+	p.SeqId++
+	if err = oprot.WriteMessageBegin("getSamplingStrategy", thrift.CALL, p.SeqId); err != nil {
+		return
+	}
+	args := SamplingManagerGetSamplingStrategyArgs{
+		ServiceName: serviceName,
+	}
+	if err = args.Write(oprot); err != nil {
+		return
+	}
+	if err = oprot.WriteMessageEnd(); err != nil {
+		return
+	}
+	return oprot.Flush()
+}
+
+func (p *SamplingManagerClient) recvGetSamplingStrategy() (value *SamplingStrategyResponse, err error) {
+	iprot := p.InputProtocol
+	if iprot == nil {
+		iprot = p.ProtocolFactory.GetProtocol(p.Transport)
+		p.InputProtocol = iprot
+	}
+	method, mTypeId, seqId, err := iprot.ReadMessageBegin()
+	if err != nil {
+		return
+	}
+	if method != "getSamplingStrategy" {
+		err = thrift.NewTApplicationException(thrift.WRONG_METHOD_NAME, "getSamplingStrategy failed: wrong method name")
+		return
+	}
+	if p.SeqId != seqId {
+		err = thrift.NewTApplicationException(thrift.BAD_SEQUENCE_ID, "getSamplingStrategy failed: out of sequence response")
+		return
+	}
+	if mTypeId == thrift.EXCEPTION {
+		error1 := thrift.NewTApplicationException(thrift.UNKNOWN_APPLICATION_EXCEPTION, "Unknown Exception")
+		var error2 error
+		error2, err = error1.Read(iprot)
+		if err != nil {
+			return
+		}
+		if err = iprot.ReadMessageEnd(); err != nil {
+			return
+		}
+		err = error2
+		return
+	}
+	if mTypeId != thrift.REPLY {
+		err = thrift.NewTApplicationException(thrift.INVALID_MESSAGE_TYPE_EXCEPTION, "getSamplingStrategy failed: invalid message type")
+		return
+	}
+	result := SamplingManagerGetSamplingStrategyResult{}
+	if err = result.Read(iprot); err != nil {
+		return
+	}
+	if err = iprot.ReadMessageEnd(); err != nil {
+		return
+	}
+	value = result.GetSuccess()
+	return
+}
+
+type SamplingManagerProcessor struct {
+	processorMap map[string]thrift.TProcessorFunction
+	handler      SamplingManager
+}
+
+func (p *SamplingManagerProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) {
+	p.processorMap[key] = processor
+}
+
+func (p *SamplingManagerProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) {
+	processor, ok = p.processorMap[key]
+	return processor, ok
+}
+
+func (p *SamplingManagerProcessor) ProcessorMap() map[string]thrift.TProcessorFunction {
+	return p.processorMap
+}
+
+func NewSamplingManagerProcessor(handler SamplingManager) *SamplingManagerProcessor {
+
+	self3 := &SamplingManagerProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)}
+	self3.processorMap["getSamplingStrategy"] = &samplingManagerProcessorGetSamplingStrategy{handler: handler}
+	return self3
+}
+
+func (p *SamplingManagerProcessor) Process(iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
+	name, _, seqId, err := iprot.ReadMessageBegin()
+	if err != nil {
+		return false, err
+	}
+	if processor, ok := p.GetProcessorFunction(name); ok {
+		return processor.Process(seqId, iprot, oprot)
+	}
+	iprot.Skip(thrift.STRUCT)
+	iprot.ReadMessageEnd()
+	x4 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function "+name)
+	oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId)
+	x4.Write(oprot)
+	oprot.WriteMessageEnd()
+	oprot.Flush()
+	return false, x4
+
+}
+
+type samplingManagerProcessorGetSamplingStrategy struct {
+	handler SamplingManager
+}
+
+func (p *samplingManagerProcessorGetSamplingStrategy) Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
+	args := SamplingManagerGetSamplingStrategyArgs{}
+	if err = args.Read(iprot); err != nil {
+		iprot.ReadMessageEnd()
+		x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error())
+		oprot.WriteMessageBegin("getSamplingStrategy", thrift.EXCEPTION, seqId)
+		x.Write(oprot)
+		oprot.WriteMessageEnd()
+		oprot.Flush()
+		return false, err
+	}
+
+	iprot.ReadMessageEnd()
+	result := SamplingManagerGetSamplingStrategyResult{}
+	var retval *SamplingStrategyResponse
+	var err2 error
+	if retval, err2 = p.handler.GetSamplingStrategy(args.ServiceName); err2 != nil {
+		x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing getSamplingStrategy: "+err2.Error())
+		oprot.WriteMessageBegin("getSamplingStrategy", thrift.EXCEPTION, seqId)
+		x.Write(oprot)
+		oprot.WriteMessageEnd()
+		oprot.Flush()
+		return true, err2
+	} else {
+		result.Success = retval
+	}
+	if err2 = oprot.WriteMessageBegin("getSamplingStrategy", thrift.REPLY, seqId); err2 != nil {
+		err = err2
+	}
+	if err2 = result.Write(oprot); err == nil && err2 != nil {
+		err = err2
+	}
+	if err2 = oprot.WriteMessageEnd(); err == nil && err2 != nil {
+		err = err2
+	}
+	if err2 = oprot.Flush(); err == nil && err2 != nil {
+		err = err2
+	}
+	if err != nil {
+		return
+	}
+	return true, err
+}
+
+// HELPER FUNCTIONS AND STRUCTURES
+
+// Attributes:
+//  - ServiceName
+type SamplingManagerGetSamplingStrategyArgs struct {
+	ServiceName string `thrift:"serviceName,1" json:"serviceName"`
+}
+
+func NewSamplingManagerGetSamplingStrategyArgs() *SamplingManagerGetSamplingStrategyArgs {
+	return &SamplingManagerGetSamplingStrategyArgs{}
+}
+
+func (p *SamplingManagerGetSamplingStrategyArgs) GetServiceName() string {
+	return p.ServiceName
+}
+func (p *SamplingManagerGetSamplingStrategyArgs) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+		default:
+			if err := iprot.Skip(fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	return nil
+}
+
+func (p *SamplingManagerGetSamplingStrategyArgs) readField1(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadString(); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		p.ServiceName = v
+	}
+	return nil
+}
+
+func (p *SamplingManagerGetSamplingStrategyArgs) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("getSamplingStrategy_args"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := 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 *SamplingManagerGetSamplingStrategyArgs) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("serviceName", thrift.STRING, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:serviceName: ", p), err)
+	}
+	if err := oprot.WriteString(string(p.ServiceName)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.serviceName (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:serviceName: ", p), err)
+	}
+	return err
+}
+
+func (p *SamplingManagerGetSamplingStrategyArgs) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("SamplingManagerGetSamplingStrategyArgs(%+v)", *p)
+}
+
+// Attributes:
+//  - Success
+type SamplingManagerGetSamplingStrategyResult struct {
+	Success *SamplingStrategyResponse `thrift:"success,0" json:"success,omitempty"`
+}
+
+func NewSamplingManagerGetSamplingStrategyResult() *SamplingManagerGetSamplingStrategyResult {
+	return &SamplingManagerGetSamplingStrategyResult{}
+}
+
+var SamplingManagerGetSamplingStrategyResult_Success_DEFAULT *SamplingStrategyResponse
+
+func (p *SamplingManagerGetSamplingStrategyResult) GetSuccess() *SamplingStrategyResponse {
+	if !p.IsSetSuccess() {
+		return SamplingManagerGetSamplingStrategyResult_Success_DEFAULT
+	}
+	return p.Success
+}
+func (p *SamplingManagerGetSamplingStrategyResult) IsSetSuccess() bool {
+	return p.Success != nil
+}
+
+func (p *SamplingManagerGetSamplingStrategyResult) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 0:
+			if err := p.readField0(iprot); err != nil {
+				return err
+			}
+		default:
+			if err := iprot.Skip(fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	return nil
+}
+
+func (p *SamplingManagerGetSamplingStrategyResult) readField0(iprot thrift.TProtocol) error {
+	p.Success = &SamplingStrategyResponse{}
+	if err := p.Success.Read(iprot); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Success), err)
+	}
+	return nil
+}
+
+func (p *SamplingManagerGetSamplingStrategyResult) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("getSamplingStrategy_result"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField0(oprot); err != nil {
+		return err
+	}
+	if err := oprot.WriteFieldStop(); err != nil {
+		return thrift.PrependError("write field stop error: ", err)
+	}
+	if err := oprot.WriteStructEnd(); err != nil {
+		return thrift.PrependError("write struct stop error: ", err)
+	}
+	return nil
+}
+
+func (p *SamplingManagerGetSamplingStrategyResult) writeField0(oprot thrift.TProtocol) (err error) {
+	if p.IsSetSuccess() {
+		if err := oprot.WriteFieldBegin("success", thrift.STRUCT, 0); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 0:success: ", p), err)
+		}
+		if err := p.Success.Write(oprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Success), err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 0:success: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *SamplingManagerGetSamplingStrategyResult) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("SamplingManagerGetSamplingStrategyResult(%+v)", *p)
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/sampling/ttypes.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/sampling/ttypes.go
new file mode 100644
index 0000000..9abaf05
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/sampling/ttypes.go
@@ -0,0 +1,873 @@
+// Autogenerated by Thrift Compiler (0.9.3)
+// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+
+package sampling
+
+import (
+	"bytes"
+	"fmt"
+	"github.com/uber/jaeger-client-go/thrift"
+)
+
+// (needed to ensure safety because of naive import list construction.)
+var _ = thrift.ZERO
+var _ = fmt.Printf
+var _ = bytes.Equal
+
+var GoUnusedProtection__ int
+
+type SamplingStrategyType int64
+
+const (
+	SamplingStrategyType_PROBABILISTIC SamplingStrategyType = 0
+	SamplingStrategyType_RATE_LIMITING SamplingStrategyType = 1
+)
+
+func (p SamplingStrategyType) String() string {
+	switch p {
+	case SamplingStrategyType_PROBABILISTIC:
+		return "PROBABILISTIC"
+	case SamplingStrategyType_RATE_LIMITING:
+		return "RATE_LIMITING"
+	}
+	return "<UNSET>"
+}
+
+func SamplingStrategyTypeFromString(s string) (SamplingStrategyType, error) {
+	switch s {
+	case "PROBABILISTIC":
+		return SamplingStrategyType_PROBABILISTIC, nil
+	case "RATE_LIMITING":
+		return SamplingStrategyType_RATE_LIMITING, nil
+	}
+	return SamplingStrategyType(0), fmt.Errorf("not a valid SamplingStrategyType string")
+}
+
+func SamplingStrategyTypePtr(v SamplingStrategyType) *SamplingStrategyType { return &v }
+
+func (p SamplingStrategyType) MarshalText() ([]byte, error) {
+	return []byte(p.String()), nil
+}
+
+func (p *SamplingStrategyType) UnmarshalText(text []byte) error {
+	q, err := SamplingStrategyTypeFromString(string(text))
+	if err != nil {
+		return err
+	}
+	*p = q
+	return nil
+}
+
+// Attributes:
+//  - SamplingRate
+type ProbabilisticSamplingStrategy struct {
+	SamplingRate float64 `thrift:"samplingRate,1,required" json:"samplingRate"`
+}
+
+func NewProbabilisticSamplingStrategy() *ProbabilisticSamplingStrategy {
+	return &ProbabilisticSamplingStrategy{}
+}
+
+func (p *ProbabilisticSamplingStrategy) GetSamplingRate() float64 {
+	return p.SamplingRate
+}
+func (p *ProbabilisticSamplingStrategy) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	var issetSamplingRate bool = false
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+			issetSamplingRate = true
+		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)
+	}
+	if !issetSamplingRate {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field SamplingRate is not set"))
+	}
+	return nil
+}
+
+func (p *ProbabilisticSamplingStrategy) readField1(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadDouble(); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		p.SamplingRate = v
+	}
+	return nil
+}
+
+func (p *ProbabilisticSamplingStrategy) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("ProbabilisticSamplingStrategy"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := oprot.WriteFieldStop(); err != nil {
+		return thrift.PrependError("write field stop error: ", err)
+	}
+	if err := oprot.WriteStructEnd(); err != nil {
+		return thrift.PrependError("write struct stop error: ", err)
+	}
+	return nil
+}
+
+func (p *ProbabilisticSamplingStrategy) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("samplingRate", thrift.DOUBLE, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:samplingRate: ", p), err)
+	}
+	if err := oprot.WriteDouble(float64(p.SamplingRate)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.samplingRate (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:samplingRate: ", p), err)
+	}
+	return err
+}
+
+func (p *ProbabilisticSamplingStrategy) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("ProbabilisticSamplingStrategy(%+v)", *p)
+}
+
+// Attributes:
+//  - MaxTracesPerSecond
+type RateLimitingSamplingStrategy struct {
+	MaxTracesPerSecond int16 `thrift:"maxTracesPerSecond,1,required" json:"maxTracesPerSecond"`
+}
+
+func NewRateLimitingSamplingStrategy() *RateLimitingSamplingStrategy {
+	return &RateLimitingSamplingStrategy{}
+}
+
+func (p *RateLimitingSamplingStrategy) GetMaxTracesPerSecond() int16 {
+	return p.MaxTracesPerSecond
+}
+func (p *RateLimitingSamplingStrategy) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	var issetMaxTracesPerSecond bool = false
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+			issetMaxTracesPerSecond = true
+		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)
+	}
+	if !issetMaxTracesPerSecond {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field MaxTracesPerSecond is not set"))
+	}
+	return nil
+}
+
+func (p *RateLimitingSamplingStrategy) readField1(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI16(); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		p.MaxTracesPerSecond = v
+	}
+	return nil
+}
+
+func (p *RateLimitingSamplingStrategy) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("RateLimitingSamplingStrategy"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := oprot.WriteFieldStop(); err != nil {
+		return thrift.PrependError("write field stop error: ", err)
+	}
+	if err := oprot.WriteStructEnd(); err != nil {
+		return thrift.PrependError("write struct stop error: ", err)
+	}
+	return nil
+}
+
+func (p *RateLimitingSamplingStrategy) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("maxTracesPerSecond", thrift.I16, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:maxTracesPerSecond: ", p), err)
+	}
+	if err := oprot.WriteI16(int16(p.MaxTracesPerSecond)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.maxTracesPerSecond (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:maxTracesPerSecond: ", p), err)
+	}
+	return err
+}
+
+func (p *RateLimitingSamplingStrategy) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("RateLimitingSamplingStrategy(%+v)", *p)
+}
+
+// Attributes:
+//  - Operation
+//  - ProbabilisticSampling
+type OperationSamplingStrategy struct {
+	Operation             string                         `thrift:"operation,1,required" json:"operation"`
+	ProbabilisticSampling *ProbabilisticSamplingStrategy `thrift:"probabilisticSampling,2,required" json:"probabilisticSampling"`
+}
+
+func NewOperationSamplingStrategy() *OperationSamplingStrategy {
+	return &OperationSamplingStrategy{}
+}
+
+func (p *OperationSamplingStrategy) GetOperation() string {
+	return p.Operation
+}
+
+var OperationSamplingStrategy_ProbabilisticSampling_DEFAULT *ProbabilisticSamplingStrategy
+
+func (p *OperationSamplingStrategy) GetProbabilisticSampling() *ProbabilisticSamplingStrategy {
+	if !p.IsSetProbabilisticSampling() {
+		return OperationSamplingStrategy_ProbabilisticSampling_DEFAULT
+	}
+	return p.ProbabilisticSampling
+}
+func (p *OperationSamplingStrategy) IsSetProbabilisticSampling() bool {
+	return p.ProbabilisticSampling != nil
+}
+
+func (p *OperationSamplingStrategy) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	var issetOperation bool = false
+	var issetProbabilisticSampling bool = false
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+			issetOperation = true
+		case 2:
+			if err := p.readField2(iprot); err != nil {
+				return err
+			}
+			issetProbabilisticSampling = true
+		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)
+	}
+	if !issetOperation {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Operation is not set"))
+	}
+	if !issetProbabilisticSampling {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field ProbabilisticSampling is not set"))
+	}
+	return nil
+}
+
+func (p *OperationSamplingStrategy) readField1(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadString(); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		p.Operation = v
+	}
+	return nil
+}
+
+func (p *OperationSamplingStrategy) readField2(iprot thrift.TProtocol) error {
+	p.ProbabilisticSampling = &ProbabilisticSamplingStrategy{}
+	if err := p.ProbabilisticSampling.Read(iprot); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.ProbabilisticSampling), err)
+	}
+	return nil
+}
+
+func (p *OperationSamplingStrategy) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("OperationSamplingStrategy"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField2(oprot); err != nil {
+		return err
+	}
+	if err := oprot.WriteFieldStop(); err != nil {
+		return thrift.PrependError("write field stop error: ", err)
+	}
+	if err := oprot.WriteStructEnd(); err != nil {
+		return thrift.PrependError("write struct stop error: ", err)
+	}
+	return nil
+}
+
+func (p *OperationSamplingStrategy) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("operation", thrift.STRING, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:operation: ", p), err)
+	}
+	if err := oprot.WriteString(string(p.Operation)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.operation (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:operation: ", p), err)
+	}
+	return err
+}
+
+func (p *OperationSamplingStrategy) writeField2(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("probabilisticSampling", thrift.STRUCT, 2); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:probabilisticSampling: ", p), err)
+	}
+	if err := p.ProbabilisticSampling.Write(oprot); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.ProbabilisticSampling), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 2:probabilisticSampling: ", p), err)
+	}
+	return err
+}
+
+func (p *OperationSamplingStrategy) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("OperationSamplingStrategy(%+v)", *p)
+}
+
+// Attributes:
+//  - DefaultSamplingProbability
+//  - DefaultLowerBoundTracesPerSecond
+//  - PerOperationStrategies
+//  - DefaultUpperBoundTracesPerSecond
+type PerOperationSamplingStrategies struct {
+	DefaultSamplingProbability       float64                      `thrift:"defaultSamplingProbability,1,required" json:"defaultSamplingProbability"`
+	DefaultLowerBoundTracesPerSecond float64                      `thrift:"defaultLowerBoundTracesPerSecond,2,required" json:"defaultLowerBoundTracesPerSecond"`
+	PerOperationStrategies           []*OperationSamplingStrategy `thrift:"perOperationStrategies,3,required" json:"perOperationStrategies"`
+	DefaultUpperBoundTracesPerSecond *float64                     `thrift:"defaultUpperBoundTracesPerSecond,4" json:"defaultUpperBoundTracesPerSecond,omitempty"`
+}
+
+func NewPerOperationSamplingStrategies() *PerOperationSamplingStrategies {
+	return &PerOperationSamplingStrategies{}
+}
+
+func (p *PerOperationSamplingStrategies) GetDefaultSamplingProbability() float64 {
+	return p.DefaultSamplingProbability
+}
+
+func (p *PerOperationSamplingStrategies) GetDefaultLowerBoundTracesPerSecond() float64 {
+	return p.DefaultLowerBoundTracesPerSecond
+}
+
+func (p *PerOperationSamplingStrategies) GetPerOperationStrategies() []*OperationSamplingStrategy {
+	return p.PerOperationStrategies
+}
+
+var PerOperationSamplingStrategies_DefaultUpperBoundTracesPerSecond_DEFAULT float64
+
+func (p *PerOperationSamplingStrategies) GetDefaultUpperBoundTracesPerSecond() float64 {
+	if !p.IsSetDefaultUpperBoundTracesPerSecond() {
+		return PerOperationSamplingStrategies_DefaultUpperBoundTracesPerSecond_DEFAULT
+	}
+	return *p.DefaultUpperBoundTracesPerSecond
+}
+func (p *PerOperationSamplingStrategies) IsSetDefaultUpperBoundTracesPerSecond() bool {
+	return p.DefaultUpperBoundTracesPerSecond != nil
+}
+
+func (p *PerOperationSamplingStrategies) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	var issetDefaultSamplingProbability bool = false
+	var issetDefaultLowerBoundTracesPerSecond bool = false
+	var issetPerOperationStrategies bool = false
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+			issetDefaultSamplingProbability = true
+		case 2:
+			if err := p.readField2(iprot); err != nil {
+				return err
+			}
+			issetDefaultLowerBoundTracesPerSecond = true
+		case 3:
+			if err := p.readField3(iprot); err != nil {
+				return err
+			}
+			issetPerOperationStrategies = true
+		case 4:
+			if err := p.readField4(iprot); err != nil {
+				return err
+			}
+		default:
+			if err := iprot.Skip(fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	if !issetDefaultSamplingProbability {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field DefaultSamplingProbability is not set"))
+	}
+	if !issetDefaultLowerBoundTracesPerSecond {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field DefaultLowerBoundTracesPerSecond is not set"))
+	}
+	if !issetPerOperationStrategies {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field PerOperationStrategies is not set"))
+	}
+	return nil
+}
+
+func (p *PerOperationSamplingStrategies) readField1(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadDouble(); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		p.DefaultSamplingProbability = v
+	}
+	return nil
+}
+
+func (p *PerOperationSamplingStrategies) readField2(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadDouble(); err != nil {
+		return thrift.PrependError("error reading field 2: ", err)
+	} else {
+		p.DefaultLowerBoundTracesPerSecond = v
+	}
+	return nil
+}
+
+func (p *PerOperationSamplingStrategies) readField3(iprot thrift.TProtocol) error {
+	_, size, err := iprot.ReadListBegin()
+	if err != nil {
+		return thrift.PrependError("error reading list begin: ", err)
+	}
+	tSlice := make([]*OperationSamplingStrategy, 0, size)
+	p.PerOperationStrategies = tSlice
+	for i := 0; i < size; i++ {
+		_elem0 := &OperationSamplingStrategy{}
+		if err := _elem0.Read(iprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem0), err)
+		}
+		p.PerOperationStrategies = append(p.PerOperationStrategies, _elem0)
+	}
+	if err := iprot.ReadListEnd(); err != nil {
+		return thrift.PrependError("error reading list end: ", err)
+	}
+	return nil
+}
+
+func (p *PerOperationSamplingStrategies) readField4(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadDouble(); err != nil {
+		return thrift.PrependError("error reading field 4: ", err)
+	} else {
+		p.DefaultUpperBoundTracesPerSecond = &v
+	}
+	return nil
+}
+
+func (p *PerOperationSamplingStrategies) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("PerOperationSamplingStrategies"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField2(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField3(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField4(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 *PerOperationSamplingStrategies) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("defaultSamplingProbability", thrift.DOUBLE, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:defaultSamplingProbability: ", p), err)
+	}
+	if err := oprot.WriteDouble(float64(p.DefaultSamplingProbability)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.defaultSamplingProbability (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:defaultSamplingProbability: ", p), err)
+	}
+	return err
+}
+
+func (p *PerOperationSamplingStrategies) writeField2(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("defaultLowerBoundTracesPerSecond", thrift.DOUBLE, 2); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:defaultLowerBoundTracesPerSecond: ", p), err)
+	}
+	if err := oprot.WriteDouble(float64(p.DefaultLowerBoundTracesPerSecond)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.defaultLowerBoundTracesPerSecond (2) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 2:defaultLowerBoundTracesPerSecond: ", p), err)
+	}
+	return err
+}
+
+func (p *PerOperationSamplingStrategies) writeField3(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("perOperationStrategies", thrift.LIST, 3); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 3:perOperationStrategies: ", p), err)
+	}
+	if err := oprot.WriteListBegin(thrift.STRUCT, len(p.PerOperationStrategies)); err != nil {
+		return thrift.PrependError("error writing list begin: ", err)
+	}
+	for _, v := range p.PerOperationStrategies {
+		if err := v.Write(oprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
+		}
+	}
+	if err := oprot.WriteListEnd(); err != nil {
+		return thrift.PrependError("error writing list end: ", err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 3:perOperationStrategies: ", p), err)
+	}
+	return err
+}
+
+func (p *PerOperationSamplingStrategies) writeField4(oprot thrift.TProtocol) (err error) {
+	if p.IsSetDefaultUpperBoundTracesPerSecond() {
+		if err := oprot.WriteFieldBegin("defaultUpperBoundTracesPerSecond", thrift.DOUBLE, 4); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 4:defaultUpperBoundTracesPerSecond: ", p), err)
+		}
+		if err := oprot.WriteDouble(float64(*p.DefaultUpperBoundTracesPerSecond)); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T.defaultUpperBoundTracesPerSecond (4) field write error: ", p), err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 4:defaultUpperBoundTracesPerSecond: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *PerOperationSamplingStrategies) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("PerOperationSamplingStrategies(%+v)", *p)
+}
+
+// Attributes:
+//  - StrategyType
+//  - ProbabilisticSampling
+//  - RateLimitingSampling
+//  - OperationSampling
+type SamplingStrategyResponse struct {
+	StrategyType          SamplingStrategyType            `thrift:"strategyType,1,required" json:"strategyType"`
+	ProbabilisticSampling *ProbabilisticSamplingStrategy  `thrift:"probabilisticSampling,2" json:"probabilisticSampling,omitempty"`
+	RateLimitingSampling  *RateLimitingSamplingStrategy   `thrift:"rateLimitingSampling,3" json:"rateLimitingSampling,omitempty"`
+	OperationSampling     *PerOperationSamplingStrategies `thrift:"operationSampling,4" json:"operationSampling,omitempty"`
+}
+
+func NewSamplingStrategyResponse() *SamplingStrategyResponse {
+	return &SamplingStrategyResponse{}
+}
+
+func (p *SamplingStrategyResponse) GetStrategyType() SamplingStrategyType {
+	return p.StrategyType
+}
+
+var SamplingStrategyResponse_ProbabilisticSampling_DEFAULT *ProbabilisticSamplingStrategy
+
+func (p *SamplingStrategyResponse) GetProbabilisticSampling() *ProbabilisticSamplingStrategy {
+	if !p.IsSetProbabilisticSampling() {
+		return SamplingStrategyResponse_ProbabilisticSampling_DEFAULT
+	}
+	return p.ProbabilisticSampling
+}
+
+var SamplingStrategyResponse_RateLimitingSampling_DEFAULT *RateLimitingSamplingStrategy
+
+func (p *SamplingStrategyResponse) GetRateLimitingSampling() *RateLimitingSamplingStrategy {
+	if !p.IsSetRateLimitingSampling() {
+		return SamplingStrategyResponse_RateLimitingSampling_DEFAULT
+	}
+	return p.RateLimitingSampling
+}
+
+var SamplingStrategyResponse_OperationSampling_DEFAULT *PerOperationSamplingStrategies
+
+func (p *SamplingStrategyResponse) GetOperationSampling() *PerOperationSamplingStrategies {
+	if !p.IsSetOperationSampling() {
+		return SamplingStrategyResponse_OperationSampling_DEFAULT
+	}
+	return p.OperationSampling
+}
+func (p *SamplingStrategyResponse) IsSetProbabilisticSampling() bool {
+	return p.ProbabilisticSampling != nil
+}
+
+func (p *SamplingStrategyResponse) IsSetRateLimitingSampling() bool {
+	return p.RateLimitingSampling != nil
+}
+
+func (p *SamplingStrategyResponse) IsSetOperationSampling() bool {
+	return p.OperationSampling != nil
+}
+
+func (p *SamplingStrategyResponse) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	var issetStrategyType bool = false
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+			issetStrategyType = true
+		case 2:
+			if err := p.readField2(iprot); err != nil {
+				return err
+			}
+		case 3:
+			if err := p.readField3(iprot); err != nil {
+				return err
+			}
+		case 4:
+			if err := p.readField4(iprot); err != nil {
+				return err
+			}
+		default:
+			if err := iprot.Skip(fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	if !issetStrategyType {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field StrategyType is not set"))
+	}
+	return nil
+}
+
+func (p *SamplingStrategyResponse) readField1(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI32(); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		temp := SamplingStrategyType(v)
+		p.StrategyType = temp
+	}
+	return nil
+}
+
+func (p *SamplingStrategyResponse) readField2(iprot thrift.TProtocol) error {
+	p.ProbabilisticSampling = &ProbabilisticSamplingStrategy{}
+	if err := p.ProbabilisticSampling.Read(iprot); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.ProbabilisticSampling), err)
+	}
+	return nil
+}
+
+func (p *SamplingStrategyResponse) readField3(iprot thrift.TProtocol) error {
+	p.RateLimitingSampling = &RateLimitingSamplingStrategy{}
+	if err := p.RateLimitingSampling.Read(iprot); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.RateLimitingSampling), err)
+	}
+	return nil
+}
+
+func (p *SamplingStrategyResponse) readField4(iprot thrift.TProtocol) error {
+	p.OperationSampling = &PerOperationSamplingStrategies{}
+	if err := p.OperationSampling.Read(iprot); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.OperationSampling), err)
+	}
+	return nil
+}
+
+func (p *SamplingStrategyResponse) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("SamplingStrategyResponse"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField2(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField3(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField4(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 *SamplingStrategyResponse) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("strategyType", thrift.I32, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:strategyType: ", p), err)
+	}
+	if err := oprot.WriteI32(int32(p.StrategyType)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.strategyType (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:strategyType: ", p), err)
+	}
+	return err
+}
+
+func (p *SamplingStrategyResponse) writeField2(oprot thrift.TProtocol) (err error) {
+	if p.IsSetProbabilisticSampling() {
+		if err := oprot.WriteFieldBegin("probabilisticSampling", thrift.STRUCT, 2); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:probabilisticSampling: ", p), err)
+		}
+		if err := p.ProbabilisticSampling.Write(oprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.ProbabilisticSampling), err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 2:probabilisticSampling: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *SamplingStrategyResponse) writeField3(oprot thrift.TProtocol) (err error) {
+	if p.IsSetRateLimitingSampling() {
+		if err := oprot.WriteFieldBegin("rateLimitingSampling", thrift.STRUCT, 3); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 3:rateLimitingSampling: ", p), err)
+		}
+		if err := p.RateLimitingSampling.Write(oprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.RateLimitingSampling), err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 3:rateLimitingSampling: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *SamplingStrategyResponse) writeField4(oprot thrift.TProtocol) (err error) {
+	if p.IsSetOperationSampling() {
+		if err := oprot.WriteFieldBegin("operationSampling", thrift.STRUCT, 4); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 4:operationSampling: ", p), err)
+		}
+		if err := p.OperationSampling.Write(oprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.OperationSampling), err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 4:operationSampling: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *SamplingStrategyResponse) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("SamplingStrategyResponse(%+v)", *p)
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/zipkincore/constants.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/zipkincore/constants.go
new file mode 100644
index 0000000..a53d46f
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/zipkincore/constants.go
@@ -0,0 +1,35 @@
+// Autogenerated by Thrift Compiler (0.9.3)
+// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+
+package zipkincore
+
+import (
+	"bytes"
+	"fmt"
+	"github.com/uber/jaeger-client-go/thrift"
+)
+
+// (needed to ensure safety because of naive import list construction.)
+var _ = thrift.ZERO
+var _ = fmt.Printf
+var _ = bytes.Equal
+
+const CLIENT_SEND = "cs"
+const CLIENT_RECV = "cr"
+const SERVER_SEND = "ss"
+const SERVER_RECV = "sr"
+const MESSAGE_SEND = "ms"
+const MESSAGE_RECV = "mr"
+const WIRE_SEND = "ws"
+const WIRE_RECV = "wr"
+const CLIENT_SEND_FRAGMENT = "csf"
+const CLIENT_RECV_FRAGMENT = "crf"
+const SERVER_SEND_FRAGMENT = "ssf"
+const SERVER_RECV_FRAGMENT = "srf"
+const LOCAL_COMPONENT = "lc"
+const CLIENT_ADDR = "ca"
+const SERVER_ADDR = "sa"
+const MESSAGE_ADDR = "ma"
+
+func init() {
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/zipkincore/ttypes.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/zipkincore/ttypes.go
new file mode 100644
index 0000000..15583e5
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/zipkincore/ttypes.go
@@ -0,0 +1,1337 @@
+// Autogenerated by Thrift Compiler (0.9.3)
+// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+
+package zipkincore
+
+import (
+	"bytes"
+	"fmt"
+	"github.com/uber/jaeger-client-go/thrift"
+)
+
+// (needed to ensure safety because of naive import list construction.)
+var _ = thrift.ZERO
+var _ = fmt.Printf
+var _ = bytes.Equal
+
+var GoUnusedProtection__ int
+
+type AnnotationType int64
+
+const (
+	AnnotationType_BOOL   AnnotationType = 0
+	AnnotationType_BYTES  AnnotationType = 1
+	AnnotationType_I16    AnnotationType = 2
+	AnnotationType_I32    AnnotationType = 3
+	AnnotationType_I64    AnnotationType = 4
+	AnnotationType_DOUBLE AnnotationType = 5
+	AnnotationType_STRING AnnotationType = 6
+)
+
+func (p AnnotationType) String() string {
+	switch p {
+	case AnnotationType_BOOL:
+		return "BOOL"
+	case AnnotationType_BYTES:
+		return "BYTES"
+	case AnnotationType_I16:
+		return "I16"
+	case AnnotationType_I32:
+		return "I32"
+	case AnnotationType_I64:
+		return "I64"
+	case AnnotationType_DOUBLE:
+		return "DOUBLE"
+	case AnnotationType_STRING:
+		return "STRING"
+	}
+	return "<UNSET>"
+}
+
+func AnnotationTypeFromString(s string) (AnnotationType, error) {
+	switch s {
+	case "BOOL":
+		return AnnotationType_BOOL, nil
+	case "BYTES":
+		return AnnotationType_BYTES, nil
+	case "I16":
+		return AnnotationType_I16, nil
+	case "I32":
+		return AnnotationType_I32, nil
+	case "I64":
+		return AnnotationType_I64, nil
+	case "DOUBLE":
+		return AnnotationType_DOUBLE, nil
+	case "STRING":
+		return AnnotationType_STRING, nil
+	}
+	return AnnotationType(0), fmt.Errorf("not a valid AnnotationType string")
+}
+
+func AnnotationTypePtr(v AnnotationType) *AnnotationType { return &v }
+
+func (p AnnotationType) MarshalText() ([]byte, error) {
+	return []byte(p.String()), nil
+}
+
+func (p *AnnotationType) UnmarshalText(text []byte) error {
+	q, err := AnnotationTypeFromString(string(text))
+	if err != nil {
+		return err
+	}
+	*p = q
+	return nil
+}
+
+// Indicates the network context of a service recording an annotation with two
+// exceptions.
+//
+// When a BinaryAnnotation, and key is CLIENT_ADDR or SERVER_ADDR,
+// the endpoint indicates the source or destination of an RPC. This exception
+// allows zipkin to display network context of uninstrumented services, or
+// clients such as web browsers.
+//
+// Attributes:
+//  - Ipv4: IPv4 host address packed into 4 bytes.
+//
+// Ex for the ip 1.2.3.4, it would be (1 << 24) | (2 << 16) | (3 << 8) | 4
+//  - Port: IPv4 port
+//
+// Note: this is to be treated as an unsigned integer, so watch for negatives.
+//
+// Conventionally, when the port isn't known, port = 0.
+//  - ServiceName: Service name in lowercase, such as "memcache" or "zipkin-web"
+//
+// Conventionally, when the service name isn't known, service_name = "unknown".
+//  - Ipv6: IPv6 host address packed into 16 bytes. Ex Inet6Address.getBytes()
+type Endpoint struct {
+	Ipv4        int32  `thrift:"ipv4,1" json:"ipv4"`
+	Port        int16  `thrift:"port,2" json:"port"`
+	ServiceName string `thrift:"service_name,3" json:"service_name"`
+	Ipv6        []byte `thrift:"ipv6,4" json:"ipv6,omitempty"`
+}
+
+func NewEndpoint() *Endpoint {
+	return &Endpoint{}
+}
+
+func (p *Endpoint) GetIpv4() int32 {
+	return p.Ipv4
+}
+
+func (p *Endpoint) GetPort() int16 {
+	return p.Port
+}
+
+func (p *Endpoint) GetServiceName() string {
+	return p.ServiceName
+}
+
+var Endpoint_Ipv6_DEFAULT []byte
+
+func (p *Endpoint) GetIpv6() []byte {
+	return p.Ipv6
+}
+func (p *Endpoint) IsSetIpv6() bool {
+	return p.Ipv6 != nil
+}
+
+func (p *Endpoint) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+		case 2:
+			if err := p.readField2(iprot); err != nil {
+				return err
+			}
+		case 3:
+			if err := p.readField3(iprot); err != nil {
+				return err
+			}
+		case 4:
+			if err := p.readField4(iprot); err != nil {
+				return err
+			}
+		default:
+			if err := iprot.Skip(fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	return nil
+}
+
+func (p *Endpoint) readField1(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI32(); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		p.Ipv4 = v
+	}
+	return nil
+}
+
+func (p *Endpoint) readField2(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI16(); err != nil {
+		return thrift.PrependError("error reading field 2: ", err)
+	} else {
+		p.Port = v
+	}
+	return nil
+}
+
+func (p *Endpoint) readField3(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadString(); err != nil {
+		return thrift.PrependError("error reading field 3: ", err)
+	} else {
+		p.ServiceName = v
+	}
+	return nil
+}
+
+func (p *Endpoint) readField4(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadBinary(); err != nil {
+		return thrift.PrependError("error reading field 4: ", err)
+	} else {
+		p.Ipv6 = v
+	}
+	return nil
+}
+
+func (p *Endpoint) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("Endpoint"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField2(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField3(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField4(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 *Endpoint) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("ipv4", thrift.I32, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:ipv4: ", p), err)
+	}
+	if err := oprot.WriteI32(int32(p.Ipv4)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.ipv4 (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:ipv4: ", p), err)
+	}
+	return err
+}
+
+func (p *Endpoint) writeField2(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("port", thrift.I16, 2); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:port: ", p), err)
+	}
+	if err := oprot.WriteI16(int16(p.Port)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.port (2) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 2:port: ", p), err)
+	}
+	return err
+}
+
+func (p *Endpoint) writeField3(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("service_name", thrift.STRING, 3); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 3:service_name: ", p), err)
+	}
+	if err := oprot.WriteString(string(p.ServiceName)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.service_name (3) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 3:service_name: ", p), err)
+	}
+	return err
+}
+
+func (p *Endpoint) writeField4(oprot thrift.TProtocol) (err error) {
+	if p.IsSetIpv6() {
+		if err := oprot.WriteFieldBegin("ipv6", thrift.STRING, 4); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 4:ipv6: ", p), err)
+		}
+		if err := oprot.WriteBinary(p.Ipv6); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T.ipv6 (4) field write error: ", p), err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 4:ipv6: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *Endpoint) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("Endpoint(%+v)", *p)
+}
+
+// An annotation is similar to a log statement. It includes a host field which
+// allows these events to be attributed properly, and also aggregatable.
+//
+// Attributes:
+//  - Timestamp: Microseconds from epoch.
+//
+// This value should use the most precise value possible. For example,
+// gettimeofday or syncing nanoTime against a tick of currentTimeMillis.
+//  - Value
+//  - Host: Always the host that recorded the event. By specifying the host you allow
+// rollup of all events (such as client requests to a service) by IP address.
+type Annotation struct {
+	Timestamp int64     `thrift:"timestamp,1" json:"timestamp"`
+	Value     string    `thrift:"value,2" json:"value"`
+	Host      *Endpoint `thrift:"host,3" json:"host,omitempty"`
+}
+
+func NewAnnotation() *Annotation {
+	return &Annotation{}
+}
+
+func (p *Annotation) GetTimestamp() int64 {
+	return p.Timestamp
+}
+
+func (p *Annotation) GetValue() string {
+	return p.Value
+}
+
+var Annotation_Host_DEFAULT *Endpoint
+
+func (p *Annotation) GetHost() *Endpoint {
+	if !p.IsSetHost() {
+		return Annotation_Host_DEFAULT
+	}
+	return p.Host
+}
+func (p *Annotation) IsSetHost() bool {
+	return p.Host != nil
+}
+
+func (p *Annotation) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+		case 2:
+			if err := p.readField2(iprot); err != nil {
+				return err
+			}
+		case 3:
+			if err := p.readField3(iprot); err != nil {
+				return err
+			}
+		default:
+			if err := iprot.Skip(fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	return nil
+}
+
+func (p *Annotation) readField1(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		p.Timestamp = v
+	}
+	return nil
+}
+
+func (p *Annotation) readField2(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadString(); err != nil {
+		return thrift.PrependError("error reading field 2: ", err)
+	} else {
+		p.Value = v
+	}
+	return nil
+}
+
+func (p *Annotation) readField3(iprot thrift.TProtocol) error {
+	p.Host = &Endpoint{}
+	if err := p.Host.Read(iprot); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Host), err)
+	}
+	return nil
+}
+
+func (p *Annotation) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("Annotation"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField2(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField3(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 *Annotation) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("timestamp", thrift.I64, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:timestamp: ", p), err)
+	}
+	if err := oprot.WriteI64(int64(p.Timestamp)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.timestamp (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:timestamp: ", p), err)
+	}
+	return err
+}
+
+func (p *Annotation) writeField2(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("value", thrift.STRING, 2); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:value: ", p), err)
+	}
+	if err := oprot.WriteString(string(p.Value)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.value (2) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 2:value: ", p), err)
+	}
+	return err
+}
+
+func (p *Annotation) writeField3(oprot thrift.TProtocol) (err error) {
+	if p.IsSetHost() {
+		if err := oprot.WriteFieldBegin("host", thrift.STRUCT, 3); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 3:host: ", p), err)
+		}
+		if err := p.Host.Write(oprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Host), err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 3:host: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *Annotation) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("Annotation(%+v)", *p)
+}
+
+// Binary annotations are tags applied to a Span to give it context. For
+// example, a binary annotation of "http.uri" could the path to a resource in a
+// RPC call.
+//
+// Binary annotations of type STRING are always queryable, though more a
+// historical implementation detail than a structural concern.
+//
+// Binary annotations can repeat, and vary on the host. Similar to Annotation,
+// the host indicates who logged the event. This allows you to tell the
+// difference between the client and server side of the same key. For example,
+// the key "http.uri" might be different on the client and server side due to
+// rewriting, like "/api/v1/myresource" vs "/myresource. Via the host field,
+// you can see the different points of view, which often help in debugging.
+//
+// Attributes:
+//  - Key
+//  - Value
+//  - AnnotationType
+//  - Host: The host that recorded tag, which allows you to differentiate between
+// multiple tags with the same key. There are two exceptions to this.
+//
+// When the key is CLIENT_ADDR or SERVER_ADDR, host indicates the source or
+// destination of an RPC. This exception allows zipkin to display network
+// context of uninstrumented services, or clients such as web browsers.
+type BinaryAnnotation struct {
+	Key            string         `thrift:"key,1" json:"key"`
+	Value          []byte         `thrift:"value,2" json:"value"`
+	AnnotationType AnnotationType `thrift:"annotation_type,3" json:"annotation_type"`
+	Host           *Endpoint      `thrift:"host,4" json:"host,omitempty"`
+}
+
+func NewBinaryAnnotation() *BinaryAnnotation {
+	return &BinaryAnnotation{}
+}
+
+func (p *BinaryAnnotation) GetKey() string {
+	return p.Key
+}
+
+func (p *BinaryAnnotation) GetValue() []byte {
+	return p.Value
+}
+
+func (p *BinaryAnnotation) GetAnnotationType() AnnotationType {
+	return p.AnnotationType
+}
+
+var BinaryAnnotation_Host_DEFAULT *Endpoint
+
+func (p *BinaryAnnotation) GetHost() *Endpoint {
+	if !p.IsSetHost() {
+		return BinaryAnnotation_Host_DEFAULT
+	}
+	return p.Host
+}
+func (p *BinaryAnnotation) IsSetHost() bool {
+	return p.Host != nil
+}
+
+func (p *BinaryAnnotation) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+		case 2:
+			if err := p.readField2(iprot); err != nil {
+				return err
+			}
+		case 3:
+			if err := p.readField3(iprot); err != nil {
+				return err
+			}
+		case 4:
+			if err := p.readField4(iprot); err != nil {
+				return err
+			}
+		default:
+			if err := iprot.Skip(fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	return nil
+}
+
+func (p *BinaryAnnotation) readField1(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadString(); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		p.Key = v
+	}
+	return nil
+}
+
+func (p *BinaryAnnotation) readField2(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadBinary(); err != nil {
+		return thrift.PrependError("error reading field 2: ", err)
+	} else {
+		p.Value = v
+	}
+	return nil
+}
+
+func (p *BinaryAnnotation) readField3(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI32(); err != nil {
+		return thrift.PrependError("error reading field 3: ", err)
+	} else {
+		temp := AnnotationType(v)
+		p.AnnotationType = temp
+	}
+	return nil
+}
+
+func (p *BinaryAnnotation) readField4(iprot thrift.TProtocol) error {
+	p.Host = &Endpoint{}
+	if err := p.Host.Read(iprot); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Host), err)
+	}
+	return nil
+}
+
+func (p *BinaryAnnotation) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("BinaryAnnotation"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField2(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField3(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField4(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 *BinaryAnnotation) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("key", thrift.STRING, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:key: ", p), err)
+	}
+	if err := oprot.WriteString(string(p.Key)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.key (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:key: ", p), err)
+	}
+	return err
+}
+
+func (p *BinaryAnnotation) writeField2(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("value", thrift.STRING, 2); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:value: ", p), err)
+	}
+	if err := oprot.WriteBinary(p.Value); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.value (2) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 2:value: ", p), err)
+	}
+	return err
+}
+
+func (p *BinaryAnnotation) writeField3(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("annotation_type", thrift.I32, 3); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 3:annotation_type: ", p), err)
+	}
+	if err := oprot.WriteI32(int32(p.AnnotationType)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.annotation_type (3) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 3:annotation_type: ", p), err)
+	}
+	return err
+}
+
+func (p *BinaryAnnotation) writeField4(oprot thrift.TProtocol) (err error) {
+	if p.IsSetHost() {
+		if err := oprot.WriteFieldBegin("host", thrift.STRUCT, 4); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 4:host: ", p), err)
+		}
+		if err := p.Host.Write(oprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Host), err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 4:host: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *BinaryAnnotation) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("BinaryAnnotation(%+v)", *p)
+}
+
+// A trace is a series of spans (often RPC calls) which form a latency tree.
+//
+// The root span is where trace_id = id and parent_id = Nil. The root span is
+// usually the longest interval in the trace, starting with a SERVER_RECV
+// annotation and ending with a SERVER_SEND.
+//
+// Attributes:
+//  - TraceID
+//  - Name: Span name in lowercase, rpc method for example
+//
+// Conventionally, when the span name isn't known, name = "unknown".
+//  - ID
+//  - ParentID
+//  - Annotations
+//  - BinaryAnnotations
+//  - Debug
+//  - Timestamp: Microseconds from epoch of the creation of this span.
+//
+// This value should be set directly by instrumentation, using the most
+// precise value possible. For example, gettimeofday or syncing nanoTime
+// against a tick of currentTimeMillis.
+//
+// For compatibility with instrumentation that precede this field, collectors
+// or span stores can derive this via Annotation.timestamp.
+// For example, SERVER_RECV.timestamp or CLIENT_SEND.timestamp.
+//
+// This field is optional for compatibility with old data: first-party span
+// stores are expected to support this at time of introduction.
+//  - Duration: Measurement of duration in microseconds, used to support queries.
+//
+// This value should be set directly, where possible. Doing so encourages
+// precise measurement decoupled from problems of clocks, such as skew or NTP
+// updates causing time to move backwards.
+//
+// For compatibility with instrumentation that precede this field, collectors
+// or span stores can derive this by subtracting Annotation.timestamp.
+// For example, SERVER_SEND.timestamp - SERVER_RECV.timestamp.
+//
+// If this field is persisted as unset, zipkin will continue to work, except
+// duration query support will be implementation-specific. Similarly, setting
+// this field non-atomically is implementation-specific.
+//
+// This field is i64 vs i32 to support spans longer than 35 minutes.
+//  - TraceIDHigh: Optional unique 8-byte additional identifier for a trace. If non zero, this
+// means the trace uses 128 bit traceIds instead of 64 bit.
+type Span struct {
+	TraceID int64 `thrift:"trace_id,1" json:"trace_id"`
+	// unused field # 2
+	Name        string        `thrift:"name,3" json:"name"`
+	ID          int64         `thrift:"id,4" json:"id"`
+	ParentID    *int64        `thrift:"parent_id,5" json:"parent_id,omitempty"`
+	Annotations []*Annotation `thrift:"annotations,6" json:"annotations"`
+	// unused field # 7
+	BinaryAnnotations []*BinaryAnnotation `thrift:"binary_annotations,8" json:"binary_annotations"`
+	Debug             bool                `thrift:"debug,9" json:"debug,omitempty"`
+	Timestamp         *int64              `thrift:"timestamp,10" json:"timestamp,omitempty"`
+	Duration          *int64              `thrift:"duration,11" json:"duration,omitempty"`
+	TraceIDHigh       *int64              `thrift:"trace_id_high,12" json:"trace_id_high,omitempty"`
+}
+
+func NewSpan() *Span {
+	return &Span{}
+}
+
+func (p *Span) GetTraceID() int64 {
+	return p.TraceID
+}
+
+func (p *Span) GetName() string {
+	return p.Name
+}
+
+func (p *Span) GetID() int64 {
+	return p.ID
+}
+
+var Span_ParentID_DEFAULT int64
+
+func (p *Span) GetParentID() int64 {
+	if !p.IsSetParentID() {
+		return Span_ParentID_DEFAULT
+	}
+	return *p.ParentID
+}
+
+func (p *Span) GetAnnotations() []*Annotation {
+	return p.Annotations
+}
+
+func (p *Span) GetBinaryAnnotations() []*BinaryAnnotation {
+	return p.BinaryAnnotations
+}
+
+var Span_Debug_DEFAULT bool = false
+
+func (p *Span) GetDebug() bool {
+	return p.Debug
+}
+
+var Span_Timestamp_DEFAULT int64
+
+func (p *Span) GetTimestamp() int64 {
+	if !p.IsSetTimestamp() {
+		return Span_Timestamp_DEFAULT
+	}
+	return *p.Timestamp
+}
+
+var Span_Duration_DEFAULT int64
+
+func (p *Span) GetDuration() int64 {
+	if !p.IsSetDuration() {
+		return Span_Duration_DEFAULT
+	}
+	return *p.Duration
+}
+
+var Span_TraceIDHigh_DEFAULT int64
+
+func (p *Span) GetTraceIDHigh() int64 {
+	if !p.IsSetTraceIDHigh() {
+		return Span_TraceIDHigh_DEFAULT
+	}
+	return *p.TraceIDHigh
+}
+func (p *Span) IsSetParentID() bool {
+	return p.ParentID != nil
+}
+
+func (p *Span) IsSetDebug() bool {
+	return p.Debug != Span_Debug_DEFAULT
+}
+
+func (p *Span) IsSetTimestamp() bool {
+	return p.Timestamp != nil
+}
+
+func (p *Span) IsSetDuration() bool {
+	return p.Duration != nil
+}
+
+func (p *Span) IsSetTraceIDHigh() bool {
+	return p.TraceIDHigh != nil
+}
+
+func (p *Span) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+		case 3:
+			if err := p.readField3(iprot); err != nil {
+				return err
+			}
+		case 4:
+			if err := p.readField4(iprot); err != nil {
+				return err
+			}
+		case 5:
+			if err := p.readField5(iprot); err != nil {
+				return err
+			}
+		case 6:
+			if err := p.readField6(iprot); err != nil {
+				return err
+			}
+		case 8:
+			if err := p.readField8(iprot); err != nil {
+				return err
+			}
+		case 9:
+			if err := p.readField9(iprot); err != nil {
+				return err
+			}
+		case 10:
+			if err := p.readField10(iprot); err != nil {
+				return err
+			}
+		case 11:
+			if err := p.readField11(iprot); err != nil {
+				return err
+			}
+		case 12:
+			if err := p.readField12(iprot); err != nil {
+				return err
+			}
+		default:
+			if err := iprot.Skip(fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	return nil
+}
+
+func (p *Span) readField1(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		p.TraceID = v
+	}
+	return nil
+}
+
+func (p *Span) readField3(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadString(); err != nil {
+		return thrift.PrependError("error reading field 3: ", err)
+	} else {
+		p.Name = v
+	}
+	return nil
+}
+
+func (p *Span) readField4(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(); err != nil {
+		return thrift.PrependError("error reading field 4: ", err)
+	} else {
+		p.ID = v
+	}
+	return nil
+}
+
+func (p *Span) readField5(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(); err != nil {
+		return thrift.PrependError("error reading field 5: ", err)
+	} else {
+		p.ParentID = &v
+	}
+	return nil
+}
+
+func (p *Span) readField6(iprot thrift.TProtocol) error {
+	_, size, err := iprot.ReadListBegin()
+	if err != nil {
+		return thrift.PrependError("error reading list begin: ", err)
+	}
+	tSlice := make([]*Annotation, 0, size)
+	p.Annotations = tSlice
+	for i := 0; i < size; i++ {
+		_elem0 := &Annotation{}
+		if err := _elem0.Read(iprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem0), err)
+		}
+		p.Annotations = append(p.Annotations, _elem0)
+	}
+	if err := iprot.ReadListEnd(); err != nil {
+		return thrift.PrependError("error reading list end: ", err)
+	}
+	return nil
+}
+
+func (p *Span) readField8(iprot thrift.TProtocol) error {
+	_, size, err := iprot.ReadListBegin()
+	if err != nil {
+		return thrift.PrependError("error reading list begin: ", err)
+	}
+	tSlice := make([]*BinaryAnnotation, 0, size)
+	p.BinaryAnnotations = tSlice
+	for i := 0; i < size; i++ {
+		_elem1 := &BinaryAnnotation{}
+		if err := _elem1.Read(iprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem1), err)
+		}
+		p.BinaryAnnotations = append(p.BinaryAnnotations, _elem1)
+	}
+	if err := iprot.ReadListEnd(); err != nil {
+		return thrift.PrependError("error reading list end: ", err)
+	}
+	return nil
+}
+
+func (p *Span) readField9(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadBool(); err != nil {
+		return thrift.PrependError("error reading field 9: ", err)
+	} else {
+		p.Debug = v
+	}
+	return nil
+}
+
+func (p *Span) readField10(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(); err != nil {
+		return thrift.PrependError("error reading field 10: ", err)
+	} else {
+		p.Timestamp = &v
+	}
+	return nil
+}
+
+func (p *Span) readField11(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(); err != nil {
+		return thrift.PrependError("error reading field 11: ", err)
+	} else {
+		p.Duration = &v
+	}
+	return nil
+}
+
+func (p *Span) readField12(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadI64(); err != nil {
+		return thrift.PrependError("error reading field 12: ", err)
+	} else {
+		p.TraceIDHigh = &v
+	}
+	return nil
+}
+
+func (p *Span) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("Span"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField3(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField4(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField5(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField6(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField8(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField9(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField10(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField11(oprot); err != nil {
+		return err
+	}
+	if err := p.writeField12(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 *Span) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("trace_id", thrift.I64, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:trace_id: ", p), err)
+	}
+	if err := oprot.WriteI64(int64(p.TraceID)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.trace_id (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:trace_id: ", p), err)
+	}
+	return err
+}
+
+func (p *Span) writeField3(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("name", thrift.STRING, 3); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 3:name: ", p), err)
+	}
+	if err := oprot.WriteString(string(p.Name)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.name (3) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 3:name: ", p), err)
+	}
+	return err
+}
+
+func (p *Span) writeField4(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("id", thrift.I64, 4); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 4:id: ", p), err)
+	}
+	if err := oprot.WriteI64(int64(p.ID)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.id (4) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 4:id: ", p), err)
+	}
+	return err
+}
+
+func (p *Span) writeField5(oprot thrift.TProtocol) (err error) {
+	if p.IsSetParentID() {
+		if err := oprot.WriteFieldBegin("parent_id", thrift.I64, 5); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 5:parent_id: ", p), err)
+		}
+		if err := oprot.WriteI64(int64(*p.ParentID)); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T.parent_id (5) field write error: ", p), err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 5:parent_id: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *Span) writeField6(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("annotations", thrift.LIST, 6); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 6:annotations: ", p), err)
+	}
+	if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Annotations)); err != nil {
+		return thrift.PrependError("error writing list begin: ", err)
+	}
+	for _, v := range p.Annotations {
+		if err := v.Write(oprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
+		}
+	}
+	if err := oprot.WriteListEnd(); err != nil {
+		return thrift.PrependError("error writing list end: ", err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 6:annotations: ", p), err)
+	}
+	return err
+}
+
+func (p *Span) writeField8(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("binary_annotations", thrift.LIST, 8); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 8:binary_annotations: ", p), err)
+	}
+	if err := oprot.WriteListBegin(thrift.STRUCT, len(p.BinaryAnnotations)); err != nil {
+		return thrift.PrependError("error writing list begin: ", err)
+	}
+	for _, v := range p.BinaryAnnotations {
+		if err := v.Write(oprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
+		}
+	}
+	if err := oprot.WriteListEnd(); err != nil {
+		return thrift.PrependError("error writing list end: ", err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 8:binary_annotations: ", p), err)
+	}
+	return err
+}
+
+func (p *Span) writeField9(oprot thrift.TProtocol) (err error) {
+	if p.IsSetDebug() {
+		if err := oprot.WriteFieldBegin("debug", thrift.BOOL, 9); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 9:debug: ", p), err)
+		}
+		if err := oprot.WriteBool(bool(p.Debug)); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T.debug (9) field write error: ", p), err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 9:debug: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *Span) writeField10(oprot thrift.TProtocol) (err error) {
+	if p.IsSetTimestamp() {
+		if err := oprot.WriteFieldBegin("timestamp", thrift.I64, 10); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 10:timestamp: ", p), err)
+		}
+		if err := oprot.WriteI64(int64(*p.Timestamp)); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T.timestamp (10) field write error: ", p), err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 10:timestamp: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *Span) writeField11(oprot thrift.TProtocol) (err error) {
+	if p.IsSetDuration() {
+		if err := oprot.WriteFieldBegin("duration", thrift.I64, 11); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 11:duration: ", p), err)
+		}
+		if err := oprot.WriteI64(int64(*p.Duration)); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T.duration (11) field write error: ", p), err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 11:duration: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *Span) writeField12(oprot thrift.TProtocol) (err error) {
+	if p.IsSetTraceIDHigh() {
+		if err := oprot.WriteFieldBegin("trace_id_high", thrift.I64, 12); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 12:trace_id_high: ", p), err)
+		}
+		if err := oprot.WriteI64(int64(*p.TraceIDHigh)); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T.trace_id_high (12) field write error: ", p), err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 12:trace_id_high: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *Span) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("Span(%+v)", *p)
+}
+
+// Attributes:
+//  - Ok
+type Response struct {
+	Ok bool `thrift:"ok,1,required" json:"ok"`
+}
+
+func NewResponse() *Response {
+	return &Response{}
+}
+
+func (p *Response) GetOk() bool {
+	return p.Ok
+}
+func (p *Response) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	var issetOk bool = false
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+			issetOk = true
+		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)
+	}
+	if !issetOk {
+		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Ok is not set"))
+	}
+	return nil
+}
+
+func (p *Response) readField1(iprot thrift.TProtocol) error {
+	if v, err := iprot.ReadBool(); err != nil {
+		return thrift.PrependError("error reading field 1: ", err)
+	} else {
+		p.Ok = v
+	}
+	return nil
+}
+
+func (p *Response) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("Response"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := oprot.WriteFieldStop(); err != nil {
+		return thrift.PrependError("write field stop error: ", err)
+	}
+	if err := oprot.WriteStructEnd(); err != nil {
+		return thrift.PrependError("write struct stop error: ", err)
+	}
+	return nil
+}
+
+func (p *Response) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("ok", thrift.BOOL, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:ok: ", p), err)
+	}
+	if err := oprot.WriteBool(bool(p.Ok)); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T.ok (1) field write error: ", p), err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:ok: ", p), err)
+	}
+	return err
+}
+
+func (p *Response) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("Response(%+v)", *p)
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift-gen/zipkincore/zipkincollector.go b/vendor/github.com/uber/jaeger-client-go/thrift-gen/zipkincore/zipkincollector.go
new file mode 100644
index 0000000..417e883
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift-gen/zipkincore/zipkincollector.go
@@ -0,0 +1,446 @@
+// Autogenerated by Thrift Compiler (0.9.3)
+// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+
+package zipkincore
+
+import (
+	"bytes"
+	"fmt"
+	"github.com/uber/jaeger-client-go/thrift"
+)
+
+// (needed to ensure safety because of naive import list construction.)
+var _ = thrift.ZERO
+var _ = fmt.Printf
+var _ = bytes.Equal
+
+type ZipkinCollector interface {
+	// Parameters:
+	//  - Spans
+	SubmitZipkinBatch(spans []*Span) (r []*Response, err error)
+}
+
+type ZipkinCollectorClient struct {
+	Transport       thrift.TTransport
+	ProtocolFactory thrift.TProtocolFactory
+	InputProtocol   thrift.TProtocol
+	OutputProtocol  thrift.TProtocol
+	SeqId           int32
+}
+
+func NewZipkinCollectorClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *ZipkinCollectorClient {
+	return &ZipkinCollectorClient{Transport: t,
+		ProtocolFactory: f,
+		InputProtocol:   f.GetProtocol(t),
+		OutputProtocol:  f.GetProtocol(t),
+		SeqId:           0,
+	}
+}
+
+func NewZipkinCollectorClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *ZipkinCollectorClient {
+	return &ZipkinCollectorClient{Transport: t,
+		ProtocolFactory: nil,
+		InputProtocol:   iprot,
+		OutputProtocol:  oprot,
+		SeqId:           0,
+	}
+}
+
+// Parameters:
+//  - Spans
+func (p *ZipkinCollectorClient) SubmitZipkinBatch(spans []*Span) (r []*Response, err error) {
+	if err = p.sendSubmitZipkinBatch(spans); err != nil {
+		return
+	}
+	return p.recvSubmitZipkinBatch()
+}
+
+func (p *ZipkinCollectorClient) sendSubmitZipkinBatch(spans []*Span) (err error) {
+	oprot := p.OutputProtocol
+	if oprot == nil {
+		oprot = p.ProtocolFactory.GetProtocol(p.Transport)
+		p.OutputProtocol = oprot
+	}
+	p.SeqId++
+	if err = oprot.WriteMessageBegin("submitZipkinBatch", thrift.CALL, p.SeqId); err != nil {
+		return
+	}
+	args := ZipkinCollectorSubmitZipkinBatchArgs{
+		Spans: spans,
+	}
+	if err = args.Write(oprot); err != nil {
+		return
+	}
+	if err = oprot.WriteMessageEnd(); err != nil {
+		return
+	}
+	return oprot.Flush()
+}
+
+func (p *ZipkinCollectorClient) recvSubmitZipkinBatch() (value []*Response, err error) {
+	iprot := p.InputProtocol
+	if iprot == nil {
+		iprot = p.ProtocolFactory.GetProtocol(p.Transport)
+		p.InputProtocol = iprot
+	}
+	method, mTypeId, seqId, err := iprot.ReadMessageBegin()
+	if err != nil {
+		return
+	}
+	if method != "submitZipkinBatch" {
+		err = thrift.NewTApplicationException(thrift.WRONG_METHOD_NAME, "submitZipkinBatch failed: wrong method name")
+		return
+	}
+	if p.SeqId != seqId {
+		err = thrift.NewTApplicationException(thrift.BAD_SEQUENCE_ID, "submitZipkinBatch failed: out of sequence response")
+		return
+	}
+	if mTypeId == thrift.EXCEPTION {
+		error2 := thrift.NewTApplicationException(thrift.UNKNOWN_APPLICATION_EXCEPTION, "Unknown Exception")
+		var error3 error
+		error3, err = error2.Read(iprot)
+		if err != nil {
+			return
+		}
+		if err = iprot.ReadMessageEnd(); err != nil {
+			return
+		}
+		err = error3
+		return
+	}
+	if mTypeId != thrift.REPLY {
+		err = thrift.NewTApplicationException(thrift.INVALID_MESSAGE_TYPE_EXCEPTION, "submitZipkinBatch failed: invalid message type")
+		return
+	}
+	result := ZipkinCollectorSubmitZipkinBatchResult{}
+	if err = result.Read(iprot); err != nil {
+		return
+	}
+	if err = iprot.ReadMessageEnd(); err != nil {
+		return
+	}
+	value = result.GetSuccess()
+	return
+}
+
+type ZipkinCollectorProcessor struct {
+	processorMap map[string]thrift.TProcessorFunction
+	handler      ZipkinCollector
+}
+
+func (p *ZipkinCollectorProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) {
+	p.processorMap[key] = processor
+}
+
+func (p *ZipkinCollectorProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) {
+	processor, ok = p.processorMap[key]
+	return processor, ok
+}
+
+func (p *ZipkinCollectorProcessor) ProcessorMap() map[string]thrift.TProcessorFunction {
+	return p.processorMap
+}
+
+func NewZipkinCollectorProcessor(handler ZipkinCollector) *ZipkinCollectorProcessor {
+
+	self4 := &ZipkinCollectorProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)}
+	self4.processorMap["submitZipkinBatch"] = &zipkinCollectorProcessorSubmitZipkinBatch{handler: handler}
+	return self4
+}
+
+func (p *ZipkinCollectorProcessor) Process(iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
+	name, _, seqId, err := iprot.ReadMessageBegin()
+	if err != nil {
+		return false, err
+	}
+	if processor, ok := p.GetProcessorFunction(name); ok {
+		return processor.Process(seqId, iprot, oprot)
+	}
+	iprot.Skip(thrift.STRUCT)
+	iprot.ReadMessageEnd()
+	x5 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function "+name)
+	oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId)
+	x5.Write(oprot)
+	oprot.WriteMessageEnd()
+	oprot.Flush()
+	return false, x5
+
+}
+
+type zipkinCollectorProcessorSubmitZipkinBatch struct {
+	handler ZipkinCollector
+}
+
+func (p *zipkinCollectorProcessorSubmitZipkinBatch) Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
+	args := ZipkinCollectorSubmitZipkinBatchArgs{}
+	if err = args.Read(iprot); err != nil {
+		iprot.ReadMessageEnd()
+		x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error())
+		oprot.WriteMessageBegin("submitZipkinBatch", thrift.EXCEPTION, seqId)
+		x.Write(oprot)
+		oprot.WriteMessageEnd()
+		oprot.Flush()
+		return false, err
+	}
+
+	iprot.ReadMessageEnd()
+	result := ZipkinCollectorSubmitZipkinBatchResult{}
+	var retval []*Response
+	var err2 error
+	if retval, err2 = p.handler.SubmitZipkinBatch(args.Spans); err2 != nil {
+		x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing submitZipkinBatch: "+err2.Error())
+		oprot.WriteMessageBegin("submitZipkinBatch", thrift.EXCEPTION, seqId)
+		x.Write(oprot)
+		oprot.WriteMessageEnd()
+		oprot.Flush()
+		return true, err2
+	} else {
+		result.Success = retval
+	}
+	if err2 = oprot.WriteMessageBegin("submitZipkinBatch", thrift.REPLY, seqId); err2 != nil {
+		err = err2
+	}
+	if err2 = result.Write(oprot); err == nil && err2 != nil {
+		err = err2
+	}
+	if err2 = oprot.WriteMessageEnd(); err == nil && err2 != nil {
+		err = err2
+	}
+	if err2 = oprot.Flush(); err == nil && err2 != nil {
+		err = err2
+	}
+	if err != nil {
+		return
+	}
+	return true, err
+}
+
+// HELPER FUNCTIONS AND STRUCTURES
+
+// Attributes:
+//  - Spans
+type ZipkinCollectorSubmitZipkinBatchArgs struct {
+	Spans []*Span `thrift:"spans,1" json:"spans"`
+}
+
+func NewZipkinCollectorSubmitZipkinBatchArgs() *ZipkinCollectorSubmitZipkinBatchArgs {
+	return &ZipkinCollectorSubmitZipkinBatchArgs{}
+}
+
+func (p *ZipkinCollectorSubmitZipkinBatchArgs) GetSpans() []*Span {
+	return p.Spans
+}
+func (p *ZipkinCollectorSubmitZipkinBatchArgs) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 1:
+			if err := p.readField1(iprot); err != nil {
+				return err
+			}
+		default:
+			if err := iprot.Skip(fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	return nil
+}
+
+func (p *ZipkinCollectorSubmitZipkinBatchArgs) readField1(iprot thrift.TProtocol) error {
+	_, size, err := iprot.ReadListBegin()
+	if err != nil {
+		return thrift.PrependError("error reading list begin: ", err)
+	}
+	tSlice := make([]*Span, 0, size)
+	p.Spans = tSlice
+	for i := 0; i < size; i++ {
+		_elem6 := &Span{}
+		if err := _elem6.Read(iprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem6), err)
+		}
+		p.Spans = append(p.Spans, _elem6)
+	}
+	if err := iprot.ReadListEnd(); err != nil {
+		return thrift.PrependError("error reading list end: ", err)
+	}
+	return nil
+}
+
+func (p *ZipkinCollectorSubmitZipkinBatchArgs) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("submitZipkinBatch_args"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField1(oprot); err != nil {
+		return err
+	}
+	if err := 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 *ZipkinCollectorSubmitZipkinBatchArgs) writeField1(oprot thrift.TProtocol) (err error) {
+	if err := oprot.WriteFieldBegin("spans", thrift.LIST, 1); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:spans: ", p), err)
+	}
+	if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Spans)); err != nil {
+		return thrift.PrependError("error writing list begin: ", err)
+	}
+	for _, v := range p.Spans {
+		if err := v.Write(oprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
+		}
+	}
+	if err := oprot.WriteListEnd(); err != nil {
+		return thrift.PrependError("error writing list end: ", err)
+	}
+	if err := oprot.WriteFieldEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:spans: ", p), err)
+	}
+	return err
+}
+
+func (p *ZipkinCollectorSubmitZipkinBatchArgs) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("ZipkinCollectorSubmitZipkinBatchArgs(%+v)", *p)
+}
+
+// Attributes:
+//  - Success
+type ZipkinCollectorSubmitZipkinBatchResult struct {
+	Success []*Response `thrift:"success,0" json:"success,omitempty"`
+}
+
+func NewZipkinCollectorSubmitZipkinBatchResult() *ZipkinCollectorSubmitZipkinBatchResult {
+	return &ZipkinCollectorSubmitZipkinBatchResult{}
+}
+
+var ZipkinCollectorSubmitZipkinBatchResult_Success_DEFAULT []*Response
+
+func (p *ZipkinCollectorSubmitZipkinBatchResult) GetSuccess() []*Response {
+	return p.Success
+}
+func (p *ZipkinCollectorSubmitZipkinBatchResult) IsSetSuccess() bool {
+	return p.Success != nil
+}
+
+func (p *ZipkinCollectorSubmitZipkinBatchResult) Read(iprot thrift.TProtocol) error {
+	if _, err := iprot.ReadStructBegin(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
+	}
+
+	for {
+		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
+		}
+		if fieldTypeId == thrift.STOP {
+			break
+		}
+		switch fieldId {
+		case 0:
+			if err := p.readField0(iprot); err != nil {
+				return err
+			}
+		default:
+			if err := iprot.Skip(fieldTypeId); err != nil {
+				return err
+			}
+		}
+		if err := iprot.ReadFieldEnd(); err != nil {
+			return err
+		}
+	}
+	if err := iprot.ReadStructEnd(); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
+	}
+	return nil
+}
+
+func (p *ZipkinCollectorSubmitZipkinBatchResult) readField0(iprot thrift.TProtocol) error {
+	_, size, err := iprot.ReadListBegin()
+	if err != nil {
+		return thrift.PrependError("error reading list begin: ", err)
+	}
+	tSlice := make([]*Response, 0, size)
+	p.Success = tSlice
+	for i := 0; i < size; i++ {
+		_elem7 := &Response{}
+		if err := _elem7.Read(iprot); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem7), err)
+		}
+		p.Success = append(p.Success, _elem7)
+	}
+	if err := iprot.ReadListEnd(); err != nil {
+		return thrift.PrependError("error reading list end: ", err)
+	}
+	return nil
+}
+
+func (p *ZipkinCollectorSubmitZipkinBatchResult) Write(oprot thrift.TProtocol) error {
+	if err := oprot.WriteStructBegin("submitZipkinBatch_result"); err != nil {
+		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
+	}
+	if err := p.writeField0(oprot); err != nil {
+		return err
+	}
+	if err := oprot.WriteFieldStop(); err != nil {
+		return thrift.PrependError("write field stop error: ", err)
+	}
+	if err := oprot.WriteStructEnd(); err != nil {
+		return thrift.PrependError("write struct stop error: ", err)
+	}
+	return nil
+}
+
+func (p *ZipkinCollectorSubmitZipkinBatchResult) writeField0(oprot thrift.TProtocol) (err error) {
+	if p.IsSetSuccess() {
+		if err := oprot.WriteFieldBegin("success", thrift.LIST, 0); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field begin error 0:success: ", p), err)
+		}
+		if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Success)); err != nil {
+			return thrift.PrependError("error writing list begin: ", err)
+		}
+		for _, v := range p.Success {
+			if err := v.Write(oprot); err != nil {
+				return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
+			}
+		}
+		if err := oprot.WriteListEnd(); err != nil {
+			return thrift.PrependError("error writing list end: ", err)
+		}
+		if err := oprot.WriteFieldEnd(); err != nil {
+			return thrift.PrependError(fmt.Sprintf("%T write field end error 0:success: ", p), err)
+		}
+	}
+	return err
+}
+
+func (p *ZipkinCollectorSubmitZipkinBatchResult) String() string {
+	if p == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("ZipkinCollectorSubmitZipkinBatchResult(%+v)", *p)
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift/.nocover b/vendor/github.com/uber/jaeger-client-go/thrift/.nocover
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift/.nocover
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift/README.md b/vendor/github.com/uber/jaeger-client-go/thrift/README.md
new file mode 100644
index 0000000..1d8e642
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift/README.md
@@ -0,0 +1,7 @@
+# Apache Thrift
+
+This is a partial copy of Apache Thrift v0.10 (https://github.com/apache/thrift/commit/b2a4d4ae21c789b689dd162deb819665567f481c).
+
+It is vendored code to avoid compatibility issues introduced in Thrift  v0.11.
+
+See https://github.com/jaegertracing/jaeger-client-go/pull/303.
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift/application_exception.go b/vendor/github.com/uber/jaeger-client-go/thrift/application_exception.go
new file mode 100644
index 0000000..6655cc5
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift/application_exception.go
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+const (
+	UNKNOWN_APPLICATION_EXCEPTION  = 0
+	UNKNOWN_METHOD                 = 1
+	INVALID_MESSAGE_TYPE_EXCEPTION = 2
+	WRONG_METHOD_NAME              = 3
+	BAD_SEQUENCE_ID                = 4
+	MISSING_RESULT                 = 5
+	INTERNAL_ERROR                 = 6
+	PROTOCOL_ERROR                 = 7
+)
+
+// Application level Thrift exception
+type TApplicationException interface {
+	TException
+	TypeId() int32
+	Read(iprot TProtocol) (TApplicationException, error)
+	Write(oprot TProtocol) error
+}
+
+type tApplicationException struct {
+	message string
+	type_   int32
+}
+
+func (e tApplicationException) Error() string {
+	return e.message
+}
+
+func NewTApplicationException(type_ int32, message string) TApplicationException {
+	return &tApplicationException{message, type_}
+}
+
+func (p *tApplicationException) TypeId() int32 {
+	return p.type_
+}
+
+func (p *tApplicationException) Read(iprot TProtocol) (TApplicationException, error) {
+	_, err := iprot.ReadStructBegin()
+	if err != nil {
+		return nil, err
+	}
+
+	message := ""
+	type_ := int32(UNKNOWN_APPLICATION_EXCEPTION)
+
+	for {
+		_, ttype, id, err := iprot.ReadFieldBegin()
+		if err != nil {
+			return nil, err
+		}
+		if ttype == STOP {
+			break
+		}
+		switch id {
+		case 1:
+			if ttype == STRING {
+				if message, err = iprot.ReadString(); err != nil {
+					return nil, err
+				}
+			} else {
+				if err = SkipDefaultDepth(iprot, ttype); err != nil {
+					return nil, err
+				}
+			}
+		case 2:
+			if ttype == I32 {
+				if type_, err = iprot.ReadI32(); err != nil {
+					return nil, err
+				}
+			} else {
+				if err = SkipDefaultDepth(iprot, ttype); err != nil {
+					return nil, err
+				}
+			}
+		default:
+			if err = SkipDefaultDepth(iprot, ttype); err != nil {
+				return nil, err
+			}
+		}
+		if err = iprot.ReadFieldEnd(); err != nil {
+			return nil, err
+		}
+	}
+	return NewTApplicationException(type_, message), iprot.ReadStructEnd()
+}
+
+func (p *tApplicationException) Write(oprot TProtocol) (err error) {
+	err = oprot.WriteStructBegin("TApplicationException")
+	if len(p.Error()) > 0 {
+		err = oprot.WriteFieldBegin("message", STRING, 1)
+		if err != nil {
+			return
+		}
+		err = oprot.WriteString(p.Error())
+		if err != nil {
+			return
+		}
+		err = oprot.WriteFieldEnd()
+		if err != nil {
+			return
+		}
+	}
+	err = oprot.WriteFieldBegin("type", I32, 2)
+	if err != nil {
+		return
+	}
+	err = oprot.WriteI32(p.type_)
+	if err != nil {
+		return
+	}
+	err = oprot.WriteFieldEnd()
+	if err != nil {
+		return
+	}
+	err = oprot.WriteFieldStop()
+	if err != nil {
+		return
+	}
+	err = oprot.WriteStructEnd()
+	return
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift/binary_protocol.go b/vendor/github.com/uber/jaeger-client-go/thrift/binary_protocol.go
new file mode 100644
index 0000000..690d341
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift/binary_protocol.go
@@ -0,0 +1,514 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+	"bytes"
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"io"
+	"math"
+)
+
+type TBinaryProtocol struct {
+	trans         TRichTransport
+	origTransport TTransport
+	reader        io.Reader
+	writer        io.Writer
+	strictRead    bool
+	strictWrite   bool
+	buffer        [64]byte
+}
+
+type TBinaryProtocolFactory struct {
+	strictRead  bool
+	strictWrite bool
+}
+
+func NewTBinaryProtocolTransport(t TTransport) *TBinaryProtocol {
+	return NewTBinaryProtocol(t, false, true)
+}
+
+func NewTBinaryProtocol(t TTransport, strictRead, strictWrite bool) *TBinaryProtocol {
+	p := &TBinaryProtocol{origTransport: t, strictRead: strictRead, strictWrite: strictWrite}
+	if et, ok := t.(TRichTransport); ok {
+		p.trans = et
+	} else {
+		p.trans = NewTRichTransport(t)
+	}
+	p.reader = p.trans
+	p.writer = p.trans
+	return p
+}
+
+func NewTBinaryProtocolFactoryDefault() *TBinaryProtocolFactory {
+	return NewTBinaryProtocolFactory(false, true)
+}
+
+func NewTBinaryProtocolFactory(strictRead, strictWrite bool) *TBinaryProtocolFactory {
+	return &TBinaryProtocolFactory{strictRead: strictRead, strictWrite: strictWrite}
+}
+
+func (p *TBinaryProtocolFactory) GetProtocol(t TTransport) TProtocol {
+	return NewTBinaryProtocol(t, p.strictRead, p.strictWrite)
+}
+
+/**
+ * Writing Methods
+ */
+
+func (p *TBinaryProtocol) WriteMessageBegin(name string, typeId TMessageType, seqId int32) error {
+	if p.strictWrite {
+		version := uint32(VERSION_1) | uint32(typeId)
+		e := p.WriteI32(int32(version))
+		if e != nil {
+			return e
+		}
+		e = p.WriteString(name)
+		if e != nil {
+			return e
+		}
+		e = p.WriteI32(seqId)
+		return e
+	} else {
+		e := p.WriteString(name)
+		if e != nil {
+			return e
+		}
+		e = p.WriteByte(int8(typeId))
+		if e != nil {
+			return e
+		}
+		e = p.WriteI32(seqId)
+		return e
+	}
+	return nil
+}
+
+func (p *TBinaryProtocol) WriteMessageEnd() error {
+	return nil
+}
+
+func (p *TBinaryProtocol) WriteStructBegin(name string) error {
+	return nil
+}
+
+func (p *TBinaryProtocol) WriteStructEnd() error {
+	return nil
+}
+
+func (p *TBinaryProtocol) WriteFieldBegin(name string, typeId TType, id int16) error {
+	e := p.WriteByte(int8(typeId))
+	if e != nil {
+		return e
+	}
+	e = p.WriteI16(id)
+	return e
+}
+
+func (p *TBinaryProtocol) WriteFieldEnd() error {
+	return nil
+}
+
+func (p *TBinaryProtocol) WriteFieldStop() error {
+	e := p.WriteByte(STOP)
+	return e
+}
+
+func (p *TBinaryProtocol) WriteMapBegin(keyType TType, valueType TType, size int) error {
+	e := p.WriteByte(int8(keyType))
+	if e != nil {
+		return e
+	}
+	e = p.WriteByte(int8(valueType))
+	if e != nil {
+		return e
+	}
+	e = p.WriteI32(int32(size))
+	return e
+}
+
+func (p *TBinaryProtocol) WriteMapEnd() error {
+	return nil
+}
+
+func (p *TBinaryProtocol) WriteListBegin(elemType TType, size int) error {
+	e := p.WriteByte(int8(elemType))
+	if e != nil {
+		return e
+	}
+	e = p.WriteI32(int32(size))
+	return e
+}
+
+func (p *TBinaryProtocol) WriteListEnd() error {
+	return nil
+}
+
+func (p *TBinaryProtocol) WriteSetBegin(elemType TType, size int) error {
+	e := p.WriteByte(int8(elemType))
+	if e != nil {
+		return e
+	}
+	e = p.WriteI32(int32(size))
+	return e
+}
+
+func (p *TBinaryProtocol) WriteSetEnd() error {
+	return nil
+}
+
+func (p *TBinaryProtocol) WriteBool(value bool) error {
+	if value {
+		return p.WriteByte(1)
+	}
+	return p.WriteByte(0)
+}
+
+func (p *TBinaryProtocol) WriteByte(value int8) error {
+	e := p.trans.WriteByte(byte(value))
+	return NewTProtocolException(e)
+}
+
+func (p *TBinaryProtocol) WriteI16(value int16) error {
+	v := p.buffer[0:2]
+	binary.BigEndian.PutUint16(v, uint16(value))
+	_, e := p.writer.Write(v)
+	return NewTProtocolException(e)
+}
+
+func (p *TBinaryProtocol) WriteI32(value int32) error {
+	v := p.buffer[0:4]
+	binary.BigEndian.PutUint32(v, uint32(value))
+	_, e := p.writer.Write(v)
+	return NewTProtocolException(e)
+}
+
+func (p *TBinaryProtocol) WriteI64(value int64) error {
+	v := p.buffer[0:8]
+	binary.BigEndian.PutUint64(v, uint64(value))
+	_, err := p.writer.Write(v)
+	return NewTProtocolException(err)
+}
+
+func (p *TBinaryProtocol) WriteDouble(value float64) error {
+	return p.WriteI64(int64(math.Float64bits(value)))
+}
+
+func (p *TBinaryProtocol) WriteString(value string) error {
+	e := p.WriteI32(int32(len(value)))
+	if e != nil {
+		return e
+	}
+	_, err := p.trans.WriteString(value)
+	return NewTProtocolException(err)
+}
+
+func (p *TBinaryProtocol) WriteBinary(value []byte) error {
+	e := p.WriteI32(int32(len(value)))
+	if e != nil {
+		return e
+	}
+	_, err := p.writer.Write(value)
+	return NewTProtocolException(err)
+}
+
+/**
+ * Reading methods
+ */
+
+func (p *TBinaryProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err error) {
+	size, e := p.ReadI32()
+	if e != nil {
+		return "", typeId, 0, NewTProtocolException(e)
+	}
+	if size < 0 {
+		typeId = TMessageType(size & 0x0ff)
+		version := int64(int64(size) & VERSION_MASK)
+		if version != VERSION_1 {
+			return name, typeId, seqId, NewTProtocolExceptionWithType(BAD_VERSION, fmt.Errorf("Bad version in ReadMessageBegin"))
+		}
+		name, e = p.ReadString()
+		if e != nil {
+			return name, typeId, seqId, NewTProtocolException(e)
+		}
+		seqId, e = p.ReadI32()
+		if e != nil {
+			return name, typeId, seqId, NewTProtocolException(e)
+		}
+		return name, typeId, seqId, nil
+	}
+	if p.strictRead {
+		return name, typeId, seqId, NewTProtocolExceptionWithType(BAD_VERSION, fmt.Errorf("Missing version in ReadMessageBegin"))
+	}
+	name, e2 := p.readStringBody(size)
+	if e2 != nil {
+		return name, typeId, seqId, e2
+	}
+	b, e3 := p.ReadByte()
+	if e3 != nil {
+		return name, typeId, seqId, e3
+	}
+	typeId = TMessageType(b)
+	seqId, e4 := p.ReadI32()
+	if e4 != nil {
+		return name, typeId, seqId, e4
+	}
+	return name, typeId, seqId, nil
+}
+
+func (p *TBinaryProtocol) ReadMessageEnd() error {
+	return nil
+}
+
+func (p *TBinaryProtocol) ReadStructBegin() (name string, err error) {
+	return
+}
+
+func (p *TBinaryProtocol) ReadStructEnd() error {
+	return nil
+}
+
+func (p *TBinaryProtocol) ReadFieldBegin() (name string, typeId TType, seqId int16, err error) {
+	t, err := p.ReadByte()
+	typeId = TType(t)
+	if err != nil {
+		return name, typeId, seqId, err
+	}
+	if t != STOP {
+		seqId, err = p.ReadI16()
+	}
+	return name, typeId, seqId, err
+}
+
+func (p *TBinaryProtocol) ReadFieldEnd() error {
+	return nil
+}
+
+var invalidDataLength = NewTProtocolExceptionWithType(INVALID_DATA, errors.New("Invalid data length"))
+
+func (p *TBinaryProtocol) ReadMapBegin() (kType, vType TType, size int, err error) {
+	k, e := p.ReadByte()
+	if e != nil {
+		err = NewTProtocolException(e)
+		return
+	}
+	kType = TType(k)
+	v, e := p.ReadByte()
+	if e != nil {
+		err = NewTProtocolException(e)
+		return
+	}
+	vType = TType(v)
+	size32, e := p.ReadI32()
+	if e != nil {
+		err = NewTProtocolException(e)
+		return
+	}
+	if size32 < 0 {
+		err = invalidDataLength
+		return
+	}
+	size = int(size32)
+	return kType, vType, size, nil
+}
+
+func (p *TBinaryProtocol) ReadMapEnd() error {
+	return nil
+}
+
+func (p *TBinaryProtocol) ReadListBegin() (elemType TType, size int, err error) {
+	b, e := p.ReadByte()
+	if e != nil {
+		err = NewTProtocolException(e)
+		return
+	}
+	elemType = TType(b)
+	size32, e := p.ReadI32()
+	if e != nil {
+		err = NewTProtocolException(e)
+		return
+	}
+	if size32 < 0 {
+		err = invalidDataLength
+		return
+	}
+	size = int(size32)
+
+	return
+}
+
+func (p *TBinaryProtocol) ReadListEnd() error {
+	return nil
+}
+
+func (p *TBinaryProtocol) ReadSetBegin() (elemType TType, size int, err error) {
+	b, e := p.ReadByte()
+	if e != nil {
+		err = NewTProtocolException(e)
+		return
+	}
+	elemType = TType(b)
+	size32, e := p.ReadI32()
+	if e != nil {
+		err = NewTProtocolException(e)
+		return
+	}
+	if size32 < 0 {
+		err = invalidDataLength
+		return
+	}
+	size = int(size32)
+	return elemType, size, nil
+}
+
+func (p *TBinaryProtocol) ReadSetEnd() error {
+	return nil
+}
+
+func (p *TBinaryProtocol) ReadBool() (bool, error) {
+	b, e := p.ReadByte()
+	v := true
+	if b != 1 {
+		v = false
+	}
+	return v, e
+}
+
+func (p *TBinaryProtocol) ReadByte() (int8, error) {
+	v, err := p.trans.ReadByte()
+	return int8(v), err
+}
+
+func (p *TBinaryProtocol) ReadI16() (value int16, err error) {
+	buf := p.buffer[0:2]
+	err = p.readAll(buf)
+	value = int16(binary.BigEndian.Uint16(buf))
+	return value, err
+}
+
+func (p *TBinaryProtocol) ReadI32() (value int32, err error) {
+	buf := p.buffer[0:4]
+	err = p.readAll(buf)
+	value = int32(binary.BigEndian.Uint32(buf))
+	return value, err
+}
+
+func (p *TBinaryProtocol) ReadI64() (value int64, err error) {
+	buf := p.buffer[0:8]
+	err = p.readAll(buf)
+	value = int64(binary.BigEndian.Uint64(buf))
+	return value, err
+}
+
+func (p *TBinaryProtocol) ReadDouble() (value float64, err error) {
+	buf := p.buffer[0:8]
+	err = p.readAll(buf)
+	value = math.Float64frombits(binary.BigEndian.Uint64(buf))
+	return value, err
+}
+
+func (p *TBinaryProtocol) ReadString() (value string, err error) {
+	size, e := p.ReadI32()
+	if e != nil {
+		return "", e
+	}
+	if size < 0 {
+		err = invalidDataLength
+		return
+	}
+
+	return p.readStringBody(size)
+}
+
+func (p *TBinaryProtocol) ReadBinary() ([]byte, error) {
+	size, e := p.ReadI32()
+	if e != nil {
+		return nil, e
+	}
+	if size < 0 {
+		return nil, invalidDataLength
+	}
+	if uint64(size) > p.trans.RemainingBytes() {
+		return nil, invalidDataLength
+	}
+
+	isize := int(size)
+	buf := make([]byte, isize)
+	_, err := io.ReadFull(p.trans, buf)
+	return buf, NewTProtocolException(err)
+}
+
+func (p *TBinaryProtocol) Flush() (err error) {
+	return NewTProtocolException(p.trans.Flush())
+}
+
+func (p *TBinaryProtocol) Skip(fieldType TType) (err error) {
+	return SkipDefaultDepth(p, fieldType)
+}
+
+func (p *TBinaryProtocol) Transport() TTransport {
+	return p.origTransport
+}
+
+func (p *TBinaryProtocol) readAll(buf []byte) error {
+	_, err := io.ReadFull(p.reader, buf)
+	return NewTProtocolException(err)
+}
+
+const readLimit = 32768
+
+func (p *TBinaryProtocol) readStringBody(size int32) (value string, err error) {
+	if size < 0 {
+		return "", nil
+	}
+	if uint64(size) > p.trans.RemainingBytes() {
+		return "", invalidDataLength
+	}
+
+	var (
+		buf bytes.Buffer
+		e   error
+		b   []byte
+	)
+
+	switch {
+	case int(size) <= len(p.buffer):
+		b = p.buffer[:size] // avoids allocation for small reads
+	case int(size) < readLimit:
+		b = make([]byte, size)
+	default:
+		b = make([]byte, readLimit)
+	}
+
+	for size > 0 {
+		_, e = io.ReadFull(p.trans, b)
+		buf.Write(b)
+		if e != nil {
+			break
+		}
+		size -= readLimit
+		if size < readLimit && size > 0 {
+			b = b[:size]
+		}
+	}
+	return buf.String(), NewTProtocolException(e)
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift/compact_protocol.go b/vendor/github.com/uber/jaeger-client-go/thrift/compact_protocol.go
new file mode 100644
index 0000000..b9299f2
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift/compact_protocol.go
@@ -0,0 +1,815 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+	"encoding/binary"
+	"fmt"
+	"io"
+	"math"
+)
+
+const (
+	COMPACT_PROTOCOL_ID       = 0x082
+	COMPACT_VERSION           = 1
+	COMPACT_VERSION_MASK      = 0x1f
+	COMPACT_TYPE_MASK         = 0x0E0
+	COMPACT_TYPE_BITS         = 0x07
+	COMPACT_TYPE_SHIFT_AMOUNT = 5
+)
+
+type tCompactType byte
+
+const (
+	COMPACT_BOOLEAN_TRUE  = 0x01
+	COMPACT_BOOLEAN_FALSE = 0x02
+	COMPACT_BYTE          = 0x03
+	COMPACT_I16           = 0x04
+	COMPACT_I32           = 0x05
+	COMPACT_I64           = 0x06
+	COMPACT_DOUBLE        = 0x07
+	COMPACT_BINARY        = 0x08
+	COMPACT_LIST          = 0x09
+	COMPACT_SET           = 0x0A
+	COMPACT_MAP           = 0x0B
+	COMPACT_STRUCT        = 0x0C
+)
+
+var (
+	ttypeToCompactType map[TType]tCompactType
+)
+
+func init() {
+	ttypeToCompactType = map[TType]tCompactType{
+		STOP:   STOP,
+		BOOL:   COMPACT_BOOLEAN_TRUE,
+		BYTE:   COMPACT_BYTE,
+		I16:    COMPACT_I16,
+		I32:    COMPACT_I32,
+		I64:    COMPACT_I64,
+		DOUBLE: COMPACT_DOUBLE,
+		STRING: COMPACT_BINARY,
+		LIST:   COMPACT_LIST,
+		SET:    COMPACT_SET,
+		MAP:    COMPACT_MAP,
+		STRUCT: COMPACT_STRUCT,
+	}
+}
+
+type TCompactProtocolFactory struct{}
+
+func NewTCompactProtocolFactory() *TCompactProtocolFactory {
+	return &TCompactProtocolFactory{}
+}
+
+func (p *TCompactProtocolFactory) GetProtocol(trans TTransport) TProtocol {
+	return NewTCompactProtocol(trans)
+}
+
+type TCompactProtocol struct {
+	trans         TRichTransport
+	origTransport TTransport
+
+	// Used to keep track of the last field for the current and previous structs,
+	// so we can do the delta stuff.
+	lastField   []int
+	lastFieldId int
+
+	// If we encounter a boolean field begin, save the TField here so it can
+	// have the value incorporated.
+	booleanFieldName    string
+	booleanFieldId      int16
+	booleanFieldPending bool
+
+	// If we read a field header, and it's a boolean field, save the boolean
+	// value here so that readBool can use it.
+	boolValue          bool
+	boolValueIsNotNull bool
+	buffer             [64]byte
+}
+
+// Create a TCompactProtocol given a TTransport
+func NewTCompactProtocol(trans TTransport) *TCompactProtocol {
+	p := &TCompactProtocol{origTransport: trans, lastField: []int{}}
+	if et, ok := trans.(TRichTransport); ok {
+		p.trans = et
+	} else {
+		p.trans = NewTRichTransport(trans)
+	}
+
+	return p
+
+}
+
+//
+// Public Writing methods.
+//
+
+// Write a message header to the wire. Compact Protocol messages contain the
+// protocol version so we can migrate forwards in the future if need be.
+func (p *TCompactProtocol) WriteMessageBegin(name string, typeId TMessageType, seqid int32) error {
+	err := p.writeByteDirect(COMPACT_PROTOCOL_ID)
+	if err != nil {
+		return NewTProtocolException(err)
+	}
+	err = p.writeByteDirect((COMPACT_VERSION & COMPACT_VERSION_MASK) | ((byte(typeId) << COMPACT_TYPE_SHIFT_AMOUNT) & COMPACT_TYPE_MASK))
+	if err != nil {
+		return NewTProtocolException(err)
+	}
+	_, err = p.writeVarint32(seqid)
+	if err != nil {
+		return NewTProtocolException(err)
+	}
+	e := p.WriteString(name)
+	return e
+
+}
+
+func (p *TCompactProtocol) WriteMessageEnd() error { return nil }
+
+// Write a struct begin. This doesn't actually put anything on the wire. We
+// use it as an opportunity to put special placeholder markers on the field
+// stack so we can get the field id deltas correct.
+func (p *TCompactProtocol) WriteStructBegin(name string) error {
+	p.lastField = append(p.lastField, p.lastFieldId)
+	p.lastFieldId = 0
+	return nil
+}
+
+// Write a struct end. This doesn't actually put anything on the wire. We use
+// this as an opportunity to pop the last field from the current struct off
+// of the field stack.
+func (p *TCompactProtocol) WriteStructEnd() error {
+	p.lastFieldId = p.lastField[len(p.lastField)-1]
+	p.lastField = p.lastField[:len(p.lastField)-1]
+	return nil
+}
+
+func (p *TCompactProtocol) WriteFieldBegin(name string, typeId TType, id int16) error {
+	if typeId == BOOL {
+		// we want to possibly include the value, so we'll wait.
+		p.booleanFieldName, p.booleanFieldId, p.booleanFieldPending = name, id, true
+		return nil
+	}
+	_, err := p.writeFieldBeginInternal(name, typeId, id, 0xFF)
+	return NewTProtocolException(err)
+}
+
+// The workhorse of writeFieldBegin. It has the option of doing a
+// 'type override' of the type header. This is used specifically in the
+// boolean field case.
+func (p *TCompactProtocol) writeFieldBeginInternal(name string, typeId TType, id int16, typeOverride byte) (int, error) {
+	// short lastField = lastField_.pop();
+
+	// if there's a type override, use that.
+	var typeToWrite byte
+	if typeOverride == 0xFF {
+		typeToWrite = byte(p.getCompactType(typeId))
+	} else {
+		typeToWrite = typeOverride
+	}
+	// check if we can use delta encoding for the field id
+	fieldId := int(id)
+	written := 0
+	if fieldId > p.lastFieldId && fieldId-p.lastFieldId <= 15 {
+		// write them together
+		err := p.writeByteDirect(byte((fieldId-p.lastFieldId)<<4) | typeToWrite)
+		if err != nil {
+			return 0, err
+		}
+	} else {
+		// write them separate
+		err := p.writeByteDirect(typeToWrite)
+		if err != nil {
+			return 0, err
+		}
+		err = p.WriteI16(id)
+		written = 1 + 2
+		if err != nil {
+			return 0, err
+		}
+	}
+
+	p.lastFieldId = fieldId
+	// p.lastField.Push(field.id);
+	return written, nil
+}
+
+func (p *TCompactProtocol) WriteFieldEnd() error { return nil }
+
+func (p *TCompactProtocol) WriteFieldStop() error {
+	err := p.writeByteDirect(STOP)
+	return NewTProtocolException(err)
+}
+
+func (p *TCompactProtocol) WriteMapBegin(keyType TType, valueType TType, size int) error {
+	if size == 0 {
+		err := p.writeByteDirect(0)
+		return NewTProtocolException(err)
+	}
+	_, err := p.writeVarint32(int32(size))
+	if err != nil {
+		return NewTProtocolException(err)
+	}
+	err = p.writeByteDirect(byte(p.getCompactType(keyType))<<4 | byte(p.getCompactType(valueType)))
+	return NewTProtocolException(err)
+}
+
+func (p *TCompactProtocol) WriteMapEnd() error { return nil }
+
+// Write a list header.
+func (p *TCompactProtocol) WriteListBegin(elemType TType, size int) error {
+	_, err := p.writeCollectionBegin(elemType, size)
+	return NewTProtocolException(err)
+}
+
+func (p *TCompactProtocol) WriteListEnd() error { return nil }
+
+// Write a set header.
+func (p *TCompactProtocol) WriteSetBegin(elemType TType, size int) error {
+	_, err := p.writeCollectionBegin(elemType, size)
+	return NewTProtocolException(err)
+}
+
+func (p *TCompactProtocol) WriteSetEnd() error { return nil }
+
+func (p *TCompactProtocol) WriteBool(value bool) error {
+	v := byte(COMPACT_BOOLEAN_FALSE)
+	if value {
+		v = byte(COMPACT_BOOLEAN_TRUE)
+	}
+	if p.booleanFieldPending {
+		// we haven't written the field header yet
+		_, err := p.writeFieldBeginInternal(p.booleanFieldName, BOOL, p.booleanFieldId, v)
+		p.booleanFieldPending = false
+		return NewTProtocolException(err)
+	}
+	// we're not part of a field, so just write the value.
+	err := p.writeByteDirect(v)
+	return NewTProtocolException(err)
+}
+
+// Write a byte. Nothing to see here!
+func (p *TCompactProtocol) WriteByte(value int8) error {
+	err := p.writeByteDirect(byte(value))
+	return NewTProtocolException(err)
+}
+
+// Write an I16 as a zigzag varint.
+func (p *TCompactProtocol) WriteI16(value int16) error {
+	_, err := p.writeVarint32(p.int32ToZigzag(int32(value)))
+	return NewTProtocolException(err)
+}
+
+// Write an i32 as a zigzag varint.
+func (p *TCompactProtocol) WriteI32(value int32) error {
+	_, err := p.writeVarint32(p.int32ToZigzag(value))
+	return NewTProtocolException(err)
+}
+
+// Write an i64 as a zigzag varint.
+func (p *TCompactProtocol) WriteI64(value int64) error {
+	_, err := p.writeVarint64(p.int64ToZigzag(value))
+	return NewTProtocolException(err)
+}
+
+// Write a double to the wire as 8 bytes.
+func (p *TCompactProtocol) WriteDouble(value float64) error {
+	buf := p.buffer[0:8]
+	binary.LittleEndian.PutUint64(buf, math.Float64bits(value))
+	_, err := p.trans.Write(buf)
+	return NewTProtocolException(err)
+}
+
+// Write a string to the wire with a varint size preceding.
+func (p *TCompactProtocol) WriteString(value string) error {
+	_, e := p.writeVarint32(int32(len(value)))
+	if e != nil {
+		return NewTProtocolException(e)
+	}
+	if len(value) > 0 {
+	}
+	_, e = p.trans.WriteString(value)
+	return e
+}
+
+// Write a byte array, using a varint for the size.
+func (p *TCompactProtocol) WriteBinary(bin []byte) error {
+	_, e := p.writeVarint32(int32(len(bin)))
+	if e != nil {
+		return NewTProtocolException(e)
+	}
+	if len(bin) > 0 {
+		_, e = p.trans.Write(bin)
+		return NewTProtocolException(e)
+	}
+	return nil
+}
+
+//
+// Reading methods.
+//
+
+// Read a message header.
+func (p *TCompactProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err error) {
+
+	protocolId, err := p.readByteDirect()
+	if err != nil {
+		return
+	}
+
+	if protocolId != COMPACT_PROTOCOL_ID {
+		e := fmt.Errorf("Expected protocol id %02x but got %02x", COMPACT_PROTOCOL_ID, protocolId)
+		return "", typeId, seqId, NewTProtocolExceptionWithType(BAD_VERSION, e)
+	}
+
+	versionAndType, err := p.readByteDirect()
+	if err != nil {
+		return
+	}
+
+	version := versionAndType & COMPACT_VERSION_MASK
+	typeId = TMessageType((versionAndType >> COMPACT_TYPE_SHIFT_AMOUNT) & COMPACT_TYPE_BITS)
+	if version != COMPACT_VERSION {
+		e := fmt.Errorf("Expected version %02x but got %02x", COMPACT_VERSION, version)
+		err = NewTProtocolExceptionWithType(BAD_VERSION, e)
+		return
+	}
+	seqId, e := p.readVarint32()
+	if e != nil {
+		err = NewTProtocolException(e)
+		return
+	}
+	name, err = p.ReadString()
+	return
+}
+
+func (p *TCompactProtocol) ReadMessageEnd() error { return nil }
+
+// Read a struct begin. There's nothing on the wire for this, but it is our
+// opportunity to push a new struct begin marker onto the field stack.
+func (p *TCompactProtocol) ReadStructBegin() (name string, err error) {
+	p.lastField = append(p.lastField, p.lastFieldId)
+	p.lastFieldId = 0
+	return
+}
+
+// Doesn't actually consume any wire data, just removes the last field for
+// this struct from the field stack.
+func (p *TCompactProtocol) ReadStructEnd() error {
+	// consume the last field we read off the wire.
+	p.lastFieldId = p.lastField[len(p.lastField)-1]
+	p.lastField = p.lastField[:len(p.lastField)-1]
+	return nil
+}
+
+// Read a field header off the wire.
+func (p *TCompactProtocol) ReadFieldBegin() (name string, typeId TType, id int16, err error) {
+	t, err := p.readByteDirect()
+	if err != nil {
+		return
+	}
+
+	// if it's a stop, then we can return immediately, as the struct is over.
+	if (t & 0x0f) == STOP {
+		return "", STOP, 0, nil
+	}
+
+	// mask off the 4 MSB of the type header. it could contain a field id delta.
+	modifier := int16((t & 0xf0) >> 4)
+	if modifier == 0 {
+		// not a delta. look ahead for the zigzag varint field id.
+		id, err = p.ReadI16()
+		if err != nil {
+			return
+		}
+	} else {
+		// has a delta. add the delta to the last read field id.
+		id = int16(p.lastFieldId) + modifier
+	}
+	typeId, e := p.getTType(tCompactType(t & 0x0f))
+	if e != nil {
+		err = NewTProtocolException(e)
+		return
+	}
+
+	// if this happens to be a boolean field, the value is encoded in the type
+	if p.isBoolType(t) {
+		// save the boolean value in a special instance variable.
+		p.boolValue = (byte(t)&0x0f == COMPACT_BOOLEAN_TRUE)
+		p.boolValueIsNotNull = true
+	}
+
+	// push the new field onto the field stack so we can keep the deltas going.
+	p.lastFieldId = int(id)
+	return
+}
+
+func (p *TCompactProtocol) ReadFieldEnd() error { return nil }
+
+// Read a map header off the wire. If the size is zero, skip reading the key
+// and value type. This means that 0-length maps will yield TMaps without the
+// "correct" types.
+func (p *TCompactProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, err error) {
+	size32, e := p.readVarint32()
+	if e != nil {
+		err = NewTProtocolException(e)
+		return
+	}
+	if size32 < 0 {
+		err = invalidDataLength
+		return
+	}
+	size = int(size32)
+
+	keyAndValueType := byte(STOP)
+	if size != 0 {
+		keyAndValueType, err = p.readByteDirect()
+		if err != nil {
+			return
+		}
+	}
+	keyType, _ = p.getTType(tCompactType(keyAndValueType >> 4))
+	valueType, _ = p.getTType(tCompactType(keyAndValueType & 0xf))
+	return
+}
+
+func (p *TCompactProtocol) ReadMapEnd() error { return nil }
+
+// Read a list header off the wire. If the list size is 0-14, the size will
+// be packed into the element type header. If it's a longer list, the 4 MSB
+// of the element type header will be 0xF, and a varint will follow with the
+// true size.
+func (p *TCompactProtocol) ReadListBegin() (elemType TType, size int, err error) {
+	size_and_type, err := p.readByteDirect()
+	if err != nil {
+		return
+	}
+	size = int((size_and_type >> 4) & 0x0f)
+	if size == 15 {
+		size2, e := p.readVarint32()
+		if e != nil {
+			err = NewTProtocolException(e)
+			return
+		}
+		if size2 < 0 {
+			err = invalidDataLength
+			return
+		}
+		size = int(size2)
+	}
+	elemType, e := p.getTType(tCompactType(size_and_type))
+	if e != nil {
+		err = NewTProtocolException(e)
+		return
+	}
+	return
+}
+
+func (p *TCompactProtocol) ReadListEnd() error { return nil }
+
+// Read a set header off the wire. If the set size is 0-14, the size will
+// be packed into the element type header. If it's a longer set, the 4 MSB
+// of the element type header will be 0xF, and a varint will follow with the
+// true size.
+func (p *TCompactProtocol) ReadSetBegin() (elemType TType, size int, err error) {
+	return p.ReadListBegin()
+}
+
+func (p *TCompactProtocol) ReadSetEnd() error { return nil }
+
+// Read a boolean off the wire. If this is a boolean field, the value should
+// already have been read during readFieldBegin, so we'll just consume the
+// pre-stored value. Otherwise, read a byte.
+func (p *TCompactProtocol) ReadBool() (value bool, err error) {
+	if p.boolValueIsNotNull {
+		p.boolValueIsNotNull = false
+		return p.boolValue, nil
+	}
+	v, err := p.readByteDirect()
+	return v == COMPACT_BOOLEAN_TRUE, err
+}
+
+// Read a single byte off the wire. Nothing interesting here.
+func (p *TCompactProtocol) ReadByte() (int8, error) {
+	v, err := p.readByteDirect()
+	if err != nil {
+		return 0, NewTProtocolException(err)
+	}
+	return int8(v), err
+}
+
+// Read an i16 from the wire as a zigzag varint.
+func (p *TCompactProtocol) ReadI16() (value int16, err error) {
+	v, err := p.ReadI32()
+	return int16(v), err
+}
+
+// Read an i32 from the wire as a zigzag varint.
+func (p *TCompactProtocol) ReadI32() (value int32, err error) {
+	v, e := p.readVarint32()
+	if e != nil {
+		return 0, NewTProtocolException(e)
+	}
+	value = p.zigzagToInt32(v)
+	return value, nil
+}
+
+// Read an i64 from the wire as a zigzag varint.
+func (p *TCompactProtocol) ReadI64() (value int64, err error) {
+	v, e := p.readVarint64()
+	if e != nil {
+		return 0, NewTProtocolException(e)
+	}
+	value = p.zigzagToInt64(v)
+	return value, nil
+}
+
+// No magic here - just read a double off the wire.
+func (p *TCompactProtocol) ReadDouble() (value float64, err error) {
+	longBits := p.buffer[0:8]
+	_, e := io.ReadFull(p.trans, longBits)
+	if e != nil {
+		return 0.0, NewTProtocolException(e)
+	}
+	return math.Float64frombits(p.bytesToUint64(longBits)), nil
+}
+
+// Reads a []byte (via readBinary), and then UTF-8 decodes it.
+func (p *TCompactProtocol) ReadString() (value string, err error) {
+	length, e := p.readVarint32()
+	if e != nil {
+		return "", NewTProtocolException(e)
+	}
+	if length < 0 {
+		return "", invalidDataLength
+	}
+	if uint64(length) > p.trans.RemainingBytes() {
+		return "", invalidDataLength
+	}
+
+	if length == 0 {
+		return "", nil
+	}
+	var buf []byte
+	if length <= int32(len(p.buffer)) {
+		buf = p.buffer[0:length]
+	} else {
+		buf = make([]byte, length)
+	}
+	_, e = io.ReadFull(p.trans, buf)
+	return string(buf), NewTProtocolException(e)
+}
+
+// Read a []byte from the wire.
+func (p *TCompactProtocol) ReadBinary() (value []byte, err error) {
+	length, e := p.readVarint32()
+	if e != nil {
+		return nil, NewTProtocolException(e)
+	}
+	if length == 0 {
+		return []byte{}, nil
+	}
+	if length < 0 {
+		return nil, invalidDataLength
+	}
+	if uint64(length) > p.trans.RemainingBytes() {
+		return nil, invalidDataLength
+	}
+
+	buf := make([]byte, length)
+	_, e = io.ReadFull(p.trans, buf)
+	return buf, NewTProtocolException(e)
+}
+
+func (p *TCompactProtocol) Flush() (err error) {
+	return NewTProtocolException(p.trans.Flush())
+}
+
+func (p *TCompactProtocol) Skip(fieldType TType) (err error) {
+	return SkipDefaultDepth(p, fieldType)
+}
+
+func (p *TCompactProtocol) Transport() TTransport {
+	return p.origTransport
+}
+
+//
+// Internal writing methods
+//
+
+// Abstract method for writing the start of lists and sets. List and sets on
+// the wire differ only by the type indicator.
+func (p *TCompactProtocol) writeCollectionBegin(elemType TType, size int) (int, error) {
+	if size <= 14 {
+		return 1, p.writeByteDirect(byte(int32(size<<4) | int32(p.getCompactType(elemType))))
+	}
+	err := p.writeByteDirect(0xf0 | byte(p.getCompactType(elemType)))
+	if err != nil {
+		return 0, err
+	}
+	m, err := p.writeVarint32(int32(size))
+	return 1 + m, err
+}
+
+// Write an i32 as a varint. Results in 1-5 bytes on the wire.
+// TODO(pomack): make a permanent buffer like writeVarint64?
+func (p *TCompactProtocol) writeVarint32(n int32) (int, error) {
+	i32buf := p.buffer[0:5]
+	idx := 0
+	for {
+		if (n & ^0x7F) == 0 {
+			i32buf[idx] = byte(n)
+			idx++
+			// p.writeByteDirect(byte(n));
+			break
+			// return;
+		} else {
+			i32buf[idx] = byte((n & 0x7F) | 0x80)
+			idx++
+			// p.writeByteDirect(byte(((n & 0x7F) | 0x80)));
+			u := uint32(n)
+			n = int32(u >> 7)
+		}
+	}
+	return p.trans.Write(i32buf[0:idx])
+}
+
+// Write an i64 as a varint. Results in 1-10 bytes on the wire.
+func (p *TCompactProtocol) writeVarint64(n int64) (int, error) {
+	varint64out := p.buffer[0:10]
+	idx := 0
+	for {
+		if (n & ^0x7F) == 0 {
+			varint64out[idx] = byte(n)
+			idx++
+			break
+		} else {
+			varint64out[idx] = byte((n & 0x7F) | 0x80)
+			idx++
+			u := uint64(n)
+			n = int64(u >> 7)
+		}
+	}
+	return p.trans.Write(varint64out[0:idx])
+}
+
+// Convert l into a zigzag long. This allows negative numbers to be
+// represented compactly as a varint.
+func (p *TCompactProtocol) int64ToZigzag(l int64) int64 {
+	return (l << 1) ^ (l >> 63)
+}
+
+// Convert l into a zigzag long. This allows negative numbers to be
+// represented compactly as a varint.
+func (p *TCompactProtocol) int32ToZigzag(n int32) int32 {
+	return (n << 1) ^ (n >> 31)
+}
+
+func (p *TCompactProtocol) fixedUint64ToBytes(n uint64, buf []byte) {
+	binary.LittleEndian.PutUint64(buf, n)
+}
+
+func (p *TCompactProtocol) fixedInt64ToBytes(n int64, buf []byte) {
+	binary.LittleEndian.PutUint64(buf, uint64(n))
+}
+
+// Writes a byte without any possibility of all that field header nonsense.
+// Used internally by other writing methods that know they need to write a byte.
+func (p *TCompactProtocol) writeByteDirect(b byte) error {
+	return p.trans.WriteByte(b)
+}
+
+// Writes a byte without any possibility of all that field header nonsense.
+func (p *TCompactProtocol) writeIntAsByteDirect(n int) (int, error) {
+	return 1, p.writeByteDirect(byte(n))
+}
+
+//
+// Internal reading methods
+//
+
+// Read an i32 from the wire as a varint. The MSB of each byte is set
+// if there is another byte to follow. This can read up to 5 bytes.
+func (p *TCompactProtocol) readVarint32() (int32, error) {
+	// if the wire contains the right stuff, this will just truncate the i64 we
+	// read and get us the right sign.
+	v, err := p.readVarint64()
+	return int32(v), err
+}
+
+// Read an i64 from the wire as a proper varint. The MSB of each byte is set
+// if there is another byte to follow. This can read up to 10 bytes.
+func (p *TCompactProtocol) readVarint64() (int64, error) {
+	shift := uint(0)
+	result := int64(0)
+	for {
+		b, err := p.readByteDirect()
+		if err != nil {
+			return 0, err
+		}
+		result |= int64(b&0x7f) << shift
+		if (b & 0x80) != 0x80 {
+			break
+		}
+		shift += 7
+	}
+	return result, nil
+}
+
+// Read a byte, unlike ReadByte that reads Thrift-byte that is i8.
+func (p *TCompactProtocol) readByteDirect() (byte, error) {
+	return p.trans.ReadByte()
+}
+
+//
+// encoding helpers
+//
+
+// Convert from zigzag int to int.
+func (p *TCompactProtocol) zigzagToInt32(n int32) int32 {
+	u := uint32(n)
+	return int32(u>>1) ^ -(n & 1)
+}
+
+// Convert from zigzag long to long.
+func (p *TCompactProtocol) zigzagToInt64(n int64) int64 {
+	u := uint64(n)
+	return int64(u>>1) ^ -(n & 1)
+}
+
+// Note that it's important that the mask bytes are long literals,
+// otherwise they'll default to ints, and when you shift an int left 56 bits,
+// you just get a messed up int.
+func (p *TCompactProtocol) bytesToInt64(b []byte) int64 {
+	return int64(binary.LittleEndian.Uint64(b))
+}
+
+// Note that it's important that the mask bytes are long literals,
+// otherwise they'll default to ints, and when you shift an int left 56 bits,
+// you just get a messed up int.
+func (p *TCompactProtocol) bytesToUint64(b []byte) uint64 {
+	return binary.LittleEndian.Uint64(b)
+}
+
+//
+// type testing and converting
+//
+
+func (p *TCompactProtocol) isBoolType(b byte) bool {
+	return (b&0x0f) == COMPACT_BOOLEAN_TRUE || (b&0x0f) == COMPACT_BOOLEAN_FALSE
+}
+
+// Given a tCompactType constant, convert it to its corresponding
+// TType value.
+func (p *TCompactProtocol) getTType(t tCompactType) (TType, error) {
+	switch byte(t) & 0x0f {
+	case STOP:
+		return STOP, nil
+	case COMPACT_BOOLEAN_FALSE, COMPACT_BOOLEAN_TRUE:
+		return BOOL, nil
+	case COMPACT_BYTE:
+		return BYTE, nil
+	case COMPACT_I16:
+		return I16, nil
+	case COMPACT_I32:
+		return I32, nil
+	case COMPACT_I64:
+		return I64, nil
+	case COMPACT_DOUBLE:
+		return DOUBLE, nil
+	case COMPACT_BINARY:
+		return STRING, nil
+	case COMPACT_LIST:
+		return LIST, nil
+	case COMPACT_SET:
+		return SET, nil
+	case COMPACT_MAP:
+		return MAP, nil
+	case COMPACT_STRUCT:
+		return STRUCT, nil
+	}
+	return STOP, TException(fmt.Errorf("don't know what type: %d", t&0x0f))
+}
+
+// Given a TType value, find the appropriate TCompactProtocol.Types constant.
+func (p *TCompactProtocol) getCompactType(t TType) tCompactType {
+	return ttypeToCompactType[t]
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift/exception.go b/vendor/github.com/uber/jaeger-client-go/thrift/exception.go
new file mode 100644
index 0000000..ea8d6f6
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift/exception.go
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+	"errors"
+)
+
+// Generic Thrift exception
+type TException interface {
+	error
+}
+
+// Prepends additional information to an error without losing the Thrift exception interface
+func PrependError(prepend string, err error) error {
+	if t, ok := err.(TTransportException); ok {
+		return NewTTransportException(t.TypeId(), prepend+t.Error())
+	}
+	if t, ok := err.(TProtocolException); ok {
+		return NewTProtocolExceptionWithType(t.TypeId(), errors.New(prepend+err.Error()))
+	}
+	if t, ok := err.(TApplicationException); ok {
+		return NewTApplicationException(t.TypeId(), prepend+t.Error())
+	}
+
+	return errors.New(prepend + err.Error())
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift/memory_buffer.go b/vendor/github.com/uber/jaeger-client-go/thrift/memory_buffer.go
new file mode 100644
index 0000000..b62fd56
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift/memory_buffer.go
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+	"bytes"
+)
+
+// Memory buffer-based implementation of the TTransport interface.
+type TMemoryBuffer struct {
+	*bytes.Buffer
+	size int
+}
+
+type TMemoryBufferTransportFactory struct {
+	size int
+}
+
+func (p *TMemoryBufferTransportFactory) GetTransport(trans TTransport) TTransport {
+	if trans != nil {
+		t, ok := trans.(*TMemoryBuffer)
+		if ok && t.size > 0 {
+			return NewTMemoryBufferLen(t.size)
+		}
+	}
+	return NewTMemoryBufferLen(p.size)
+}
+
+func NewTMemoryBufferTransportFactory(size int) *TMemoryBufferTransportFactory {
+	return &TMemoryBufferTransportFactory{size: size}
+}
+
+func NewTMemoryBuffer() *TMemoryBuffer {
+	return &TMemoryBuffer{Buffer: &bytes.Buffer{}, size: 0}
+}
+
+func NewTMemoryBufferLen(size int) *TMemoryBuffer {
+	buf := make([]byte, 0, size)
+	return &TMemoryBuffer{Buffer: bytes.NewBuffer(buf), size: size}
+}
+
+func (p *TMemoryBuffer) IsOpen() bool {
+	return true
+}
+
+func (p *TMemoryBuffer) Open() error {
+	return nil
+}
+
+func (p *TMemoryBuffer) Close() error {
+	p.Buffer.Reset()
+	return nil
+}
+
+// Flushing a memory buffer is a no-op
+func (p *TMemoryBuffer) Flush() error {
+	return nil
+}
+
+func (p *TMemoryBuffer) RemainingBytes() (num_bytes uint64) {
+	return uint64(p.Buffer.Len())
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift/messagetype.go b/vendor/github.com/uber/jaeger-client-go/thrift/messagetype.go
new file mode 100644
index 0000000..25ab2e9
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift/messagetype.go
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+// Message type constants in the Thrift protocol.
+type TMessageType int32
+
+const (
+	INVALID_TMESSAGE_TYPE TMessageType = 0
+	CALL                  TMessageType = 1
+	REPLY                 TMessageType = 2
+	EXCEPTION             TMessageType = 3
+	ONEWAY                TMessageType = 4
+)
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift/numeric.go b/vendor/github.com/uber/jaeger-client-go/thrift/numeric.go
new file mode 100644
index 0000000..aa8daa9
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift/numeric.go
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+	"math"
+	"strconv"
+)
+
+type Numeric interface {
+	Int64() int64
+	Int32() int32
+	Int16() int16
+	Byte() byte
+	Int() int
+	Float64() float64
+	Float32() float32
+	String() string
+	isNull() bool
+}
+
+type numeric struct {
+	iValue int64
+	dValue float64
+	sValue string
+	isNil  bool
+}
+
+var (
+	INFINITY          Numeric
+	NEGATIVE_INFINITY Numeric
+	NAN               Numeric
+	ZERO              Numeric
+	NUMERIC_NULL      Numeric
+)
+
+func NewNumericFromDouble(dValue float64) Numeric {
+	if math.IsInf(dValue, 1) {
+		return INFINITY
+	}
+	if math.IsInf(dValue, -1) {
+		return NEGATIVE_INFINITY
+	}
+	if math.IsNaN(dValue) {
+		return NAN
+	}
+	iValue := int64(dValue)
+	sValue := strconv.FormatFloat(dValue, 'g', 10, 64)
+	isNil := false
+	return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil}
+}
+
+func NewNumericFromI64(iValue int64) Numeric {
+	dValue := float64(iValue)
+	sValue := string(iValue)
+	isNil := false
+	return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil}
+}
+
+func NewNumericFromI32(iValue int32) Numeric {
+	dValue := float64(iValue)
+	sValue := string(iValue)
+	isNil := false
+	return &numeric{iValue: int64(iValue), dValue: dValue, sValue: sValue, isNil: isNil}
+}
+
+func NewNumericFromString(sValue string) Numeric {
+	if sValue == INFINITY.String() {
+		return INFINITY
+	}
+	if sValue == NEGATIVE_INFINITY.String() {
+		return NEGATIVE_INFINITY
+	}
+	if sValue == NAN.String() {
+		return NAN
+	}
+	iValue, _ := strconv.ParseInt(sValue, 10, 64)
+	dValue, _ := strconv.ParseFloat(sValue, 64)
+	isNil := len(sValue) == 0
+	return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil}
+}
+
+func NewNumericFromJSONString(sValue string, isNull bool) Numeric {
+	if isNull {
+		return NewNullNumeric()
+	}
+	if sValue == JSON_INFINITY {
+		return INFINITY
+	}
+	if sValue == JSON_NEGATIVE_INFINITY {
+		return NEGATIVE_INFINITY
+	}
+	if sValue == JSON_NAN {
+		return NAN
+	}
+	iValue, _ := strconv.ParseInt(sValue, 10, 64)
+	dValue, _ := strconv.ParseFloat(sValue, 64)
+	return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNull}
+}
+
+func NewNullNumeric() Numeric {
+	return &numeric{iValue: 0, dValue: 0.0, sValue: "", isNil: true}
+}
+
+func (p *numeric) Int64() int64 {
+	return p.iValue
+}
+
+func (p *numeric) Int32() int32 {
+	return int32(p.iValue)
+}
+
+func (p *numeric) Int16() int16 {
+	return int16(p.iValue)
+}
+
+func (p *numeric) Byte() byte {
+	return byte(p.iValue)
+}
+
+func (p *numeric) Int() int {
+	return int(p.iValue)
+}
+
+func (p *numeric) Float64() float64 {
+	return p.dValue
+}
+
+func (p *numeric) Float32() float32 {
+	return float32(p.dValue)
+}
+
+func (p *numeric) String() string {
+	return p.sValue
+}
+
+func (p *numeric) isNull() bool {
+	return p.isNil
+}
+
+func init() {
+	INFINITY = &numeric{iValue: 0, dValue: math.Inf(1), sValue: "Infinity", isNil: false}
+	NEGATIVE_INFINITY = &numeric{iValue: 0, dValue: math.Inf(-1), sValue: "-Infinity", isNil: false}
+	NAN = &numeric{iValue: 0, dValue: math.NaN(), sValue: "NaN", isNil: false}
+	ZERO = &numeric{iValue: 0, dValue: 0, sValue: "0", isNil: false}
+	NUMERIC_NULL = &numeric{iValue: 0, dValue: 0, sValue: "0", isNil: true}
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift/processor.go b/vendor/github.com/uber/jaeger-client-go/thrift/processor.go
new file mode 100644
index 0000000..ca0d3fa
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift/processor.go
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+// A processor is a generic object which operates upon an input stream and
+// writes to some output stream.
+type TProcessor interface {
+	Process(in, out TProtocol) (bool, TException)
+}
+
+type TProcessorFunction interface {
+	Process(seqId int32, in, out TProtocol) (bool, TException)
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift/protocol.go b/vendor/github.com/uber/jaeger-client-go/thrift/protocol.go
new file mode 100644
index 0000000..45fa202
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift/protocol.go
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+	"errors"
+)
+
+const (
+	VERSION_MASK = 0xffff0000
+	VERSION_1    = 0x80010000
+)
+
+type TProtocol interface {
+	WriteMessageBegin(name string, typeId TMessageType, seqid int32) error
+	WriteMessageEnd() error
+	WriteStructBegin(name string) error
+	WriteStructEnd() error
+	WriteFieldBegin(name string, typeId TType, id int16) error
+	WriteFieldEnd() error
+	WriteFieldStop() error
+	WriteMapBegin(keyType TType, valueType TType, size int) error
+	WriteMapEnd() error
+	WriteListBegin(elemType TType, size int) error
+	WriteListEnd() error
+	WriteSetBegin(elemType TType, size int) error
+	WriteSetEnd() error
+	WriteBool(value bool) error
+	WriteByte(value int8) error
+	WriteI16(value int16) error
+	WriteI32(value int32) error
+	WriteI64(value int64) error
+	WriteDouble(value float64) error
+	WriteString(value string) error
+	WriteBinary(value []byte) error
+
+	ReadMessageBegin() (name string, typeId TMessageType, seqid int32, err error)
+	ReadMessageEnd() error
+	ReadStructBegin() (name string, err error)
+	ReadStructEnd() error
+	ReadFieldBegin() (name string, typeId TType, id int16, err error)
+	ReadFieldEnd() error
+	ReadMapBegin() (keyType TType, valueType TType, size int, err error)
+	ReadMapEnd() error
+	ReadListBegin() (elemType TType, size int, err error)
+	ReadListEnd() error
+	ReadSetBegin() (elemType TType, size int, err error)
+	ReadSetEnd() error
+	ReadBool() (value bool, err error)
+	ReadByte() (value int8, err error)
+	ReadI16() (value int16, err error)
+	ReadI32() (value int32, err error)
+	ReadI64() (value int64, err error)
+	ReadDouble() (value float64, err error)
+	ReadString() (value string, err error)
+	ReadBinary() (value []byte, err error)
+
+	Skip(fieldType TType) (err error)
+	Flush() (err error)
+
+	Transport() TTransport
+}
+
+// The maximum recursive depth the skip() function will traverse
+const DEFAULT_RECURSION_DEPTH = 64
+
+// Skips over the next data element from the provided input TProtocol object.
+func SkipDefaultDepth(prot TProtocol, typeId TType) (err error) {
+	return Skip(prot, typeId, DEFAULT_RECURSION_DEPTH)
+}
+
+// Skips over the next data element from the provided input TProtocol object.
+func Skip(self TProtocol, fieldType TType, maxDepth int) (err error) {
+	
+    if maxDepth <= 0 {
+		return NewTProtocolExceptionWithType( DEPTH_LIMIT, errors.New("Depth limit exceeded"))
+	}
+
+	switch fieldType {
+	case STOP:
+		return
+	case BOOL:
+		_, err = self.ReadBool()
+		return
+	case BYTE:
+		_, err = self.ReadByte()
+		return
+	case I16:
+		_, err = self.ReadI16()
+		return
+	case I32:
+		_, err = self.ReadI32()
+		return
+	case I64:
+		_, err = self.ReadI64()
+		return
+	case DOUBLE:
+		_, err = self.ReadDouble()
+		return
+	case STRING:
+		_, err = self.ReadString()
+		return
+	case STRUCT:
+		if _, err = self.ReadStructBegin(); err != nil {
+			return err
+		}
+		for {
+			_, typeId, _, _ := self.ReadFieldBegin()
+			if typeId == STOP {
+				break
+			}
+			err := Skip(self, typeId, maxDepth-1)
+			if err != nil {
+				return err
+			}
+			self.ReadFieldEnd()
+		}
+		return self.ReadStructEnd()
+	case MAP:
+		keyType, valueType, size, err := self.ReadMapBegin()
+		if err != nil {
+			return err
+		}
+		for i := 0; i < size; i++ {
+			err := Skip(self, keyType, maxDepth-1)
+			if err != nil {
+				return err
+			}
+			self.Skip(valueType)
+		}
+		return self.ReadMapEnd()
+	case SET:
+		elemType, size, err := self.ReadSetBegin()
+		if err != nil {
+			return err
+		}
+		for i := 0; i < size; i++ {
+			err := Skip(self, elemType, maxDepth-1)
+			if err != nil {
+				return err
+			}
+		}
+		return self.ReadSetEnd()
+	case LIST:
+		elemType, size, err := self.ReadListBegin()
+		if err != nil {
+			return err
+		}
+		for i := 0; i < size; i++ {
+			err := Skip(self, elemType, maxDepth-1)
+			if err != nil {
+				return err
+			}
+		}
+		return self.ReadListEnd()
+	}
+	return nil
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift/protocol_exception.go b/vendor/github.com/uber/jaeger-client-go/thrift/protocol_exception.go
new file mode 100644
index 0000000..6e357ee
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift/protocol_exception.go
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+	"encoding/base64"
+)
+
+// Thrift Protocol exception
+type TProtocolException interface {
+	TException
+	TypeId() int
+}
+
+const (
+	UNKNOWN_PROTOCOL_EXCEPTION = 0
+	INVALID_DATA               = 1
+	NEGATIVE_SIZE              = 2
+	SIZE_LIMIT                 = 3
+	BAD_VERSION                = 4
+	NOT_IMPLEMENTED            = 5
+	DEPTH_LIMIT                = 6
+)
+
+type tProtocolException struct {
+	typeId  int
+	message string
+}
+
+func (p *tProtocolException) TypeId() int {
+	return p.typeId
+}
+
+func (p *tProtocolException) String() string {
+	return p.message
+}
+
+func (p *tProtocolException) Error() string {
+	return p.message
+}
+
+func NewTProtocolException(err error) TProtocolException {
+	if err == nil {
+		return nil
+	}
+	if e,ok := err.(TProtocolException); ok {
+		return e
+	}
+	if _, ok := err.(base64.CorruptInputError); ok {
+		return &tProtocolException{INVALID_DATA, err.Error()}
+	}
+	return &tProtocolException{UNKNOWN_PROTOCOL_EXCEPTION, err.Error()}
+}
+
+func NewTProtocolExceptionWithType(errType int, err error) TProtocolException {
+	if err == nil {
+		return nil
+	}
+	return &tProtocolException{errType, err.Error()}
+}
+
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift/protocol_factory.go b/vendor/github.com/uber/jaeger-client-go/thrift/protocol_factory.go
new file mode 100644
index 0000000..c40f796
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift/protocol_factory.go
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+// Factory interface for constructing protocol instances.
+type TProtocolFactory interface {
+	GetProtocol(trans TTransport) TProtocol
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift/rich_transport.go b/vendor/github.com/uber/jaeger-client-go/thrift/rich_transport.go
new file mode 100644
index 0000000..8e296a9
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift/rich_transport.go
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import "io"
+
+type RichTransport struct {
+	TTransport
+}
+
+// Wraps Transport to provide TRichTransport interface
+func NewTRichTransport(trans TTransport) *RichTransport {
+	return &RichTransport{trans}
+}
+
+func (r *RichTransport) ReadByte() (c byte, err error) {
+	return readByte(r.TTransport)
+}
+
+func (r *RichTransport) WriteByte(c byte) error {
+	return writeByte(r.TTransport, c)
+}
+
+func (r *RichTransport) WriteString(s string) (n int, err error) {
+	return r.Write([]byte(s))
+}
+
+func (r *RichTransport) RemainingBytes() (num_bytes uint64) {
+	return r.TTransport.RemainingBytes()
+}
+
+func readByte(r io.Reader) (c byte, err error) {
+	v := [1]byte{0}
+	n, err := r.Read(v[0:1])
+	if n > 0 && (err == nil || err == io.EOF) {
+		return v[0], nil
+	}
+	if n > 0 && err != nil {
+		return v[0], err
+	}
+	if err != nil {
+		return 0, err
+	}
+	return v[0], nil
+}
+
+func writeByte(w io.Writer, c byte) error {
+	v := [1]byte{c}
+	_, err := w.Write(v[0:1])
+	return err
+}
+
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift/serializer.go b/vendor/github.com/uber/jaeger-client-go/thrift/serializer.go
new file mode 100644
index 0000000..7712229
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift/serializer.go
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+type TSerializer struct {
+	Transport *TMemoryBuffer
+	Protocol  TProtocol
+}
+
+type TStruct interface {
+	Write(p TProtocol) error
+	Read(p TProtocol) error
+}
+
+func NewTSerializer() *TSerializer {
+	transport := NewTMemoryBufferLen(1024)
+	protocol := NewTBinaryProtocolFactoryDefault().GetProtocol(transport)
+
+	return &TSerializer{
+		transport,
+		protocol}
+}
+
+func (t *TSerializer) WriteString(msg TStruct) (s string, err error) {
+	t.Transport.Reset()
+
+	if err = msg.Write(t.Protocol); err != nil {
+		return
+	}
+
+	if err = t.Protocol.Flush(); err != nil {
+		return
+	}
+	if err = t.Transport.Flush(); err != nil {
+		return
+	}
+
+	return t.Transport.String(), nil
+}
+
+func (t *TSerializer) Write(msg TStruct) (b []byte, err error) {
+	t.Transport.Reset()
+
+	if err = msg.Write(t.Protocol); err != nil {
+		return
+	}
+
+	if err = t.Protocol.Flush(); err != nil {
+		return
+	}
+
+	if err = t.Transport.Flush(); err != nil {
+		return
+	}
+
+	b = append(b, t.Transport.Bytes()...)
+	return
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift/simple_json_protocol.go b/vendor/github.com/uber/jaeger-client-go/thrift/simple_json_protocol.go
new file mode 100644
index 0000000..412a482
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift/simple_json_protocol.go
@@ -0,0 +1,1337 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+	"bufio"
+	"bytes"
+	"encoding/base64"
+	"encoding/json"
+	"fmt"
+	"io"
+	"math"
+	"strconv"
+)
+
+type _ParseContext int
+
+const (
+	_CONTEXT_IN_TOPLEVEL          _ParseContext = 1
+	_CONTEXT_IN_LIST_FIRST        _ParseContext = 2
+	_CONTEXT_IN_LIST              _ParseContext = 3
+	_CONTEXT_IN_OBJECT_FIRST      _ParseContext = 4
+	_CONTEXT_IN_OBJECT_NEXT_KEY   _ParseContext = 5
+	_CONTEXT_IN_OBJECT_NEXT_VALUE _ParseContext = 6
+)
+
+func (p _ParseContext) String() string {
+	switch p {
+	case _CONTEXT_IN_TOPLEVEL:
+		return "TOPLEVEL"
+	case _CONTEXT_IN_LIST_FIRST:
+		return "LIST-FIRST"
+	case _CONTEXT_IN_LIST:
+		return "LIST"
+	case _CONTEXT_IN_OBJECT_FIRST:
+		return "OBJECT-FIRST"
+	case _CONTEXT_IN_OBJECT_NEXT_KEY:
+		return "OBJECT-NEXT-KEY"
+	case _CONTEXT_IN_OBJECT_NEXT_VALUE:
+		return "OBJECT-NEXT-VALUE"
+	}
+	return "UNKNOWN-PARSE-CONTEXT"
+}
+
+// JSON protocol implementation for thrift.
+//
+// This protocol produces/consumes a simple output format
+// suitable for parsing by scripting languages.  It should not be
+// confused with the full-featured TJSONProtocol.
+//
+type TSimpleJSONProtocol struct {
+	trans TTransport
+
+	parseContextStack []int
+	dumpContext       []int
+
+	writer *bufio.Writer
+	reader *bufio.Reader
+}
+
+// Constructor
+func NewTSimpleJSONProtocol(t TTransport) *TSimpleJSONProtocol {
+	v := &TSimpleJSONProtocol{trans: t,
+		writer: bufio.NewWriter(t),
+		reader: bufio.NewReader(t),
+	}
+	v.parseContextStack = append(v.parseContextStack, int(_CONTEXT_IN_TOPLEVEL))
+	v.dumpContext = append(v.dumpContext, int(_CONTEXT_IN_TOPLEVEL))
+	return v
+}
+
+// Factory
+type TSimpleJSONProtocolFactory struct{}
+
+func (p *TSimpleJSONProtocolFactory) GetProtocol(trans TTransport) TProtocol {
+	return NewTSimpleJSONProtocol(trans)
+}
+
+func NewTSimpleJSONProtocolFactory() *TSimpleJSONProtocolFactory {
+	return &TSimpleJSONProtocolFactory{}
+}
+
+var (
+	JSON_COMMA                   []byte
+	JSON_COLON                   []byte
+	JSON_LBRACE                  []byte
+	JSON_RBRACE                  []byte
+	JSON_LBRACKET                []byte
+	JSON_RBRACKET                []byte
+	JSON_QUOTE                   byte
+	JSON_QUOTE_BYTES             []byte
+	JSON_NULL                    []byte
+	JSON_TRUE                    []byte
+	JSON_FALSE                   []byte
+	JSON_INFINITY                string
+	JSON_NEGATIVE_INFINITY       string
+	JSON_NAN                     string
+	JSON_INFINITY_BYTES          []byte
+	JSON_NEGATIVE_INFINITY_BYTES []byte
+	JSON_NAN_BYTES               []byte
+	json_nonbase_map_elem_bytes  []byte
+)
+
+func init() {
+	JSON_COMMA = []byte{','}
+	JSON_COLON = []byte{':'}
+	JSON_LBRACE = []byte{'{'}
+	JSON_RBRACE = []byte{'}'}
+	JSON_LBRACKET = []byte{'['}
+	JSON_RBRACKET = []byte{']'}
+	JSON_QUOTE = '"'
+	JSON_QUOTE_BYTES = []byte{'"'}
+	JSON_NULL = []byte{'n', 'u', 'l', 'l'}
+	JSON_TRUE = []byte{'t', 'r', 'u', 'e'}
+	JSON_FALSE = []byte{'f', 'a', 'l', 's', 'e'}
+	JSON_INFINITY = "Infinity"
+	JSON_NEGATIVE_INFINITY = "-Infinity"
+	JSON_NAN = "NaN"
+	JSON_INFINITY_BYTES = []byte{'I', 'n', 'f', 'i', 'n', 'i', 't', 'y'}
+	JSON_NEGATIVE_INFINITY_BYTES = []byte{'-', 'I', 'n', 'f', 'i', 'n', 'i', 't', 'y'}
+	JSON_NAN_BYTES = []byte{'N', 'a', 'N'}
+	json_nonbase_map_elem_bytes = []byte{']', ',', '['}
+}
+
+func jsonQuote(s string) string {
+	b, _ := json.Marshal(s)
+	s1 := string(b)
+	return s1
+}
+
+func jsonUnquote(s string) (string, bool) {
+	s1 := new(string)
+	err := json.Unmarshal([]byte(s), s1)
+	return *s1, err == nil
+}
+
+func mismatch(expected, actual string) error {
+	return fmt.Errorf("Expected '%s' but found '%s' while parsing JSON.", expected, actual)
+}
+
+func (p *TSimpleJSONProtocol) WriteMessageBegin(name string, typeId TMessageType, seqId int32) error {
+	p.resetContextStack() // THRIFT-3735
+	if e := p.OutputListBegin(); e != nil {
+		return e
+	}
+	if e := p.WriteString(name); e != nil {
+		return e
+	}
+	if e := p.WriteByte(int8(typeId)); e != nil {
+		return e
+	}
+	if e := p.WriteI32(seqId); e != nil {
+		return e
+	}
+	return nil
+}
+
+func (p *TSimpleJSONProtocol) WriteMessageEnd() error {
+	return p.OutputListEnd()
+}
+
+func (p *TSimpleJSONProtocol) WriteStructBegin(name string) error {
+	if e := p.OutputObjectBegin(); e != nil {
+		return e
+	}
+	return nil
+}
+
+func (p *TSimpleJSONProtocol) WriteStructEnd() error {
+	return p.OutputObjectEnd()
+}
+
+func (p *TSimpleJSONProtocol) WriteFieldBegin(name string, typeId TType, id int16) error {
+	if e := p.WriteString(name); e != nil {
+		return e
+	}
+	return nil
+}
+
+func (p *TSimpleJSONProtocol) WriteFieldEnd() error {
+	//return p.OutputListEnd()
+	return nil
+}
+
+func (p *TSimpleJSONProtocol) WriteFieldStop() error { return nil }
+
+func (p *TSimpleJSONProtocol) WriteMapBegin(keyType TType, valueType TType, size int) error {
+	if e := p.OutputListBegin(); e != nil {
+		return e
+	}
+	if e := p.WriteByte(int8(keyType)); e != nil {
+		return e
+	}
+	if e := p.WriteByte(int8(valueType)); e != nil {
+		return e
+	}
+	return p.WriteI32(int32(size))
+}
+
+func (p *TSimpleJSONProtocol) WriteMapEnd() error {
+	return p.OutputListEnd()
+}
+
+func (p *TSimpleJSONProtocol) WriteListBegin(elemType TType, size int) error {
+	return p.OutputElemListBegin(elemType, size)
+}
+
+func (p *TSimpleJSONProtocol) WriteListEnd() error {
+	return p.OutputListEnd()
+}
+
+func (p *TSimpleJSONProtocol) WriteSetBegin(elemType TType, size int) error {
+	return p.OutputElemListBegin(elemType, size)
+}
+
+func (p *TSimpleJSONProtocol) WriteSetEnd() error {
+	return p.OutputListEnd()
+}
+
+func (p *TSimpleJSONProtocol) WriteBool(b bool) error {
+	return p.OutputBool(b)
+}
+
+func (p *TSimpleJSONProtocol) WriteByte(b int8) error {
+	return p.WriteI32(int32(b))
+}
+
+func (p *TSimpleJSONProtocol) WriteI16(v int16) error {
+	return p.WriteI32(int32(v))
+}
+
+func (p *TSimpleJSONProtocol) WriteI32(v int32) error {
+	return p.OutputI64(int64(v))
+}
+
+func (p *TSimpleJSONProtocol) WriteI64(v int64) error {
+	return p.OutputI64(int64(v))
+}
+
+func (p *TSimpleJSONProtocol) WriteDouble(v float64) error {
+	return p.OutputF64(v)
+}
+
+func (p *TSimpleJSONProtocol) WriteString(v string) error {
+	return p.OutputString(v)
+}
+
+func (p *TSimpleJSONProtocol) WriteBinary(v []byte) error {
+	// JSON library only takes in a string,
+	// not an arbitrary byte array, to ensure bytes are transmitted
+	// efficiently we must convert this into a valid JSON string
+	// therefore we use base64 encoding to avoid excessive escaping/quoting
+	if e := p.OutputPreValue(); e != nil {
+		return e
+	}
+	if _, e := p.write(JSON_QUOTE_BYTES); e != nil {
+		return NewTProtocolException(e)
+	}
+	writer := base64.NewEncoder(base64.StdEncoding, p.writer)
+	if _, e := writer.Write(v); e != nil {
+		p.writer.Reset(p.trans) // THRIFT-3735
+		return NewTProtocolException(e)
+	}
+	if e := writer.Close(); e != nil {
+		return NewTProtocolException(e)
+	}
+	if _, e := p.write(JSON_QUOTE_BYTES); e != nil {
+		return NewTProtocolException(e)
+	}
+	return p.OutputPostValue()
+}
+
+// Reading methods.
+func (p *TSimpleJSONProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err error) {
+	p.resetContextStack() // THRIFT-3735
+	if isNull, err := p.ParseListBegin(); isNull || err != nil {
+		return name, typeId, seqId, err
+	}
+	if name, err = p.ReadString(); err != nil {
+		return name, typeId, seqId, err
+	}
+	bTypeId, err := p.ReadByte()
+	typeId = TMessageType(bTypeId)
+	if err != nil {
+		return name, typeId, seqId, err
+	}
+	if seqId, err = p.ReadI32(); err != nil {
+		return name, typeId, seqId, err
+	}
+	return name, typeId, seqId, nil
+}
+
+func (p *TSimpleJSONProtocol) ReadMessageEnd() error {
+	return p.ParseListEnd()
+}
+
+func (p *TSimpleJSONProtocol) ReadStructBegin() (name string, err error) {
+	_, err = p.ParseObjectStart()
+	return "", err
+}
+
+func (p *TSimpleJSONProtocol) ReadStructEnd() error {
+	return p.ParseObjectEnd()
+}
+
+func (p *TSimpleJSONProtocol) ReadFieldBegin() (string, TType, int16, error) {
+	if err := p.ParsePreValue(); err != nil {
+		return "", STOP, 0, err
+	}
+	b, _ := p.reader.Peek(1)
+	if len(b) > 0 {
+		switch b[0] {
+		case JSON_RBRACE[0]:
+			return "", STOP, 0, nil
+		case JSON_QUOTE:
+			p.reader.ReadByte()
+			name, err := p.ParseStringBody()
+			// simplejson is not meant to be read back into thrift
+			// - see http://wiki.apache.org/thrift/ThriftUsageJava
+			// - use JSON instead
+			if err != nil {
+				return name, STOP, 0, err
+			}
+			return name, STOP, -1, p.ParsePostValue()
+			/*
+			   if err = p.ParsePostValue(); err != nil {
+			     return name, STOP, 0, err
+			   }
+			   if isNull, err := p.ParseListBegin(); isNull || err != nil {
+			     return name, STOP, 0, err
+			   }
+			   bType, err := p.ReadByte()
+			   thetype := TType(bType)
+			   if err != nil {
+			     return name, thetype, 0, err
+			   }
+			   id, err := p.ReadI16()
+			   return name, thetype, id, err
+			*/
+		}
+		e := fmt.Errorf("Expected \"}\" or '\"', but found: '%s'", string(b))
+		return "", STOP, 0, NewTProtocolExceptionWithType(INVALID_DATA, e)
+	}
+	return "", STOP, 0, NewTProtocolException(io.EOF)
+}
+
+func (p *TSimpleJSONProtocol) ReadFieldEnd() error {
+	return nil
+	//return p.ParseListEnd()
+}
+
+func (p *TSimpleJSONProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, e error) {
+	if isNull, e := p.ParseListBegin(); isNull || e != nil {
+		return VOID, VOID, 0, e
+	}
+
+	// read keyType
+	bKeyType, e := p.ReadByte()
+	keyType = TType(bKeyType)
+	if e != nil {
+		return keyType, valueType, size, e
+	}
+
+	// read valueType
+	bValueType, e := p.ReadByte()
+	valueType = TType(bValueType)
+	if e != nil {
+		return keyType, valueType, size, e
+	}
+
+	// read size
+	iSize, err := p.ReadI64()
+	size = int(iSize)
+	return keyType, valueType, size, err
+}
+
+func (p *TSimpleJSONProtocol) ReadMapEnd() error {
+	return p.ParseListEnd()
+}
+
+func (p *TSimpleJSONProtocol) ReadListBegin() (elemType TType, size int, e error) {
+	return p.ParseElemListBegin()
+}
+
+func (p *TSimpleJSONProtocol) ReadListEnd() error {
+	return p.ParseListEnd()
+}
+
+func (p *TSimpleJSONProtocol) ReadSetBegin() (elemType TType, size int, e error) {
+	return p.ParseElemListBegin()
+}
+
+func (p *TSimpleJSONProtocol) ReadSetEnd() error {
+	return p.ParseListEnd()
+}
+
+func (p *TSimpleJSONProtocol) ReadBool() (bool, error) {
+	var value bool
+
+	if err := p.ParsePreValue(); err != nil {
+		return value, err
+	}
+	f, _ := p.reader.Peek(1)
+	if len(f) > 0 {
+		switch f[0] {
+		case JSON_TRUE[0]:
+			b := make([]byte, len(JSON_TRUE))
+			_, err := p.reader.Read(b)
+			if err != nil {
+				return false, NewTProtocolException(err)
+			}
+			if string(b) == string(JSON_TRUE) {
+				value = true
+			} else {
+				e := fmt.Errorf("Expected \"true\" but found: %s", string(b))
+				return value, NewTProtocolExceptionWithType(INVALID_DATA, e)
+			}
+			break
+		case JSON_FALSE[0]:
+			b := make([]byte, len(JSON_FALSE))
+			_, err := p.reader.Read(b)
+			if err != nil {
+				return false, NewTProtocolException(err)
+			}
+			if string(b) == string(JSON_FALSE) {
+				value = false
+			} else {
+				e := fmt.Errorf("Expected \"false\" but found: %s", string(b))
+				return value, NewTProtocolExceptionWithType(INVALID_DATA, e)
+			}
+			break
+		case JSON_NULL[0]:
+			b := make([]byte, len(JSON_NULL))
+			_, err := p.reader.Read(b)
+			if err != nil {
+				return false, NewTProtocolException(err)
+			}
+			if string(b) == string(JSON_NULL) {
+				value = false
+			} else {
+				e := fmt.Errorf("Expected \"null\" but found: %s", string(b))
+				return value, NewTProtocolExceptionWithType(INVALID_DATA, e)
+			}
+		default:
+			e := fmt.Errorf("Expected \"true\", \"false\", or \"null\" but found: %s", string(f))
+			return value, NewTProtocolExceptionWithType(INVALID_DATA, e)
+		}
+	}
+	return value, p.ParsePostValue()
+}
+
+func (p *TSimpleJSONProtocol) ReadByte() (int8, error) {
+	v, err := p.ReadI64()
+	return int8(v), err
+}
+
+func (p *TSimpleJSONProtocol) ReadI16() (int16, error) {
+	v, err := p.ReadI64()
+	return int16(v), err
+}
+
+func (p *TSimpleJSONProtocol) ReadI32() (int32, error) {
+	v, err := p.ReadI64()
+	return int32(v), err
+}
+
+func (p *TSimpleJSONProtocol) ReadI64() (int64, error) {
+	v, _, err := p.ParseI64()
+	return v, err
+}
+
+func (p *TSimpleJSONProtocol) ReadDouble() (float64, error) {
+	v, _, err := p.ParseF64()
+	return v, err
+}
+
+func (p *TSimpleJSONProtocol) ReadString() (string, error) {
+	var v string
+	if err := p.ParsePreValue(); err != nil {
+		return v, err
+	}
+	f, _ := p.reader.Peek(1)
+	if len(f) > 0 && f[0] == JSON_QUOTE {
+		p.reader.ReadByte()
+		value, err := p.ParseStringBody()
+		v = value
+		if err != nil {
+			return v, err
+		}
+	} else if len(f) > 0 && f[0] == JSON_NULL[0] {
+		b := make([]byte, len(JSON_NULL))
+		_, err := p.reader.Read(b)
+		if err != nil {
+			return v, NewTProtocolException(err)
+		}
+		if string(b) != string(JSON_NULL) {
+			e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b))
+			return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
+		}
+	} else {
+		e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f))
+		return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
+	}
+	return v, p.ParsePostValue()
+}
+
+func (p *TSimpleJSONProtocol) ReadBinary() ([]byte, error) {
+	var v []byte
+	if err := p.ParsePreValue(); err != nil {
+		return nil, err
+	}
+	f, _ := p.reader.Peek(1)
+	if len(f) > 0 && f[0] == JSON_QUOTE {
+		p.reader.ReadByte()
+		value, err := p.ParseBase64EncodedBody()
+		v = value
+		if err != nil {
+			return v, err
+		}
+	} else if len(f) > 0 && f[0] == JSON_NULL[0] {
+		b := make([]byte, len(JSON_NULL))
+		_, err := p.reader.Read(b)
+		if err != nil {
+			return v, NewTProtocolException(err)
+		}
+		if string(b) != string(JSON_NULL) {
+			e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b))
+			return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
+		}
+	} else {
+		e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f))
+		return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
+	}
+
+	return v, p.ParsePostValue()
+}
+
+func (p *TSimpleJSONProtocol) Flush() (err error) {
+	return NewTProtocolException(p.writer.Flush())
+}
+
+func (p *TSimpleJSONProtocol) Skip(fieldType TType) (err error) {
+	return SkipDefaultDepth(p, fieldType)
+}
+
+func (p *TSimpleJSONProtocol) Transport() TTransport {
+	return p.trans
+}
+
+func (p *TSimpleJSONProtocol) OutputPreValue() error {
+	cxt := _ParseContext(p.dumpContext[len(p.dumpContext)-1])
+	switch cxt {
+	case _CONTEXT_IN_LIST, _CONTEXT_IN_OBJECT_NEXT_KEY:
+		if _, e := p.write(JSON_COMMA); e != nil {
+			return NewTProtocolException(e)
+		}
+		break
+	case _CONTEXT_IN_OBJECT_NEXT_VALUE:
+		if _, e := p.write(JSON_COLON); e != nil {
+			return NewTProtocolException(e)
+		}
+		break
+	}
+	return nil
+}
+
+func (p *TSimpleJSONProtocol) OutputPostValue() error {
+	cxt := _ParseContext(p.dumpContext[len(p.dumpContext)-1])
+	switch cxt {
+	case _CONTEXT_IN_LIST_FIRST:
+		p.dumpContext = p.dumpContext[:len(p.dumpContext)-1]
+		p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_LIST))
+		break
+	case _CONTEXT_IN_OBJECT_FIRST:
+		p.dumpContext = p.dumpContext[:len(p.dumpContext)-1]
+		p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_OBJECT_NEXT_VALUE))
+		break
+	case _CONTEXT_IN_OBJECT_NEXT_KEY:
+		p.dumpContext = p.dumpContext[:len(p.dumpContext)-1]
+		p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_OBJECT_NEXT_VALUE))
+		break
+	case _CONTEXT_IN_OBJECT_NEXT_VALUE:
+		p.dumpContext = p.dumpContext[:len(p.dumpContext)-1]
+		p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_OBJECT_NEXT_KEY))
+		break
+	}
+	return nil
+}
+
+func (p *TSimpleJSONProtocol) OutputBool(value bool) error {
+	if e := p.OutputPreValue(); e != nil {
+		return e
+	}
+	var v string
+	if value {
+		v = string(JSON_TRUE)
+	} else {
+		v = string(JSON_FALSE)
+	}
+	switch _ParseContext(p.dumpContext[len(p.dumpContext)-1]) {
+	case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY:
+		v = jsonQuote(v)
+	default:
+	}
+	if e := p.OutputStringData(v); e != nil {
+		return e
+	}
+	return p.OutputPostValue()
+}
+
+func (p *TSimpleJSONProtocol) OutputNull() error {
+	if e := p.OutputPreValue(); e != nil {
+		return e
+	}
+	if _, e := p.write(JSON_NULL); e != nil {
+		return NewTProtocolException(e)
+	}
+	return p.OutputPostValue()
+}
+
+func (p *TSimpleJSONProtocol) OutputF64(value float64) error {
+	if e := p.OutputPreValue(); e != nil {
+		return e
+	}
+	var v string
+	if math.IsNaN(value) {
+		v = string(JSON_QUOTE) + JSON_NAN + string(JSON_QUOTE)
+	} else if math.IsInf(value, 1) {
+		v = string(JSON_QUOTE) + JSON_INFINITY + string(JSON_QUOTE)
+	} else if math.IsInf(value, -1) {
+		v = string(JSON_QUOTE) + JSON_NEGATIVE_INFINITY + string(JSON_QUOTE)
+	} else {
+		v = strconv.FormatFloat(value, 'g', -1, 64)
+		switch _ParseContext(p.dumpContext[len(p.dumpContext)-1]) {
+		case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY:
+			v = string(JSON_QUOTE) + v + string(JSON_QUOTE)
+		default:
+		}
+	}
+	if e := p.OutputStringData(v); e != nil {
+		return e
+	}
+	return p.OutputPostValue()
+}
+
+func (p *TSimpleJSONProtocol) OutputI64(value int64) error {
+	if e := p.OutputPreValue(); e != nil {
+		return e
+	}
+	v := strconv.FormatInt(value, 10)
+	switch _ParseContext(p.dumpContext[len(p.dumpContext)-1]) {
+	case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY:
+		v = jsonQuote(v)
+	default:
+	}
+	if e := p.OutputStringData(v); e != nil {
+		return e
+	}
+	return p.OutputPostValue()
+}
+
+func (p *TSimpleJSONProtocol) OutputString(s string) error {
+	if e := p.OutputPreValue(); e != nil {
+		return e
+	}
+	if e := p.OutputStringData(jsonQuote(s)); e != nil {
+		return e
+	}
+	return p.OutputPostValue()
+}
+
+func (p *TSimpleJSONProtocol) OutputStringData(s string) error {
+	_, e := p.write([]byte(s))
+	return NewTProtocolException(e)
+}
+
+func (p *TSimpleJSONProtocol) OutputObjectBegin() error {
+	if e := p.OutputPreValue(); e != nil {
+		return e
+	}
+	if _, e := p.write(JSON_LBRACE); e != nil {
+		return NewTProtocolException(e)
+	}
+	p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_OBJECT_FIRST))
+	return nil
+}
+
+func (p *TSimpleJSONProtocol) OutputObjectEnd() error {
+	if _, e := p.write(JSON_RBRACE); e != nil {
+		return NewTProtocolException(e)
+	}
+	p.dumpContext = p.dumpContext[:len(p.dumpContext)-1]
+	if e := p.OutputPostValue(); e != nil {
+		return e
+	}
+	return nil
+}
+
+func (p *TSimpleJSONProtocol) OutputListBegin() error {
+	if e := p.OutputPreValue(); e != nil {
+		return e
+	}
+	if _, e := p.write(JSON_LBRACKET); e != nil {
+		return NewTProtocolException(e)
+	}
+	p.dumpContext = append(p.dumpContext, int(_CONTEXT_IN_LIST_FIRST))
+	return nil
+}
+
+func (p *TSimpleJSONProtocol) OutputListEnd() error {
+	if _, e := p.write(JSON_RBRACKET); e != nil {
+		return NewTProtocolException(e)
+	}
+	p.dumpContext = p.dumpContext[:len(p.dumpContext)-1]
+	if e := p.OutputPostValue(); e != nil {
+		return e
+	}
+	return nil
+}
+
+func (p *TSimpleJSONProtocol) OutputElemListBegin(elemType TType, size int) error {
+	if e := p.OutputListBegin(); e != nil {
+		return e
+	}
+	if e := p.WriteByte(int8(elemType)); e != nil {
+		return e
+	}
+	if e := p.WriteI64(int64(size)); e != nil {
+		return e
+	}
+	return nil
+}
+
+func (p *TSimpleJSONProtocol) ParsePreValue() error {
+	if e := p.readNonSignificantWhitespace(); e != nil {
+		return NewTProtocolException(e)
+	}
+	cxt := _ParseContext(p.parseContextStack[len(p.parseContextStack)-1])
+	b, _ := p.reader.Peek(1)
+	switch cxt {
+	case _CONTEXT_IN_LIST:
+		if len(b) > 0 {
+			switch b[0] {
+			case JSON_RBRACKET[0]:
+				return nil
+			case JSON_COMMA[0]:
+				p.reader.ReadByte()
+				if e := p.readNonSignificantWhitespace(); e != nil {
+					return NewTProtocolException(e)
+				}
+				return nil
+			default:
+				e := fmt.Errorf("Expected \"]\" or \",\" in list context, but found \"%s\"", string(b))
+				return NewTProtocolExceptionWithType(INVALID_DATA, e)
+			}
+		}
+		break
+	case _CONTEXT_IN_OBJECT_NEXT_KEY:
+		if len(b) > 0 {
+			switch b[0] {
+			case JSON_RBRACE[0]:
+				return nil
+			case JSON_COMMA[0]:
+				p.reader.ReadByte()
+				if e := p.readNonSignificantWhitespace(); e != nil {
+					return NewTProtocolException(e)
+				}
+				return nil
+			default:
+				e := fmt.Errorf("Expected \"}\" or \",\" in object context, but found \"%s\"", string(b))
+				return NewTProtocolExceptionWithType(INVALID_DATA, e)
+			}
+		}
+		break
+	case _CONTEXT_IN_OBJECT_NEXT_VALUE:
+		if len(b) > 0 {
+			switch b[0] {
+			case JSON_COLON[0]:
+				p.reader.ReadByte()
+				if e := p.readNonSignificantWhitespace(); e != nil {
+					return NewTProtocolException(e)
+				}
+				return nil
+			default:
+				e := fmt.Errorf("Expected \":\" in object context, but found \"%s\"", string(b))
+				return NewTProtocolExceptionWithType(INVALID_DATA, e)
+			}
+		}
+		break
+	}
+	return nil
+}
+
+func (p *TSimpleJSONProtocol) ParsePostValue() error {
+	if e := p.readNonSignificantWhitespace(); e != nil {
+		return NewTProtocolException(e)
+	}
+	cxt := _ParseContext(p.parseContextStack[len(p.parseContextStack)-1])
+	switch cxt {
+	case _CONTEXT_IN_LIST_FIRST:
+		p.parseContextStack = p.parseContextStack[:len(p.parseContextStack)-1]
+		p.parseContextStack = append(p.parseContextStack, int(_CONTEXT_IN_LIST))
+		break
+	case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY:
+		p.parseContextStack = p.parseContextStack[:len(p.parseContextStack)-1]
+		p.parseContextStack = append(p.parseContextStack, int(_CONTEXT_IN_OBJECT_NEXT_VALUE))
+		break
+	case _CONTEXT_IN_OBJECT_NEXT_VALUE:
+		p.parseContextStack = p.parseContextStack[:len(p.parseContextStack)-1]
+		p.parseContextStack = append(p.parseContextStack, int(_CONTEXT_IN_OBJECT_NEXT_KEY))
+		break
+	}
+	return nil
+}
+
+func (p *TSimpleJSONProtocol) readNonSignificantWhitespace() error {
+	for {
+		b, _ := p.reader.Peek(1)
+		if len(b) < 1 {
+			return nil
+		}
+		switch b[0] {
+		case ' ', '\r', '\n', '\t':
+			p.reader.ReadByte()
+			continue
+		default:
+			break
+		}
+		break
+	}
+	return nil
+}
+
+func (p *TSimpleJSONProtocol) ParseStringBody() (string, error) {
+	line, err := p.reader.ReadString(JSON_QUOTE)
+	if err != nil {
+		return "", NewTProtocolException(err)
+	}
+	l := len(line)
+	// count number of escapes to see if we need to keep going
+	i := 1
+	for ; i < l; i++ {
+		if line[l-i-1] != '\\' {
+			break
+		}
+	}
+	if i&0x01 == 1 {
+		v, ok := jsonUnquote(string(JSON_QUOTE) + line)
+		if !ok {
+			return "", NewTProtocolException(err)
+		}
+		return v, nil
+	}
+	s, err := p.ParseQuotedStringBody()
+	if err != nil {
+		return "", NewTProtocolException(err)
+	}
+	str := string(JSON_QUOTE) + line + s
+	v, ok := jsonUnquote(str)
+	if !ok {
+		e := fmt.Errorf("Unable to parse as JSON string %s", str)
+		return "", NewTProtocolExceptionWithType(INVALID_DATA, e)
+	}
+	return v, nil
+}
+
+func (p *TSimpleJSONProtocol) ParseQuotedStringBody() (string, error) {
+	line, err := p.reader.ReadString(JSON_QUOTE)
+	if err != nil {
+		return "", NewTProtocolException(err)
+	}
+	l := len(line)
+	// count number of escapes to see if we need to keep going
+	i := 1
+	for ; i < l; i++ {
+		if line[l-i-1] != '\\' {
+			break
+		}
+	}
+	if i&0x01 == 1 {
+		return line, nil
+	}
+	s, err := p.ParseQuotedStringBody()
+	if err != nil {
+		return "", NewTProtocolException(err)
+	}
+	v := line + s
+	return v, nil
+}
+
+func (p *TSimpleJSONProtocol) ParseBase64EncodedBody() ([]byte, error) {
+	line, err := p.reader.ReadBytes(JSON_QUOTE)
+	if err != nil {
+		return line, NewTProtocolException(err)
+	}
+	line2 := line[0 : len(line)-1]
+	l := len(line2)
+	if (l % 4) != 0 {
+		pad := 4 - (l % 4)
+		fill := [...]byte{'=', '=', '='}
+		line2 = append(line2, fill[:pad]...)
+		l = len(line2)
+	}
+	output := make([]byte, base64.StdEncoding.DecodedLen(l))
+	n, err := base64.StdEncoding.Decode(output, line2)
+	return output[0:n], NewTProtocolException(err)
+}
+
+func (p *TSimpleJSONProtocol) ParseI64() (int64, bool, error) {
+	if err := p.ParsePreValue(); err != nil {
+		return 0, false, err
+	}
+	var value int64
+	var isnull bool
+	if p.safePeekContains(JSON_NULL) {
+		p.reader.Read(make([]byte, len(JSON_NULL)))
+		isnull = true
+	} else {
+		num, err := p.readNumeric()
+		isnull = (num == nil)
+		if !isnull {
+			value = num.Int64()
+		}
+		if err != nil {
+			return value, isnull, err
+		}
+	}
+	return value, isnull, p.ParsePostValue()
+}
+
+func (p *TSimpleJSONProtocol) ParseF64() (float64, bool, error) {
+	if err := p.ParsePreValue(); err != nil {
+		return 0, false, err
+	}
+	var value float64
+	var isnull bool
+	if p.safePeekContains(JSON_NULL) {
+		p.reader.Read(make([]byte, len(JSON_NULL)))
+		isnull = true
+	} else {
+		num, err := p.readNumeric()
+		isnull = (num == nil)
+		if !isnull {
+			value = num.Float64()
+		}
+		if err != nil {
+			return value, isnull, err
+		}
+	}
+	return value, isnull, p.ParsePostValue()
+}
+
+func (p *TSimpleJSONProtocol) ParseObjectStart() (bool, error) {
+	if err := p.ParsePreValue(); err != nil {
+		return false, err
+	}
+	var b []byte
+	b, err := p.reader.Peek(1)
+	if err != nil {
+		return false, err
+	}
+	if len(b) > 0 && b[0] == JSON_LBRACE[0] {
+		p.reader.ReadByte()
+		p.parseContextStack = append(p.parseContextStack, int(_CONTEXT_IN_OBJECT_FIRST))
+		return false, nil
+	} else if p.safePeekContains(JSON_NULL) {
+		return true, nil
+	}
+	e := fmt.Errorf("Expected '{' or null, but found '%s'", string(b))
+	return false, NewTProtocolExceptionWithType(INVALID_DATA, e)
+}
+
+func (p *TSimpleJSONProtocol) ParseObjectEnd() error {
+	if isNull, err := p.readIfNull(); isNull || err != nil {
+		return err
+	}
+	cxt := _ParseContext(p.parseContextStack[len(p.parseContextStack)-1])
+	if (cxt != _CONTEXT_IN_OBJECT_FIRST) && (cxt != _CONTEXT_IN_OBJECT_NEXT_KEY) {
+		e := fmt.Errorf("Expected to be in the Object Context, but not in Object Context (%d)", cxt)
+		return NewTProtocolExceptionWithType(INVALID_DATA, e)
+	}
+	line, err := p.reader.ReadString(JSON_RBRACE[0])
+	if err != nil {
+		return NewTProtocolException(err)
+	}
+	for _, char := range line {
+		switch char {
+		default:
+			e := fmt.Errorf("Expecting end of object \"}\", but found: \"%s\"", line)
+			return NewTProtocolExceptionWithType(INVALID_DATA, e)
+		case ' ', '\n', '\r', '\t', '}':
+			break
+		}
+	}
+	p.parseContextStack = p.parseContextStack[:len(p.parseContextStack)-1]
+	return p.ParsePostValue()
+}
+
+func (p *TSimpleJSONProtocol) ParseListBegin() (isNull bool, err error) {
+	if e := p.ParsePreValue(); e != nil {
+		return false, e
+	}
+	var b []byte
+	b, err = p.reader.Peek(1)
+	if err != nil {
+		return false, err
+	}
+	if len(b) >= 1 && b[0] == JSON_LBRACKET[0] {
+		p.parseContextStack = append(p.parseContextStack, int(_CONTEXT_IN_LIST_FIRST))
+		p.reader.ReadByte()
+		isNull = false
+	} else if p.safePeekContains(JSON_NULL) {
+		isNull = true
+	} else {
+		err = fmt.Errorf("Expected \"null\" or \"[\", received %q", b)
+	}
+	return isNull, NewTProtocolExceptionWithType(INVALID_DATA, err)
+}
+
+func (p *TSimpleJSONProtocol) ParseElemListBegin() (elemType TType, size int, e error) {
+	if isNull, e := p.ParseListBegin(); isNull || e != nil {
+		return VOID, 0, e
+	}
+	bElemType, err := p.ReadByte()
+	elemType = TType(bElemType)
+	if err != nil {
+		return elemType, size, err
+	}
+	nSize, err2 := p.ReadI64()
+	size = int(nSize)
+	return elemType, size, err2
+}
+
+func (p *TSimpleJSONProtocol) ParseListEnd() error {
+	if isNull, err := p.readIfNull(); isNull || err != nil {
+		return err
+	}
+	cxt := _ParseContext(p.parseContextStack[len(p.parseContextStack)-1])
+	if cxt != _CONTEXT_IN_LIST {
+		e := fmt.Errorf("Expected to be in the List Context, but not in List Context (%d)", cxt)
+		return NewTProtocolExceptionWithType(INVALID_DATA, e)
+	}
+	line, err := p.reader.ReadString(JSON_RBRACKET[0])
+	if err != nil {
+		return NewTProtocolException(err)
+	}
+	for _, char := range line {
+		switch char {
+		default:
+			e := fmt.Errorf("Expecting end of list \"]\", but found: \"%s\"", line)
+			return NewTProtocolExceptionWithType(INVALID_DATA, e)
+		case ' ', '\n', '\r', '\t', rune(JSON_RBRACKET[0]):
+			break
+		}
+	}
+	p.parseContextStack = p.parseContextStack[:len(p.parseContextStack)-1]
+	if _ParseContext(p.parseContextStack[len(p.parseContextStack)-1]) == _CONTEXT_IN_TOPLEVEL {
+		return nil
+	}
+	return p.ParsePostValue()
+}
+
+func (p *TSimpleJSONProtocol) readSingleValue() (interface{}, TType, error) {
+	e := p.readNonSignificantWhitespace()
+	if e != nil {
+		return nil, VOID, NewTProtocolException(e)
+	}
+	b, e := p.reader.Peek(1)
+	if len(b) > 0 {
+		c := b[0]
+		switch c {
+		case JSON_NULL[0]:
+			buf := make([]byte, len(JSON_NULL))
+			_, e := p.reader.Read(buf)
+			if e != nil {
+				return nil, VOID, NewTProtocolException(e)
+			}
+			if string(JSON_NULL) != string(buf) {
+				e = mismatch(string(JSON_NULL), string(buf))
+				return nil, VOID, NewTProtocolExceptionWithType(INVALID_DATA, e)
+			}
+			return nil, VOID, nil
+		case JSON_QUOTE:
+			p.reader.ReadByte()
+			v, e := p.ParseStringBody()
+			if e != nil {
+				return v, UTF8, NewTProtocolException(e)
+			}
+			if v == JSON_INFINITY {
+				return INFINITY, DOUBLE, nil
+			} else if v == JSON_NEGATIVE_INFINITY {
+				return NEGATIVE_INFINITY, DOUBLE, nil
+			} else if v == JSON_NAN {
+				return NAN, DOUBLE, nil
+			}
+			return v, UTF8, nil
+		case JSON_TRUE[0]:
+			buf := make([]byte, len(JSON_TRUE))
+			_, e := p.reader.Read(buf)
+			if e != nil {
+				return true, BOOL, NewTProtocolException(e)
+			}
+			if string(JSON_TRUE) != string(buf) {
+				e := mismatch(string(JSON_TRUE), string(buf))
+				return true, BOOL, NewTProtocolExceptionWithType(INVALID_DATA, e)
+			}
+			return true, BOOL, nil
+		case JSON_FALSE[0]:
+			buf := make([]byte, len(JSON_FALSE))
+			_, e := p.reader.Read(buf)
+			if e != nil {
+				return false, BOOL, NewTProtocolException(e)
+			}
+			if string(JSON_FALSE) != string(buf) {
+				e := mismatch(string(JSON_FALSE), string(buf))
+				return false, BOOL, NewTProtocolExceptionWithType(INVALID_DATA, e)
+			}
+			return false, BOOL, nil
+		case JSON_LBRACKET[0]:
+			_, e := p.reader.ReadByte()
+			return make([]interface{}, 0), LIST, NewTProtocolException(e)
+		case JSON_LBRACE[0]:
+			_, e := p.reader.ReadByte()
+			return make(map[string]interface{}), STRUCT, NewTProtocolException(e)
+		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'e', 'E', '.', '+', '-', JSON_INFINITY[0], JSON_NAN[0]:
+			// assume numeric
+			v, e := p.readNumeric()
+			return v, DOUBLE, e
+		default:
+			e := fmt.Errorf("Expected element in list but found '%s' while parsing JSON.", string(c))
+			return nil, VOID, NewTProtocolExceptionWithType(INVALID_DATA, e)
+		}
+	}
+	e = fmt.Errorf("Cannot read a single element while parsing JSON.")
+	return nil, VOID, NewTProtocolExceptionWithType(INVALID_DATA, e)
+
+}
+
+func (p *TSimpleJSONProtocol) readIfNull() (bool, error) {
+	cont := true
+	for cont {
+		b, _ := p.reader.Peek(1)
+		if len(b) < 1 {
+			return false, nil
+		}
+		switch b[0] {
+		default:
+			return false, nil
+		case JSON_NULL[0]:
+			cont = false
+			break
+		case ' ', '\n', '\r', '\t':
+			p.reader.ReadByte()
+			break
+		}
+	}
+	if p.safePeekContains(JSON_NULL) {
+		p.reader.Read(make([]byte, len(JSON_NULL)))
+		return true, nil
+	}
+	return false, nil
+}
+
+func (p *TSimpleJSONProtocol) readQuoteIfNext() {
+	b, _ := p.reader.Peek(1)
+	if len(b) > 0 && b[0] == JSON_QUOTE {
+		p.reader.ReadByte()
+	}
+}
+
+func (p *TSimpleJSONProtocol) readNumeric() (Numeric, error) {
+	isNull, err := p.readIfNull()
+	if isNull || err != nil {
+		return NUMERIC_NULL, err
+	}
+	hasDecimalPoint := false
+	nextCanBeSign := true
+	hasE := false
+	MAX_LEN := 40
+	buf := bytes.NewBuffer(make([]byte, 0, MAX_LEN))
+	continueFor := true
+	inQuotes := false
+	for continueFor {
+		c, err := p.reader.ReadByte()
+		if err != nil {
+			if err == io.EOF {
+				break
+			}
+			return NUMERIC_NULL, NewTProtocolException(err)
+		}
+		switch c {
+		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+			buf.WriteByte(c)
+			nextCanBeSign = false
+		case '.':
+			if hasDecimalPoint {
+				e := fmt.Errorf("Unable to parse number with multiple decimal points '%s.'", buf.String())
+				return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e)
+			}
+			if hasE {
+				e := fmt.Errorf("Unable to parse number with decimal points in the exponent '%s.'", buf.String())
+				return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e)
+			}
+			buf.WriteByte(c)
+			hasDecimalPoint, nextCanBeSign = true, false
+		case 'e', 'E':
+			if hasE {
+				e := fmt.Errorf("Unable to parse number with multiple exponents '%s%c'", buf.String(), c)
+				return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e)
+			}
+			buf.WriteByte(c)
+			hasE, nextCanBeSign = true, true
+		case '-', '+':
+			if !nextCanBeSign {
+				e := fmt.Errorf("Negative sign within number")
+				return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e)
+			}
+			buf.WriteByte(c)
+			nextCanBeSign = false
+		case ' ', 0, '\t', '\n', '\r', JSON_RBRACE[0], JSON_RBRACKET[0], JSON_COMMA[0], JSON_COLON[0]:
+			p.reader.UnreadByte()
+			continueFor = false
+		case JSON_NAN[0]:
+			if buf.Len() == 0 {
+				buffer := make([]byte, len(JSON_NAN))
+				buffer[0] = c
+				_, e := p.reader.Read(buffer[1:])
+				if e != nil {
+					return NUMERIC_NULL, NewTProtocolException(e)
+				}
+				if JSON_NAN != string(buffer) {
+					e := mismatch(JSON_NAN, string(buffer))
+					return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e)
+				}
+				if inQuotes {
+					p.readQuoteIfNext()
+				}
+				return NAN, nil
+			} else {
+				e := fmt.Errorf("Unable to parse number starting with character '%c'", c)
+				return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e)
+			}
+		case JSON_INFINITY[0]:
+			if buf.Len() == 0 || (buf.Len() == 1 && buf.Bytes()[0] == '+') {
+				buffer := make([]byte, len(JSON_INFINITY))
+				buffer[0] = c
+				_, e := p.reader.Read(buffer[1:])
+				if e != nil {
+					return NUMERIC_NULL, NewTProtocolException(e)
+				}
+				if JSON_INFINITY != string(buffer) {
+					e := mismatch(JSON_INFINITY, string(buffer))
+					return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e)
+				}
+				if inQuotes {
+					p.readQuoteIfNext()
+				}
+				return INFINITY, nil
+			} else if buf.Len() == 1 && buf.Bytes()[0] == JSON_NEGATIVE_INFINITY[0] {
+				buffer := make([]byte, len(JSON_NEGATIVE_INFINITY))
+				buffer[0] = JSON_NEGATIVE_INFINITY[0]
+				buffer[1] = c
+				_, e := p.reader.Read(buffer[2:])
+				if e != nil {
+					return NUMERIC_NULL, NewTProtocolException(e)
+				}
+				if JSON_NEGATIVE_INFINITY != string(buffer) {
+					e := mismatch(JSON_NEGATIVE_INFINITY, string(buffer))
+					return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e)
+				}
+				if inQuotes {
+					p.readQuoteIfNext()
+				}
+				return NEGATIVE_INFINITY, nil
+			} else {
+				e := fmt.Errorf("Unable to parse number starting with character '%c' due to existing buffer %s", c, buf.String())
+				return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e)
+			}
+		case JSON_QUOTE:
+			if !inQuotes {
+				inQuotes = true
+			} else {
+				break
+			}
+		default:
+			e := fmt.Errorf("Unable to parse number starting with character '%c'", c)
+			return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e)
+		}
+	}
+	if buf.Len() == 0 {
+		e := fmt.Errorf("Unable to parse number from empty string ''")
+		return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e)
+	}
+	return NewNumericFromJSONString(buf.String(), false), nil
+}
+
+// Safely peeks into the buffer, reading only what is necessary
+func (p *TSimpleJSONProtocol) safePeekContains(b []byte) bool {
+	for i := 0; i < len(b); i++ {
+		a, _ := p.reader.Peek(i + 1)
+		if len(a) == 0 || a[i] != b[i] {
+			return false
+		}
+	}
+	return true
+}
+
+// Reset the context stack to its initial state.
+func (p *TSimpleJSONProtocol) resetContextStack() {
+	p.parseContextStack = []int{int(_CONTEXT_IN_TOPLEVEL)}
+	p.dumpContext = []int{int(_CONTEXT_IN_TOPLEVEL)}
+}
+
+func (p *TSimpleJSONProtocol) write(b []byte) (int, error) {
+	n, err := p.writer.Write(b)
+	if err != nil {
+		p.writer.Reset(p.trans) // THRIFT-3735
+	}
+	return n, err
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift/transport.go b/vendor/github.com/uber/jaeger-client-go/thrift/transport.go
new file mode 100644
index 0000000..4538996
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift/transport.go
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+	"errors"
+	"io"
+)
+
+var errTransportInterrupted = errors.New("Transport Interrupted")
+
+type Flusher interface {
+	Flush() (err error)
+}
+
+type ReadSizeProvider interface {
+	RemainingBytes() (num_bytes uint64)
+}
+
+
+// Encapsulates the I/O layer
+type TTransport interface {
+	io.ReadWriteCloser
+	Flusher
+	ReadSizeProvider
+
+	// Opens the transport for communication
+	Open() error
+
+	// Returns true if the transport is open
+	IsOpen() bool
+}
+
+type stringWriter interface {
+	WriteString(s string) (n int, err error)
+}
+
+
+// This is "enchanced" transport with extra capabilities. You need to use one of these
+// to construct protocol.
+// Notably, TSocket does not implement this interface, and it is always a mistake to use
+// TSocket directly in protocol.
+type TRichTransport interface {
+	io.ReadWriter
+	io.ByteReader
+	io.ByteWriter
+	stringWriter
+	Flusher
+	ReadSizeProvider
+}
+
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift/transport_exception.go b/vendor/github.com/uber/jaeger-client-go/thrift/transport_exception.go
new file mode 100644
index 0000000..9505b44
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift/transport_exception.go
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+	"errors"
+	"io"
+)
+
+type timeoutable interface {
+	Timeout() bool
+}
+
+// Thrift Transport exception
+type TTransportException interface {
+	TException
+	TypeId() int
+	Err() error
+}
+
+const (
+	UNKNOWN_TRANSPORT_EXCEPTION = 0
+	NOT_OPEN                    = 1
+	ALREADY_OPEN                = 2
+	TIMED_OUT                   = 3
+	END_OF_FILE                 = 4
+)
+
+type tTransportException struct {
+	typeId int
+	err    error
+}
+
+func (p *tTransportException) TypeId() int {
+	return p.typeId
+}
+
+func (p *tTransportException) Error() string {
+	return p.err.Error()
+}
+
+func (p *tTransportException) Err() error {
+	return p.err
+}
+
+func NewTTransportException(t int, e string) TTransportException {
+	return &tTransportException{typeId: t, err: errors.New(e)}
+}
+
+func NewTTransportExceptionFromError(e error) TTransportException {
+	if e == nil {
+		return nil
+	}
+
+	if t, ok := e.(TTransportException); ok {
+		return t
+	}
+
+	switch v := e.(type) {
+	case TTransportException:
+		return v
+	case timeoutable:
+		if v.Timeout() {
+			return &tTransportException{typeId: TIMED_OUT, err: e}
+		}
+	}
+
+	if e == io.EOF {
+		return &tTransportException{typeId: END_OF_FILE, err: e}
+	}
+
+	return &tTransportException{typeId: UNKNOWN_TRANSPORT_EXCEPTION, err: e}
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift/transport_factory.go b/vendor/github.com/uber/jaeger-client-go/thrift/transport_factory.go
new file mode 100644
index 0000000..533d1b4
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift/transport_factory.go
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+// Factory class used to create wrapped instance of Transports.
+// This is used primarily in servers, which get Transports from
+// a ServerTransport and then may want to mutate them (i.e. create
+// a BufferedTransport from the underlying base transport)
+type TTransportFactory interface {
+	GetTransport(trans TTransport) TTransport
+}
+
+type tTransportFactory struct{}
+
+// Return a wrapped instance of the base Transport.
+func (p *tTransportFactory) GetTransport(trans TTransport) TTransport {
+	return trans
+}
+
+func NewTTransportFactory() TTransportFactory {
+	return &tTransportFactory{}
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/thrift/type.go b/vendor/github.com/uber/jaeger-client-go/thrift/type.go
new file mode 100644
index 0000000..4292ffc
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/thrift/type.go
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+// Type constants in the Thrift protocol
+type TType byte
+
+const (
+	STOP   = 0
+	VOID   = 1
+	BOOL   = 2
+	BYTE   = 3
+	I08    = 3
+	DOUBLE = 4
+	I16    = 6
+	I32    = 8
+	I64    = 10
+	STRING = 11
+	UTF7   = 11
+	STRUCT = 12
+	MAP    = 13
+	SET    = 14
+	LIST   = 15
+	UTF8   = 16
+	UTF16  = 17
+	//BINARY = 18   wrong and unusued
+)
+
+var typeNames = map[int]string{
+	STOP:   "STOP",
+	VOID:   "VOID",
+	BOOL:   "BOOL",
+	BYTE:   "BYTE",
+	DOUBLE: "DOUBLE",
+	I16:    "I16",
+	I32:    "I32",
+	I64:    "I64",
+	STRING: "STRING",
+	STRUCT: "STRUCT",
+	MAP:    "MAP",
+	SET:    "SET",
+	LIST:   "LIST",
+	UTF8:   "UTF8",
+	UTF16:  "UTF16",
+}
+
+func (p TType) String() string {
+	if s, ok := typeNames[int(p)]; ok {
+		return s
+	}
+	return "Unknown"
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/tracer.go b/vendor/github.com/uber/jaeger-client-go/tracer.go
new file mode 100644
index 0000000..8a3fc97
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/tracer.go
@@ -0,0 +1,488 @@
+// Copyright (c) 2017-2018 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import (
+	"fmt"
+	"io"
+	"math/rand"
+	"os"
+	"reflect"
+	"strconv"
+	"sync"
+	"time"
+
+	"github.com/opentracing/opentracing-go"
+	"github.com/opentracing/opentracing-go/ext"
+
+	"github.com/uber/jaeger-client-go/internal/baggage"
+	"github.com/uber/jaeger-client-go/internal/throttler"
+	"github.com/uber/jaeger-client-go/log"
+	"github.com/uber/jaeger-client-go/utils"
+)
+
+// Tracer implements opentracing.Tracer.
+type Tracer struct {
+	serviceName string
+	hostIPv4    uint32 // this is for zipkin endpoint conversion
+
+	sampler  SamplerV2
+	reporter Reporter
+	metrics  Metrics
+	logger   log.DebugLogger
+
+	timeNow      func() time.Time
+	randomNumber func() uint64
+
+	options struct {
+		gen128Bit                   bool // whether to generate 128bit trace IDs
+		zipkinSharedRPCSpan         bool
+		highTraceIDGenerator        func() uint64 // custom high trace ID generator
+		maxTagValueLength           int
+		noDebugFlagOnForcedSampling bool
+		maxLogsPerSpan              int
+		// more options to come
+	}
+	// allocator of Span objects
+	spanAllocator SpanAllocator
+
+	injectors  map[interface{}]Injector
+	extractors map[interface{}]Extractor
+
+	observer compositeObserver
+
+	tags    []Tag
+	process Process
+
+	baggageRestrictionManager baggage.RestrictionManager
+	baggageSetter             *baggageSetter
+
+	debugThrottler throttler.Throttler
+}
+
+// NewTracer creates Tracer implementation that reports tracing to Jaeger.
+// The returned io.Closer can be used in shutdown hooks to ensure that the internal
+// queue of the Reporter is drained and all buffered spans are submitted to collectors.
+// TODO (breaking change) return *Tracer only, without closer.
+func NewTracer(
+	serviceName string,
+	sampler Sampler,
+	reporter Reporter,
+	options ...TracerOption,
+) (opentracing.Tracer, io.Closer) {
+	t := &Tracer{
+		serviceName:   serviceName,
+		sampler:       samplerV1toV2(sampler),
+		reporter:      reporter,
+		injectors:     make(map[interface{}]Injector),
+		extractors:    make(map[interface{}]Extractor),
+		metrics:       *NewNullMetrics(),
+		spanAllocator: simpleSpanAllocator{},
+	}
+
+	for _, option := range options {
+		option(t)
+	}
+
+	// register default injectors/extractors unless they are already provided via options
+	textPropagator := NewTextMapPropagator(getDefaultHeadersConfig(), t.metrics)
+	t.addCodec(opentracing.TextMap, textPropagator, textPropagator)
+
+	httpHeaderPropagator := NewHTTPHeaderPropagator(getDefaultHeadersConfig(), t.metrics)
+	t.addCodec(opentracing.HTTPHeaders, httpHeaderPropagator, httpHeaderPropagator)
+
+	binaryPropagator := NewBinaryPropagator(t)
+	t.addCodec(opentracing.Binary, binaryPropagator, binaryPropagator)
+
+	// TODO remove after TChannel supports OpenTracing
+	interopPropagator := &jaegerTraceContextPropagator{tracer: t}
+	t.addCodec(SpanContextFormat, interopPropagator, interopPropagator)
+
+	zipkinPropagator := &zipkinPropagator{tracer: t}
+	t.addCodec(ZipkinSpanFormat, zipkinPropagator, zipkinPropagator)
+
+	if t.baggageRestrictionManager != nil {
+		t.baggageSetter = newBaggageSetter(t.baggageRestrictionManager, &t.metrics)
+	} else {
+		t.baggageSetter = newBaggageSetter(baggage.NewDefaultRestrictionManager(0), &t.metrics)
+	}
+	if t.debugThrottler == nil {
+		t.debugThrottler = throttler.DefaultThrottler{}
+	}
+
+	if t.randomNumber == nil {
+		seedGenerator := utils.NewRand(time.Now().UnixNano())
+		pool := sync.Pool{
+			New: func() interface{} {
+				return rand.NewSource(seedGenerator.Int63())
+			},
+		}
+
+		t.randomNumber = func() uint64 {
+			generator := pool.Get().(rand.Source)
+			number := uint64(generator.Int63())
+			pool.Put(generator)
+			return number
+		}
+	}
+	if t.timeNow == nil {
+		t.timeNow = time.Now
+	}
+	if t.logger == nil {
+		t.logger = log.NullLogger
+	}
+	// Set tracer-level tags
+	t.tags = append(t.tags, Tag{key: JaegerClientVersionTagKey, value: JaegerClientVersion})
+	if hostname, err := os.Hostname(); err == nil {
+		t.tags = append(t.tags, Tag{key: TracerHostnameTagKey, value: hostname})
+	}
+	if ipval, ok := t.getTag(TracerIPTagKey); ok {
+		ipv4, err := utils.ParseIPToUint32(ipval.(string))
+		if err != nil {
+			t.hostIPv4 = 0
+			t.logger.Error("Unable to convert the externally provided ip to uint32: " + err.Error())
+		} else {
+			t.hostIPv4 = ipv4
+		}
+	} else if ip, err := utils.HostIP(); err == nil {
+		t.tags = append(t.tags, Tag{key: TracerIPTagKey, value: ip.String()})
+		t.hostIPv4 = utils.PackIPAsUint32(ip)
+	} else {
+		t.logger.Error("Unable to determine this host's IP address: " + err.Error())
+	}
+
+	if t.options.gen128Bit {
+		if t.options.highTraceIDGenerator == nil {
+			t.options.highTraceIDGenerator = t.randomNumber
+		}
+	} else if t.options.highTraceIDGenerator != nil {
+		t.logger.Error("Overriding high trace ID generator but not generating " +
+			"128 bit trace IDs, consider enabling the \"Gen128Bit\" option")
+	}
+	if t.options.maxTagValueLength == 0 {
+		t.options.maxTagValueLength = DefaultMaxTagValueLength
+	}
+	t.process = Process{
+		Service: serviceName,
+		UUID:    strconv.FormatUint(t.randomNumber(), 16),
+		Tags:    t.tags,
+	}
+	if throttler, ok := t.debugThrottler.(ProcessSetter); ok {
+		throttler.SetProcess(t.process)
+	}
+
+	return t, t
+}
+
+// addCodec adds registers injector and extractor for given propagation format if not already defined.
+func (t *Tracer) addCodec(format interface{}, injector Injector, extractor Extractor) {
+	if _, ok := t.injectors[format]; !ok {
+		t.injectors[format] = injector
+	}
+	if _, ok := t.extractors[format]; !ok {
+		t.extractors[format] = extractor
+	}
+}
+
+// StartSpan implements StartSpan() method of opentracing.Tracer.
+func (t *Tracer) StartSpan(
+	operationName string,
+	options ...opentracing.StartSpanOption,
+) opentracing.Span {
+	sso := opentracing.StartSpanOptions{}
+	for _, o := range options {
+		o.Apply(&sso)
+	}
+	return t.startSpanWithOptions(operationName, sso)
+}
+
+func (t *Tracer) startSpanWithOptions(
+	operationName string,
+	options opentracing.StartSpanOptions,
+) opentracing.Span {
+	if options.StartTime.IsZero() {
+		options.StartTime = t.timeNow()
+	}
+
+	// Predicate whether the given span context is a valid reference
+	// which may be used as parent / debug ID / baggage items source
+	isValidReference := func(ctx SpanContext) bool {
+		return ctx.IsValid() || ctx.isDebugIDContainerOnly() || len(ctx.baggage) != 0
+	}
+
+	var references []Reference
+	var parent SpanContext
+	var hasParent bool // need this because `parent` is a value, not reference
+	var ctx SpanContext
+	var isSelfRef bool
+	for _, ref := range options.References {
+		ctxRef, ok := ref.ReferencedContext.(SpanContext)
+		if !ok {
+			t.logger.Error(fmt.Sprintf(
+				"Reference contains invalid type of SpanReference: %s",
+				reflect.ValueOf(ref.ReferencedContext)))
+			continue
+		}
+		if !isValidReference(ctxRef) {
+			continue
+		}
+
+		if ref.Type == selfRefType {
+			isSelfRef = true
+			ctx = ctxRef
+			continue
+		}
+
+		references = append(references, Reference{Type: ref.Type, Context: ctxRef})
+
+		if !hasParent {
+			parent = ctxRef
+			hasParent = ref.Type == opentracing.ChildOfRef
+		}
+	}
+	if !hasParent && isValidReference(parent) {
+		// If ChildOfRef wasn't found but a FollowFromRef exists, use the context from
+		// the FollowFromRef as the parent
+		hasParent = true
+	}
+
+	rpcServer := false
+	if v, ok := options.Tags[ext.SpanKindRPCServer.Key]; ok {
+		rpcServer = (v == ext.SpanKindRPCServerEnum || v == string(ext.SpanKindRPCServerEnum))
+	}
+
+	var internalTags []Tag
+	newTrace := false
+	if !isSelfRef {
+		if !hasParent || !parent.IsValid() {
+			newTrace = true
+			ctx.traceID.Low = t.randomID()
+			if t.options.gen128Bit {
+				ctx.traceID.High = t.options.highTraceIDGenerator()
+			}
+			ctx.spanID = SpanID(ctx.traceID.Low)
+			ctx.parentID = 0
+			ctx.samplingState = &samplingState{
+				localRootSpan: ctx.spanID,
+			}
+			if hasParent && parent.isDebugIDContainerOnly() && t.isDebugAllowed(operationName) {
+				ctx.samplingState.setDebugAndSampled()
+				internalTags = append(internalTags, Tag{key: JaegerDebugHeader, value: parent.debugID})
+			}
+		} else {
+			ctx.traceID = parent.traceID
+			if rpcServer && t.options.zipkinSharedRPCSpan {
+				// Support Zipkin's one-span-per-RPC model
+				ctx.spanID = parent.spanID
+				ctx.parentID = parent.parentID
+			} else {
+				ctx.spanID = SpanID(t.randomID())
+				ctx.parentID = parent.spanID
+			}
+			ctx.samplingState = parent.samplingState
+			if parent.remote {
+				ctx.samplingState.setFinal()
+				ctx.samplingState.localRootSpan = ctx.spanID
+			}
+		}
+		if hasParent {
+			// copy baggage items
+			if l := len(parent.baggage); l > 0 {
+				ctx.baggage = make(map[string]string, len(parent.baggage))
+				for k, v := range parent.baggage {
+					ctx.baggage[k] = v
+				}
+			}
+		}
+	}
+
+	sp := t.newSpan()
+	sp.context = ctx
+	sp.tracer = t
+	sp.operationName = operationName
+	sp.startTime = options.StartTime
+	sp.duration = 0
+	sp.references = references
+	sp.firstInProcess = rpcServer || sp.context.parentID == 0
+
+	if !sp.isSamplingFinalized() {
+		decision := t.sampler.OnCreateSpan(sp)
+		sp.applySamplingDecision(decision, false)
+	}
+	sp.observer = t.observer.OnStartSpan(sp, operationName, options)
+
+	if tagsTotalLength := len(options.Tags) + len(internalTags); tagsTotalLength > 0 {
+		if sp.tags == nil || cap(sp.tags) < tagsTotalLength {
+			sp.tags = make([]Tag, 0, tagsTotalLength)
+		}
+		sp.tags = append(sp.tags, internalTags...)
+		for k, v := range options.Tags {
+			sp.setTagInternal(k, v, false)
+		}
+	}
+	t.emitNewSpanMetrics(sp, newTrace)
+	return sp
+}
+
+// Inject implements Inject() method of opentracing.Tracer
+func (t *Tracer) Inject(ctx opentracing.SpanContext, format interface{}, carrier interface{}) error {
+	c, ok := ctx.(SpanContext)
+	if !ok {
+		return opentracing.ErrInvalidSpanContext
+	}
+	if injector, ok := t.injectors[format]; ok {
+		return injector.Inject(c, carrier)
+	}
+	return opentracing.ErrUnsupportedFormat
+}
+
+// Extract implements Extract() method of opentracing.Tracer
+func (t *Tracer) Extract(
+	format interface{},
+	carrier interface{},
+) (opentracing.SpanContext, error) {
+	if extractor, ok := t.extractors[format]; ok {
+		spanCtx, err := extractor.Extract(carrier)
+		if err != nil {
+			return nil, err // ensure returned spanCtx is nil
+		}
+		spanCtx.remote = true
+		return spanCtx, nil
+	}
+	return nil, opentracing.ErrUnsupportedFormat
+}
+
+// Close releases all resources used by the Tracer and flushes any remaining buffered spans.
+func (t *Tracer) Close() error {
+	t.logger.Debugf("closing tracer")
+	t.reporter.Close()
+	t.sampler.Close()
+	if mgr, ok := t.baggageRestrictionManager.(io.Closer); ok {
+		_ = mgr.Close()
+	}
+	if throttler, ok := t.debugThrottler.(io.Closer); ok {
+		_ = throttler.Close()
+	}
+	return nil
+}
+
+// Tags returns a slice of tracer-level tags.
+func (t *Tracer) Tags() []opentracing.Tag {
+	tags := make([]opentracing.Tag, len(t.tags))
+	for i, tag := range t.tags {
+		tags[i] = opentracing.Tag{Key: tag.key, Value: tag.value}
+	}
+	return tags
+}
+
+// getTag returns the value of specific tag, if not exists, return nil.
+// TODO only used by tests, move there.
+func (t *Tracer) getTag(key string) (interface{}, bool) {
+	for _, tag := range t.tags {
+		if tag.key == key {
+			return tag.value, true
+		}
+	}
+	return nil, false
+}
+
+// newSpan returns an instance of a clean Span object.
+// If options.PoolSpans is true, the spans are retrieved from an object pool.
+func (t *Tracer) newSpan() *Span {
+	return t.spanAllocator.Get()
+}
+
+// emitNewSpanMetrics generates metrics on the number of started spans and traces.
+// newTrace param: we cannot simply check for parentID==0 because in Zipkin model the
+// server-side RPC span has the exact same trace/span/parent IDs as the
+// calling client-side span, but obviously the server side span is
+// no longer a root span of the trace.
+func (t *Tracer) emitNewSpanMetrics(sp *Span, newTrace bool) {
+	if !sp.isSamplingFinalized() {
+		t.metrics.SpansStartedDelayedSampling.Inc(1)
+		if newTrace {
+			t.metrics.TracesStartedDelayedSampling.Inc(1)
+		}
+		// joining a trace is not possible, because sampling decision inherited from upstream is final
+	} else if sp.context.IsSampled() {
+		t.metrics.SpansStartedSampled.Inc(1)
+		if newTrace {
+			t.metrics.TracesStartedSampled.Inc(1)
+		} else if sp.firstInProcess {
+			t.metrics.TracesJoinedSampled.Inc(1)
+		}
+	} else {
+		t.metrics.SpansStartedNotSampled.Inc(1)
+		if newTrace {
+			t.metrics.TracesStartedNotSampled.Inc(1)
+		} else if sp.firstInProcess {
+			t.metrics.TracesJoinedNotSampled.Inc(1)
+		}
+	}
+}
+
+func (t *Tracer) reportSpan(sp *Span) {
+	if !sp.isSamplingFinalized() {
+		t.metrics.SpansFinishedDelayedSampling.Inc(1)
+	} else if sp.context.IsSampled() {
+		t.metrics.SpansFinishedSampled.Inc(1)
+	} else {
+		t.metrics.SpansFinishedNotSampled.Inc(1)
+	}
+
+	// Note: if the reporter is processing Span asynchronously then it needs to Retain() the span,
+	// and then Release() it when no longer needed.
+	// Otherwise, the span may be reused for another trace and its data may be overwritten.
+	if sp.context.IsSampled() {
+		t.reporter.Report(sp)
+	}
+
+	sp.Release()
+}
+
+// randomID generates a random trace/span ID, using tracer.random() generator.
+// It never returns 0.
+func (t *Tracer) randomID() uint64 {
+	val := t.randomNumber()
+	for val == 0 {
+		val = t.randomNumber()
+	}
+	return val
+}
+
+// (NB) span must hold the lock before making this call
+func (t *Tracer) setBaggage(sp *Span, key, value string) {
+	t.baggageSetter.setBaggage(sp, key, value)
+}
+
+// (NB) span must hold the lock before making this call
+func (t *Tracer) isDebugAllowed(operation string) bool {
+	return t.debugThrottler.IsAllowed(operation)
+}
+
+// Sampler returns the sampler given to the tracer at creation.
+func (t *Tracer) Sampler() SamplerV2 {
+	return t.sampler
+}
+
+// SelfRef creates an opentracing compliant SpanReference from a jaeger
+// SpanContext. This is a factory function in order to encapsulate jaeger specific
+// types.
+func SelfRef(ctx SpanContext) opentracing.SpanReference {
+	return opentracing.SpanReference{
+		Type:              selfRefType,
+		ReferencedContext: ctx,
+	}
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/tracer_options.go b/vendor/github.com/uber/jaeger-client-go/tracer_options.go
new file mode 100644
index 0000000..f0734b7
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/tracer_options.go
@@ -0,0 +1,182 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import (
+	"time"
+
+	"github.com/opentracing/opentracing-go"
+
+	"github.com/uber/jaeger-client-go/internal/baggage"
+	"github.com/uber/jaeger-client-go/internal/throttler"
+	"github.com/uber/jaeger-client-go/log"
+)
+
+// TracerOption is a function that sets some option on the tracer
+type TracerOption func(tracer *Tracer)
+
+// TracerOptions is a factory for all available TracerOption's
+var TracerOptions tracerOptions
+
+type tracerOptions struct{}
+
+// Metrics creates a TracerOption that initializes Metrics on the tracer,
+// which is used to emit statistics.
+func (tracerOptions) Metrics(m *Metrics) TracerOption {
+	return func(tracer *Tracer) {
+		tracer.metrics = *m
+	}
+}
+
+// Logger creates a TracerOption that gives the tracer a Logger.
+func (tracerOptions) Logger(logger Logger) TracerOption {
+	return func(tracer *Tracer) {
+		tracer.logger = log.DebugLogAdapter(logger)
+	}
+}
+
+func (tracerOptions) CustomHeaderKeys(headerKeys *HeadersConfig) TracerOption {
+	return func(tracer *Tracer) {
+		if headerKeys == nil {
+			return
+		}
+		textPropagator := NewTextMapPropagator(headerKeys.ApplyDefaults(), tracer.metrics)
+		tracer.addCodec(opentracing.TextMap, textPropagator, textPropagator)
+
+		httpHeaderPropagator := NewHTTPHeaderPropagator(headerKeys.ApplyDefaults(), tracer.metrics)
+		tracer.addCodec(opentracing.HTTPHeaders, httpHeaderPropagator, httpHeaderPropagator)
+	}
+}
+
+// TimeNow creates a TracerOption that gives the tracer a function
+// used to generate timestamps for spans.
+func (tracerOptions) TimeNow(timeNow func() time.Time) TracerOption {
+	return func(tracer *Tracer) {
+		tracer.timeNow = timeNow
+	}
+}
+
+// RandomNumber creates a TracerOption that gives the tracer
+// a thread-safe random number generator function for generating trace IDs.
+func (tracerOptions) RandomNumber(randomNumber func() uint64) TracerOption {
+	return func(tracer *Tracer) {
+		tracer.randomNumber = randomNumber
+	}
+}
+
+// PoolSpans creates a TracerOption that tells the tracer whether it should use
+// an object pool to minimize span allocations.
+// This should be used with care, only if the service is not running any async tasks
+// that can access parent spans after those spans have been finished.
+func (tracerOptions) PoolSpans(poolSpans bool) TracerOption {
+	return func(tracer *Tracer) {
+		if poolSpans {
+			tracer.spanAllocator = newSyncPollSpanAllocator()
+		} else {
+			tracer.spanAllocator = simpleSpanAllocator{}
+		}
+	}
+}
+
+// Deprecated: HostIPv4 creates a TracerOption that identifies the current service/process.
+// If not set, the factory method will obtain the current IP address.
+// The TracerOption is deprecated; the tracer will attempt to automatically detect the IP.
+func (tracerOptions) HostIPv4(hostIPv4 uint32) TracerOption {
+	return func(tracer *Tracer) {
+		tracer.hostIPv4 = hostIPv4
+	}
+}
+
+func (tracerOptions) Injector(format interface{}, injector Injector) TracerOption {
+	return func(tracer *Tracer) {
+		tracer.injectors[format] = injector
+	}
+}
+
+func (tracerOptions) Extractor(format interface{}, extractor Extractor) TracerOption {
+	return func(tracer *Tracer) {
+		tracer.extractors[format] = extractor
+	}
+}
+
+func (t tracerOptions) Observer(observer Observer) TracerOption {
+	return t.ContribObserver(&oldObserver{obs: observer})
+}
+
+func (tracerOptions) ContribObserver(observer ContribObserver) TracerOption {
+	return func(tracer *Tracer) {
+		tracer.observer.append(observer)
+	}
+}
+
+func (tracerOptions) Gen128Bit(gen128Bit bool) TracerOption {
+	return func(tracer *Tracer) {
+		tracer.options.gen128Bit = gen128Bit
+	}
+}
+
+func (tracerOptions) NoDebugFlagOnForcedSampling(noDebugFlagOnForcedSampling bool) TracerOption {
+	return func(tracer *Tracer) {
+		tracer.options.noDebugFlagOnForcedSampling = noDebugFlagOnForcedSampling
+	}
+}
+
+func (tracerOptions) HighTraceIDGenerator(highTraceIDGenerator func() uint64) TracerOption {
+	return func(tracer *Tracer) {
+		tracer.options.highTraceIDGenerator = highTraceIDGenerator
+	}
+}
+
+func (tracerOptions) MaxTagValueLength(maxTagValueLength int) TracerOption {
+	return func(tracer *Tracer) {
+		tracer.options.maxTagValueLength = maxTagValueLength
+	}
+}
+
+// MaxLogsPerSpan limits the number of Logs in a span (if set to a nonzero
+// value). If a span has more logs than this value, logs are dropped as
+// necessary (and replaced with a log describing how many were dropped).
+//
+// About half of the MaxLogsPerSpan logs kept are the oldest logs, and about
+// half are the newest logs.
+func (tracerOptions) MaxLogsPerSpan(maxLogsPerSpan int) TracerOption {
+	return func(tracer *Tracer) {
+		tracer.options.maxLogsPerSpan = maxLogsPerSpan
+	}
+}
+
+func (tracerOptions) ZipkinSharedRPCSpan(zipkinSharedRPCSpan bool) TracerOption {
+	return func(tracer *Tracer) {
+		tracer.options.zipkinSharedRPCSpan = zipkinSharedRPCSpan
+	}
+}
+
+func (tracerOptions) Tag(key string, value interface{}) TracerOption {
+	return func(tracer *Tracer) {
+		tracer.tags = append(tracer.tags, Tag{key: key, value: value})
+	}
+}
+
+func (tracerOptions) BaggageRestrictionManager(mgr baggage.RestrictionManager) TracerOption {
+	return func(tracer *Tracer) {
+		tracer.baggageRestrictionManager = mgr
+	}
+}
+
+func (tracerOptions) DebugThrottler(throttler throttler.Throttler) TracerOption {
+	return func(tracer *Tracer) {
+		tracer.debugThrottler = throttler
+	}
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/transport.go b/vendor/github.com/uber/jaeger-client-go/transport.go
new file mode 100644
index 0000000..c5f5b19
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/transport.go
@@ -0,0 +1,38 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import (
+	"io"
+)
+
+// Transport abstracts the method of sending spans out of process.
+// Implementations are NOT required to be thread-safe; the RemoteReporter
+// is expected to only call methods on the Transport from the same go-routine.
+type Transport interface {
+	// Append converts the span to the wire representation and adds it
+	// to sender's internal buffer.  If the buffer exceeds its designated
+	// size, the transport should call Flush() and return the number of spans
+	// flushed, otherwise return 0. If error is returned, the returned number
+	// of spans is treated as failed span, and reported to metrics accordingly.
+	Append(span *Span) (int, error)
+
+	// Flush submits the internal buffer to the remote server. It returns the
+	// number of spans flushed. If error is returned, the returned number of
+	// spans is treated as failed span, and reported to metrics accordingly.
+	Flush() (int, error)
+
+	io.Closer
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/transport/doc.go b/vendor/github.com/uber/jaeger-client-go/transport/doc.go
new file mode 100644
index 0000000..6b961fb
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/transport/doc.go
@@ -0,0 +1,23 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package transport defines various transports that can be used with
+// RemoteReporter to send spans out of process. Transport is responsible
+// for serializing the spans into a specific format suitable for sending
+// to the tracing backend. Examples may include Thrift over UDP, Thrift
+// or JSON over HTTP, Thrift over Kafka, etc.
+//
+// Implementations are NOT required to be thread-safe; the RemoteReporter
+// is expected to only call methods on the Transport from the same go-routine.
+package transport
diff --git a/vendor/github.com/uber/jaeger-client-go/transport/http.go b/vendor/github.com/uber/jaeger-client-go/transport/http.go
new file mode 100644
index 0000000..bb7eb00
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/transport/http.go
@@ -0,0 +1,174 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package transport
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"time"
+
+	"github.com/uber/jaeger-client-go/thrift"
+
+	"github.com/uber/jaeger-client-go"
+	j "github.com/uber/jaeger-client-go/thrift-gen/jaeger"
+)
+
+// Default timeout for http request in seconds
+const defaultHTTPTimeout = time.Second * 5
+
+// HTTPTransport implements Transport by forwarding spans to a http server.
+type HTTPTransport struct {
+	url             string
+	client          *http.Client
+	batchSize       int
+	spans           []*j.Span
+	process         *j.Process
+	httpCredentials *HTTPBasicAuthCredentials
+	headers         map[string]string
+}
+
+// HTTPBasicAuthCredentials stores credentials for HTTP basic auth.
+type HTTPBasicAuthCredentials struct {
+	username string
+	password string
+}
+
+// HTTPOption sets a parameter for the HttpCollector
+type HTTPOption func(c *HTTPTransport)
+
+// HTTPTimeout sets maximum timeout for http request.
+func HTTPTimeout(duration time.Duration) HTTPOption {
+	return func(c *HTTPTransport) { c.client.Timeout = duration }
+}
+
+// HTTPBatchSize sets the maximum batch size, after which a collect will be
+// triggered. The default batch size is 100 spans.
+func HTTPBatchSize(n int) HTTPOption {
+	return func(c *HTTPTransport) { c.batchSize = n }
+}
+
+// HTTPBasicAuth sets the credentials required to perform HTTP basic auth
+func HTTPBasicAuth(username string, password string) HTTPOption {
+	return func(c *HTTPTransport) {
+		c.httpCredentials = &HTTPBasicAuthCredentials{username: username, password: password}
+	}
+}
+
+// HTTPRoundTripper configures the underlying Transport on the *http.Client
+// that is used
+func HTTPRoundTripper(transport http.RoundTripper) HTTPOption {
+	return func(c *HTTPTransport) {
+		c.client.Transport = transport
+	}
+}
+
+// HTTPHeaders defines the HTTP headers that will be attached to the jaeger client's HTTP request
+func HTTPHeaders(headers map[string]string) HTTPOption {
+	return func(c *HTTPTransport) {
+		c.headers = headers
+	}
+}
+
+// NewHTTPTransport returns a new HTTP-backend transport. url should be an http
+// url of the collector to handle POST request, typically something like:
+//     http://hostname:14268/api/traces?format=jaeger.thrift
+func NewHTTPTransport(url string, options ...HTTPOption) *HTTPTransport {
+	c := &HTTPTransport{
+		url:       url,
+		client:    &http.Client{Timeout: defaultHTTPTimeout},
+		batchSize: 100,
+		spans:     []*j.Span{},
+	}
+
+	for _, option := range options {
+		option(c)
+	}
+	return c
+}
+
+// Append implements Transport.
+func (c *HTTPTransport) Append(span *jaeger.Span) (int, error) {
+	if c.process == nil {
+		c.process = jaeger.BuildJaegerProcessThrift(span)
+	}
+	jSpan := jaeger.BuildJaegerThrift(span)
+	c.spans = append(c.spans, jSpan)
+	if len(c.spans) >= c.batchSize {
+		return c.Flush()
+	}
+	return 0, nil
+}
+
+// Flush implements Transport.
+func (c *HTTPTransport) Flush() (int, error) {
+	count := len(c.spans)
+	if count == 0 {
+		return 0, nil
+	}
+	err := c.send(c.spans)
+	c.spans = c.spans[:0]
+	return count, err
+}
+
+// Close implements Transport.
+func (c *HTTPTransport) Close() error {
+	return nil
+}
+
+func (c *HTTPTransport) send(spans []*j.Span) error {
+	batch := &j.Batch{
+		Spans:   spans,
+		Process: c.process,
+	}
+	body, err := serializeThrift(batch)
+	if err != nil {
+		return err
+	}
+	req, err := http.NewRequest("POST", c.url, body)
+	if err != nil {
+		return err
+	}
+	req.Header.Set("Content-Type", "application/x-thrift")
+	for k, v := range c.headers {
+		req.Header.Set(k, v)
+	}
+
+	if c.httpCredentials != nil {
+		req.SetBasicAuth(c.httpCredentials.username, c.httpCredentials.password)
+	}
+
+	resp, err := c.client.Do(req)
+	if err != nil {
+		return err
+	}
+	io.Copy(ioutil.Discard, resp.Body)
+	resp.Body.Close()
+	if resp.StatusCode >= http.StatusBadRequest {
+		return fmt.Errorf("error from collector: %d", resp.StatusCode)
+	}
+	return nil
+}
+
+func serializeThrift(obj thrift.TStruct) (*bytes.Buffer, error) {
+	t := thrift.NewTMemoryBuffer()
+	p := thrift.NewTBinaryProtocolTransport(t)
+	if err := obj.Write(p); err != nil {
+		return nil, err
+	}
+	return t.Buffer, nil
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/transport_udp.go b/vendor/github.com/uber/jaeger-client-go/transport_udp.go
new file mode 100644
index 0000000..7370d80
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/transport_udp.go
@@ -0,0 +1,170 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import (
+	"errors"
+	"fmt"
+
+	"github.com/uber/jaeger-client-go/internal/reporterstats"
+	"github.com/uber/jaeger-client-go/thrift"
+	j "github.com/uber/jaeger-client-go/thrift-gen/jaeger"
+	"github.com/uber/jaeger-client-go/utils"
+)
+
+// Empirically obtained constant for how many bytes in the message are used for envelope.
+// The total datagram size is:
+// sizeof(Span) * numSpans + processByteSize + emitBatchOverhead <= maxPacketSize
+//
+// Note that due to the use of Compact Thrift protocol, overhead grows with the number of spans
+// in the batch, because the length of the list is encoded as varint32, as well as SeqId.
+//
+// There is a unit test `TestEmitBatchOverhead` that validates this number, it fails at <68.
+const emitBatchOverhead = 70
+
+var errSpanTooLarge = errors.New("span is too large")
+
+type udpSender struct {
+	client          *utils.AgentClientUDP
+	maxPacketSize   int                   // max size of datagram in bytes
+	maxSpanBytes    int                   // max number of bytes to record spans (excluding envelope) in the datagram
+	byteBufferSize  int                   // current number of span bytes accumulated in the buffer
+	spanBuffer      []*j.Span             // spans buffered before a flush
+	thriftBuffer    *thrift.TMemoryBuffer // buffer used to calculate byte size of a span
+	thriftProtocol  thrift.TProtocol
+	process         *j.Process
+	processByteSize int
+
+	// reporterStats provides access to stats that are only known to Reporter
+	reporterStats reporterstats.ReporterStats
+
+	// The following counters are always non-negative, but we need to send them in signed i64 Thrift fields,
+	// so we keep them as signed. At 10k QPS, overflow happens in about 300 million years.
+	batchSeqNo           int64
+	tooLargeDroppedSpans int64
+	failedToEmitSpans    int64
+}
+
+// NewUDPTransport creates a reporter that submits spans to jaeger-agent.
+// TODO: (breaking change) move to transport/ package.
+func NewUDPTransport(hostPort string, maxPacketSize int) (Transport, error) {
+	if len(hostPort) == 0 {
+		hostPort = fmt.Sprintf("%s:%d", DefaultUDPSpanServerHost, DefaultUDPSpanServerPort)
+	}
+	if maxPacketSize == 0 {
+		maxPacketSize = utils.UDPPacketMaxLength
+	}
+
+	protocolFactory := thrift.NewTCompactProtocolFactory()
+
+	// Each span is first written to thriftBuffer to determine its size in bytes.
+	thriftBuffer := thrift.NewTMemoryBufferLen(maxPacketSize)
+	thriftProtocol := protocolFactory.GetProtocol(thriftBuffer)
+
+	client, err := utils.NewAgentClientUDP(hostPort, maxPacketSize)
+	if err != nil {
+		return nil, err
+	}
+
+	return &udpSender{
+		client:         client,
+		maxSpanBytes:   maxPacketSize - emitBatchOverhead,
+		thriftBuffer:   thriftBuffer,
+		thriftProtocol: thriftProtocol,
+	}, nil
+}
+
+// SetReporterStats implements reporterstats.Receiver.
+func (s *udpSender) SetReporterStats(rs reporterstats.ReporterStats) {
+	s.reporterStats = rs
+}
+
+func (s *udpSender) calcSizeOfSerializedThrift(thriftStruct thrift.TStruct) int {
+	s.thriftBuffer.Reset()
+	_ = thriftStruct.Write(s.thriftProtocol)
+	return s.thriftBuffer.Len()
+}
+
+func (s *udpSender) Append(span *Span) (int, error) {
+	if s.process == nil {
+		s.process = BuildJaegerProcessThrift(span)
+		s.processByteSize = s.calcSizeOfSerializedThrift(s.process)
+		s.byteBufferSize += s.processByteSize
+	}
+	jSpan := BuildJaegerThrift(span)
+	spanSize := s.calcSizeOfSerializedThrift(jSpan)
+	if spanSize > s.maxSpanBytes {
+		s.tooLargeDroppedSpans++
+		return 1, errSpanTooLarge
+	}
+
+	s.byteBufferSize += spanSize
+	if s.byteBufferSize <= s.maxSpanBytes {
+		s.spanBuffer = append(s.spanBuffer, jSpan)
+		if s.byteBufferSize < s.maxSpanBytes {
+			return 0, nil
+		}
+		return s.Flush()
+	}
+	// the latest span did not fit in the buffer
+	n, err := s.Flush()
+	s.spanBuffer = append(s.spanBuffer, jSpan)
+	s.byteBufferSize = spanSize + s.processByteSize
+	return n, err
+}
+
+func (s *udpSender) Flush() (int, error) {
+	n := len(s.spanBuffer)
+	if n == 0 {
+		return 0, nil
+	}
+	s.batchSeqNo++
+	batchSeqNo := int64(s.batchSeqNo)
+	err := s.client.EmitBatch(&j.Batch{
+		Process: s.process,
+		Spans:   s.spanBuffer,
+		SeqNo:   &batchSeqNo,
+		Stats:   s.makeStats(),
+	})
+	s.resetBuffers()
+	if err != nil {
+		s.failedToEmitSpans += int64(n)
+	}
+	return n, err
+}
+
+func (s *udpSender) Close() error {
+	return s.client.Close()
+}
+
+func (s *udpSender) resetBuffers() {
+	for i := range s.spanBuffer {
+		s.spanBuffer[i] = nil
+	}
+	s.spanBuffer = s.spanBuffer[:0]
+	s.byteBufferSize = s.processByteSize
+}
+
+func (s *udpSender) makeStats() *j.ClientStats {
+	var dropped int64
+	if s.reporterStats != nil {
+		dropped = s.reporterStats.SpansDroppedFromQueue()
+	}
+	return &j.ClientStats{
+		FullQueueDroppedSpans: dropped,
+		TooLargeDroppedSpans:  s.tooLargeDroppedSpans,
+		FailedToEmitSpans:     s.failedToEmitSpans,
+	}
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/utils/http_json.go b/vendor/github.com/uber/jaeger-client-go/utils/http_json.go
new file mode 100644
index 0000000..237211f
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/utils/http_json.go
@@ -0,0 +1,54 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package utils
+
+import (
+	"encoding/json"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/http"
+)
+
+// GetJSON makes an HTTP call to the specified URL and parses the returned JSON into `out`.
+func GetJSON(url string, out interface{}) error {
+	resp, err := http.Get(url)
+	if err != nil {
+		return err
+	}
+	return ReadJSON(resp, out)
+}
+
+// ReadJSON reads JSON from http.Response and parses it into `out`
+func ReadJSON(resp *http.Response, out interface{}) error {
+	defer resp.Body.Close()
+
+	if resp.StatusCode >= 400 {
+		body, err := ioutil.ReadAll(resp.Body)
+		if err != nil {
+			return err
+		}
+
+		return fmt.Errorf("StatusCode: %d, Body: %s", resp.StatusCode, body)
+	}
+
+	if out == nil {
+		io.Copy(ioutil.Discard, resp.Body)
+		return nil
+	}
+
+	decoder := json.NewDecoder(resp.Body)
+	return decoder.Decode(out)
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/utils/localip.go b/vendor/github.com/uber/jaeger-client-go/utils/localip.go
new file mode 100644
index 0000000..b51af77
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/utils/localip.go
@@ -0,0 +1,84 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package utils
+
+import (
+	"errors"
+	"net"
+)
+
+// This code is borrowed from https://github.com/uber/tchannel-go/blob/dev/localip.go
+
+// scoreAddr scores how likely the given addr is to be a remote address and returns the
+// IP to use when listening. Any address which receives a negative score should not be used.
+// Scores are calculated as:
+// -1 for any unknown IP addresses.
+// +300 for IPv4 addresses
+// +100 for non-local addresses, extra +100 for "up" interaces.
+func scoreAddr(iface net.Interface, addr net.Addr) (int, net.IP) {
+	var ip net.IP
+	if netAddr, ok := addr.(*net.IPNet); ok {
+		ip = netAddr.IP
+	} else if netIP, ok := addr.(*net.IPAddr); ok {
+		ip = netIP.IP
+	} else {
+		return -1, nil
+	}
+
+	var score int
+	if ip.To4() != nil {
+		score += 300
+	}
+	if iface.Flags&net.FlagLoopback == 0 && !ip.IsLoopback() {
+		score += 100
+		if iface.Flags&net.FlagUp != 0 {
+			score += 100
+		}
+	}
+	return score, ip
+}
+
+// HostIP tries to find an IP that can be used by other machines to reach this machine.
+func HostIP() (net.IP, error) {
+	interfaces, err := net.Interfaces()
+	if err != nil {
+		return nil, err
+	}
+
+	bestScore := -1
+	var bestIP net.IP
+	// Select the highest scoring IP as the best IP.
+	for _, iface := range interfaces {
+		addrs, err := iface.Addrs()
+		if err != nil {
+			// Skip this interface if there is an error.
+			continue
+		}
+
+		for _, addr := range addrs {
+			score, ip := scoreAddr(iface, addr)
+			if score > bestScore {
+				bestScore = score
+				bestIP = ip
+			}
+		}
+	}
+
+	if bestScore == -1 {
+		return nil, errors.New("no addresses to listen on")
+	}
+
+	return bestIP, nil
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/utils/rand.go b/vendor/github.com/uber/jaeger-client-go/utils/rand.go
new file mode 100644
index 0000000..9875f7f
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/utils/rand.go
@@ -0,0 +1,46 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package utils
+
+import (
+	"math/rand"
+	"sync"
+)
+
+// lockedSource allows a random number generator to be used by multiple goroutines concurrently.
+// The code is very similar to math/rand.lockedSource, which is unfortunately not exposed.
+type lockedSource struct {
+	mut sync.Mutex
+	src rand.Source
+}
+
+// NewRand returns a rand.Rand that is threadsafe.
+func NewRand(seed int64) *rand.Rand {
+	return rand.New(&lockedSource{src: rand.NewSource(seed)})
+}
+
+func (r *lockedSource) Int63() (n int64) {
+	r.mut.Lock()
+	n = r.src.Int63()
+	r.mut.Unlock()
+	return
+}
+
+// Seed implements Seed() of Source
+func (r *lockedSource) Seed(seed int64) {
+	r.mut.Lock()
+	r.src.Seed(seed)
+	r.mut.Unlock()
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/utils/rate_limiter.go b/vendor/github.com/uber/jaeger-client-go/utils/rate_limiter.go
new file mode 100644
index 0000000..bf2f131
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/utils/rate_limiter.go
@@ -0,0 +1,112 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package utils
+
+import (
+	"sync"
+	"time"
+)
+
+// RateLimiter is a filter used to check if a message that is worth itemCost units is within the rate limits.
+//
+// TODO (breaking change) remove this interface in favor of public struct below
+//
+// Deprecated, use ReconfigurableRateLimiter.
+type RateLimiter interface {
+	CheckCredit(itemCost float64) bool
+}
+
+// ReconfigurableRateLimiter is a rate limiter based on leaky bucket algorithm, formulated in terms of a
+// credits balance that is replenished every time CheckCredit() method is called (tick) by the amount proportional
+// to the time elapsed since the last tick, up to max of creditsPerSecond. A call to CheckCredit() takes a cost
+// of an item we want to pay with the balance. If the balance exceeds the cost of the item, the item is "purchased"
+// and the balance reduced, indicated by returned value of true. Otherwise the balance is unchanged and return false.
+//
+// This can be used to limit a rate of messages emitted by a service by instantiating the Rate Limiter with the
+// max number of messages a service is allowed to emit per second, and calling CheckCredit(1.0) for each message
+// to determine if the message is within the rate limit.
+//
+// It can also be used to limit the rate of traffic in bytes, by setting creditsPerSecond to desired throughput
+// as bytes/second, and calling CheckCredit() with the actual message size.
+//
+// TODO (breaking change) rename to RateLimiter once the interface is removed
+type ReconfigurableRateLimiter struct {
+	lock sync.Mutex
+
+	creditsPerSecond float64
+	balance          float64
+	maxBalance       float64
+	lastTick         time.Time
+
+	timeNow func() time.Time
+}
+
+// NewRateLimiter creates a new ReconfigurableRateLimiter.
+func NewRateLimiter(creditsPerSecond, maxBalance float64) *ReconfigurableRateLimiter {
+	return &ReconfigurableRateLimiter{
+		creditsPerSecond: creditsPerSecond,
+		balance:          maxBalance,
+		maxBalance:       maxBalance,
+		lastTick:         time.Now(),
+		timeNow:          time.Now,
+	}
+}
+
+// CheckCredit tries to reduce the current balance by itemCost provided that the current balance
+// is not lest than itemCost.
+func (rl *ReconfigurableRateLimiter) CheckCredit(itemCost float64) bool {
+	rl.lock.Lock()
+	defer rl.lock.Unlock()
+
+	// if we have enough credits to pay for current item, then reduce balance and allow
+	if rl.balance >= itemCost {
+		rl.balance -= itemCost
+		return true
+	}
+	// otherwise check if balance can be increased due to time elapsed, and try again
+	rl.updateBalance()
+	if rl.balance >= itemCost {
+		rl.balance -= itemCost
+		return true
+	}
+	return false
+}
+
+// updateBalance recalculates current balance based on time elapsed. Must be called while holding a lock.
+func (rl *ReconfigurableRateLimiter) updateBalance() {
+	// calculate how much time passed since the last tick, and update current tick
+	currentTime := rl.timeNow()
+	elapsedTime := currentTime.Sub(rl.lastTick)
+	rl.lastTick = currentTime
+	// calculate how much credit have we accumulated since the last tick
+	rl.balance += elapsedTime.Seconds() * rl.creditsPerSecond
+	if rl.balance > rl.maxBalance {
+		rl.balance = rl.maxBalance
+	}
+}
+
+// Update changes the main parameters of the rate limiter in-place, while retaining
+// the current accumulated balance (pro-rated to the new maxBalance value). Using this method
+// instead of creating a new rate limiter helps to avoid thundering herd when sampling
+// strategies are updated.
+func (rl *ReconfigurableRateLimiter) Update(creditsPerSecond, maxBalance float64) {
+	rl.lock.Lock()
+	defer rl.lock.Unlock()
+
+	rl.updateBalance() // get up to date balance
+	rl.balance = rl.balance * maxBalance / rl.maxBalance
+	rl.creditsPerSecond = creditsPerSecond
+	rl.maxBalance = maxBalance
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/utils/udp_client.go b/vendor/github.com/uber/jaeger-client-go/utils/udp_client.go
new file mode 100644
index 0000000..fadd73e
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/utils/udp_client.go
@@ -0,0 +1,98 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package utils
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"net"
+
+	"github.com/uber/jaeger-client-go/thrift"
+
+	"github.com/uber/jaeger-client-go/thrift-gen/agent"
+	"github.com/uber/jaeger-client-go/thrift-gen/jaeger"
+	"github.com/uber/jaeger-client-go/thrift-gen/zipkincore"
+)
+
+// UDPPacketMaxLength is the max size of UDP packet we want to send, synced with jaeger-agent
+const UDPPacketMaxLength = 65000
+
+// AgentClientUDP is a UDP client to Jaeger agent that implements agent.Agent interface.
+type AgentClientUDP struct {
+	agent.Agent
+	io.Closer
+
+	connUDP       *net.UDPConn
+	client        *agent.AgentClient
+	maxPacketSize int                   // max size of datagram in bytes
+	thriftBuffer  *thrift.TMemoryBuffer // buffer used to calculate byte size of a span
+}
+
+// NewAgentClientUDP creates a client that sends spans to Jaeger Agent over UDP.
+func NewAgentClientUDP(hostPort string, maxPacketSize int) (*AgentClientUDP, error) {
+	if maxPacketSize == 0 {
+		maxPacketSize = UDPPacketMaxLength
+	}
+
+	thriftBuffer := thrift.NewTMemoryBufferLen(maxPacketSize)
+	protocolFactory := thrift.NewTCompactProtocolFactory()
+	client := agent.NewAgentClientFactory(thriftBuffer, protocolFactory)
+
+	destAddr, err := net.ResolveUDPAddr("udp", hostPort)
+	if err != nil {
+		return nil, err
+	}
+
+	connUDP, err := net.DialUDP(destAddr.Network(), nil, destAddr)
+	if err != nil {
+		return nil, err
+	}
+	if err := connUDP.SetWriteBuffer(maxPacketSize); err != nil {
+		return nil, err
+	}
+
+	clientUDP := &AgentClientUDP{
+		connUDP:       connUDP,
+		client:        client,
+		maxPacketSize: maxPacketSize,
+		thriftBuffer:  thriftBuffer}
+	return clientUDP, nil
+}
+
+// EmitZipkinBatch implements EmitZipkinBatch() of Agent interface
+func (a *AgentClientUDP) EmitZipkinBatch(spans []*zipkincore.Span) error {
+	return errors.New("Not implemented")
+}
+
+// EmitBatch implements EmitBatch() of Agent interface
+func (a *AgentClientUDP) EmitBatch(batch *jaeger.Batch) error {
+	a.thriftBuffer.Reset()
+	a.client.SeqId = 0 // we have no need for distinct SeqIds for our one-way UDP messages
+	if err := a.client.EmitBatch(batch); err != nil {
+		return err
+	}
+	if a.thriftBuffer.Len() > a.maxPacketSize {
+		return fmt.Errorf("data does not fit within one UDP packet; size %d, max %d, spans %d",
+			a.thriftBuffer.Len(), a.maxPacketSize, len(batch.Spans))
+	}
+	_, err := a.connUDP.Write(a.thriftBuffer.Bytes())
+	return err
+}
+
+// Close implements Close() of io.Closer and closes the underlying UDP connection.
+func (a *AgentClientUDP) Close() error {
+	return a.connUDP.Close()
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/utils/utils.go b/vendor/github.com/uber/jaeger-client-go/utils/utils.go
new file mode 100644
index 0000000..ac3c325
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/utils/utils.go
@@ -0,0 +1,87 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package utils
+
+import (
+	"encoding/binary"
+	"errors"
+	"net"
+	"strconv"
+	"strings"
+	"time"
+)
+
+var (
+	// ErrEmptyIP an error for empty ip strings
+	ErrEmptyIP = errors.New("empty string given for ip")
+
+	// ErrNotHostColonPort an error for invalid host port string
+	ErrNotHostColonPort = errors.New("expecting host:port")
+
+	// ErrNotFourOctets an error for the wrong number of octets after splitting a string
+	ErrNotFourOctets = errors.New("Wrong number of octets")
+)
+
+// ParseIPToUint32 converts a string ip (e.g. "x.y.z.w") to an uint32
+func ParseIPToUint32(ip string) (uint32, error) {
+	if ip == "" {
+		return 0, ErrEmptyIP
+	}
+
+	if ip == "localhost" {
+		return 127<<24 | 1, nil
+	}
+
+	octets := strings.Split(ip, ".")
+	if len(octets) != 4 {
+		return 0, ErrNotFourOctets
+	}
+
+	var intIP uint32
+	for i := 0; i < 4; i++ {
+		octet, err := strconv.Atoi(octets[i])
+		if err != nil {
+			return 0, err
+		}
+		intIP = (intIP << 8) | uint32(octet)
+	}
+
+	return intIP, nil
+}
+
+// ParsePort converts port number from string to uin16
+func ParsePort(portString string) (uint16, error) {
+	port, err := strconv.ParseUint(portString, 10, 16)
+	return uint16(port), err
+}
+
+// PackIPAsUint32 packs an IPv4 as uint32
+func PackIPAsUint32(ip net.IP) uint32 {
+	if ipv4 := ip.To4(); ipv4 != nil {
+		return binary.BigEndian.Uint32(ipv4)
+	}
+	return 0
+}
+
+// TimeToMicrosecondsSinceEpochInt64 converts Go time.Time to a long
+// representing time since epoch in microseconds, which is used expected
+// in the Jaeger spans encoded as Thrift.
+func TimeToMicrosecondsSinceEpochInt64(t time.Time) int64 {
+	// ^^^ Passing time.Time by value is faster than passing a pointer!
+	// BenchmarkTimeByValue-8	2000000000	         1.37 ns/op
+	// BenchmarkTimeByPtr-8  	2000000000	         1.98 ns/op
+
+	return t.UnixNano() / 1000
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/zipkin.go b/vendor/github.com/uber/jaeger-client-go/zipkin.go
new file mode 100644
index 0000000..98cab4b
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/zipkin.go
@@ -0,0 +1,77 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import (
+	"github.com/opentracing/opentracing-go"
+)
+
+// ZipkinSpanFormat is an OpenTracing carrier format constant
+const ZipkinSpanFormat = "zipkin-span-format"
+
+// ExtractableZipkinSpan is a type of Carrier used for integration with Zipkin-aware
+// RPC frameworks (like TChannel). It does not support baggage, only trace IDs.
+type ExtractableZipkinSpan interface {
+	TraceID() uint64
+	SpanID() uint64
+	ParentID() uint64
+	Flags() byte
+}
+
+// InjectableZipkinSpan is a type of Carrier used for integration with Zipkin-aware
+// RPC frameworks (like TChannel). It does not support baggage, only trace IDs.
+type InjectableZipkinSpan interface {
+	SetTraceID(traceID uint64)
+	SetSpanID(spanID uint64)
+	SetParentID(parentID uint64)
+	SetFlags(flags byte)
+}
+
+type zipkinPropagator struct {
+	tracer *Tracer
+}
+
+func (p *zipkinPropagator) Inject(
+	ctx SpanContext,
+	abstractCarrier interface{},
+) error {
+	carrier, ok := abstractCarrier.(InjectableZipkinSpan)
+	if !ok {
+		return opentracing.ErrInvalidCarrier
+	}
+
+	carrier.SetTraceID(ctx.TraceID().Low) // TODO this cannot work with 128bit IDs
+	carrier.SetSpanID(uint64(ctx.SpanID()))
+	carrier.SetParentID(uint64(ctx.ParentID()))
+	carrier.SetFlags(ctx.samplingState.flags())
+	return nil
+}
+
+func (p *zipkinPropagator) Extract(abstractCarrier interface{}) (SpanContext, error) {
+	carrier, ok := abstractCarrier.(ExtractableZipkinSpan)
+	if !ok {
+		return emptyContext, opentracing.ErrInvalidCarrier
+	}
+	if carrier.TraceID() == 0 {
+		return emptyContext, opentracing.ErrSpanContextNotFound
+	}
+	var ctx SpanContext
+	ctx.traceID.Low = carrier.TraceID()
+	ctx.spanID = SpanID(carrier.SpanID())
+	ctx.parentID = SpanID(carrier.ParentID())
+	ctx.samplingState = &samplingState{}
+	ctx.samplingState.setFlags(carrier.Flags())
+	return ctx, nil
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/zipkin_thrift_span.go b/vendor/github.com/uber/jaeger-client-go/zipkin_thrift_span.go
new file mode 100644
index 0000000..73aeb00
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/zipkin_thrift_span.go
@@ -0,0 +1,329 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jaeger
+
+import (
+	"encoding/binary"
+	"fmt"
+	"time"
+
+	"github.com/opentracing/opentracing-go/ext"
+
+	"github.com/uber/jaeger-client-go/internal/spanlog"
+	z "github.com/uber/jaeger-client-go/thrift-gen/zipkincore"
+	"github.com/uber/jaeger-client-go/utils"
+)
+
+const (
+	// Zipkin UI does not work well with non-string tag values
+	allowPackedNumbers = false
+)
+
+var specialTagHandlers = map[string]func(*zipkinSpan, interface{}){
+	string(ext.SpanKind):     setSpanKind,
+	string(ext.PeerHostIPv4): setPeerIPv4,
+	string(ext.PeerPort):     setPeerPort,
+	string(ext.PeerService):  setPeerService,
+	TracerIPTagKey:           removeTag,
+}
+
+// BuildZipkinThrift builds thrift span based on internal span.
+// TODO: (breaking change) move to transport/zipkin and make private.
+func BuildZipkinThrift(s *Span) *z.Span {
+	span := &zipkinSpan{Span: s}
+	span.handleSpecialTags()
+	parentID := int64(span.context.parentID)
+	var ptrParentID *int64
+	if parentID != 0 {
+		ptrParentID = &parentID
+	}
+	traceIDHigh := int64(span.context.traceID.High)
+	var ptrTraceIDHigh *int64
+	if traceIDHigh != 0 {
+		ptrTraceIDHigh = &traceIDHigh
+	}
+	timestamp := utils.TimeToMicrosecondsSinceEpochInt64(span.startTime)
+	duration := span.duration.Nanoseconds() / int64(time.Microsecond)
+	endpoint := &z.Endpoint{
+		ServiceName: span.tracer.serviceName,
+		Ipv4:        int32(span.tracer.hostIPv4)}
+	thriftSpan := &z.Span{
+		TraceID:           int64(span.context.traceID.Low),
+		TraceIDHigh:       ptrTraceIDHigh,
+		ID:                int64(span.context.spanID),
+		ParentID:          ptrParentID,
+		Name:              span.operationName,
+		Timestamp:         &timestamp,
+		Duration:          &duration,
+		Debug:             span.context.IsDebug(),
+		Annotations:       buildAnnotations(span, endpoint),
+		BinaryAnnotations: buildBinaryAnnotations(span, endpoint)}
+	return thriftSpan
+}
+
+func buildAnnotations(span *zipkinSpan, endpoint *z.Endpoint) []*z.Annotation {
+	// automatically adding 2 Zipkin CoreAnnotations
+	annotations := make([]*z.Annotation, 0, 2+len(span.logs))
+	var startLabel, endLabel string
+	if span.spanKind == string(ext.SpanKindRPCClientEnum) {
+		startLabel, endLabel = z.CLIENT_SEND, z.CLIENT_RECV
+	} else if span.spanKind == string(ext.SpanKindRPCServerEnum) {
+		startLabel, endLabel = z.SERVER_RECV, z.SERVER_SEND
+	}
+	if !span.startTime.IsZero() && startLabel != "" {
+		start := &z.Annotation{
+			Timestamp: utils.TimeToMicrosecondsSinceEpochInt64(span.startTime),
+			Value:     startLabel,
+			Host:      endpoint}
+		annotations = append(annotations, start)
+		if span.duration != 0 {
+			endTs := span.startTime.Add(span.duration)
+			end := &z.Annotation{
+				Timestamp: utils.TimeToMicrosecondsSinceEpochInt64(endTs),
+				Value:     endLabel,
+				Host:      endpoint}
+			annotations = append(annotations, end)
+		}
+	}
+	for _, log := range span.logs {
+		anno := &z.Annotation{
+			Timestamp: utils.TimeToMicrosecondsSinceEpochInt64(log.Timestamp),
+			Host:      endpoint}
+		if content, err := spanlog.MaterializeWithJSON(log.Fields); err == nil {
+			anno.Value = truncateString(string(content), span.tracer.options.maxTagValueLength)
+		} else {
+			anno.Value = err.Error()
+		}
+		annotations = append(annotations, anno)
+	}
+	return annotations
+}
+
+func buildBinaryAnnotations(span *zipkinSpan, endpoint *z.Endpoint) []*z.BinaryAnnotation {
+	// automatically adding local component or server/client address tag, and client version
+	annotations := make([]*z.BinaryAnnotation, 0, 2+len(span.tags))
+
+	if span.peerDefined() && span.isRPC() {
+		peer := z.Endpoint{
+			Ipv4:        span.peer.Ipv4,
+			Port:        span.peer.Port,
+			ServiceName: span.peer.ServiceName}
+		label := z.CLIENT_ADDR
+		if span.isRPCClient() {
+			label = z.SERVER_ADDR
+		}
+		anno := &z.BinaryAnnotation{
+			Key:            label,
+			Value:          []byte{1},
+			AnnotationType: z.AnnotationType_BOOL,
+			Host:           &peer}
+		annotations = append(annotations, anno)
+	}
+	if !span.isRPC() {
+		componentName := endpoint.ServiceName
+		for _, tag := range span.tags {
+			if tag.key == string(ext.Component) {
+				componentName = stringify(tag.value)
+				break
+			}
+		}
+		local := &z.BinaryAnnotation{
+			Key:            z.LOCAL_COMPONENT,
+			Value:          []byte(componentName),
+			AnnotationType: z.AnnotationType_STRING,
+			Host:           endpoint}
+		annotations = append(annotations, local)
+	}
+	for _, tag := range span.tags {
+		// "Special tags" are already handled by this point, we'd be double reporting the
+		// tags if we don't skip here
+		if _, ok := specialTagHandlers[tag.key]; ok {
+			continue
+		}
+		if anno := buildBinaryAnnotation(tag.key, tag.value, span.tracer.options.maxTagValueLength, nil); anno != nil {
+			annotations = append(annotations, anno)
+		}
+	}
+	return annotations
+}
+
+func buildBinaryAnnotation(key string, val interface{}, maxTagValueLength int, endpoint *z.Endpoint) *z.BinaryAnnotation {
+	bann := &z.BinaryAnnotation{Key: key, Host: endpoint}
+	if value, ok := val.(string); ok {
+		bann.Value = []byte(truncateString(value, maxTagValueLength))
+		bann.AnnotationType = z.AnnotationType_STRING
+	} else if value, ok := val.([]byte); ok {
+		if len(value) > maxTagValueLength {
+			value = value[:maxTagValueLength]
+		}
+		bann.Value = value
+		bann.AnnotationType = z.AnnotationType_BYTES
+	} else if value, ok := val.(int32); ok && allowPackedNumbers {
+		bann.Value = int32ToBytes(value)
+		bann.AnnotationType = z.AnnotationType_I32
+	} else if value, ok := val.(int64); ok && allowPackedNumbers {
+		bann.Value = int64ToBytes(value)
+		bann.AnnotationType = z.AnnotationType_I64
+	} else if value, ok := val.(int); ok && allowPackedNumbers {
+		bann.Value = int64ToBytes(int64(value))
+		bann.AnnotationType = z.AnnotationType_I64
+	} else if value, ok := val.(bool); ok {
+		bann.Value = []byte{boolToByte(value)}
+		bann.AnnotationType = z.AnnotationType_BOOL
+	} else {
+		value := stringify(val)
+		bann.Value = []byte(truncateString(value, maxTagValueLength))
+		bann.AnnotationType = z.AnnotationType_STRING
+	}
+	return bann
+}
+
+func stringify(value interface{}) string {
+	if s, ok := value.(string); ok {
+		return s
+	}
+	return fmt.Sprintf("%+v", value)
+}
+
+func truncateString(value string, maxLength int) string {
+	// we ignore the problem of utf8 runes possibly being sliced in the middle,
+	// as it is rather expensive to iterate through each tag just to find rune
+	// boundaries.
+	if len(value) > maxLength {
+		return value[:maxLength]
+	}
+	return value
+}
+
+func boolToByte(b bool) byte {
+	if b {
+		return 1
+	}
+	return 0
+}
+
+// int32ToBytes converts int32 to bytes.
+func int32ToBytes(i int32) []byte {
+	buf := make([]byte, 4)
+	binary.BigEndian.PutUint32(buf, uint32(i))
+	return buf
+}
+
+// int64ToBytes converts int64 to bytes.
+func int64ToBytes(i int64) []byte {
+	buf := make([]byte, 8)
+	binary.BigEndian.PutUint64(buf, uint64(i))
+	return buf
+}
+
+type zipkinSpan struct {
+	*Span
+
+	// peer points to the peer service participating in this span,
+	// e.g. the Client if this span is a server span,
+	// or Server if this span is a client span
+	peer struct {
+		Ipv4        int32
+		Port        int16
+		ServiceName string
+	}
+
+	// used to distinguish local vs. RPC Server vs. RPC Client spans
+	spanKind string
+}
+
+func (s *zipkinSpan) handleSpecialTags() {
+	s.Lock()
+	defer s.Unlock()
+	if s.firstInProcess {
+		// append the process tags
+		s.tags = append(s.tags, s.tracer.tags...)
+	}
+	filteredTags := make([]Tag, 0, len(s.tags))
+	for _, tag := range s.tags {
+		if handler, ok := specialTagHandlers[tag.key]; ok {
+			handler(s, tag.value)
+		} else {
+			filteredTags = append(filteredTags, tag)
+		}
+	}
+	s.tags = filteredTags
+}
+
+func setSpanKind(s *zipkinSpan, value interface{}) {
+	if val, ok := value.(string); ok {
+		s.spanKind = val
+		return
+	}
+	if val, ok := value.(ext.SpanKindEnum); ok {
+		s.spanKind = string(val)
+	}
+}
+
+func setPeerIPv4(s *zipkinSpan, value interface{}) {
+	if val, ok := value.(string); ok {
+		if ip, err := utils.ParseIPToUint32(val); err == nil {
+			s.peer.Ipv4 = int32(ip)
+			return
+		}
+	}
+	if val, ok := value.(uint32); ok {
+		s.peer.Ipv4 = int32(val)
+		return
+	}
+	if val, ok := value.(int32); ok {
+		s.peer.Ipv4 = val
+	}
+}
+
+func setPeerPort(s *zipkinSpan, value interface{}) {
+	if val, ok := value.(string); ok {
+		if port, err := utils.ParsePort(val); err == nil {
+			s.peer.Port = int16(port)
+			return
+		}
+	}
+	if val, ok := value.(uint16); ok {
+		s.peer.Port = int16(val)
+		return
+	}
+	if val, ok := value.(int); ok {
+		s.peer.Port = int16(val)
+	}
+}
+
+func setPeerService(s *zipkinSpan, value interface{}) {
+	if val, ok := value.(string); ok {
+		s.peer.ServiceName = val
+	}
+}
+
+func removeTag(s *zipkinSpan, value interface{}) {}
+
+func (s *zipkinSpan) peerDefined() bool {
+	return s.peer.ServiceName != "" || s.peer.Ipv4 != 0 || s.peer.Port != 0
+}
+
+func (s *zipkinSpan) isRPC() bool {
+	s.RLock()
+	defer s.RUnlock()
+	return s.spanKind == string(ext.SpanKindRPCClientEnum) || s.spanKind == string(ext.SpanKindRPCServerEnum)
+}
+
+func (s *zipkinSpan) isRPCClient() bool {
+	s.RLock()
+	defer s.RUnlock()
+	return s.spanKind == string(ext.SpanKindRPCClientEnum)
+}
diff --git a/vendor/github.com/uber/jaeger-lib/LICENSE b/vendor/github.com/uber/jaeger-lib/LICENSE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-lib/LICENSE
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/vendor/github.com/uber/jaeger-lib/metrics/counter.go b/vendor/github.com/uber/jaeger-lib/metrics/counter.go
new file mode 100644
index 0000000..2a6a43e
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-lib/metrics/counter.go
@@ -0,0 +1,28 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package metrics
+
+// Counter tracks the number of times an event has occurred
+type Counter interface {
+	// Inc adds the given value to the counter.
+	Inc(int64)
+}
+
+// NullCounter counter that does nothing
+var NullCounter Counter = nullCounter{}
+
+type nullCounter struct{}
+
+func (nullCounter) Inc(int64) {}
diff --git a/vendor/github.com/uber/jaeger-lib/metrics/factory.go b/vendor/github.com/uber/jaeger-lib/metrics/factory.go
new file mode 100644
index 0000000..0ead061
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-lib/metrics/factory.go
@@ -0,0 +1,78 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package metrics
+
+import (
+	"time"
+)
+
+// NSOptions defines the name and tags map associated with a factory namespace
+type NSOptions struct {
+	Name string
+	Tags map[string]string
+}
+
+// Options defines the information associated with a metric
+type Options struct {
+	Name string
+	Tags map[string]string
+	Help string
+}
+
+// TimerOptions defines the information associated with a metric
+type TimerOptions struct {
+	Name    string
+	Tags    map[string]string
+	Help    string
+	Buckets []time.Duration
+}
+
+// HistogramOptions defines the information associated with a metric
+type HistogramOptions struct {
+	Name    string
+	Tags    map[string]string
+	Help    string
+	Buckets []float64
+}
+
+// Factory creates new metrics
+type Factory interface {
+	Counter(metric Options) Counter
+	Timer(metric TimerOptions) Timer
+	Gauge(metric Options) Gauge
+	Histogram(metric HistogramOptions) Histogram
+
+	// Namespace returns a nested metrics factory.
+	Namespace(scope NSOptions) Factory
+}
+
+// NullFactory is a metrics factory that returns NullCounter, NullTimer, and NullGauge.
+var NullFactory Factory = nullFactory{}
+
+type nullFactory struct{}
+
+func (nullFactory) Counter(options Options) Counter {
+	return NullCounter
+}
+func (nullFactory) Timer(options TimerOptions) Timer {
+	return NullTimer
+}
+func (nullFactory) Gauge(options Options) Gauge {
+	return NullGauge
+}
+func (nullFactory) Histogram(options HistogramOptions) Histogram {
+	return NullHistogram
+}
+func (nullFactory) Namespace(scope NSOptions) Factory { return NullFactory }
diff --git a/vendor/github.com/uber/jaeger-lib/metrics/gauge.go b/vendor/github.com/uber/jaeger-lib/metrics/gauge.go
new file mode 100644
index 0000000..3c60639
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-lib/metrics/gauge.go
@@ -0,0 +1,28 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package metrics
+
+// Gauge returns instantaneous measurements of something as an int64 value
+type Gauge interface {
+	// Update the gauge to the value passed in.
+	Update(int64)
+}
+
+// NullGauge gauge that does nothing
+var NullGauge Gauge = nullGauge{}
+
+type nullGauge struct{}
+
+func (nullGauge) Update(int64) {}
diff --git a/vendor/github.com/uber/jaeger-lib/metrics/histogram.go b/vendor/github.com/uber/jaeger-lib/metrics/histogram.go
new file mode 100644
index 0000000..d3bd617
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-lib/metrics/histogram.go
@@ -0,0 +1,28 @@
+// Copyright (c) 2018 The Jaeger Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package metrics
+
+// Histogram that keeps track of a distribution of values.
+type Histogram interface {
+	// Records the value passed in.
+	Record(float64)
+}
+
+// NullHistogram that does nothing
+var NullHistogram Histogram = nullHistogram{}
+
+type nullHistogram struct{}
+
+func (nullHistogram) Record(float64) {}
diff --git a/vendor/github.com/uber/jaeger-lib/metrics/keys.go b/vendor/github.com/uber/jaeger-lib/metrics/keys.go
new file mode 100644
index 0000000..c24445a
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-lib/metrics/keys.go
@@ -0,0 +1,35 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package metrics
+
+import (
+	"sort"
+)
+
+// GetKey converts name+tags into a single string of the form
+// "name|tag1=value1|...|tagN=valueN", where tag names are
+// sorted alphabetically.
+func GetKey(name string, tags map[string]string, tagsSep string, tagKVSep string) string {
+	keys := make([]string, 0, len(tags))
+	for k := range tags {
+		keys = append(keys, k)
+	}
+	sort.Strings(keys)
+	key := name
+	for _, k := range keys {
+		key = key + tagsSep + k + tagKVSep + tags[k]
+	}
+	return key
+}
diff --git a/vendor/github.com/uber/jaeger-lib/metrics/metrics.go b/vendor/github.com/uber/jaeger-lib/metrics/metrics.go
new file mode 100644
index 0000000..0df0c66
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-lib/metrics/metrics.go
@@ -0,0 +1,137 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package metrics
+
+import (
+	"fmt"
+	"reflect"
+	"strconv"
+	"strings"
+)
+
+// MustInit initializes the passed in metrics and initializes its fields using the passed in factory.
+//
+// It uses reflection to initialize a struct containing metrics fields
+// by assigning new Counter/Gauge/Timer values with the metric name retrieved
+// from the `metric` tag and stats tags retrieved from the `tags` tag.
+//
+// Note: all fields of the struct must be exported, have a `metric` tag, and be
+// of type Counter or Gauge or Timer.
+//
+// Errors during Init lead to a panic.
+func MustInit(metrics interface{}, factory Factory, globalTags map[string]string) {
+	if err := Init(metrics, factory, globalTags); err != nil {
+		panic(err.Error())
+	}
+}
+
+// Init does the same as MustInit, but returns an error instead of
+// panicking.
+func Init(m interface{}, factory Factory, globalTags map[string]string) error {
+	// Allow user to opt out of reporting metrics by passing in nil.
+	if factory == nil {
+		factory = NullFactory
+	}
+
+	counterPtrType := reflect.TypeOf((*Counter)(nil)).Elem()
+	gaugePtrType := reflect.TypeOf((*Gauge)(nil)).Elem()
+	timerPtrType := reflect.TypeOf((*Timer)(nil)).Elem()
+	histogramPtrType := reflect.TypeOf((*Histogram)(nil)).Elem()
+
+	v := reflect.ValueOf(m).Elem()
+	t := v.Type()
+	for i := 0; i < t.NumField(); i++ {
+		tags := make(map[string]string)
+		for k, v := range globalTags {
+			tags[k] = v
+		}
+		var buckets []float64
+		field := t.Field(i)
+		metric := field.Tag.Get("metric")
+		if metric == "" {
+			return fmt.Errorf("Field %s is missing a tag 'metric'", field.Name)
+		}
+		if tagString := field.Tag.Get("tags"); tagString != "" {
+			tagPairs := strings.Split(tagString, ",")
+			for _, tagPair := range tagPairs {
+				tag := strings.Split(tagPair, "=")
+				if len(tag) != 2 {
+					return fmt.Errorf(
+						"Field [%s]: Tag [%s] is not of the form key=value in 'tags' string [%s]",
+						field.Name, tagPair, tagString)
+				}
+				tags[tag[0]] = tag[1]
+			}
+		}
+		if bucketString := field.Tag.Get("buckets"); bucketString != "" {
+			if field.Type.AssignableTo(timerPtrType) {
+				// TODO: Parse timer duration buckets
+				return fmt.Errorf(
+					"Field [%s]: Buckets are not currently initialized for timer metrics",
+					field.Name)
+			} else if field.Type.AssignableTo(histogramPtrType) {
+				bucketValues := strings.Split(bucketString, ",")
+				for _, bucket := range bucketValues {
+					b, err := strconv.ParseFloat(bucket, 64)
+					if err != nil {
+						return fmt.Errorf(
+							"Field [%s]: Bucket [%s] could not be converted to float64 in 'buckets' string [%s]",
+							field.Name, bucket, bucketString)
+					}
+					buckets = append(buckets, b)
+				}
+			} else {
+				return fmt.Errorf(
+					"Field [%s]: Buckets should only be defined for Timer and Histogram metric types",
+					field.Name)
+			}
+		}
+		help := field.Tag.Get("help")
+		var obj interface{}
+		if field.Type.AssignableTo(counterPtrType) {
+			obj = factory.Counter(Options{
+				Name: metric,
+				Tags: tags,
+				Help: help,
+			})
+		} else if field.Type.AssignableTo(gaugePtrType) {
+			obj = factory.Gauge(Options{
+				Name: metric,
+				Tags: tags,
+				Help: help,
+			})
+		} else if field.Type.AssignableTo(timerPtrType) {
+			// TODO: Add buckets once parsed (see TODO above)
+			obj = factory.Timer(TimerOptions{
+				Name: metric,
+				Tags: tags,
+				Help: help,
+			})
+		} else if field.Type.AssignableTo(histogramPtrType) {
+			obj = factory.Histogram(HistogramOptions{
+				Name:    metric,
+				Tags:    tags,
+				Help:    help,
+				Buckets: buckets,
+			})
+		} else {
+			return fmt.Errorf(
+				"Field %s is not a pointer to timer, gauge, or counter",
+				field.Name)
+		}
+		v.Field(i).Set(reflect.ValueOf(obj))
+	}
+	return nil
+}
diff --git a/vendor/github.com/uber/jaeger-lib/metrics/stopwatch.go b/vendor/github.com/uber/jaeger-lib/metrics/stopwatch.go
new file mode 100644
index 0000000..4a8abdb
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-lib/metrics/stopwatch.go
@@ -0,0 +1,43 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package metrics
+
+import (
+	"time"
+)
+
+// StartStopwatch begins recording the executing time of an event, returning
+// a Stopwatch that should be used to stop the recording the time for
+// that event.  Multiple events can be occurring simultaneously each
+// represented by different active Stopwatches
+func StartStopwatch(timer Timer) Stopwatch {
+	return Stopwatch{t: timer, start: time.Now()}
+}
+
+// A Stopwatch tracks the execution time of a specific event
+type Stopwatch struct {
+	t     Timer
+	start time.Time
+}
+
+// Stop stops executing of the stopwatch and records the amount of elapsed time
+func (s Stopwatch) Stop() {
+	s.t.Record(s.ElapsedTime())
+}
+
+// ElapsedTime returns the amount of elapsed time (in time.Duration)
+func (s Stopwatch) ElapsedTime() time.Duration {
+	return time.Since(s.start)
+}
diff --git a/vendor/github.com/uber/jaeger-lib/metrics/timer.go b/vendor/github.com/uber/jaeger-lib/metrics/timer.go
new file mode 100644
index 0000000..e18d222
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-lib/metrics/timer.go
@@ -0,0 +1,33 @@
+// Copyright (c) 2017 Uber Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package metrics
+
+import (
+	"time"
+)
+
+// Timer accumulates observations about how long some operation took,
+// and also maintains a historgam of percentiles.
+type Timer interface {
+	// Records the time passed in.
+	Record(time.Duration)
+}
+
+// NullTimer timer that does nothing
+var NullTimer Timer = nullTimer{}
+
+type nullTimer struct{}
+
+func (nullTimer) Record(time.Duration) {}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 1e2d7e2..9ebda8d 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -37,15 +37,44 @@
 github.com/mitchellh/go-homedir
 # github.com/mitchellh/mapstructure v1.1.2
 github.com/mitchellh/mapstructure
-# github.com/opencord/voltha-lib-go/v3 v3.0.20
-github.com/opencord/voltha-lib-go/v3/pkg/db
-github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore
-github.com/opencord/voltha-lib-go/v3/pkg/log
-github.com/opencord/voltha-lib-go/v3/pkg/ponresourcemanager
-github.com/opencord/voltha-lib-go/v3/pkg/techprofile
-# github.com/opencord/voltha-protos/v3 v3.2.6
-github.com/opencord/voltha-protos/v3/go/openolt
-github.com/opencord/voltha-protos/v3/go/tech_profile
+# github.com/opencord/voltha-lib-go/v4 v4.0.0
+github.com/opencord/voltha-lib-go/v4/pkg/db
+github.com/opencord/voltha-lib-go/v4/pkg/db/kvstore
+github.com/opencord/voltha-lib-go/v4/pkg/log
+github.com/opencord/voltha-lib-go/v4/pkg/ponresourcemanager
+github.com/opencord/voltha-lib-go/v4/pkg/techprofile
+# github.com/opencord/voltha-protos/v4 v4.0.2
+github.com/opencord/voltha-protos/v4/go/common
+github.com/opencord/voltha-protos/v4/go/ext/config
+github.com/opencord/voltha-protos/v4/go/openolt
+github.com/opencord/voltha-protos/v4/go/tech_profile
+# github.com/opentracing/opentracing-go v1.1.0
+github.com/opentracing/opentracing-go
+github.com/opentracing/opentracing-go/ext
+github.com/opentracing/opentracing-go/log
+# github.com/pkg/errors v0.8.1
+github.com/pkg/errors
+# github.com/uber/jaeger-client-go v2.23.1+incompatible
+github.com/uber/jaeger-client-go
+github.com/uber/jaeger-client-go/config
+github.com/uber/jaeger-client-go/internal/baggage
+github.com/uber/jaeger-client-go/internal/baggage/remote
+github.com/uber/jaeger-client-go/internal/reporterstats
+github.com/uber/jaeger-client-go/internal/spanlog
+github.com/uber/jaeger-client-go/internal/throttler
+github.com/uber/jaeger-client-go/internal/throttler/remote
+github.com/uber/jaeger-client-go/log
+github.com/uber/jaeger-client-go/rpcmetrics
+github.com/uber/jaeger-client-go/thrift
+github.com/uber/jaeger-client-go/thrift-gen/agent
+github.com/uber/jaeger-client-go/thrift-gen/baggage
+github.com/uber/jaeger-client-go/thrift-gen/jaeger
+github.com/uber/jaeger-client-go/thrift-gen/sampling
+github.com/uber/jaeger-client-go/thrift-gen/zipkincore
+github.com/uber/jaeger-client-go/transport
+github.com/uber/jaeger-client-go/utils
+# github.com/uber/jaeger-lib v2.2.0+incompatible
+github.com/uber/jaeger-lib/metrics
 # go.etcd.io/etcd v0.0.0-20190930204107-236ac2a90522
 go.etcd.io/etcd/auth/authpb
 go.etcd.io/etcd/clientv3