浏览代码

Merge remote-tracking branch 'origin/master'

NECionpy 6 年之前
父节点
当前提交
2dbc61998a
共有 100 个文件被更改,包括 6625 次插入323 次删除
  1. 2 1
      README.md
  2. 5 7
      pkg/cache/cache.go
  3. 7 5
      pkg/cache/memcache.go
  4. 4 6
      pkg/cache/memcache_test.go
  5. 10 0
      pkg/coap/error.go
  6. 219 0
      pkg/coap/manager.go
  7. 583 0
      pkg/coap/message.go
  8. 59 0
      pkg/coap/message_test.go
  9. 12 0
      pkg/coap/provider.go
  10. 10 0
      pkg/coap/request.go
  11. 7 4
      pkg/generator/key_gen.go
  12. 1 1
      pkg/generator/password_gen.go
  13. 2 2
      pkg/generator/token_gen.go
  14. 1 1
      pkg/models/application.go
  15. 5 0
      pkg/mongo/recorder.go
  16. 6 2
      pkg/mongo/recorder_test.go
  17. 5 0
      pkg/mqtt/broker.go
  18. 38 33
      pkg/mqtt/connection.go
  19. 10 10
      pkg/mqtt/manager.go
  20. 35 35
      pkg/mqtt/message.go
  21. 1 1
      pkg/mqtt/utils.go
  22. 13 0
      pkg/mqtt/utils_test.go
  23. 2 2
      pkg/protocol/structure.go
  24. 5 0
      pkg/rpcs/registry.go
  25. 3 3
      pkg/rule/ifttt.go
  26. 4 4
      pkg/rule/rule_action.go
  27. 3 2
      pkg/rule/timer.go
  28. 2 0
      pkg/server/config.go
  29. 2 0
      pkg/server/errors.go
  30. 6 2
      pkg/server/rpc_client.go
  31. 1 1
      pkg/server/rpc_client_test.go
  32. 64 16
      pkg/server/server.go
  33. 14 3
      pkg/server/server_manager.go
  34. 3 1
      pkg/server/tcp_server_test.go
  35. 52 0
      pkg/server/udp_server.go
  36. 64 0
      pkg/server/udp_server_test.go
  37. 106 96
      pkg/tlv/tlv.go
  38. 10 7
      pkg/token/token_test.go
  39. 27 0
      pkg/tracing/tracer.go
  40. 2 1
      run.sh
  41. 45 6
      services/apiprovider/actions.go
  42. 9 8
      services/apiprovider/middleware.go
  43. 3 3
      services/apiprovider/notifier.go
  44. 17 0
      services/coapaccess/access.go
  45. 69 0
      services/coapaccess/coap_provider.go
  46. 28 0
      services/coapaccess/main.go
  47. 26 0
      services/coapaccess/readme.md
  48. 1 1
      services/controller/controller.go
  49. 23 2
      services/httpaccess/actions.go
  50. 12 3
      services/knowoapi/controllers/application.go
  51. 2 2
      services/knowoapi/controllers/device.go
  52. 11 3
      services/knowoapi/controllers/product.go
  53. 1 0
      services/knowoapi/model/role.go
  54. 1 1
      services/knowoapi/model/role_test.go
  55. 11 1
      services/knowoapi/router.go
  56. 1 3
      services/knowoapi/services/user.go
  57. 6 6
      services/mqttaccess/mqtt_provider.go
  58. 2 2
      services/registry/product.go
  59. 10 8
      services/registry/registry.go
  60. 96 0
      tests/coaptool/main.go
  61. 二进制
      tests/device/device
  62. 103 18
      tests/device/device.go
  63. 8 7
      tests/device/main.go
  64. 1 1
      tools/pdcfg/application.go
  65. 1 1
      tools/pdcfg/product.go
  66. 1 1
      tools/pdcfg/vendor.go
  67. 14 0
      vendor/github.com/opentracing/opentracing-go/CHANGELOG.md
  68. 201 0
      vendor/github.com/opentracing/opentracing-go/LICENSE
  69. 20 0
      vendor/github.com/opentracing/opentracing-go/Makefile
  70. 171 0
      vendor/github.com/opentracing/opentracing-go/README.md
  71. 210 0
      vendor/github.com/opentracing/opentracing-go/ext/tags.go
  72. 42 0
      vendor/github.com/opentracing/opentracing-go/globaltracer.go
  73. 54 0
      vendor/github.com/opentracing/opentracing-go/gocontext.go
  74. 269 0
      vendor/github.com/opentracing/opentracing-go/log/field.go
  75. 54 0
      vendor/github.com/opentracing/opentracing-go/log/util.go
  76. 64 0
      vendor/github.com/opentracing/opentracing-go/noop.go
  77. 176 0
      vendor/github.com/opentracing/opentracing-go/propagation.go
  78. 189 0
      vendor/github.com/opentracing/opentracing-go/span.go
  79. 305 0
      vendor/github.com/opentracing/opentracing-go/tracer.go
  80. 23 0
      vendor/github.com/pkg/errors/LICENSE
  81. 52 0
      vendor/github.com/pkg/errors/README.md
  82. 32 0
      vendor/github.com/pkg/errors/appveyor.yml
  83. 269 0
      vendor/github.com/pkg/errors/errors.go
  84. 147 0
      vendor/github.com/pkg/errors/stack.go
  85. 197 0
      vendor/github.com/uber/jaeger-client-go/CHANGELOG.md
  86. 170 0
      vendor/github.com/uber/jaeger-client-go/CONTRIBUTING.md
  87. 37 0
      vendor/github.com/uber/jaeger-client-go/DCO
  88. 164 0
      vendor/github.com/uber/jaeger-client-go/Gopkg.lock
  89. 27 0
      vendor/github.com/uber/jaeger-client-go/Gopkg.toml
  90. 201 0
      vendor/github.com/uber/jaeger-client-go/LICENSE
  91. 120 0
      vendor/github.com/uber/jaeger-client-go/Makefile
  92. 270 0
      vendor/github.com/uber/jaeger-client-go/README.md
  93. 11 0
      vendor/github.com/uber/jaeger-client-go/RELEASE.md
  94. 77 0
      vendor/github.com/uber/jaeger-client-go/baggage_setter.go
  95. 395 0
      vendor/github.com/uber/jaeger-client-go/config/config.go
  96. 221 0
      vendor/github.com/uber/jaeger-client-go/config/config_env.go
  97. 148 0
      vendor/github.com/uber/jaeger-client-go/config/options.go
  98. 88 0
      vendor/github.com/uber/jaeger-client-go/constants.go
  99. 258 0
      vendor/github.com/uber/jaeger-client-go/context.go
  100. 56 0
      vendor/github.com/uber/jaeger-client-go/contrib_observer.go

+ 2 - 1
README.md

@@ -9,4 +9,5 @@
 * `httpaccess`: 设备Http API接入服务,实现设备登陆,注册,认证等逻辑 [文档说明](httpaccess.md)
 * `mqttaccess`: MQTT接入服务 [文档说明](mqttaccess.md)
 * `knowoapi`: 开放平台管理中心api接口服务 [文档说明](knowoapi.md)
-* `fileaccess`: 静态文件服务器 [文档说明](./services/fileaccess/readme.markdown)
+* `fileaccess`: 静态文件服务器 [文档说明](./services/fileaccess/readme.markdown)
+* `coapaccess`: CoAP接入服务[文档说明](./services/coapaccess/readme.md)

+ 5 - 7
pkg/cache/cache.go

@@ -1,8 +1,6 @@
 package cache
 
-
-
-//return status of chache
+// CacheStatus return status of chache
 type CacheStatus struct {
 	Gets        int64
 	Hits        int64
@@ -10,10 +8,10 @@ type CacheStatus struct {
 	CurrentSize int
 }
 
-//this is a interface which defines some common functions
-type Cache interface{
+// Cache this is a interface which defines some common functions
+type Cache interface {
 	Set(key string, value interface{})
 	Get(key string) (interface{}, bool)
 	Delete(key string)
-	Status()(*CacheStatus)
-}
+	Status() *CacheStatus
+}

+ 7 - 5
pkg/cache/memcache.go

@@ -24,7 +24,7 @@ type entry struct {
 	value interface{}
 }
 
-// If maxItemSize is zero, the cache has no limit.
+// NewMemCache If maxItemSize is zero, the cache has no limit.
 //if maxItemSize is not zero, when cache's size beyond maxItemSize,start to swap
 func NewMemCache(maxItemSize int) *MemCache {
 	return &MemCache{
@@ -34,8 +34,8 @@ func NewMemCache(maxItemSize int) *MemCache {
 	}
 }
 
-//return the status of cache
-func (c *MemCache) Status() *CacheStatus{
+// Status return the status of cache
+func (c *MemCache) Status() *CacheStatus {
 	c.mutex.RLock()
 	defer c.mutex.RUnlock()
 	return &CacheStatus{
@@ -46,7 +46,7 @@ func (c *MemCache) Status() *CacheStatus{
 	}
 }
 
-//get value with key
+//Get value with key
 func (c *MemCache) Get(key string) (interface{}, bool) {
 	c.mutex.RLock()
 	defer c.mutex.RUnlock()
@@ -58,7 +58,7 @@ func (c *MemCache) Get(key string) (interface{}, bool) {
 	return nil, false
 }
 
-//set a value with key
+//Set a value with key
 func (c *MemCache) Set(key string, value interface{}) {
 	c.mutex.Lock()
 	defer c.mutex.Unlock()
@@ -80,6 +80,7 @@ func (c *MemCache) Set(key string, value interface{}) {
 	}
 }
 
+// Delete a value with key
 func (c *MemCache) Delete(key string) {
 	c.mutex.Lock()
 	defer c.mutex.Unlock()
@@ -94,6 +95,7 @@ func (c *MemCache) Delete(key string) {
 	}
 }
 
+// RemoveOldest remove oldest key
 func (c *MemCache) RemoveOldest() {
 	if c.cache == nil {
 		return

+ 4 - 6
pkg/cache/memcache_test.go

@@ -25,25 +25,23 @@ var getTests = []struct {
 }
 
 func TestSet(t *testing.T) {
-	var cache Cache
-	cache = NewMemCache(0)
+	cache := NewMemCache(0)
 	values := []string{"test1", "test2", "test3"}
 	key := "key1"
 	for _, v := range values {
 		cache.Set(key, v)
 		val, ok := cache.Get(key)
-		if !ok{
+		if !ok {
 			t.Fatalf("expect key:%v ,value:%v", key, v)
 		} else if ok && val != v {
-			t.Fatalf("expect value:%v, get value:%v", key, v, val)
+			t.Fatalf("key :%v,expect value:%v, get value:%v", key, v, val)
 		}
 		t.Logf("value:%v ", val)
 	}
 }
 
 func TestGet(t *testing.T) {
-	var cache Cache
-	cache = NewMemCache(0)
+	cache := NewMemCache(0)
 	for _, tt := range getTests {
 		cache.Set(tt.keyToAdd, 1234)
 		val, ok := cache.Get(tt.keyToGet)

+ 10 - 0
pkg/coap/error.go

@@ -0,0 +1,10 @@
+package coap
+
+import "errors"
+
+// define errors
+var (
+	ErrInvalidTokenLen   = errors.New("invalid token length")
+	ErrOptionTooLong     = errors.New("option is too long")
+	ErrOptionGapTooLarge = errors.New("option gap too large")
+)

+ 219 - 0
pkg/coap/manager.go

@@ -0,0 +1,219 @@
+package coap
+
+import (
+	"net"
+	"sparrow/pkg/rpcs"
+	"sparrow/pkg/server"
+	"strconv"
+	"sync/atomic"
+	"time"
+)
+
+const (
+	// ResponseTimeout is the amount of time to wait for a
+	// response.
+	ResponseTimeout = time.Second * 2
+	// ResponseRandomFactor is a multiplier for response backoff.
+	ResponseRandomFactor = 1.5
+	// MaxRetransmit is the maximum number of times a message will
+	// be retransmitted.
+	MaxRetransmit     = 4
+	maxPktlen         = 1500
+	maxWorkersCount   = 10000
+	idleWorkerTimeout = 10 * time.Second
+
+	pubStatusTopic  = "s"
+	pubEventTopic   = "e"
+	subCommandTopic = "c"
+)
+
+// Manager manager
+type Manager struct {
+	queue        chan *Request
+	Provider     Provider
+	workersCount int32
+}
+
+// NewManager new manager
+func NewManager(p Provider) *Manager {
+	return &Manager{
+		Provider: p,
+		queue:    make(chan *Request),
+	}
+}
+
+// Handler udp handler
+func (m *Manager) Handler(conn *net.UDPConn) {
+	buf := make([]byte, maxPktlen)
+	for {
+		nr, addr, err := conn.ReadFromUDP(buf)
+		if err != nil {
+			if neterr, ok := err.(net.Error); ok && (neterr.Temporary() || neterr.Timeout()) {
+				time.Sleep(5 * time.Millisecond)
+				continue
+			}
+
+		}
+		tmp := make([]byte, nr)
+		copy(tmp, buf)
+		msg, err := ParseMessage(tmp)
+		if err != nil {
+			server.Log.Error(err)
+		}
+		m.spawnWorker(&Request{
+			Msg:  msg,
+			Addr: addr,
+			Conn: conn,
+		})
+	}
+}
+func (m *Manager) worker(w *Request) {
+	m.serve(w)
+	for {
+		count := atomic.LoadInt32(&m.workersCount)
+		if count > maxWorkersCount {
+			return
+		}
+		if atomic.CompareAndSwapInt32(&m.workersCount, count, count+1) {
+			break
+		}
+	}
+	defer atomic.AddInt32(&m.workersCount, -1)
+	inUse := false
+	timeout := time.NewTimer(idleWorkerTimeout)
+	defer timeout.Stop()
+	for m.workerChannelHandler(inUse, timeout) {
+	}
+}
+func (m *Manager) workerChannelHandler(inUse bool, timeout *time.Timer) bool {
+	select {
+	case w, ok := <-m.queue:
+		if !ok {
+			return false
+		}
+		inUse = true
+		m.serve(w)
+	case <-timeout.C:
+		if !inUse {
+			return false
+		}
+		inUse = false
+		timeout.Reset(idleWorkerTimeout)
+	}
+	return true
+}
+
+// coap://endpoint/$DEVICE_ID/s
+func (m *Manager) serve(w *Request) {
+	msg := w.Msg
+	server.Log.Debugf("get packet:%#v, workers count :%d", msg, m.workersCount)
+	if msg.IsConfirmable() && len(msg.Path()) > 1 {
+		token := msg.GetToken()
+		// TODO:想别的deviceid的
+		deviceid, err := strconv.ParseUint(msg.Path()[0], 10, 0)
+		if err != nil {
+			server.Log.Errorf("device id error:%s", msg.Path()[0])
+			return
+		}
+		if len(token) != 8 {
+			res := &BaseMessage{
+				Code:      Unauthorized,
+				Type:      ACK,
+				MessageID: msg.GetMessageID(),
+				Token:     msg.GetToken(),
+			}
+			bytes, _ := res.Encode()
+			w.Conn.WriteTo(bytes, w.Addr)
+			server.Log.Errorf("token length error, size :%d", len(token))
+			return
+		}
+		//check token
+		err = m.Provider.ValidateDeviceToken(deviceid, token)
+		if err != nil {
+			res := &BaseMessage{
+				Code:      Unauthorized,
+				Type:      ACK,
+				MessageID: msg.GetMessageID(),
+				Token:     msg.GetToken(),
+			}
+			bytes, _ := res.Encode()
+			w.Conn.WriteTo(bytes, w.Addr)
+			server.Log.Warnf("device %d token not validate, token :%v", deviceid, token)
+			return
+		}
+		args := rpcs.ArgsGetOnline{
+			Id:                deviceid,
+			ClientIP:          w.Addr.String(),
+			AccessRPCHost:     server.GetRPCHost(),
+			HeartbeatInterval: 30,
+		}
+
+		ack := &BaseMessage{
+			Code:      Changed,
+			Type:      ACK,
+			MessageID: msg.GetMessageID(),
+			Token:     msg.GetToken(),
+		}
+		ackbytes, _ := ack.Encode()
+		w.Conn.WriteTo(ackbytes, w.Addr)
+		err = m.Provider.OnDeviceOnline(args)
+		if err != nil {
+			server.Log.Warnf("device online error :%v", err)
+			return
+		}
+		server.Log.Infof("device %d, connected to server now host:%s", deviceid, w.Addr.String())
+		topic := msg.Path()[1]
+		switch topic {
+		case pubStatusTopic, pubEventTopic, subCommandTopic:
+			server.Log.Infof("%s, publish status", w.Addr.String())
+			m.Provider.OnDeviceMessage(uint64(deviceid), topic, msg.GetPayload())
+			err := m.Provider.OnDeviceHeartBeat(uint64(deviceid))
+			if err != nil {
+				server.Log.Warnf("heartbeat set error:%s", w.Addr.String())
+				return
+			}
+			//pub ack
+			ack := &BaseMessage{
+				Code:      Created,
+				Type:      ACK,
+				MessageID: msg.GetMessageID(),
+				Token:     msg.GetToken(),
+			}
+			ackbytes, _ := ack.Encode()
+			w.Conn.WriteTo(ackbytes, w.Addr)
+		default:
+			//无效主题
+			server.Log.Errorf("unknown msg type:%s", topic)
+			ack := &BaseMessage{
+				Code:      BadRequest,
+				Type:      ACK,
+				MessageID: msg.GetMessageID(),
+				Token:     msg.GetToken(),
+			}
+			ackbytes, _ := ack.Encode()
+			w.Conn.WriteTo(ackbytes, w.Addr)
+			return
+		}
+	} else {
+		//无效请求
+	}
+}
+
+func (m *Manager) spawnWorker(req *Request) {
+	select {
+	case m.queue <- req:
+	default:
+		go m.serve(req)
+	}
+}
+
+// Receive a message.
+func Receive(l *net.UDPConn, buf []byte) (Message, error) {
+	l.SetReadDeadline(time.Now().Add(ResponseTimeout))
+
+	nr, _, err := l.ReadFromUDP(buf)
+	if err != nil {
+		return &BaseMessage{}, err
+	}
+	return ParseMessage(buf[:nr])
+}

+ 583 - 0
pkg/coap/message.go

@@ -0,0 +1,583 @@
+package coap
+
+import (
+	"bytes"
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"reflect"
+	"sort"
+	"strconv"
+	"strings"
+)
+
+// COAPType 代表消息类型
+type COAPType uint8
+
+// MaxTokenSize 最大token size
+const MaxTokenSize = 8
+
+const (
+	// CON 需要被确认的请求
+	CON COAPType = 0
+	// NON 不需要被确认的请求
+	NON COAPType = 1
+	// ACK 应答消息,接受到CON消息的响应
+	ACK COAPType = 2
+	// RST 复位消息,当接收者接受到的消息包含一个错误,接受者解析消息或者不再关心发送者发送的内容,那么复位消息将会被发送
+	RST COAPType = 3
+)
+
+// COAPCode 请求方法的类型
+type COAPCode uint8
+
+// request codes
+const (
+	GET COAPCode = iota + 1
+	POST
+	PUT
+	DELETE
+)
+
+// Response codes
+const (
+	Empty                   COAPCode = 0
+	Created                 COAPCode = 65
+	Deleted                 COAPCode = 66
+	Valid                   COAPCode = 67
+	Changed                 COAPCode = 68
+	Content                 COAPCode = 69
+	Continue                COAPCode = 95
+	BadRequest              COAPCode = 128
+	Unauthorized            COAPCode = 129
+	BadOption               COAPCode = 130
+	Forbidden               COAPCode = 131
+	NotFound                COAPCode = 132
+	MethodNotAllowed        COAPCode = 133
+	NotAcceptable           COAPCode = 134
+	RequestEntityIncomplete COAPCode = 136
+	PreconditionFailed      COAPCode = 140
+	RequestEntityTooLarge   COAPCode = 141
+	UnsupportedMediaType    COAPCode = 143
+	InternalServerError     COAPCode = 160
+	NotImplemented          COAPCode = 161
+	BadGateway              COAPCode = 162
+	ServiceUnavailable      COAPCode = 163
+	GatewayTimeout          COAPCode = 164
+	ProxyingNotSupported    COAPCode = 165
+)
+
+// MediaType 请求消息的媒体类型 对应Content-Format
+type MediaType uint16
+
+// Content formats.
+const (
+	TextPlain MediaType = 0  // text/plain;charset=utf-8
+	AppXML    MediaType = 41 // application/xml
+	AppOctets MediaType = 42 // application/octet-stream
+	AppExi    MediaType = 47 // application/exi
+	AppJSON   MediaType = 50 // application/json
+	AppCBOR   MediaType = 60 //application/cbor (RFC 7049)
+)
+
+func (c MediaType) String() string {
+	switch c {
+	case TextPlain:
+		return "text/plain;charset=utf-8"
+	case AppXML:
+		return "application/xml"
+	case AppOctets:
+		return "application/octet-stream"
+	case AppExi:
+		return "application/exi"
+	case AppJSON:
+		return "application/json"
+	case AppCBOR:
+		return "application/cbor (RFC 7049)"
+	}
+	return "Unknown media type: 0x" + strconv.FormatInt(int64(c), 16)
+}
+
+// OptionID Option编号
+type OptionID uint8
+
+// Option IDs.
+const (
+	IfMatch       OptionID = 1
+	URIHost       OptionID = 3
+	ETag          OptionID = 4
+	IfNoneMatch   OptionID = 5
+	Observe       OptionID = 6
+	URIPort       OptionID = 7
+	LocationPath  OptionID = 8
+	URIPath       OptionID = 11
+	ContentFormat OptionID = 12
+	MaxAge        OptionID = 14
+	URIQuery      OptionID = 15
+	Accept        OptionID = 17
+	LocationQuery OptionID = 20
+	Block2        OptionID = 23
+	Block1        OptionID = 27
+	Size2         OptionID = 28
+	ProxyURI      OptionID = 35
+	ProxyScheme   OptionID = 39
+	Size1         OptionID = 60
+)
+
+// Option value format (RFC7252 section 3.2)
+type valueFormat uint8
+
+const (
+	valueUnknown valueFormat = iota
+	valueEmpty
+	valueOpaque
+	valueUint
+	valueString
+)
+
+type optionDef struct {
+	valueFormat valueFormat
+	minLen      int
+	maxLen      int
+}
+
+var coapOptionDefs = map[OptionID]optionDef{
+	IfMatch:       optionDef{valueFormat: valueOpaque, minLen: 0, maxLen: 8},
+	URIHost:       optionDef{valueFormat: valueString, minLen: 1, maxLen: 255},
+	ETag:          optionDef{valueFormat: valueOpaque, minLen: 1, maxLen: 8},
+	IfNoneMatch:   optionDef{valueFormat: valueEmpty, minLen: 0, maxLen: 0},
+	Observe:       optionDef{valueFormat: valueUint, minLen: 0, maxLen: 3},
+	URIPort:       optionDef{valueFormat: valueUint, minLen: 0, maxLen: 2},
+	LocationPath:  optionDef{valueFormat: valueString, minLen: 0, maxLen: 255},
+	URIPath:       optionDef{valueFormat: valueString, minLen: 0, maxLen: 255},
+	ContentFormat: optionDef{valueFormat: valueUint, minLen: 0, maxLen: 2},
+	MaxAge:        optionDef{valueFormat: valueUint, minLen: 0, maxLen: 4},
+	URIQuery:      optionDef{valueFormat: valueString, minLen: 0, maxLen: 255},
+	Accept:        optionDef{valueFormat: valueUint, minLen: 0, maxLen: 2},
+	LocationQuery: optionDef{valueFormat: valueString, minLen: 0, maxLen: 255},
+	Block2:        optionDef{valueFormat: valueUint, minLen: 0, maxLen: 3},
+	Block1:        optionDef{valueFormat: valueUint, minLen: 0, maxLen: 3},
+	Size2:         optionDef{valueFormat: valueUint, minLen: 0, maxLen: 4},
+	ProxyURI:      optionDef{valueFormat: valueString, minLen: 1, maxLen: 1034},
+	ProxyScheme:   optionDef{valueFormat: valueString, minLen: 1, maxLen: 255},
+	Size1:         optionDef{valueFormat: valueUint, minLen: 0, maxLen: 4},
+}
+
+type option struct {
+	ID    OptionID
+	Value interface{}
+}
+
+func encodeInt(v uint32) []byte {
+	switch {
+	case v == 0:
+		return nil
+	case v < 256:
+		return []byte{byte(v)}
+	case v < 65536:
+		rv := []byte{0, 0}
+		binary.BigEndian.PutUint16(rv, uint16(v))
+		return rv
+	case v < 16777216:
+		rv := []byte{0, 0, 0, 0}
+		binary.BigEndian.PutUint32(rv, uint32(v))
+		return rv[1:]
+	default:
+		rv := []byte{0, 0, 0, 0}
+		binary.BigEndian.PutUint32(rv, uint32(v))
+		return rv
+	}
+}
+
+func decodeInt(b []byte) uint32 {
+	tmp := []byte{0, 0, 0, 0}
+	copy(tmp[4-len(b):], b)
+	return binary.BigEndian.Uint32(tmp)
+}
+
+func (o option) toBytes() []byte {
+	var v uint32
+
+	switch i := o.Value.(type) {
+	case string:
+		return []byte(i)
+	case []byte:
+		return i
+	case MediaType:
+		v = uint32(i)
+	case int:
+		v = uint32(i)
+	case int32:
+		v = uint32(i)
+	case uint:
+		v = uint32(i)
+	case uint32:
+		v = i
+	default:
+		panic(fmt.Errorf("invalid type for option %x: %T (%v)",
+			o.ID, o.Value, o.Value))
+	}
+
+	return encodeInt(v)
+}
+
+type options []option
+
+func (o options) Len() int {
+	return len(o)
+}
+
+func (o options) Less(i, j int) bool {
+	if o[i].ID == o[j].ID {
+		return i < j
+	}
+	return o[i].ID < o[j].ID
+}
+
+func (o options) Swap(i, j int) {
+	o[i], o[j] = o[j], o[i]
+}
+
+func (o options) Remove(oid OptionID) options {
+	idx := 0
+	for i := 0; i < len(o); i++ {
+		if o[i].ID != oid {
+			o[idx] = o[i]
+			idx++
+		}
+	}
+	return o[:idx]
+}
+
+const (
+	extoptByteCode   = 13
+	extoptByteAddend = 13
+	extoptWordCode   = 14
+	extoptWordAddend = 269
+	extoptError      = 15
+)
+
+// Message interface
+type Message interface {
+	Encode() ([]byte, error)
+	Decode(data []byte) error
+	Option(opid OptionID) interface{}
+	Path() []string
+	PathString() string
+	SetPath([]string)
+	SetPathString(s string)
+	AddOption(opid OptionID, val interface{})
+	RemoveOption(opid OptionID)
+	IsConfirmable() bool
+	OptionStrings(opid OptionID) []string
+	GetMessageID() uint16
+	GetToken() []byte
+	GetCode() COAPCode
+	GetPayload() []byte
+}
+
+// BaseMessage COAP 消息体
+type BaseMessage struct {
+	Type      COAPType
+	Code      COAPCode
+	MessageID uint16
+	Token     []byte
+	Payload   []byte
+	Opts      options
+}
+
+// GetToken get token
+func (m *BaseMessage) GetToken() []byte {
+	return m.Token
+}
+
+// GetMessageID get message id
+func (m *BaseMessage) GetMessageID() uint16 {
+	return m.MessageID
+}
+
+// GetCode get code
+func (m *BaseMessage) GetCode() COAPCode {
+	return m.Code
+}
+
+// Encode 消息打包
+func (m *BaseMessage) Encode() ([]byte, error) {
+	tmpbuf := []byte{0, 0}
+	binary.BigEndian.PutUint16(tmpbuf, m.MessageID)
+	buf := bytes.Buffer{}
+	buf.Write([]byte{
+		(1 << 6) | (uint8(m.Type) << 4) | uint8(0xf&len(m.Token)),
+		byte(m.Code),
+		tmpbuf[0], tmpbuf[1],
+	})
+	buf.Write(m.Token)
+	extendOpt := func(opt int) (int, int) {
+		ext := 0
+		if opt >= extoptByteAddend {
+			if opt >= extoptWordAddend {
+				ext = opt - extoptWordAddend
+				opt = extoptWordCode
+			} else {
+				ext = opt - extoptByteAddend
+				opt = extoptByteCode
+			}
+		}
+		return opt, ext
+	}
+
+	writeOptHeader := func(delta, length int) {
+		d, dx := extendOpt(delta)
+		l, lx := extendOpt(length)
+
+		buf.WriteByte(byte(d<<4) | byte(l))
+
+		tmp := []byte{0, 0}
+		writeExt := func(opt, ext int) {
+			switch opt {
+			case extoptByteCode:
+				buf.WriteByte(byte(ext))
+			case extoptWordCode:
+				binary.BigEndian.PutUint16(tmp, uint16(ext))
+				buf.Write(tmp)
+			}
+		}
+
+		writeExt(d, dx)
+		writeExt(l, lx)
+	}
+
+	sort.Stable(&m.Opts)
+
+	prev := 0
+
+	for _, o := range m.Opts {
+		b := o.toBytes()
+		writeOptHeader(int(o.ID)-prev, len(b))
+		buf.Write(b)
+		prev = int(o.ID)
+	}
+
+	if len(m.Payload) > 0 {
+		buf.Write([]byte{0xff})
+	}
+
+	buf.Write(m.Payload)
+
+	return buf.Bytes(), nil
+}
+
+// Decode 消息解包
+func (m *BaseMessage) Decode(data []byte) error {
+	if len(data) < 4 {
+		return errors.New("short packet")
+	}
+
+	if data[0]>>6 != 1 {
+		return errors.New("invalid version")
+	}
+
+	m.Type = COAPType((data[0] >> 4) & 0x3)
+	tokenLen := int(data[0] & 0xf)
+	if tokenLen > 8 {
+		return ErrInvalidTokenLen
+	}
+
+	m.Code = COAPCode(data[1])
+	m.MessageID = binary.BigEndian.Uint16(data[2:4])
+
+	if tokenLen > 0 {
+		m.Token = make([]byte, tokenLen)
+	}
+	if len(data) < 4+tokenLen {
+		return errors.New("truncated")
+	}
+	copy(m.Token, data[4:4+tokenLen])
+	b := data[4+tokenLen:]
+	prev := 0
+
+	parseExtOpt := func(opt int) (int, error) {
+		switch opt {
+		case extoptByteCode:
+			if len(b) < 1 {
+				return -1, errors.New("truncated")
+			}
+			opt = int(b[0]) + extoptByteAddend
+			b = b[1:]
+		case extoptWordCode:
+			if len(b) < 2 {
+				return -1, errors.New("truncated")
+			}
+			opt = int(binary.BigEndian.Uint16(b[:2])) + extoptWordAddend
+			b = b[2:]
+		}
+		return opt, nil
+	}
+
+	for len(b) > 0 {
+		if b[0] == 0xff {
+			b = b[1:]
+			break
+		}
+
+		delta := int(b[0] >> 4)
+		length := int(b[0] & 0x0f)
+
+		if delta == extoptError || length == extoptError {
+			return errors.New("unexpected extended option marker")
+		}
+
+		b = b[1:]
+
+		delta, err := parseExtOpt(delta)
+		if err != nil {
+			return err
+		}
+		length, err = parseExtOpt(length)
+		if err != nil {
+			return err
+		}
+
+		if len(b) < length {
+			return errors.New("truncated")
+		}
+
+		oid := OptionID(prev + delta)
+		opval := parseOptionValue(oid, b[:length])
+		b = b[length:]
+		prev = int(oid)
+
+		if opval != nil {
+			m.Opts = append(m.Opts, option{ID: oid, Value: opval})
+		}
+	}
+	m.Payload = b
+	return nil
+}
+
+// IsConfirmable 如果是CON类型的消息类型,返回true
+func (m *BaseMessage) IsConfirmable() bool {
+	return m.Type == CON
+}
+
+// GetPayload get payload
+func (m *BaseMessage) GetPayload() []byte {
+	return m.Payload
+}
+
+// Option get option by id
+func (m *BaseMessage) Option(o OptionID) interface{} {
+	for _, v := range m.Opts {
+		if o == v.ID {
+			return v.Value
+		}
+	}
+	return nil
+}
+
+// Options 获取所的option value
+func (m *BaseMessage) Options(o OptionID) []interface{} {
+	var rv []interface{}
+
+	for _, v := range m.Opts {
+		if o == v.ID {
+			rv = append(rv, v.Value)
+		}
+	}
+
+	return rv
+}
+
+// OptionStrings get option strings by id
+func (m *BaseMessage) OptionStrings(o OptionID) []string {
+	var rv []string
+	for _, o := range m.Options(o) {
+		rv = append(rv, o.(string))
+	}
+	return rv
+}
+
+// Path 获取URIPath
+func (m *BaseMessage) Path() []string {
+	return m.OptionStrings(URIPath)
+}
+
+// PathString gets a path as a / separated string.
+func (m *BaseMessage) PathString() string {
+	return strings.Join(m.Path(), "/")
+}
+
+// SetPathString sets a path by a / separated string.
+func (m *BaseMessage) SetPathString(s string) {
+	switch s {
+	case "", "/":
+		//root path is not set as option
+		return
+	default:
+		if s[0] == '/' {
+			s = s[1:]
+		}
+		m.SetPath(strings.Split(s, "/"))
+	}
+}
+
+//RemoveOption remove a given opid
+func (m *BaseMessage) RemoveOption(opID OptionID) {
+	m.Opts = m.Opts.Remove(opID)
+}
+
+// AddOption ``
+func (m *BaseMessage) AddOption(opID OptionID, val interface{}) {
+	iv := reflect.ValueOf(val)
+	if (iv.Kind() == reflect.Slice || iv.Kind() == reflect.Array) &&
+		iv.Type().Elem().Kind() == reflect.String {
+		for i := 0; i < iv.Len(); i++ {
+			m.Opts = append(m.Opts, option{opID, iv.Index(i).Interface()})
+		}
+		return
+	}
+	m.Opts = append(m.Opts, option{opID, val})
+}
+
+// SetPath ``
+func (m *BaseMessage) SetPath(s []string) {
+	m.SetOption(URIPath, s)
+}
+
+// SetOption sets an option, discarding any previous value
+func (m *BaseMessage) SetOption(opID OptionID, val interface{}) {
+	m.RemoveOption(opID)
+	m.AddOption(opID, val)
+}
+func parseOptionValue(optionID OptionID, valueBuf []byte) interface{} {
+	def := coapOptionDefs[optionID]
+	if def.valueFormat == valueUnknown {
+		// Skip unrecognized options (RFC7252 section 5.4.1)
+		return nil
+	}
+	if len(valueBuf) < def.minLen || len(valueBuf) > def.maxLen {
+		// Skip options with illegal value length (RFC7252 section 5.4.3)
+		return nil
+	}
+	switch def.valueFormat {
+	case valueUint:
+		intValue := decodeInt(valueBuf)
+		if optionID == ContentFormat || optionID == Accept {
+			return MediaType(intValue)
+		}
+		return intValue
+
+	case valueString:
+		return string(valueBuf)
+	case valueOpaque, valueEmpty:
+		return valueBuf
+	}
+	// Skip unrecognized options (should never be reached)
+	return nil
+}
+
+// ParseMessage parse []byte to message
+func ParseMessage(data []byte) (Message, error) {
+	rv := &BaseMessage{}
+	return rv, rv.Decode(data)
+}

+ 59 - 0
pkg/coap/message_test.go

@@ -0,0 +1,59 @@
+package coap
+
+import (
+	"bytes"
+	"fmt"
+	"testing"
+)
+
+func TestMediaTypes(t *testing.T) {
+	types := []interface{}{TextPlain, AppXML, AppOctets, AppExi, AppJSON}
+	exp := "coap.MediaType"
+	for _, typ := range types {
+		if got := fmt.Sprintf("%T", typ); got != exp {
+			t.Errorf("Error on %#v, expected %q, was %q", typ, exp, got)
+		}
+	}
+}
+func TestOptionToBytes(t *testing.T) {
+	tests := []struct {
+		in  interface{}
+		exp []byte
+	}{
+		{"", []byte{}},
+		{[]byte{}, []byte{}},
+		{"x", []byte{'x'}},
+		{[]byte{'x'}, []byte{'x'}},
+		{MediaType(3), []byte{0x3}},
+		{3, []byte{0x3}},
+		{838, []byte{0x3, 0x46}},
+		{int32(838), []byte{0x3, 0x46}},
+		{uint(838), []byte{0x3, 0x46}},
+		{uint32(838), []byte{0x3, 0x46}},
+	}
+
+	for _, test := range tests {
+		op := option{Value: test.in}
+		got := op.toBytes()
+		if !bytes.Equal(test.exp, got) {
+			t.Errorf("Error on %T(%v), got %#v, wanted %#v",
+				test.in, test.in, got, test.exp)
+		}
+	}
+}
+func TestMessageConfirmable(t *testing.T) {
+	tests := []struct {
+		m   Message
+		exp bool
+	}{
+		{&BaseMessage{mtype: CON}, true},
+		{&BaseMessage{mtype: NON}, false},
+	}
+
+	for _, test := range tests {
+		got := test.m.IsConfirmable()
+		if got != test.exp {
+			t.Errorf("Expected %v for %v", test.exp, test.m)
+		}
+	}
+}

+ 12 - 0
pkg/coap/provider.go

@@ -0,0 +1,12 @@
+package coap
+
+import "sparrow/pkg/rpcs"
+
+// Provider 处理设备业务逻辑
+type Provider interface {
+	ValidateDeviceToken(deviceid uint64, token []byte) error
+	OnDeviceOnline(args rpcs.ArgsGetOnline) error
+	OnDeviceOffline(deviceid uint64) error
+	OnDeviceHeartBeat(deviceid uint64) error
+	OnDeviceMessage(deviceid uint64, msgtype string, message []byte)
+}

+ 10 - 0
pkg/coap/request.go

@@ -0,0 +1,10 @@
+package coap
+
+import "net"
+
+// Request a client request
+type Request struct {
+	Msg  Message
+	Conn *net.UDPConn
+	Addr *net.UDPAddr
+}

+ 7 - 4
pkg/generator/key_gen.go

@@ -15,6 +15,7 @@ const (
 	maxEncodeLen = 32
 )
 
+// KeyGenerator key generator
 type KeyGenerator struct {
 	AESKey string
 }
@@ -55,16 +56,18 @@ func decryptAESCFB(msg, key []byte) ([]byte, error) {
 	return msg, nil
 }
 
+// NewKeyGenerator create a key generator
 func NewKeyGenerator(key string) (*KeyGenerator, error) {
 	l := len(key)
 	if l != 16 && l != 24 && l != 32 {
-		return nil, errors.New("invalid aes key length, should be 16, 24 or 32 bytes.")
+		return nil, errors.New("invalid aes key length, should be 16, 24 or 32 bytes")
 	}
 	return &KeyGenerator{
 		AESKey: key,
 	}, nil
 }
 
+// GenRandomKey get random key
 func (g *KeyGenerator) GenRandomKey(id int64) (string, error) {
 	buf := make([]byte, maxEncodeLen-binary.Size(id)-aes.BlockSize)
 	if _, err := io.ReadFull(rand.Reader, buf); err != nil {
@@ -84,8 +87,8 @@ func (g *KeyGenerator) GenRandomKey(id int64) (string, error) {
 	return hex.EncodeToString(binkey), nil
 }
 
-// get id from encrypt strings
-func (g *KeyGenerator) DecodeIdFromRandomKey(encrypted string) (int64, error) {
+// DecodeIDFromRandomKey get id from encrypt strings
+func (g *KeyGenerator) DecodeIDFromRandomKey(encrypted string) (int64, error) {
 	buf, err := hex.DecodeString(encrypted)
 	if err != nil {
 		return 0, err
@@ -99,7 +102,7 @@ func (g *KeyGenerator) DecodeIdFromRandomKey(encrypted string) (int64, error) {
 	var id int64
 
 	if len(raw) > maxEncodeLen || len(raw) < maxEncodeLen-aes.BlockSize-binary.Size(id) {
-		return 0, errors.New("invalid key format.")
+		return 0, errors.New("invalid key format")
 	}
 
 	binbuf := bytes.NewBuffer(raw[maxEncodeLen-aes.BlockSize-binary.Size(id):])

+ 1 - 1
pkg/generator/password_gen.go

@@ -9,7 +9,7 @@ const (
 	ranPasswordByteLength = 24
 )
 
-// gen random base64 encoded password
+// GenRandomPassword gen random base64 encoded password
 func GenRandomPassword() (string, error) {
 	ranbuf := make([]byte, ranPasswordByteLength)
 	_, err := rand.Read(ranbuf)

+ 2 - 2
pkg/generator/token_gen.go

@@ -5,10 +5,10 @@ import (
 )
 
 const (
-	ranTokendByteLength = 16
+	ranTokendByteLength = 8
 )
 
-// gen random token bytes
+// GenRandomToken gen random token bytes
 func GenRandomToken() ([]byte, error) {
 	ranbuf := make([]byte, ranTokendByteLength)
 	_, err := rand.Read(ranbuf)

+ 1 - 1
pkg/models/application.go

@@ -1,4 +1,3 @@
-// application is app who will use the cloud api
 package models
 
 import (
@@ -8,6 +7,7 @@ import (
 )
 
 // Application 代指一个应用程序
+// application is app who will use the cloud api
 type Application struct {
 	gorm.Model
 	// App-Key for api

+ 5 - 0
pkg/mongo/recorder.go

@@ -5,12 +5,14 @@ import (
 	"labix.org/v2/mgo/bson"
 )
 
+// Recorder record device data
 type Recorder struct {
 	session    *mgo.Session
 	set        string
 	collection string
 }
 
+// NewRecorder create a recorder
 func NewRecorder(host string, set string, collection string) (*Recorder, error) {
 	sess, err := mgo.Dial(host)
 	if err != nil {
@@ -26,6 +28,7 @@ func NewRecorder(host string, set string, collection string) (*Recorder, error)
 	}, nil
 }
 
+// Insert insert data
 func (r *Recorder) Insert(args interface{}) error {
 	dbHandler := r.session.DB(r.set).C(r.collection)
 
@@ -37,6 +40,7 @@ func (r *Recorder) Insert(args interface{}) error {
 	return nil
 }
 
+// FindLatest find latest device data
 func (r *Recorder) FindLatest(deviceid uint64, record interface{}) error {
 	dbHandler := r.session.DB(r.set).C(r.collection)
 	err := dbHandler.Find(bson.M{
@@ -47,6 +51,7 @@ func (r *Recorder) FindLatest(deviceid uint64, record interface{}) error {
 	return err
 }
 
+// FindByTimestamp find by timestmp
 func (r *Recorder) FindByTimestamp(deviceid uint64, start uint64, end uint64, records interface{}) error {
 	dbHandler := r.session.DB(r.set).C(r.collection)
 	err := dbHandler.Find(bson.M{

+ 6 - 2
pkg/mongo/recorder_test.go

@@ -1,10 +1,10 @@
 package mongo
 
 import (
+	"reflect"
 	"sparrow/pkg/protocol"
 	"sparrow/pkg/rpcs"
 	"sparrow/pkg/tlv"
-	"reflect"
 	"testing"
 	"time"
 )
@@ -24,7 +24,11 @@ func TestRecorder(t *testing.T) {
 	timestamp := uint64(time.Now().Unix() * 1000)
 
 	subdata := protocol.SubData{
-		Head:   protocol.SubDataHead{1, 2, 3},
+		Head: protocol.SubDataHead{
+			SubDeviceid: 1,
+			PropertyNum: 2,
+			ParamsCount: 3,
+		},
 		Params: tlvs,
 	}
 

+ 5 - 0
pkg/mqtt/broker.go

@@ -5,10 +5,12 @@ import (
 	"time"
 )
 
+// Broker a mqtt broker
 type Broker struct {
 	mgr *Manager
 }
 
+// NewBroker create new broker
 func NewBroker(p Provider) *Broker {
 	// manager
 	mgr := NewManager(p)
@@ -18,10 +20,12 @@ func NewBroker(p Provider) *Broker {
 	return handler
 }
 
+// Handle tcp conn handle
 func (b *Broker) Handle(conn net.Conn) {
 	b.mgr.NewConn(conn)
 }
 
+// SendMessageToDevice send message to device
 func (b *Broker) SendMessageToDevice(deviceid uint64, msgtype string, message []byte, timeout time.Duration) error {
 	msg := &Publish{}
 	msg.Header.QosLevel = QosAtLeastOnce
@@ -30,6 +34,7 @@ func (b *Broker) SendMessageToDevice(deviceid uint64, msgtype string, message []
 	return b.mgr.PublishMessage2Device(deviceid, msg, timeout)
 }
 
+// GetToken get device token with device id
 func (b *Broker) GetToken(deviceid uint64) ([]byte, error) {
 	return b.mgr.GetToken(deviceid)
 }

+ 38 - 33
pkg/mqtt/connection.go

@@ -3,35 +3,39 @@ package mqtt
 import (
 	"encoding/hex"
 	"errors"
+	"net"
 	"sparrow/pkg/rpcs"
 	"sparrow/pkg/server"
-	"net"
 	"time"
 )
 
+// const def
 const (
 	SendChanLen      = 16
 	defaultKeepAlive = 30
 )
 
+// ResponseType response type
 type ResponseType struct {
 	SendTime    uint8
 	PublishType uint8
 	DataType    string
 }
 
+// Connection client connection
 type Connection struct {
 	Mgr             *Manager
-	DeviceId        uint64
+	DeviceID        uint64
 	Conn            net.Conn
 	SendChan        chan Message
-	MessageId       uint16
+	MessageID       uint16
 	MessageWaitChan map[uint16]chan error
 	KeepAlive       uint16
 	LastHbTime      int64
 	Token           []byte
 }
 
+// NewConnection create a connection
 func NewConnection(conn net.Conn, mgr *Manager) *Connection {
 	sendchan := make(chan Message, SendChanLen)
 	c := &Connection{
@@ -48,6 +52,7 @@ func NewConnection(conn net.Conn, mgr *Manager) *Connection {
 	return c
 }
 
+// Submit submit a message to send chan
 func (c *Connection) Submit(msg Message) {
 	if c.Conn != nil {
 		c.SendChan <- msg
@@ -59,8 +64,8 @@ func (c *Connection) Publish(msg Message, timeout time.Duration) error {
 	server.Log.Debugf("publishing message : %v, timeout %v", msg, timeout)
 
 	message := msg.(*Publish)
-	message.MessageId = c.MessageId
-	c.MessageId++
+	message.MessageID = c.MessageID
+	c.MessageID++
 	c.Submit(message)
 
 	ch := make(chan error)
@@ -70,15 +75,15 @@ func (c *Connection) Publish(msg Message, timeout time.Duration) error {
 		return nil
 	}
 
-	c.MessageWaitChan[message.MessageId] = ch
+	c.MessageWaitChan[message.MessageID] = ch
 	// wait for timeout and
 	go func() {
 		timer := time.NewTimer(timeout)
 		<-timer.C
-		waitCh, exist := c.MessageWaitChan[message.MessageId]
+		waitCh, exist := c.MessageWaitChan[message.MessageID]
 		if exist {
 			waitCh <- errors.New("timeout pushlishing message.")
-			delete(c.MessageWaitChan, message.MessageId)
+			delete(c.MessageWaitChan, message.MessageID)
 			close(waitCh)
 		}
 	}()
@@ -87,18 +92,18 @@ func (c *Connection) Publish(msg Message, timeout time.Duration) error {
 	return err
 }
 
-func (c *Connection) confirmPublish(messageid uint16) {
-	waitCh, exist := c.MessageWaitChan[messageid]
+func (c *Connection) confirmPublish(MessageID uint16) {
+	waitCh, exist := c.MessageWaitChan[MessageID]
 	if exist {
 		waitCh <- nil
-		delete(c.MessageWaitChan, messageid)
+		delete(c.MessageWaitChan, MessageID)
 		close(waitCh)
 	}
 }
 
 func (c *Connection) ValidateToken(token []byte) error {
 
-	err := c.Mgr.Provider.ValidateDeviceToken(c.DeviceId, token)
+	err := c.Mgr.Provider.ValidateDeviceToken(c.DeviceID, token)
 	if err != nil {
 		return err
 	}
@@ -109,12 +114,12 @@ func (c *Connection) ValidateToken(token []byte) error {
 }
 
 func (c *Connection) Close() {
-	deviceid := c.DeviceId
-	server.Log.Infof("closing connection of device %v", deviceid)
+	DeviceID := c.DeviceID
+	server.Log.Infof("closing connection of device %v", DeviceID)
 	if c.Conn != nil {
 		c.Conn.Close()
 		c.Conn = nil
-		c.Mgr.Provider.OnDeviceOffline(deviceid)
+		c.Mgr.Provider.OnDeviceOffline(DeviceID)
 	}
 	if c.SendChan != nil {
 		close(c.SendChan)
@@ -148,20 +153,20 @@ func (c *Connection) RcvMsgFromClient() {
 				ret = RetCodeUnacceptableProtocolVersion
 			}
 
-			if len(msg.ClientId) < 1 || len(msg.ClientId) > 23 {
-				server.Log.Warn("invalid clientid length: %d", len(msg.ClientId))
+			if len(msg.ClientID) < 1 || len(msg.ClientID) > 23 {
+				server.Log.Warn("invalid ClientID length: %d", len(msg.ClientID))
 				ret = RetCodeIdentifierRejected
 				c.Close()
 				return
 			}
 
-			deviceid, err := ClientIdToDeviceId(msg.ClientId)
+			DeviceID, err := ClientIDToDeviceID(msg.ClientID)
 			if err != nil {
 				server.Log.Warn("invalid Identify: %d", ret)
 				c.Close()
 				return
 			}
-			c.DeviceId = deviceid
+			c.DeviceID = DeviceID
 
 			token, err := hex.DecodeString(msg.Password)
 			if err != nil {
@@ -185,13 +190,13 @@ func (c *Connection) RcvMsgFromClient() {
 			}
 
 			args := rpcs.ArgsGetOnline{
-				Id:                c.DeviceId,
+				Id:                c.DeviceID,
 				ClientIP:          host,
 				AccessRPCHost:     server.GetRPCHost(),
 				HeartbeatInterval: uint32(c.KeepAlive),
 			}
 
-			c.Mgr.AddConn(c.DeviceId, c)
+			c.Mgr.AddConn(c.DeviceID, c)
 			connack := &ConnAck{
 				ReturnCode: ret,
 			}
@@ -206,23 +211,23 @@ func (c *Connection) RcvMsgFromClient() {
 				return
 			}
 
-			server.Log.Infof("device %d, connected to server now, host: %s", c.DeviceId, host)
+			server.Log.Infof("device %d, connected to server now, host: %s", c.DeviceID, host)
 
 		case *Publish:
 			server.Log.Infof("%s, publish topic: %s", host, msg.TopicName)
 
-			c.Mgr.PublishMessage2Server(c.DeviceId, msg)
+			c.Mgr.PublishMessage2Server(c.DeviceID, msg)
 			if msg.QosLevel.IsAtLeastOnce() {
 				server.Log.Infof("publish ack send now")
-				publishack := &PubAck{MessageId: msg.MessageId}
+				publishack := &PubAck{MessageID: msg.MessageID}
 				c.Submit(publishack)
 			} else if msg.QosLevel.IsExactlyOnce() {
 				server.Log.Infof("publish Rec send now")
-				publishRec := &PubRec{MessageId: msg.MessageId}
+				publishRec := &PubRec{MessageID: msg.MessageID}
 				c.Submit(publishRec)
 			}
 
-			err := c.Mgr.Provider.OnDeviceHeartBeat(c.DeviceId)
+			err := c.Mgr.Provider.OnDeviceHeartBeat(c.DeviceID)
 			if err != nil {
 				server.Log.Warnf("%s, heartbeat set error %s, close now...", host, err)
 				c.Close()
@@ -231,8 +236,8 @@ func (c *Connection) RcvMsgFromClient() {
 
 		case *PubAck:
 			server.Log.Infof("%s, comes publish ack", host)
-			c.confirmPublish(msg.MessageId)
-			err := c.Mgr.Provider.OnDeviceHeartBeat(c.DeviceId)
+			c.confirmPublish(msg.MessageID)
+			err := c.Mgr.Provider.OnDeviceHeartBeat(c.DeviceID)
 			if err != nil {
 				server.Log.Warnf("%s, heartbeat set error %s, close now...", host, err)
 				c.Close()
@@ -241,18 +246,18 @@ func (c *Connection) RcvMsgFromClient() {
 
 		case *PubRec:
 			server.Log.Infof("%s, comes publish rec", host)
-			publishRel := &PubRel{MessageId: msg.MessageId}
+			publishRel := &PubRel{MessageID: msg.MessageID}
 			c.Submit(publishRel)
 
 		case *PubRel:
 			server.Log.Infof("%s, comes publish rel", host)
-			publishCom := &PubComp{MessageId: msg.MessageId}
+			publishCom := &PubComp{MessageID: msg.MessageID}
 			c.Submit(publishCom)
 
 		case *PubComp:
 			server.Log.Infof("%s, comes publish comp", host)
-			c.confirmPublish(msg.MessageId)
-			err := c.Mgr.Provider.OnDeviceHeartBeat(c.DeviceId)
+			c.confirmPublish(msg.MessageID)
+			err := c.Mgr.Provider.OnDeviceHeartBeat(c.DeviceID)
 			if err != nil {
 				server.Log.Warnf("%s, heartbeat set error %s, close now...", host, err)
 				c.Close()
@@ -262,7 +267,7 @@ func (c *Connection) RcvMsgFromClient() {
 		case *PingReq:
 			server.Log.Infof("%s, ping req comes", host)
 			pingrsp := &PingResp{}
-			err := c.Mgr.Provider.OnDeviceHeartBeat(c.DeviceId)
+			err := c.Mgr.Provider.OnDeviceHeartBeat(c.DeviceID)
 			if err != nil {
 				server.Log.Warnf("%s, heartbeat set error %s, close now...", host, err)
 				c.Close()

+ 10 - 10
pkg/mqtt/manager.go

@@ -1,8 +1,8 @@
 package mqtt
 
 import (
-	"sparrow/pkg/server"
 	"net"
+	"sparrow/pkg/server"
 	"sync"
 	"time"
 )
@@ -49,34 +49,34 @@ func (m *Manager) DelConn(id uint64) {
 	m.CxtMutex.Unlock()
 }
 
-func (m *Manager) GetToken(deviceid uint64) ([]byte, error) {
+func (m *Manager) GetToken(DeviceID uint64) ([]byte, error) {
 	m.CxtMutex.RLock()
-	con, exist := m.IdToConn[deviceid]
+	con, exist := m.IdToConn[DeviceID]
 	m.CxtMutex.RUnlock()
 	if !exist {
-		return nil, errorf("device not exist: %v[%v]", deviceid, deviceid)
+		return nil, errorf("device not exist: %v[%v]", DeviceID, DeviceID)
 	}
 
 	return con.Token, nil
 }
 
-func (m *Manager) PublishMessage2Device(deviceid uint64, msg *Publish, timeout time.Duration) error {
+func (m *Manager) PublishMessage2Device(DeviceID uint64, msg *Publish, timeout time.Duration) error {
 	m.CxtMutex.RLock()
-	con, exist := m.IdToConn[deviceid]
+	con, exist := m.IdToConn[DeviceID]
 	m.CxtMutex.RUnlock()
 	if !exist {
-		return errorf("device not exist: %v", deviceid)
+		return errorf("device not exist: %v", DeviceID)
 	}
 
 	return con.Publish(msg, timeout)
 }
 
-func (m *Manager) PublishMessage2Server(deviceid uint64, msg *Publish) error {
+func (m *Manager) PublishMessage2Server(DeviceID uint64, msg *Publish) error {
 	topic := msg.TopicName
 
 	payload := msg.Payload.(BytesPayload)
 
-	m.Provider.OnDeviceMessage(deviceid, topic, payload)
+	m.Provider.OnDeviceMessage(DeviceID, topic, payload)
 	return nil
 }
 
@@ -93,7 +93,7 @@ func (m *Manager) CleanWorker() {
 			if uint16(curTime-con.LastHbTime) > uint16(3*con.KeepAlive/2) {
 				server.Log.Infof("connection %v inactive , removing", con)
 				con.Close()
-				delete(m.IdToConn, con.DeviceId)
+				delete(m.IdToConn, con.DeviceID)
 			}
 		}
 

+ 35 - 35
pkg/mqtt/message.go

@@ -172,7 +172,7 @@ type Connect struct {
 	CleanSession               bool
 	WillQos                    TagQosLevel
 	KeepAliveTimer             uint16
-	ClientId                   string
+	ClientID                   string
 	WillTopic, WillMessage     string
 	UsernameFlag, PasswordFlag bool
 	Username, Password         string
@@ -196,7 +196,7 @@ func (msg *Connect) Encode(w io.Writer) (err error) {
 	setUint8(msg.ProtocolVersion, buf)
 	buf.WriteByte(flags)
 	setUint16(msg.KeepAliveTimer, buf)
-	setString(msg.ClientId, buf)
+	setString(msg.ClientID, buf)
 	if msg.WillFlag {
 		setString(msg.WillTopic, buf)
 		setString(msg.WillMessage, buf)
@@ -228,7 +228,7 @@ func (msg *Connect) Decode(r io.Reader, hdr Header, packetRemaining int32) (err
 	if err != nil {
 		return err
 	}
-	clientId, err := getString(r, &packetRemaining)
+	ClientID, err := getString(r, &packetRemaining)
 	if err != nil {
 		return err
 	}
@@ -244,7 +244,7 @@ func (msg *Connect) Decode(r io.Reader, hdr Header, packetRemaining int32) (err
 		WillFlag:        flags&0x04 > 0,
 		CleanSession:    flags&0x02 > 0,
 		KeepAliveTimer:  keepAliveTimer,
-		ClientId:        clientId,
+		ClientID:        ClientID,
 	}
 
 	if msg.WillFlag {
@@ -320,7 +320,7 @@ func (msg *ConnAck) Decode(r io.Reader, hdr Header, packetRemaining int32) (err
 type Publish struct {
 	Header
 	TopicName string
-	MessageId uint16
+	MessageID uint16
 	Payload   Payload
 }
 
@@ -329,7 +329,7 @@ func (msg *Publish) Encode(w io.Writer) (err error) {
 
 	setString(msg.TopicName, buf)
 	if msg.Header.QosLevel.HasId() {
-		setUint16(msg.MessageId, buf)
+		setUint16(msg.MessageID, buf)
 	}
 
 	if err = msg.Payload.WritePayload(buf); err != nil {
@@ -351,7 +351,7 @@ func (msg *Publish) Decode(r io.Reader, hdr Header, packetRemaining int32) (err
 		return err
 	}
 	if msg.Header.QosLevel.HasId() {
-		msg.MessageId, err = getUint16(r, &packetRemaining)
+		msg.MessageID, err = getUint16(r, &packetRemaining)
 		if err != nil {
 			return err
 		}
@@ -366,67 +366,67 @@ func (msg *Publish) Decode(r io.Reader, hdr Header, packetRemaining int32) (err
 // PubAck represents an MQTT PUBACK message.
 type PubAck struct {
 	Header
-	MessageId uint16
+	MessageID uint16
 }
 
 func (msg *PubAck) Encode(w io.Writer) error {
-	return encodeAckCommon(w, &msg.Header, msg.MessageId, MsgPubAck)
+	return encodeAckCommon(w, &msg.Header, msg.MessageID, MsgPubAck)
 }
 
 func (msg *PubAck) Decode(r io.Reader, hdr Header, packetRemaining int32) (err error) {
 	msg.Header = hdr
-	return decodeAckCommon(r, packetRemaining, &msg.MessageId)
+	return decodeAckCommon(r, packetRemaining, &msg.MessageID)
 }
 
 // PubRec represents an MQTT PUBREC message.
 type PubRec struct {
 	Header
-	MessageId uint16
+	MessageID uint16
 }
 
 func (msg *PubRec) Encode(w io.Writer) error {
-	return encodeAckCommon(w, &msg.Header, msg.MessageId, MsgPubRec)
+	return encodeAckCommon(w, &msg.Header, msg.MessageID, MsgPubRec)
 }
 
 func (msg *PubRec) Decode(r io.Reader, hdr Header, packetRemaining int32) (err error) {
 	msg.Header = hdr
-	return decodeAckCommon(r, packetRemaining, &msg.MessageId)
+	return decodeAckCommon(r, packetRemaining, &msg.MessageID)
 }
 
 // PubRel represents an MQTT PUBREL message.
 type PubRel struct {
 	Header
-	MessageId uint16
+	MessageID uint16
 }
 
 func (msg *PubRel) Encode(w io.Writer) error {
-	return encodeAckCommon(w, &msg.Header, msg.MessageId, MsgPubRel)
+	return encodeAckCommon(w, &msg.Header, msg.MessageID, MsgPubRel)
 }
 
 func (msg *PubRel) Decode(r io.Reader, hdr Header, packetRemaining int32) (err error) {
 	msg.Header = hdr
-	return decodeAckCommon(r, packetRemaining, &msg.MessageId)
+	return decodeAckCommon(r, packetRemaining, &msg.MessageID)
 }
 
 // PubComp represents an MQTT PUBCOMP message.
 type PubComp struct {
 	Header
-	MessageId uint16
+	MessageID uint16
 }
 
 func (msg *PubComp) Encode(w io.Writer) error {
-	return encodeAckCommon(w, &msg.Header, msg.MessageId, MsgPubComp)
+	return encodeAckCommon(w, &msg.Header, msg.MessageID, MsgPubComp)
 }
 
 func (msg *PubComp) Decode(r io.Reader, hdr Header, packetRemaining int32) (err error) {
 	msg.Header = hdr
-	return decodeAckCommon(r, packetRemaining, &msg.MessageId)
+	return decodeAckCommon(r, packetRemaining, &msg.MessageID)
 }
 
 // Subscribe represents an MQTT SUBSCRIBE message.
 type Subscribe struct {
 	Header
-	MessageId uint16
+	MessageID uint16
 	Topics    []TopicQos
 }
 
@@ -438,7 +438,7 @@ type TopicQos struct {
 func (msg *Subscribe) Encode(w io.Writer) (err error) {
 	buf := new(bytes.Buffer)
 	if msg.Header.QosLevel.HasId() {
-		setUint16(msg.MessageId, buf)
+		setUint16(msg.MessageID, buf)
 	}
 	for _, topicSub := range msg.Topics {
 		setString(topicSub.Topic, buf)
@@ -452,7 +452,7 @@ func (msg *Subscribe) Decode(r io.Reader, hdr Header, packetRemaining int32) (er
 	msg.Header = hdr
 
 	if msg.Header.QosLevel.HasId() {
-		msg.MessageId, err = getUint16(r, &packetRemaining)
+		msg.MessageID, err = getUint16(r, &packetRemaining)
 		if err != nil {
 			return err
 		}
@@ -480,13 +480,13 @@ func (msg *Subscribe) Decode(r io.Reader, hdr Header, packetRemaining int32) (er
 // SubAck represents an MQTT SUBACK message.
 type SubAck struct {
 	Header
-	MessageId uint16
+	MessageID uint16
 	TopicsQos []TagQosLevel
 }
 
 func (msg *SubAck) Encode(w io.Writer) (err error) {
 	buf := new(bytes.Buffer)
-	setUint16(msg.MessageId, buf)
+	setUint16(msg.MessageID, buf)
 	for i := 0; i < len(msg.TopicsQos); i += 1 {
 		setUint8(uint8(msg.TopicsQos[i]), buf)
 	}
@@ -497,7 +497,7 @@ func (msg *SubAck) Encode(w io.Writer) (err error) {
 func (msg *SubAck) Decode(r io.Reader, hdr Header, packetRemaining int32) (err error) {
 	msg.Header = hdr
 
-	msg.MessageId, err = getUint16(r, &packetRemaining)
+	msg.MessageID, err = getUint16(r, &packetRemaining)
 	if err != nil {
 		return err
 	}
@@ -518,14 +518,14 @@ func (msg *SubAck) Decode(r io.Reader, hdr Header, packetRemaining int32) (err e
 // Unsubscribe represents an MQTT UNSUBSCRIBE message.
 type Unsubscribe struct {
 	Header
-	MessageId uint16
+	MessageID uint16
 	Topics    []string
 }
 
 func (msg *Unsubscribe) Encode(w io.Writer) (err error) {
 	buf := new(bytes.Buffer)
 	if msg.Header.QosLevel.HasId() {
-		setUint16(msg.MessageId, buf)
+		setUint16(msg.MessageID, buf)
 	}
 	for _, topic := range msg.Topics {
 		setString(topic, buf)
@@ -538,7 +538,7 @@ func (msg *Unsubscribe) Decode(r io.Reader, hdr Header, packetRemaining int32) (
 	msg.Header = hdr
 
 	if msg.Header.QosLevel.HasId() {
-		msg.MessageId, err = getUint16(r, &packetRemaining)
+		msg.MessageID, err = getUint16(r, &packetRemaining)
 		if err != nil {
 			return err
 		}
@@ -559,16 +559,16 @@ func (msg *Unsubscribe) Decode(r io.Reader, hdr Header, packetRemaining int32) (
 // UnsubAck represents an MQTT UNSUBACK message.
 type UnsubAck struct {
 	Header
-	MessageId uint16
+	MessageID uint16
 }
 
 func (msg *UnsubAck) Encode(w io.Writer) error {
-	return encodeAckCommon(w, &msg.Header, msg.MessageId, MsgUnsubAck)
+	return encodeAckCommon(w, &msg.Header, msg.MessageID, MsgUnsubAck)
 }
 
 func (msg *UnsubAck) Decode(r io.Reader, hdr Header, packetRemaining int32) (err error) {
 	msg.Header = hdr
-	return decodeAckCommon(r, packetRemaining, &msg.MessageId)
+	return decodeAckCommon(r, packetRemaining, &msg.MessageID)
 }
 
 // PingReq represents an MQTT PINGREQ message.
@@ -619,14 +619,14 @@ func (msg *Disconnect) Decode(r io.Reader, hdr Header, packetRemaining int32) er
 	return nil
 }
 
-func encodeAckCommon(w io.Writer, hdr *Header, messageId uint16, msgType TagMessageType) error {
+func encodeAckCommon(w io.Writer, hdr *Header, MessageID uint16, msgType TagMessageType) error {
 	buf := new(bytes.Buffer)
-	setUint16(messageId, buf)
+	setUint16(MessageID, buf)
 	return writeMessage(w, msgType, hdr, buf, 0)
 }
 
-func decodeAckCommon(r io.Reader, packetRemaining int32, messageId *uint16) (err error) {
-	*messageId, err = getUint16(r, &packetRemaining)
+func decodeAckCommon(r io.Reader, packetRemaining int32, MessageID *uint16) (err error) {
+	*MessageID, err = getUint16(r, &packetRemaining)
 	if err != nil {
 		return err
 	}

+ 1 - 1
pkg/mqtt/utils.go

@@ -28,7 +28,7 @@ func DeviceIdToClientId(deviceid uint64) string {
 	return strconv.FormatUint(deviceid, 16)
 }
 
-func ClientIdToDeviceId(identify string) (uint64, error) {
+func ClientIDToDeviceID(identify string) (uint64, error) {
 	deviceId, err := strconv.ParseUint(identify, 16, 64)
 	if err != nil {
 		return uint64(0), err

+ 13 - 0
pkg/mqtt/utils_test.go

@@ -0,0 +1,13 @@
+package mqtt
+
+import "testing"
+
+func TestClientIdToDeviceId(t *testing.T) {
+	id, err := ClientIdToDeviceId("ff")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if id != 255 {
+		t.Fatalf("result not 255,but %d", id)
+	}
+}

+ 2 - 2
pkg/protocol/structure.go

@@ -7,7 +7,7 @@ import (
 type CommandEventHead struct {
 	Flag        uint8
 	Timestamp   uint64
-	Token       [16]byte
+	Token       [8]byte
 	SubDeviceid uint16
 	No          uint16
 	Priority    uint16
@@ -27,7 +27,7 @@ type Event struct {
 type DataHead struct {
 	Flag      uint8
 	Timestamp uint64
-	Token     [16]byte
+	Token     [8]byte
 }
 
 type Data struct {

+ 5 - 0
pkg/rpcs/registry.go

@@ -8,6 +8,11 @@ type ArgsDeviceRegister struct {
 	ModuleName    string
 }
 
+// ArgsDeviceAuth device auth
+type ArgsDeviceAuth struct {
+	DeviceID int64
+}
+
 // ArgsDeviceUpdate device update args
 type ArgsDeviceUpdate struct {
 	DeviceIdentifier  string

+ 3 - 3
pkg/rule/ifttt.go

@@ -19,7 +19,7 @@ func (ift *Ifttt) Check(deviceid uint64, eventid uint16) error {
 		RuleType: "ifttt",
 		DeviceID: int64(deviceid),
 	}
-	err := server.RPCCallByName("registry", "Registry.QueryRules", query, actions)
+	err := server.RPCCallByName(nil, "registry", "Registry.QueryRules", query, actions)
 	if err != nil {
 		server.Log.Warnf("load ifttt rules error : %v", err)
 		return err
@@ -27,14 +27,14 @@ func (ift *Ifttt) Check(deviceid uint64, eventid uint16) error {
 
 	if len(*actions) > 0 {
 		device := &models.Device{}
-		err := server.RPCCallByName("registry", "Registry.FindDeviceById", int64(deviceid), device)
+		err := server.RPCCallByName(nil, "registry", "Registry.FindDeviceById", int64(deviceid), device)
 		if err != nil {
 			server.Log.Errorf("find device error : %v", err)
 			return err
 		}
 
 		product := &models.Product{}
-		err = server.RPCCallByName("registry", "Registry.FindProduct", device.ProductID, product)
+		err = server.RPCCallByName(nil, "registry", "Registry.FindProduct", device.ProductID, product)
 		if err != nil {
 			server.Log.Errorf("find product error : %v", err)
 			return err

+ 4 - 4
pkg/rule/rule_action.go

@@ -20,13 +20,13 @@ func performRuleAction(target string, action string) error {
 
 	identifier := parts[1]
 	device := &models.Device{}
-	err := server.RPCCallByName("registry", "Registry.FindDeviceByIdentifier", identifier, device)
+	err := server.RPCCallByName(nil, "registry", "Registry.FindDeviceByIdentifier", identifier, device)
 	if err != nil {
 		return err
 	}
 
 	product := &models.Product{}
-	err = server.RPCCallByName("registry", "Registry.FindProduct", device.ProductID, product)
+	err = server.RPCCallByName(nil, "registry", "Registry.FindProduct", device.ProductID, product)
 	if err != nil {
 		return err
 	}
@@ -66,7 +66,7 @@ func performRuleAction(target string, action string) error {
 			Params:    command.Params,
 		}
 		cmdreply := rpcs.ReplySendCommand{}
-		err = server.RPCCallByName("controller", "Controller.SendCommand", cmdargs, &cmdreply)
+		err = server.RPCCallByName(nil, "controller", "Controller.SendCommand", cmdargs, &cmdreply)
 		if err != nil {
 			server.Log.Errorf("send device command error: %v", err)
 			return err
@@ -82,7 +82,7 @@ func performRuleAction(target string, action string) error {
 			Status:   status,
 		}
 		statusreply := rpcs.ReplySetStatus{}
-		err = server.RPCCallByName("controller", "Controller.SetStatus", statusargs, &statusreply)
+		err = server.RPCCallByName(nil, "controller", "Controller.SetStatus", statusargs, &statusreply)
 		if err != nil {
 			server.Log.Errorf("set devie status error: %v", err)
 			return err

+ 3 - 2
pkg/rule/timer.go

@@ -5,8 +5,9 @@ import (
 	"fmt"
 	"sparrow/pkg/models"
 	"sparrow/pkg/server"
-	"github.com/robfig/cron"
 	"time"
+
+	"github.com/robfig/cron"
 )
 
 type Timer struct {
@@ -37,7 +38,7 @@ func (t *Timer) refresh() {
 	query := &models.Rule{
 		RuleType: "timer",
 	}
-	err := server.RPCCallByName("registry", "Registry.QueryRules", query, timers)
+	err := server.RPCCallByName(nil, "registry", "Registry.QueryRules", query, timers)
 	if err != nil {
 		server.Log.Warnf("refresh timer rules error : %v", err)
 		return

+ 2 - 0
pkg/server/config.go

@@ -16,9 +16,11 @@ const (
 	FlagRPCHost  = "rpchost"
 	FlagEtcd     = "etcd"
 	FlagLogLevel = "loglevel"
+	FlagUDPHost  = "udphost"
 )
 
 var (
+	confUDPHost = flag.String(FlagUDPHost, "", "udp server listen address, format ip:port")
 	confTCPHost = flag.String(FlagTCPHost, "", "tcp server listen address, format ip:port")
 	confUseTls  = flag.Bool(FlagUseTls, false, "if tcp server uses tls, default false")
 

+ 2 - 0
pkg/server/errors.go

@@ -12,4 +12,6 @@ const (
 	errWrongHostAddr           = "wrong address : %s"
 	errWrongEtcdPath           = "wrong path in etcd: %s"
 	errServerManagerNotInit    = "sever manager not init!"
+	errUDPHandlerNotRegisterd  = "Start UDP server error : udp handler not registerd!"
+	errUDPListenFailed         = "FATAL: udp listen (%s) failed - %s"
 )

+ 6 - 2
pkg/server/rpc_client.go

@@ -6,6 +6,8 @@ import (
 	"math/rand"
 	"net/rpc"
 	"time"
+
+	"github.com/opentracing/opentracing-go"
 )
 
 type RPCClient struct {
@@ -40,7 +42,8 @@ func rpcCallWithReconnect(client *rpc.Client, addr string, serverMethod string,
 }
 
 // RPC call with reconnect and retry.
-func (client *RPCClient) Call(severName string, serverMethod string, args interface{}, reply interface{}) error {
+func (client *RPCClient) Call(span opentracing.Span, severName string, serverMethod string, args interface{}, reply interface{}) error {
+	defer span.Finish()
 	addrs, err := serverInstance.svrmgr.GetServerHosts(severName, FlagRPCHost)
 	if err != nil {
 		return err
@@ -60,7 +63,8 @@ func (client *RPCClient) Call(severName string, serverMethod string, args interf
 				continue
 			}
 		}
-
+		span.SetTag("server.method", serverMethod)
+		span.SetTag("server.addr", addr)
 		err = rpcCallWithReconnect(client.clients[mapkey], addr, serverMethod, args, reply)
 		if err != nil {
 			Log.Warnf("RpcCallWithReconnect error : %s", err)

+ 1 - 1
pkg/server/rpc_client_test.go

@@ -22,7 +22,7 @@ func validateRPCClient(t *testing.T) {
 		t.Fatalf("rpc client test faild, want %d, got %d", testRPCArgs.A*testRPCArgs.B, reply)
 	}
 
-	err = RPCCallByName("test", "Arith.Multiply", args, &reply)
+	err = RPCCallByName(nil, "test", "Arith.Multiply", args, &reply)
 	if err != nil {
 		t.Fatal(err)
 	}

+ 64 - 16
pkg/server/server.go

@@ -7,10 +7,16 @@
 package server
 
 import (
+	"context"
+
+	"github.com/opentracing/opentracing-go"
+	"github.com/opentracing/opentracing-go/log"
+
 	// "github.com/vharitonsky/iniflags"
 	"flag"
 	"net/http"
 	"net/rpc"
+	"sparrow/pkg/tracing"
 	"time"
 )
 
@@ -26,6 +32,7 @@ type Server struct {
 	tcpsvr    *TCPServer  // TCP server
 	httpsvr   *HTTPServer // HTTP server
 	timertask TimerTask   // timer task
+	udpsvr    *UDPServer
 	// functions
 	svrmgr *ServerManager // service registration&discovery manager
 	rpccli *RPCClient     // rpc client
@@ -62,14 +69,13 @@ func Init(name string) error {
 		if err != nil {
 			return err
 		}
-
 		Log.Infof("server %s init success.", name)
 
 	}
 	return nil
 }
 
-// register TCP handler class
+// RegisterTCPHandler register TCP handler class
 func RegisterTCPHandler(handler TCPHandler) error {
 	if serverInstance == nil {
 		return errorf(errServerNotInit)
@@ -81,7 +87,7 @@ func RegisterTCPHandler(handler TCPHandler) error {
 
 		addr, err := fixHostIp(*confTCPHost)
 		if err != nil {
-			return errorf(errWrongHostAddr, confTCPHost)
+			return errorf(errWrongHostAddr, *confTCPHost)
 		}
 
 		serverInstance.tcpsvr = &TCPServer{
@@ -93,7 +99,28 @@ func RegisterTCPHandler(handler TCPHandler) error {
 	return nil
 }
 
-// register HTTP handler class
+// RegisterUDPHandler register UDP handler class
+func RegisterUDPHandler(handler UDPHandler) error {
+	if serverInstance == nil {
+		return errorf(errServerNotInit)
+	}
+	if serverInstance.udpsvr == nil {
+		if *confUDPHost == "" {
+			return errorf(errMissingFlag, FlagUDPHost)
+		}
+		addr, err := fixHostIp(*confUDPHost)
+		if err != nil {
+			return errorf(errWrongHostAddr, *confUDPHost)
+		}
+		serverInstance.udpsvr = &UDPServer{
+			addr:    addr,
+			handler: handler,
+		}
+	}
+	return nil
+}
+
+// RegisterHTTPHandler register HTTP handler class
 func RegisterHTTPHandler(handler http.Handler) error {
 	if serverInstance == nil {
 		return errorf(errServerNotInit)
@@ -117,7 +144,7 @@ func RegisterHTTPHandler(handler http.Handler) error {
 	return nil
 }
 
-// register RPC handler class
+// RegisterRPCHandler register RPC handler class
 func RegisterRPCHandler(rcvr interface{}) error {
 	if serverInstance == nil {
 		return errorf(errServerNotInit)
@@ -150,7 +177,7 @@ func RegisterRPCHandler(rcvr interface{}) error {
 	return nil
 }
 
-// register timer task
+// RegisterTimerTask register timer task
 func RegisterTimerTask(task TimerTask) error {
 	if serverInstance == nil {
 		return errorf(errServerNotInit)
@@ -161,16 +188,28 @@ func RegisterTimerTask(task TimerTask) error {
 	return nil
 }
 
-// rpc call by name
-func RPCCallByName(serverName string, serverMethod string, args interface{}, reply interface{}) error {
+// RPCCallByName rpc call by name
+func RPCCallByName(ctx context.Context, serverName string, serverMethod string, args interface{}, reply interface{}) error {
 	if serverInstance == nil {
 		return errorf(errServerNotInit)
 	}
+	var span opentracing.Span
+
+	if ctx != nil {
+		sp := opentracing.SpanFromContext(ctx)
+		span = opentracing.StartSpan(serverName, opentracing.ChildOf(sp.Context()))
 
-	return serverInstance.rpccli.Call(serverName, serverMethod, args, reply)
+	} else {
+		span = opentracing.StartSpan(serverName)
+	}
+	span.LogFields(
+		log.Object("args", args),
+	)
+	span.SetTag("server.name", serverName)
+	return serverInstance.rpccli.Call(span, serverName, serverMethod, args, reply)
 }
 
-// rpc call by host
+// RPCCallByHost rpc call by host
 func RPCCallByHost(host string, serverMethod string, args interface{}, reply interface{}) error {
 	if serverInstance == nil {
 		return errorf(errServerNotInit)
@@ -179,7 +218,7 @@ func RPCCallByHost(host string, serverMethod string, args interface{}, reply int
 	return serverInstance.rpccli.CallHost(host, serverMethod, args, reply)
 }
 
-// get server's hosts by server name and service type
+// GetServerHosts get server's hosts by server name and service type
 func GetServerHosts(serverName string, hostType string) ([]string, error) {
 	if serverInstance == nil {
 		return nil, errorf(errServerNotInit)
@@ -205,7 +244,7 @@ func GetHTTPHost() string {
 	return serverInstance.httpsvr.addr
 }
 
-// start service
+// Run start service
 func Run() error {
 	if serverInstance == nil {
 		return errorf(errServerNotInit)
@@ -227,6 +266,14 @@ func Run() error {
 		Log.Info("starting http server ... OK")
 	}
 
+	if serverInstance.udpsvr != nil {
+		err := serverInstance.udpsvr.Start()
+		if err != nil {
+			return err
+		}
+		Log.Infof("starting udp server ... OK")
+	}
+
 	if serverInstance.rpcsvr != nil {
 		err := serverInstance.rpcsvr.Start()
 		if err != nil {
@@ -234,7 +281,10 @@ func Run() error {
 		}
 		Log.Info("starting rpc server ... OK")
 	}
-
+	tracer, closer := tracing.Init(serverInstance.name)
+	// opentracing
+	defer closer.Close()
+	opentracing.InitGlobalTracer(tracer)
 	Log.Info("sever launch successfully!")
 
 	// loop to do something
@@ -248,7 +298,7 @@ func Run() error {
 		}
 		err = serverInstance.svrmgr.UpdateServerHosts()
 		if err != nil {
-			Log.Error("UpdateServerHosts error: %s", err)
+			Log.Errorf("UpdateServerHosts error: %s", err)
 		} else {
 			Log.Info("UpdateServerHosts Success")
 		}
@@ -260,6 +310,4 @@ func Run() error {
 
 		time.Sleep(60 * time.Second)
 	}
-
-	return nil
 }

+ 14 - 3
pkg/server/server_manager.go

@@ -13,12 +13,15 @@ import (
 )
 
 const (
-	EtcdServersPrefix    = "/pando/servers/"
+	// EtcdServersPrefix prefix
+	EtcdServersPrefix    = "/knowo/servers/"
 	EtcdServersPrefixCnt = 2
 	EnvTCPProxy          = "TCP_PROXY_ADDR"
 	EnvHTTPProxy         = "HTTP_PROXY_ADDR"
+	EnvUDPProxy          = "UDP_PROXY_ADDR"
 )
 
+// ServerManager server manager
 type ServerManager struct {
 	serverName string
 	// servername -> hosttype -> hostlist
@@ -27,6 +30,7 @@ type ServerManager struct {
 	etcdHosts  []string
 }
 
+// NewServerManager new server manager
 // etcd hosts is config as http://ip1:port1;http://ip2:port2;http://ip3:port3
 func NewServerManager(name string, etcd string) (*ServerManager, error) {
 	if etcd == "" {
@@ -69,6 +73,13 @@ func (mgr *ServerManager) RegisterServer() error {
 		addr, _ := fixHostIp(*confRPCHost)
 		response, err = kapi.Set(context.Background(), prefix+FlagRPCHost+"/"+addr, addr, opt)
 	}
+	if serverInstance.udpsvr != nil {
+		addr := os.Getenv(EnvUDPProxy)
+		if addr == "" {
+			addr, _ = fixHostIp(*confUDPHost)
+		}
+		response, err = kapi.Set(context.Background(), prefix+FlagUDPHost+"/"+addr, addr, opt)
+	}
 	if serverInstance.httpsvr != nil {
 		addr := os.Getenv(EnvHTTPProxy)
 		if addr == "" {
@@ -80,7 +91,7 @@ func (mgr *ServerManager) RegisterServer() error {
 		return err
 	}
 	// print common key info
-	Log.Infof("RegisterServer is done. Metadata is %q\n", response)
+	Log.Infof("RegisterServer is done. Metadata is %v\n", response)
 
 	return nil
 }
@@ -137,7 +148,7 @@ func (mgr *ServerManager) UpdateServerHosts() error {
 
 	mgr.mapServers = servers
 
-	//Log.Infof("UpdateServerHosts is done: %v", mgr.mapServers)
+	Log.Infof("UpdateServerHosts is done: %v", mgr.mapServers)
 	return nil
 
 }

+ 3 - 1
pkg/server/tcp_server_test.go

@@ -12,7 +12,7 @@ const (
 	testTCPHost = "localhost:12345"
 )
 
-var testEchoData = "hello pando"
+var testEchoData = "hello"
 
 type testEchoHandler struct{}
 
@@ -45,6 +45,7 @@ func validateTCPServer(t *testing.T, addr string) {
 		t.Fatal(err)
 	}
 	gotData := string(buf[:length])
+	t.Log(gotData)
 	if gotData != testEchoData {
 		t.Errorf("echo server test failed. want: %s, got: %s", testEchoData, gotData)
 	}
@@ -68,6 +69,7 @@ func validateTLSServer(t *testing.T, addr string) {
 		t.Fatal(err)
 	}
 	gotData := string(buf[:length])
+	t.Log(gotData)
 	if gotData != testEchoData {
 		t.Errorf("echo server test failed. want: %s, got: %s", testEchoData, gotData)
 	}

+ 52 - 0
pkg/server/udp_server.go

@@ -0,0 +1,52 @@
+package server
+
+import (
+	"net"
+	"runtime"
+
+	"golang.org/x/net/ipv4"
+	"golang.org/x/net/ipv6"
+)
+
+// UDPHandler udp handler
+type UDPHandler interface {
+	Handler(*net.UDPConn)
+}
+
+// UDPServer udp server
+type UDPServer struct {
+	addr    string
+	handler UDPHandler
+}
+
+// Start udp server start
+func (us *UDPServer) Start() error {
+	if us.handler == nil {
+		return errorf(errUDPHandlerNotRegisterd)
+	}
+	var ln *net.UDPConn
+	var err error
+	a, err := net.ResolveUDPAddr("udp", us.addr)
+	if err != nil {
+		return err
+	}
+	ln, err = net.ListenUDP("udp", a)
+	if err != nil {
+		return errorf(errUDPListenFailed, us.addr, err)
+	}
+	Log.Infof("UDP Server Listen on %s", us.addr)
+	if err := setUDPSocketOptions(ln); err != nil {
+		return err
+	}
+	go us.handler.Handler(ln)
+	return nil
+}
+func setUDPSocketOptions(conn *net.UDPConn) error {
+	if runtime.GOOS == "windows" {
+		return nil
+	}
+	if ip4 := conn.LocalAddr().(*net.UDPAddr).IP.To4(); ip4 != nil {
+		return ipv4.NewPacketConn(conn).SetControlMessage(ipv4.FlagDst|ipv4.FlagInterface, true)
+	}
+	return ipv6.NewPacketConn(conn).SetControlMessage(ipv6.FlagDst|ipv6.FlagInterface, true)
+}

+ 64 - 0
pkg/server/udp_server_test.go

@@ -0,0 +1,64 @@
+package server
+
+import (
+	"fmt"
+	"net"
+	"testing"
+	"time"
+)
+
+const (
+	testUDPHost = "127.0.0.1:5638"
+)
+
+type testUDPEchoHandler struct{}
+
+func (a testUDPEchoHandler) Handler(conn *net.UDPConn) {
+	buf := make([]byte, 1024)
+	for {
+		len, addr, err := conn.ReadFromUDP(buf)
+		if err != nil {
+			fmt.Println(err)
+			continue
+		}
+		strData := string(buf)
+		fmt.Println("Received:", strData)
+		len, err = conn.WriteToUDP(buf[:len], addr)
+		if err != nil {
+			fmt.Println(err)
+		}
+	}
+}
+func validateUDPServer(t *testing.T, addr string) {
+	cli, err := net.Dial("udp", testUDPHost)
+	if err != nil {
+		t.Fatal(err)
+	}
+	_, err = cli.Write([]byte(testEchoData))
+	if err != nil {
+		t.Fatal(err)
+	}
+	buf := make([]byte, 1024)
+	length, err := cli.Read(buf)
+	if err != nil {
+		t.Fatal(err)
+	}
+	gotData := string(buf[:length])
+	if gotData != testEchoData {
+		t.Errorf("echo server test failed. want: %s, got: %s", testEchoData, gotData)
+	}
+}
+func TestUDPServer(t *testing.T) {
+	initLog("test", "debug")
+	h := testUDPEchoHandler{}
+	svr := &UDPServer{
+		addr:    testUDPHost,
+		handler: h,
+	}
+	err := svr.Start()
+	if err != nil {
+		t.Fatal(err)
+	}
+	time.Sleep(time.Millisecond * 100)
+	validateUDPServer(t, testUDPHost)
+}

+ 106 - 96
pkg/tlv/tlv.go

@@ -8,35 +8,37 @@ import (
 	"io"
 )
 
+// 定义数据类型
 const (
-	TLV_FLOAT64 = 1
-	TLV_FLOAT32 = 2
-	TLV_INT8    = 3
-	TLV_INT16   = 4
-	TLV_INT32   = 5
-	TLV_INT64   = 6
-	TLV_UINT8   = 7
-	TLV_UINT16  = 8
-	TLV_UINT32  = 9
-	TLV_UINT64  = 10
-	TLV_BYTES   = 11
-	TLV_STRING  = 12
-	TLV_BOOL    = 13
+	TLVFLOAT64 = 1
+	TLVFLOAT32 = 2
+	TLVINT8    = 3
+	TLVINT16   = 4
+	TLVINT32   = 5
+	TLVINT64   = 6
+	TLVUINT8   = 7
+	TLVUINT16  = 8
+	TLVUINT32  = 9
+	TLVUINT64  = 10
+	TLVBYTES   = 11
+	TLVSTRING  = 12
+	TLVBOOL    = 13
 )
 
+// TLV type length value
 type TLV struct {
 	Tag   uint16
 	Value []byte
 }
 
-func Uint16ToByte(value uint16) []byte {
+func uint16ToByte(value uint16) []byte {
 	buf := bytes.NewBuffer([]byte{})
 	binary.Write(buf, binary.BigEndian, value)
 
 	return buf.Bytes()
 }
 
-func ByteToUint16(buf []byte) uint16 {
+func byteToUint16(buf []byte) uint16 {
 	tmpBuf := bytes.NewBuffer(buf)
 	var value uint16
 	binary.Read(tmpBuf, binary.BigEndian, &value)
@@ -44,6 +46,7 @@ func ByteToUint16(buf []byte) uint16 {
 	return value
 }
 
+// ToBinary make tlv to []byte
 func (tlv *TLV) ToBinary() []byte {
 	buf := new(bytes.Buffer)
 	binary.Write(buf, binary.BigEndian, &tlv.Tag)
@@ -52,34 +55,35 @@ func (tlv *TLV) ToBinary() []byte {
 	return buf.Bytes()
 }
 
+// Length get tlv length
 func (tlv *TLV) Length() int {
 	length := int(0)
 	switch tlv.Tag {
-	case TLV_FLOAT64:
+	case TLVFLOAT64:
 		length = 8
-	case TLV_INT64:
+	case TLVINT64:
 		length = 8
-	case TLV_UINT64:
+	case TLVUINT64:
 		length = 8
-	case TLV_FLOAT32:
+	case TLVFLOAT32:
 		length = 4
-	case TLV_INT32:
+	case TLVINT32:
 		length = 4
-	case TLV_UINT32:
+	case TLVUINT32:
 		length = 4
-	case TLV_INT16:
+	case TLVINT16:
 		length = 2
-	case TLV_UINT16:
+	case TLVUINT16:
 		length = 2
-	case TLV_INT8:
+	case TLVINT8:
 		length = 1
-	case TLV_UINT8:
+	case TLVUINT8:
 		length = 1
-	case TLV_BYTES:
-		length = int(ByteToUint16(tlv.Value[0:2]))
+	case TLVBYTES:
+		length = int(byteToUint16(tlv.Value[0:2]))
 		length += 2
-	case TLV_STRING:
-		length = int(ByteToUint16(tlv.Value[0:2]))
+	case TLVSTRING:
+		length = int(byteToUint16(tlv.Value[0:2]))
 		length += 2
 	default:
 		length = 0
@@ -90,124 +94,126 @@ func (tlv *TLV) Length() int {
 	return length
 }
 
+// FromBinary read from binary
 func (tlv *TLV) FromBinary(r io.Reader) error {
 	binary.Read(r, binary.BigEndian, &tlv.Tag)
 	length := uint16(0)
 	switch tlv.Tag {
-	case TLV_FLOAT64:
+	case TLVFLOAT64:
 		length = 8
 		tlv.Value = make([]byte, length)
 		binary.Read(r, binary.BigEndian, &tlv.Value)
-	case TLV_INT64:
+	case TLVINT64:
 		length = 8
 		tlv.Value = make([]byte, length)
 		binary.Read(r, binary.BigEndian, &tlv.Value)
-	case TLV_UINT64:
+	case TLVUINT64:
 		length = 8
 		tlv.Value = make([]byte, length)
 		binary.Read(r, binary.BigEndian, &tlv.Value)
-	case TLV_FLOAT32:
+	case TLVFLOAT32:
 		length = 4
 		tlv.Value = make([]byte, length)
 		binary.Read(r, binary.BigEndian, &tlv.Value)
-	case TLV_INT32:
+	case TLVINT32:
 		length = 4
 		tlv.Value = make([]byte, length)
 		binary.Read(r, binary.BigEndian, &tlv.Value)
-	case TLV_UINT32:
+	case TLVUINT32:
 		length = 4
 		tlv.Value = make([]byte, length)
 		binary.Read(r, binary.BigEndian, &tlv.Value)
-	case TLV_INT16:
+	case TLVINT16:
 		length = 2
 		tlv.Value = make([]byte, length)
 		binary.Read(r, binary.BigEndian, &tlv.Value)
-	case TLV_UINT16:
+	case TLVUINT16:
 		length = 2
 		tlv.Value = make([]byte, length)
 		binary.Read(r, binary.BigEndian, &tlv.Value)
-	case TLV_INT8:
+	case TLVINT8:
 		length = 1
 		tlv.Value = make([]byte, length)
 		binary.Read(r, binary.BigEndian, &tlv.Value)
-	case TLV_UINT8:
+	case TLVUINT8:
 		length = 1
 		tlv.Value = make([]byte, length)
 		binary.Read(r, binary.BigEndian, &tlv.Value)
-	case TLV_BYTES:
+	case TLVBYTES:
 		binary.Read(r, binary.BigEndian, &length)
 		tlv.Value = make([]byte, length+2)
-		copy(tlv.Value[0:2], Uint16ToByte(length))
+		copy(tlv.Value[0:2], uint16ToByte(length))
 		binary.Read(r, binary.BigEndian, tlv.Value[2:])
-	case TLV_STRING:
+	case TLVSTRING:
 		binary.Read(r, binary.BigEndian, &length)
 		tlv.Value = make([]byte, length+2)
-		copy(tlv.Value[0:2], Uint16ToByte(length))
+		copy(tlv.Value[0:2], uint16ToByte(length))
 		binary.Read(r, binary.BigEndian, tlv.Value[2:])
 	default:
-		return errors.New(fmt.Sprintf("unsuport value: %d", tlv.Tag))
+		return fmt.Errorf("unsuport value: %d", tlv.Tag)
 	}
 
 	return nil
 }
 
+// MakeTLV make a tlv pointer
 func MakeTLV(a interface{}) (*TLV, error) {
 	var tag uint16
 	var length uint16
 	buf := new(bytes.Buffer)
-	switch a.(type) {
+	switch a := a.(type) {
 	case float64:
-		tag = TLV_FLOAT64
+		tag = TLVFLOAT64
 		length = 8
-		binary.Write(buf, binary.BigEndian, a.(float64))
+		binary.Write(buf, binary.BigEndian, a)
 	case float32:
-		tag = TLV_FLOAT32
+		tag = TLVFLOAT32
 		length = 4
-		binary.Write(buf, binary.BigEndian, a.(float32))
+		binary.Write(buf, binary.BigEndian, a)
 	case int8:
-		tag = TLV_INT8
+		tag = TLVINT8
 		length = 1
-		binary.Write(buf, binary.BigEndian, a.(int8))
+		binary.Write(buf, binary.BigEndian, a)
 	case int16:
-		tag = TLV_INT16
+		tag = TLVINT16
 		length = 2
-		binary.Write(buf, binary.BigEndian, a.(int16))
+		binary.Write(buf, binary.BigEndian, a)
 	case int32:
-		tag = TLV_INT32
+		tag = TLVINT32
 		length = 4
-		binary.Write(buf, binary.BigEndian, a.(int32))
+		binary.Write(buf, binary.BigEndian, a)
 	case int64:
-		tag = TLV_INT64
+		tag = TLVINT64
 		length = 8
-		binary.Write(buf, binary.BigEndian, a.(int64))
+		binary.Write(buf, binary.BigEndian, a)
 	case uint8:
-		tag = TLV_UINT8
+		tag = TLVUINT8
 		length = 1
-		binary.Write(buf, binary.BigEndian, a.(uint8))
+		binary.Write(buf, binary.BigEndian, a)
 	case uint16:
-		tag = TLV_UINT16
+		tag = TLVUINT16
 		length = 2
-		binary.Write(buf, binary.BigEndian, a.(uint16))
+		binary.Write(buf, binary.BigEndian, a)
 	case uint32:
-		tag = TLV_UINT32
+		tag = TLVUINT32
 		length = 4
-		binary.Write(buf, binary.BigEndian, a.(uint32))
+		binary.Write(buf, binary.BigEndian, a)
 	case uint64:
-		tag = TLV_UINT64
+		tag = TLVUINT64
 		length = 8
-		binary.Write(buf, binary.BigEndian, a.(uint64))
+		binary.Write(buf, binary.BigEndian, a)
 	case []byte:
-		tag = TLV_BYTES
-		length = uint16(len(a.([]byte)))
+		tag = TLVBYTES
+		length = uint16(len(a))
 		binary.Write(buf, binary.BigEndian, length)
-		binary.Write(buf, binary.BigEndian, a.([]byte))
+		binary.Write(buf, binary.BigEndian, a)
 	case string:
-		tag = TLV_STRING
-		length = uint16(len(a.(string)))
+		tag = TLVSTRING
+		length = uint16(len(a))
 		binary.Write(buf, binary.BigEndian, length)
-		binary.Write(buf, binary.BigEndian, []byte(a.(string)))
+		binary.Write(buf, binary.BigEndian, []byte(a))
 	default:
-		return nil, errors.New(fmt.Sprintf("unsuport value: %v", a))
+		return nil, fmt.Errorf("unsuport value: %v", a)
 	}
 
 	tlv := TLV{
@@ -222,6 +228,7 @@ func MakeTLV(a interface{}) (*TLV, error) {
 	return &tlv, nil
 }
 
+// ReadTLV read from tlv pointer
 func ReadTLV(tlv *TLV) (interface{}, error) {
 	tag := tlv.Tag
 	length := uint16(0)
@@ -229,47 +236,47 @@ func ReadTLV(tlv *TLV) (interface{}, error) {
 
 	buffer := bytes.NewReader(value)
 	switch tag {
-	case TLV_FLOAT64:
+	case TLVFLOAT64:
 		retvar := float64(0.0)
 		err := binary.Read(buffer, binary.BigEndian, &retvar)
 		return retvar, err
-	case TLV_FLOAT32:
+	case TLVFLOAT32:
 		retvar := float32(0.0)
 		err := binary.Read(buffer, binary.BigEndian, &retvar)
 		return retvar, err
-	case TLV_INT8:
+	case TLVINT8:
 		retvar := int8(0)
 		err := binary.Read(buffer, binary.BigEndian, &retvar)
 		return retvar, err
-	case TLV_INT16:
+	case TLVINT16:
 		retvar := int16(0)
 		err := binary.Read(buffer, binary.BigEndian, &retvar)
 		return retvar, err
-	case TLV_INT32:
+	case TLVINT32:
 		retvar := int32(0)
 		err := binary.Read(buffer, binary.BigEndian, &retvar)
 		return retvar, err
-	case TLV_INT64:
+	case TLVINT64:
 		retvar := int64(0)
 		err := binary.Read(buffer, binary.BigEndian, &retvar)
 		return retvar, err
-	case TLV_UINT8:
+	case TLVUINT8:
 		retvar := uint8(0)
 		err := binary.Read(buffer, binary.BigEndian, &retvar)
 		return retvar, err
-	case TLV_UINT16:
+	case TLVUINT16:
 		retvar := uint16(0)
 		err := binary.Read(buffer, binary.BigEndian, &retvar)
 		return retvar, err
-	case TLV_UINT32:
+	case TLVUINT32:
 		retvar := uint32(0)
 		err := binary.Read(buffer, binary.BigEndian, &retvar)
 		return retvar, err
-	case TLV_UINT64:
+	case TLVUINT64:
 		retvar := uint64(0)
 		err := binary.Read(buffer, binary.BigEndian, &retvar)
 		return retvar, err
-	case TLV_BYTES:
+	case TLVBYTES:
 		err := binary.Read(buffer, binary.BigEndian, &length)
 		if err != nil {
 			return []byte{}, err
@@ -277,7 +284,7 @@ func ReadTLV(tlv *TLV) (interface{}, error) {
 		retvar := make([]byte, length)
 		err = binary.Read(buffer, binary.BigEndian, &retvar)
 		return retvar, err
-	case TLV_STRING:
+	case TLVSTRING:
 		err := binary.Read(buffer, binary.BigEndian, &length)
 		if err != nil {
 			return string([]byte{}), err
@@ -290,6 +297,7 @@ func ReadTLV(tlv *TLV) (interface{}, error) {
 	}
 }
 
+// MakeTLVs ``
 func MakeTLVs(a []interface{}) ([]TLV, error) {
 	tlvs := []TLV{}
 	for _, one := range a {
@@ -302,6 +310,7 @@ func MakeTLVs(a []interface{}) ([]TLV, error) {
 	return tlvs, nil
 }
 
+// ReadTLVs ``
 func ReadTLVs(tlvs []TLV) ([]interface{}, error) {
 	values := []interface{}{}
 	for _, tlv := range tlvs {
@@ -314,31 +323,32 @@ func ReadTLVs(tlvs []TLV) ([]interface{}, error) {
 	return values, nil
 }
 
+// CastTLV cast tlv
 func CastTLV(value interface{}, valueType int32) interface{} {
 	switch valueType {
-	case TLV_FLOAT64:
+	case TLVFLOAT64:
 		return float64(value.(float64))
-	case TLV_FLOAT32:
+	case TLVFLOAT32:
 		return float32(value.(float64))
-	case TLV_INT8:
+	case TLVINT8:
 		return int8(value.(float64))
-	case TLV_INT16:
+	case TLVINT16:
 		return int16(value.(float64))
-	case TLV_INT32:
+	case TLVINT32:
 		return int32(value.(float64))
-	case TLV_INT64:
+	case TLVINT64:
 		return int64(value.(float64))
-	case TLV_UINT8:
+	case TLVUINT8:
 		return uint8(value.(float64))
-	case TLV_UINT16:
+	case TLVUINT16:
 		return uint16(value.(float64))
-	case TLV_UINT32:
+	case TLVUINT32:
 		return uint32(value.(float64))
-	case TLV_UINT64:
+	case TLVUINT64:
 		return uint64(value.(float64))
-	case TLV_BYTES:
+	case TLVBYTES:
 		return []byte(value.(string))
-	case TLV_STRING:
+	case TLVSTRING:
 		return value.(string)
 	default:
 		return nil

+ 10 - 7
pkg/token/token_test.go

@@ -1,27 +1,30 @@
 package token
 
 import (
+	"encoding/hex"
 	"testing"
 )
 
 func TestTokenHelper(t *testing.T) {
-	helper := NewHelper("localhost:6379")
+	helper := NewHelper("192.168.175.60:6379")
 
-	testid := uint64(123)
+	testid := uint64(2)
 
 	token, err := helper.GenerateToken(testid)
 	if err != nil {
 		t.Error(err)
 	}
-
+	encodedStr := hex.EncodeToString(token)
+	de, _ := hex.DecodeString(encodedStr)
+	t.Log(encodedStr, de, token)
 	err = helper.ValidateToken(testid, token)
 	if err != nil {
 		t.Error(err)
 	}
 
-	err = helper.ClearToken(testid)
-	if err != nil {
-		t.Error(err)
-	}
+	// err = helper.ClearToken(testid)
+	// if err != nil {
+	// 	t.Error(err)
+	// }
 
 }

+ 27 - 0
pkg/tracing/tracer.go

@@ -0,0 +1,27 @@
+package tracing
+
+import (
+	"fmt"
+	"io"
+
+	opentracing "github.com/opentracing/opentracing-go"
+	jaeger "github.com/uber/jaeger-client-go"
+	config "github.com/uber/jaeger-client-go/config"
+)
+
+func Init(service string) (opentracing.Tracer, io.Closer) {
+	cfg := &config.Configuration{
+		Sampler: &config.SamplerConfig{
+			Type:  "const",
+			Param: 1,
+		},
+		Reporter: &config.ReporterConfig{
+			LogSpans: true,
+		},
+	}
+	tracer, closer, err := cfg.New(service, config.Logger(jaeger.StdLogger))
+	if err != nil {
+		panic(fmt.Sprintf("ERROR: cannot init Jaeger: %v\n", err))
+	}
+	return tracer, closer
+}

+ 2 - 1
run.sh

@@ -1,6 +1,6 @@
 export GOPATH=/Users/terrence/go
 
-sudo killall -9 httpaccess registry apiprovider devicemanager controller mqttaccess knowoapi fileaccess
+sudo killall -9 httpaccess registry apiprovider devicemanager controller mqttaccess knowoapi fileaccess coapaccess
 
 # start services
 #$GOPATH/bin/httpaccess -etcd http://localhost:2379 -httphost internal:443 -loglevel debug -usehttps -keyfile $GOPATH/src/github.com/PandoCloud/pando-cloud/pkg/server/testdata/key.pem -cafile $GOPATH/src/github.com/PandoCloud/pando-cloud/pkg/server/testdata/cert.pem &
@@ -13,6 +13,7 @@ $GOPATH/bin/controller -etcd http://192.168.175.60:2379 -loglevel debug  -rpchos
 $GOPATH/bin/mqttaccess -etcd http://192.168.175.60:2379 -loglevel debug  -rpchost localhost:20030 -tcphost internal:1883  &
 $GOPATH/bin/knowoapi -etcd http://192.168.175.60:2379 -loglevel debug  -httphost localhost:8889 -dbhost 192.168.175.60 -dbname SparrowCloud -dbport 3306 -dbuser SparrowCloud -dbpass 123456 -aeskey ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP &
 $GOPATH/bin/fileaccess -etcd http://192.168.175.60:2379 -loglevel debug  -rpchost localhost:20035 -httphost localhost:9000 &
+$GOPATH/bin/coapaccess -etcd http://192.168.175.60:2379 -loglevel debug  -udphost localhost:56883 &
 exit 0
 
 

+ 45 - 6
services/apiprovider/actions.go

@@ -1,11 +1,16 @@
 package main
 
 import (
+	"context"
 	"encoding/json"
 	"errors"
 	"sparrow/pkg/productconfig"
 	"sparrow/pkg/rpcs"
 
+	"github.com/opentracing/opentracing-go/ext"
+
+	"github.com/opentracing/opentracing-go"
+
 	"net/http"
 
 	"sparrow/pkg/models"
@@ -54,11 +59,16 @@ func done(result interface{}) Common {
 	}
 }
 
+// GetDeviceInfoByKey get device info with device key
 func GetDeviceInfoByKey(params martini.Params, req *http.Request, r render.Render) {
 	key := req.URL.Query().Get("device_key")
 	server.Log.Printf("ACTION GetDeviceInfoByKey, key:: %v", key)
 	device := &models.Device{}
-	err := server.RPCCallByName("registry", "Registry.ValidateDevice", key, device)
+	span, ctx := opentracing.StartSpanFromContext(context.Background(), "GetDeviceInfoByKey")
+	defer span.Finish()
+	ext.SpanKindRPCClient.Set(span)
+	span.SetTag("device_key", key)
+	err := server.RPCCallByName(ctx, "registry", "Registry.ValidateDevice", key, device)
 	if err != nil {
 		r.JSON(http.StatusOK, renderError(ErrDeviceNotFound, err))
 		return
@@ -76,11 +86,16 @@ func GetDeviceInfoByKey(params martini.Params, req *http.Request, r render.Rende
 	return
 }
 
+// GetDeviceInfoByIdentifier get device info with device identifier
 func GetDeviceInfoByIdentifier(urlparams martini.Params, r render.Render) {
 	identifier := urlparams["identifier"]
 	server.Log.Printf("ACTION GetDeviceInfoByIdentifier, identifier:: %v", identifier)
 	device := &models.Device{}
-	err := server.RPCCallByName("registry", "Registry.FindDeviceByIdentifier", identifier, device)
+	span, ctx := opentracing.StartSpanFromContext(context.Background(), "GetDeviceInfoByIdentifier")
+	defer span.Finish()
+	ext.SpanKindRPCClient.Set(span)
+	span.SetTag("identifier", identifier)
+	err := server.RPCCallByName(ctx, "registry", "Registry.FindDeviceByIdentifier", identifier, device)
 	if err != nil {
 		r.JSON(http.StatusOK, renderError(ErrDeviceNotFound, err))
 		return
@@ -106,7 +121,12 @@ func GetDeviceCurrentStatus(device *models.Device, config *productconfig.Product
 		Id: uint64(device.ID),
 	}
 	statusreply := rpcs.ReplyGetStatus{}
-	err := server.RPCCallByName("controller", "Controller.GetStatus", statusargs, &statusreply)
+	//opentracing
+	span, ctx := opentracing.StartSpanFromContext(context.Background(), "GetDeviceCurrentStatus")
+	defer span.Finish()
+	ext.SpanKindRPCClient.Set(span)
+
+	err := server.RPCCallByName(ctx, "controller", "Controller.GetStatus", statusargs, &statusreply)
 	if err != nil {
 		server.Log.Errorf("get devie status error: %v", err)
 		r.JSON(http.StatusOK, renderError(ErrSystemFault, err))
@@ -126,10 +146,12 @@ func GetDeviceCurrentStatus(device *models.Device, config *productconfig.Product
 	return
 }
 
+// GetDeviceLatestStatus get device latest status
 func GetDeviceLatestStatus() {
 
 }
 
+// SetDeviceStatus set device status
 func SetDeviceStatus(device *models.Device, config *productconfig.ProductConfig,
 	urlparams martini.Params, req *http.Request, r render.Render) {
 	server.Log.Printf("ACTION GetDeviceCurrentStatus, identifier:: %v,request: %v", device.DeviceIdentifier, req.Body)
@@ -159,7 +181,12 @@ func SetDeviceStatus(device *models.Device, config *productconfig.ProductConfig,
 		Status:   status,
 	}
 	statusreply := rpcs.ReplySetStatus{}
-	err = server.RPCCallByName("controller", "Controller.SetStatus", statusargs, &statusreply)
+	//opentracing
+	span, ctx := opentracing.StartSpanFromContext(context.Background(), "SetDeviceStatus")
+	defer span.Finish()
+	ext.SpanKindRPCClient.Set(span)
+
+	err = server.RPCCallByName(ctx, "controller", "Controller.SetStatus", statusargs, &statusreply)
 	if err != nil {
 		server.Log.Errorf("set devie status error: %v", err)
 		r.JSON(http.StatusOK, renderError(ErrSystemFault, err))
@@ -171,6 +198,7 @@ func SetDeviceStatus(device *models.Device, config *productconfig.ProductConfig,
 
 }
 
+// SendCommandToDevice send command to device
 func SendCommandToDevice(device *models.Device, config *productconfig.ProductConfig,
 	urlparams martini.Params, req *http.Request, r render.Render) {
 	timeout := req.URL.Query().Get("timeout")
@@ -206,7 +234,13 @@ func SendCommandToDevice(device *models.Device, config *productconfig.ProductCon
 		Params:    command.Params,
 	}
 	cmdreply := rpcs.ReplySendCommand{}
-	err = server.RPCCallByName("controller", "Controller.SendCommand", cmdargs, &cmdreply)
+
+	//opentracing
+	span, ctx := opentracing.StartSpanFromContext(context.Background(), "SendCommandToDevice")
+	defer span.Finish()
+	ext.SpanKindRPCClient.Set(span)
+
+	err = server.RPCCallByName(ctx, "controller", "Controller.SendCommand", cmdargs, &cmdreply)
 	if err != nil {
 		server.Log.Errorf("send devie command error: %v", err)
 		r.JSON(http.StatusOK, renderError(ErrSystemFault, err))
@@ -218,6 +252,7 @@ func SendCommandToDevice(device *models.Device, config *productconfig.ProductCon
 
 }
 
+// AddRule 增加设备规则
 func AddRule(device *models.Device, req *http.Request, r render.Render) {
 	var ruleReq CreateRuleRequest
 	decoder := json.NewDecoder(req.Body)
@@ -235,8 +270,12 @@ func AddRule(device *models.Device, req *http.Request, r render.Render) {
 		Action:   ruleReq.Action,
 	}
 	reply := &rpcs.ReplyEmptyResult{}
+	//opentracing
+	span, ctx := opentracing.StartSpanFromContext(context.Background(), "AddRule")
+	defer span.Finish()
+	ext.SpanKindRPCClient.Set(span)
 
-	err = server.RPCCallByName("registry", "Registry.CreateRule", rule, reply)
+	err = server.RPCCallByName(ctx, "registry", "Registry.CreateRule", rule, reply)
 	if err != nil {
 		server.Log.Errorf("create device rule error: %v", err)
 		r.JSON(http.StatusOK, renderError(ErrSystemFault, err))

+ 9 - 8
services/apiprovider/middleware.go

@@ -2,15 +2,16 @@ package main
 
 import (
 	"errors"
+	"net/http"
 	"sparrow/pkg/models"
 	"sparrow/pkg/productconfig"
 	"sparrow/pkg/rpcs"
 	"sparrow/pkg/server"
-	"github.com/go-martini/martini"
-	"github.com/martini-contrib/render"
-	"net/http"
 	"strconv"
 	"strings"
+
+	"github.com/go-martini/martini"
+	"github.com/martini-contrib/render"
 )
 
 func checkAppDomain(domain string, identifier string) error {
@@ -74,7 +75,7 @@ func ApplicationAuthOnDeviceIdentifer(context martini.Context, params martini.Pa
 	}
 
 	app := &models.Application{}
-	err := server.RPCCallByName("registry", "Registry.ValidateApplication", key, app)
+	err := server.RPCCallByName(nil, "registry", "Registry.ValidateApplication", key, app)
 	if err != nil {
 		r.JSON(http.StatusOK, renderError(ErrAccessDenied, err))
 		return
@@ -93,7 +94,7 @@ func CheckDeviceOnline(context martini.Context, params martini.Params, req *http
 	identifier := params["identifier"]
 
 	device := &models.Device{}
-	err := server.RPCCallByName("registry", "Registry.FindDeviceByIdentifier", identifier, device)
+	err := server.RPCCallByName(nil, "registry", "Registry.FindDeviceByIdentifier", identifier, device)
 	if err != nil {
 		r.JSON(http.StatusOK, renderError(ErrDeviceNotFound, err))
 		return
@@ -103,7 +104,7 @@ func CheckDeviceOnline(context martini.Context, params martini.Params, req *http
 		Id: uint64(device.ID),
 	}
 	onlinereply := rpcs.ReplyGetDeviceOnlineStatus{}
-	err = server.RPCCallByName("devicemanager", "DeviceManager.GetDeviceOnlineStatus", onlineargs, &onlinereply)
+	err = server.RPCCallByName(nil, "devicemanager", "DeviceManager.GetDeviceOnlineStatus", onlineargs, &onlinereply)
 	if err != nil {
 		server.Log.Errorf("get devie online status error: %v", err)
 		r.JSON(http.StatusOK, renderError(ErrDeviceNotOnline, err))
@@ -118,7 +119,7 @@ func CheckDeviceIdentifier(context martini.Context, params martini.Params, req *
 	identifier := params["identifier"]
 
 	device := &models.Device{}
-	err := server.RPCCallByName("registry", "Registry.FindDeviceByIdentifier", identifier, device)
+	err := server.RPCCallByName(nil, "registry", "Registry.FindDeviceByIdentifier", identifier, device)
 	if err != nil {
 		r.JSON(http.StatusOK, renderError(ErrDeviceNotFound, err))
 		return
@@ -131,7 +132,7 @@ func CheckDeviceIdentifier(context martini.Context, params martini.Params, req *
 func CheckProductConfig(context martini.Context, device *models.Device,
 	params martini.Params, req *http.Request, r render.Render) {
 	product := &models.Product{}
-	err := server.RPCCallByName("registry", "Registry.FindProduct", device.ProductID, product)
+	err := server.RPCCallByName(nil, "registry", "Registry.FindProduct", device.ProductID, product)
 	if err != nil {
 		r.JSON(http.StatusOK, renderError(ErrProductNotFound, err))
 		return

+ 3 - 3
services/apiprovider/notifier.go

@@ -64,7 +64,7 @@ func (n *Notifier) processStatus() error {
 func (n *Notifier) updateApplications() error {
 	for {
 
-		err := server.RPCCallByName("registry", "Registry.GetApplications", 0, &n.apps)
+		err := server.RPCCallByName(nil, "registry", "Registry.GetApplications", 0, &n.apps)
 		if err != nil {
 			server.Log.Errorf("get applications error : %v", err)
 		}
@@ -77,14 +77,14 @@ func (n *Notifier) reportEvent(event rpcs.ArgsOnEvent) error {
 	server.Log.Debugf("reporting event %v", event)
 
 	device := &models.Device{}
-	err := server.RPCCallByName("registry", "Registry.FindDeviceById", int64(event.DeviceId), device)
+	err := server.RPCCallByName(nil, "registry", "Registry.FindDeviceById", int64(event.DeviceId), device)
 	if err != nil {
 		server.Log.Errorf("find device error : %v", err)
 		return err
 	}
 
 	product := &models.Product{}
-	err = server.RPCCallByName("registry", "Registry.FindProduct", device.ProductID, product)
+	err = server.RPCCallByName(nil, "registry", "Registry.FindProduct", device.ProductID, product)
 	if err != nil {
 		server.Log.Errorf("find product error : %v", err)
 		return err

+ 17 - 0
services/coapaccess/access.go

@@ -0,0 +1,17 @@
+package main
+
+import (
+	"sparrow/pkg/coap"
+)
+
+type Access struct {
+	CoAPManager *coap.Manager
+}
+
+func NewAccess() (*Access, error) {
+	p := NewCoAPProvider()
+	mgr := coap.NewManager(p)
+	return &Access{
+		CoAPManager: mgr,
+	}, nil
+}

+ 69 - 0
services/coapaccess/coap_provider.go

@@ -0,0 +1,69 @@
+package main
+
+import (
+	"sparrow/pkg/protocol"
+	"sparrow/pkg/rpcs"
+	"sparrow/pkg/server"
+)
+
+type CoAPProvider struct {
+}
+
+func NewCoAPProvider() *CoAPProvider {
+	return &CoAPProvider{}
+}
+func (mp *CoAPProvider) ValidateDeviceToken(deviceid uint64, token []byte) error {
+	args := rpcs.ArgsValidateDeviceAccessToken{
+		Id:          deviceid,
+		AccessToken: token,
+	}
+	reply := rpcs.ReplyValidateDeviceAccessToken{}
+	err := server.RPCCallByName(nil, "devicemanager", "DeviceManager.ValidateDeviceAccessToken", args, &reply)
+	if err != nil {
+		server.Log.Errorf("validate device token error. deviceid : %v, token : %v, error: %v", deviceid, token, err)
+		return err
+	}
+	return nil
+}
+func (mp *CoAPProvider) OnDeviceOnline(args rpcs.ArgsGetOnline) error {
+	reply := rpcs.ReplyGetOnline{}
+	err := server.RPCCallByName(nil, "devicemanager", "DeviceManager.GetOnline", args, &reply)
+	if err != nil {
+		server.Log.Errorf("device online error. args: %v, error: %v", args, err)
+	}
+
+	return err
+}
+func (mp *CoAPProvider) OnDeviceOffline(deviceid uint64) error {
+	args := rpcs.ArgsGetOffline{
+		Id: deviceid,
+	}
+	reply := rpcs.ReplyGetOffline{}
+	err := server.RPCCallByName(nil, "devicemanager", "DeviceManager.GetOffline", args, &reply)
+	if err != nil {
+		server.Log.Errorf("device offline error. deviceid: %v, error: %v", deviceid, err)
+	}
+
+	return err
+}
+func (mp *CoAPProvider) OnDeviceHeartBeat(deviceid uint64) error {
+	args := rpcs.ArgsDeviceId{
+		Id: deviceid,
+	}
+	reply := rpcs.ReplyHeartBeat{}
+	err := server.RPCCallByName(nil, "devicemanager", "DeviceManager.HeartBeat", args, &reply)
+	if err != nil {
+		server.Log.Errorf("device heartbeat error. deviceid: %v, error: %v", deviceid, err)
+	}
+	return err
+}
+func (mp *CoAPProvider) OnDeviceMessage(deviceid uint64, msgtype string, message []byte) {
+	server.Log.Infof("device {%v} message {%v} : %x", deviceid, msgtype, message)
+	data := &protocol.Data{}
+	err := data.UnMarshal(message)
+	if err != nil {
+		server.Log.Errorf("unmarshal data error : %v", err)
+		return
+	}
+	server.Log.Debugf("data %#v", data.SubData)
+}

+ 28 - 0
services/coapaccess/main.go

@@ -0,0 +1,28 @@
+package main
+
+import (
+	"sparrow/pkg/server"
+)
+
+func main() {
+	err := server.Init("coapaccess")
+	if err != nil {
+		server.Log.Fatal(err)
+		return
+	}
+	a, err := NewAccess()
+	if err != nil {
+		server.Log.Fatal(err)
+		return
+	}
+	err = server.RegisterUDPHandler(a.CoAPManager)
+	if err != nil {
+		server.Log.Errorf("Register UDP service Error: %s", err)
+		return
+	}
+	// start to run
+	err = server.Run()
+	if err != nil {
+		server.Log.Fatal(err)
+	}
+}

+ 26 - 0
services/coapaccess/readme.md

@@ -0,0 +1,26 @@
+## CoAP协议与平台通讯协议对应关系
+
+* TKL:长度固定为**8**个字节
+* Token:承载平台通讯协议中的token,用于校验,校验不通过会返回__4.01__
+* Payload:承载平台通讯协议中的Payload
+
+
+### 状态上报
+
+* URIPath: `/s`
+* Code: `POST`
+* Type: `CON`
+* Payload:依据平台通讯协议打包的二进制内容.
+
+### 事件上报
+* URIPath: `/e`
+* Code: `POST`
+* Type: `CON`
+* Payload:依据平台通讯协议打包的二进制内容.
+
+### 命令下发监听(未实现)
+
+* URIPath: `/c`
+* Code: `GET`
+* Type: `NON`
+

+ 1 - 1
services/controller/controller.go

@@ -131,7 +131,7 @@ func getAccessRPCHost(deviceid uint64) (string, error) {
 		Id: deviceid,
 	}
 	reply := &rpcs.ReplyGetDeviceOnlineStatus{}
-	err := server.RPCCallByName("devicemanager", "DeviceManager.GetDeviceOnlineStatus", args, reply)
+	err := server.RPCCallByName(nil, "devicemanager", "DeviceManager.GetDeviceOnlineStatus", args, reply)
 	if err != nil {
 		return "", err
 	}

+ 23 - 2
services/httpaccess/actions.go

@@ -1,6 +1,7 @@
 package main
 
 import (
+	"context"
 	"encoding/hex"
 	"errors"
 	"math/rand"
@@ -10,6 +11,10 @@ import (
 	"sparrow/pkg/server"
 	"sparrow/pkg/token"
 
+	"github.com/opentracing/opentracing-go/ext"
+
+	"github.com/opentracing/opentracing-go"
+
 	"github.com/martini-contrib/render"
 )
 
@@ -47,6 +52,9 @@ type DeviceAuthArgs struct {
 // RegisterDevice 设备激活
 func RegisterDevice(args DeviceRegisterArgs, r render.Render) {
 	server.Log.Printf("ACTION RegisterDevice, args:: %v ", args)
+	span, ctx := opentracing.StartSpanFromContext(context.Background(), "RegisterDevice")
+	defer span.Finish()
+
 	rpcargs := &rpcs.ArgsDeviceRegister{
 		ProductKey:    args.ProductKey,
 		DeviceCode:    args.DeviceCode,
@@ -54,7 +62,8 @@ func RegisterDevice(args DeviceRegisterArgs, r render.Render) {
 		ModuleName:    args.ModuleName,
 	}
 	device := &models.Device{}
-	err := server.RPCCallByName("registry", "Registry.RegisterDevice", rpcargs, device)
+	ext.SpanKindRPCClient.Set(span)
+	err := server.RPCCallByName(ctx, "registry", "Registry.RegisterDevice", rpcargs, device)
 	if err != nil {
 		r.JSON(http.StatusOK, renderError(ErrSystemFault, err))
 		return
@@ -76,7 +85,17 @@ func RegisterDevice(args DeviceRegisterArgs, r render.Render) {
 func AuthDevice(args DeviceAuthArgs, r render.Render) {
 	server.Log.Printf("ACTION AuthDevice, args:: %v", args)
 	device := &models.Device{}
-	err := server.RPCCallByName("registry", "Registry.FindDeviceById", int64(args.DeviceId), device)
+
+	arg := &rpcs.ArgsDeviceAuth{
+		DeviceID: args.DeviceId,
+	}
+
+	span, ctx := opentracing.StartSpanFromContext(context.Background(), "AuthDevice")
+	defer span.Finish()
+
+	ext.SpanKindRPCClient.Set(span)
+
+	err := server.RPCCallByName(ctx, "registry", "Registry.FindDeviceById", arg, device)
 	if err != nil {
 		r.JSON(http.StatusOK, renderError(ErrDeviceNotFound, err))
 		return
@@ -101,6 +120,8 @@ func AuthDevice(args DeviceAuthArgs, r render.Render) {
 		hosts, err = server.GetServerHosts(args.Protocol+"access", "httphost")
 	case "mqtt":
 		hosts, err = server.GetServerHosts(args.Protocol+"access", "tcphost")
+	case "coap":
+		hosts, err = server.GetServerHosts(args.Protocol+"access", "udphost")
 	default:
 		err = errors.New("unsuported protocol: " + args.Protocol)
 	}

+ 12 - 3
services/knowoapi/controllers/application.go

@@ -1,12 +1,17 @@
 package controllers
 
 import (
+	"context"
 	"sparrow/pkg/models"
 	"sparrow/pkg/rpcs"
 	"sparrow/pkg/server"
 	"sparrow/services/knowoapi/services"
 	"strings"
 
+	"github.com/opentracing/opentracing-go/ext"
+
+	"github.com/opentracing/opentracing-go"
+
 	"github.com/kataras/iris"
 )
 
@@ -33,7 +38,11 @@ func (a *AppController) Post() {
 			Target: "application",
 		}
 		reply := &rpcs.ReplyMoveFile{}
-		err := server.RPCCallByName("fileaccess", "FileAccess.MoveFile", args, reply)
+		span, ctx := opentracing.StartSpanFromContext(context.Background(), a.Ctx.Path())
+		defer span.Finish()
+		ext.SpanKindRPCClient.Set(span)
+		ext.HTTPMethod.Set(span, a.Ctx.Method())
+		err := server.RPCCallByName(ctx, "fileaccess", "FileAccess.MoveFile", args, reply)
 		if err != nil {
 			server.Log.Error(err)
 			app.AppIcon = ""
@@ -117,7 +126,7 @@ func (a *AppController) Put() {
 			Target: "application",
 		}
 		reply := &rpcs.ReplyMoveFile{}
-		err := server.RPCCallByName("fileaccess", "FileAccess.MoveFile", args, reply)
+		err := server.RPCCallByName(nil, "fileaccess", "FileAccess.MoveFile", args, reply)
 		if err != nil {
 			server.Log.Error(err)
 			app.AppIcon = ""
@@ -131,7 +140,7 @@ func (a *AppController) Put() {
 			FileName: old.AppIcon,
 		}
 		reply := &rpcs.ReplyEmptyResult{}
-		server.RPCCallByName("fileaccess", "FileAccess.DeleteFile", arg, reply)
+		server.RPCCallByName(nil, "fileaccess", "FileAccess.DeleteFile", arg, reply)
 	}
 	result, err := a.Service.Update(app)
 	if err != nil {

+ 2 - 2
services/knowoapi/controllers/device.go

@@ -100,10 +100,10 @@ func (a *DeviceController) GetBannerdata() {
 		responseError(a.Ctx, ErrDatabase, err.Error())
 		return
 	}
-	if tact != 0 {
+	if tact != 0 && yact != 0 {
 		comparedWithYesterdayActive = (float64(tact) / float64(yact)) * 100
 	}
-	if tlive != 0 {
+	if tlive != 0 && ylive != 0 {
 		comparedWithYesterdayLive = (float64(tlive) / float64(ylive)) * 100
 		rateOfTodayLive = float64(tlive) / float64(totolact) * 100
 	}

+ 11 - 3
services/knowoapi/controllers/product.go

@@ -1,6 +1,7 @@
 package controllers
 
 import (
+	"context"
 	"sparrow/pkg/models"
 	"sparrow/pkg/rpcs"
 	"sparrow/pkg/server"
@@ -8,6 +9,8 @@ import (
 	"strings"
 
 	"github.com/kataras/iris"
+	opentracing "github.com/opentracing/opentracing-go"
+	"github.com/opentracing/opentracing-go/ext"
 )
 
 // ProductController 产品API
@@ -34,7 +37,12 @@ func (a *ProductController) Post() {
 			Target: "product",
 		}
 		reply := &rpcs.ReplyMoveFile{}
-		err := server.RPCCallByName("fileaccess", "FileAccess.MoveFile", args, reply)
+
+		span, ctx := opentracing.StartSpanFromContext(context.Background(), a.Ctx.Path())
+		defer span.Finish()
+		ext.SpanKindRPCClient.Set(span)
+		ext.HTTPMethod.Set(span, a.Ctx.Method())
+		err := server.RPCCallByName(ctx, "fileaccess", "FileAccess.MoveFile", args, reply)
 		if err != nil {
 			server.Log.Error(err)
 			product.ProductImage = ""
@@ -88,7 +96,7 @@ func (a *ProductController) Put() {
 			Target: "product",
 		}
 		reply := &rpcs.ReplyMoveFile{}
-		err := server.RPCCallByName("fileaccess", "FileAccess.MoveFile", args, reply)
+		err := server.RPCCallByName(nil, "fileaccess", "FileAccess.MoveFile", args, reply)
 		if err != nil {
 			server.Log.Error(err)
 			product.ProductImage = ""
@@ -103,7 +111,7 @@ func (a *ProductController) Put() {
 			FileName: old.ProductImage,
 		}
 		reply := &rpcs.ReplyEmptyResult{}
-		server.RPCCallByName("fileaccess", "FileAccess.DeleteFile", arg, reply)
+		server.RPCCallByName(nil, "fileaccess", "FileAccess.DeleteFile", arg, reply)
 	}
 	pro, err := a.Service.Update(product)
 	if err != nil {

+ 1 - 0
services/knowoapi/model/role.go

@@ -29,6 +29,7 @@ func (a *Role) Update(role *models.Role) error {
 
 // Delete delete
 func (a *Role) Delete(role *models.Role) error {
+	a.db.Model(&models.User{}).Where("user_role_id = ?", role.ID).Update(map[string]interface{}{"user_role_id": 1})
 	return a.db.Delete(role).Error
 }
 

+ 1 - 1
services/knowoapi/model/role_test.go

@@ -40,7 +40,7 @@ func TestRoleDelete(t *testing.T) {
 		RoleName: "管理员修改",
 		MenuList: "home",
 	}
-	data.ID = 1
+	data.ID = 2
 	err := role.Delete(data)
 	if err != nil {
 		t.Fatal(err)

+ 11 - 1
services/knowoapi/router.go

@@ -6,6 +6,8 @@ import (
 	"sparrow/services/knowoapi/model"
 	"sparrow/services/knowoapi/services"
 
+	"github.com/opentracing/opentracing-go"
+
 	jwt "github.com/dgrijalva/jwt-go"
 	jwtmiddleware "github.com/iris-contrib/middleware/jwt"
 	"github.com/kataras/iris"
@@ -50,7 +52,15 @@ func registerRouters(srv *iris.Application, models *model.All, gen *generator.Ke
 	alertService := services.NewAlertService(models)
 	deviceService := services.NewDeviceService(models)
 	roleService := services.NewRoleService(models)
-	v1router := srv.Party("/api/v1")
+	v1router := srv.Party("/api/v1", func(ctx iris.Context) {
+		span := opentracing.StartSpan(ctx.Path())
+		defer span.Finish()
+		span.SetTag("http.method", ctx.Method())
+		span.SetTag("http.url", ctx.Path())
+		span.SetTag("http.status_code", ctx.GetStatusCode())
+		ctx.Values().Set("span", span)
+		ctx.Next()
+	})
 
 	// 登陆,注册
 	loginAPI := mvc.New(v1router.Party("/"))

+ 1 - 3
services/knowoapi/services/user.go

@@ -4,7 +4,6 @@ import (
 	"encoding/base64"
 	"sparrow/pkg/generator"
 	"sparrow/pkg/models"
-	"sparrow/pkg/server"
 	"sparrow/pkg/utils"
 	"sparrow/services/knowoapi/model"
 )
@@ -52,6 +51,7 @@ func (a userservice) Register(user *models.Reqrequest) (*models.User, error) {
 	_u.UserName = user.UserName
 	_u.Phone = user.Phone
 	_u.Email = user.Email
+	_u.UserRoleID = 1 //默认普通用户
 	vedor := &models.Vendor{
 		VendorName: user.VendorName,
 	}
@@ -66,10 +66,8 @@ func (a userservice) Register(user *models.Reqrequest) (*models.User, error) {
 func (a userservice) ModifyPassword(userid uint, new, old string) (bool, error) {
 	obytes, _ := base64.StdEncoding.DecodeString(old)
 	nbytes, _ := base64.StdEncoding.DecodeString(new)
-	server.Log.Debugf("旧密码:%s, 新密码:%s")
 	old = utils.Md5(string(obytes) + model.SignedString)
 	new = utils.Md5(string(nbytes) + model.SignedString)
-	server.Log.Debugf("旧密码:%s, 新密码:%s, 旧加密:%s,新加密:%s", string(obytes), string(nbytes), old, new)
 	return a.model.User.UpdatePassword(userid, new, old)
 }
 

+ 6 - 6
services/mqttaccess/mqtt_provider.go

@@ -18,7 +18,7 @@ func (mp *MQTTProvider) ValidateDeviceToken(deviceid uint64, token []byte) error
 		AccessToken: token,
 	}
 	reply := rpcs.ReplyValidateDeviceAccessToken{}
-	err := server.RPCCallByName("devicemanager", "DeviceManager.ValidateDeviceAccessToken", args, &reply)
+	err := server.RPCCallByName(nil, "devicemanager", "DeviceManager.ValidateDeviceAccessToken", args, &reply)
 	if err != nil {
 		server.Log.Errorf("validate device token error. deviceid : %v, token : %v, error: %v", deviceid, token, err)
 		return err
@@ -27,7 +27,7 @@ func (mp *MQTTProvider) ValidateDeviceToken(deviceid uint64, token []byte) error
 }
 func (mp *MQTTProvider) OnDeviceOnline(args rpcs.ArgsGetOnline) error {
 	reply := rpcs.ReplyGetOnline{}
-	err := server.RPCCallByName("devicemanager", "DeviceManager.GetOnline", args, &reply)
+	err := server.RPCCallByName(nil, "devicemanager", "DeviceManager.GetOnline", args, &reply)
 	if err != nil {
 		server.Log.Errorf("device online error. args: %v, error: %v", args, err)
 	}
@@ -39,7 +39,7 @@ func (mp *MQTTProvider) OnDeviceOffline(deviceid uint64) error {
 		Id: deviceid,
 	}
 	reply := rpcs.ReplyGetOffline{}
-	err := server.RPCCallByName("devicemanager", "DeviceManager.GetOffline", args, &reply)
+	err := server.RPCCallByName(nil, "devicemanager", "DeviceManager.GetOffline", args, &reply)
 	if err != nil {
 		server.Log.Errorf("device offline error. deviceid: %v, error: %v", deviceid, err)
 	}
@@ -51,7 +51,7 @@ func (mp *MQTTProvider) OnDeviceHeartBeat(deviceid uint64) error {
 		Id: deviceid,
 	}
 	reply := rpcs.ReplyHeartBeat{}
-	err := server.RPCCallByName("devicemanager", "DeviceManager.HeartBeat", args, &reply)
+	err := server.RPCCallByName(nil, "devicemanager", "DeviceManager.HeartBeat", args, &reply)
 	if err != nil {
 		server.Log.Errorf("device heartbeat error. deviceid: %v, error: %v", deviceid, err)
 	}
@@ -82,7 +82,7 @@ func (mp *MQTTProvider) OnDeviceMessage(deviceid uint64, msgtype string, message
 			Timestamp: data.Head.Timestamp,
 			Subdata:   data.SubData,
 		}
-		err = server.RPCCallByName("controller", "Controller.OnStatus", args, &reply)
+		err = server.RPCCallByName(nil, "controller", "Controller.OnStatus", args, &reply)
 		if err != nil {
 			server.Log.Errorf("device report status error. args: %v, error: %v", args, err)
 			return
@@ -104,7 +104,7 @@ func (mp *MQTTProvider) OnDeviceMessage(deviceid uint64, msgtype string, message
 			Priority:  event.Head.Priority,
 			Params:    event.Params,
 		}
-		err = server.RPCCallByName("controller", "Controller.OnEvent", args, &reply)
+		err = server.RPCCallByName(nil, "controller", "Controller.OnEvent", args, &reply)
 		if err != nil {
 			server.Log.Errorf("device on event error. args: %v, error: %v", args, err)
 			return

+ 2 - 2
services/registry/product.go

@@ -91,7 +91,7 @@ func (r *Registry) FindProduct(id int32, reply *models.Product) error {
 	return nil
 }
 
-// ValidProduct try to validate the given product key.
+// ValidateProduct try to validate the given product key.
 // if success, it will reply the corresponding product
 func (r *Registry) ValidateProduct(key string, reply *models.Product) error {
 	db, err := getDB()
@@ -99,7 +99,7 @@ func (r *Registry) ValidateProduct(key string, reply *models.Product) error {
 		return err
 	}
 
-	id, err := r.keygen.DecodeIdFromRandomKey(key)
+	id, err := r.keygen.DecodeIDFromRandomKey(key)
 	server.Log.Debug(id)
 	if err != nil {
 		return err

+ 10 - 8
services/registry/registry.go

@@ -163,7 +163,7 @@ func (r *Registry) ValidateApplication(key string, reply *models.Application) er
 		return err
 	}
 
-	id, err := r.keygen.DecodeIdFromRandomKey(key)
+	id, err := r.keygen.DecodeIDFromRandomKey(key)
 	if err != nil {
 		return err
 	}
@@ -264,6 +264,7 @@ func (r *Registry) FindApplication(id int32, reply *models.Application) error {
 // if the device has already been registered,
 // the registration will success return the registered device before.
 func (r *Registry) RegisterDevice(args *rpcs.ArgsDeviceRegister, reply *models.Device) error {
+
 	db, err := getDB()
 	if err != nil {
 		return err
@@ -319,9 +320,7 @@ func (r *Registry) RegisterDevice(args *rpcs.ArgsDeviceRegister, reply *models.D
 		if err != nil {
 			return err
 		}
-
 	}
-
 	return nil
 }
 
@@ -353,13 +352,14 @@ func (r *Registry) FindDeviceByIdentifier(identifier string, reply *models.Devic
 }
 
 // FindDeviceById will find the device with given id
-func (r *Registry) FindDeviceById(id int64, reply *models.Device) error {
+func (r *Registry) FindDeviceById(args *rpcs.ArgsDeviceAuth, reply *models.Device) error {
+
 	db, err := getDB()
 	if err != nil {
 		return err
 	}
 	d := &models.Device{}
-	d.ID = uint(id)
+	d.ID = uint(args.DeviceID)
 	err = db.Where(d).First(reply).Error
 
 	if err != nil {
@@ -370,12 +370,14 @@ func (r *Registry) FindDeviceById(id int64, reply *models.Device) error {
 
 // ValidateDevice will validate a device key and return the model if success.
 func (r *Registry) ValidateDevice(key string, device *models.Device) error {
-	id, err := r.keygen.DecodeIdFromRandomKey(key)
+	id, err := r.keygen.DecodeIDFromRandomKey(key)
 	if err != nil {
 		return err
 	}
-
-	err = r.FindDeviceById(id, device)
+	args := rpcs.ArgsDeviceAuth{
+		DeviceID: id,
+	}
+	err = r.FindDeviceById(&args, device)
 	if err != nil {
 		return err
 	}

+ 96 - 0
tests/coaptool/main.go

@@ -0,0 +1,96 @@
+package main
+
+import (
+	"encoding/hex"
+	"fmt"
+	"net"
+	"os"
+	"sparrow/pkg/coap"
+	"sparrow/pkg/protocol"
+	"sparrow/pkg/tlv"
+	"time"
+)
+
+const url = "127.0.0.1:56883"
+
+func main() {
+	addr, err := net.ResolveUDPAddr("udp", url)
+	if err != nil {
+		fmt.Println("Can't resolve address: ", err)
+		os.Exit(1)
+	}
+	conn, err := net.DialUDP("udp", nil, addr)
+	if err != nil {
+		fmt.Println("Can't dial: ", err)
+		os.Exit(1)
+	}
+	defer conn.Close()
+	token, _ := hex.DecodeString("e30680acf77ecd60")
+	payloadHead := protocol.DataHead{
+		Flag:      0,
+		Timestamp: uint64(time.Now().Unix() * 1000),
+	}
+	param1 := []interface{}{uint32(3), float32(1.2), int64(10)}
+	params1, err := tlv.MakeTLVs(param1)
+	if err != nil {
+		fmt.Println(err)
+	}
+	sub1 := protocol.SubData{
+		Head: protocol.SubDataHead{
+			SubDeviceid: uint16(1),
+			PropertyNum: uint16(1),
+			ParamsCount: uint16(len(params1)),
+		},
+		Params: params1,
+	}
+	param2 := []interface{}{uint32(4), int64(11)}
+	params2, err := tlv.MakeTLVs(param2)
+	if err != nil {
+		fmt.Println(err)
+	}
+	sub2 := protocol.SubData{
+		Head: protocol.SubDataHead{
+			SubDeviceid: uint16(1),
+			PropertyNum: uint16(2),
+			ParamsCount: uint16(len(params2)),
+		},
+		Params: params2,
+	}
+
+	payload := &protocol.Data{
+		Head:    payloadHead,
+		SubData: []protocol.SubData{},
+	}
+	payload.SubData = append(payload.SubData, sub1)
+	payload.SubData = append(payload.SubData, sub2)
+
+	buf, err := payload.Marshal()
+	if err != nil {
+		if err != nil {
+			fmt.Println(err)
+		}
+	}
+	req := &coap.BaseMessage{
+		Code:      coap.POST,
+		Type:      coap.CON,
+		MessageID: 2,
+		//Token:     []byte{0, 1, 0x2, 3, 4, 5, 6, 7, 8, 9, 1, 12, 12, 1, 2, 1, 2, 2},
+		Token:   token,
+		Payload: buf,
+	}
+	req.SetPathString("/2")
+	bytes, err := req.Encode()
+	if err != nil {
+		fmt.Printf("dial err %s", err.Error())
+	}
+	conn.Write(bytes)
+	msg := make([]byte, 20)
+
+	_, err = conn.Read(msg)
+	if err != nil {
+		fmt.Println(err)
+	}
+
+	fmt.Printf("Response:%#v", msg)
+
+}

二进制
tests/device/device


+ 103 - 18
tests/device/device.go

@@ -5,7 +5,9 @@ import (
 	"encoding/json"
 	"fmt"
 	"log"
+	"net"
 	"os"
+	"sparrow/pkg/coap"
 	"sparrow/pkg/protocol"
 	"sparrow/pkg/tlv"
 	"time"
@@ -17,27 +19,27 @@ const (
 	commonCmdGetStatus = uint16(65528)
 )
 
-// device register args
+// DeviceRegisterArgs device register args
 type DeviceRegisterArgs struct {
 	ProductKey string `json:"product_key"  binding:"required"`
 	DeviceCode string `json:"device_code"  binding:"required"`
 	Version    string `json:"version"  binding:"required"`
 }
 
-// device authentication args
+// DeviceAuthArgs device authentication args
 type DeviceAuthArgs struct {
 	DeviceId     int64  `json:"device_id" binding:"required"`
 	DeviceSecret string `json:"device_secret" binding:"required"`
 	Protocol     string `json:"protocol" binding:"required"`
 }
 
-// common response fields
+// Common common response fields
 type Common struct {
 	Code    int    `json:"code"`
 	Message string `json:"message"`
 }
 
-// device register response data field
+// DeviceRegisterData device register response data field
 type DeviceRegisterData struct {
 	DeviceId         int64  `json:"device_id"`
 	DeviceSecret     string `json:"device_secret"`
@@ -45,32 +47,34 @@ type DeviceRegisterData struct {
 	DeviceIdentifier string `json:"device_identifier"`
 }
 
-// device register response
+// DeviceRegisterResponse device register response
 type DeviceRegisterResponse struct {
 	Common
 	Data DeviceRegisterData `json:"data"`
 }
 
-// device auth response data field
+// DeviceAuthData device auth response data field
 type DeviceAuthData struct {
 	AccessToken string `json:"access_token"`
 	AccessAddr  string `json:"access_addr"`
 }
 
-// device auth response
+// DeviceAuthResponse device auth response
 type DeviceAuthResponse struct {
 	Common
 	Data DeviceAuthData `json:"data"`
 }
 
+// Device a device
 type Device struct {
-	// API URL
+	// Url API URL
 	Url string
 
 	// basic info
 	ProductKey string
 	DeviceCode string
 	Version    string
+	Proto      string
 
 	// private things
 	id      int64
@@ -79,28 +83,31 @@ type Device struct {
 	access  string
 }
 
-func NewDevice(url string, productkey string, code string, version string) *Device {
+// NewDevice create a device
+func NewDevice(url string, productkey string, code string, version string, proto string) *Device {
 
 	return &Device{
 		Url:        url,
 		ProductKey: productkey,
 		DeviceCode: code,
 		Version:    version,
+		Proto:      proto,
 	}
 }
 
+// DoRegister device register
 func (d *Device) DoRegister() error {
 	args := DeviceRegisterArgs{
 		ProductKey: d.ProductKey,
 		DeviceCode: d.DeviceCode,
 		Version:    d.Version,
 	}
-	regUrl := fmt.Sprintf("%v%v", d.Url, "/v1/devices/registration")
+	regURL := fmt.Sprintf("%v%v", d.Url, "/v1/devices/registration")
 	request, err := json.Marshal(args)
 	if err != nil {
 		return err
 	}
-	jsonresp, err := SendHttpRequest(regUrl, string(request), "POST", nil)
+	jsonresp, err := SendHttpRequest(regURL, string(request), "POST", nil)
 	if err != nil {
 		return err
 	}
@@ -120,18 +127,19 @@ func (d *Device) DoRegister() error {
 	return nil
 }
 
+// DoLogin device log in
 func (d *Device) DoLogin() error {
 	args := DeviceAuthArgs{
 		DeviceId:     d.id,
 		DeviceSecret: d.secrect,
-		Protocol:     "mqtt",
+		Protocol:     d.Proto,
 	}
-	regUrl := fmt.Sprintf("%v%v", d.Url, "/v1/devices/authentication")
+	regURL := fmt.Sprintf("%v%v", d.Url, "/v1/devices/authentication")
 	request, err := json.Marshal(args)
 	if err != nil {
 		return err
 	}
-	jsonresp, err := SendHttpRequest(regUrl, string(request), "POST", nil)
+	jsonresp, err := SendHttpRequest(regURL, string(request), "POST", nil)
 	if err != nil {
 		return err
 	}
@@ -163,7 +171,7 @@ func (d *Device) reportStatus(client *MQTT.Client) {
 			Flag:      0,
 			Timestamp: uint64(time.Now().Unix() * 1000),
 		}
-		param := []interface{}{"li jian"}
+		param := []interface{}{1}
 		params, err := tlv.MakeTLVs(param)
 		if err != nil {
 			fmt.Println(err)
@@ -196,6 +204,56 @@ func (d *Device) reportStatus(client *MQTT.Client) {
 
 }
 
+func (d *Device) coapReportStatus(conn *net.UDPConn) {
+	fmt.Println("coapReportStatus")
+	for {
+		payloadHead := protocol.DataHead{
+			Flag:      0,
+			Timestamp: uint64(time.Now().Unix() * 1000),
+		}
+		param := []interface{}{int64(10)}
+		params, err := tlv.MakeTLVs(param)
+		if err != nil {
+			fmt.Println(err)
+			return
+		}
+		sub := protocol.SubData{
+			Head: protocol.SubDataHead{
+				SubDeviceid: uint16(1),
+				PropertyNum: uint16(1),
+				ParamsCount: uint16(len(params)),
+			},
+			Params: params,
+		}
+
+		status := protocol.Data{
+			Head:    payloadHead,
+			SubData: []protocol.SubData{},
+		}
+
+		status.SubData = append(status.SubData, sub)
+
+		payload, err := status.Marshal()
+		if err != nil {
+			fmt.Println(err)
+			return
+		}
+
+		req := &coap.BaseMessage{
+			Code:      coap.POST,
+			Type:      coap.CON,
+			Token:     d.token,
+			MessageID: 2,
+			Payload:   payload,
+		}
+		req.SetPathString(fmt.Sprintf("%d/s", d.id))
+		reqbytes, _ := req.Encode()
+		conn.Write(reqbytes)
+		fmt.Println("write end")
+		time.Sleep(10 * time.Second)
+	}
+}
+
 func (d *Device) reportEvent(client *MQTT.Client) {
 	for {
 		time.Sleep(3 * time.Second)
@@ -275,7 +333,37 @@ func (d *Device) messageHandler(client *MQTT.Client, msg MQTT.Message) {
 	}
 }
 
+// DoAccess device access
 func (d *Device) DoAccess() error {
+	if d.Proto == "mqtt" {
+		if err := d.doMQTTAccess(); err != nil {
+			fmt.Printf("do mqtt access error:%s", err.Error())
+		}
+	} else if d.Proto == "coap" {
+		if err := d.doCoAPAccess(); err != nil {
+			fmt.Printf("do coap access error:%s", err.Error())
+		}
+	}
+	return nil
+}
+
+func (d *Device) doCoAPAccess() error {
+	fmt.Printf("get access addr :%s", d.access)
+	addr, err := net.ResolveUDPAddr("udp", d.access)
+	if err != nil {
+		return err
+	}
+	conn, err := net.DialUDP("udp", nil, addr)
+	if err != nil {
+		return err
+	}
+	go d.coapReportStatus(conn)
+	<-make(chan int)
+	defer conn.Close()
+	return nil
+}
+
+func (d *Device) doMQTTAccess() error {
 	logger := log.New(os.Stdout, "", log.LstdFlags)
 	MQTT.ERROR = logger
 	MQTT.CRITICAL = logger
@@ -298,9 +386,6 @@ func (d *Device) DoAccess() error {
 	if token := c.Connect(); token.Wait() && token.Error() != nil {
 		return token.Error()
 	}
-
-	// beigin report event test
-	//go d.reportEvent(c)
 	go d.reportStatus(c)
 	// we just pause here to wait for messages
 	<-make(chan int)

+ 8 - 7
tests/device/main.go

@@ -6,35 +6,36 @@ import (
 )
 
 var (
-	TestUrl        = flag.String("url", "http://192.168.175.60:8088", "login url")
-	TestProductKey = flag.String("productkey", "99b11b395c84435202692e36dada175c7af9452038a62a40b230b5e18b7d51ff", "product key")
+	testURL        = flag.String("url", "http://192.168.175.60:8088", "login url")
+	testProductKey = flag.String("productkey", "99b11b395c84435202692e36dada175c7af9452038a62a40b230b5e18b7d51ff", "product key")
+	testProtocol   = flag.String("protocol", "mqtt", "access protocol")
 )
 
 func main() {
 	flag.Parse()
 
-	if *TestProductKey == "" {
+	if *testProductKey == "" {
 		fmt.Println("product key not provided. use -productkey flag")
 		return
 	}
 
-	dev := NewDevice(*TestUrl, *TestProductKey, "ffe34e", "version")
+	dev := NewDevice(*testURL, *testProductKey, "ffe34e", "version", *testProtocol)
 
 	err := dev.DoRegister()
 	if err != nil {
-		fmt.Errorf("device register error %s", err)
+		fmt.Printf("device register error %s", err)
 		return
 	}
 
 	err = dev.DoLogin()
 	if err != nil {
-		fmt.Errorf("device login error %s", err)
+		fmt.Printf("device login error %s", err)
 		return
 	}
 
 	err = dev.DoAccess()
 	if err != nil {
-		fmt.Errorf("device access error %s", err)
+		fmt.Printf("device access error %s", err)
 		return
 	}
 

+ 1 - 1
tools/pdcfg/application.go

@@ -54,7 +54,7 @@ func addApplication() error {
 
 	reply := &models.Application{}
 
-	err = server.RPCCallByName("registry", "Registry.SaveApplication", &args, reply)
+	err = server.RPCCallByName(nil, "registry", "Registry.SaveApplication", &args, reply)
 	if err != nil {
 		return err
 	}

+ 1 - 1
tools/pdcfg/product.go

@@ -66,7 +66,7 @@ func addProduct() error {
 
 	reply := &models.Product{}
 
-	err = server.RPCCallByName("registry", "Registry.SaveProduct", &args, reply)
+	err = server.RPCCallByName(nil, "registry", "Registry.SaveProduct", &args, reply)
 	if err != nil {
 		return err
 	}

+ 1 - 1
tools/pdcfg/vendor.go

@@ -31,7 +31,7 @@ func addVendor() error {
 
 	reply := &models.Vendor{}
 
-	err = server.RPCCallByName("registry", "Registry.SaveVendor", &args, reply)
+	err = server.RPCCallByName(nil, "registry", "Registry.SaveVendor", &args, reply)
 	if err != nil {
 		return err
 	}

+ 14 - 0
vendor/github.com/opentracing/opentracing-go/CHANGELOG.md

@@ -0,0 +1,14 @@
+Changes by Version
+==================
+
+1.1.0 (unreleased)
+-------------------
+
+- Deprecate InitGlobalTracer() in favor of SetGlobalTracer()
+
+
+1.0.0 (2016-09-26)
+-------------------
+
+- This release implements OpenTracing Specification 1.0 (http://opentracing.io/spec)
+

+ 201 - 0
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.

+ 20 - 0
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 ./...

+ 171 - 0
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](http://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).

+ 210 - 0
vendor/github.com/opentracing/opentracing-go/ext/tags.go

@@ -0,0 +1,210 @@
+package ext
+
+import opentracing "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)
+}

+ 42 - 0
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
+}

+ 54 - 0
vendor/github.com/opentracing/opentracing-go/gocontext.go

@@ -0,0 +1,54 @@
+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 is factored out for testing purposes.
+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)
+}

+ 269 - 0
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())
+}

+ 54 - 0
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
+}

+ 64 - 0
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
+}

+ 176 - 0
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
+}

+ 189 - 0
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
+}

+ 305 - 0
vendor/github.com/opentracing/opentracing-go/tracer.go

@@ -0,0 +1,305 @@
+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/golang.org/x/net/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)
+}

+ 23 - 0
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.

+ 52 - 0
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

+ 32 - 0
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

+ 269 - 0
vendor/github.com/pkg/errors/errors.go

@@ -0,0 +1,269 @@
+// Package errors provides simple error handling primitives.
+//
+// The traditional error handling idiom in Go is roughly akin to
+//
+//     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 by recording a stack trace at the point Wrap is called,
+// and 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 of annotating
+// an error with a stack trace and an 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 which 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
+//     }
+//
+// causer interface is not exported by this package, but is considered a part
+// of stable public API.
+//
+// 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
+//     }
+//
+// Where errors.StackTrace 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)
+//             }
+//     }
+//
+// stackTracer interface is not exported by this package, but is considered a part
+// of stable public API.
+//
+// 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 call, 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,
+	}
+}
+
+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
+}

+ 147 - 0
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:]
+}

+ 197 - 0
vendor/github.com/uber/jaeger-client-go/CHANGELOG.md

@@ -0,0 +1,197 @@
+Changes by Version
+==================
+
+2.15.1 (unreleased)
+-------------------
+
+- nothing yet
+
+
+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"

+ 170 - 0
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 [glide](https://github.com/Masterminds/glide) 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
+```
+
+Then install dependencies and run the tests:
+
+```
+git submodule update --init --recursive
+glide 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"
+```

+ 37 - 0
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.
+

+ 164 - 0
vendor/github.com/uber/jaeger-client-go/Gopkg.lock

@@ -0,0 +1,164 @@
+# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
+
+
+[[projects]]
+  branch = "master"
+  name = "github.com/beorn7/perks"
+  packages = ["quantile"]
+  revision = "3a771d992973f24aa725d07868b467d1ddfceafb"
+
+[[projects]]
+  branch = "master"
+  name = "github.com/codahale/hdrhistogram"
+  packages = ["."]
+  revision = "3a0bb77429bd3a61596f5e8a3172445844342120"
+
+[[projects]]
+  branch = "master"
+  name = "github.com/crossdock/crossdock-go"
+  packages = [
+    ".",
+    "assert",
+    "require"
+  ]
+  revision = "049aabb0122b03bc9bd30cab8f3f91fb60166361"
+
+[[projects]]
+  name = "github.com/davecgh/go-spew"
+  packages = ["spew"]
+  revision = "346938d642f2ec3594ed81d874461961cd0faa76"
+  version = "v1.1.0"
+
+[[projects]]
+  name = "github.com/golang/protobuf"
+  packages = ["proto"]
+  revision = "925541529c1fa6821df4e44ce2723319eb2be768"
+  version = "v1.0.0"
+
+[[projects]]
+  name = "github.com/matttproud/golang_protobuf_extensions"
+  packages = ["pbutil"]
+  revision = "3247c84500bff8d9fb6d579d800f20b3e091582c"
+  version = "v1.0.0"
+
+[[projects]]
+  name = "github.com/opentracing/opentracing-go"
+  packages = [
+    ".",
+    "ext",
+    "log"
+  ]
+  revision = "1949ddbfd147afd4d964a9f00b24eb291e0e7c38"
+  version = "v1.0.2"
+
+[[projects]]
+  name = "github.com/pkg/errors"
+  packages = ["."]
+  revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
+  version = "v0.8.0"
+
+[[projects]]
+  name = "github.com/pmezard/go-difflib"
+  packages = ["difflib"]
+  revision = "792786c7400a136282c1664665ae0a8db921c6c2"
+  version = "v1.0.0"
+
+[[projects]]
+  name = "github.com/prometheus/client_golang"
+  packages = ["prometheus"]
+  revision = "c5b7fccd204277076155f10851dad72b76a49317"
+  version = "v0.8.0"
+
+[[projects]]
+  branch = "master"
+  name = "github.com/prometheus/client_model"
+  packages = ["go"]
+  revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c"
+
+[[projects]]
+  branch = "master"
+  name = "github.com/prometheus/common"
+  packages = [
+    "expfmt",
+    "internal/bitbucket.org/ww/goautoneg",
+    "model"
+  ]
+  revision = "d811d2e9bf898806ecfb6ef6296774b13ffc314c"
+
+[[projects]]
+  branch = "master"
+  name = "github.com/prometheus/procfs"
+  packages = [
+    ".",
+    "internal/util",
+    "nfs",
+    "xfs"
+  ]
+  revision = "8b1c2da0d56deffdbb9e48d4414b4e674bd8083e"
+
+[[projects]]
+  name = "github.com/stretchr/testify"
+  packages = [
+    "assert",
+    "require",
+    "suite"
+  ]
+  revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71"
+  version = "v1.2.1"
+
+[[projects]]
+  name = "github.com/uber-go/atomic"
+  packages = ["."]
+  revision = "8474b86a5a6f79c443ce4b2992817ff32cf208b8"
+  version = "v1.3.1"
+
+[[projects]]
+  name = "github.com/uber/jaeger-lib"
+  packages = [
+    "metrics",
+    "metrics/metricstest",
+    "metrics/prometheus"
+  ]
+  revision = "0e30338a695636fe5bcf7301e8030ce8dd2a8530"
+  version = "v2.0.0"
+
+[[projects]]
+  name = "go.uber.org/atomic"
+  packages = ["."]
+  revision = "54f72d32435d760d5604f17a82e2435b28dc4ba5"
+  version = "v1.3.0"
+
+[[projects]]
+  name = "go.uber.org/multierr"
+  packages = ["."]
+  revision = "3c4937480c32f4c13a875a1829af76c98ca3d40a"
+  version = "v1.1.0"
+
+[[projects]]
+  name = "go.uber.org/zap"
+  packages = [
+    ".",
+    "buffer",
+    "internal/bufferpool",
+    "internal/color",
+    "internal/exit",
+    "zapcore"
+  ]
+  revision = "eeedf312bc6c57391d84767a4cd413f02a917974"
+  version = "v1.8.0"
+
+[[projects]]
+  branch = "master"
+  name = "golang.org/x/net"
+  packages = [
+    "context",
+    "context/ctxhttp"
+  ]
+  revision = "5f9ae10d9af5b1c89ae6904293b14b064d4ada23"
+
+[solve-meta]
+  analyzer-name = "dep"
+  analyzer-version = 1
+  inputs-digest = "6d9f4397c5091bc5a3b0e91e62196bfb0883df2c194998a9d5c0868f6cfba281"
+  solver-name = "gps-cdcl"
+  solver-version = 1

+ 27 - 0
vendor/github.com/uber/jaeger-client-go/Gopkg.toml

@@ -0,0 +1,27 @@
+[[constraint]]
+  name = "github.com/crossdock/crossdock-go"
+  branch = "master"
+
+[[constraint]]
+  name = "github.com/opentracing/opentracing-go"
+  version = "^1"
+
+[[constraint]]
+  name = "github.com/prometheus/client_golang"
+  version = "0.8.0"
+
+[[constraint]]
+  name = "github.com/stretchr/testify"
+  version = "^1.1.3"
+
+[[constraint]]
+  name = "github.com/uber-go/atomic"
+  version = "^1"
+
+[[constraint]]
+  name = "github.com/uber/jaeger-lib"
+  version = "^2.0"
+
+[[constraint]]
+  name = "go.uber.org/zap"
+  version = "^1"

+ 201 - 0
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.

+ 120 - 0
vendor/github.com/uber/jaeger-client-go/Makefile

@@ -0,0 +1,120 @@
+PROJECT_ROOT=github.com/uber/jaeger-client-go
+PACKAGES := $(shell glide novendor | grep -v -e ./thrift-gen/... -e ./thrift/...)
+# 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.*")
+
+-include crossdock/rules.mk
+
+export GO15VENDOREXPERIMENT=1
+
+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:
+	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:
+	glide --version || go get github.com/Masterminds/glide
+ifeq ($(USE_DEP),true)
+	dep ensure
+else
+	glide install
+endif
+
+
+.PHONY: cover
+cover:
+	./scripts/cover.sh $(shell go list $(PACKAGES))
+	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
+
+# TODO at the moment we're not generating tchan_*.go files
+thrift: idl-submodule 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
+
+idl-submodule:
+	git submodule init
+	git submodule update
+
+thrift-image:
+	$(THRIFT) -version
+
+.PHONY: install-dep-ci
+install-dep-ci:
+	- curl -L -s https://github.com/golang/dep/releases/download/v0.3.2/dep-linux-amd64 -o $$GOPATH/bin/dep
+	- chmod +x $$GOPATH/bin/dep
+
+.PHONY: install-ci
+install-ci: install-dep-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:
+	@./scripts/cover.sh $(shell go list $(PACKAGES))
+ifeq ($(CI_SKIP_LINT),true)
+	echo 'skipping lint'
+else
+	make lint
+endif

+ 270 - 0
vendor/github.com/uber/jaeger-client-go/README.md

@@ -0,0 +1,270 @@
+[![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](http://opentracing.io) 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 [glide](https://github.com/Masterminds/glide)
+and [semantic versioning](http://semver.org/) when including this library into an application.
+For example, Jaeger backend imports this library like this:
+
+```yaml
+- package: github.com/uber/jaeger-client-go
+  version: ^2.7.0
+```
+
+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 `glide` 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 overriden 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.Closer()` 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.
+
+### 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.
+
+## 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

+ 11 - 0
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`

+ 77 - 0
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...)
+}

+ 395 - 0
vendor/github.com/uber/jaeger-client-go/config/config.go

@@ -0,0 +1,395 @@
+// 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"`
+
+	// MaxOperations is the maximum number of operations that the sampler
+	// 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"`
+
+	// 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"`
+}
+
+// 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"`
+}
+
+// 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.ServiceName == "" {
+		return nil, nil, errors.New("no service name provided")
+	}
+
+	if c.Disabled {
+		return &opentracing.NoopTracer{}, &nullCloser{}, nil
+	}
+	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.ZipkinSharedRPCSpan(opts.zipkinSharedRPCSpan),
+		jaeger.TracerOptions.MaxTagValueLength(opts.maxTagValueLength),
+	}
+
+	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: %v. Expecting value between 0 and 1",
+			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),
+		}
+		if sc.MaxOperations != 0 {
+			options = append(options, jaeger.SamplerOptions.MaxOperations(sc.MaxOperations))
+		}
+		if sc.SamplingRefreshInterval != 0 {
+			options = append(options, jaeger.SamplerOptions.SamplingRefreshInterval(sc.SamplingRefreshInterval))
+		}
+		return jaeger.NewRemotelyControlledSampler(serviceName, options...), nil
+	}
+	return nil, fmt.Errorf("Unknown sampler type %v", 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 != "" && rc.User != "" && rc.Password != "":
+		return transport.NewHTTPTransport(rc.CollectorEndpoint, transport.HTTPBatchSize(1),
+			transport.HTTPBasicAuth(rc.User, rc.Password)), nil
+	case rc.CollectorEndpoint != "":
+		return transport.NewHTTPTransport(rc.CollectorEndpoint, transport.HTTPBatchSize(1)), nil
+	default:
+		return jaeger.NewUDPTransport(rc.LocalAgentHostPort, 0)
+	}
+}

+ 221 - 0
vendor/github.com/uber/jaeger-client-go/config/config_env.go

@@ -0,0 +1,221 @@
+// 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{}
+
+	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 s, err := samplerConfigFromEnv(); err == nil {
+		c.Sampler = s
+	} else {
+		return nil, errors.Wrap(err, "cannot obtain sampler config from env")
+	}
+
+	if r, err := 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 samplerConfigFromEnv() (*SamplerConfig, error) {
+	sc := &SamplerConfig{}
+
+	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
+	}
+
+	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 reporterConfigFromEnv() (*ReporterConfig, error) {
+	rc := &ReporterConfig{}
+
+	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
+}

+ 148 - 0
vendor/github.com/uber/jaeger-client-go/config/options.go

@@ -0,0 +1,148 @@
+// 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
+	zipkinSharedRPCSpan bool
+	maxTagValueLength   int
+	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 recieve 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
+	}
+}
+
+// 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
+	}
+}
+
+// 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
+}

+ 88 - 0
vendor/github.com/uber/jaeger-client-go/constants.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
+
+const (
+	// JaegerClientVersion is the version of the client library reported as Span tag.
+	JaegerClientVersion = "Go-2.15.1dev"
+
+	// 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
+
+	// DefaultMaxTagValueLength is the default max length of byte array or string allowed in the tag value.
+	DefaultMaxTagValueLength = 256
+)

+ 258 - 0
vendor/github.com/uber/jaeger-client-go/context.go

@@ -0,0 +1,258 @@
+// 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"
+)
+
+const (
+	flagSampled = byte(1)
+	flagDebug   = byte(2)
+)
+
+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
+
+	// flags is a bitmap containing such bits as 'sampled' and 'debug'.
+	flags byte
+
+	// 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
+}
+
+// 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.flags & flagSampled) == flagSampled
+}
+
+// IsDebug indicates whether sampling was explicitly requested by the service.
+func (c SpanContext) IsDebug() bool {
+	return (c.flags & flagDebug) == flagDebug
+}
+
+// IsValid indicates whether this context actually represents a valid trace.
+func (c SpanContext) IsValid() bool {
+	return c.traceID.IsValid() && c.spanID != 0
+}
+
+func (c SpanContext) String() string {
+	if c.traceID.High == 0 {
+		return fmt.Sprintf("%x:%x:%x:%x", c.traceID.Low, uint64(c.spanID), uint64(c.parentID), c.flags)
+	}
+	return fmt.Sprintf("%x%016x:%x:%x:%x", c.traceID.High, c.traceID.Low, uint64(c.spanID), uint64(c.parentID), c.flags)
+}
+
+// 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.flags = 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
+}
+
+// NewSpanContext creates a new instance of SpanContext
+func NewSpanContext(traceID TraceID, spanID, parentID SpanID, sampled bool, baggage map[string]string) SpanContext {
+	flags := byte(0)
+	if sampled {
+		flags = flagSampled
+	}
+	return SpanContext{
+		traceID:  traceID,
+		spanID:   spanID,
+		parentID: parentID,
+		flags:    flags,
+		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.flags = ctx.flags
+	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, c.flags, newBaggage, ""}
+}
+
+// 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
+}

+ 56 - 0
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
+}

部分文件因为文件数量过多而无法显示